📄 gen_segment.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include <stdio.h>#include <stdlib.h>#include <assert.h>/* NOTE: This is kind-of a hack; it would be better to somehow get this * included on the compile line. */#include <mpid_dataloop.h>#include <mpiimpl.h>#undef DLOOP_M_VERBOSE#ifndef GEN_DATALOOP_H#error "You must explicitly include a header that sets the PREPEND_PREFIX and includes gen_dataloop.h"#endif/* Notes on functions: * * There are a few different sets of functions here: * - DLOOP_Segment_manipulate() - uses a "piece" function to perform operations * using segments (piece functions defined elsewhere) * - PREPEND_PREFIX functions - these define the externally visible interface * to segment functionality */static inline int DLOOP_Stackelm_blocksize(struct DLOOP_Dataloop_stackelm *elmp);static inline int DLOOP_Stackelm_offset(struct DLOOP_Dataloop_stackelm *elmp);/* Segment_init * * buf - datatype buffer location * count - number of instances of the datatype in the buffer * handle - handle for datatype (could be derived or not) * segp - pointer to previously allocated segment structure * * Assumes that the segment has been allocated. * * NOTE: THIS IMPLEMENTATION DOES NOT HANDLE STRUCT DATALOOPS. */int PREPEND_PREFIX(Segment_init)(const DLOOP_Buffer buf, DLOOP_Count count, DLOOP_Handle handle, struct DLOOP_Segment *segp){ int i, elmsize, depth = 0; struct DLOOP_Dataloop_stackelm *elmp; struct DLOOP_Dataloop *dlp = 0; /* first figure out what to do with the datatype/count. * there are three cases: * - predefined datatype, any count; use the builtin loop only * - derived type, count == 1; don't use builtin at all * - derived type, count > 1; use builtin for contig of derived type */#ifdef DLOOP_M_VERBOSE DLOOP_dbg_printf("DLOOP_Segment_init: count = %d, buf = %x\n", count, buf);#endif if (!DLOOP_Handle_hasloop_macro(handle)) { /* simplest case; datatype has no loop (basic) */ DLOOP_Handle_get_size_macro(handle, elmsize); /* NOTE: ELMSIZE IS WRONG */ segp->builtin_loop.kind = DLOOP_KIND_CONTIG | DLOOP_FINAL_MASK | (elmsize << DLOOP_ELMSIZE_SHIFT); segp->builtin_loop.handle = handle; segp->builtin_loop.loop_params.c_t.count = count; segp->builtin_loop.loop_params.c_t.dataloop = 0; segp->builtin_loop.el_size = elmsize; DLOOP_Handle_get_extent_macro(handle, segp->builtin_loop.el_extent); dlp = &segp->builtin_loop; depth = 1; } else if (count == 1) { /* don't use the builtin */ DLOOP_Handle_get_loopptr_macro(handle, dlp); DLOOP_Handle_get_loopdepth_macro(handle, depth); } else { /* need to use builtin to handle contig; must check loop depth first */ DLOOP_Handle_get_loopdepth_macro(handle, depth); if (depth >= DLOOP_MAX_DATATYPE_DEPTH) return -1; depth++; /* we're adding to the depth with the builtin */ DLOOP_Handle_get_size_macro(handle, elmsize); /* NOTE: ELMSIZE IS WRONG */ segp->builtin_loop.kind = DLOOP_KIND_CONTIG | (elmsize << DLOOP_ELMSIZE_SHIFT); segp->builtin_loop.loop_params.c_t.count = count; DLOOP_Handle_get_loopptr_macro(handle, segp->builtin_loop.loop_params.c_t.dataloop); segp->builtin_loop.el_size = elmsize; DLOOP_Handle_get_extent_macro(handle, segp->builtin_loop.el_extent); dlp = &segp->builtin_loop; } /* initialize the rest of the segment values */ segp->handle = handle; segp->ptr = (DLOOP_Buffer) buf; segp->stream_off = 0; segp->cur_sp = 0; segp->valid_sp = 0; /* initialize the first stackelm in its entirety */ /* Note that we start counts (and blocks) at the maximum value and then decrement; * that way when we're testing for completion we don't have to look back at the * maximum value. */ elmp = &(segp->stackelm[0]); elmp->loop_p = dlp; elmp->orig_count = dlp->loop_params.count; elmp->curcount = elmp->orig_count; elmp->orig_offset = 0; /* NOTE: orig_count, curcount, and loop_p MUST be correct in elm before calling * DLOOP_Stackelm_blocksize(). */ elmp->orig_block = DLOOP_Stackelm_blocksize(elmp); elmp->curblock = elmp->orig_block; /* NOTE: orig_count, curcount, and loop_p MUST be correct in elm before calling * DLOOP_Stackelm_offset(). */ elmp->curoffset = /* elmp->orig_offset + */ DLOOP_Stackelm_offset(elmp); dlp = dlp->loop_params.cm_t.dataloop; for (i=1; i < depth; i++) { /* for the rest of the elements, we only fill in loop_p, orig_count, and * orig_block. the rest are filled in as we process the type (and for * indexed case orig_block will be overwritten as well). */ elmp = &(segp->stackelm[i]); elmp->curcount = dlp->loop_params.count; elmp->loop_p = dlp; /* DO NOT MOVE THIS BELOW THE Stackelm CALLS! */ elmp->orig_count = elmp->curcount; elmp->orig_block = DLOOP_Stackelm_blocksize(elmp); if (i < depth-1) { /* not at last point in the stack */ if (dlp->kind & DLOOP_FINAL_MASK) assert(0); dlp = dlp->loop_params.cm_t.dataloop; } else if (!(dlp->kind & DLOOP_FINAL_MASK)) assert(0); /* sanity check */ } segp->valid_sp = depth-1; return 0;}/* Segment_alloc * */struct DLOOP_Segment * PREPEND_PREFIX(Segment_alloc)(void){ return (struct DLOOP_Segment *) DLOOP_Malloc(sizeof(struct DLOOP_Segment));}/* Segment_free * * Input Parameters: * segp - pointer to segment */void PREPEND_PREFIX(Segment_free)(struct DLOOP_Segment *segp){ DLOOP_Free(segp); return;}/* DLOOP_Segment_manipulate - do something to a segment * * If you think of all the data to be manipulated (packed, unpacked, whatever), * as a stream of bytes, it's easier to understand how first and last fit in. * * This function does all the work, calling the piecefn passed in when it * encounters a datatype element which falls into the range of first..(last-1). * * piecefn can be NULL, in which case this function doesn't do anything when it * hits a region. This is used internally for repositioning within this stream. * * last is a byte offset to the byte just past the last byte in the stream * to operate on. this makes the calculations all over MUCH cleaner. * * This is a horribly long function. Too bad; it's complicated :)! -- Rob * * NOTE: THIS IMPLEMENTATION CANNOT HANDLE STRUCT DATALOOPS. */#define DLOOP_SEGMENT_SAVE_LOCAL_VALUES \do { \ segp->cur_sp = cur_sp; \ segp->valid_sp = valid_sp; \ segp->stream_off = stream_off; \ *lastp = stream_off; \} while (0)#define DLOOP_SEGMENT_LOAD_LOCAL_VALUES \do { \ last = *lastp; \ cur_sp = segp->cur_sp; \ valid_sp = segp->valid_sp; \ stream_off = segp->stream_off; \ cur_elmp = &(segp->stackelm[cur_sp]); \} while (0)#define DLOOP_SEGMENT_RESET_VALUES \do { \ segp->stream_off = 0; \ segp->cur_sp = 0; \ cur_elmp = &(segp->stackelm[0]); \ cur_elmp->curcount = cur_elmp->orig_count; \ cur_elmp->orig_block = DLOOP_Stackelm_blocksize(cur_elmp); \ cur_elmp->curblock = cur_elmp->orig_block; \ cur_elmp->curoffset = cur_elmp->orig_offset + DLOOP_Stackelm_offset(cur_elmp); \} while (0)#define DLOOP_SEGMENT_POP_AND_MAYBE_EXIT \do { \ cur_sp--; \ if (cur_sp >= 0) cur_elmp = &segp->stackelm[cur_sp]; \ else { \ DLOOP_SEGMENT_SAVE_LOCAL_VALUES; \ return; \ } \} while (0)#define DLOOP_SEGMENT_PUSH \do { \ cur_sp++; \ cur_elmp = &segp->stackelm[cur_sp]; \} while (0)#define DLOOP_STACKELM_BLOCKINDEXED_OFFSET(__elmp, __curcount) \(__elmp)->loop_p->loop_params.bi_t.offset_array[(__curcount)]#define DLOOP_STACKELM_INDEXED_OFFSET(__elmp, __curcount) \(__elmp)->loop_p->loop_params.i_t.offset_array[(__curcount)]#define DLOOP_STACKELM_INDEXED_BLOCKSIZE(__elmp, __curcount) \(__elmp)->loop_p->loop_params.i_t.blocksize_array[(__curcount)]void PREPEND_PREFIX(Segment_manipulate)(struct DLOOP_Segment *segp, DLOOP_Offset first, DLOOP_Offset *lastp, int (*piecefn)(DLOOP_Handle, int, int, void *, void *), void *pieceparams){ int cur_sp, valid_sp; DLOOP_Offset last; DLOOP_Offset stream_off; struct DLOOP_Dataloop_stackelm *cur_elmp; DLOOP_SEGMENT_LOAD_LOCAL_VALUES; /* first we ensure that stream_off and first are in the same spot */ if (first != stream_off) { DLOOP_Offset tmp_last;#ifdef DLOOP_M_VERBOSE DLOOP_dbg_printf("first=%d; stream_off=%ld; resetting.\n", first, stream_off);#endif /* TODO: BE SMARTER AND DON'T RESET IF STREAM_OFF IS BEFORE FIRST */ /* reset to beginning of stream */ DLOOP_SEGMENT_RESET_VALUES; /* TODO: AVOID CALLING MANIP. IF FIRST == 0 */ /* Note: we're simply using the manipulate function with a NULL piecefn * to handle this case. It's one more function call, but it dramatically * simplifies this code. */ tmp_last = first; PREPEND_PREFIX(Segment_manipulate)(segp, 0, &tmp_last, NULL, NULL); /* verify that we're in the right location */ if (tmp_last != first) assert(0); DLOOP_SEGMENT_LOAD_LOCAL_VALUES; /* continue processing... */#ifdef DLOOP_M_VERBOSE DLOOP_dbg_printf("done repositioning stream_off; first=%d, stream_off=%ld, last=%d\n", first, stream_off, last);#endif } for (;;) { if ((cur_elmp->loop_p->kind & DLOOP_KIND_MASK) == DLOOP_KIND_STRUCT) assert(0);#ifdef DLOOP_M_VERBOSE DLOOP_dbg_printf("looptop; cur_sp=%d, cur_elmp=%x\n", cur_sp, (unsigned) cur_elmp);#endif if (cur_elmp->loop_p->kind & DLOOP_FINAL_MASK) { int partial_flag, piecefn_indicated_exit; DLOOP_Offset piece_size, basic_size, dtype_size; /* process data region */ /* First discover how large a region we *could* process, if it * could all be handled by the processing function. */ dtype_size = cur_elmp->loop_p->el_size; /* this is the fundamental size at which we should work. * this could theoretically be smaller than the * dtype size; dunno yet. if so, it will be a big mess * to keep up with... * * TODO: GET THIS FROM THE TYPE MORE CORRECTLY */ basic_size = cur_elmp->loop_p->el_size; switch (cur_elmp->loop_p->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: piece_size = cur_elmp->curcount * dtype_size; break; case DLOOP_KIND_BLOCKINDEXED: case DLOOP_KIND_INDEXED:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -