-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/ch3/src/ch3u_rma_ops.c
        -:    0:Graph:ch3u_rma_ops.gcno
        -:    0:Data:ch3u_rma_ops.gcda
        -:    0:Runs:2065
        -:    0:Programs:288
        -:    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 "mpidi_ch3_impl.h"
        -:    8:#include "mpidrma.h"
        -:    9:
        -:   10:#define MPIDI_PASSIVE_TARGET_DONE_TAG  348297
        -:   11:#define MPIDI_PASSIVE_TARGET_RMA_TAG 563924
        -:   12:
        -:   13:
        -:   14:#undef FUNCNAME
        -:   15:#define FUNCNAME MPIDI_Win_create
        -:   16:#undef FCNAME
        -:   17:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   18:int MPIDI_Win_create(void *base, MPI_Aint size, int disp_unit, MPID_Info *info,
        -:   19:		     MPID_Comm *comm_ptr, MPID_Win **win_ptr )
    16250:   20:{
    16250:   21:    int mpi_errno=MPI_SUCCESS, i, comm_size, rank;
        -:   22:    MPI_Aint *tmp_buf;
    16250:   23:    MPIU_CHKPMEM_DECL(4);
    16250:   24:    MPIU_CHKLMEM_DECL(1);
    16250:   25:    MPIU_THREADPRIV_DECL;
        -:   26:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_WIN_CREATE);
        -:   27:    
        -:   28:    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_WIN_CREATE);
        -:   29:
        -:   30:    /* FIXME: There should be no unreferenced args */
        -:   31:    MPIU_UNREFERENCED_ARG(info);
        -:   32:
    16250:   33:    MPIU_THREADPRIV_GET;
        -:   34:
    16250:   35:    MPIR_Nest_incr();
        -:   36:        
    16250:   37:    comm_size = comm_ptr->local_size;
    16250:   38:    rank = comm_ptr->rank;
        -:   39:    
    16250:   40:    *win_ptr = (MPID_Win *)MPIU_Handle_obj_alloc( &MPID_Win_mem );
    16250:   41:    MPIU_ERR_CHKANDJUMP(!(*win_ptr),mpi_errno,MPI_ERR_OTHER,"**nomem");
        -:   42:
    16250:   43:    MPIU_Object_set_ref(*win_ptr, 1);
        -:   44:
    16250:   45:    (*win_ptr)->fence_cnt = 0;
    16250:   46:    (*win_ptr)->base = base;
    16250:   47:    (*win_ptr)->size = size;
    16250:   48:    (*win_ptr)->disp_unit = disp_unit;
    16250:   49:    (*win_ptr)->start_group_ptr = NULL; 
    16250:   50:    (*win_ptr)->start_assert = 0; 
    16250:   51:    (*win_ptr)->attributes = NULL;
    16250:   52:    (*win_ptr)->rma_ops_list = NULL;
    16250:   53:    (*win_ptr)->lock_granted = 0;
    16250:   54:    (*win_ptr)->current_lock_type = MPID_LOCK_NONE;
    16250:   55:    (*win_ptr)->shared_lock_ref_cnt = 0;
    16250:   56:    (*win_ptr)->lock_queue = NULL;
    16250:   57:    (*win_ptr)->my_counter = 0;
    16250:   58:    (*win_ptr)->my_pt_rma_puts_accs = 0;
        -:   59:    
    16250:   60:    mpi_errno = NMPI_Comm_dup(comm_ptr->handle, &((*win_ptr)->comm));
    16250:   61:    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
        -:   62:    
        -:   63:    /* allocate memory for the base addresses, disp_units, and
        -:   64:       completion counters of all processes */ 
    16250:   65:    MPIU_CHKPMEM_MALLOC((*win_ptr)->base_addrs, void **,
        -:   66:			comm_size*sizeof(void *), 
        -:   67:			mpi_errno, "(*win_ptr)->base_addrs");
        -:   68:
    16250:   69:    MPIU_CHKPMEM_MALLOC((*win_ptr)->disp_units, int *, comm_size*sizeof(int), 
        -:   70:			mpi_errno, "(*win_ptr)->disp_units");
        -:   71:
    16250:   72:    MPIU_CHKPMEM_MALLOC((*win_ptr)->all_win_handles, MPI_Win *, 
        -:   73:			comm_size*sizeof(MPI_Win), 
        -:   74:			mpi_errno, "(*win_ptr)->all_win_handles");
        -:   75:    
    16250:   76:    MPIU_CHKPMEM_MALLOC((*win_ptr)->pt_rma_puts_accs, int *, 
        -:   77:			comm_size*sizeof(int), 
        -:   78:			mpi_errno, "(*win_ptr)->pt_rma_puts_accs");
    16250:   79:    for (i=0; i<comm_size; i++)	(*win_ptr)->pt_rma_puts_accs[i] = 0;
        -:   80:    
        -:   81:    /* get the addresses of the windows, window objects, and completion
        -:   82:       counters of all processes.  allocate temp. buffer for communication */
    16250:   83:    MPIU_CHKLMEM_MALLOC(tmp_buf, MPI_Aint *, 3*comm_size*sizeof(MPI_Aint),
        -:   84:			mpi_errno, "tmp_buf");
        -:   85:    
        -:   86:    /* FIXME: This needs to be fixed for heterogeneous systems */
    16250:   87:    tmp_buf[3*rank] = MPIU_PtrToAint(base);
    16250:   88:    tmp_buf[3*rank+1] = (MPI_Aint) disp_unit;
    16250:   89:    tmp_buf[3*rank+2] = (MPI_Aint) (*win_ptr)->handle;
        -:   90:    
    16250:   91:    mpi_errno = NMPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
        -:   92:			       tmp_buf, 3 * sizeof(MPI_Aint), MPI_BYTE, 
        -:   93:			       comm_ptr->handle);   
    16250:   94:    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
        -:   95:    
    69054:   96:    for (i=0; i<comm_size; i++)
        -:   97:    {
    52804:   98:	(*win_ptr)->base_addrs[i] = MPIU_AintToPtr(tmp_buf[3*i]);
    52804:   99:	(*win_ptr)->disp_units[i] = (int) tmp_buf[3*i+1];
    52804:  100:	(*win_ptr)->all_win_handles[i] = (MPI_Win) tmp_buf[3*i+2];
        -:  101:    }
        -:  102:        
    16250:  103: fn_exit:
    16250:  104:    MPIR_Nest_decr();
    16250:  105:    MPIU_CHKLMEM_FREEALL();
        -:  106:    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_WIN_CREATE);
    16250:  107:    return mpi_errno;
        -:  108:    /* --BEGIN ERROR HANDLING-- */
        -:  109: fn_fail:
    #####:  110:    MPIU_CHKPMEM_REAP();
        -:  111:    goto fn_exit;
        -:  112:    /* --END ERROR HANDLING-- */
        -:  113:}
        -:  114:
        -:  115:
        -:  116:
        -:  117:
        -:  118:#undef FUNCNAME
        -:  119:#define FUNCNAME MPIDI_Win_free
        -:  120:#undef FCNAME
        -:  121:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  122:int MPIDI_Win_free(MPID_Win **win_ptr)
    16250:  123:{
    16250:  124:    int mpi_errno=MPI_SUCCESS, total_pt_rma_puts_accs, i, *recvcnts, comm_size;
        -:  125:    MPID_Comm *comm_ptr;
        -:  126:    int in_use;
    16250:  127:    MPIU_CHKLMEM_DECL(1);
    16250:  128:    MPIU_THREADPRIV_DECL;
        -:  129:    
        -:  130:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_WIN_FREE);
        -:  131:        
        -:  132:    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_WIN_FREE);
        -:  133:        
    16250:  134:    MPIU_THREADPRIV_GET;
    16250:  135:    MPIR_Nest_incr();
        -:  136:
        -:  137:    /* set up the recvcnts array for the reduce scatter to check if all
        -:  138:       passive target rma operations are done */
    16250:  139:    MPID_Comm_get_ptr( (*win_ptr)->comm, comm_ptr );
    16250:  140:    comm_size = comm_ptr->local_size;
        -:  141:        
    16250:  142:    MPIU_CHKLMEM_MALLOC(recvcnts, int *, comm_size*sizeof(int), mpi_errno, 
        -:  143:			"recvcnts");
    16250:  144:    for (i=0; i<comm_size; i++)  recvcnts[i] = 1;
        -:  145:        
    16250:  146:    mpi_errno = NMPI_Reduce_scatter((*win_ptr)->pt_rma_puts_accs, 
        -:  147:				    &total_pt_rma_puts_accs, recvcnts, 
        -:  148:				    MPI_INT, MPI_SUM, (*win_ptr)->comm);
    16250:  149:    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
        -:  150:
    16250:  151:    if (total_pt_rma_puts_accs != (*win_ptr)->my_pt_rma_puts_accs)
        -:  152:    {
        -:  153:	MPID_Progress_state progress_state;
        -:  154:            
        -:  155:	/* poke the progress engine until the two are equal */
    #####:  156:	MPID_Progress_start(&progress_state);
    #####:  157:	while (total_pt_rma_puts_accs != (*win_ptr)->my_pt_rma_puts_accs)
        -:  158:	{
    #####:  159:	    mpi_errno = MPID_Progress_wait(&progress_state);
        -:  160:	    /* --BEGIN ERROR HANDLING-- */
    #####:  161:	    if (mpi_errno != MPI_SUCCESS)
        -:  162:	    {
        -:  163:		MPID_Progress_end(&progress_state);
    #####:  164:		MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**winnoprogress");
        -:  165:	    }
        -:  166:	    /* --END ERROR HANDLING-- */
        -:  167:	}
        -:  168:	MPID_Progress_end(&progress_state);
        -:  169:    }
        -:  170:
    16250:  171:    NMPI_Comm_free(&((*win_ptr)->comm));
        -:  172:
    16250:  173:    MPIU_Free((*win_ptr)->base_addrs);
    16250:  174:    MPIU_Free((*win_ptr)->disp_units);
    16250:  175:    MPIU_Free((*win_ptr)->all_win_handles);
    16250:  176:    MPIU_Free((*win_ptr)->pt_rma_puts_accs);
        -:  177:
    16250:  178:    MPIU_Object_release_ref(*win_ptr, &in_use);
        -:  179:    /* MPI windows don't have reference count semantics, so this should always be true */
    16250:  180:    MPIU_Assert(!in_use);
    16250:  181:    MPIU_Handle_obj_free( &MPID_Win_mem, *win_ptr );
        -:  182:
    16250:  183: fn_exit:
    16250:  184:    MPIR_Nest_decr();
    16250:  185:    MPIU_CHKLMEM_FREEALL();
        -:  186:    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_WIN_FREE);
    16250:  187:    return mpi_errno;
        -:  188:
        -:  189: fn_fail:
        -:  190:    goto fn_exit;
        -:  191:}
        -:  192:
        -:  193:
        -:  194:
        -:  195:#undef FUNCNAME
        -:  196:#define FUNCNAME MPIDI_Put
        -:  197:#undef FCNAME
        -:  198:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  199:int MPIDI_Put(void *origin_addr, int origin_count, MPI_Datatype
        -:  200:            origin_datatype, int target_rank, MPI_Aint target_disp,
        -:  201:            int target_count, MPI_Datatype target_datatype, MPID_Win *win_ptr)
     6089:  202:{
     6089:  203:    int mpi_errno = MPI_SUCCESS;
        -:  204:    int dt_contig, rank, predefined;
        -:  205:    MPIDI_RMA_ops *curr_ptr, *prev_ptr, *new_ptr;
        -:  206:    MPID_Datatype *dtp;
        -:  207:    MPI_Aint dt_true_lb;
        -:  208:    MPIDI_msg_sz_t data_sz;
     6089:  209:    MPIU_CHKPMEM_DECL(1);
     6089:  210:    MPIU_THREADPRIV_DECL;
        -:  211:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_PUT);
        -:  212:        
        -:  213:    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_PUT);
        -:  214:
     6089:  215:    MPIU_THREADPRIV_GET;
     6089:  216:    MPIDI_Datatype_get_info(origin_count, origin_datatype,
        -:  217:			    dt_contig, data_sz, dtp,dt_true_lb); 
        -:  218:    
     6089:  219:    if ((data_sz == 0) || (target_rank == MPI_PROC_NULL))
        -:  220:    {
    #####:  221:	goto fn_exit;
        -:  222:    }
        -:  223:
        -:  224:    /* FIXME: It makes sense to save the rank (and size) of the
        -:  225:       communicator in the window structure to speed up these operations,
        -:  226:       or to save a pointer to the communicator structure, rather than
        -:  227:       just the handle 
        -:  228:    */
     6089:  229:    MPIR_Nest_incr();
     6089:  230:    NMPI_Comm_rank(win_ptr->comm, &rank);
     6089:  231:    MPIR_Nest_decr();
        -:  232:    
        -:  233:    /* If the put is a local operation, do it here */
     6089:  234:    if (target_rank == rank)
        -:  235:    {
        1:  236:	mpi_errno = MPIR_Localcopy(origin_addr, origin_count, origin_datatype,
        -:  237:				   (char *) win_ptr->base + win_ptr->disp_unit *
        -:  238:				   target_disp, target_count, target_datatype); 
        -:  239:    }
        -:  240:    else
        -:  241:    {
        -:  242:	/* queue it up */
     6088:  243:	curr_ptr = win_ptr->rma_ops_list;
     6088:  244:	prev_ptr = curr_ptr;
    33370:  245:	while (curr_ptr != NULL)
        -:  246:	{
    21194:  247:	    prev_ptr = curr_ptr;
    21194:  248:	    curr_ptr = curr_ptr->next;
        -:  249:	}
        -:  250:
        -:  251:	/* FIXME: Where does this memory get freed? */
     6088:  252:	MPIU_CHKPMEM_MALLOC(new_ptr, MPIDI_RMA_ops *, sizeof(MPIDI_RMA_ops), 
        -:  253:			    mpi_errno, "RMA operation entry");
     6088:  254:	if (prev_ptr != NULL)
      806:  255:	    prev_ptr->next = new_ptr;
        -:  256:	else 
     5282:  257:	    win_ptr->rma_ops_list = new_ptr;
        -:  258:	
     6088:  259:	new_ptr->next = NULL;  
     6088:  260:	new_ptr->type = MPIDI_RMA_PUT;
     6088:  261:	new_ptr->origin_addr = origin_addr;
     6088:  262:	new_ptr->origin_count = origin_count;
     6088:  263:	new_ptr->origin_datatype = origin_datatype;
     6088:  264:	new_ptr->target_rank = target_rank;
     6088:  265:	new_ptr->target_disp = target_disp;
     6088:  266:	new_ptr->target_count = target_count;
     6088:  267:	new_ptr->target_datatype = target_datatype;
        -:  268:	
        -:  269:	/* if source or target datatypes are derived, increment their
        -:  270:	   reference counts */ 
     6088:  271:	MPIDI_CH3I_DATATYPE_IS_PREDEFINED(origin_datatype, predefined);
     6088:  272:	if (!predefined)
        -:  273:	{
     2305:  274:	    MPID_Datatype_get_ptr(origin_datatype, dtp);
     2305:  275:	    MPID_Datatype_add_ref(dtp);
        -:  276:	}
     6088:  277:	MPIDI_CH3I_DATATYPE_IS_PREDEFINED(target_datatype, predefined);
     6088:  278:	if (!predefined)
        -:  279:	{
     1205:  280:	    MPID_Datatype_get_ptr(target_datatype, dtp);
     1205:  281:	    MPID_Datatype_add_ref(dtp);
        -:  282:	}
        -:  283:    }
        -:  284:
     6089:  285:  fn_exit:
        -:  286:    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_PUT);    
     6089:  287:    return mpi_errno;
        -:  288:
        -:  289:    /* --BEGIN ERROR HANDLING-- */
        -:  290:  fn_fail:
    #####:  291:    MPIU_CHKPMEM_REAP();
        -:  292:    goto fn_exit;
        -:  293:    /* --END ERROR HANDLING-- */
        -:  294:}
        -:  295:
        -:  296:
        -:  297:
        -:  298:#undef FUNCNAME
        -:  299:#define FUNCNAME MPIDI_Get
        -:  300:#undef FCNAME
        -:  301:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  302:int MPIDI_Get(void *origin_addr, int origin_count, MPI_Datatype
        -:  303:            origin_datatype, int target_rank, MPI_Aint target_disp,
        -:  304:            int target_count, MPI_Datatype target_datatype, MPID_Win *win_ptr)
    10132:  305:{
    10132:  306:    int mpi_errno = MPI_SUCCESS;
        -:  307:    MPIDI_msg_sz_t data_sz;
        -:  308:    int dt_contig, rank, predefined;
        -:  309:    MPI_Aint dt_true_lb;
        -:  310:    MPIDI_RMA_ops *curr_ptr, *prev_ptr, *new_ptr;
        -:  311:    MPID_Datatype *dtp;
    10132:  312:    MPIU_CHKPMEM_DECL(1);
    10132:  313:    MPIU_THREADPRIV_DECL;
        -:  314:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_GET);
        -:  315:        
        -:  316:    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_GET);
        -:  317:
    10132:  318:    MPIU_THREADPRIV_GET;
    10132:  319:    MPIDI_Datatype_get_info(origin_count, origin_datatype,
        -:  320:			    dt_contig, data_sz, dtp, dt_true_lb); 
        -:  321:
    10132:  322:    if ((data_sz == 0) || (target_rank == MPI_PROC_NULL))
        -:  323:    {
    #####:  324:	goto fn_exit;
        -:  325:    }
        -:  326:
        -:  327:    /* FIXME: It makes sense to save the rank (and size) of the
        -:  328:       communicator in the window structure to speed up these operations */
    10132:  329:    MPIR_Nest_incr();
    10132:  330:    NMPI_Comm_rank(win_ptr->comm, &rank);
    10132:  331:    MPIR_Nest_decr();
        -:  332:    
        -:  333:    /* If the get is a local operation, do it here */
    10132:  334:    if (target_rank == rank)
        -:  335:    {
        2:  336:	mpi_errno = MPIR_Localcopy((char *) win_ptr->base +
        -:  337:				   win_ptr->disp_unit * target_disp,
        -:  338:				   target_count, target_datatype,
        -:  339:				   origin_addr, origin_count,
        -:  340:				   origin_datatype);  
        -:  341:    }
        -:  342:    else
        -:  343:    {
        -:  344:	/* queue it up */
    10130:  345:	curr_ptr = win_ptr->rma_ops_list;
    10130:  346:	prev_ptr = curr_ptr;
  8058462:  347:	while (curr_ptr != NULL)
        -:  348:	{
  8038202:  349:	    prev_ptr = curr_ptr;
  8038202:  350:	    curr_ptr = curr_ptr->next;
        -:  351:	}
        -:  352:	
    10130:  353:	MPIU_CHKPMEM_MALLOC(new_ptr, MPIDI_RMA_ops *, sizeof(MPIDI_RMA_ops), 
        -:  354:			    mpi_errno, "RMA operation entry");
    10130:  355:	if (prev_ptr != NULL)
        -:  356:	{
     9243:  357:	    prev_ptr->next = new_ptr;
        -:  358:	}
        -:  359:	else
        -:  360:	{
      887:  361:	    win_ptr->rma_ops_list = new_ptr;
        -:  362:	}
        -:  363:            
    10130:  364:	new_ptr->next = NULL;  
    10130:  365:	new_ptr->type = MPIDI_RMA_GET;
    10130:  366:	new_ptr->origin_addr = origin_addr;
    10130:  367:	new_ptr->origin_count = origin_count;
    10130:  368:	new_ptr->origin_datatype = origin_datatype;
    10130:  369:	new_ptr->target_rank = target_rank;
    10130:  370:	new_ptr->target_disp = target_disp;
    10130:  371:	new_ptr->target_count = target_count;
    10130:  372:	new_ptr->target_datatype = target_datatype;
        -:  373:	
        -:  374:	/* if source or target datatypes are derived, increment their
        -:  375:	   reference counts */ 
    10130:  376:	MPIDI_CH3I_DATATYPE_IS_PREDEFINED(origin_datatype, predefined);
    10130:  377:	if (!predefined)
        -:  378:	{
      432:  379:	    MPID_Datatype_get_ptr(origin_datatype, dtp);
      432:  380:	    MPID_Datatype_add_ref(dtp);
        -:  381:	}
    10130:  382:	MPIDI_CH3I_DATATYPE_IS_PREDEFINED(target_datatype, predefined);
    10130:  383:	if (!predefined)
        -:  384:	{
      914:  385:	    MPID_Datatype_get_ptr(target_datatype, dtp);
      914:  386:	    MPID_Datatype_add_ref(dtp);
        -:  387:	}
        -:  388:    }
        -:  389:
    10132:  390:  fn_exit:
        -:  391:    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_GET);
    10132:  392:    return mpi_errno;
        -:  393:
        -:  394:    /* --BEGIN ERROR HANDLING-- */
        -:  395:  fn_fail:
    #####:  396:    MPIU_CHKPMEM_REAP();
        -:  397:    goto fn_exit;
        -:  398:    /* --END ERROR HANDLING-- */
        -:  399:}
        -:  400:
        -:  401:
        -:  402:
        -:  403:#undef FUNCNAME
        -:  404:#define FUNCNAME MPIDI_Accumulate
        -:  405:#undef FCNAME
        -:  406:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  407:int MPIDI_Accumulate(void *origin_addr, int origin_count, MPI_Datatype
        -:  408:                    origin_datatype, int target_rank, MPI_Aint target_disp,
        -:  409:                    int target_count, MPI_Datatype target_datatype, MPI_Op op,
        -:  410:                    MPID_Win *win_ptr)
     1665:  411:{
     1665:  412:    int nest_level_inc = FALSE;
     1665:  413:    int mpi_errno=MPI_SUCCESS;
        -:  414:    MPIDI_msg_sz_t data_sz;
        -:  415:    int dt_contig, rank, origin_predefined, target_predefined;
        -:  416:    MPI_Aint dt_true_lb;
        -:  417:    MPIDI_RMA_ops *curr_ptr, *prev_ptr, *new_ptr;
        -:  418:    MPID_Datatype *dtp;
     1665:  419:    MPIU_CHKLMEM_DECL(2);
     1665:  420:    MPIU_CHKPMEM_DECL(1);
     1665:  421:    MPIU_THREADPRIV_DECL;
        -:  422:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_ACCUMULATE);
        -:  423:    
        -:  424:    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_ACCUMULATE);
        -:  425:
     1665:  426:    MPIU_THREADPRIV_GET;
     1665:  427:    MPIDI_Datatype_get_info(origin_count, origin_datatype,
        -:  428:			    dt_contig, data_sz, dtp, dt_true_lb);  
        -:  429:    
     1665:  430:    if ((data_sz == 0) || (target_rank == MPI_PROC_NULL))
        -:  431:    {
    #####:  432:	goto fn_exit;
        -:  433:    }
        -:  434:    
     1665:  435:    MPIR_Nest_incr();
     1665:  436:    nest_level_inc = TRUE;
        -:  437:    
        -:  438:    /* FIXME: It makes sense to save the rank (and size) of the
        -:  439:       communicator in the window structure to speed up these operations,
        -:  440:       or to save a pointer to the communicator structure, rather than
        -:  441:       just the handle 
        -:  442:    */
     1665:  443:    NMPI_Comm_rank(win_ptr->comm, &rank);
        -:  444:    
     1665:  445:    MPIDI_CH3I_DATATYPE_IS_PREDEFINED(origin_datatype, origin_predefined);
     1665:  446:    MPIDI_CH3I_DATATYPE_IS_PREDEFINED(target_datatype, target_predefined);
        -:  447:
     1665:  448:    if (target_rank == rank)
        -:  449:    {
        -:  450:	MPI_User_function *uop;
        -:  451:	
       92:  452:	if (op == MPI_REPLACE)
        -:  453:	{
    #####:  454:	    mpi_errno = MPIR_Localcopy(origin_addr, origin_count, 
        -:  455:				origin_datatype,
        -:  456:				(char *) win_ptr->base + win_ptr->disp_unit *
        -:  457:				target_disp, target_count, target_datatype); 
    #####:  458:	    goto fn_exit;
        -:  459:	}
        -:  460:	
       92:  461:	MPIU_ERR_CHKANDJUMP1((HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN), 
        -:  462:			     mpi_errno, MPI_ERR_OP, "**opnotpredefined",
        -:  463:			     "**opnotpredefined %d", op );
        -:  464:	
        -:  465:	/* get the function by indexing into the op table */
       92:  466:	uop = MPIR_Op_table[(op)%16 - 1];
        -:  467:	
       92:  468:	if (origin_predefined && target_predefined)
        -:  469:	{    
       90:  470:	    (*uop)(origin_addr, (char *) win_ptr->base + win_ptr->disp_unit *
        -:  471:		   target_disp, &target_count, &target_datatype);
        -:  472:	}
        -:  473:	else
        -:  474:	{
        -:  475:	    /* derived datatype */
        -:  476:	    
        -:  477:	    MPID_Segment *segp;
        -:  478:	    DLOOP_VECTOR *dloop_vec;
        -:  479:	    MPI_Aint first, last;
        -:  480:	    int vec_len, i, type_size, count;
        -:  481:	    MPI_Datatype type;
        -:  482:	    MPI_Aint true_lb, true_extent, extent;
        2:  483:	    void *tmp_buf=NULL, *source_buf, *target_buf;
        -:  484:	    
        2:  485:	    if (origin_datatype != target_datatype)
        -:  486:	    {
        -:  487:		/* first copy the data into a temporary buffer with
        -:  488:		   the same datatype as the target. Then do the
        -:  489:		   accumulate operation. */
        -:  490:		
        1:  491:		mpi_errno = NMPI_Type_get_true_extent(target_datatype, 
        -:  492:						      &true_lb, &true_extent);
        1:  493:		if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
        -:  494:		
        1:  495:		MPID_Datatype_get_extent_macro(target_datatype, extent); 
        -:  496:		
        1:  497:		MPIU_CHKLMEM_MALLOC(tmp_buf, void *, 
        -:  498:			target_count * (MPIR_MAX(extent,true_extent)), 
        -:  499:			mpi_errno, "temporary buffer");
        -:  500:		/* adjust for potential negative lower bound in datatype */
        1:  501:		tmp_buf = (void *)((char*)tmp_buf - true_lb);
        -:  502:		
        1:  503:		mpi_errno = MPIR_Localcopy(origin_addr, origin_count,
        -:  504:					   origin_datatype, tmp_buf,
        -:  505:					   target_count, target_datatype);  
        1:  506:		if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
        -:  507:	    }
        -:  508:
        2:  509:	    if (target_predefined) { 
        -:  510:		/* target predefined type, origin derived datatype */
        -:  511:
    #####:  512:		(*uop)(tmp_buf, (char *) win_ptr->base + win_ptr->disp_unit *
        -:  513:		   target_disp, &target_count, &target_datatype);
        -:  514:	    }
        -:  515:	    else {
        -:  516:	    
        2:  517:		segp = MPID_Segment_alloc();
        2:  518:		MPIU_ERR_CHKANDJUMP((!segp), mpi_errno, MPI_ERR_OTHER, "**nomem"); 
        2:  519:		MPID_Segment_init(NULL, target_count, target_datatype, segp, 0);
        2:  520:		first = 0;
        2:  521:		last  = SEGMENT_IGNORE_LAST;
        -:  522:		
        2:  523:		MPID_Datatype_get_ptr(target_datatype, dtp);
        2:  524:		vec_len = dtp->max_contig_blocks * target_count + 1; 
        -:  525:		/* +1 needed because Rob says so */
        2:  526:		MPIU_CHKLMEM_MALLOC(dloop_vec, DLOOP_VECTOR *, 
        -:  527:				    vec_len * sizeof(DLOOP_VECTOR), 
        -:  528:				    mpi_errno, "dloop vector");
        -:  529:		
        2:  530:		MPID_Segment_pack_vector(segp, first, &last, dloop_vec, &vec_len);
        -:  531:		
        2:  532:		source_buf = (tmp_buf != NULL) ? tmp_buf : origin_addr;
        2:  533:		target_buf = (char *) win_ptr->base + 
        -:  534:		    win_ptr->disp_unit * target_disp;
        2:  535:		type = dtp->eltype;
        2:  536:		type_size = MPID_Datatype_get_basic_size(type);
    10252:  537:		for (i=0; i<vec_len; i++)
        -:  538:		{
    10250:  539:		    count = (dloop_vec[i].DLOOP_VECTOR_LEN)/type_size;
    10250:  540:		    (*uop)((char *)source_buf + MPIU_PtrToAint(dloop_vec[i].DLOOP_VECTOR_BUF),
        -:  541:			   (char *)target_buf + MPIU_PtrToAint(dloop_vec[i].DLOOP_VECTOR_BUF),
        -:  542:			   &count, &type);
        -:  543:		}
        -:  544:		
        2:  545:		MPID_Segment_free(segp);
        -:  546:	    }
        -:  547:	}
        -:  548:    }
        -:  549:    else
        -:  550:    {
        -:  551:	/* queue it up */
     1573:  552:	curr_ptr = win_ptr->rma_ops_list;
     1573:  553:	prev_ptr = curr_ptr;
     3889:  554:	while (curr_ptr != NULL)
        -:  555:	{
      743:  556:	    prev_ptr = curr_ptr;
      743:  557:	    curr_ptr = curr_ptr->next;
        -:  558:	}
        -:  559:	
     1573:  560:	MPIU_CHKPMEM_MALLOC(new_ptr, MPIDI_RMA_ops *, sizeof(MPIDI_RMA_ops), 
        -:  561:			    mpi_errno, "RMA operation entry");
     1573:  562:	if (prev_ptr != NULL)
        -:  563:	{
      497:  564:	    prev_ptr->next = new_ptr;
        -:  565:	}
        -:  566:	else
        -:  567:	{
     1076:  568:	    win_ptr->rma_ops_list = new_ptr;
        -:  569:	}
        -:  570:        
     1573:  571:	new_ptr->next = NULL;  
     1573:  572:	new_ptr->type = MPIDI_RMA_ACCUMULATE;
     1573:  573:	new_ptr->origin_addr = origin_addr;
     1573:  574:	new_ptr->origin_count = origin_count;
     1573:  575:	new_ptr->origin_datatype = origin_datatype;
     1573:  576:	new_ptr->target_rank = target_rank;
     1573:  577:	new_ptr->target_disp = target_disp;
     1573:  578:	new_ptr->target_count = target_count;
     1573:  579:	new_ptr->target_datatype = target_datatype;
     1573:  580:	new_ptr->op = op;
        -:  581:	
        -:  582:	/* if source or target datatypes are derived, increment their
        -:  583:	   reference counts */ 
     1573:  584:	if (!origin_predefined)
        -:  585:	{
      384:  586:	    MPID_Datatype_get_ptr(origin_datatype, dtp);
      384:  587:	    MPID_Datatype_add_ref(dtp);
        -:  588:	}
     1573:  589:	if (!target_predefined)
        -:  590:	{
      434:  591:	    MPID_Datatype_get_ptr(target_datatype, dtp);
      434:  592:	    MPID_Datatype_add_ref(dtp);
        -:  593:	}
        -:  594:    }
        -:  595:
        -:  596: fn_exit:
        3:  597:    MPIU_CHKLMEM_FREEALL();
     1665:  598:    if (nest_level_inc)
        -:  599:    { 
     1665:  600:	MPIR_Nest_decr();
        -:  601:    }
        -:  602:    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_ACCUMULATE);
     1665:  603:    return mpi_errno;
        -:  604:
        -:  605:    /* --BEGIN ERROR HANDLING-- */
        -:  606:  fn_fail:
    #####:  607:    MPIU_CHKPMEM_REAP();
        -:  608:    goto fn_exit;
        -:  609:    /* --END ERROR HANDLING-- */
        -:  610:}
        -:  611:
        -:  612:
        -:  613:#undef FUNCNAME
        -:  614:#define FUNCNAME MPIDI_Alloc_mem
        -:  615:#undef FCNAME
        -:  616:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  617:void *MPIDI_Alloc_mem( size_t size, MPID_Info *info_ptr )
       73:  618:{
        -:  619:    void *ap;
        -:  620:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_ALLOC_MEM);
        -:  621:
        -:  622:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_ALLOC_MEM);
        -:  623:
       73:  624:    ap = MPIU_Malloc(size);
        -:  625:    
        -:  626:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_ALLOC_MEM);
       73:  627:    return ap;
        -:  628:}
        -:  629:
        -:  630:
        -:  631:#undef FUNCNAME
        -:  632:#define FUNCNAME MPIDI_Free_mem
        -:  633:#undef FCNAME
        -:  634:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  635:int MPIDI_Free_mem( void *ptr )
       73:  636:{
       73:  637:    int mpi_errno = MPI_SUCCESS;
        -:  638:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_FREE_MEM);
        -:  639:
        -:  640:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_FREE_MEM);
        -:  641:
       73:  642:    MPIU_Free(ptr);
        -:  643:    
        -:  644:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_FREE_MEM);
       73:  645:    return mpi_errno;
        -:  646:}