📄 mpid_rma_common.c
字号:
* * Lookup a foreign (remote, origin) datatype in local cache. * Uses origin lpid and (foreign) datatype. * * \param[in] lpid Rank of origin * \param[in] fdt Foreign (origin) datatype handle to search for * \param[out] dti Pointer to datatype info struct * \return 0 if locally cached datatype found, * or 1 if not found. * * \ref dtcache_design */static int MPIDU_lookup_dt(int lpid, MPI_Datatype fdt, mpid_dt_info *dti) { struct mpid_dtc_entry *dtc; if (lpid == mpid_my_lpid) { /* origin == target, was cached as "target" */ lpid |= MPIDU_TARGET_FLAG; } else { lpid |= MPIDU_ORIGIN_FLAG; } dtc = MPIDU_locate_dt(lpid, fdt, NULL, NULL); if (dtc != NULL && dtc->dti.map != NULL) { if (dti) { *dti = dtc->dti; } return 0; } else { return 1; }}#endif /* NOT_USED *//** * \brief Prepare to receive a foreign datatype (step 1 - map). * * Called when MPID_MSGTYPE_DT_MAP (first datatype packet) received. * Returns NULL if this datatype is already in the cache. * Since the origin should be mirroring our cache status, * we would expect to never see this case here. * Must be the first of sequence: * - MPID_MSGTYPE_DT_MAP * - MPID_MSGTYPE_DT_IOV * - MPID_MSGTYPE_ACC (_PUT, _GET) * Although, the cache operation is not dependant on any subsequent * RMA operations - i.e. the caching may be done for its own sake. * * Allocates storage for the map and updates cache element. * * mpid_info_w0 = MPID_MSGTYPE_MAP * mpid_info_w1 = map size, bytes * mpid_info_w2 = origin lpid * mpid_info_w3 = foreign datatype handle * mpid_info_w4 = datatype extent * mpid_info_w5 = datatype element type * mpid_info_w6 = datatype element size * mpid_info_w7 = (not used) * * \param[in] mi MPIDU_Onesided_info_t containing data * \return pointer to buffer to receive foreign datatype map * structure, or NULL if datatype is already cached. * * \ref dtcache_design */char *MPID_Prepare_rem_dt(MPIDU_Onesided_info_t *mi) { struct mpid_dtc_entry *dtc; int new = 0; dtc = MPIDU_locate_dt(mi->mpid_info_w2 | MPIDU_ORIGIN_FLAG, (MPI_Datatype)mi->mpid_info_w3, &new, NULL); if (!new) { /* if origin is re-sending, they must know what they're doing. */ if (dtc->dti.map) MPIDU_FREE(dtc->dti.map, mpi_errno, "MPID_Prepare_rem_dt"); } if (!dtc->dti.dtp) { dtc->dti.dtp = MPIDU_MALLOC(dtc->dti.dtp, MPID_Datatype, sizeof(MPID_Datatype), mpi_errno, "MPID_Prepare_rem_dt"); MPID_assert(dtc->dti.dtp != NULL); } /* caution! not a real datatype object! */ dtc->dti.dtp->handle = 0; dtc->dti.dtp->extent = mi->mpid_info_w4; dtc->dti.dtp->eltype = mi->mpid_info_w5; dtc->dti.dtp->element_size = mi->mpid_info_w6; dtc->dti.map_len = 0; MPIDU_MALLOC(dtc->dti.map, MPID_Type_map, mi->mpid_info_w1 * sizeof(*dtc->dti.map), mpi_errno, "MPID_Prepare_rem_dt"); MPID_assert(dtc->dti.map != NULL);#ifdef NOT_USED dtc->dti.iov = NULL;#endif /* NOT_USED */ return (char *)dtc->dti.map;}#ifdef NOT_USED/** * \brief Prepare to update foreign datatype (step 2 - iov). * * Called when MPID_MSGTYPE_DT_IOV (second datatype packet) received. * Returns NULL if this datatype is already in the cache. * Must be the second of sequence: * - MPID_MSGTYPE_DT_MAP * - MPID_MSGTYPE_DT_IOV * - MPID_MSGTYPE_ACC (_PUT, _GET) * * Allocates storage for the iov and updates cache element. * * \param[in] lpid Rank of origin * \param[in] fdt Foreign (origin) datatype handle to search for * \param[in] dlz iov size (number of elements) * \return pointer to buffer to receive foreign datatype iov * structure, or NULL if datatype is already cached. * * \ref dtcache_design */static char *mpid_update_rem_dt(int lpid, MPI_Datatype fdt, int dlz) { struct mpid_dtc_entry *dtc; dtc = MPIDU_locate_dt(lpid | MPIDU_ORIGIN_FLAG, fdt, NULL, NULL); MPID_assert_debug(dtc != NULL); MPID_assert_debug(dtc->dti.iov == NULL); /* must follow MPID_MSGTYPE_DT_MAP */ dtc->dti.iov_len = 0; MPIDU_MALLOC(dtc->dti.iov, DLOOP_VECTOR, dlz * sizeof(*dtc->dti.iov), lpid, "mpid_update_rem_dt"); MPID_assert(dtc->dti.iov != NULL); return (char *)dtc->dti.iov;}#endif /* NOT_USED *//** * \brief completion for datatype cache messages (map and iov) * * To use this callback, the msginfo (DCQuad) must * be filled as follows: * * - \e w0 - extent size * - \e w1 - number of elements in map or iov * - \e w2 - origin rank * - \e w3 - datatype handle on origin * * \param[in] xt Pointer to xtra msginfo saved from original message * \return nothing * */void MPID_Recvdone1_rem_dt(const DCQuad *xt) { struct mpid_dtc_entry *dtc; dtc = MPIDU_locate_dt(xt->w2 | MPIDU_ORIGIN_FLAG, xt->w3, NULL, NULL); MPID_assert_debug(dtc != NULL); dtc->dti.map_len = xt->w1;}#ifdef NOT_USED/** * \brief completion for datatype cache messages (map and iov) * * To use this callback, the msginfo (DCQuad) must * be filled as follows: * * - \e w0 - MPID_MSGTYPE_DT_IOV * - \e w1 - number of elements in map or iov * - \e w2 - origin rank * - \e w3 - datatype handle on origin * * \param[in] xt Pointer to xtra msginfo saved from original message * \return nothing * */static void mpid_recvdone2_rem_dt(const DCQuad *xt) { struct mpid_dtc_entry *dtc; dtc = MPIDU_locate_dt(xt->w2 | MPIDU_ORIGIN_FLAG, xt->w3, NULL, NULL); MPID_assert_debug(dtc != NULL); dtc->dti.iov_len = xt->w1;}#endif /* NOT_USED *//** * \brief Checks whether a local datatype has already been cached * at the target node. * * Determine whether a local datatype has already been sent to * this target (and thus is cached over there). * Returns bool TRUE if datatype is (should be) in lpid's cache. * * Should only be called on the origin. * * \param[in] lpid lpid of target * \param[in] dt Local datatype handle to search for * \param[out] dti Pointer to datatype info struct * \return Boolean TRUE if the datatype has already been cached. * * \ref dtcache_design */int MPIDU_check_dt(int lpid, MPI_Datatype dt, mpid_dt_info *dti) { struct mpid_dtc_entry *dtc, *cln = NULL; int new = 0; dtc = MPIDU_locate_dt(lpid | MPIDU_TARGET_FLAG, dt, &new, &cln); if (new) { if (cln) { /* * same local datatype, different target, * copy what we already have cached. */ dtc->dti = cln->dti; } else { /* * first time using this datatype - create map/iov. */ make_dt_map_vec(dt, &dtc->dti);#ifdef NOT_USED MPID_assert_debug(dtc->dti.iov != NULL);#endif /* NOT_USED */ MPID_assert_debug(dtc->dti.map != NULL); } } if (dti) { *dti = dtc->dti; }/* we never send datatype */return 1; return (!new);}/* * * * * * Request object (DCMF_Request_t) cache * * * * * * * because the request object is larger than a cache line, * no attempt is made to keep objects cache-aligned, for example * by padding the header to be the same size as the element or * padding the element to a cache-line size. * * The "piggy-back" data is declared as DCQuad for no special * reason - it was simply a convenient type that contained * adequate space. This component is not used directly as * msginfo in any message layer calls. * *//** * \page rqcache_design Request Object Cache Design * * The request cache element consists of a \e DCMF_Request_t * and a single \e DCQuad that may be used to save context * between the routine that allocated the request object and the * callback that frees it. * * When a request is allocated, the only value returned is * a pointer to the \e DCMF_Request_t field of the cache element. * When a request is freed, the cache must be searched for * a matching element, which is then moved to the free list. * Before the element is moved to the free list, the \e DCQuad * must be copied into a caller-supplied buffer or it will be lost. * * Callbacks that involve a request cache element will call * \e MPIDU_free_req with a \e DCQuad buffer to receive the context * info, if used. Then the context info is examined and action * taken accordingly. Common use for the contaxt info is to * free a buffer involved in a send operation and/or decrement * a counter to indicate completion. *//** \brief Number of Request Cache elements per allocation block */#define MPIDU_NUM_RQC_ENTRIES 8/** * \brief DCMF Request Cache Element * * \ref rqcache_design */struct mpid_rqc_entry { struct mpid_rqc_entry *next; /**< next used or next free */ int _pad[3]; /**< must 16-byte align DCMF_Request_t */ DCQuad bgq; /**< generic piggy-back. * Not directly used in communications. */ MPIDU_Onesided_info_t info; /**< MPID1S info */ DCMF_Request_t req; /**< DCMF Request object */};/** \brief Padding for Request Cache Element resource block header */#define MPIDU_PAD_RQC_ENTRIES 0/** \brief Queue Head for DCMF Request Object Cache */static struct mpid_qhead rqc = MPIDU_INIT_QHEAD_DECL(MPIDU_NUM_RQC_ENTRIES, sizeof(struct mpid_rqc_entry), MPIDU_PAD_RQC_ENTRIES);/** * \brief Test if a request object is represented by the given element. * * \param[in] v1 Pointer to DCMF request object in question * \param[in] v2 Pointer to request cache element to test * \param[in] v3 not used * \return 1 if NOT a matching request * * \ref rqcache_design */static int mpid_match_rq(void *v1, void *v2, void *v3) { DCMF_Request_t *w1 = (DCMF_Request_t *)v1; struct mpid_rqc_entry *w2 = (struct mpid_rqc_entry *)v2; return (w1 != &w2->req);}/** * \brief Get a new request object from the resource queue. * * If 'bgq' is not NULL, copy data into request cache element, * otherwise zero the field. * Returns pointer to the request component of the cache element. * * \param[in] bgq Optional pointer to additional info to save * \param[out] info Optional pointer to private msg info to use * \return Pointer to DCMF request object * * \ref rqcache_design */DCMF_Request_t *MPIDU_get_req(const DCQuad *bgq, MPIDU_Onesided_info_t **info) { struct mpid_rqc_entry *rqe; rqe = MPIDU_get_element(&rqc); MPID_assert_debug(rqe != NULL); // This assert is not relavent for non-BG and not needed for BG. // MPID_assert_debug((((unsigned)&rqe->req) & 0x0f) == 0); if (bgq) { rqe->bgq = *bgq; } else { memset(&rqe->bgq, 0, sizeof(rqe->bgq)); } if (info) { *info = &rqe->info; } return &rqe->req;}/** * \brief Release a DCMF request object and retrieve info * * Locate the request object in the request cache and free it. * If 'bgq' is not NULL, copy piggy-back data into 'bgp'. * Assumes request object was returned by a call to MPIDU_get_req(). * * \param[in] req Pointer to DCMF request object being released * \param[out] bgq Optional pointer to receive saved additional info * \return nothing * * \ref rqcache_design */void MPIDU_free_req(DCMF_Request_t *req, DCQuad *bgq) { struct mpid_rqc_entry *rqe; struct mpid_element *pp = NULL; rqe = (struct mpid_rqc_entry *)MPIDU_find_element(&rqc, mpid_match_rq, NULL, req, &pp); MPID_assert_debug(rqe != NULL); if (bgq) { *bgq = rqe->bgq; } MPIDU_free_element(&rqc, rqe, pp);}/* * * * * * * Callbacks used on request cache objects * * * * * *//**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -