# vim: set ft=c: MPI_Cancel: .desc: Cancels a communication request .docnotes: NULL /* Notes: The primary expected use of 'MPI_Cancel' is in multi-buffering schemes, where speculative 'MPI_Irecvs' are made. When the computation completes, some of these receive requests may remain; using 'MPI_Cancel' allows the user to cancel these unsatisfied requests. Cancelling a send operation is much more difficult, in large part because the send will usually be at least partially complete (the information on the tag, size, and source are usually sent immediately to the destination). Users are advised that cancelling a send, while a local operation (as defined by the MPI standard), is likely to be expensive (usually generating one or more internal messages). */ MPI_Grequest_complete: .desc: Notify MPI that a user-defined request is complete .seealso: MPI_Grequest_start { -- error_check -- if (request_ptr && request_ptr->kind != MPIR_REQUEST_KIND__GREQUEST) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_REQUEST, "**notgenreq", 0); goto fn_fail; } } MPI_Grequest_start: .desc: Create and return a user-defined request MPIX_Grequest_start: query_fn: FUNCTION_SMALL, func_type=MPI_Grequest_query_function, [callback function invoked when request status is queried] free_fn: FUNCTION_SMALL, func_type=MPI_Grequest_free_function, [callback function invoked when request is freed] cancel_fn: FUNCTION_SMALL, func_type=MPI_Grequest_cancel_function, [callback function invoked when request is cancelled] poll_fn: FUNCTION_SMALL, func_type=MPIX_Grequest_poll_function, [callback function invoked when request completion is tested] wait_fn: FUNCTION_SMALL, func_type=MPIX_Grequest_wait_function, [callback function invoked when request is waited on] extra_state: EXTRA_STATE, [extra state] request: REQUEST, direction=out, [generalized request] .file: grequest_start_x .desc: Create and return a user-defined extended request { MPIR_Request *request_ptr = NULL; mpi_errno = MPIR_Grequest_start_impl(query_fn, free_fn, cancel_fn, extra_state, &request_ptr); if (mpi_errno) { goto fn_fail; } request_ptr->u.ureq.greq_fns->poll_fn = poll_fn; request_ptr->u.ureq.greq_fns->wait_fn = wait_fn; *request = request_ptr->handle; } MPIX_Grequest_class_create: query_fn: FUNCTION_SMALL, func_type=MPI_Grequest_query_function, [callback function invoked when request status is queried] free_fn: FUNCTION_SMALL, func_type=MPI_Grequest_free_function, [callback function invoked when request is freed] cancel_fn: FUNCTION_SMALL, func_type=MPI_Grequest_cancel_function, [callback function invoked when request is cancelled] poll_fn: FUNCTION_SMALL, func_type=MPIX_Grequest_poll_function, [callback function invoked when request completion is tested] wait_fn: FUNCTION_SMALL, func_type=MPIX_Grequest_wait_function, [callback function invoked when request is waited on] greq_class: GREQUEST_CLASS, direction=out, [generalized request class] MPIX_Grequest_class_allocate: greq_class: GREQUEST_CLASS, [generalized request class] extra_state: EXTRA_STATE, [extra state] request: REQUEST, direction=out, [generalized request] .desc: Create and return a user-defined extended request based on a generalized request class MPI_Request_free: .desc: Frees a communication request object .seealso: MPI_Isend, MPI_Irecv, MPI_Issend, MPI_Ibsend, MPI_Irsend, MPI_Recv_init, MPI_Send_init, MPI_Ssend_init, MPI_Rsend_init, MPI_Wait, MPI_Test, MPI_Waitall, MPI_Waitany, MPI_Waitsome, MPI_Testall, MPI_Testany, MPI_Testsome /* Notes: This routine is normally used to free inactive persistent requests created with either 'MPI_Recv_init' or 'MPI_Send_init' and friends. It `is` also permissible to free an active request. However, once freed, the request can no longer be used in a wait or test routine (e.g., 'MPI_Wait') to determine completion. This routine may also be used to free a non-persistent requests such as those created with 'MPI_Irecv' or 'MPI_Isend' and friends. Like active persistent requests, once freed, the request can no longer be used with test/wait routines to determine completion. */ MPI_Request_get_status: .desc: Nondestructive test for the completion of a Request /* Notes: Unlike 'MPI_Test', 'MPI_Request_get_status' does not deallocate or deactivate the request. A call to one of the test/wait routines or 'MPI_Request_free' should be made to release the request object. */ { -- early_return -- if (request == MPI_REQUEST_NULL || !MPIR_Request_is_active(request_ptr)) { *flag = 1; MPIR_Status_set_empty(status); goto fn_exit; } } { mpi_errno = MPIR_Test(request_ptr, flag, status); if (mpi_errno) { goto fn_fail; } } MPI_Request_get_status_all: .desc: Nondestructive test for the completion of all requests { mpi_errno = MPIR_Testall(count, request_ptrs, flag, array_of_statuses); if (mpi_errno) { goto fn_fail; } } MPI_Request_get_status_any: .desc: Nondestructive test for the completion of any of the requests { mpi_errno = MPIR_Testany(count, request_ptrs, indx, flag, status); if (mpi_errno) { goto fn_fail; } } MPI_Request_get_status_some: .desc: Nondestructive test for the completion of some of the requests { -- error_check -- array_of_indices if (incount > 0) { MPIR_ERRTEST_ARGNULL(array_of_requests, "array_of_requests", mpi_errno); MPIR_ERRTEST_ARGNULL(array_of_indices, "array_of_indices", mpi_errno); } } { mpi_errno = MPIR_Testsome(incount, request_ptrs, outcount, array_of_indices, array_of_statuses); if (mpi_errno) { goto fn_fail; } } MPI_Start: .desc: Initiates a communication with a persistent request handle { mpi_errno = MPID_Startall(1, &request_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPI_Startall: .desc: Starts a collection of persistent requests .impl: mpid /* Notes: Unlike 'MPI_Waitall', 'MPI_Startall' does not provide a mechanism for returning multiple errors nor pinpointing the request(s) involved. Furthermore, the behavior of 'MPI_Startall' after an error occurs is not defined by the MPI standard. If well-defined error reporting and behavior are required, multiple calls to 'MPI_Start' should be used instead. */ MPI_Status_get_error: .desc: Get MPI_ERROR field from the status .skip: initcheck, global_cs .impl: direct { *error = status->MPI_ERROR; return MPI_SUCCESS; } MPI_Status_get_source: .desc: Get MPI_SOURCE field from the status .skip: initcheck, global_cs .impl: direct { *source = status->MPI_SOURCE; return MPI_SUCCESS; } MPI_Status_get_tag: .desc: Get MPI_TAG field from the status .skip: initcheck, global_cs .impl: direct { *tag = status->MPI_TAG; return MPI_SUCCESS; } MPI_Status_set_error: .desc: Set MPI_ERROR field in the status .skip: initcheck, global_cs, validate-error .impl: direct { status->MPI_ERROR = error; return MPI_SUCCESS; } MPI_Status_set_source: .desc: Set MPI_SOURCE field in the status .skip: initcheck, global_cs, validate-source .impl: direct { status->MPI_SOURCE = source; return MPI_SUCCESS; } MPI_Status_set_tag: .desc: Set MPI_TAG field in the status .skip: initcheck, global_cs, validate-tag .impl: direct { status->MPI_TAG = tag; return MPI_SUCCESS; } MPI_Status_set_cancelled: .desc: Sets the cancelled state associated with a request .skip: initcheck, global_cs MPI_Test_cancelled: .desc: Tests to see if a request was cancelled .skip: global_cs MPI_Test: .desc: Test for the completion of a request .docnotes: waitstatus { -- early_return -- if (*request == MPI_REQUEST_NULL || !MPIR_Request_is_active(request_ptr)) { *flag = 1; MPIR_Status_set_empty(status); goto fn_exit; } } { mpi_errno = MPIR_Test(request_ptr, flag, status); if (*flag) { if (!MPIR_Request_is_persistent(request_ptr)) { int rc = MPIR_Request_free_return(request_ptr); *request = MPI_REQUEST_NULL; if (rc) { mpi_errno = rc; } } } if (mpi_errno) goto fn_fail; } MPI_Testall: .desc: Tests for the completion of all previously initiated requests .docnotes: waitstatus .error: MPI_ERR_IN_STATUS /* Notes: 'flag' is true only if all requests have completed. Otherwise, flag is false and neither the 'array_of_requests' nor the 'array_of_statuses' is modified. If one or more of the requests completes with an error, 'MPI_ERR_IN_STATUS' is returned. An error value will be present is elements of 'array_of_statuses' associated with the requests. Likewise, the 'MPI_ERROR' field in the status elements associated with requests that have successfully completed will be 'MPI_SUCCESS'. Finally, those requests that have not completed will have a value of 'MPI_ERR_PENDING'. While it is possible to list a request handle more than once in the 'array_of_requests', such an action is considered erroneous and may cause the program to unexecpectedly terminate or produce incorrect results. */ { mpi_errno = MPIR_Testall(count, request_ptrs, flag, array_of_statuses); if (*flag) { for (int i = 0; i < count; i++) { if (mpi_errno && array_of_statuses != MPI_STATUSES_IGNORE && array_of_statuses[i].MPI_ERROR == MPI_ERR_PENDING) { continue; } if (request_ptrs[i] && !MPIR_Request_is_persistent(request_ptrs[i])) { int rc = MPIR_Request_free_return(request_ptrs[i]); array_of_requests[i] = MPI_REQUEST_NULL; if (rc) { if (array_of_statuses == MPI_STATUSES_IGNORE) { mpi_errno = MPI_ERR_IN_STATUS; } else if (mpi_errno == MPI_ERR_IN_STATUS) { array_of_statuses[i].MPI_ERROR = rc; } else { MPIR_Assert(mpi_errno == MPI_SUCCESS); /* init all statuses' MPI_ERROR fields first */ for (int j = 0; j < count; j++) { array_of_statuses[j].MPI_ERROR = MPI_SUCCESS; } mpi_errno = MPI_ERR_IN_STATUS; array_of_statuses[i].MPI_ERROR = rc; } } } } } if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPI_Testany: .desc: Tests for completion of any previdously initiated requests .docnotes: waitstatus /* Notes: While it is possible to list a request handle more than once in the 'array_of_requests', such an action is considered erroneous and may cause the program to unexecpectedly terminate or produce incorrect results. */ { /* Pass down request ptr to avoid redundant handle to ptr translation. */ mpi_errno = MPIR_Testany(count, request_ptrs, indx, flag, status); if (*indx != MPI_UNDEFINED) { if (request_ptrs[*indx] && !MPIR_Request_is_persistent(request_ptrs[*indx])) { int rc = MPIR_Request_free_return(request_ptrs[*indx]); array_of_requests[*indx] = MPI_REQUEST_NULL; if (rc) { mpi_errno = rc; } } } if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPI_Testsome: .desc: Tests for some given requests to complete .docnotes: waitstatus /* Notes: While it is possible to list a request handle more than once in the 'array_of_requests', such an action is considered erroneous and may cause the program to unexecpectedly terminate or produce incorrect results. */ { -- error_check -- array_of_indices if (incount > 0) { MPIR_ERRTEST_ARGNULL(array_of_requests, "array_of_requests", mpi_errno); MPIR_ERRTEST_ARGNULL(array_of_indices, "array_of_indices", mpi_errno); } } { /* Pass down request ptr to avoid redundant handle to ptr translation. */ mpi_errno = MPIR_Testsome(incount, request_ptrs, outcount, array_of_indices, array_of_statuses); for (int i = 0; i < *outcount; i++) { int idx = array_of_indices[i]; if (request_ptrs[idx] && !MPIR_Request_is_persistent(request_ptrs[idx])) { int rc = MPIR_Request_free_return(request_ptrs[idx]); array_of_requests[idx] = MPI_REQUEST_NULL; if (rc) { if (array_of_statuses == MPI_STATUSES_IGNORE) { mpi_errno = MPI_ERR_IN_STATUS; } else if (mpi_errno == MPI_ERR_IN_STATUS) { array_of_statuses[i].MPI_ERROR = rc; } else { MPIR_Assert(mpi_errno == MPI_SUCCESS); /* init all statuses' MPI_ERROR fields first */ for (int j = 0; j < *outcount; j++) { array_of_statuses[j].MPI_ERROR = MPI_SUCCESS; } mpi_errno = MPI_ERR_IN_STATUS; array_of_statuses[i].MPI_ERROR = rc; } } } } if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPI_Wait: .desc: Waits for an MPI request to complete .docnotes: waitstatus { -- early_return -- if (*request == MPI_REQUEST_NULL || !MPIR_Request_is_active(request_ptr)) { MPIR_Status_set_empty(status); goto fn_exit; } } { mpi_errno = MPIR_Wait(request_ptr, status); if (!MPIR_Request_is_persistent(request_ptr)) { int rc = MPIR_Request_free_return(request_ptr); *request = MPI_REQUEST_NULL; if (rc) { mpi_errno = rc; } } if (mpi_errno) goto fn_fail; } MPI_Waitall: .desc: Waits for all given MPI Requests to complete .docnotes: waitstatus .error: MPI_ERR_IN_STATUS /* Notes: If one or more of the requests completes with an error, 'MPI_ERR_IN_STATUS' is returned. An error value will be present is elements of 'array_of_statuses' associated with the requests. Likewise, the 'MPI_ERROR' field in the status elements associated with requests that have successfully completed will be 'MPI_SUCCESS'. Finally, those requests that have not completed will have a value of 'MPI_ERR_PENDING'. While it is possible to list a request handle more than once in the array_of_requests, such an action is considered erroneous and may cause the program to unexecpectedly terminate or produce incorrect results. */ { mpi_errno = MPIR_Waitall(count, request_ptrs, array_of_statuses); for (int i = 0; i < count; i++) { if (mpi_errno && array_of_statuses != MPI_STATUSES_IGNORE && array_of_statuses[i].MPI_ERROR == MPI_ERR_PENDING) { continue; } if (request_ptrs[i] && !MPIR_Request_is_persistent(request_ptrs[i])) { int rc = MPIR_Request_free_return(request_ptrs[i]); array_of_requests[i] = MPI_REQUEST_NULL; if (rc) { if (array_of_statuses == MPI_STATUSES_IGNORE) { mpi_errno = MPI_ERR_IN_STATUS; } else if (mpi_errno == MPI_ERR_IN_STATUS) { array_of_statuses[i].MPI_ERROR = rc; } else { MPIR_Assert(mpi_errno == MPI_SUCCESS); /* init all statuses' MPI_ERROR fields first */ for (int j = 0; j < count; j++) { array_of_statuses[j].MPI_ERROR = MPI_SUCCESS; } mpi_errno = MPI_ERR_IN_STATUS; array_of_statuses[i].MPI_ERROR = rc; } } } } if (mpi_errno) goto fn_fail; } MPI_Waitany: .desc: Waits for any specified MPI Request to complete .docnotes: waitstatus /* Notes: If all of the requests are 'MPI_REQUEST_NULL', then 'indx' is returned as 'MPI_UNDEFINED', and 'status' is returned as an empty status. While it is possible to list a request handle more than once in the array_of_requests, such an action is considered erroneous and may cause the program to unexecpectedly terminate or produce incorrect results. */ { /* Pass down request ptr to avoid redundant handle to ptr translation. */ mpi_errno = MPIR_Waitany(count, request_ptrs, indx, status); if (*indx != MPI_UNDEFINED) { if (request_ptrs[*indx] && !MPIR_Request_is_persistent(request_ptrs[*indx])) { int rc = MPIR_Request_free_return(request_ptrs[*indx]); array_of_requests[*indx] = MPI_REQUEST_NULL; if (rc) { mpi_errno = rc; } } } if (mpi_errno) goto fn_fail; } MPI_Waitsome: .desc: Waits for some given MPI Requests to complete /* Notes: The array of indices are in the range '0' to 'incount - 1' for C and in the range '1' to 'incount' for Fortran. Null requests are ignored; if all requests are null, then the routine returns with 'outcount' set to 'MPI_UNDEFINED'. While it is possible to list a request handle more than once in the array_of_requests, such an action is considered erroneous and may cause the program to unexecpectedly terminate or produce incorrect results. 'MPI_Waitsome' provides an interface much like the Unix 'select' or 'poll' calls and, in a high qualilty implementation, indicates all of the requests that have completed when 'MPI_Waitsome' is called. However, 'MPI_Waitsome' only guarantees that at least one request has completed; there is no guarantee that `all` completed requests will be returned, or that the entries in 'array_of_indices' will be in increasing order. Also, requests that are completed while 'MPI_Waitsome' is executing may or may not be returned, depending on the timing of the completion of the message. .N waitstatus */ { -- error_check -- array_of_indices if (incount > 0) { MPIR_ERRTEST_ARGNULL(array_of_indices, "array_of_indices", mpi_errno); } } { /* Pass down request ptr to avoid redundant handle to ptr translation. */ mpi_errno = MPIR_Waitsome(incount, request_ptrs, outcount, array_of_indices, array_of_statuses); for (int i = 0; i < *outcount; i++) { int idx = array_of_indices[i]; if (request_ptrs[idx] && !MPIR_Request_is_persistent(request_ptrs[idx])) { int rc = MPIR_Request_free_return(request_ptrs[idx]); array_of_requests[idx] = MPI_REQUEST_NULL; if (rc) { if (array_of_statuses == MPI_STATUSES_IGNORE) { mpi_errno = MPI_ERR_IN_STATUS; } else if (mpi_errno == MPI_ERR_IN_STATUS) { array_of_statuses[i].MPI_ERROR = rc; } else { MPIR_Assert(mpi_errno == MPI_SUCCESS); /* init all statuses' MPI_ERROR fields first */ for (int j = 0; j < *outcount; j++) { array_of_statuses[j].MPI_ERROR = MPI_SUCCESS; } mpi_errno = MPI_ERR_IN_STATUS; array_of_statuses[i].MPI_ERROR = rc; } } } } if (mpi_errno) goto fn_fail; } MPIX_Request_is_complete: .return: LOGICAL request: REQUEST, direction=in, pointer=False .impl: direct { MPIR_Request *request_ptr; MPIR_Request_get_ptr(request, request_ptr); if (request_ptr) { return MPIR_Request_is_complete(request_ptr); } else { return 1; } }