int MPIDI_CH3U_Complete_posted_with_error(MPIDI_VC_t *vc) { int mpi_errno = MPI_SUCCESS; MPID_Request *req, *prev_req; int error = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPIDU_COMPLETE_POSTED_WITH_ERROR); MPIDI_FUNC_ENTER(MPID_STATE_MPIDU_COMPLETE_POSTED_WITH_ERROR); MPIU_THREAD_CS_ENTER(MSGQUEUE,); /* check each req to see if the VC is part of that communicator */ req = recvq_posted_head; prev_req = NULL; while (req) { if (req->dev.match.parts.rank != MPI_ANY_SOURCE && req_uses_vc(req, vc)) { /* this req is expected on the VC */ dequeue_and_set_error(&req, prev_req, &error, vc->pg_rank); } else if (req->dev.match.parts.rank == MPI_ANY_SOURCE && is_vc_in_comm(vc, req->comm)) { /* This req is an ANY_SOURCE and is expected on a communicator that includes the VC. We need to dequeue all anysources posted in a communicator with a failed VC. We check whether the VC is in the communicator by iterating over the comm's VC table. Since this may be expensive, now that we know the VC is in comm, we take the opportunity to scan the rest of the posted recv queue for other anysources with the same communicator. Note that in the worst case this is O(N*M), where N is the number of posted requests and M is the number of communicators. This can happen if every req is an anysource and uses a different communicator. We can possibly conditionally execute the optimization based on number of comms, number of posted requests and communicator size. */ MPID_Request *as_req = req->dev.next; MPID_Request *prev_as_req = req; /* First remove any AS recvs on this comm that were posted AFTER this req */ while (as_req) { if (as_req->comm == req->comm && as_req->dev.match.parts.rank == MPI_ANY_SOURCE) { dequeue_and_set_error(&as_req, prev_as_req, &error, vc->pg_rank); } else { prev_as_req = as_req; as_req = as_req->dev.next; } } /* Now remove this req. We do this in this order to make it easier to keep track of req and prev_req pointers */ dequeue_and_set_error(&req, prev_req, &error, vc->pg_rank); } else { prev_req = req; req = req->dev.next; } } fn_exit: MPIU_THREAD_CS_EXIT(MSGQUEUE,); MPIDI_FUNC_EXIT(MPID_STATE_MPIDU_COMPLETE_POSTED_WITH_ERROR); return mpi_errno; fn_fail: goto fn_exit; }
int MPIDI_CH3U_Complete_posted_with_error(MPIDI_VC_t *vc) { int mpi_errno = MPI_SUCCESS; MPID_Request *req, *prev_req; int error = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPIDU_COMPLETE_POSTED_WITH_ERROR); MPIDI_FUNC_ENTER(MPID_STATE_MPIDU_COMPLETE_POSTED_WITH_ERROR); MPIU_THREAD_CS_ENTER(MSGQUEUE,); /* check each req in the posted queue and complete-with-error any requests using this VC. */ req = recvq_posted_head; prev_req = NULL; while (req) { if (req->dev.match.parts.rank != MPI_ANY_SOURCE && req_uses_vc(req, vc)) { dequeue_and_set_error(&req, prev_req, &error, vc->pg_rank); } else { prev_req = req; req = req->dev.next; } } fn_exit: MPIU_THREAD_CS_EXIT(MSGQUEUE,); MPIDI_FUNC_EXIT(MPID_STATE_MPIDU_COMPLETE_POSTED_WITH_ERROR); return mpi_errno; fn_fail: goto fn_exit; }
int MPIDI_CH3U_Complete_disabled_anysources(void) { int mpi_errno = MPI_SUCCESS; MPID_Request *req, *prev_req; int error = MPI_SUCCESS; MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_COMPLETE_DISABLED_ANYSOURCES); MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_COMPLETE_DISABLED_ANYSOURCES); MPIU_THREAD_CS_ENTER(MSGQUEUE,); /* Check each request in the posted queue, and complete-with-error any anysource requests posted on communicators that have disabled anysources */ req = recvq_posted_head; prev_req = NULL; while (req) { if (req->dev.match.parts.rank == MPI_ANY_SOURCE && !MPIDI_CH3I_Comm_AS_enabled(req->comm)) { dequeue_and_set_error(&req, prev_req, &error, MPI_PROC_NULL); /* we don't know the rank of the failed proc */ } else { prev_req = req; req = req->dev.next; } } fn_exit: MPIU_THREAD_CS_EXIT(MSGQUEUE,); MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_COMPLETE_DISABLED_ANYSOURCES); return mpi_errno; fn_fail: goto fn_exit; }