2 This source code file is part of thread_mpi.
3 Written by Sander Pronk, Erik Lindahl, and possibly others.
5 Copyright (c) 2009, Sander Pronk, Erik Lindahl.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 1) Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3) Neither the name of the copyright holders nor the
16 names of its contributors may be used to endorse or promote products
17 derived from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
20 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 If you want to redistribute modifications, please consider that
31 scientific software is very special. Version control is crucial -
32 bugs must be traceable. We will be happy to consider code for
33 inclusion in the official distribution, but derived work should not
34 be called official thread_mpi. Details are found in the README & COPYING
38 #ifdef HAVE_TMPI_CONFIG_H
39 #include "tmpi_config.h"
56 #if !(defined( _WIN32 ) || defined( _WIN64 ) )
63 /* this is where all the tMPI_Reduce ops are included from tmpi_ops.h */
64 #define THREAD_MPI_OPS 1
86 #ifdef SIZEOF_LONG_LONG_INT
88 #define TYPE long long
93 #define TYPE long long int
94 #define TYPENM L_L_INT
100 #define TYPE signed char
101 #define TYPENM S_CHAR
103 #include "tmpi_ops.h"
105 #define TYPE unsigned char
106 #define TYPENM U_CHAR
108 #include "tmpi_ops.h"
110 #define TYPE unsigned short
111 #define TYPENM U_SHORT
113 #include "tmpi_ops.h"
115 #define TYPE unsigned
116 #define TYPENM UNSIGNED
118 #include "tmpi_ops.h"
120 #define TYPE unsigned long
121 #define TYPENM U_LONG
123 #include "tmpi_ops.h"
125 #ifdef SIZEOF_LONG_LONG_INT
127 #define TYPE unsigned long long
128 #define TYPENM U_L_LONG
130 #include "tmpi_ops.h"
137 #include "tmpi_ops.h"
140 #define TYPENM DOUBLE
142 #include "tmpi_ops.h"
144 #define TYPE long double
145 #define TYPENM L_DOUBLE
147 #include "tmpi_ops.h"
152 #include "tmpi_ops.h"
159 #define TYPENM INT64_T
161 #include "tmpi_ops.h"
164 /* These are the fundamental data types. They exist as global variables */
165 tmpi_dt tmpi_char = {sizeof(char), oplist_CHAR, 0, NULL, TRUE};
166 tmpi_dt tmpi_short = {sizeof(short), oplist_SHORT, 0, NULL, TRUE};
167 tmpi_dt tmpi_int = {sizeof(int), oplist_INT, 0, NULL, TRUE};
168 tmpi_dt tmpi_long = {sizeof(long), oplist_LONG, 0, NULL, TRUE};
169 #ifdef SIZEOF_LONG_LONG_INT
170 tmpi_dt tmpi_l_long = {sizeof(long long), oplist_L_LONG, 0, NULL, TRUE};
171 tmpi_dt tmpi_l_l_int = {sizeof(long long int), oplist_L_L_INT, 0, NULL, TRUE};
173 tmpi_dt tmpi_s_char = {sizeof(signed char), oplist_S_CHAR, 0, NULL, TRUE};
174 tmpi_dt tmpi_u_char = {sizeof(unsigned char), oplist_U_CHAR, 0, NULL, TRUE};
175 tmpi_dt tmpi_u_short = {sizeof(unsigned short), oplist_U_SHORT, 0, NULL, TRUE};
176 tmpi_dt tmpi_unsigned = {sizeof(unsigned), oplist_UNSIGNED, 0, NULL, TRUE};
177 tmpi_dt tmpi_u_long = {sizeof(unsigned long), oplist_U_LONG, 0, NULL, TRUE};
178 #ifdef SIZEOF_LONG_LONG_INT
179 tmpi_dt tmpi_u_l_long = {sizeof(unsigned long long), oplist_U_L_LONG, 0, NULL, TRUE};
181 tmpi_dt tmpi_float = {sizeof(float), oplist_FLOAT, 0, NULL, TRUE};
182 tmpi_dt tmpi_double = {sizeof(double), oplist_DOUBLE, 0, NULL, TRUE};
183 tmpi_dt tmpi_l_double = {sizeof(long double), oplist_L_DOUBLE, 0, NULL, TRUE};
184 tmpi_dt tmpi_byte = {sizeof(char), oplist_CHAR, 0, NULL, TRUE};
185 tmpi_dt tmpi_pointer = {sizeof(void*), NULL, 0, NULL, TRUE};
186 tmpi_dt tmpi_int64_t = {8, oplist_INT64_T, 0, NULL, TRUE};
189 /* the variable types as they are referred to from MPI */
190 const tMPI_Datatype TMPI_CHAR = &tmpi_char;
191 const tMPI_Datatype TMPI_SHORT = &tmpi_short;
192 const tMPI_Datatype TMPI_INT = &tmpi_int;
193 const tMPI_Datatype TMPI_LONG = &tmpi_long;
194 #ifdef SIZEOF_LONG_LONG_INT
195 const tMPI_Datatype TMPI_LONG_LONG = &tmpi_l_long;
196 const tMPI_Datatype TMPI_LONG_LONG_INT = &tmpi_l_l_int;
198 const tMPI_Datatype TMPI_SIGNED_CHAR = &tmpi_s_char;
199 const tMPI_Datatype TMPI_UNSIGNED_CHAR = &tmpi_u_char;
200 const tMPI_Datatype TMPI_UNSIGNED_SHORT = &tmpi_u_short;
201 const tMPI_Datatype TMPI_UNSIGNED = &tmpi_unsigned;
202 const tMPI_Datatype TMPI_UNSIGNED_LONG = &tmpi_u_long;
203 #ifdef SIZEOF_LONG_LONG_INT
204 const tMPI_Datatype TMPI_UNSIGNED_LONG_LONG = &tmpi_u_l_long;
207 const tMPI_Datatype TMPI_FLOAT = &tmpi_float;
208 const tMPI_Datatype TMPI_DOUBLE = &tmpi_double;
209 const tMPI_Datatype TMPI_LONG_DOUBLE = &tmpi_l_double;
211 /*extern tMPI_Datatype tMPI_UNSIGNED_WCHAR*/
212 const tMPI_Datatype TMPI_BYTE = &tmpi_byte;
214 const tMPI_Datatype TMPI_POINTER = &tmpi_pointer;
216 const tMPI_Datatype TMPI_INT64_T = &tmpi_int64_t;
222 int tMPI_Type_contiguous(int count, tMPI_Datatype oldtype,
223 tMPI_Datatype *newtype)
225 struct tmpi_datatype_ *ntp;
228 tMPI_Trace_print("tMPI_Type_contiguous(%d, %p, %p)", count, oldtype,
231 ntp = (struct tmpi_datatype_*)tMPI_Malloc(sizeof(struct tmpi_datatype_));
232 ntp->size = count*oldtype->size;
233 ntp->op_functions = NULL;
235 /* establish components */
237 ntp->comps = (struct tmpi_datatype_component*)tMPI_Malloc(
238 sizeof(struct tmpi_datatype_component)*1);
239 ntp->comps[0].type = oldtype;
240 ntp->comps[0].count = 1;
241 ntp->committed = FALSE;
243 /* now add it to the list. */
244 tMPI_Spinlock_lock(&(tmpi_global->datatype_lock));
245 /* check whether there's space */
246 if (tmpi_global->N_usertypes + 1 >= tmpi_global->Nalloc_usertypes)
249 tmpi_global->Nalloc_usertypes = Nthreads*(tmpi_global->N_usertypes) + 1;
250 tmpi_global->usertypes = (struct tmpi_datatype_**)
251 tMPI_Realloc(tmpi_global->usertypes,
252 (sizeof(struct tmpi_datatype_ *)*
253 tmpi_global->Nalloc_usertypes)
257 /* add to the list */
258 tmpi_global->usertypes[tmpi_global->N_usertypes] = ntp;
259 tmpi_global->N_usertypes++;
261 tMPI_Spinlock_unlock(&(tmpi_global->datatype_lock));
267 int tMPI_Type_commit(tMPI_Datatype *datatype)
270 struct tmpi_datatype_ *dt = *datatype;
273 tMPI_Trace_print("tMPI_Type_commit(%p)", datatype);
280 /* search the list for a matching committed type, because if there's
281 already a committed type that has the same composition, we just
282 make the datatype pointer point to it, ensuring we share datatype
283 information across threads. */
284 tMPI_Spinlock_lock(&(tmpi_global->datatype_lock));
285 for (i = 0; i < tmpi_global->N_usertypes; i++)
287 struct tmpi_datatype_ *lt = tmpi_global->usertypes[i];
288 if (lt->committed && lt->N_comp == dt->N_comp)
290 tmpi_bool found = TRUE;
291 for (j = 0; j < lt->N_comp; j++)
293 if ( (lt->comps[j].type != dt->comps[j].type) ||
294 (lt->comps[j].count != dt->comps[j].count) )
308 tmpi_bool found = FALSE;
309 /* we remove the old one from the list */
310 for (i = 0; i < tmpi_global->N_usertypes; i++)
312 if (tmpi_global->usertypes[i] == *datatype)
320 /* we put the last one in the list in our slot */
321 tmpi_global->usertypes[i] = tmpi_global->
322 usertypes[tmpi_global->N_usertypes-1];
323 tmpi_global->N_usertypes--;
325 free( (*datatype)->comps);
328 /* and overwrite the pointer with the new data type */
333 /* it was the first one of its type */
334 dt->committed = TRUE;
336 tMPI_Spinlock_unlock(&(tmpi_global->datatype_lock));