1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 
3 /*
4  *  (C) 2001 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 
8 #ifndef DATALOOP_PARTS_H
9 #define DATALOOP_PARTS_H
10 
11 /* Check that all the appropriate defines are present */
12 #ifndef PREPEND_PREFIX
13 #error "PREPEND_PREFIX must be defined before dataloop_parts.h is included."
14 #endif
15 
16 #ifndef DLOOP_Offset
17 #error "DLOOP_Offset must be defined before dataloop_parts.h is included."
18 #endif
19 
20 #ifndef DLOOP_Count
21 #error "DLOOP_Count must be defined before dataloop_parts.h is included."
22 #endif
23 
24 #ifndef DLOOP_Handle
25 #error "DLOOP_Handle must be defined before dataloop_parts.h is included."
26 #endif
27 
28 #ifndef DLOOP_Buffer
29 #error "DLOOP_Buffer must be defined before dataloop_parts.h is included."
30 #endif
31 
32 #ifndef DLOOP_Type
33 #error "DLOOP_Type must be defined before dataloop_parts.h is included."
34 #endif
35 
36 /* Redefine all of the internal structures in terms of the prefix */
37 #define DLOOP_Dataloop              PREPEND_PREFIX(Dataloop)
38 #define DLOOP_Dataloop_contig       PREPEND_PREFIX(Dataloop_contig)
39 #define DLOOP_Dataloop_vector       PREPEND_PREFIX(Dataloop_vector)
40 #define DLOOP_Dataloop_blockindexed PREPEND_PREFIX(Dataloop_blockindexed)
41 #define DLOOP_Dataloop_indexed      PREPEND_PREFIX(Dataloop_indexed)
42 #define DLOOP_Dataloop_struct       PREPEND_PREFIX(Dataloop_struct)
43 #define DLOOP_Dataloop_common       PREPEND_PREFIX(Dataloop_common)
44 #define DLOOP_Segment               PREPEND_PREFIX(Segment)
45 #define DLOOP_Dataloop_stackelm     PREPEND_PREFIX(Dataloop_stackelm)
46 
47 /* These flags are used at creation time to specify what types of
48  * optimizations may be applied. They are also passed in at Segment_init
49  * time to specify which dataloop to use.
50  *
51  * Note: The flag to MPID_Segment_init() was originally simply "hetero"
52  * and was a boolean value (0 meaning homogeneous). Some MPICH2 code
53  * may still rely on HOMOGENEOUS being "0" and HETEROGENEOUS being "1".
54  */
55 #define DLOOP_DATALOOP_HOMOGENEOUS   0
56 #define DLOOP_DATALOOP_HETEROGENEOUS 1
57 #define DLOOP_DATALOOP_ALL_BYTES     2
58 
59 /* NOTE: ASSUMING LAST TYPE IS SIGNED */
60 #define SEGMENT_IGNORE_LAST ((DLOOP_Offset) -1)
61 /*
62  * Each of the MPI datatypes can be mapped into one of 5 very simple
63  * loops.  This loop has the following parameters:
64  * - count
65  * - blocksize[]
66  * - offset[]
67  * - stride
68  * - datatype[]
69  *
70  * where each [] indicates that a field may be *either* an array or a scalar.
71  * For each such type, we define a struct that describes these parameters
72  */
73 
74 /*S
75   DLOOP_Dataloop_contig - Description of a contiguous dataloop
76 
77   Fields:
78 + count - Number of elements
79 - dataloop - Dataloop of the elements
80 
81   Module:
82   Datatype
83   S*/
84 typedef struct DLOOP_Dataloop_contig {
85     DLOOP_Count count;
86     struct DLOOP_Dataloop *dataloop;
87 } DLOOP_Dataloop_contig;
88 
89 /*S
90   DLOOP_Dataloop_vector - Description of a vector or strided dataloop
91 
92   Fields:
93 + count - Number of elements
94 . blocksize - Number of dataloops in each element
95 . stride - Stride (in bytes) between each block
96 - dataloop - Dataloop of each element
97 
98   Module:
99   Datatype
100   S*/
101 typedef struct DLOOP_Dataloop_vector {
102     DLOOP_Count count;
103     struct DLOOP_Dataloop *dataloop;
104     DLOOP_Count blocksize;
105     DLOOP_Offset stride;
106 } DLOOP_Dataloop_vector;
107 
108 /*S
109   DLOOP_Dataloop_blockindexed - Description of a block-indexed dataloop
110 
111   Fields:
112 + count - Number of blocks
113 . blocksize - Number of elements in each block
114 . offset_array - Array of offsets (in bytes) to each block
115 . total_blocks - count of total blocks in the array (cached value)
116 - dataloop - Dataloop of each element
117 
118   Module:
119   Datatype
120 
121   S*/
122 typedef struct DLOOP_Dataloop_blockindexed {
123     DLOOP_Count count;
124     struct DLOOP_Dataloop *dataloop;
125     DLOOP_Count blocksize;
126     DLOOP_Offset *offset_array;
127 } DLOOP_Dataloop_blockindexed;
128 
129 /*S
130   DLOOP_Dataloop_indexed - Description of an indexed dataloop
131 
132   Fields:
133 + count - Number of blocks
134 . blocksize_array - Array giving the number of elements in each block
135 . offset_array - Array of offsets (in bytes) to each block
136 . total_blocks - count of total blocks in the array (cached value)
137 - dataloop - Dataloop of each element
138 
139   Module:
140   Datatype
141 
142   S*/
143 typedef struct DLOOP_Dataloop_indexed {
144     DLOOP_Count count;
145     struct DLOOP_Dataloop *dataloop;
146     DLOOP_Count *blocksize_array;
147     DLOOP_Offset *offset_array;
148     DLOOP_Count total_blocks;
149 } DLOOP_Dataloop_indexed;
150 
151 /*S
152   DLOOP_Dataloop_struct - Description of a structure dataloop
153 
154   Fields:
155 + count - Number of blocks
156 . blocksize_array - Array giving the number of elements in each block
157 . offset_array - Array of offsets (in bytes) to each block
158 - dataloop_array - Array of dataloops describing the elements of each block
159 
160   Module:
161   Datatype
162 
163   S*/
164 typedef struct DLOOP_Dataloop_struct {
165     DLOOP_Count count;
166     struct DLOOP_Dataloop **dataloop_array;
167     DLOOP_Count            *blocksize_array;
168     DLOOP_Offset           *offset_array;
169     DLOOP_Offset           *el_extent_array; /* need more than one */
170 } DLOOP_Dataloop_struct;
171 
172 /* In many cases, we need the count and the next dataloop item. This
173    common structure gives a quick access to both.  Note that all other
174    structures must use the same ordering of elements.
175    Question: should we put the pointer first in case
176    sizeof(pointer)>sizeof(int) ?
177 */
178 typedef struct DLOOP_Dataloop_common {
179     DLOOP_Count count;
180     struct DLOOP_Dataloop *dataloop;
181 } DLOOP_Dataloop_common;
182 
183 /*S
184   DLOOP_Dataloop - Description of the structure used to hold a dataloop
185   description
186 
187   Fields:
188 +  kind - Describes the type of the dataloop.  This is divided into three
189    separate bit fields\:
190 .vb
191      Dataloop type (e.g., DLOOP_CONTIG etc.).  3 bits
192      IsFinal (a "leaf" dataloop; see text) 1 bit
193      Element Size (units for fields.) 2 bits
194         Element size has 4 values
195         0   - Elements are in units of bytes
196         1   - Elements are in units of 2 bytes
197         2   - Elements are in units of 4 bytes
198         3   - Elements are in units of 8 bytes
199 .ve
200   The dataloop type is one of 'DLOOP_CONTIG', 'DLOOP_VECTOR',
201   'DLOOP_BLOCKINDEXED', 'DLOOP_INDEXED', or 'DLOOP_STRUCT'.
202 . loop_parms - A union containing the 5 dataloop structures, e.g.,
203   'DLOOP_Dataloop_contig', 'DLOOP_Dataloop_vector', etc.  A sixth element in
204   this union, 'count', allows quick access to the shared 'count' field in the
205   five dataloop structure.
206 . extent - The extent of the dataloop
207 
208   Module:
209   Datatype
210 
211   S*/
212 typedef struct DLOOP_Dataloop {
213     int kind;                  /* Contains both the loop type
214 				  (contig, vector, blockindexed, indexed,
215 				  or struct) and a bit that indicates
216 				  whether the dataloop is a leaf type. */
217     union {
218 	DLOOP_Count                 count;
219 	DLOOP_Dataloop_contig       c_t;
220 	DLOOP_Dataloop_vector       v_t;
221 	DLOOP_Dataloop_blockindexed bi_t;
222 	DLOOP_Dataloop_indexed      i_t;
223 	DLOOP_Dataloop_struct       s_t;
224 	DLOOP_Dataloop_common       cm_t;
225     } loop_params;
226     DLOOP_Offset el_size;
227     DLOOP_Offset el_extent;
228     DLOOP_Type   el_type;
229 } DLOOP_Dataloop;
230 
231 #define DLOOP_FINAL_MASK  0x00000008
232 #define DLOOP_KIND_MASK   0x00000007
233 #define DLOOP_KIND_CONTIG 0x1
234 #define DLOOP_KIND_VECTOR 0x2
235 #define DLOOP_KIND_BLOCKINDEXED 0x3
236 #define DLOOP_KIND_INDEXED 0x4
237 #define DLOOP_KIND_STRUCT 0x5
238 
239 /* The max datatype depth is the maximum depth of the stack used to
240    evaluate datatypes.  It represents the length of the chain of
241    datatype dependencies.  Defining this and testing when a datatype
242    is created removes a test in the datatype evaluation loop. */
243 #define DLOOP_MAX_DATATYPE_DEPTH 16
244 
245 /*S
246   DLOOP_Dataloop_stackelm - Structure for an element of the stack used
247   to process dataloops
248 
249   Fields:
250 + curcount - Current loop count value (between 0 and
251              loop.loop_params.count-1)
252 . orig_count - original count value (cached so we don't have to look it up)
253 . curoffset - Offset into memory relative to the pointer to the buffer
254               passed in by the user.  Used to maintain our position as we
255               move up and down the stack.  NEED MORE NOTES ON THIS!!!
256 . orig_offset - original offset, set before the stackelm is processed, so that
257                 we know where the offset was.  this is used in processing indexed
258                 types and possibly others.  it is set for all types, but not
259 		referenced in some cases.
260 . curblock - Current block value...NEED MORE NOTES ON THIS!!!
261 . orig_block - original block value (caches so we don't have to look it up);
262                INVALID FOR INDEX AND STRUCT TYPES.
263 - loop_p  - pointer to Loop-based description of the dataloop
264 
265 S*/
266 typedef struct DLOOP_Dataloop_stackelm {
267     int may_require_reloading; /* indicates that items below might
268 				* need reloading (e.g. this is a struct)
269 				*/
270 
271     DLOOP_Count  curcount;
272     DLOOP_Offset curoffset;
273     DLOOP_Count  curblock;
274 
275     DLOOP_Count  orig_count;
276     DLOOP_Offset orig_offset;
277     DLOOP_Count  orig_block;
278 
279     struct DLOOP_Dataloop *loop_p;
280 } DLOOP_Dataloop_stackelm;
281 
282 /*S
283   DLOOP_Segment - Description of the Segment datatype
284 
285   Notes:
286   This has no corresponding MPI datatype.
287 
288   Module:
289   Segment
290 
291   Questions:
292   Should this have an id for allocation and similarity purposes?
293   S*/
294 typedef struct DLOOP_Segment {
295     void *ptr; /* pointer to datatype buffer */
296     DLOOP_Handle handle;
297     DLOOP_Offset stream_off; /* next offset into data stream resulting from datatype
298 		              * processing.  in other words, how many bytes have
299 			      * we created/used by parsing so far?  that amount + 1.
300 			      */
301     DLOOP_Dataloop_stackelm stackelm[DLOOP_MAX_DATATYPE_DEPTH];
302     int  cur_sp;   /* Current stack pointer when using dataloop */
303     int  valid_sp; /* maximum valid stack pointer.  This is used to
304                       maintain information on the stack after it has
305                       been placed there by following the datatype field
306                       in a DLOOP_Dataloop_st for any type except struct */
307 
308     struct DLOOP_Dataloop builtin_loop; /* used for both predefined types (which
309 		         		  * won't have a loop already) and for
310 				  * situations where a count is passed in
311 				  * and we need to create a contig loop
312 				  * to handle it
313 				  */
314     /* other, device-specific information */
315 } DLOOP_Segment;
316 
317 /* Dataloop functions (dataloop.c) */
318 void PREPEND_PREFIX(Dataloop_copy)(void *dest,
319 				   void *src,
320 				   int size);
321 void PREPEND_PREFIX(Dataloop_update)(DLOOP_Dataloop *dataloop,
322 				     DLOOP_Offset ptrdiff);
323 DLOOP_Offset
324 PREPEND_PREFIX(Dataloop_stream_size)(DLOOP_Dataloop *dl_p,
325 				     DLOOP_Offset (*sizefn)(DLOOP_Type el_type));
326 void PREPEND_PREFIX(Dataloop_print)(DLOOP_Dataloop *dataloop,
327 				    int depth);
328 
329 void PREPEND_PREFIX(Dataloop_alloc)(int kind,
330 				    DLOOP_Count count,
331 				    DLOOP_Dataloop **new_loop_p,
332 				    int *new_loop_sz_p);
333 void PREPEND_PREFIX(Dataloop_alloc_and_copy)(int kind,
334 					     DLOOP_Count count,
335 					     DLOOP_Dataloop *old_loop,
336 					     int old_loop_sz,
337 					     DLOOP_Dataloop **new_loop_p,
338 					     int *new_loop_sz_p);
339 void PREPEND_PREFIX(Dataloop_struct_alloc)(DLOOP_Count count,
340 					   int old_loop_sz,
341 					   int basic_ct,
342 					   DLOOP_Dataloop **old_loop_p,
343 					   DLOOP_Dataloop **new_loop_p,
344 					   int *new_loop_sz_p);
345 void PREPEND_PREFIX(Dataloop_dup)(DLOOP_Dataloop *old_loop,
346 				  int old_loop_sz,
347 				  DLOOP_Dataloop **new_loop_p);
348 
349 void PREPEND_PREFIX(Dataloop_free)(DLOOP_Dataloop **dataloop);
350 
351 /* Segment functions (segment.c) */
352 DLOOP_Segment * PREPEND_PREFIX(Segment_alloc)(void);
353 
354 void PREPEND_PREFIX(Segment_free)(DLOOP_Segment *segp);
355 
356 int PREPEND_PREFIX(Segment_init)(const DLOOP_Buffer buf,
357 				 DLOOP_Count count,
358 				 DLOOP_Handle handle,
359 				 DLOOP_Segment *segp,
360 				 int hetero);
361 
362 void
363 PREPEND_PREFIX(Segment_manipulate)(DLOOP_Segment *segp,
364 				   DLOOP_Offset first,
365 				   DLOOP_Offset *lastp,
366 				   int (*piecefn) (DLOOP_Offset *blocks_p,
367 						   DLOOP_Type el_type,
368 						   DLOOP_Offset rel_off,
369 						   DLOOP_Buffer bufp,
370 						   void *v_paramp),
371 				   int (*vectorfn) (DLOOP_Offset *blocks_p,
372 						    DLOOP_Count count,
373 						    DLOOP_Count blklen,
374 						    DLOOP_Offset stride,
375 						    DLOOP_Type el_type,
376 						    DLOOP_Offset rel_off,
377 						    DLOOP_Buffer bufp,
378 						    void *v_paramp),
379 				   int (*blkidxfn) (DLOOP_Offset *blocks_p,
380 						    DLOOP_Count count,
381 						    DLOOP_Count blklen,
382 						    DLOOP_Offset *offsetarray,
383 						    DLOOP_Type el_type,
384 						    DLOOP_Offset rel_off,
385 						    DLOOP_Buffer bufp,
386 						    void *v_paramp),
387 				   int (*indexfn) (DLOOP_Offset *blocks_p,
388 						   DLOOP_Count count,
389 						   DLOOP_Count *blockarray,
390 						   DLOOP_Offset *offsetarray,
391 						   DLOOP_Type el_type,
392 						   DLOOP_Offset rel_off,
393 						   DLOOP_Buffer bufp,
394 						   void *v_paramp),
395 				   DLOOP_Offset (*sizefn) (DLOOP_Type el_type),
396 				   void *pieceparams);
397 
398 /* Common segment operations (segment_ops.c) */
399 void PREPEND_PREFIX(Segment_count_contig_blocks)(DLOOP_Segment *segp,
400 						 DLOOP_Offset first,
401 						 DLOOP_Offset *lastp,
402 						 DLOOP_Count *countp);
403 void PREPEND_PREFIX(Segment_mpi_flatten)(DLOOP_Segment *segp,
404 					 DLOOP_Offset first,
405 					 DLOOP_Offset *lastp,
406 					 int *blklens,
407 					 MPI_Aint *disps,
408 					 int *lengthp);
409 
410 #define DLOOP_M2M_TO_USERBUF   0
411 #define DLOOP_M2M_FROM_USERBUF 1
412 
PREPEND_PREFIX(m2m_params)413 struct PREPEND_PREFIX(m2m_params) {
414     int direction; /* M2M_TO_USERBUF or M2M_FROM_USERBUF */
415     char *streambuf;
416     char *userbuf;
417 };
418 
419 void PREPEND_PREFIX(Segment_pack)(struct DLOOP_Segment *segp,
420 				  DLOOP_Offset   first,
421 				  DLOOP_Offset  *lastp,
422 				  void *streambuf);
423 void PREPEND_PREFIX(Segment_unpack)(struct DLOOP_Segment *segp,
424 				    DLOOP_Offset   first,
425 				    DLOOP_Offset  *lastp,
426 				    void *streambuf);
427 
428 /* Segment piece functions that are used in specific cases elsewhere */
429 int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p,
430 				       DLOOP_Type el_type,
431 				       DLOOP_Offset rel_off,
432 				       void *bufp, /* unused */
433 				       void *v_paramp);
434 int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
435 				       DLOOP_Count count, /* unused */
436 				       DLOOP_Count blksz,
437 				       DLOOP_Offset stride,
438 				       DLOOP_Type el_type,
439 				       DLOOP_Offset rel_off,
440 				       void *bufp, /* unused */
441 				       void *v_paramp);
442 int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p,
443 				       DLOOP_Count count,
444 				       DLOOP_Count blocklen,
445 				       DLOOP_Offset *offsetarray,
446 				       DLOOP_Type el_type,
447 				       DLOOP_Offset rel_off,
448 				       void *bufp, /*unused */
449 				       void *v_paramp);
450 int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p,
451 				      DLOOP_Count count,
452 				      DLOOP_Count *blockarray,
453 				      DLOOP_Offset *offsetarray,
454 				      DLOOP_Type el_type,
455 				      DLOOP_Offset rel_off,
456 				      void *bufp, /*unused */
457 				      void *v_paramp);
458 #endif
459 
460 
461 
462