📄 ch3u_request.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include "mpidimpl.h"/* This file contains two types of routines associated with requests: * Routines to allocate and free requests * Routines to manage iovs on requests * * Note that there are a number of macros that also manage requests defined * in mpidimpl.h ; these are intended to optimize request creation for * specific types of requests. See the comments in mpidimpl.h for more * details. *//* Routines and data structures for request allocation and deallocation */#ifndef MPID_REQUEST_PREALLOC#define MPID_REQUEST_PREALLOC 8#endifMPID_Request MPID_Request_direct[MPID_REQUEST_PREALLOC] = {{0}};MPIU_Object_alloc_t MPID_Request_mem = { 0, 0, 0, 0, MPID_REQUEST, sizeof(MPID_Request), MPID_Request_direct, MPID_REQUEST_PREALLOC };/* See the comments above about request creation. Some routines will use macros in mpidimpl.h *instead* of this routine */#undef FUNCNAME#define FUNCNAME MPID_Request_create#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)MPID_Request * MPID_Request_create(void){ MPID_Request * req; MPIDI_STATE_DECL(MPID_STATE_MPID_REQUEST_CREATE); MPIDI_FUNC_ENTER(MPID_STATE_MPID_REQUEST_CREATE); req = MPIU_Handle_obj_alloc(&MPID_Request_mem); if (req != NULL) { MPIU_DBG_MSG_P(CH3_CHANNEL,VERBOSE, "allocated request, handle=0x%08x", req->handle);#ifdef MPICH_DBG_OUTPUT /*MPIU_Assert(HANDLE_GET_MPI_KIND(req->handle) == MPID_REQUEST);*/ if (HANDLE_GET_MPI_KIND(req->handle) != MPID_REQUEST) { int mpi_errno; mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_OTHER, "**invalid_handle", "**invalid_handle %d", req->handle); MPID_Abort(MPIR_Process.comm_world, mpi_errno, -1, NULL); }#endif /* FIXME: This makes request creation expensive. We need to trim this to the basics, with additional setup for special-purpose requests (think base class and inheritance). For example, do we *really* want to set the kind to UNDEFINED? And should the RMA values be set only for RMA requests? */ MPIU_Object_set_ref(req, 1); req->kind = MPID_REQUEST_UNDEFINED; req->cc = 1; req->cc_ptr = &req->cc; /* FIXME: status fields meaningful only for receive, and even then should not need to be set. */ req->status.MPI_SOURCE = MPI_UNDEFINED; req->status.MPI_TAG = MPI_UNDEFINED; req->status.MPI_ERROR = MPI_SUCCESS; req->status.count = 0; req->status.cancelled = FALSE; req->comm = NULL; req->dev.datatype_ptr = NULL; req->dev.segment_ptr = NULL; /* Masks and flags for channel device state in an MPID_Request */ req->dev.state = 0; req->dev.cancel_pending = FALSE; /* FIXME: RMA ops shouldn't need to be set except when creating a request for RMA operations */ req->dev.target_win_handle = MPI_WIN_NULL; req->dev.source_win_handle = MPI_WIN_NULL; req->dev.single_op_opt = 0; req->dev.lock_queue_entry = NULL; req->dev.dtype_info = NULL; req->dev.dataloop = NULL; req->dev.iov_offset = 0;#if 0 req->dev.rdma_iov_count = 0; req->dev.rdma_iov_offset = 0;#endif#ifdef MPIDI_CH3_REQUEST_INIT MPIDI_CH3_REQUEST_INIT(req);#endif } else { /* FIXME: This fails to fail if debugging is turned off */ MPIU_DBG_MSG(CH3_CHANNEL,TYPICAL,"unable to allocate a request"); } MPIDI_FUNC_EXIT(MPID_STATE_MPID_REQUEST_CREATE); return req;}/* FIXME: We need a lighter-weight version of this to avoid all of the extra checks. One posibility would be a single, no special case (no comm, datatype, or srbuf to check) and a more general (check everything) version. */#undef FUNCNAME#define FUNCNAME MPIDI_CH3_Request_destroy#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)void MPIDI_CH3_Request_destroy(MPID_Request * req){ MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3_REQUEST_DESTROY); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3_REQUEST_DESTROY); MPIU_DBG_MSG_P(CH3_CHANNEL,VERBOSE, "freeing request, handle=0x%08x", req->handle); #ifdef MPICH_DBG_OUTPUT /*MPIU_Assert(HANDLE_GET_MPI_KIND(req->handle) == MPID_REQUEST);*/ if (HANDLE_GET_MPI_KIND(req->handle) != MPID_REQUEST) { int mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_OTHER, "**invalid_handle", "**invalid_handle %d", req->handle); MPID_Abort(MPIR_Process.comm_world, mpi_errno, -1, NULL); } /*MPIU_Assert(req->ref_count == 0);*/ if (req->ref_count != 0) { int mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_OTHER, "**invalid_refcount", "**invalid_refcount %d", req->ref_count); MPID_Abort(MPIR_Process.comm_world, mpi_errno, -1, NULL); }#endif /* FIXME: We need a better way to handle these so that we do not always need to initialize these fields and check them when we destroy a request */ /* FIXME: We need a way to call these routines ONLY when the related ref count has become zero. */ if (req->comm != NULL) { MPIR_Comm_release(req->comm, 0); } if (req->dev.datatype_ptr != NULL) { MPID_Datatype_release(req->dev.datatype_ptr); } if (req->dev.segment_ptr != NULL) { MPID_Segment_free(req->dev.segment_ptr); } if (MPIDI_Request_get_srbuf_flag(req)) { MPIDI_CH3U_SRBuf_free(req); } MPIU_Handle_obj_free(&MPID_Request_mem, req); MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3_REQUEST_DESTROY);}/* ------------------------------------------------------------------------- *//* Here are the routines to manipulate the iovs in the requests *//* ------------------------------------------------------------------------- *//* * MPIDI_CH3U_Request_load_send_iov() * * Fill the provided IOV with the next (or remaining) portion of data described * by the segment contained in the request structure. * If the density of IOV is not sufficient, pack the data into a send/receive * buffer and point the IOV at the buffer. */#undef FUNCNAME#define FUNCNAME MPIDI_CH3U_Request_load_send_iov#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPIDI_CH3U_Request_load_send_iov(MPID_Request * const sreq, MPID_IOV * const iov, int * const iov_n){ MPIDI_msg_sz_t last; int mpi_errno = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_SEND_IOV); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_SEND_IOV); last = sreq->dev.segment_size; MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST, "pre-pv: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT ", iov_n=%d", sreq->dev.segment_first, last, *iov_n)); MPIU_Assert(sreq->dev.segment_first < last); MPIU_Assert(last > 0); MPIU_Assert(*iov_n > 0 && *iov_n <= MPID_IOV_LIMIT); MPID_Segment_pack_vector(sreq->dev.segment_ptr, sreq->dev.segment_first, &last, iov, iov_n); MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST, "post-pv: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT ", iov_n=%d", sreq->dev.segment_first, last, *iov_n)); MPIU_Assert(*iov_n > 0 && *iov_n <= MPID_IOV_LIMIT); if (last == sreq->dev.segment_size) { MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"remaining data loaded into IOV"); sreq->dev.OnDataAvail = sreq->dev.OnFinal; } else if ((last - sreq->dev.segment_first) / *iov_n >= MPIDI_IOV_DENSITY_MIN) { MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"more data loaded into IOV"); sreq->dev.segment_first = last; sreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_SendReloadIOV; } else { MPIDI_msg_sz_t data_sz; int i, iov_data_copied; MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"low density. using SRBuf."); data_sz = sreq->dev.segment_size - sreq->dev.segment_first; if (!MPIDI_Request_get_srbuf_flag(sreq)) { MPIDI_CH3U_SRBuf_alloc(sreq, data_sz); /* --BEGIN ERROR HANDLING-- */ if (sreq->dev.tmpbuf_sz == 0) { MPIU_DBG_MSG(CH3_CHANNEL,TYPICAL,"SRBuf allocation failure"); mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0); sreq->status.MPI_ERROR = mpi_errno; goto fn_exit; } /* --END ERROR HANDLING-- */ } iov_data_copied = 0; for (i = 0; i < *iov_n; i++) { memcpy((char*) sreq->dev.tmpbuf + iov_data_copied, iov[i].MPID_IOV_BUF, iov[i].MPID_IOV_LEN); iov_data_copied += iov[i].MPID_IOV_LEN; } sreq->dev.segment_first = last; last = (data_sz <= sreq->dev.tmpbuf_sz - iov_data_copied) ? sreq->dev.segment_size : sreq->dev.segment_first + sreq->dev.tmpbuf_sz - iov_data_copied; MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST, "pre-pack: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT, sreq->dev.segment_first, last)); MPID_Segment_pack(sreq->dev.segment_ptr, sreq->dev.segment_first, &last, (char*) sreq->dev.tmpbuf + iov_data_copied); MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST, "post-pack: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT, sreq->dev.segment_first, last)); iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)sreq->dev.tmpbuf; iov[0].MPID_IOV_LEN = last - sreq->dev.segment_first + iov_data_copied; *iov_n = 1; if (last == sreq->dev.segment_size) { MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"remaining data packed into SRBuf"); sreq->dev.OnDataAvail = sreq->dev.OnFinal; } else { MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"more data packed into SRBuf"); sreq->dev.segment_first = last; sreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_SendReloadIOV; } } fn_exit: MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_SEND_IOV); return mpi_errno;}/* * MPIDI_CH3U_Request_load_recv_iov() * * Fill the request's IOV with the next (or remaining) portion of data * described by the segment (also contained in the request * structure). If the density of IOV is not sufficient, allocate a * send/receive buffer and point the IOV at the buffer. */#undef FUNCNAME#define FUNCNAME MPIDI_CH3U_Request_load_recv_iov#undef FCNAME#define FCNAME MPIDI_QUOTE(FUNCNAME)int MPIDI_CH3U_Request_load_recv_iov(MPID_Request * const rreq){ MPIDI_msg_sz_t last; int mpi_errno = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_RECV_IOV); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_RECV_IOV); if (rreq->dev.segment_first < rreq->dev.segment_size) { /* still reading data that needs to go into the user buffer */ if (MPIDI_Request_get_srbuf_flag(rreq)) { MPIDI_msg_sz_t data_sz; MPIDI_msg_sz_t tmpbuf_sz; /* Once a SRBuf is in use, we continue to use it since a small amount of data may already be present at the beginning of the buffer. This data is left over from the previous unpack, most like a result of alignment issues. NOTE: we could force the use of the SRBuf only when (rreq->dev.tmpbuf_off > 0)... */ data_sz = rreq->dev.segment_size - rreq->dev.segment_first - rreq->dev.tmpbuf_off; MPIU_Assert(data_sz > 0); tmpbuf_sz = rreq->dev.tmpbuf_sz - rreq->dev.tmpbuf_off; if (data_sz > tmpbuf_sz) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -