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 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12
13 #include "dataloop.h"
14 #include "veccpy.h"
15
16 /* NOTE: bufp values are unused, ripe for removal */
17
18 int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p,
19 DLOOP_Type el_type,
20 DLOOP_Offset rel_off,
21 void *bufp,
22 void *v_paramp);
23 int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
24 DLOOP_Count count,
25 DLOOP_Count blksz,
26 DLOOP_Offset stride,
27 DLOOP_Type el_type,
28 DLOOP_Offset rel_off,
29 void *bufp,
30 void *v_paramp);
31 int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p,
32 DLOOP_Count count,
33 DLOOP_Count blocklen,
34 DLOOP_Offset *offsetarray,
35 DLOOP_Type el_type,
36 DLOOP_Offset rel_off,
37 void *bufp,
38 void *v_paramp);
39 int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p,
40 DLOOP_Count count,
41 DLOOP_Count *blockarray,
42 DLOOP_Offset *offsetarray,
43 DLOOP_Type el_type,
44 DLOOP_Offset rel_off,
45 void *bufp,
46 void *v_paramp);
47
PREPEND_PREFIX(Segment_pack)48 void PREPEND_PREFIX(Segment_pack)(DLOOP_Segment *segp,
49 DLOOP_Offset first,
50 DLOOP_Offset *lastp,
51 void *streambuf)
52 {
53 struct PREPEND_PREFIX(m2m_params) params; /* defined in dataloop_parts.h */
54
55 /* experimenting with discarding buf value in the segment, keeping in
56 * per-use structure instead. would require moving the parameters around a
57 * bit.
58 */
59 params.userbuf = segp->ptr;
60 params.streambuf = streambuf;
61 params.direction = DLOOP_M2M_FROM_USERBUF;
62
63 PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp,
64 PREPEND_PREFIX(Segment_contig_m2m),
65 PREPEND_PREFIX(Segment_vector_m2m),
66 PREPEND_PREFIX(Segment_blkidx_m2m),
67 PREPEND_PREFIX(Segment_index_m2m),
68 NULL, /* size fn */
69 ¶ms);
70 return;
71 }
72
PREPEND_PREFIX(Segment_unpack)73 void PREPEND_PREFIX(Segment_unpack)(DLOOP_Segment *segp,
74 DLOOP_Offset first,
75 DLOOP_Offset *lastp,
76 void *streambuf)
77 {
78 struct PREPEND_PREFIX(m2m_params) params;
79
80 /* experimenting with discarding buf value in the segment, keeping in
81 * per-use structure instead. would require moving the parameters around a
82 * bit.
83 */
84 params.userbuf = segp->ptr;
85 params.streambuf = streambuf;
86 params.direction = DLOOP_M2M_TO_USERBUF;
87
88 PREPEND_PREFIX(Segment_manipulate)(segp, first, lastp,
89 PREPEND_PREFIX(Segment_contig_m2m),
90 PREPEND_PREFIX(Segment_vector_m2m),
91 PREPEND_PREFIX(Segment_blkidx_m2m),
92 PREPEND_PREFIX(Segment_index_m2m),
93 NULL, /* size fn */
94 ¶ms);
95 return;
96 }
97
98 /* PIECE FUNCTIONS BELOW */
99
PREPEND_PREFIX(Segment_contig_m2m)100 int PREPEND_PREFIX(Segment_contig_m2m)(DLOOP_Offset *blocks_p,
101 DLOOP_Type el_type,
102 DLOOP_Offset rel_off,
103 void *bufp ATTRIBUTE((unused)),
104 void *v_paramp)
105 {
106 DLOOP_Offset el_size; /* DLOOP_Count? */
107 DLOOP_Offset size;
108 struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
109
110 DLOOP_Handle_get_size_macro(el_type, el_size);
111 size = *blocks_p * el_size;
112
113 #ifdef MPID_SU_VERBOSE
114 dbg_printf("\t[contig unpack: do=" DLOOP_OFFSET_FMT_DEC_SPEC ", dp=%x, bp=%x, sz=" DLOOP_OFFSET_FMT_DEC_SPEC ", blksz=" DLOOP_OFFSET_FMT_DEC_SPEC "]\n",
115 rel_off,
116 (unsigned) bufp,
117 (unsigned) paramp->u.unpack.unpack_buffer,
118 el_size,
119 *blocks_p);
120 #endif
121
122 if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
123 /* Ensure that pointer increment fits in a pointer */
124 /* userbuf is a pointer (not a displacement) since it is being
125 * used on a memcpy */
126 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->userbuf)) + rel_off);
127 DLOOP_Memcpy((char *) paramp->userbuf + rel_off, paramp->streambuf, size);
128 }
129 else {
130 /* Ensure that pointer increment fits in a pointer */
131 /* userbuf is a pointer (not a displacement) since it is being used on a memcpy */
132 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->userbuf)) + rel_off);
133 DLOOP_Memcpy(paramp->streambuf, (char *) paramp->userbuf + rel_off, size);
134 }
135 /* Ensure that pointer increment fits in a pointer */
136 /* streambuf is a pointer (not a displacement) since it was used on a memcpy */
137 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) + size);
138 paramp->streambuf += size;
139 return 0;
140 }
141
142 /* Segment_vector_m2m
143 *
144 * Note: this combines both packing and unpacking functionality.
145 *
146 * Note: this is only called when the starting position is at the beginning
147 * of a whole block in a vector type.
148 */
PREPEND_PREFIX(Segment_vector_m2m)149 int PREPEND_PREFIX(Segment_vector_m2m)(DLOOP_Offset *blocks_p,
150 DLOOP_Count count ATTRIBUTE((unused)),
151 DLOOP_Count blksz,
152 DLOOP_Offset stride,
153 DLOOP_Type el_type,
154 DLOOP_Offset rel_off, /* offset into buffer */
155 void *bufp ATTRIBUTE((unused)),
156 void *v_paramp)
157 {
158 DLOOP_Count i, blocks_left, whole_count;
159 DLOOP_Offset el_size;
160 struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
161 char *cbufp;
162
163 /* Ensure that pointer increment fits in a pointer */
164 /* userbuf is a pointer (not a displacement) since it is being used for a memory copy */
165 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->userbuf)) + rel_off);
166 cbufp = (char*) paramp->userbuf + rel_off;
167 DLOOP_Handle_get_size_macro(el_type, el_size);
168
169 whole_count = (blksz > 0) ? (*blocks_p / (DLOOP_Offset) blksz) : 0;
170 blocks_left = (blksz > 0) ? (*blocks_p % (DLOOP_Offset) blksz) : 0;
171
172 if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
173 if (el_size == 8
174 MPIR_ALIGN8_TEST(paramp->streambuf,cbufp))
175 {
176 MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, stride,
177 int64_t, blksz, whole_count);
178 MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0,
179 int64_t, blocks_left, 1);
180 }
181 else if (el_size == 4
182 MPIR_ALIGN4_TEST(paramp->streambuf,cbufp))
183 {
184 MPIDI_COPY_TO_VEC((paramp->streambuf), cbufp, stride,
185 int32_t, blksz, whole_count);
186 MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0,
187 int32_t, blocks_left, 1);
188 }
189 else if (el_size == 2) {
190 MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, stride,
191 int16_t, blksz, whole_count);
192 MPIDI_COPY_TO_VEC(paramp->streambuf, cbufp, 0,
193 int16_t, blocks_left, 1);
194 }
195 else {
196 for (i=0; i < whole_count; i++) {
197 DLOOP_Memcpy(cbufp, paramp->streambuf, ((DLOOP_Offset) blksz) * el_size);
198 /* Ensure that pointer increment fits in a pointer */
199 /* streambuf is a pointer (not a displacement) since it is being used for a memory copy */
200 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) +
201 ((DLOOP_Offset) blksz) * el_size);
202 paramp->streambuf += ((DLOOP_Offset) blksz) * el_size;
203
204 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (cbufp)) + stride);
205 cbufp += stride;
206 }
207 if (blocks_left) {
208 DLOOP_Memcpy(cbufp, paramp->streambuf, ((DLOOP_Offset) blocks_left) * el_size);
209 /* Ensure that pointer increment fits in a pointer */
210 /* streambuf is a pointer (not a displacement) since
211 * it is being used for a memory copy */
212 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) +
213 ((DLOOP_Offset) blocks_left) * el_size);
214 paramp->streambuf += ((DLOOP_Offset) blocks_left) * el_size;
215 }
216 }
217 }
218 else /* M2M_FROM_USERBUF */ {
219 if (el_size == 8
220 MPIR_ALIGN8_TEST(cbufp,paramp->streambuf))
221 {
222 MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride,
223 int64_t, blksz, whole_count);
224 MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0,
225 int64_t, blocks_left, 1);
226 }
227 else if (el_size == 4
228 MPIR_ALIGN4_TEST(cbufp,paramp->streambuf))
229 {
230 MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride,
231 int32_t, blksz, whole_count);
232 MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0,
233 int32_t, blocks_left, 1);
234 }
235 else if (el_size == 2) {
236 MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, stride,
237 int16_t, blksz, whole_count);
238 MPIDI_COPY_FROM_VEC(cbufp, paramp->streambuf, 0,
239 int16_t, blocks_left, 1);
240 }
241 else {
242 for (i=0; i < whole_count; i++) {
243 DLOOP_Memcpy(paramp->streambuf, cbufp, (DLOOP_Offset) blksz * el_size);
244 /* Ensure that pointer increment fits in a pointer */
245 /* streambuf is a pointer (not a displacement) since
246 * it is being used for a memory copy */
247 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) +
248 (DLOOP_Offset) blksz * el_size);
249 paramp->streambuf += (DLOOP_Offset) blksz * el_size;
250 cbufp += stride;
251 }
252 if (blocks_left) {
253 DLOOP_Memcpy(paramp->streambuf, cbufp, (DLOOP_Offset) blocks_left * el_size);
254 /* Ensure that pointer increment fits in a pointer */
255 /* streambuf is a pointer (not a displacement) since
256 * it is being used for a memory copy */
257 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) +
258 (DLOOP_Offset) blocks_left * el_size);
259 paramp->streambuf += (DLOOP_Offset) blocks_left * el_size;
260 }
261 }
262 }
263
264 return 0;
265 }
266
267 /* MPID_Segment_blkidx_m2m
268 */
PREPEND_PREFIX(Segment_blkidx_m2m)269 int PREPEND_PREFIX(Segment_blkidx_m2m)(DLOOP_Offset *blocks_p,
270 DLOOP_Count count,
271 DLOOP_Count blocklen,
272 DLOOP_Offset *offsetarray,
273 DLOOP_Type el_type,
274 DLOOP_Offset rel_off,
275 void *bufp ATTRIBUTE((unused)),
276 void *v_paramp)
277 {
278 DLOOP_Count curblock = 0;
279 DLOOP_Offset el_size;
280 DLOOP_Offset blocks_left = *blocks_p;
281 char *cbufp;
282 struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
283
284 DLOOP_Handle_get_size_macro(el_type, el_size);
285
286 while (blocks_left) {
287 char *src, *dest;
288
289 DLOOP_Assert(curblock < count);
290
291 /* Ensure that pointer increment fits in a pointer */
292 /* userbuf is a pointer (not a displacement) since it is being
293 * used for a memory copy */
294 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->userbuf)) +
295 rel_off + offsetarray[curblock]);
296 cbufp = (char*) paramp->userbuf + rel_off + offsetarray[curblock];
297
298 if (blocklen > blocks_left) blocklen = blocks_left;
299
300 if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
301 src = paramp->streambuf;
302 dest = cbufp;
303 }
304 else {
305 src = cbufp;
306 dest = paramp->streambuf;
307 }
308
309 /* note: macro modifies dest buffer ptr, so we must reset */
310 if (el_size == 8
311 MPIR_ALIGN8_TEST(src, dest))
312 {
313 MPIDI_COPY_FROM_VEC(src, dest, 0, int64_t, blocklen, 1);
314 }
315 else if (el_size == 4
316 MPIR_ALIGN4_TEST(src,dest))
317 {
318 MPIDI_COPY_FROM_VEC(src, dest, 0, int32_t, blocklen, 1);
319 }
320 else if (el_size == 2) {
321 MPIDI_COPY_FROM_VEC(src, dest, 0, int16_t, blocklen, 1);
322 }
323 else {
324 DLOOP_Memcpy(dest, src, (DLOOP_Offset) blocklen * el_size);
325 }
326
327 /* Ensure that pointer increment fits in a pointer */
328 /* streambuf is a pointer (not a displacement) since it is
329 * being used for a memory copy */
330 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) +
331 (DLOOP_Offset) blocklen * el_size);
332 paramp->streambuf += (DLOOP_Offset) blocklen * el_size;
333 blocks_left -= blocklen;
334 curblock++;
335 }
336
337 return 0;
338 }
339
340 /* MPID_Segment_index_m2m
341 */
PREPEND_PREFIX(Segment_index_m2m)342 int PREPEND_PREFIX(Segment_index_m2m)(DLOOP_Offset *blocks_p,
343 DLOOP_Count count,
344 DLOOP_Count *blockarray,
345 DLOOP_Offset *offsetarray,
346 DLOOP_Type el_type,
347 DLOOP_Offset rel_off,
348 void *bufp ATTRIBUTE((unused)),
349 void *v_paramp)
350 {
351 int curblock = 0;
352 DLOOP_Offset el_size;
353 DLOOP_Offset cur_block_sz, blocks_left = *blocks_p;
354 char *cbufp;
355 struct PREPEND_PREFIX(m2m_params) *paramp = v_paramp;
356
357 DLOOP_Handle_get_size_macro(el_type, el_size);
358
359 while (blocks_left) {
360 char *src, *dest;
361
362 DLOOP_Assert(curblock < count);
363 cur_block_sz = blockarray[curblock];
364
365 /* Ensure that pointer increment fits in a pointer */
366 /* userbuf is a pointer (not a displacement) since it is being
367 * used for a memory copy */
368 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->userbuf)) +
369 rel_off + offsetarray[curblock]);
370 cbufp = (char*) paramp->userbuf + rel_off + offsetarray[curblock];
371
372 if (cur_block_sz > blocks_left) cur_block_sz = blocks_left;
373
374 if (paramp->direction == DLOOP_M2M_TO_USERBUF) {
375 src = paramp->streambuf;
376 dest = cbufp;
377 }
378 else {
379 src = cbufp;
380 dest = paramp->streambuf;
381 }
382
383 /* note: macro modifies dest buffer ptr, so we must reset */
384 if (el_size == 8
385 MPIR_ALIGN8_TEST(src, dest))
386 {
387 MPIDI_COPY_FROM_VEC(src, dest, 0, int64_t, cur_block_sz, 1);
388 }
389 else if (el_size == 4
390 MPIR_ALIGN4_TEST(src,dest))
391 {
392 MPIDI_COPY_FROM_VEC(src, dest, 0, int32_t, cur_block_sz, 1);
393 }
394 else if (el_size == 2) {
395 MPIDI_COPY_FROM_VEC(src, dest, 0, int16_t, cur_block_sz, 1);
396 }
397 else {
398 DLOOP_Memcpy(dest, src, cur_block_sz * el_size);
399 }
400
401 /* Ensure that pointer increment fits in a pointer */
402 /* streambuf is a pointer (not a displacement) since it is
403 * being used for a memory copy */
404 DLOOP_Ensure_Offset_fits_in_pointer((DLOOP_VOID_PTR_CAST_TO_OFFSET (paramp->streambuf)) +
405 cur_block_sz * el_size);
406 paramp->streambuf += cur_block_sz * el_size;
407 blocks_left -= cur_block_sz;
408 curblock++;
409 }
410
411 return 0;
412 }
413
414 /*
415 * Local variables:
416 * c-indent-tabs-mode: nil
417 * End:
418 */
419