Example #1
0
void MPID_Request_free(MPI_Request request)
{
    int mpi_errno = MPI_SUCCESS;

    if (request == NULL)
        return;

    /* rely on the fact that SendIcomplete and RecvIcomplete
     * do a device check
     */
    switch (request->handle_type) {
    case MPIR_SEND:
        if (MPID_SendIcomplete(request, &mpi_errno)) {
            MPID_SendFree(request);
            request = 0;
        }
        break;
    case MPIR_RECV:
        if (MPID_RecvIcomplete(request, (MPI_Status *) 0, &mpi_errno)) {
            MPID_RecvFree(request);
            request = 0;
        }
        break;
    case MPIR_PERSISTENT_SEND:
        if (MPID_SendIcomplete(request, &mpi_errno)) {
            MPID_PSendFree(request);
            request = 0;
        }
        break;
    case MPIR_PERSISTENT_RECV:
        if (MPID_RecvIcomplete(request, (MPI_Status *) 0, &mpi_errno)) {
            MPID_PRecvFree(request);
            request = 0;
        }
        break;
    default:
        MPID_Abort((struct MPIR_COMMUNICATOR *) 0, 1, (char *)"MPI internal",
                   (char *)"Unknown request type in MPID_Request_free");
        break;
    }


    /* the device will still have pointers (I hope!) to
     * pending sends and receives. They will be freed
     * automatically when the request completes
     * and the device notices the zero reference count.
     * See SEND_COMPLETE and RECV_COMPLETE in psmpriv.h
     */

    if (request != NULL) {
        request->chandle.ref_count--;
    }
}
Example #2
0
/*@
    MPI_Testsome - Tests for some given communications to complete

Input Parameters:
+ incount - length of array_of_requests (integer) 
- array_of_requests - array of requests (array of handles) 

Output Parameters:
+ outcount - number of completed requests (integer) 
. array_of_indices - array of indices of operations that 
completed (array of integers) 
- array_of_statuses - array of status objects for 
    operations that completed (array of Status).  May be 'MPI_STATUSES_IGNORE'.

.N waitstatus

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_IN_STATUS

@*/
int MPI_Testsome( 
	int incount, 
	MPI_Request array_of_requests[], 
	int *outcount, 
	int array_of_indices[], 
	MPI_Status array_of_statuses[] )
{
    int i, j, mpi_errno = MPI_SUCCESS;
    int nfound = 0;
    int nnull  = 0;
    int mpi_lerr;
    MPI_Request request;
    static char myname[] = "MPI_TESTSOME";
  
    disableSignal();

    TR_PUSH(myname);
    /* NOTE:
       This implementation will not work correctly if the device requires
       messages to be received in some particular order.  In that case, 
       this routine needs to try and complete the messages in ANY order.
       
       The same is true for testall.c .
     */
    MPID_DeviceCheck( MPID_NOTBLOCKING );
    for (i = 0; i < incount; i++) {
	/* Skip over null handles.  We need this for handles generated
	   when MPI_PROC_NULL is the source or destination of an 
	   operation */
	request = array_of_requests[i];

	if (!request) {/*  || !request->chandle.active) { */
	    nnull ++;
	    continue;
	    }

	mpi_lerr = 0;
	switch (request->handle_type) {
	case MPIR_SEND:
	    if (MPID_SendRequestCancelled(request)) {
		if (array_of_statuses) {
		    array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED; 
		    array_of_statuses[i].MPI_ERROR = MPI_SUCCESS;
		}
	        nfound++; }
	    else {
		if (request->shandle.is_complete || 
		    MPID_SendIcomplete( request, &mpi_lerr )) {
		    array_of_indices[nfound] = i;
		    if (mpi_lerr) {
			if (mpi_errno == MPI_SUCCESS) {
			    if (array_of_statuses) {
				for (j=0; j<incount; j++) 
				    array_of_statuses[j].MPI_ERROR = MPI_SUCCESS;
			    }
			    mpi_errno = MPI_ERR_IN_STATUS;
			}
			if (array_of_statuses) 
			    array_of_statuses[nfound].MPI_ERROR = mpi_lerr;
		    }
		    MPIR_FORGET_SEND( &request->shandle );
		    MPID_SendFree( request );
		    array_of_requests[i] = 0;
		    nfound++;
		}
	    }
	    break;
	case MPIR_RECV:
	    if (request->rhandle.s.MPI_TAG == MPIR_MSG_CANCELLED) {
		if (array_of_statuses)
		    array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED; 
	        nfound++; }
	    else {
		if (request->rhandle.is_complete || 
		    MPID_RecvIcomplete( request, (MPI_Status *)0, 
					&mpi_lerr )) {
		    array_of_indices[nfound]  = i;
		    if (request->rhandle.s.MPI_ERROR) {
			if (mpi_errno == MPI_SUCCESS) {
			    if (array_of_statuses) {
				for (j=0; j<incount; j++) 
				    array_of_statuses[j].MPI_ERROR = MPI_SUCCESS;
			    }
			    mpi_errno = MPI_ERR_IN_STATUS;
			}
		    }
		    if (array_of_statuses)
			array_of_statuses[nfound] = request->rhandle.s;
		    MPID_RecvFree( request );
		    array_of_requests[i] = 0;
		    nfound++;
		}
	    }
	    break;
	case MPIR_PERSISTENT_SEND:
	    if (!request->persistent_shandle.active) {
		if (MPID_SendRequestCancelled(&request->persistent_shandle)) {
		    if (array_of_statuses) 
			array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED;
		    nfound++;
		}
		else
		    nnull++;
	    }
	    else if (request->persistent_shandle.shandle.is_complete ||
		     MPID_SendIcomplete( request, &mpi_lerr )) {
		array_of_indices[nfound] = i;
		if (mpi_lerr) {
		    if (mpi_errno == MPI_SUCCESS) {
			if (array_of_statuses) {
			    for (j=0; j<incount; j++) 
				array_of_statuses[j].MPI_ERROR = MPI_SUCCESS;
			}
		    mpi_errno = MPI_ERR_IN_STATUS;
		    }
		    if (array_of_statuses) 
			array_of_statuses[nfound].MPI_ERROR = mpi_lerr;
		}
		request->persistent_shandle.active = 0;
		nfound++;
	    }
	    break;
	case MPIR_PERSISTENT_RECV:
	    if (!request->persistent_rhandle.active) {
		if (request->persistent_rhandle.rhandle.s.MPI_TAG ==
		    MPIR_MSG_CANCELLED) {
		    if (array_of_statuses) 
			array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED;
		    nfound++;
		}
		else
		    nnull++;
	    }
	    else if (request->persistent_rhandle.rhandle.is_complete ||
		     MPID_RecvIcomplete( request, (MPI_Status *)0, 
					 &mpi_lerr )) {
		array_of_indices[nfound] = i;
		if (mpi_lerr) {
		    if (mpi_errno == MPI_SUCCESS) {
			if (array_of_statuses) {
			    for (j=0; j<incount; j++) 
				array_of_statuses[j].MPI_ERROR = MPI_SUCCESS;
			}
			mpi_errno = MPI_ERR_IN_STATUS;
		    }
		}
		if (array_of_statuses) 
		    array_of_statuses[nfound] = 
			request->persistent_rhandle.rhandle.s;
		request->persistent_rhandle.active = 0;
		nfound++;
	    }
	    break;
	}
    }
    if (nnull == incount)
	*outcount = MPI_UNDEFINED;
    else
	*outcount = nfound;
    if (mpi_errno) {
        revertSignal();
	return MPIR_ERROR(MPIR_COMM_WORLD, mpi_errno, myname );
	}
    TR_POP;
    revertSignal();
    return mpi_errno;
}
Example #3
0
/*@
    MPI_Testall - Tests for the completion of all previously initiated
    communications

Input Parameters:
+ count - lists length (integer) 
- array_of_requests - array of requests (array of handles) 

Output Parameters:
+ flag - (logical) 
- array_of_statuses - array of status objects (array of 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.

.N waitstatus

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_IN_STATUS

@*/
EXPORT_MPI_API int MPI_Testall( 
	int count, 
	MPI_Request array_of_requests[], 
	int *flag, 
	MPI_Status array_of_statuses[] )
{
    int i, mpi_errno = MPI_SUCCESS;
    MPI_Request request;
    int nready;
    static char myname[] = "MPI_TESTALL";

    TR_PUSH(myname);

    MPID_DeviceCheck( MPID_NOTBLOCKING );
  /* It is a good thing that the receive requests contain the status object!
     We need this to save the status information in the case where not
     all of the requests have completed.

     Note that this routine forces some changes on the ADI test routines.
     It must be possible to test a completed request multiple times;
     once the "is_complete" field is set, the data must be saved until
     the request is explicitly freed.  That is, unlike the MPI tests,
     the ADI tests must be nondestructive.
   */
    nready = 0;
    for (i = 0; i < count; i++ ) {
	request = array_of_requests[i];
	if (!request) {
	    nready ++;
	    continue;
	}
	switch (request->handle_type) {
	case MPIR_SEND:
	    if (MPID_SendRequestCancelled(request)) {
		array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED; 
	        nready++; }
	    else {
	    if (!request->shandle.is_complete) {
		if (MPID_SendIcomplete( request, &mpi_errno ))
		    nready++;
	    }
	    else nready++;
	    }
	    break;
	case MPIR_RECV:
	    if (request->rhandle.s.MPI_TAG == MPIR_MSG_CANCELLED) {
		array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED; 
	        nready++; }
	    else {
	    if (!request->rhandle.is_complete) {
		if (MPID_RecvIcomplete( request, (MPI_Status *)0, &mpi_errno ))
		    nready++;
	    }
	    else nready++;
	    }
	    break;
	case MPIR_PERSISTENT_SEND:
	    if (request->persistent_shandle.active &&
		!request->persistent_shandle.shandle.is_complete) {
		if (MPID_SendIcomplete( request, &mpi_errno ))
		    nready++;
	    }
	    else nready++;
	    break;
	case MPIR_PERSISTENT_RECV:
	    if (request->persistent_rhandle.active &&
		!request->persistent_rhandle.rhandle.is_complete) {
		if (MPID_RecvIcomplete( request, (MPI_Status *)0, &mpi_errno ))
		    nready++;
	    }
	    else nready++;
	    break;
	}
	if (mpi_errno) {
	    MPIR_Set_Status_error_array( array_of_requests, count, i, 
					 mpi_errno, array_of_statuses );
	    mpi_errno = MPI_ERR_IN_STATUS;
	    TR_POP;
	    MPIR_RETURN(MPIR_COMM_WORLD, mpi_errno, myname );
	}
    }
    *flag = (nready == count);
    /* Because a request may have completed with an error (such as 
       MPI_ERR_TRUNCATE), we need to check here as well */
    if (nready == count) {
	for (i=0; i<count; i++) {
	    request = array_of_requests[i];
	    if (!request) {
		/* See MPI Standard, 3.7 */
		array_of_statuses[i].MPI_TAG	= MPI_ANY_TAG;
		array_of_statuses[i].MPI_SOURCE	= MPI_ANY_SOURCE;
		array_of_statuses[i].MPI_ERROR	= MPI_SUCCESS;
		array_of_statuses[i].count	= 0;
		continue;
	    }
	    switch (request->handle_type) {
	    case MPIR_SEND:
		if (array_of_statuses[i].MPI_TAG != MPIR_MSG_CANCELLED) {
		    MPIR_FORGET_SEND( &request->shandle );
		    MPID_Send_free( array_of_requests[i] );
		    array_of_requests[i] = 0;
		}
		break;
	    case MPIR_RECV:
		if (array_of_statuses[i].MPI_TAG != MPIR_MSG_CANCELLED) {
		    if (request->rhandle.s.MPI_ERROR) 
			mpi_errno = request->rhandle.s.MPI_ERROR;
/*
		if (request->rhandle.s.MPI_ERROR && mpi_errno == MPI_SUCCESS) {
		    for (j=0; j<count; j++) {
			if (!array_of_requests[i] || 
			    array_of_requests[i].is_complete)
			    array_of_statuses[j].MPI_ERROR = MPI_SUCCESS;
			else
			    array_of_statuses[j].MPI_ERROR = MPI_ERR_PENDING;
		    }
		    mpi_errno = MPI_ERR_IN_STATUS;
		}
 */
		array_of_statuses[i] = request->rhandle.s;
		MPID_Recv_free( array_of_requests[i] );
		array_of_requests[i] = 0;
		}
		break;
	    case MPIR_PERSISTENT_SEND:
		if (request->persistent_shandle.active) {
		    /* array_of_statuses[i] =
			request->persistent_shandle.shandle.s; */
		    array_of_statuses[i].MPI_ERROR = 
		       MPID_SendRequestErrval(&request->persistent_shandle.shandle);
		    request->persistent_shandle.active = 0;
		}
		else {
		    /* See MPI Standard, 3.7 */
		    /* Thanks to [email protected] for this fix */
		    if (MPID_SendRequestCancelled(&request->persistent_shandle))
			array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED;
		    else
			array_of_statuses[i].MPI_TAG = MPI_ANY_TAG;

		    array_of_statuses[i].MPI_SOURCE = MPI_ANY_SOURCE;
		    array_of_statuses[i].MPI_ERROR  = MPI_SUCCESS;
		    array_of_statuses[i].count	    = 0;
		}
		break;
	    case MPIR_PERSISTENT_RECV:
		if (request->persistent_rhandle.active) {
		    array_of_statuses[i] = 
			request->persistent_rhandle.rhandle.s;
		    mpi_errno = request->persistent_rhandle.rhandle.s.MPI_ERROR;
		    request->persistent_rhandle.active = 0;
		}
		else {
		    /* See MPI Standard, 3.7 */
		    /* Thanks to [email protected] for this fix */
		    if (request->persistent_rhandle.rhandle.s.MPI_TAG ==
			MPIR_MSG_CANCELLED) 
			array_of_statuses[i].MPI_TAG = MPIR_MSG_CANCELLED;
		    else
			array_of_statuses[i].MPI_TAG = MPI_ANY_TAG;

		    array_of_statuses[i].MPI_SOURCE = MPI_ANY_SOURCE;
		    array_of_statuses[i].MPI_ERROR  = MPI_SUCCESS;
		    array_of_statuses[i].count	    = 0;
		}
		break;
	    }
	    if (mpi_errno) {
		MPIR_Set_Status_error_array( array_of_requests, count, i, 
					     mpi_errno, array_of_statuses );
		mpi_errno = MPI_ERR_IN_STATUS;
		TR_POP;
		MPIR_RETURN(MPIR_COMM_WORLD, mpi_errno, myname );
	    }
	}
    }
    TR_POP;
    MPIR_RETURN(MPIR_COMM_WORLD, mpi_errno, myname );
}
Example #4
0
/*@
    MPI_Waitany - Waits for any specified send or receive to complete

Input Parameters:
+ count - list length (integer) 
- array_of_requests - array of requests (array of handles) 

Output Parameters:
+ index - index of handle for operation that completed (integer).  In the
range '0' to 'count-1'.  In Fortran, the range is '1' to 'count'.
- status - status object (Status) 

Notes:
If all of the requests are 'MPI_REQUEST_NULL', then 'index' is returned as 
'MPI_UNDEFINED', and 'status' is returned as an empty status.

.N waitstatus

.N fortran

.N Errors
.N MPI_SUCCESS
.N MPI_ERR_REQUEST
.N MPI_ERR_ARG
@*/
EXPORT_MPI_API int MPI_Waitany(
	int count, 
	MPI_Request array_of_requests[], 
	int *index, 
	MPI_Status *status )
{
    int i, mpi_errno = MPI_SUCCESS;
    int done;
    MPI_Request request;
    static char myname[] = "MPI_WAITANY";

    TR_PUSH(myname);
    *index = MPI_UNDEFINED;

    /* Check for all requests either null or inactive persistent */
    for (i=0; i < count; i++) {
	request = array_of_requests[i];
	if (!request) continue;
	if (request->handle_type == MPIR_PERSISTENT_SEND) {
	    if (request->persistent_shandle.active) break;
	    if (MPID_SendRequestCancelled(&request->persistent_shandle))
		break;
	}
	else if (request->handle_type == MPIR_PERSISTENT_RECV) {
	    if (request->persistent_rhandle.active) break;
	    if (request->persistent_rhandle.rhandle.s.MPI_TAG ==
		MPIR_MSG_CANCELLED) break;
	}
	else 
	    break;
    }

    if (i == count) {
	/* MPI Standard 1.1 requires an empty status in this case */
 	status->MPI_TAG	   = MPI_ANY_TAG;
	status->MPI_SOURCE = MPI_ANY_SOURCE;
	status->MPI_ERROR  = MPI_SUCCESS;
	MPID_ZERO_STATUS_COUNT(status);
        *index             = MPI_UNDEFINED;
	TR_POP;
	return mpi_errno;
	}
    done = 0;
    while (!done) {
	for (i=0; !done && i<count; i++) {
	    request = array_of_requests[i];
	    if (!request) continue;
	    switch (request->handle_type) {
	    case MPIR_SEND:
		if (MPID_SendRequestCancelled(request)) {
		    status->MPI_TAG = MPIR_MSG_CANCELLED; 
		    *index = i;
		    done = 1;
		}
		else {
		    if (MPID_SendIcomplete( request, &mpi_errno )) {
			if (mpi_errno) 
			    MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
			MPIR_FORGET_SEND( &request->shandle );
			MPID_Send_free( array_of_requests[i] );
			*index = i;
			array_of_requests[i] = 0;
			done = 1;
		    }
		}
		break;
	    case MPIR_RECV:
		if (request->rhandle.s.MPI_TAG == MPIR_MSG_CANCELLED) {
		    status->MPI_TAG = MPIR_MSG_CANCELLED;
		    MPID_Recv_free( array_of_requests[i] );
		    *index = i;
		    array_of_requests[i] = 0; 
		    done = 1;
		}
		else {
		    if (MPID_RecvIcomplete( request, status, &mpi_errno )) {
			if (mpi_errno) 
			    MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
			MPID_Recv_free( array_of_requests[i] );
			*index = i;
			array_of_requests[i] = 0;
			done = 1;
		    }
		}
		break;
	    case MPIR_PERSISTENT_SEND:
		if (request->persistent_shandle.active) {
		    if (MPID_SendIcomplete( request, &mpi_errno )) {
			if (mpi_errno) 
			    MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
			request->persistent_shandle.active = 0;
			*index = i;
			done = 1;
		    }
		}
		else {
		    if (MPID_SendRequestCancelled(&request->persistent_shandle)) {
			status->MPI_TAG = MPIR_MSG_CANCELLED; 
			*index = i;
			done = 1;
		    }
		}
		break;
	    case MPIR_PERSISTENT_RECV:
		if (request->persistent_rhandle.active) {
		    if (MPID_RecvIcomplete( request, status, &mpi_errno )) {
			if (mpi_errno) 
			    MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname );
			request->persistent_rhandle.active = 0;
			*index = i;
			done   = 1;
		    }
		}
		else {
		    if (request->persistent_rhandle.rhandle.s.MPI_TAG ==
			MPIR_MSG_CANCELLED) {
			status->MPI_TAG = MPIR_MSG_CANCELLED; 
			*index = i;
			done = 1;
		    }
		}
		break;
	    }
	}
	if (!done) {
	    /* Do a NON blocking check */
	    MPID_DeviceCheck( MPID_NOTBLOCKING );
	}
	else 
	    break;
    }
    TR_POP;
    return mpi_errno;
}
Example #5
0
void MPID_Request_free (MPI_Request request )
{
    MPID_Device *dev = NULL;
    MPI_Request rq = request ; /* MPID_devset->req_pending; */
    int mpi_errno = MPI_SUCCESS;
    
    switch (rq->handle_type) {
    case MPIR_SEND:
	if (MPID_SendIcomplete( rq, &mpi_errno )) {
	    MPIR_FORGET_SEND( &rq->shandle );
	    MPID_Send_free( rq );
	    /* MPID_devset->req_pending = 0;*/
	    rq = 0;
	}
	break;
    case MPIR_RECV:
	if (MPID_RecvIcomplete( rq, (MPI_Status *)0, &mpi_errno )) {
	    MPID_Recv_free( rq );
	    /* MPID_devset->req_pending = 0; */
	    rq = 0;
	}
	break;
    case MPIR_PERSISTENT_SEND:
	if (rq->persistent_shandle.active) {
	    MPID_Abort( (struct MPIR_COMMUNICATOR *)0, 1, "MPI internal", 
			"Unimplemented operation - active persistent send free" );
	} else {
  	    dev = MPID_devset->dev[((rq->persistent_shandle.perm_comm)->lrank_to_grank)
				  [rq->persistent_shandle.perm_dest]];
	    if (dev->persistent_free != NULL)
	      MPID_Device_call_persistent_free (rq, dev);
	    
	    MPID_PSend_free( rq );
	}
	break;
    case MPIR_PERSISTENT_RECV:
	if (rq->persistent_rhandle.active) {
	    MPID_Abort( (struct MPIR_COMMUNICATOR *)0, 1, "MPI internal", 
			"Unimplemented operation - active persistent recv free" );
	} else {
	    if (rq->persistent_rhandle.perm_source >= 0) {
		dev = MPID_devset->dev[rq->persistent_rhandle.perm_source];
	    } else {
		/* For a single device, we can use the related function, 
		   but what to do for multiple available devices? Multiple
		   persistent initialization? */
		if (MPID_devset->ndev == 1) {
		    dev = MPID_devset->dev_list;
		}
	    }
	    
	    if (dev != NULL && dev->persistent_free != NULL)
	      MPID_Device_call_persistent_free (rq, dev);
	}
	break;
    }

    MPID_DeviceCheck( MPID_NOTBLOCKING );
    /* 
     * If we couldn't complete it, decrement it's reference count
     * and forget about it.  This requires that the device detect
     * orphaned requests when they do complete, and process them
     * independent of any wait/test.
     */
    /*if (MPID_devset->req_pending) {*/
    if (rq) {
	rq->chandle.ref_count--;
/*	PRINTF( "Setting ref count to %d for %x\n", 
		rq->chandle.ref_count, (long)rq ); */
	/* MPID_devset->req_pending = 0; */
    }
}