Redefine the default boolean type to gmx_bool.
[alexxy/gromacs.git] / src / gmxlib / thread_mpi / type.c
1 /*
2 This source code file is part of thread_mpi.  
3 Written by Sander Pronk, Erik Lindahl, and possibly others. 
4
5 Copyright (c) 2009, Sander Pronk, Erik Lindahl.
6 All rights reserved.
7
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.
18
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.
29
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
35 files.
36 */
37
38 #ifdef HAVE_TMPI_CONFIG_H
39 #include "tmpi_config.h"
40 #endif
41
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56 #if ! (defined( _WIN32 ) || defined( _WIN64 ) )
57 #include <sys/time.h>
58 #endif
59
60 #include "impl.h"
61
62
63 /* this is where all the tMPI_Reduce ops are included from tmpi_ops.h */
64 #define THREAD_MPI_OPS 1
65
66 #define TYPE char
67 #define TYPENM CHAR
68 #define INTTYPE 1
69 #include "tmpi_ops.h"
70
71 #define TYPE short
72 #define TYPENM SHORT
73 #define INTTYPE 1
74 #include "tmpi_ops.h"
75
76 #define TYPE int
77 #define TYPENM INT
78 #define INTTYPE 1
79 #include "tmpi_ops.h"
80
81 #define TYPE long
82 #define TYPENM LONG
83 #define INTTYPE 1
84 #include "tmpi_ops.h"
85
86 #ifdef SIZEOF_LONG_LONG_INT
87
88 #define TYPE long long
89 #define TYPENM L_LONG
90 #define INTTYPE 1
91 #include "tmpi_ops.h"
92
93 #define TYPE long long int
94 #define TYPENM L_L_INT
95 #define INTTYPE 1
96 #include "tmpi_ops.h"
97
98 #endif
99
100 #define TYPE signed char
101 #define TYPENM S_CHAR
102 #define INTTYPE 1
103 #include "tmpi_ops.h"
104
105 #define TYPE unsigned char
106 #define TYPENM U_CHAR
107 #define INTTYPE 1
108 #include "tmpi_ops.h"
109
110 #define TYPE unsigned short
111 #define TYPENM U_SHORT
112 #define INTTYPE 1
113 #include "tmpi_ops.h"
114
115 #define TYPE unsigned 
116 #define TYPENM UNSIGNED
117 #define INTTYPE 1
118 #include "tmpi_ops.h"
119
120 #define TYPE unsigned long
121 #define TYPENM U_LONG
122 #define INTTYPE 1
123 #include "tmpi_ops.h"
124
125 #ifdef SIZEOF_LONG_LONG_INT
126
127 #define TYPE unsigned long long
128 #define TYPENM U_L_LONG
129 #define INTTYPE 1
130 #include "tmpi_ops.h"
131
132 #endif
133
134 #define TYPE float
135 #define TYPENM FLOAT
136 #define INTTYPE 0
137 #include "tmpi_ops.h"
138
139 #define TYPE double
140 #define TYPENM DOUBLE
141 #define INTTYPE 0
142 #include "tmpi_ops.h"
143
144 #define TYPE long double
145 #define TYPENM L_DOUBLE
146 #define INTTYPE 0
147 #include "tmpi_ops.h"
148
149 #define TYPE char
150 #define TYPENM BYTE
151 #define INTTYPE 1
152 #include "tmpi_ops.h"
153
154
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};
163 #endif
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};
171 #endif
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};
177
178
179
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;
188 #endif
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;
196 #endif
197
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;
201
202 /*extern tMPI_Datatype tMPI_UNSIGNED_WCHAR*/
203 const tMPI_Datatype TMPI_BYTE               = &tmpi_byte;
204
205 const tMPI_Datatype TMPI_POINTER            = &tmpi_pointer;
206
207
208
209
210
211
212 int tMPI_Type_contiguous(int count, tMPI_Datatype oldtype, 
213                          tMPI_Datatype *newtype)
214 {
215     struct tmpi_datatype_ *ntp;
216
217 #ifdef TMPI_TRACE
218     tMPI_Trace_print("tMPI_Type_contiguous(%d, %p, %p)", count, oldtype, 
219                        newtype);
220 #endif
221     ntp=(struct tmpi_datatype_*)tMPI_Malloc(sizeof(struct tmpi_datatype_));
222     ntp->size=count*oldtype->size;
223     ntp->op_functions=NULL;
224
225     /* establish components */
226     ntp->N_comp=1;
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;
232
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)
237     {
238         /* make space */
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)
244                                     );
245
246     }
247     /* add to the list */
248     tmpi_global->usertypes[tmpi_global->N_usertypes]=ntp;
249     tmpi_global->N_usertypes++;
250     *newtype=ntp;
251     tMPI_Spinlock_unlock(&(tmpi_global->datatype_lock));
252
253     return TMPI_SUCCESS;
254 }
255
256
257 int tMPI_Type_commit(tMPI_Datatype *datatype)
258 {
259     int i,j;
260     struct tmpi_datatype_ *dt=*datatype;
261
262 #ifdef TMPI_TRACE
263     tMPI_Trace_print("tMPI_Type_commit(%p)", datatype);
264 #endif
265     if (dt->committed)
266         return TMPI_SUCCESS;
267
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++)
274     {
275         struct tmpi_datatype_ *lt=tmpi_global->usertypes[i];
276         if (lt->committed && lt->N_comp==dt->N_comp)
277         {
278             gmx_bool found=TRUE;
279             for(j=0;j<lt->N_comp;j++)
280             {
281                 if ( (lt->comps[j].type  != dt->comps[j].type) ||
282                      (lt->comps[j].count != dt->comps[j].count) )
283                 {
284                     found=FALSE;
285                     break;
286                 }
287             }
288             if (found)
289             {
290                 dt=lt;
291             }
292         }
293     }
294     if (dt != *datatype)
295     {
296         gmx_bool found=FALSE;
297         /* we remove the old one from the list */
298         for(i=0;i<tmpi_global->N_usertypes;i++)
299         {
300             if (tmpi_global->usertypes[i]==*datatype)
301             {
302                 found=TRUE;
303                 break;
304             }
305         }
306         if (found)
307         {
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--;
312         }
313         free( (*datatype)->comps);
314         free(  *datatype );
315
316         /* and overwrite the pointer with the new data type */
317         *datatype=dt;
318     }
319     else
320     {
321         /* it was the first one of its type */
322         dt->committed=TRUE;
323     }
324     tMPI_Spinlock_unlock(&(tmpi_global->datatype_lock));
325     return TMPI_SUCCESS;
326 }
327