-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/comm/commutil.c
        -:    0:Graph:commutil.gcno
        -:    0:Data:commutil.gcda
        -:    0:Runs:4383
        -:    0:Programs:1376
        -:    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 "mpiimpl.h"
        -:    8:#include "mpicomm.h"
        -:    9:
        -:   10:/* This is the utility file for comm that contains the basic comm items
        -:   11:   and storage management */
        -:   12:#ifndef MPID_COMM_PREALLOC
        -:   13:#define MPID_COMM_PREALLOC 8
        -:   14:#endif
        -:   15:
        -:   16:/* Preallocated comm objects */
        -:   17:MPID_Comm MPID_Comm_builtin[MPID_COMM_N_BUILTIN] = { { MPIU_OBJECT_HEADER_INITIALIZER(0,0) } };
        -:   18:MPID_Comm MPID_Comm_direct[MPID_COMM_PREALLOC]   = { { MPIU_OBJECT_HEADER_INITIALIZER(0,0) } };
        -:   19:MPIU_Object_alloc_t MPID_Comm_mem = { 0, 0, 0, 0, MPID_COMM, 
        -:   20:				      sizeof(MPID_Comm), MPID_Comm_direct,
        -:   21:                                      MPID_COMM_PREALLOC};
        -:   22:
        -:   23:/* utility function to pretty print a context ID for debugging purposes, see
        -:   24: * mpiimpl.h for more info on the various fields */
        -:   25:static void MPIR_Comm_dump_context_id(MPIR_Context_id_t context_id, char *out_str, int len)
        -:   26:{
        -:   27:    int subcomm_type = MPID_CONTEXT_READ_FIELD(SUBCOMM,context_id);
        -:   28:    const char *subcomm_type_name = NULL;
        -:   29:
        -:   30:    switch (subcomm_type) {
        -:   31:        case 0: subcomm_type_name = "parent"; break;
        -:   32:        case 1: subcomm_type_name = "intranode"; break;
        -:   33:        case 2: subcomm_type_name = "internode"; break;
        -:   34:        default: MPIU_Assert(FALSE); break;
        -:   35:    }
        -:   36:    MPIU_Snprintf(out_str, len,
        -:   37:                  "context_id=%d (%#x): DYNAMIC_PROC=%d PREFIX=%#x IS_LOCALCOMM=%d SUBCOMM=%s SUFFIX=%s",
        -:   38:                  context_id,
        -:   39:                  context_id,
        -:   40:                  MPID_CONTEXT_READ_FIELD(DYNAMIC_PROC,context_id),
        -:   41:                  MPID_CONTEXT_READ_FIELD(PREFIX,context_id),
        -:   42:                  MPID_CONTEXT_READ_FIELD(IS_LOCALCOMM,context_id),
        -:   43:                  subcomm_type_name,
        -:   44:                  (MPID_CONTEXT_READ_FIELD(SUFFIX,context_id) ? "coll" : "pt2pt"));
        -:   45:}
        -:   46:
        -:   47:/* FIXME :
        -:   48:   Reusing context ids can lead to a race condition if (as is desirable)
        -:   49:   MPI_Comm_free does not include a barrier.  Consider the following:
        -:   50:   Process A frees the communicator.
        -:   51:   Process A creates a new communicator, reusing the just released id
        -:   52:   Process B sends a message to A on the old communicator.
        -:   53:   Process A receives the message, and believes that it belongs to the
        -:   54:   new communicator.
        -:   55:   Process B then cancels the message, and frees the communicator.
        -:   56:
        -:   57:   The likelyhood of this happening can be reduced by introducing a gap
        -:   58:   between when a context id is released and when it is reused.  An alternative
        -:   59:   is to use an explicit message (in the implementation of MPI_Comm_free)
        -:   60:   to indicate that a communicator is being freed; this will often require
        -:   61:   less communication than a barrier in MPI_Comm_free, and will ensure that 
        -:   62:   no messages are later sent to the same communicator (we may also want to
        -:   63:   have a similar check when building fault-tolerant versions of MPI).
        -:   64: */
        -:   65:
        -:   66:/* Create a new communicator with a context.  
        -:   67:   Do *not* initialize the other fields except for the reference count.
        -:   68:   See MPIR_Comm_copy for a function to produce a copy of part of a
        -:   69:   communicator 
        -:   70:*/
        -:   71:
        -:   72:
        -:   73:/*  
        -:   74:    Create a communicator structure and perform basic initialization 
        -:   75:    (mostly clearing fields and updating the reference count).  
        -:   76: */
        -:   77:#undef FUNCNAME
        -:   78:#define FUNCNAME MPIR_Comm_create
        -:   79:#undef FCNAME
        -:   80:#define FCNAME "MPIR_Comm_create"
        -:   81:int MPIR_Comm_create( MPID_Comm **newcomm_ptr )
  1652591:   82:{   
  1652591:   83:    int mpi_errno = MPI_SUCCESS;
        -:   84:    MPID_Comm *newptr;
        -:   85:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE);
        -:   86:
        -:   87:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_CREATE);
        -:   88:
  1652591:   89:    newptr = (MPID_Comm *)MPIU_Handle_obj_alloc( &MPID_Comm_mem );
        -:   90:    /* --BEGIN ERROR HANDLING-- */
  1652591:   91:    if (!newptr) {
    #####:   92:	mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
        -:   93:		   FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0 );
    #####:   94:	goto fn_fail;
        -:   95:    }
        -:   96:    /* --END ERROR HANDLING-- */
  1652591:   97:    *newcomm_ptr = newptr;
  1652591:   98:    MPIU_Object_set_ref( newptr, 1 );
        -:   99:
        -:  100:    /* Clear many items (empty means to use the default; some of these
        -:  101:       may be overridden within the communicator initialization) */
  1652591:  102:    newptr->errhandler   = 0;
  1652591:  103:    newptr->attributes	 = 0;
  1652591:  104:    newptr->remote_group = 0;
  1652591:  105:    newptr->local_group	 = 0;
  1652591:  106:    newptr->coll_fns	 = 0;
  1652591:  107:    newptr->topo_fns	 = 0;
  1652591:  108:    newptr->name[0]	 = 0;
        -:  109:
  1652591:  110:    newptr->is_node_aware   = 0;
  1652591:  111:    newptr->node_comm       = NULL;
  1652591:  112:    newptr->node_roots_comm = NULL;
  1652591:  113:    newptr->intranode_table = NULL;
  1652591:  114:    newptr->internode_table = NULL;
        -:  115:
        -:  116:    /* Fields not set include context_id, remote and local size, and 
        -:  117:       kind, since different communicator construction routines need 
        -:  118:       different values */
        -:  119:
        -:  120:    /* Insert this new communicator into the list of known communicators.
        -:  121:       Make this conditional on debugger support to match the test in 
        -:  122:       MPIR_Comm_release . */
        -:  123:    MPIR_COMML_REMEMBER( newptr );
        -:  124:
  1652591:  125: fn_fail:
        -:  126:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_CREATE);
        -:  127:
  1652591:  128:    return mpi_errno;
        -:  129:}
        -:  130:
        -:  131:/* Create a local intra communicator from the local group of the
        -:  132:   specified intercomm. */
        -:  133:/* FIXME this is an alternative constructor that doesn't use MPIR_Comm_create! */
        -:  134:#undef FUNCNAME
        -:  135:#define FUNCNAME MPIR_Setup_intercomm_localcomm
        -:  136:#undef FCNAME
        -:  137:#define FCNAME "MPIR_Setup_intercomm_localcomm"
        -:  138:int MPIR_Setup_intercomm_localcomm( MPID_Comm *intercomm_ptr )
     2335:  139:{
        -:  140:    MPID_Comm *localcomm_ptr;
     2335:  141:    int mpi_errno = MPI_SUCCESS;
        -:  142:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
        -:  143:
        -:  144:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
        -:  145:
     2335:  146:    localcomm_ptr = (MPID_Comm *)MPIU_Handle_obj_alloc( &MPID_Comm_mem );
     2335:  147:    MPIU_ERR_CHKANDJUMP(!localcomm_ptr,mpi_errno,MPI_ERR_OTHER,"**nomem");
        -:  148:
     2335:  149:    MPIU_Object_set_ref( localcomm_ptr, 1 );
        -:  150:    /* use the parent intercomm's recv ctx as the basis for our ctx */
     2335:  151:    localcomm_ptr->recvcontext_id = MPID_CONTEXT_SET_FIELD(IS_LOCALCOMM, intercomm_ptr->recvcontext_id, 1);
     2335:  152:    localcomm_ptr->context_id = localcomm_ptr->recvcontext_id;
        -:  153:
        -:  154:    /* Duplicate the VCRT references */
     2335:  155:    MPID_VCRT_Add_ref( intercomm_ptr->local_vcrt );
     2335:  156:    localcomm_ptr->vcrt = intercomm_ptr->local_vcrt;
     2335:  157:    localcomm_ptr->vcr  = intercomm_ptr->local_vcr;
        -:  158:
        -:  159:    /* Save the kind of the communicator */
     2335:  160:    localcomm_ptr->comm_kind   = MPID_INTRACOMM;
        -:  161:
        -:  162:    /* Set the sizes and ranks */
     2335:  163:    localcomm_ptr->remote_size = intercomm_ptr->local_size;
     2335:  164:    localcomm_ptr->local_size  = intercomm_ptr->local_size;
     2335:  165:    localcomm_ptr->rank        = intercomm_ptr->rank;
        -:  166:
        -:  167:    /* More advanced version: if the group is available, dup it by 
        -:  168:       increasing the reference count */
     2335:  169:    localcomm_ptr->local_group  = 0;
     2335:  170:    localcomm_ptr->remote_group = 0;
        -:  171:
        -:  172:    /* This is an internal communicator, so ignore */
     2335:  173:    localcomm_ptr->errhandler = 0;
        -:  174:    
        -:  175:    /* FIXME  : No local functions for the collectives */
     2335:  176:    localcomm_ptr->coll_fns = 0;
        -:  177:
        -:  178:    /* FIXME  : No local functions for the topology routines */
     2335:  179:    localcomm_ptr->topo_fns = 0;
        -:  180:
        -:  181:    /* We do *not* inherit any name */
     2335:  182:    localcomm_ptr->name[0] = 0;
        -:  183:
     2335:  184:    localcomm_ptr->attributes = 0;
        -:  185:
     2335:  186:    intercomm_ptr->local_comm = localcomm_ptr;
        -:  187:
     2335:  188:    localcomm_ptr->is_node_aware   = 0;
     2335:  189:    localcomm_ptr->node_comm       = NULL;
     2335:  190:    localcomm_ptr->node_roots_comm = NULL;
     2335:  191:    localcomm_ptr->intranode_table = NULL;
     2335:  192:    localcomm_ptr->internode_table = NULL;
        -:  193:
        -:  194:    /* sets up the SMP-aware sub-communicators and tables */
     2335:  195:    mpi_errno = MPIR_Comm_commit(localcomm_ptr);
     2335:  196:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  197:
     2335:  198: fn_fail:
        -:  199:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
        -:  200:
     2335:  201:    return mpi_errno;
        -:  202:}
        -:  203:
        -:  204:/* Provides a hook for the top level functions to perform some manipulation on a
        -:  205:   communicator just before it is given to the application level.
        -:  206:  
        -:  207:   For example, we create sub-communicators for SMP-aware collectives at this
        -:  208:   step. */
        -:  209:int MPIR_Comm_commit(MPID_Comm *comm)
   695941:  210:{
   695941:  211:    int mpi_errno = MPI_SUCCESS;
        -:  212:    int i;
   695941:  213:    int num_local = -1, num_external = -1;
   695941:  214:    int local_rank = -1, external_rank = -1;
   695941:  215:    int *local_procs = NULL, *external_procs = NULL;
        -:  216:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_COMMIT);
        -:  217:
        -:  218:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_COMMIT);
        -:  219:
        -:  220:    /* It's OK to relax these assertions, but we should do so very
        -:  221:       intentionally.  For now this function is the only place that we create
        -:  222:       our hierarchy of communicators */
   695941:  223:    MPIU_Assert(comm->node_comm == NULL);
   695941:  224:    MPIU_Assert(comm->node_roots_comm == NULL);
        -:  225:
   695941:  226:    if (comm->comm_kind == MPID_INTRACOMM) {
        -:  227:
   692280:  228:        mpi_errno = MPIU_Find_local_and_external(comm,
        -:  229:                                                 &num_local,    &local_rank,    &local_procs,
        -:  230:                                                 &num_external, &external_rank, &external_procs,
        -:  231:                                                 &comm->intranode_table, &comm->internode_table);
   692280:  232:        if (mpi_errno) {
       63:  233:            if (MPIR_Err_is_fatal(mpi_errno)) MPIU_ERR_POP(mpi_errno);
        -:  234:
        -:  235:            /* Non-fatal errors simply mean that this communicator will not have
        -:  236:               any node awareness.  Node-aware collectives are an optimization. */
        -:  237:            MPIU_DBG_MSG_P(COMM,VERBOSE,"MPIU_Find_local_and_external failed for comm_ptr=%p", comm);
       63:  238:            if (comm->intranode_table)
    #####:  239:                MPIU_Free(comm->intranode_table);
       63:  240:            if (comm->internode_table)
    #####:  241:                MPIU_Free(comm->internode_table);
        -:  242:
       63:  243:            mpi_errno = MPI_SUCCESS;
       63:  244:            goto fn_exit;
        -:  245:        }
        -:  246:
        -:  247:        /* defensive checks */
   692217:  248:        MPIU_Assert(num_local > 0);
   692217:  249:        MPIU_Assert(num_local > 1 || external_rank >= 0);
   692217:  250:        MPIU_Assert(external_rank < 0 || external_procs != NULL);
        -:  251:
        -:  252:        /* if the node_roots_comm and comm would be the same size, then creating
        -:  253:           the second communicator is useless and wasteful. */
   692217:  254:        if (num_external == comm->remote_size) {
    37535:  255:            MPIU_Assert(num_local == 1);
        -:  256:            goto fn_exit;
        -:  257:        }
        -:  258:
        -:  259:        /* we don't need a local comm if this process is the only one on this node */
   654682:  260:        if (num_local > 1) {
   654682:  261:            mpi_errno = MPIR_Comm_create(&comm->node_comm);
   654682:  262:            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  263:
   654682:  264:            comm->node_comm->context_id = comm->context_id + MPID_CONTEXT_INTRANODE_OFFSET;
   654682:  265:            comm->node_comm->recvcontext_id = comm->node_comm->context_id;
   654682:  266:            comm->node_comm->rank = local_rank;
   654682:  267:            comm->node_comm->comm_kind = MPID_INTRACOMM;
   654682:  268:            comm->node_comm->local_comm = NULL;
        -:  269:
   654682:  270:            comm->node_comm->local_size  = num_local;
   654682:  271:            comm->node_comm->remote_size = num_local;
        -:  272:
   654682:  273:            MPID_VCRT_Create( num_local, &comm->node_comm->vcrt );
   654682:  274:            MPID_VCRT_Get_ptr( comm->node_comm->vcrt, &comm->node_comm->vcr );
  2209306:  275:            for (i = 0; i < num_local; ++i) {
        -:  276:                /* For rank i in the new communicator, find the corresponding
        -:  277:                   rank in the input communicator */
  1554624:  278:                MPID_VCR_Dup( comm->vcr[local_procs[i]], 
        -:  279:                              &comm->node_comm->vcr[i] );
        -:  280:            }
        -:  281:
        -:  282:            MPID_Dev_comm_create_hook( comm->node_comm );
        -:  283:            /* don't call MPIR_Comm_commit here */
        -:  284:        }
        -:  285:
        -:  286:
        -:  287:        /* this process may not be a member of the node_roots_comm */
   654682:  288:        if (local_rank == 0) {
   309029:  289:            mpi_errno = MPIR_Comm_create(&comm->node_roots_comm);
   309029:  290:            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  291:
   309029:  292:            comm->node_roots_comm->context_id = comm->context_id + MPID_CONTEXT_INTERNODE_OFFSET;
   309029:  293:            comm->node_roots_comm->recvcontext_id = comm->node_roots_comm->context_id;
   309029:  294:            comm->node_roots_comm->rank = external_rank;
   309029:  295:            comm->node_roots_comm->comm_kind = MPID_INTRACOMM;
   309029:  296:            comm->node_roots_comm->local_comm = NULL;
        -:  297:
   309029:  298:            comm->node_roots_comm->local_size  = num_external;
   309029:  299:            comm->node_roots_comm->remote_size = num_external;
        -:  300:
   309029:  301:            MPID_VCRT_Create( num_external, &comm->node_roots_comm->vcrt );
   309029:  302:            MPID_VCRT_Get_ptr( comm->node_roots_comm->vcrt, &comm->node_roots_comm->vcr );
   618058:  303:            for (i = 0; i < num_external; ++i) {
        -:  304:                /* For rank i in the new communicator, find the corresponding
        -:  305:                   rank in the input communicator */
   309029:  306:                MPID_VCR_Dup( comm->vcr[external_procs[i]], 
        -:  307:                              &comm->node_roots_comm->vcr[i] );
        -:  308:            }
        -:  309:
        -:  310:            MPID_Dev_comm_create_hook( comm->node_roots_comm );
        -:  311:            /* don't call MPIR_Comm_commit here */
        -:  312:        }
        -:  313:
   654682:  314:        comm->is_node_aware = 1;
        -:  315:    }
        -:  316:
   695941:  317:fn_exit:
   695941:  318:    if (external_procs != NULL)
   692217:  319:        MPIU_Free(external_procs);
   695941:  320:    if (local_procs != NULL)
   692217:  321:        MPIU_Free(local_procs);
        -:  322:
        -:  323:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_COMMIT);
   695941:  324:    return mpi_errno;
        -:  325:fn_fail:
        -:  326:    goto fn_exit;
        -:  327:}
        -:  328:
        -:  329:/* Returns true if the given communicator is aware of node topology information,
        -:  330:   false otherwise.  Such information could be used to implement more efficient
        -:  331:   collective communication, for example. */
        -:  332:int MPIR_Comm_is_node_aware(MPID_Comm * comm)
  4176576:  333:{
  4176576:  334:    return comm->is_node_aware;
        -:  335:}
        -:  336:
        -:  337:/* Returns true if the communicator is node-aware and processes in all the nodes
        -:  338:   are consecutive. For example, if node 0 contains "0, 1, 2, 3", node 1
        -:  339:   contains "4, 5, 6", and node 2 contains "7", we shall return true. */
        -:  340:int MPIR_Comm_is_node_consecutive(MPID_Comm * comm)
    18217:  341:{
    18217:  342:    int i = 0, curr_nodeidx = 0;
    18217:  343:    int *internode_table = comm->internode_table;
        -:  344:
    18217:  345:    if (!comm->is_node_aware)
     7173:  346:        return 0;
        -:  347:
    22646:  348:    for (; i < comm->local_size; i++)
        -:  349:    {
    22646:  350:        if (internode_table[i] == curr_nodeidx + 1)
    #####:  351:            curr_nodeidx++;
    22646:  352:        else if (internode_table[i] != curr_nodeidx)
    #####:  353:            return 0;
        -:  354:    }
        -:  355:
    11044:  356:    return 1;
        -:  357:}
        -:  358:
        -:  359:/*
        -:  360: * Here are the routines to find a new context id.  The algorithm is discussed 
        -:  361: * in detail in the mpich2 coding document.  There are versions for
        -:  362: * single threaded and multithreaded MPI.
        -:  363: *
        -:  364: * Both the threaded and non-threaded routines use the same mask of
        -:  365: * available context id values.
        -:  366: */
        -:  367:static uint32_t context_mask[MPIR_MAX_CONTEXT_MASK];
        -:  368:static int initialize_context_mask = 1;
        -:  369:
        -:  370:#ifdef USE_DBG_LOGGING
        -:  371:/* Create a string that contains the context mask.  This is
        -:  372:   used only with the logging interface, and must be used by one thread at 
        -:  373:   a time (should this be enforced by the logging interface?).
        -:  374:   Converts the mask to hex and returns a pointer to that string */
        -:  375:static char *MPIR_ContextMaskToStr( void )
        -:  376:{
        -:  377:    static char bufstr[MPIR_MAX_CONTEXT_MASK*8+1];
        -:  378:    int i;
        -:  379:    int maxset=0;
        -:  380:
        -:  381:    for (maxset=MPIR_MAX_CONTEXT_MASK-1; maxset>=0; maxset--) {
        -:  382:	if (context_mask[maxset] != 0) break;
        -:  383:    }
        -:  384:
        -:  385:    for (i=0; i<maxset; i++) {
        -:  386:	MPIU_Snprintf( &bufstr[i*8], 9, "%.8x", context_mask[i] );
        -:  387:    }
        -:  388:    return bufstr;
        -:  389:}
        -:  390:#endif
        -:  391:
        -:  392:#ifdef MPICH_DEBUG_HANDLEALLOC
        -:  393:static int MPIU_CheckContextIDsOnFinalize(void *context_mask_ptr)
        -:  394:{
        -:  395:    int i;
        -:  396:    uint32_t *mask = context_mask_ptr;
        -:  397:    /* the predefined communicators should be freed by this point, so we don't
        -:  398:     * need to special case bits 0,1, and 2 */
        -:  399:    for (i = 0; i < MPIR_MAX_CONTEXT_MASK; ++i) {
        -:  400:        if (~mask[i]) {
        -:  401:            /* some bits were still cleared */
        -:  402:            printf("leaked context IDs detected: mask=%p mask[%d]=%#x\n", mask, i, (int)mask[i]);
        -:  403:        }
        -:  404:    }
        -:  405:    return MPI_SUCCESS;
        -:  406:}
        -:  407:#endif
        -:  408:
        -:  409:static void MPIR_Init_contextid(void)
     2426:  410:{
        -:  411:    int i;
        -:  412:
   155264:  413:    for (i=1; i<MPIR_MAX_CONTEXT_MASK; i++) {
   152838:  414:	context_mask[i] = 0xFFFFFFFF;
        -:  415:    }
        -:  416:    /* the first three values are already used (comm_world, comm_self,
        -:  417:       and the internal-only copy of comm_world) */
     2426:  418:    context_mask[0] = 0xFFFFFFF8; 
     2426:  419:    initialize_context_mask = 0;
        -:  420:
        -:  421:#ifdef MPICH_DEBUG_HANDLEALLOC
        -:  422:    /* check for context ID leaks in MPI_Finalize.  Use (_PRIO-1) to make sure
        -:  423:     * that we run after MPID_Finalize. */
        -:  424:    MPIR_Add_finalize(MPIU_CheckContextIDsOnFinalize, context_mask,
        -:  425:                      MPIR_FINALIZE_CALLBACK_PRIO - 1);
        -:  426:#endif
     2426:  427:}
        -:  428:
        -:  429:/* Return the context id corresponding to the first set bit in the mask.
        -:  430:   Return 0 if no bit found.  This function does _not_ alter local_mask. */
        -:  431:static int MPIR_Locate_context_bit(uint32_t local_mask[])
   982446:  432:{
   982446:  433:    int i, j, context_id = 0;
  2583318:  434:    for (i=0; i<MPIR_MAX_CONTEXT_MASK; i++) {
  2580402:  435:	if (local_mask[i]) {
        -:  436:	    /* There is a bit set in this word. */
        -:  437:	    register uint32_t     val, nval;
        -:  438:	    /* The following code finds the highest set bit by recursively
        -:  439:	       checking the top half of a subword for a bit, and incrementing
        -:  440:	       the bit location by the number of bit of the lower sub word if 
        -:  441:	       the high subword contains a set bit.  The assumption is that
        -:  442:	       full-word bitwise operations and compares against zero are 
        -:  443:	       fast */
   979530:  444:	    val = local_mask[i];
   979530:  445:	    j   = 0;
   979530:  446:	    nval = val & 0xFFFF0000;
   979530:  447:	    if (nval) {
   785718:  448:		j += 16;
   785718:  449:		val = nval;
        -:  450:	    }
   979530:  451:	    nval = val & 0xFF00FF00;
   979530:  452:	    if (nval) {
   775858:  453:		j += 8;
   775858:  454:		val = nval;
        -:  455:	    }
   979530:  456:	    nval = val & 0xF0F0F0F0;
   979530:  457:	    if (nval) {
   664705:  458:		j += 4;
   664705:  459:		val = nval;
        -:  460:	    }
   979530:  461:	    nval = val & 0xCCCCCCCC;
   979530:  462:	    if (nval) {
   765961:  463:		j += 2;
   765961:  464:		val = nval;
        -:  465:	    }
   979530:  466:	    if (val & 0xAAAAAAAA) {
   745438:  467:		j += 1;
        -:  468:	    }
   979530:  469:	    context_id = (MPIR_CONTEXT_INT_BITS * i + j) << MPID_CONTEXT_PREFIX_SHIFT;
   979530:  470:	    return context_id;
        -:  471:	}
        -:  472:    }
     2916:  473:    return 0;
        -:  474:}
        -:  475:
        -:  476:/* Allocates a context ID from the given mask by clearing the bit
        -:  477: * corresponding to the the given id.  Returns 0 on failure, id on
        -:  478: * success. */
        -:  479:static int MPIR_Allocate_context_bit(uint32_t mask[], MPIR_Context_id_t id)
   967236:  480:{
        -:  481:    int raw_prefix, idx, bitpos;
   967236:  482:    raw_prefix = MPID_CONTEXT_READ_FIELD(PREFIX,id);
   967236:  483:    idx    = raw_prefix / MPIR_CONTEXT_INT_BITS;
   967236:  484:    bitpos = raw_prefix % MPIR_CONTEXT_INT_BITS;
        -:  485:
        -:  486:    /* the bit should not already be cleared (allocated) */
   967236:  487:    MPIU_Assert(mask[idx] & (1<<bitpos));
        -:  488:
        -:  489:    /* clear the bit */
   967236:  490:    mask[idx] &= ~(1<<bitpos);
        -:  491:
        -:  492:    MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,
        -:  493:            "allocating contextid = %d, (mask=%p, mask[%d], bit %d)",
        -:  494:            id, mask, idx, bitpos));
   967236:  495:    return id;
        -:  496:}
        -:  497:
        -:  498:/* Allocates the first available context ID from context_mask based on the available
        -:  499: * bits given in local_mask.  This function will clear the corresponding bit in
        -:  500: * context_mask if allocation was successful.
        -:  501: *
        -:  502: * Returns 0 on failure.  Returns the allocated context ID on success. */
        -:  503:static int MPIR_Find_and_allocate_context_id(uint32_t local_mask[])
   970152:  504:{
        -:  505:    MPIR_Context_id_t context_id;
   970152:  506:    context_id = MPIR_Locate_context_bit(local_mask);
   970152:  507:    if (context_id != 0) {
   967236:  508:        context_id = MPIR_Allocate_context_bit(context_mask, context_id);
        -:  509:    }
   970152:  510:    return context_id;
        -:  511:}
        -:  512:
        -:  513:#ifndef MPICH_IS_THREADED
        -:  514:/* Unthreaded (only one MPI call active at any time) */
        -:  515:
        -:  516:#undef FUNCNAME
        -:  517:#define FUNCNAME MPIR_Get_contextid
        -:  518:#undef FCNAME
        -:  519:#define FCNAME "MPIR_Get_contextid"
        -:  520:int MPIR_Get_contextid( MPID_Comm *comm_ptr, MPIR_Context_id_t *context_id )
        -:  521:{
        -:  522:    int mpi_errno = MPI_SUCCESS;
        -:  523:    uint32_t     local_mask[MPIR_MAX_CONTEXT_MASK];
        -:  524:    MPIU_THREADPRIV_DECL;
        -:  525:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_CONTEXTID);
        -:  526:
        -:  527:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_CONTEXTID);
        -:  528:
        -:  529:    *context_id = 0;
        -:  530:
        -:  531:    if (initialize_context_mask) {
        -:  532:	MPIR_Init_contextid();
        -:  533:    }
        -:  534:    MPIU_Memcpy( local_mask, context_mask, MPIR_MAX_CONTEXT_MASK * sizeof(int) );
        -:  535:
        -:  536:    /* Note that this is the unthreaded version */
        -:  537:    MPIU_THREADPRIV_GET;
        -:  538:    MPIR_Nest_incr();
        -:  539:    /* Comm must be an intracommunicator */
        -:  540:    mpi_errno = NMPI_Allreduce( MPI_IN_PLACE, local_mask, MPIR_MAX_CONTEXT_MASK, 
        -:  541:				MPI_INT, MPI_BAND, comm_ptr->handle );
        -:  542:    MPIR_Nest_decr();
        -:  543:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  544:
        -:  545:    *context_id = MPIR_Find_and_allocate_context_id(local_mask);
        -:  546:    MPIU_ERR_CHKANDJUMP(!(*context_id), mpi_errno, MPIR_ERR_RECOVERABLE, "**toomanycomm");
        -:  547:
        -:  548:fn_exit:
        -:  549:    MPIU_DBG_MSG_S(COMM,VERBOSE,"Context mask = %s",MPIR_ContextMaskToStr());
        -:  550:
        -:  551:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_CONTEXTID);
        -:  552:    return mpi_errno;
        -:  553:fn_fail:
        -:  554:    goto fn_exit;
        -:  555:}
        -:  556:
        -:  557:#else /* MPICH_IS_THREADED is set and true */
        -:  558:
        -:  559:/* Additional values needed to maintain thread safety */
        -:  560:static volatile int mask_in_use = 0;
        -:  561:/* lowestContextId is used to break ties when multiple threads
        -:  562:   are contending for the mask */
        -:  563:#define MPIR_MAXID (1 << 30)
        -:  564:static volatile int lowestContextId = MPIR_MAXID;
        -:  565:
        -:  566:#undef FUNCNAME
        -:  567:#define FUNCNAME MPIR_Get_contextid
        -:  568:#undef FCNAME
        -:  569:#define FCNAME "MPIR_Get_contextid"
        -:  570:int MPIR_Get_contextid( MPID_Comm *comm_ptr, MPIR_Context_id_t *context_id )
   967236:  571:{
   967236:  572:    int          mpi_errno = MPI_SUCCESS;
        -:  573:    uint32_t     local_mask[MPIR_MAX_CONTEXT_MASK];
   967236:  574:    int          own_mask = 0;
   967236:  575:    int          testCount = 10; /* if you change this value, you need to also change 
        -:  576:				    it below where it is reinitialized */
        -:  577:
   967236:  578:    MPIU_THREADPRIV_DECL;
        -:  579:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_CONTEXTID);
        -:  580:
        -:  581:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_CONTEXTID);
        -:  582:
   967236:  583:    MPIU_THREADPRIV_GET;
        -:  584:
   967236:  585:    *context_id = 0;
        -:  586:
        -:  587:    /* We increment the nest level now because we need to know that we're
        -:  588:     within another MPI routine before calling the CS_ENTER macro */
   967236:  589:    MPIR_Nest_incr();
        -:  590:
        -:  591:    /* We lock only around access to the mask.  If another thread is
        -:  592:       using the mask, we take a mask of zero */
        -:  593:    MPIU_DBG_MSG_FMT( COMM, VERBOSE, (MPIU_DBG_FDEST,
        -:  594:         "Entering; shared state is %d:%d", mask_in_use, lowestContextId ) );
        -:  595:    /* We need a special test in this loop for the case where some process
        -:  596:     has exhausted its supply of context ids.  In the single threaded case, 
        -:  597:     this is simple, because the algorithm is deterministic (see above).  In 
        -:  598:     the multithreaded case, it is more complicated, because we may get a
        -:  599:     zero for the context mask because some other thread holds the mask.  
        -:  600:     In addition, we can't check for the case where this process did not
        -:  601:     select MPI_THREAD_MULTIPLE, because one of the other processes
        -:  602:     may have selected MPI_THREAD_MULTIPLE.  To handle this case, after a 
        -:  603:     fixed number of failures, we test to see if some process has exhausted 
        -:  604:     its supply of context ids.  If so, all processes can invoke the 
        -:  605:     out-of-context-id error.  That fixed number of tests is in testCount */
  3038824:  606:    while (*context_id == 0) {
        -:  607:	/* In all but the global-critical-section case, we must ensure that
        -:  608:	   only one thread access the context id mask at a time */
        -:  609:	MPIU_THREAD_CS_ENTER(CONTEXTID,);
  1104352:  610:	if (initialize_context_mask) {
     2426:  611:	    MPIR_Init_contextid();
        -:  612:	}
  1104352:  613:	if (mask_in_use || comm_ptr->context_id > lowestContextId) {
   134200:  614:	    memset( local_mask, 0, MPIR_MAX_CONTEXT_MASK * sizeof(int) );
   134200:  615:	    own_mask        = 0;
   134200:  616:	    if (comm_ptr->context_id < lowestContextId) {
      948:  617:		lowestContextId = comm_ptr->context_id;
        -:  618:	    }
        -:  619:	    MPIU_DBG_MSG_D( COMM, VERBOSE, 
        -:  620:	       "In in-use, set lowestContextId to %d", lowestContextId );
        -:  621:	}
        -:  622:	else {
   970152:  623:	    MPIU_Memcpy( local_mask, context_mask, MPIR_MAX_CONTEXT_MASK * sizeof(int) );
   970152:  624:	    mask_in_use     = 1;
   970152:  625:	    own_mask        = 1;
   970152:  626:	    lowestContextId = comm_ptr->context_id;
        -:  627:	    MPIU_DBG_MSG( COMM, VERBOSE, "Copied local_mask" );
        -:  628:	}
        -:  629:	MPIU_THREAD_CS_EXIT(CONTEXTID,);
        -:  630:	
        -:  631:	/* Now, try to get a context id */
  1104352:  632:        MPIU_Assert(comm_ptr->comm_kind == MPID_INTRACOMM);
        -:  633:	/* In the global and brief-global cases, note that this routine will
        -:  634:	   release that global lock when it needs to wait.  That will allow 
        -:  635:	   other processes to enter the global or brief global critical section.
        -:  636:	 */ 
  1104352:  637:	mpi_errno = NMPI_Allreduce( MPI_IN_PLACE, local_mask, MPIR_MAX_CONTEXT_MASK,
        -:  638:				    MPI_INT, MPI_BAND, comm_ptr->handle );
  1104352:  639:	if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  640:
  1104352:  641:	if (own_mask) {
        -:  642:	    /* There is a chance that we've found a context id */
        -:  643:	    MPIU_THREAD_CS_ENTER(CONTEXTID,);
        -:  644:	    /* Find_and_allocate_context_id updates the context_mask if it finds a match */
   970152:  645:	    *context_id = MPIR_Find_and_allocate_context_id(local_mask);
        -:  646:	    MPIU_DBG_MSG_D( COMM, VERBOSE, 
        -:  647:			    "Context id is now %hd", *context_id );
   970152:  648:	    if (*context_id > 0) {
        -:  649:		/* If we were the lowest context id, reset the value to
        -:  650:		   allow the other threads to compete for the mask */
   967236:  651:		if (lowestContextId == comm_ptr->context_id) {
   967226:  652:		    lowestContextId = MPIR_MAXID;
        -:  653:		    /* Else leave it alone; there is another thread waiting */
        -:  654:		}
        -:  655:	    }
        -:  656:	    else {
        -:  657:		/* else we did not find a context id. Give up the mask in case
        -:  658:		   there is another thread (with a lower context id) waiting for
        -:  659:		   it.
        -:  660:
        -:  661:		   We need to ensure that any other threads have the 
        -:  662:		   opportunity to run.  We do this by releasing the single
        -:  663:		   mutex, yielding, and then reaquiring the mutex.
        -:  664:		   We might want to do something more sophisticated, such
        -:  665:		   as using a condition variable (if we know for sure that
        -:  666:		   there is another thread on this process that is waiting).
        -:  667:		*/
     2916:  668:		MPIU_THREAD_CS_YIELD(CONTEXTID,);
        -:  669:#if 0
        -:  670:		/* The old code */
        -:  671:		MPID_Thread_mutex_unlock(&MPIR_ThreadInfo.global_mutex);
        -:  672:		MPID_Thread_yield();
        -:  673:		MPID_Thread_mutex_lock(&MPIR_ThreadInfo.global_mutex);
        -:  674:#endif
        -:  675:	    }
   970152:  676:	    mask_in_use = 0;
        -:  677:	    MPIU_THREAD_CS_EXIT(CONTEXTID,);
        -:  678:	}
        -:  679:	else {
        -:  680:	    /* As above, force this thread to yield */
        -:  681:	    /* FIXME: TEMP for current yield definition*/
        -:  682:	    MPIU_THREAD_CS_ENTER(CONTEXTID,);
   134200:  683:	    MPIU_THREAD_CS_YIELD(CONTEXTID,);
        -:  684:	    MPIU_THREAD_CS_EXIT(CONTEXTID,);
        -:  685:#if 0
        -:  686:	    MPID_Thread_mutex_unlock(&MPIR_ThreadInfo.global_mutex);
        -:  687:	    MPID_Thread_yield();
        -:  688:	    MPID_Thread_mutex_lock(&MPIR_ThreadInfo.global_mutex);
        -:  689:#endif
        -:  690:	}
        -:  691:	/* Here is the test for out-of-context ids */
  1104352:  692:	if ((testCount-- == 0) && (*context_id == 0)) {
        -:  693:	    int hasNoId, totalHasNoId;
        -:  694:	    /* We don't need to lock on this because we're just looking for
        -:  695:	       zero or nonzero */
    12294:  696:	    hasNoId = MPIR_Locate_context_bit(context_mask) == 0;
    12294:  697:	    mpi_errno = NMPI_Allreduce( &hasNoId, &totalHasNoId, 1, MPI_INT, 
        -:  698:			    MPI_MAX, comm_ptr->handle );
    12294:  699:	    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    12294:  700:	    if (totalHasNoId == 1) {
        -:  701:		/* Release the mask for use by other threads */
    #####:  702:		if (own_mask) {
    #####:  703:		    mask_in_use = 0;
        -:  704:		}
    #####:  705:		MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**toomanycomm");
        -:  706:	    }
        -:  707:	    else { /* reinitialize testCount */
    12294:  708:		testCount = 10;
        -:  709:                MPIU_DBG_MSG_D(COMM, VERBOSE, "reinitialized testCount to %d", testCount);
        -:  710:	    }
        -:  711:	}
        -:  712:    }
        -:  713:
   967236:  714:fn_exit:
        -:  715:    MPIU_DBG_MSG_S(COMM,VERBOSE,"Context mask = %s",MPIR_ContextMaskToStr());
   967236:  716:    MPIR_Nest_decr();
        -:  717:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_CONTEXTID);
   967236:  718:    return mpi_errno;
    #####:  719:fn_fail:
        -:  720:    /* Release the masks */
    #####:  721:    if (own_mask) {
    #####:  722:        mask_in_use = 0;
        -:  723:    }
        -:  724:    goto fn_exit;
        -:  725:}
        -:  726:#endif
        -:  727:
        -:  728:/* Get a context for a new intercomm.  There are two approaches 
        -:  729:   here (for MPI-1 codes only)
        -:  730:   (a) Each local group gets a context; the groups exchange, and
        -:  731:       the low value is accepted and the high one returned.  This
        -:  732:       works because the context ids are taken from the same pool.
        -:  733:   (b) Form a temporary intracomm over all processes and use that
        -:  734:       with the regular algorithm.
        -:  735:   
        -:  736:   In some ways, (a) is the better approach because it is the one that
        -:  737:   extends to MPI-2 (where the last step, returning the context, is 
        -:  738:   not used and instead separate send and receive context id value 
        -:  739:   are kept).  For this reason, we'll use (a).
        -:  740:
        -:  741:   Even better is to separate the local and remote context ids.  Then
        -:  742:   each group of processes can manage their context ids separately.
        -:  743:*/
        -:  744:/* 
        -:  745: * This uses the thread-safe (if necessary) routine to get a context id
        -:  746: * and does not need its own thread-safe version.
        -:  747: */
        -:  748:#undef FUNCNAME
        -:  749:#define FUNCNAME MPIR_Get_intercomm_contextid
        -:  750:#undef FCNAME
        -:  751:#define FCNAME "MPIR_Get_intercomm_contextid"
        -:  752:int MPIR_Get_intercomm_contextid( MPID_Comm *comm_ptr, MPIR_Context_id_t *context_id, 
        -:  753:				  MPIR_Context_id_t *recvcontext_id )
      331:  754:{
        -:  755:    MPIR_Context_id_t mycontext_id, remote_context_id;
      331:  756:    int mpi_errno = MPI_SUCCESS;
      331:  757:    int tag = 31567; /* FIXME  - we need an internal tag or 
        -:  758:		        communication channel.  Can we use a different
        -:  759:		        context instead?.  Or can we use the tag 
        -:  760:		        provided in the intercomm routine? (not on a dup, 
        -:  761:			but in that case it can use the collective context) */
      331:  762:    MPIU_THREADPRIV_DECL;
        -:  763:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);
        -:  764:
        -:  765:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);
        -:  766:
      331:  767:    if (!comm_ptr->local_comm) {
        -:  768:        /* Manufacture the local communicator */
      321:  769:        mpi_errno = MPIR_Setup_intercomm_localcomm( comm_ptr );
      321:  770:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  771:    }
        -:  772:
      331:  773:    mpi_errno = MPIR_Get_contextid( comm_ptr->local_comm, &mycontext_id );
      331:  774:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
      331:  775:    MPIU_Assert(mycontext_id != 0);
        -:  776:
      331:  777:    MPIU_THREADPRIV_GET;
        -:  778:
        -:  779:    /* MPIC routine uses an internal context id.  The local leads (process 0)
        -:  780:       exchange data */
      331:  781:    remote_context_id = -1;
      331:  782:    if (comm_ptr->rank == 0) {
      150:  783:        mpi_errno = MPIC_Sendrecv( &mycontext_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, 0, tag,
        -:  784:                                   &remote_context_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, 0, tag, 
        -:  785:                                   comm_ptr->handle, MPI_STATUS_IGNORE );
      150:  786:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  787:    }
        -:  788:
        -:  789:    /* Make sure that all of the local processes now have this
        -:  790:       id */
      331:  791:    MPIR_Nest_incr();
      331:  792:    mpi_errno = NMPI_Bcast( &remote_context_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, 
        -:  793:                            0, comm_ptr->local_comm->handle );
      331:  794:    MPIR_Nest_decr();
      331:  795:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  796:
        -:  797:    /* The recvcontext_id must be the one that was allocated out of the local
        -:  798:     * group, not the remote group.  Otherwise we could end up posting two
        -:  799:     * MPI_ANY_SOURCE,MPI_ANY_TAG recvs on the same context IDs even though we
        -:  800:     * are attempting to post them for two separate communicators. */
      331:  801:    *context_id     = remote_context_id;
      331:  802:    *recvcontext_id = mycontext_id;
      331:  803: fn_fail:
        -:  804:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);
      331:  805:    return mpi_errno;
        -:  806:}
        -:  807:
        -:  808:#undef FUNCNAME
        -:  809:#define FUNCNAME MPIR_Free_contextid
        -:  810:#undef FCNAME
        -:  811:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  812:void MPIR_Free_contextid( MPIR_Context_id_t context_id )
  1947385:  813:{
        -:  814:    int idx, bitpos, raw_prefix;
        -:  815:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_FREE_CONTEXTID);
        -:  816:    
        -:  817:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_FREE_CONTEXTID);
        -:  818:
        -:  819:    /* Convert the context id to the bit position */
  1947385:  820:    raw_prefix = MPID_CONTEXT_READ_FIELD(PREFIX,context_id);
  1947385:  821:    idx    = raw_prefix / MPIR_CONTEXT_INT_BITS;
  1947385:  822:    bitpos = raw_prefix % MPIR_CONTEXT_INT_BITS;
        -:  823:
        -:  824:    /* --BEGIN ERROR HANDLING-- */
  1947385:  825:    if (idx < 0 || idx >= MPIR_MAX_CONTEXT_MASK) {
    #####:  826:	MPID_Abort( 0, MPI_ERR_INTERN, 1, 
        -:  827:		    "In MPIR_Free_contextid, idx is out of range" );
        -:  828:    }
        -:  829:
        -:  830:    /* The low order bits for dynamic context IDs don't have meaning the
        -:  831:     * same way that low bits of non-dynamic ctx IDs do.  So we have to
        -:  832:     * check the dynamic case first. */
  1947385:  833:    if (MPID_CONTEXT_READ_FIELD(DYNAMIC_PROC, context_id)) {
        -:  834:        MPIU_DBG_MSG_D(COMM,VERBOSE,"skipping dynamic process ctx id, context_id=%d", context_id);
     1336:  835:        goto fn_exit;
        -:  836:    }
        -:  837:    else { /* non-dynamic context ID */
        -:  838:        /* In terms of the context ID bit vector, intercomms and their constituent
        -:  839:         * localcomms have the same value.  To avoid a double-free situation we just
        -:  840:         * don't free the context ID for localcomms and assume it will be cleaned up
        -:  841:         * when the parent intercomm is itself completely freed. */
  1946049:  842:        if (MPID_CONTEXT_READ_FIELD(IS_LOCALCOMM, context_id)) {
        -:  843:#ifdef USE_DBG_LOGGING
        -:  844:            char dump_str[1024];
        -:  845:            MPIR_Comm_dump_context_id(context_id, dump_str, sizeof(dump_str));
        -:  846:            MPIU_DBG_MSG_S(COMM,VERBOSE,"skipping localcomm id: %s", dump_str);
        -:  847:#endif
     4840:  848:            goto fn_exit;
        -:  849:        }
  1941209:  850:        else if (MPID_CONTEXT_READ_FIELD(SUBCOMM, context_id)) {
        -:  851:            MPIU_DBG_MSG_D(COMM,VERBOSE,"skipping non-parent communicator ctx id, context_id=%d", context_id);
   961074:  852:            goto fn_exit;
        -:  853:        }
        -:  854:    }
        -:  855:
        -:  856:    /* Check that this context id has been allocated */
   980135:  857:    if ( (context_mask[idx] & (0x1 << bitpos)) != 0 ) {
        -:  858:#ifdef USE_DBG_LOGGING
        -:  859:        char dump_str[1024];
        -:  860:        MPIR_Comm_dump_context_id(context_id, dump_str, sizeof(dump_str));
        -:  861:        MPIU_DBG_MSG_S(COMM,VERBOSE,"context dump: %s", dump_str);
        -:  862:        MPIU_DBG_MSG_S(COMM,VERBOSE,"context mask = %s",MPIR_ContextMaskToStr());
        -:  863:#endif
    #####:  864:	MPID_Abort( 0, MPI_ERR_INTERN, 1, 
        -:  865:		    "In MPIR_Free_contextid, the context id is not in use" );
        -:  866:    }
        -:  867:    /* --END ERROR HANDLING-- */
        -:  868:
        -:  869:    MPIU_THREAD_CS_ENTER(CONTEXTID,);
        -:  870:    /* MT: Note that this update must be done atomically in the multithreaedd
        -:  871:       case.  In the "one, single lock" implementation, that lock is indeed
        -:  872:       held when this operation is called. */
   980135:  873:    context_mask[idx] |= (0x1 << bitpos);
        -:  874:    MPIU_THREAD_CS_EXIT(CONTEXTID,);
        -:  875:
        -:  876:    MPIU_DBG_MSG_FMT(COMM,VERBOSE,
        -:  877:                     (MPIU_DBG_FDEST,
        -:  878:                      "Freed context %d, mask[%d] bit %d (prefix=%#x)",
        -:  879:                      context_id, idx, bitpos, raw_prefix));
  1947385:  880:fn_exit:
        -:  881:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_FREE_CONTEXTID);
  1947385:  882:}
        -:  883:
        -:  884:/*
        -:  885: * Copy a communicator, including creating a new context and copying the
        -:  886: * virtual connection tables and clearing the various fields.
        -:  887: * Does *not* copy attributes.  If size is < the size of the local group
        -:  888: * in the input communicator, copy only the first size elements.
        -:  889: * If this process is not a member, return a null pointer in outcomm_ptr.
        -:  890: * This is only supported in the case where the communicator is in 
        -:  891: * Intracomm (not an Intercomm).  Note that this is all that is required
        -:  892: * for cart_create and graph_create.
        -:  893: *
        -:  894: * Used by cart_create, graph_create, and dup_create 
        -:  895: */
        -:  896:#undef FUNCNAME
        -:  897:#define FUNCNAME MPIR_Comm_copy
        -:  898:#undef FCNAME
        -:  899:#define FCNAME "MPIR_Comm_copy"
        -:  900:int MPIR_Comm_copy( MPID_Comm *comm_ptr, int size, MPID_Comm **outcomm_ptr )
   530919:  901:{
   530919:  902:    int mpi_errno = MPI_SUCCESS;
        -:  903:    MPIR_Context_id_t new_context_id, new_recvcontext_id;
   530919:  904:    MPID_Comm *newcomm_ptr = NULL;
        -:  905:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_COPY);
        -:  906:
        -:  907:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_COPY);
        -:  908:
        -:  909:    /* Get a new context first.  We need this to be collective over the
        -:  910:       input communicator */
        -:  911:    /* If there is a context id cache in oldcomm, use it here.  Otherwise,
        -:  912:       use the appropriate algorithm to get a new context id.  Be careful
        -:  913:       of intercomms here */
   530919:  914:    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
      331:  915:	mpi_errno = 
        -:  916:	    MPIR_Get_intercomm_contextid( 
        -:  917:		 comm_ptr, &new_context_id, &new_recvcontext_id );
      331:  918:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  919:    }
        -:  920:    else {
   530588:  921:	mpi_errno = MPIR_Get_contextid( comm_ptr, &new_context_id );
   530588:  922:	new_recvcontext_id = new_context_id;
   530588:  923:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
   530588:  924:        MPIU_Assert(new_context_id != 0);
        -:  925:    }
        -:  926:    /* --BEGIN ERROR HANDLING-- */
   530919:  927:    if (new_context_id == 0) {
    #####:  928:        MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**toomanycomm" );
        -:  929:    }
        -:  930:    /* --END ERROR HANDLING-- */
        -:  931:
        -:  932:    /* This is the local size, not the remote size, in the case of
        -:  933:       an intercomm */
   530919:  934:    if (comm_ptr->rank >= size) {
        1:  935:        *outcomm_ptr = 0;
        -:  936:        /* always free the recvcontext ID, never the "send" ID */
        1:  937:        MPIR_Free_contextid(new_recvcontext_id);
        1:  938:	goto fn_exit;
        -:  939:    }
        -:  940:
        -:  941:    /* We're left with the processes that will have a non-null communicator.
        -:  942:       Create the object, initialize the data, and return the result */
        -:  943:
   530918:  944:    mpi_errno = MPIR_Comm_create( &newcomm_ptr );
   530918:  945:    if (mpi_errno) goto fn_fail;
        -:  946:
   530918:  947:    newcomm_ptr->context_id     = new_context_id;
   530918:  948:    newcomm_ptr->recvcontext_id = new_recvcontext_id;
        -:  949:
        -:  950:    /* Save the kind of the communicator */
   530918:  951:    newcomm_ptr->comm_kind   = comm_ptr->comm_kind;
   530918:  952:    newcomm_ptr->local_comm  = 0;
        -:  953:
        -:  954:    /* There are two cases here - size is the same as the old communicator,
        -:  955:       or it is smaller.  If the size is the same, we can just add a reference.
        -:  956:       Otherwise, we need to create a new VCRT.  Note that this is the
        -:  957:       test that matches the test on rank above. */
   530918:  958:    if (size == comm_ptr->local_size) {
        -:  959:	/* Duplicate the VCRT references */
   530915:  960:	MPID_VCRT_Add_ref( comm_ptr->vcrt );
   530915:  961:	newcomm_ptr->vcrt = comm_ptr->vcrt;
   530915:  962:	newcomm_ptr->vcr  = comm_ptr->vcr;
        -:  963:    }
        -:  964:    else {
        -:  965:	int i;
        -:  966:	/* The "remote" vcr gets the shortened vcrt */
        3:  967:	MPID_VCRT_Create( size, &newcomm_ptr->vcrt );
        3:  968:	MPID_VCRT_Get_ptr( newcomm_ptr->vcrt, 
        -:  969:			   &newcomm_ptr->vcr );
       12:  970:	for (i=0; i<size; i++) {
        -:  971:	    /* For rank i in the new communicator, find the corresponding
        -:  972:	       rank in the input communicator */
        9:  973:	    MPID_VCR_Dup( comm_ptr->vcr[i], &newcomm_ptr->vcr[i] );
        -:  974:	}
        -:  975:    }
        -:  976:
        -:  977:    /* If it is an intercomm, duplicate the local vcrt references */
   530918:  978:    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
      331:  979:	MPID_VCRT_Add_ref( comm_ptr->local_vcrt );
      331:  980:	newcomm_ptr->local_vcrt = comm_ptr->local_vcrt;
      331:  981:	newcomm_ptr->local_vcr  = comm_ptr->local_vcr;
        -:  982:    }
        -:  983:
        -:  984:    /* Set the sizes and ranks */
   530918:  985:    newcomm_ptr->rank        = comm_ptr->rank;
   530918:  986:    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
      331:  987:	newcomm_ptr->local_size   = comm_ptr->local_size;
      331:  988:	newcomm_ptr->remote_size  = comm_ptr->remote_size;
      331:  989:	newcomm_ptr->is_low_group = comm_ptr->is_low_group;
        -:  990:    }
        -:  991:    else {
   530587:  992:	newcomm_ptr->local_size  = size;
   530587:  993:	newcomm_ptr->remote_size = size;
        -:  994:    }
        -:  995:
        -:  996:    /* Inherit the error handler (if any) */
   530918:  997:    newcomm_ptr->errhandler = comm_ptr->errhandler;
   530918:  998:    if (comm_ptr->errhandler) {
   409669:  999:	MPIR_Errhandler_add_ref( comm_ptr->errhandler );
        -: 1000:    }
        -: 1001:
        -: 1002:    /* Notify the device of the new communicator */
        -: 1003:    MPID_Dev_comm_create_hook(newcomm_ptr);
   530918: 1004:    mpi_errno = MPIR_Comm_commit(newcomm_ptr);
   530918: 1005:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -: 1006:
        -: 1007:    /* Start with no attributes on this communicator */
   530918: 1008:    newcomm_ptr->attributes = 0;
   530918: 1009:    *outcomm_ptr = newcomm_ptr;
        -: 1010:
   530919: 1011: fn_fail:
   530919: 1012: fn_exit:
        -: 1013:
        -: 1014:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_COPY);
        -: 1015:
   530919: 1016:    return mpi_errno;
        -: 1017:}
        -: 1018:
        -: 1019:/* Common body between MPIR_Comm_release and MPIR_comm_release_always.  This
        -: 1020: * helper function frees the actual MPID_Comm structure and any associated
        -: 1021: * storage.  It also releases any refernces to other objects, such as the VCRT.
        -: 1022: * This function should only be called when the communicator's reference count
        -: 1023: * has dropped to 0. */
        -: 1024:#undef FUNCNAME
        -: 1025:#define FUNCNAME comm_delete
        -: 1026:#undef FCNAME
        -: 1027:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -: 1028:static int comm_delete(MPID_Comm * comm_ptr, int isDisconnect)
  1667695: 1029:{
        -: 1030:    int in_use;
  1667695: 1031:    int mpi_errno = MPI_SUCCESS;
        -: 1032:    MPID_MPI_STATE_DECL(MPID_STATE_COMM_DELETE);
        -: 1033:
        -: 1034:    MPID_MPI_FUNC_ENTER(MPID_STATE_COMM_DELETE);
        -: 1035:
  1667695: 1036:    MPIU_Assert(MPIU_Object_get_ref(comm_ptr) == 0); /* sanity check */
        -: 1037:
        -: 1038:    /* Remove the attributes, executing the attribute delete routine.
        -: 1039:       Do this only if the attribute functions are defined.
        -: 1040:       This must be done first, because if freeing the attributes
        -: 1041:       returns an error, the communicator is not freed */
  1667695: 1042:    if (MPIR_Process.attr_free && comm_ptr->attributes) {
        -: 1043:        /* Temporarily add a reference to this communicator because
        -: 1044:           the attr_free code requires a valid communicator */
     5507: 1045:        MPIU_Object_add_ref( comm_ptr );
     5507: 1046:        mpi_errno = MPIR_Process.attr_free( comm_ptr->handle,
        -: 1047:                                            &comm_ptr->attributes );
        -: 1048:        /* Release the temporary reference added before the call to
        -: 1049:           attr_free */
     5507: 1050:        MPIU_Object_release_ref( comm_ptr, &in_use);
        -: 1051:    }
        -: 1052:
        -: 1053:    /* If the attribute delete functions return failure, the
        -: 1054:       communicator must not be freed.  That is the reason for the
        -: 1055:       test on mpi_errno here. */
  1667695: 1056:    if (mpi_errno == MPI_SUCCESS) {
        -: 1057:        /* If this communicator is our parent, and we're disconnecting
        -: 1058:           from the parent, mark that fact */
  1667693: 1059:        if (MPIR_Process.comm_parent == comm_ptr)
      406: 1060:            MPIR_Process.comm_parent = NULL;
        -: 1061:
        -: 1062:        /* Notify the device that the communicator is about to be
        -: 1063:           destroyed */
        -: 1064:        MPID_Dev_comm_destroy_hook(comm_ptr);
        -: 1065:
        -: 1066:        /* Free the VCRT */
  1667693: 1067:        mpi_errno = MPID_VCRT_Release(comm_ptr->vcrt, isDisconnect);
  1667693: 1068:        if (mpi_errno != MPI_SUCCESS) {
    #####: 1069:            MPIU_ERR_POP(mpi_errno);
        -: 1070:        }
  1667693: 1071:        if (comm_ptr->comm_kind == MPID_INTERCOMM) {
     7568: 1072:            mpi_errno = MPID_VCRT_Release(
        -: 1073:                                          comm_ptr->local_vcrt, isDisconnect);
     7568: 1074:            if (mpi_errno != MPI_SUCCESS) {
    #####: 1075:                MPIU_ERR_POP(mpi_errno);
        -: 1076:            }
     7568: 1077:            if (comm_ptr->local_comm)
     2331: 1078:                MPIR_Comm_release(comm_ptr->local_comm, isDisconnect );
        -: 1079:        }
        -: 1080:
        -: 1081:        /* Free the local and remote groups, if they exist */
  1667693: 1082:        if (comm_ptr->local_group)
     8899: 1083:            MPIR_Group_release(comm_ptr->local_group);
  1667693: 1084:        if (comm_ptr->remote_group)
     4252: 1085:            MPIR_Group_release(comm_ptr->remote_group);
        -: 1086:
        -: 1087:        /* free the intra/inter-node communicators, if they exist */
  1667693: 1088:        if (comm_ptr->node_comm)
   654594: 1089:            MPIR_Comm_release(comm_ptr->node_comm, isDisconnect);
  1667693: 1090:        if (comm_ptr->node_roots_comm)
   308989: 1091:            MPIR_Comm_release(comm_ptr->node_roots_comm, isDisconnect);
  1667693: 1092:        if (comm_ptr->intranode_table != NULL)
   692105: 1093:            MPIU_Free(comm_ptr->intranode_table);
  1667693: 1094:        if (comm_ptr->internode_table != NULL)
   692105: 1095:            MPIU_Free(comm_ptr->internode_table);
        -: 1096:
        -: 1097:        /* Free the context value.  This should come after freeing the
        -: 1098:         * intra/inter-node communicators since those free calls won't
        -: 1099:         * release this context ID and releasing this before then could lead
        -: 1100:         * to races once we make threading finer grained. */
        -: 1101:        /* This must be the recvcontext_id (i.e. not the (send)context_id)
        -: 1102:         * because in the case of intercommunicators the send context ID is
        -: 1103:         * allocated out of the remote group's bit vector, not ours. */
  1667693: 1104:        MPIR_Free_contextid( comm_ptr->recvcontext_id );
        -: 1105:
        -: 1106:        /* We need to release the error handler */
  1667693: 1107:        if (comm_ptr->errhandler &&
        -: 1108:            ! (HANDLE_GET_KIND(comm_ptr->errhandler->handle) ==
        -: 1109:               HANDLE_KIND_BUILTIN) ) {
        -: 1110:            int errhInuse;
     6010: 1111:            MPIR_Errhandler_release_ref( comm_ptr->errhandler,&errhInuse);
     6010: 1112:            if (!errhInuse) {
     4006: 1113:                MPIU_Handle_obj_free( &MPID_Errhandler_mem,
        -: 1114:                                      comm_ptr->errhandler );
        -: 1115:            }
        -: 1116:        }
        -: 1117:
        -: 1118:        /* Check for predefined communicators - these should not
        -: 1119:           be freed */
  1667693: 1120:        if (! (HANDLE_GET_KIND(comm_ptr->handle) == HANDLE_KIND_BUILTIN) )
  1654581: 1121:            MPIU_Handle_obj_free( &MPID_Comm_mem, comm_ptr );
        -: 1122:
        -: 1123:        /* Remove from the list of active communicators if
        -: 1124:           we are supporting message-queue debugging.  We make this
        -: 1125:           conditional on having debugger support since the
        -: 1126:           operation is not constant-time */
        -: 1127:        MPIR_COMML_FORGET( comm_ptr );
        -: 1128:    }
        -: 1129:    else {
        -: 1130:        /* If the user attribute free function returns an error,
        -: 1131:           then do not free the communicator */
        2: 1132:        MPIR_Comm_add_ref( comm_ptr );
        -: 1133:    }
        -: 1134:
  1667695: 1135: fn_exit:
        -: 1136:    MPID_MPI_FUNC_EXIT(MPID_STATE_COMM_DELETE);
  1667695: 1137:    return mpi_errno;
        -: 1138: fn_fail:
        -: 1139:    goto fn_exit;
        -: 1140:}
        -: 1141:
        -: 1142:/* Release a reference to a communicator.  If there are no pending
        -: 1143:   references, delete the communicator and recover all storage and 
        -: 1144:   context ids */
        -: 1145:#undef FUNCNAME 
        -: 1146:#define FUNCNAME MPIR_Comm_release
        -: 1147:#undef FCNAME
        -: 1148:#define FCNAME "MPIR_Comm_release"
        -: 1149:int MPIR_Comm_release(MPID_Comm * comm_ptr, int isDisconnect)
 27236309: 1150:{
 27236309: 1151:    int mpi_errno = MPI_SUCCESS;
        -: 1152:    int in_use;
        -: 1153:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_RELEASE);
        -: 1154:
        -: 1155:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_RELEASE);
        -: 1156:
 27236309: 1157:    MPIR_Comm_release_ref(comm_ptr, &in_use);
 27236309: 1158:    if (!in_use) {
  1654584: 1159:        mpi_errno = comm_delete(comm_ptr, isDisconnect);
  1654584: 1160:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -: 1161:    }
        -: 1162:
 27236309: 1163: fn_exit:
        -: 1164:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_RELEASE);
 27236309: 1165:    return mpi_errno;
        -: 1166: fn_fail:
        -: 1167:    goto fn_exit;
        -: 1168:}
        -: 1169:
        -: 1170:/* Release a reference to a communicator.  If there are no pending
        -: 1171:   references, delete the communicator and recover all storage and
        -: 1172:   context ids.  This version of the function always manipulates the reference
        -: 1173:   counts, even for predefined objects. */
        -: 1174:#undef FUNCNAME
        -: 1175:#define FUNCNAME MPIR_Comm_release_always
        -: 1176:#undef FCNAME
        -: 1177:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -: 1178:int MPIR_Comm_release_always(MPID_Comm *comm_ptr, int isDisconnect)
    13122: 1179:{
    13122: 1180:    int mpi_errno = MPI_SUCCESS;
        -: 1181:    int in_use;
        -: 1182:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
        -: 1183:
        -: 1184:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
        -: 1185:
        -: 1186:    /* we want to short-circuit any optimization that avoids reference counting
        -: 1187:     * predefined communicators, such as MPI_COMM_WORLD or MPI_COMM_SELF. */
    13122: 1188:    MPIU_Object_release_ref_always(comm_ptr, &in_use);
    13122: 1189:    if (!in_use) {
    13111: 1190:        mpi_errno = comm_delete(comm_ptr, isDisconnect);
    13111: 1191:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -: 1192:    }
        -: 1193:
    13122: 1194: fn_exit:
        -: 1195:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
    13122: 1196:    return mpi_errno;
        -: 1197: fn_fail:
        -: 1198:    goto fn_exit;
        -: 1199:}
        -: 1200: