-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/ch3/src/mpid_cancel_send.c
        -:    0:Graph:mpid_cancel_send.gcno
        -:    0:Data:mpid_cancel_send.gcda
        -:    0:Runs:3459
        -:    0:Programs:899
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *  (C) 2001 by Argonne National Laboratory.
        -:    4: *      See COPYRIGHT in top-level directory.
        -:    5: */
        -:    6:
        -:    7:#include "mpidimpl.h"
        -:    8:
        -:    9:/* FIXME: This should call a channel-provided routine to deliver the 
        -:   10:   cancel message, once the code decides that the request can still
        -:   11:   be cancelled */
        -:   12:
        -:   13:#undef FUNCNAME
        -:   14:#define FUNCNAME MPID_Cancel_send
        -:   15:#undef FCNAME
        -:   16:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   17:int MPID_Cancel_send(MPID_Request * sreq)
       43:   18:{
        -:   19:    MPIDI_VC_t * vc;
        -:   20:    int proto;
        -:   21:    int flag;
       43:   22:    int mpi_errno = MPI_SUCCESS;
        -:   23:    MPIDI_STATE_DECL(MPID_STATE_MPID_CANCEL_SEND);
        -:   24:
        -:   25:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_CANCEL_SEND);
        -:   26:    
       43:   27:    MPIU_Assert(sreq->kind == MPID_REQUEST_SEND);
        -:   28:
       43:   29:    MPIDI_Request_cancel_pending(sreq, &flag);
       43:   30:    if (flag)
        -:   31:    {
    #####:   32:	goto fn_exit;
        -:   33:    }
        -:   34:
        -:   35:    /*
        -:   36:     * FIXME: user requests returned by MPI_Ibsend() have a NULL comm pointer
        -:   37:     * and no pointer to the underlying communication
        -:   38:     * request.  For now, we simply fail to cancel the request.  In the future,
        -:   39:     * we should add a new request kind to indicate that
        -:   40:     * the request is a BSEND.  Then we can properly cancel the request, much 
        -:   41:     * in the way we do persistent requests.
        -:   42:     */
       43:   43:    if (sreq->comm == NULL)
        -:   44:    {
    #####:   45:	goto fn_exit;
        -:   46:    }
        -:   47:
       43:   48:    MPIDI_Comm_get_vc_set_active(sreq->comm, sreq->dev.match.parts.rank, &vc);
        -:   49:
       43:   50:    proto = MPIDI_Request_get_msg_type(sreq);
        -:   51:
       43:   52:    if (proto == MPIDI_REQUEST_SELF_MSG)
        -:   53:    {
        -:   54:	MPID_Request * rreq;
        -:   55:	
        -:   56:	MPIU_DBG_MSG(CH3_OTHER,VERBOSE,
        -:   57:		     "attempting to cancel message sent to self");
        -:   58:	
        -:   59:	MPIU_THREAD_CS_ENTER(MSGQUEUE,);
    #####:   60:	rreq = MPIDI_CH3U_Recvq_FDU(sreq->handle, &sreq->dev.match);
        -:   61:	MPIU_THREAD_CS_EXIT(MSGQUEUE,);
    #####:   62:	if (rreq)
        -:   63:	{
    #####:   64:	    MPIU_Assert(rreq->partner_request == sreq);
        -:   65:	    
        -:   66:	    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:   67:             "send-to-self cancellation successful, sreq=0x%08x, rreq=0x%08x",
        -:   68:						sreq->handle, rreq->handle));
        -:   69:	    
    #####:   70:	    MPIU_Object_set_ref(rreq, 0);
    #####:   71:	    MPIDI_CH3_Request_destroy(rreq);
        -:   72:	    
    #####:   73:	    sreq->status.cancelled = TRUE;
        -:   74:	    /* no other thread should be waiting on sreq, so it is safe to 
        -:   75:	       reset ref_count and cc */
    #####:   76:	    sreq->cc = 0;
    #####:   77:	    MPIU_Object_set_ref(sreq, 1);
        -:   78:	}
        -:   79:	else
        -:   80:	{
    #####:   81:	    sreq->status.cancelled = FALSE; 
        -:   82:	    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:   83:               "send-to-self cancellation failed, sreq=0x%08x, rreq=0x%08x",
        -:   84:						sreq->handle, rreq->handle));
        -:   85:	}
        -:   86:	
        -:   87:	goto fn_exit;
        -:   88:    }
        -:   89:
        -:   90:    /* Check to see if the send is still in the send queue.  If so, remove it, 
        -:   91:       mark the request and cancelled and complete, and
        -:   92:       release the device's reference to the request object.  
        -:   93:    */
        -:   94:    {
        -:   95:	int cancelled;
        -:   96:	
       43:   97:	if (proto == MPIDI_REQUEST_RNDV_MSG)
        -:   98:	{
        -:   99:	    MPID_Request * rts_sreq;
        -:  100:	    /* The cancellation of the RTS request needs to be atomic through 
        -:  101:	       the destruction of the RTS request to avoid
        -:  102:               conflict with release of the RTS request if the CTS is received
        -:  103:	       (see handling of a rendezvous CTS packet in
        -:  104:               MPIDI_CH3U_Handle_recv_pkt()).  
        -:  105:	       MPID_Request_fetch_and_clear_rts_sreq() is used to gurantee 
        -:  106:	       that atomicity. */
        9:  107:	    MPIDI_Request_fetch_and_clear_rts_sreq(sreq, &rts_sreq);
        9:  108:	    if (rts_sreq != NULL) 
        -:  109:	    {
    #####:  110:		cancelled = FALSE;
        -:  111:		
        -:  112:		/* since we attempted to cancel a RTS request, then we are 
        -:  113:		   responsible for releasing that request */
    #####:  114:		MPID_Request_release(rts_sreq);
        -:  115:
        -:  116:		/* --BEGIN ERROR HANDLING-- */
    #####:  117:		if (mpi_errno != MPI_SUCCESS)
        -:  118:		{
    #####:  119:		    mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
        -:  120:						     "**ch3|cancelrndv", 0);
    #####:  121:		    goto fn_exit;
        -:  122:		}
        -:  123:		/* --END ERROR HANDLING-- */
        -:  124:		
    #####:  125:		if (cancelled)
        -:  126:		{
    #####:  127:		    sreq->status.cancelled = TRUE;
        -:  128:		    /* no other thread should be waiting on sreq, so it is 
        -:  129:		       safe to reset ref_count and cc */
    #####:  130:		    sreq->cc = 0;
    #####:  131:		    MPIU_Object_set_ref(sreq, 1);
    #####:  132:		    goto fn_exit;
        -:  133:		}
        -:  134:	    }
        -:  135:	}
        -:  136:	else
        -:  137:	{
       34:  138:	    cancelled = FALSE;
       34:  139:	    if (cancelled)
        -:  140:	    {
    #####:  141:		sreq->status.cancelled = TRUE;
        -:  142:		/* no other thread should be waiting on sreq, so it is safe to 
        -:  143:		   reset ref_count and cc */
    #####:  144:		sreq->cc = 0;
    #####:  145:		MPIU_Object_set_ref(sreq, 1);
    #####:  146:		goto fn_exit;
        -:  147:	    }
        -:  148:	}
        -:  149:    }
        -:  150:
        -:  151:    /* Part or all of the message has already been sent, so we need to send a 
        -:  152:       cancellation request to the receiver in an attempt
        -:  153:       to catch the message before it is matched. */
        -:  154:    {
        -:  155:	int was_incomplete;
        -:  156:	MPIDI_CH3_Pkt_t upkt;
       43:  157:	MPIDI_CH3_Pkt_cancel_send_req_t * const csr_pkt = &upkt.cancel_send_req;
        -:  158:	MPID_Request * csr_sreq;
        -:  159:	
        -:  160:	MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:  161:              "sending cancel request to %d for 0x%08x", 
        -:  162:	      sreq->dev.match.parts.rank, sreq->handle));
        -:  163:	
        -:  164:	/* The completion counter and reference count are incremented to keep 
        -:  165:	   the request around long enough to receive a
        -:  166:	   response regardless of what the user does (free the request before 
        -:  167:	   waiting, etc.). */
       43:  168:	MPIDI_CH3U_Request_increment_cc(sreq, &was_incomplete);
       43:  169:	if (!was_incomplete)
        -:  170:	{
        -:  171:	    /* The reference count is incremented only if the request was 
        -:  172:	       complete before the increment. */
       25:  173:	    MPIR_Request_add_ref( sreq );
        -:  174:	}
        -:  175:
       43:  176:	MPIDI_Pkt_init(csr_pkt, MPIDI_CH3_PKT_CANCEL_SEND_REQ);
       43:  177:	csr_pkt->match.parts.rank = sreq->comm->rank;
       43:  178:	csr_pkt->match.parts.tag = sreq->dev.match.parts.tag;
       43:  179:	csr_pkt->match.parts.context_id = sreq->dev.match.parts.context_id;
       43:  180:	csr_pkt->sender_req_id = sreq->handle;
        -:  181:	
        -:  182:	MPIU_THREAD_CS_ENTER(CH3COMM,vc);
       43:  183:	mpi_errno = MPIU_CALL(MPIDI_CH3,iStartMsg(vc, csr_pkt, 
        -:  184:					  sizeof(*csr_pkt), &csr_sreq));
        -:  185:	MPIU_THREAD_CS_EXIT(CH3COMM,vc);
       43:  186:	if (mpi_errno != MPI_SUCCESS) {
    #####:  187:	    MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**ch3|cancelreq");
        -:  188:	}
       43:  189:	if (csr_sreq != NULL)
        -:  190:	{
        5:  191:	    MPID_Request_release(csr_sreq);
        -:  192:	}
        -:  193:    }
        -:  194:    
        -:  195:    /* FIXME: if send cancellation packets are allowed to arrive out-of-order 
        -:  196:       with respect to send packets, then we need to
        -:  197:       timestamp send and cancel packets to insure that a cancellation request 
        -:  198:       does not bypass the send packet to be cancelled
        -:  199:       and erroneously cancel a previously sent message with the same request 
        -:  200:       handle. */
        -:  201:    /* FIXME: A timestamp is more than is necessary; a message sequence number
        -:  202:       should be adequate. */
       43:  203: fn_fail:
       43:  204: fn_exit:
        -:  205:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_CANCEL_SEND);
       43:  206:    return mpi_errno;
        -:  207:}
        -:  208:
        -:  209:/*
        -:  210: * Handler routines called when cancel send packets arrive
        -:  211: */
        -:  212:
        -:  213:int MPIDI_CH3_PktHandler_CancelSendReq( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt,
        -:  214:					MPIDI_msg_sz_t *buflen, MPID_Request **rreqp )
       43:  215:{
       43:  216:    MPIDI_CH3_Pkt_cancel_send_req_t * req_pkt = &pkt->cancel_send_req;
        -:  217:    MPID_Request * rreq;
        -:  218:    int ack;
        -:  219:    MPIDI_CH3_Pkt_t upkt;
       43:  220:    MPIDI_CH3_Pkt_cancel_send_resp_t * resp_pkt = &upkt.cancel_send_resp;
        -:  221:    MPID_Request * resp_sreq;
       43:  222:    int mpi_errno = MPI_SUCCESS;
        -:  223:    
        -:  224:    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:  225:      "received cancel send req pkt, sreq=0x%08x, rank=%d, tag=%d, context=%d",
        -:  226:		      req_pkt->sender_req_id, req_pkt->match.parts.rank, 
        -:  227:		      req_pkt->match.parts.tag, req_pkt->match.parts.context_id));
        -:  228:	    
       43:  229:    *buflen = sizeof(MPIDI_CH3_Pkt_t);
        -:  230:    /* FIXME: Note that this routine is called from within the packet handler. 
        -:  231:       If the message queue mutex is different from the progress mutex, this 
        -:  232:       must be protected within a message-queue mutex */
       43:  233:    rreq = MPIDI_CH3U_Recvq_FDU(req_pkt->sender_req_id, &req_pkt->match);
       43:  234:    if (rreq != NULL)
        -:  235:    {
        -:  236:	MPIU_DBG_MSG(CH3_OTHER,TYPICAL,"message cancelled");
       35:  237:	if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_EAGER_MSG && rreq->dev.recv_data_sz > 0)
        -:  238:	{
       27:  239:	    MPIU_Free(rreq->dev.tmpbuf);
        -:  240:	}
       35:  241:	MPID_Request_release(rreq);
       35:  242:	ack = TRUE;
        -:  243:    }
        -:  244:    else
        -:  245:    {
        -:  246:	MPIU_DBG_MSG(CH3_OTHER,TYPICAL,"unable to cancel message");
        8:  247:	ack = FALSE;
        -:  248:    }
        -:  249:    
       43:  250:    MPIDI_Pkt_init(resp_pkt, MPIDI_CH3_PKT_CANCEL_SEND_RESP);
       43:  251:    resp_pkt->sender_req_id = req_pkt->sender_req_id;
       43:  252:    resp_pkt->ack = ack;
        -:  253:    /* FIXME: This is called within the packet handler */
        -:  254:    /* MPIU_THREAD_CS_ENTER(CH3COMM,vc); */
       43:  255:    mpi_errno = MPIU_CALL(MPIDI_CH3,iStartMsg(vc, resp_pkt, 
        -:  256:					      sizeof(*resp_pkt), &resp_sreq));
        -:  257:    /* MPIU_THREAD_CS_EXIT(CH3COMM,vc); */
       43:  258:    if (mpi_errno != MPI_SUCCESS) {
    #####:  259:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,
        -:  260:			    "**ch3|cancelresp");
        -:  261:    }
       43:  262:    if (resp_sreq != NULL)
        -:  263:    {
    #####:  264:	MPID_Request_release(resp_sreq);
        -:  265:    }
        -:  266:    
       43:  267:    *rreqp = NULL;
        -:  268:
       43:  269: fn_fail:
       43:  270:    return mpi_errno;
        -:  271:}
        -:  272:
        -:  273:int MPIDI_CH3_PktHandler_CancelSendResp( MPIDI_VC_t *vc ATTRIBUTE((unused)), 
        -:  274:					 MPIDI_CH3_Pkt_t *pkt,
        -:  275:					 MPIDI_msg_sz_t *buflen, MPID_Request **rreqp )
       43:  276:{
       43:  277:    MPIDI_CH3_Pkt_cancel_send_resp_t * resp_pkt = &pkt->cancel_send_resp;
        -:  278:    MPID_Request * sreq;
        -:  279:    
        -:  280:    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:  281:			"received cancel send resp pkt, sreq=0x%08x, ack=%d",
        -:  282:			resp_pkt->sender_req_id, resp_pkt->ack));
        -:  283:	    
       43:  284:    *buflen = sizeof(MPIDI_CH3_Pkt_t);
        -:  285:
       43:  286:    MPID_Request_get_ptr(resp_pkt->sender_req_id, sreq);
        -:  287:    
       43:  288:    if (resp_pkt->ack)
        -:  289:    {
       35:  290:	sreq->status.cancelled = TRUE;
        -:  291:	
       35:  292:	if (MPIDI_Request_get_msg_type(sreq) == MPIDI_REQUEST_RNDV_MSG ||
        -:  293:	    MPIDI_Request_get_type(sreq) == MPIDI_REQUEST_TYPE_SSEND)
        -:  294:	{
        -:  295:	    int cc;
        -:  296:	    
        -:  297:	    /* decrement the CC one additional time for the CTS/sync ack that 
        -:  298:	       is never going to arrive */
       14:  299:	    MPIDI_CH3U_Request_decrement_cc(sreq, &cc);
        -:  300:	}
        -:  301:		
        -:  302:	MPIU_DBG_MSG(CH3_OTHER,TYPICAL,"message cancelled");
        -:  303:    }
        -:  304:    else
        -:  305:    {
        8:  306:	sreq->status.cancelled = FALSE; 
        -:  307:	MPIU_DBG_MSG(CH3_OTHER,TYPICAL,"unable to cancel message");
        -:  308:    }
        -:  309:    
       43:  310:    MPIDI_CH3U_Request_complete(sreq);
        -:  311:    
       43:  312:    *rreqp = NULL;
        -:  313:
       43:  314:    return MPI_SUCCESS;
        -:  315:}
        -:  316:
        -:  317:/*
        -:  318: * Define the routines that can print out the cancel packets if 
        -:  319: * debugging is enabled.
        -:  320: */
        -:  321:#ifdef MPICH_DBG_OUTPUT
        -:  322:int MPIDI_CH3_PktPrint_CancelSendReq( FILE *fp, MPIDI_CH3_Pkt_t *pkt )
        -:  323:{
        -:  324:    MPIU_DBG_PRINTF((" type ......... CANCEL_SEND\n"));
        -:  325:    MPIU_DBG_PRINTF((" sender_reqid . 0x%08X\n", pkt->cancel_send_req.sender_req_id));
        -:  326:    MPIU_DBG_PRINTF((" context_id ... %d\n", pkt->cancel_send_req.match.parts.context_id));
        -:  327:    MPIU_DBG_PRINTF((" tag .......... %d\n", pkt->cancel_send_req.match.parts.tag));
        -:  328:    MPIU_DBG_PRINTF((" rank ......... %d\n", pkt->cancel_send_req.match.parts.rank));
        -:  329:
        -:  330:    return MPI_SUCCESS;
        -:  331:}
        -:  332:
        -:  333:int MPIDI_CH3_PktPrint_CancelSendResp( FILE *fp, MPIDI_CH3_Pkt_t *pkt )
        -:  334:{
        -:  335:    MPIU_DBG_PRINTF((" type ......... CANCEL_SEND_RESP\n"));
        -:  336:    MPIU_DBG_PRINTF((" sender_reqid . 0x%08X\n", pkt->cancel_send_resp.sender_req_id));
        -:  337:    MPIU_DBG_PRINTF((" ack .......... %d\n", pkt->cancel_send_resp.ack));
        -:  338:    
        -:  339:    return MPI_SUCCESS;
        -:  340:}
        -:  341:#endif