📄 mpid_onesided.h
字号:
/* (C)Copyright IBM Corp. 2007, 2008 *//** * \file src/onesided/mpid_onesided.h * \brief MPI-DCMF Common declarations and definitions for RMA */#include "mpidimpl.h"/* redefine these for debugging purposes *//** * \brief Macro for allocating memory * * \param[out] p variable to receive new pointer * \param[in] t type of "p", excluding "*" * \param[in] z size in bytes to allocate * \param[in] e variable to receive error code * \param[in] n string to identify where/what allocation is * \return nothing, per ce. fills in "p" with address or NULL */#define MPIDU_MALLOC(p, t, z, e, n) p = (t *)MPIU_Malloc(z)/** * \brief Macro for allocating memory * * \param[in] p variable containing address to be freed * \param[in] e variable to receive error code * \param[in] n string to identify where/what allocation/free is */#define MPIDU_FREE(p, e, n) MPIU_Free((void *)p)/** * \brief structure of DCMF_Control_t as used by RMA ops * * DCMF_Control_t is assumed to be one quad. */typedef union { DCMF_Control_t ctl; /**< access to underlying type */ struct { unsigned _0w0; /**< word 0 */ unsigned _0w1; /**< word 1 */ unsigned _0w2; /**< word 2 */ unsigned _0w3; /**< word 3 */ } _c_u; /**< overlay of DCMF_Control_t */} MPIDU_Onesided_ctl_t __attribute__ ((__aligned__ (16)));#define mpid_ctl_w0 _c_u._0w0 /**< ctl word 0 */#define mpid_ctl_w1 _c_u._0w1 /**< ctl word 1 */#define mpid_ctl_w2 _c_u._0w2 /**< ctl word 2 */#define mpid_ctl_w3 _c_u._0w3 /**< ctl word 3 *//** * \brief structure of "msginfo" as used by RMA ops * * We always use 2 quads, just for consistency. */typedef union { DCQuad info[2]; /**< access to underlying type */ struct { unsigned _0w0; /**< word 0 */ unsigned _0w1; /**< word 1 */ unsigned _0w2; /**< word 2 */ unsigned _0w3; /**< word 3 */ unsigned _1w0; /**< word 4 */ unsigned _1w1; /**< word 5 */ unsigned _1w2; /**< word 6 */ unsigned _1w3; /**< word 7 */ } _i_u; /**< overlay of DCQuads */} MPIDU_Onesided_info_t __attribute__ ((__aligned__ (16)));#define mpid_info_w0 _i_u._0w0 /**< info word 0 */#define mpid_info_w1 _i_u._0w1 /**< info word 1 */#define mpid_info_w2 _i_u._0w2 /**< info word 2 */#define mpid_info_w3 _i_u._0w3 /**< info word 3 */#define mpid_info_w4 _i_u._1w0 /**< info word 4 */#define mpid_info_w5 _i_u._1w1 /**< info word 5 */#define mpid_info_w6 _i_u._1w2 /**< info word 6 */#define mpid_info_w7 _i_u._1w3 /**< info word 7 */#if 0/** * \brief Translate message type into string */extern char *msgtypes[];#endif/** \brief DCMF Protocol object for DCMF_Send() calls */extern DCMF_Protocol_t bg1s_sn_proto;/** \brief DCMF Protocol object for DCMF_Get() calls */extern DCMF_Protocol_t bg1s_gt_proto;/** \brief DCMF Protocol object for DCMF_Control() calls */extern DCMF_Protocol_t bg1s_ct_proto;/** \brief global for our lpid */extern unsigned mpid_my_lpid;/** * \brief struct used by MPID_Get to delay unpacking of datatype * * Active only when the origin datatype is non-contiguous. * Reference count is used to determine when the last chunk of * data is received, rest of struct is used to unpack data. */struct mpid_get_cb_data { int ref; /**< reference counter */ MPID_Datatype *dtp; /**< datatype object */ void *addr; /**< origin address of get */ int count; /**< origin count */ int len; /**< computed length of get */ char *buf; /**< temp buffer of packed data */};/** \brief datatype map entry - adjacent fields with same datatype are combined * * map[x].len = map[x].num * MPID_Datatype_get_basic_size(map[x].dt); * map[x+1].off = map[x].off + map[x].len + <stride>; * */typedef struct MPID_Type_map { unsigned off; /**< offset in datatype */ unsigned len; /**< length of map segment */ unsigned num; /**< number of fields */ MPI_Datatype dt; /**< datatype of fields */} MPID_Type_map;/*******************************************************//** * \brief Structure to house info on cached datatypes * * Used to store info in the actual cache, and also to pass * info back and forth. * * Only derived datatypes ever use this. eltype and elsize are * zero if the dtp->eltype is not builtin. MPID_Accumulate() * uses this for error checking. */typedef struct { MPID_Datatype *dtp; /**< datatype object */ int _pad; /**< padding to power of 2 length */ MPID_Type_map *map; /**< datatype map */ int map_len; /**< datatype map length */} mpid_dt_info;/** * \brief Build datatype map and iovec * * \param[in] dt Datatype to build map/iov for * \param[out] dti Pointer to datatype info struct */void make_dt_map_vec(MPI_Datatype dt, mpid_dt_info *dti);/** \brief Hi-order bit of integer type \note should be taken from standard include */#define INT_MSB (1UL << (sizeof(int) * 8 - 1))/** * \brief Datatype created to represent the rma_sends element * of the coll_info array of the window structure */extern MPI_Datatype Coll_info_rma_dt;/** * \brief User defined function created to process the rma_sends * elements of the coll_info array of the window structure */extern MPI_Op Coll_info_rma_op;/** * \brief Dummy, global, MPID_Progress_state since its not used. */extern MPID_Progress_state dummy_state;/** * \brief Progress (advance) wait - how to spin and make progress * * 'expr' is true if must wait, i.e. * while(expr) { make_progress; } * * Guaranteed to call DCMF_Messager_advance() _at least_ once * (via MPID_Progress_wait()) * * In DCMF, MPID_Progress_wait() never returns an error... * Also, MPID_Progress_state is never used. * * \param[in] expr Conditional expression to be evaluated on each loop, * FALSE will terminate loop. * \return nothing */#define MPIDU_Progress_spin(expr) { \ MPID_Progress_start(&dummy_state);\ do { \ (void)MPID_Progress_test();\ MPID_CS_EXIT(); \ MPID_CS_ENTER(); \ } while (expr); \ MPID_Progress_end(&dummy_state);\}/* * * * * * Generic resource pool management * * * * * *//** * \page rsrc_design Basic resource element design * * Generic resources are managed through a \e mpid_qhead structure * which defines the basic geometry of the allocation blocks and * references the first allocated block. * * Generic resources are allocated in blocks. Each block begins * with a header of \e mpid_resource and is followed by a number * of elements whose size and count are defined for each resource * type. Also, the header size is defined, which may be larger * than the natural size of \e mpid_resource in order to optimize * memory layout (i.e. cache usage). * * Resource blocks are never freed (exception: lock wait queue * resources are freed when the window is freed). * * Specific resources are defined by their elements. Every resource * element must have as its first field the \e next pointer, as * defined by \e mpid_element. Following this is * defined by the needs of the specific resource. * * A newly allocated block is initialized with all elements \e next * chained together and the block's \e next_free pointer set to the * first (free) element. Except for the first allocated block * (the one directly referenced by \e mpid_qhead), the \e next_free * is not used again. This also applies to the \e next_used and * \e last_used pointers. * * A newly allocated secondary block is linked into the \e mpid_qhead * \e next_block chain and \e next_free chain. * * When an element is taken from the free list, it is always taken * from the top of the list, i.e. directly from \e next_free. * When an element is returned to the free list, it is placed * (pushed) on the top. So an element to be allocated is always the * one most-recently freed, i.e. a LIFO queue. * * When an element is added to the used list, it is always added * to the end of the list, i.e. using the \e last_used pointer. * If an arbitrary element is taken from the used list, it is * taken from the top of the list, i.e. using \e next_used. This * effectively forms a FIFO queue. * * Other routines exist that permit the used list to be searched, * and the found element may be removed from the used list * "out of turn". A specific resource implementation decides * how it will use this list. *//** * \brief Basic resource element structure. * * This implements the basic linked-list pointer(s) * needed to manage generic elements. * An actual element implementation will have additional * fields. * * \ref rsrc_design */struct mpid_element { struct mpid_element *next; /**< next used or next free */};/** * \brief Resource block header structure. * * This structure exists at the beginning of each * allocated block of elements. * * \ref rsrc_design */struct mpid_resource { struct mpid_element *next_used; /**< Pointer to top of queue */ struct mpid_element *last_used; /**< Pointer to bottom of queue */ struct mpid_element *next_free; /**< Pointer to top of free list */ struct mpid_resource *next_block; /**< Pointer to next allocated block */};/** * \brief Resource "queue head" structure. * * This structure is required to exist and be initialized * before any resource or element management functions are call. * * \ref rsrc_design */struct mpid_qhead { int num; /**< number of elements per block */ short len; /**< length of each element */ short hdl; /**< length of header in block */ struct mpid_resource *blocks; /**< Allocated block(s) chain */ struct mpid_resource *lastblock; /**< last block in chain */};/** * \brief Queue-head static initializer. * * This is used to initialize a mpid_qhead structure at * compile-time. * * \param[in] n number of elements per block * \param[in] l length (bytes) of each element * \param[in] p padding for header: added to sizeof(mpid_resource) * \return static initializer * * \ref rsrc_design */#define MPIDU_INIT_QHEAD_DECL(n, l, p) \ { (n), (l), sizeof(struct mpid_resource) + p, NULL }/** * \brief Queue-head dynamic initializer. * * This is used to initialize a mpid_qhead structure at * runtime. * * \param[in] qp pointer to mpid_qhead structure * \param[in] n number of elements per block * \param[in] l length (bytes) of each element * \param[in] p padding for header: added to sizeof(mpid_resource) * \return n/a * * \ref rsrc_design */#define MPIDU_INIT_QHEAD(qp, n, l, p) { \ (qp)->num = n; \ (qp)->len = l; \ (qp)->hdl = sizeof(struct mpid_resource) + p; \ (qp)->blocks = NULL; \}/** * \brief Allocate a new block of elements. * * Unconditionally allocates a block of resources as described by * 'qhead' and link the block into 'qhead'. The new elements * are added to the 'qhead' free list. The new elements are * uninitialized except for the mpid_element field(s). * * \param[in] qhead Queue Head * \return nothing * * \ref rsrc_design */void MPIDU_alloc_resource(struct mpid_qhead *qhead);/** * \brief Unconditionally free all resource blocks * referenced by 'qhead'. * * NOTE: elements such as datatype cache require addition freeing * and so won't work with this. We could add a "free func ptr" to * qhead and call it here - so each element type can free any other * buffers it may have allocated. * * Right now, this is only called by Win_free() on the lock and unlock * wait queues, which do no additional allocation. * * \param[in] qhead Queue Head * \return nothing * * \ref rsrc_design */void MPIDU_free_resource(struct mpid_qhead *qhead);/** * \brief Get a new (unused) resource element. * * Take a resource element off the free list and put it on the * end of used list (bottom of queue). Element is uninitialized * except for mpid_element structure fields. * * \param[in] qhead Queue Head * \return pointer to element. * * \ref rsrc_design */void *MPIDU_get_element(struct mpid_qhead *qhead);/** * \brief Initialize a new (unused) element. * * Get a new element from free list and initialize its contents * from 'el'. Element is placed at bottom of queue. * 'el' is assumed to be of qhead->len size. * * \param[in] qhead Queue Head * \param[in] el Pointer to new element data * \return pointer to element. * * \ref rsrc_design */void *MPIDU_add_element(struct mpid_qhead *qhead, void *el);/** * \brief Peek at top element in queue (used list). * * Copy contents of first element in used list (top of queue) * into 'el'. Does not alter qhead (used or free lists). * 'el' is assumed to be of qhead->len size. * * \param[in] qhead Queue Head * \param[out] el Pointer to destination for element data * \return 1 if no elements on queue or * 0 on success with 'el' filled-in. * * \ref rsrc_design */int MPIDU_peek_element(struct mpid_qhead *qhead, void *el);/** * \brief Free an element. * * Remove element 'el' (parent element 'pe') from used list * and place on free list. Typically, this is only called * after calling MPIDU_find_element() to obtain 'el' and 'pe'. * * (See MPIDU_free_resource()) This does not take into account * any additional allocations done by the element type. Whether * any such buffers need to be freed depends on how the element- * type re-uses elements (when taken off the free list). * * \param[in] qhead Queue Head * \param[in] el Element object * \param[in] pe Parent element object, or NULL if 'el' * is at top of queue. * \return nothing * * \ref rsrc_design */void MPIDU_free_element(struct mpid_qhead *qhead, void *el, void *pe);/** * \brief Pop first element off used list (top of queue). * * Element contents is copied into 'el', if not NULL. * Popped element is placed on free list. * Returns 0 (success) if element was popped, or 1 if list empty. * * \param[in] qhead Queue Head * \param[out] el Element contents buffer * \return 1 if no elements on queue or * 0 on success with 'el' filled-in. * * \ref rsrc_design */int MPIDU_pop_element(struct mpid_qhead *qhead, void *el);/** * \brief Find specific element in queue. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -