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"
155 /* These are the fundamental data types. They exist as global variables */
156 tmpi_dt tmpi_char ={sizeof(char), oplist_CHAR, 0,NULL,TRUE};
157 tmpi_dt tmpi_short ={sizeof(short), oplist_SHORT, 0,NULL,TRUE};
158 tmpi_dt tmpi_int ={sizeof(int), oplist_INT, 0,NULL,TRUE};
159 tmpi_dt tmpi_long ={sizeof(long), oplist_LONG, 0,NULL,TRUE};
160 #ifdef SIZEOF_LONG_LONG_INT
161 tmpi_dt tmpi_l_long ={sizeof(long long), oplist_L_LONG, 0,NULL,TRUE};
162 tmpi_dt tmpi_l_l_int ={sizeof(long long int), oplist_L_L_INT, 0,NULL,TRUE};
164 tmpi_dt tmpi_s_char ={sizeof(signed char), oplist_S_CHAR, 0,NULL,TRUE};
165 tmpi_dt tmpi_u_char ={sizeof(unsigned char), oplist_U_CHAR, 0,NULL,TRUE};
166 tmpi_dt tmpi_u_short ={sizeof(unsigned short), oplist_U_SHORT, 0,NULL,TRUE};
167 tmpi_dt tmpi_unsigned={sizeof(unsigned), oplist_UNSIGNED, 0,NULL,TRUE};
168 tmpi_dt tmpi_u_long ={sizeof(unsigned long), oplist_U_LONG, 0,NULL,TRUE};
169 #ifdef SIZEOF_LONG_LONG_INT
170 tmpi_dt tmpi_u_l_long={sizeof(unsigned long long),oplist_U_L_LONG, 0,NULL,TRUE};
172 tmpi_dt tmpi_float ={sizeof(float), oplist_FLOAT, 0,NULL,TRUE};
173 tmpi_dt tmpi_double ={sizeof(double), oplist_DOUBLE, 0,NULL,TRUE};
174 tmpi_dt tmpi_l_double={sizeof(long double), oplist_L_DOUBLE, 0,NULL,TRUE};
175 tmpi_dt tmpi_byte ={sizeof(char), oplist_CHAR, 0,NULL,TRUE};
176 tmpi_dt tmpi_pointer ={sizeof(void*), NULL, 0,NULL,TRUE};
180 /* the variable types as they are referred to from MPI */
181 const tMPI_Datatype TMPI_CHAR = &tmpi_char;
182 const tMPI_Datatype TMPI_SHORT = &tmpi_short;
183 const tMPI_Datatype TMPI_INT = &tmpi_int;
184 const tMPI_Datatype TMPI_LONG = &tmpi_long;
185 #ifdef SIZEOF_LONG_LONG_INT
186 const tMPI_Datatype TMPI_LONG_LONG = &tmpi_l_long;
187 const tMPI_Datatype TMPI_LONG_LONG_INT = &tmpi_l_l_int;
189 const tMPI_Datatype TMPI_SIGNED_CHAR = &tmpi_s_char;
190 const tMPI_Datatype TMPI_UNSIGNED_CHAR = &tmpi_u_char;
191 const tMPI_Datatype TMPI_UNSIGNED_SHORT = &tmpi_u_short;
192 const tMPI_Datatype TMPI_UNSIGNED = &tmpi_unsigned;
193 const tMPI_Datatype TMPI_UNSIGNED_LONG = &tmpi_u_long;
194 #ifdef SIZEOF_LONG_LONG_INT
195 const tMPI_Datatype TMPI_UNSIGNED_LONG_LONG = &tmpi_u_l_long;
198 const tMPI_Datatype TMPI_FLOAT = &tmpi_float;
199 const tMPI_Datatype TMPI_DOUBLE = &tmpi_double;
200 const tMPI_Datatype TMPI_LONG_DOUBLE = &tmpi_l_double;
202 /*extern tMPI_Datatype tMPI_UNSIGNED_WCHAR*/
203 const tMPI_Datatype TMPI_BYTE = &tmpi_byte;
205 const tMPI_Datatype TMPI_POINTER = &tmpi_pointer;
212 int tMPI_Type_contiguous(int count, tMPI_Datatype oldtype,
213 tMPI_Datatype *newtype)
215 struct tmpi_datatype_ *ntp;
218 tMPI_Trace_print("tMPI_Type_contiguous(%d, %p, %p)", count, oldtype,
221 ntp=(struct tmpi_datatype_*)tMPI_Malloc(sizeof(struct tmpi_datatype_));
222 ntp->size=count*oldtype->size;
223 ntp->op_functions=NULL;
225 /* establish components */
227 ntp->comps=(struct tmpi_datatype_component*)tMPI_Malloc(
228 sizeof(struct tmpi_datatype_component)*1);
229 ntp->comps[0].type=oldtype;
230 ntp->comps[0].count=1;
231 ntp->committed=FALSE;
233 /* now add it to the list. */
234 tMPI_Spinlock_lock(&(tmpi_global->datatype_lock));
235 /* check whether there's space */
236 if (tmpi_global->N_usertypes + 1 >= tmpi_global->Nalloc_usertypes)
239 tmpi_global->Nalloc_usertypes=Nthreads*(tmpi_global->N_usertypes) + 1;
240 tmpi_global->usertypes=(struct tmpi_datatype_**)
241 tMPI_Realloc(tmpi_global->usertypes,
242 (sizeof(struct tmpi_datatype_ *)*
243 tmpi_global->Nalloc_usertypes)
247 /* add to the list */
248 tmpi_global->usertypes[tmpi_global->N_usertypes]=ntp;
249 tmpi_global->N_usertypes++;
251 tMPI_Spinlock_unlock(&(tmpi_global->datatype_lock));
257 int tMPI_Type_commit(tMPI_Datatype *datatype)
260 struct tmpi_datatype_ *dt=*datatype;
263 tMPI_Trace_print("tMPI_Type_commit(%p)", datatype);
268 /* search the list for a matching committed type, because if there's
269 already a committed type that has the same composition, we just
270 make the datatype pointer point to it, ensuring we share datatype
271 information across threads. */
272 tMPI_Spinlock_lock(&(tmpi_global->datatype_lock));
273 for(i=0;i<tmpi_global->N_usertypes;i++)
275 struct tmpi_datatype_ *lt=tmpi_global->usertypes[i];
276 if (lt->committed && lt->N_comp==dt->N_comp)
279 for(j=0;j<lt->N_comp;j++)
281 if ( (lt->comps[j].type != dt->comps[j].type) ||
282 (lt->comps[j].count != dt->comps[j].count) )
296 gmx_bool found=FALSE;
297 /* we remove the old one from the list */
298 for(i=0;i<tmpi_global->N_usertypes;i++)
300 if (tmpi_global->usertypes[i]==*datatype)
308 /* we put the last one in the list in our slot */
309 tmpi_global->usertypes[i]=tmpi_global->
310 usertypes[tmpi_global->N_usertypes-1];
311 tmpi_global->N_usertypes--;
313 free( (*datatype)->comps);
316 /* and overwrite the pointer with the new data type */
321 /* it was the first one of its type */
324 tMPI_Spinlock_unlock(&(tmpi_global->datatype_lock));