-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/comm/comm_create.c
        -:    0:Graph:comm_create.gcno
        -:    0:Data:comm_create.gcda
        -:    0:Runs:3765
        -:    0:Programs:1142
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *
        -:    4: *  (C) 2001 by Argonne National Laboratory.
        -:    5: *      See COPYRIGHT in top-level directory.
        -:    6: */
        -:    7:
        -:    8:#include "mpiimpl.h"
        -:    9:#include "mpicomm.h"
        -:   10:
        -:   11:/* -- Begin Profiling Symbol Block for routine MPI_Comm_create */
        -:   12:#if defined(HAVE_PRAGMA_WEAK)
        -:   13:#pragma weak MPI_Comm_create = PMPI_Comm_create
        -:   14:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
        -:   15:#pragma _HP_SECONDARY_DEF PMPI_Comm_create  MPI_Comm_create
        -:   16:#elif defined(HAVE_PRAGMA_CRI_DUP)
        -:   17:#pragma _CRI duplicate MPI_Comm_create as PMPI_Comm_create
        -:   18:#endif
        -:   19:/* -- End Profiling Symbol Block */
        -:   20:
        -:   21:/* prototypes to make the compiler happy in the case that PMPI_LOCAL expands to
        -:   22: * nothing instead of "static" */
        -:   23:PMPI_LOCAL int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
        -:   24:                                                  MPID_Comm   *comm_ptr,
        -:   25:                                                  MPID_VCR   **mapping_vcr_out,
        -:   26:                                                  int        **mapping_out);
        -:   27:
        -:   28:PMPI_LOCAL int MPIR_Comm_create_create_and_map_vcrt(int n,
        -:   29:                                                    int *mapping,
        -:   30:                                                    MPID_VCR *mapping_vcr,
        -:   31:                                                    MPID_VCRT *out_vcrt,
        -:   32:                                                    MPID_VCR **out_vcr);
        -:   33:
        -:   34:PMPI_LOCAL int MPIR_Comm_create_intra(MPID_Comm *comm_ptr, MPID_Group *group_ptr, MPI_Comm *newcomm);
        -:   35:PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr, MPI_Comm *newcomm);
        -:   36:
        -:   37:
        -:   38:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
        -:   39:   the MPI routines */
        -:   40:#ifndef MPICH_MPI_FROM_PMPI
        -:   41:#undef MPI_Comm_create
        -:   42:#define MPI_Comm_create PMPI_Comm_create
        -:   43:
        -:   44:/* This function allocates and calculates an array (*mapping_out) such that
        -:   45: * (*mapping_out)[i] is the rank in (*mapping_vcr_out) corresponding to local
        -:   46: * rank i in the given group_ptr.
        -:   47: *
        -:   48: * Ownership of the (*mapping_out) array is transferred to the caller who is
        -:   49: * responsible for freeing it. */
        -:   50:#undef FUNCNAME
        -:   51:#define FUNCNAME MPIR_Comm_create_calculate_mapping
        -:   52:#undef FCNAME
        -:   53:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:   54:PMPI_LOCAL int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
        -:   55:                                                  MPID_Comm   *comm_ptr,
        -:   56:                                                  MPID_VCR   **mapping_vcr_out,
        -:   57:                                                  int        **mapping_out)
     4392:   58:{
     4392:   59:    int mpi_errno = MPI_SUCCESS;
     4392:   60:    int subsetOfWorld = 0;
        -:   61:    int i, j;
        -:   62:    int n;
        -:   63:    int *mapping;
        -:   64:    int vcr_size;
        -:   65:    MPID_VCR *vcr;
     4392:   66:    MPIU_CHKPMEM_DECL(1);
        -:   67:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE_CALCULATE_MAPPING);
        -:   68:
        -:   69:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_CREATE_CALCULATE_MAPPING);
        -:   70:
     4392:   71:    *mapping_out = NULL;
     4392:   72:    *mapping_vcr_out = NULL;
        -:   73:
        -:   74:    /* N.B. For intracomms only the comm_ptr->vcr is valid and populated,
        -:   75:     * however local_size and remote_size are always set to the same value for
        -:   76:     * intracomms.  For intercomms both are valid and populated, with the
        -:   77:     * local_vcr holding VCs corresponding to the local_group, local_comm, and
        -:   78:     * local_size.
        -:   79:     *
        -:   80:     * For this mapping calculation we always want the logically local vcr,
        -:   81:     * regardless of whether it is stored in the "plain" vcr or local_vcr. */
     4392:   82:    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
      316:   83:        vcr      = comm_ptr->local_vcr;
      316:   84:        vcr_size = comm_ptr->local_size;
        -:   85:    }
        -:   86:    else {
     4076:   87:        vcr      = comm_ptr->vcr;
     4076:   88:        vcr_size = comm_ptr->remote_size;
        -:   89:    }
        -:   90:
     4392:   91:    n = group_ptr->size;
     4392:   92:    MPIU_CHKPMEM_MALLOC(mapping,int*,n*sizeof(int),mpi_errno,"mapping");
        -:   93:
        -:   94:    /* Make sure that the processes for this group are contained within
        -:   95:       the input communicator.  Also identify the mapping from the ranks of
        -:   96:       the old communicator to the new communicator.
        -:   97:       We do this by matching the lpids of the members of the group
        -:   98:       with the lpids of the members of the input communicator.
        -:   99:       It is an error if the group contains a reference to an lpid that
        -:  100:       does not exist in the communicator.
        -:  101:
        -:  102:       An important special case is groups (and communicators) that
        -:  103:       are subsets of MPI_COMM_WORLD.  In this case, the lpids are
        -:  104:       exactly the same as the ranks in comm world.
        -:  105:    */
        -:  106:
        -:  107:    /* we examine the group's lpids in both the intracomm and non-comm_world cases */
     4392:  108:    MPIR_Group_setup_lpid_list( group_ptr );
        -:  109:
        -:  110:    /* Optimize for groups contained within MPI_COMM_WORLD. */
     4392:  111:    if (comm_ptr->comm_kind == MPID_INTRACOMM) {
        -:  112:        int wsize;
     4076:  113:        subsetOfWorld = 1;
     4076:  114:        wsize         = MPIR_Process.comm_world->local_size;
   231902:  115:        for (i=0; i<n; i++) {
   111882:  116:            int g_lpid = group_ptr->lrank_to_lpid[i].lpid;
        -:  117:
        -:  118:            /* This mapping is relative to comm world */
        -:  119:            MPIU_DBG_MSG_FMT(COMM,VERBOSE,
        -:  120:                             (MPIU_DBG_FDEST,
        -:  121:                              "comm-create - mapping into world[%d] = %d\n",
        -:  122:                              i, g_lpid ));
   111882:  123:            if (g_lpid < wsize) {
   111875:  124:                mapping[i] = g_lpid;
        -:  125:            }
        -:  126:            else {
        7:  127:                subsetOfWorld = 0;
        7:  128:                break;
        -:  129:            }
        -:  130:        }
        -:  131:    }
        -:  132:    MPIU_DBG_MSG_D(COMM,VERBOSE, "subsetOfWorld=%d", subsetOfWorld );
     4392:  133:    if (subsetOfWorld) {
        -:  134:#           ifdef HAVE_ERROR_CHECKING
        -:  135:        {
        -:  136:            MPID_BEGIN_ERROR_CHECKS;
        -:  137:            {
        -:  138:                int idx;
     4069:  139:                mpi_errno = MPIR_GroupCheckVCRSubset( group_ptr, vcr_size, vcr, &idx );
     4069:  140:                if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  141:            }
        -:  142:            MPID_END_ERROR_CHECKS;
        -:  143:        }
        -:  144:#           endif
        -:  145:        /* Override the vcr to be used with the mapping array. */
     4067:  146:        vcr = MPIR_Process.comm_world->vcr;
     4067:  147:        vcr_size = MPIR_Process.comm_world->local_size;
        -:  148:    }
        -:  149:    else {
     1126:  150:        for (i=0; i<n; i++) {
        -:  151:            /* mapping[i] is the rank in the communicator of the process
        -:  152:               that is the ith element of the group */
        -:  153:            /* FIXME : BUBBLE SORT */
      803:  154:            mapping[i] = -1;
     2228:  155:            for (j=0; j<vcr_size; j++) {
        -:  156:                int comm_lpid;
     2228:  157:                MPID_VCR_Get_lpid( vcr[j], &comm_lpid );
     2228:  158:                if (comm_lpid == group_ptr->lrank_to_lpid[i].lpid) {
      803:  159:                    mapping[i] = j;
      803:  160:                    break;
        -:  161:                }
        -:  162:            }
      803:  163:            MPIU_ERR_CHKANDJUMP1(mapping[i] == -1,mpi_errno,MPI_ERR_GROUP,
        -:  164:                                 "**groupnotincomm", "**groupnotincomm %d", i );
        -:  165:        }
        -:  166:    }
        -:  167:
     4390:  168:    MPIU_Assert(vcr != NULL);
     4390:  169:    MPIU_Assert(mapping != NULL);
     4390:  170:    *mapping_vcr_out = vcr;
     4390:  171:    *mapping_out     = mapping;
        -:  172:    MPL_VG_CHECK_MEM_IS_DEFINED(*mapping_vcr_out, vcr_size * sizeof(**mapping_vcr_out));
        -:  173:    MPL_VG_CHECK_MEM_IS_DEFINED(*mapping_out, n * sizeof(**mapping_out));
        -:  174:
     4390:  175:    MPIU_CHKPMEM_COMMIT();
     4392:  176:fn_exit:
        -:  177:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_CREATE_CALCULATE_MAPPING);
     4392:  178:    return mpi_errno;
        -:  179:fn_fail:
        2:  180:    MPIU_CHKPMEM_REAP();
        -:  181:    goto fn_exit;
        -:  182:}
        -:  183:
        -:  184:/* This function creates a new VCRT and assigns it to out_vcrt, creates a new
        -:  185: * vcr and assigns it to out_vcr, and then populates it from the mapping_vcr
        -:  186: * array according to the rank mapping table provided.
        -:  187: *
        -:  188: * mapping[i] is the index in the old vcr of index i in the new vcr */
        -:  189:#undef FUNCNAME
        -:  190:#define FUNCNAME MPIR_Comm_create_and_map_vcrt
        -:  191:#undef FCNAME
        -:  192:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  193:PMPI_LOCAL int MPIR_Comm_create_create_and_map_vcrt(int         n,
        -:  194:                                                    int        *mapping,
        -:  195:                                                    MPID_VCR   *mapping_vcr,
        -:  196:                                                    MPID_VCRT  *out_vcrt,
        -:  197:                                                    MPID_VCR  **out_vcr)
     4488:  198:{
     4488:  199:    int mpi_errno = MPI_SUCCESS;
        -:  200:    int i;
     4488:  201:    MPID_VCR *vcr = NULL;
        -:  202:
     4488:  203:    MPID_VCRT_Create(n, out_vcrt);
     4488:  204:    MPID_VCRT_Get_ptr(*out_vcrt, out_vcr);
     4488:  205:    vcr = *out_vcr;
   117457:  206:    for (i=0; i<n; i++) {
        -:  207:        MPIU_DBG_MSG_FMT(COMM,VERBOSE,
        -:  208:                         (MPIU_DBG_FDEST, "dupping from mapping_vcr=%p rank=%d into new_rank=%d/%d in new_vcr=%p",
        -:  209:                          mapping_vcr, mapping[i], i, n, vcr));
   112969:  210:        mpi_errno = MPID_VCR_Dup(mapping_vcr[mapping[i]], &vcr[i]);
   112969:  211:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  212:    }
        -:  213:
     4488:  214:fn_fail:
     4488:  215:    return mpi_errno;
        -:  216:}
        -:  217:
        -:  218:
        -:  219:#undef FUNCNAME
        -:  220:#define FUNCNAME MPIR_Comm_create_intra
        -:  221:#undef FCNAME
        -:  222:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  223:/* comm create impl for intracommunicators, assumes that the standard error
        -:  224: * checking has already taken place in the calling function */
        -:  225:PMPI_LOCAL int MPIR_Comm_create_intra(MPID_Comm *comm_ptr, MPID_Group *group_ptr, MPI_Comm *newcomm)
    12241:  226:{
    12241:  227:    int mpi_errno = MPI_SUCCESS;
    12241:  228:    MPIR_Context_id_t new_context_id = 0;
    12241:  229:    MPID_Comm *newcomm_ptr = NULL;
    12241:  230:    int *mapping = NULL;
        -:  231:    int n;
        -:  232:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE_INTRA);
        -:  233:
        -:  234:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_CREATE_INTRA);
        -:  235:
    12241:  236:    MPIU_Assert(comm_ptr->comm_kind == MPID_INTRACOMM);
        -:  237:
    12241:  238:    n = group_ptr->size;
    12241:  239:    *newcomm = MPI_COMM_NULL;
        -:  240:
        -:  241:    /* Create a new communicator from the specified group members */
        -:  242:
        -:  243:    /* Creating the context id is collective over the *input* communicator,
        -:  244:       so it must be created before we decide if this process is a
        -:  245:       member of the group */
        -:  246:    /* In the multi-threaded case, MPIR_Get_contextid assumes that the
        -:  247:       calling routine already holds the single criticial section */
    12241:  248:    mpi_errno = MPIR_Get_contextid( comm_ptr, &new_context_id );
    12241:  249:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
    12241:  250:    MPIU_Assert(new_context_id != 0);
        -:  251:
    12241:  252:    if (group_ptr->rank != MPI_UNDEFINED) {
     4076:  253:        MPID_VCR *mapping_vcr = NULL;
        -:  254:
     4076:  255:        mpi_errno = MPIR_Comm_create_calculate_mapping(group_ptr, comm_ptr, &mapping_vcr, &mapping);
     4076:  256:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  257:
        -:  258:        /* Get the new communicator structure and context id */
        -:  259:
     4074:  260:        mpi_errno = MPIR_Comm_create( &newcomm_ptr );
     4074:  261:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  262:
     4074:  263:        newcomm_ptr->recvcontext_id = new_context_id;
     4074:  264:        newcomm_ptr->rank           = group_ptr->rank;
     4074:  265:        newcomm_ptr->comm_kind      = comm_ptr->comm_kind;
        -:  266:        /* Since the group has been provided, let the new communicator know
        -:  267:           about the group */
     4074:  268:        newcomm_ptr->local_comm     = 0;
     4074:  269:        newcomm_ptr->local_group    = group_ptr;
     4074:  270:        MPIR_Group_add_ref( group_ptr );
        -:  271:
     4074:  272:        newcomm_ptr->remote_group   = group_ptr;
     4074:  273:        MPIR_Group_add_ref( group_ptr );
     4074:  274:        newcomm_ptr->context_id     = newcomm_ptr->recvcontext_id;
     4074:  275:        newcomm_ptr->remote_size    = newcomm_ptr->local_size = n;
        -:  276:
        -:  277:        /* Setup the communicator's vc table.  This is for the remote group,
        -:  278:           which is the same as the local group for intracommunicators */
     4074:  279:        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(n,
        -:  280:                                                         mapping,
        -:  281:                                                         mapping_vcr,
        -:  282:                                                         &newcomm_ptr->vcrt,
        -:  283:                                                         &newcomm_ptr->vcr);
     4074:  284:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  285:
        -:  286:        /* Notify the device of this new communicator */
        -:  287:        MPID_Dev_comm_create_hook( newcomm_ptr );
     4074:  288:        mpi_errno = MPIR_Comm_commit(newcomm_ptr);
     4074:  289:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  290:
     4074:  291:        *newcomm = newcomm_ptr->handle;
        -:  292:    }
        -:  293:    else {
        -:  294:        /* This process is not in the group */
     8165:  295:        MPIR_Free_contextid( new_context_id );
     8165:  296:        new_context_id = 0;
        -:  297:    }
        -:  298:
    12241:  299:fn_exit:
    12241:  300:    if (mapping)
     4074:  301:        MPIU_Free(mapping);
        -:  302:
        -:  303:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_CREATE_INTRA);
    12241:  304:    return mpi_errno;
        2:  305:fn_fail:
        2:  306:    if (newcomm_ptr != NULL) {
    #####:  307:        MPIR_Comm_release(newcomm_ptr, 0/*isDisconnect*/);
    #####:  308:        new_context_id = 0; /* MPIR_Comm_release frees the new ctx id */
        -:  309:    }
        2:  310:    if (new_context_id != 0)
        2:  311:        MPIR_Free_contextid(new_context_id);
        2:  312:    *newcomm = MPI_COMM_NULL;
        -:  313:
        2:  314:    goto fn_exit;
        -:  315:}
        -:  316:
        -:  317:#undef FUNCNAME
        -:  318:#define FUNCNAME MPIR_Comm_create_inter
        -:  319:#undef FCNAME
        -:  320:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  321:/* comm create impl for intercommunicators, assumes that the standard error
        -:  322: * checking has already taken place in the calling function */
        -:  323:PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr, MPI_Comm *newcomm)
      316:  324:{
      316:  325:    int mpi_errno = MPI_SUCCESS;
        -:  326:    MPIR_Context_id_t new_context_id;
      316:  327:    MPID_Comm *newcomm_ptr = NULL;
      316:  328:    MPI_Comm comm = comm_ptr->handle;
      316:  329:    int *mapping = NULL;
      316:  330:    int *remote_mapping = NULL;
      316:  331:    int remote_size = -1;
        -:  332:    int rinfo[2];
      316:  333:    MPID_VCR *mapping_vcr = NULL;
      316:  334:    MPID_VCR *remote_mapping_vcr = NULL;
        -:  335:
      316:  336:    MPIU_THREADPRIV_DECL;
      316:  337:    MPIU_CHKLMEM_DECL(1);
        -:  338:    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE_INTER);
        -:  339:
        -:  340:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_CREATE_INTER);
      316:  341:    MPIU_THREADPRIV_GET;
        -:  342:
      316:  343:    MPIU_Assert(comm_ptr->comm_kind == MPID_INTERCOMM);
        -:  344:
        -:  345:    /* Create a new communicator from the specified group members */
        -:  346:
        -:  347:    /* If there is a context id cache in oldcomm, use it here.  Otherwise,
        -:  348:       use the appropriate algorithm to get a new context id. 
        -:  349:       Creating the context id is collective over the *input* communicator,
        -:  350:       so it must be created before we decide if this process is a 
        -:  351:       member of the group */
        -:  352:    /* In the multi-threaded case, MPIR_Get_contextid assumes that the
        -:  353:       calling routine already holds the single criticial section */
      316:  354:    if (!comm_ptr->local_comm) {
      263:  355:        MPIR_Setup_intercomm_localcomm( comm_ptr );
        -:  356:    }
      316:  357:    mpi_errno = MPIR_Get_contextid( comm_ptr->local_comm, &new_context_id );
      316:  358:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
      316:  359:    MPIU_Assert(new_context_id != 0);
      316:  360:    MPIU_Assert(new_context_id != comm_ptr->recvcontext_id);
        -:  361:
      316:  362:    remote_mapping_vcr = comm_ptr->vcr;
        -:  363:
      316:  364:    mpi_errno = MPIR_Comm_create_calculate_mapping(group_ptr, comm_ptr, &mapping_vcr, &mapping);
      316:  365:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  366:
      316:  367:    if (group_ptr->rank != MPI_UNDEFINED) {
        -:  368:        /* Get the new communicator structure and context id */
      207:  369:        mpi_errno = MPIR_Comm_create( &newcomm_ptr );
      207:  370:        if (mpi_errno) goto fn_fail;
        -:  371:
      207:  372:        newcomm_ptr->recvcontext_id = new_context_id;
      207:  373:        newcomm_ptr->rank           = group_ptr->rank;
      207:  374:        newcomm_ptr->comm_kind      = comm_ptr->comm_kind;
        -:  375:        /* Since the group has been provided, let the new communicator know
        -:  376:           about the group */
      207:  377:        newcomm_ptr->local_comm     = 0;
      207:  378:        newcomm_ptr->local_group    = group_ptr;
      207:  379:        MPIR_Group_add_ref( group_ptr );
        -:  380:
      207:  381:        newcomm_ptr->local_size   = group_ptr->size;
      207:  382:        newcomm_ptr->remote_group = 0;
        -:  383:
      207:  384:        newcomm_ptr->is_low_group = comm_ptr->is_low_group;
        -:  385:    }
        -:  386:
        -:  387:    /* There is an additional step.  We must communicate the information
        -:  388:       on the local context id and the group members, given by the ranks
        -:  389:       so that the remote process can construct the appropriate VCRT
        -:  390:       First we exchange group sizes and context ids.  Then the
        -:  391:       ranks in the remote group, from which the remote VCRT can
        -:  392:       be constructed.  We can't use NMPI_Sendrecv since we need to
        -:  393:       use the "collective" context in the original intercommunicator */
      316:  394:    if (comm_ptr->rank == 0) {
        -:  395:        int info[2];
       98:  396:        info[0] = new_context_id;
       98:  397:        info[1] = group_ptr->size;
        -:  398:
       98:  399:        mpi_errno = MPIC_Sendrecv(info, 2, MPI_INT, 0, 0,
        -:  400:                                  rinfo, 2, MPI_INT, 0, 0,
        -:  401:                                  comm, MPI_STATUS_IGNORE );
       98:  402:        if (mpi_errno) { MPIU_ERR_POP( mpi_errno ); }
       98:  403:        if (newcomm_ptr != NULL) {
       28:  404:            newcomm_ptr->context_id = rinfo[0];
        -:  405:        }
       98:  406:        remote_size = rinfo[1];
        -:  407:
       98:  408:        MPIU_CHKLMEM_MALLOC(remote_mapping,int*,
        -:  409:                            remote_size*sizeof(int),
        -:  410:                            mpi_errno,"remote_mapping");
        -:  411:
        -:  412:        /* Populate and exchange the ranks */
       98:  413:        mpi_errno = MPIC_Sendrecv( mapping, group_ptr->size, MPI_INT, 0, 0,
        -:  414:                                   remote_mapping, remote_size, MPI_INT, 0, 0,
        -:  415:                                   comm, MPI_STATUS_IGNORE );
       98:  416:        if (mpi_errno) { MPIU_ERR_POP( mpi_errno ); }
        -:  417:
        -:  418:        /* Broadcast to the other members of the local group */
       98:  419:        MPIR_Nest_incr();
       98:  420:        NMPI_Bcast( rinfo, 2, MPI_INT, 0,
        -:  421:                    comm_ptr->local_comm->handle );
       98:  422:        NMPI_Bcast( remote_mapping, remote_size, MPI_INT, 0,
        -:  423:                    comm_ptr->local_comm->handle );
       98:  424:        MPIR_Nest_decr();
        -:  425:    }
        -:  426:    else {
        -:  427:        /* The other processes */
        -:  428:        /* Broadcast to the other members of the local group */
      218:  429:        MPIR_Nest_incr();
      218:  430:        NMPI_Bcast( rinfo, 2, MPI_INT, 0,
        -:  431:                    comm_ptr->local_comm->handle );
      218:  432:        if (newcomm_ptr != NULL) {
      179:  433:            newcomm_ptr->context_id = rinfo[0];
        -:  434:        }
      218:  435:        remote_size = rinfo[1];
      218:  436:        MPIU_CHKLMEM_MALLOC(remote_mapping,int*,
        -:  437:                            remote_size*sizeof(int),
        -:  438:                            mpi_errno,"remote_mapping");
      218:  439:        NMPI_Bcast( remote_mapping, remote_size, MPI_INT, 0,
        -:  440:                    comm_ptr->local_comm->handle );
      218:  441:        MPIR_Nest_decr();
        -:  442:    }
        -:  443:
      316:  444:    if (group_ptr->rank != MPI_UNDEFINED) {
      207:  445:        newcomm_ptr->remote_size    = remote_size;
        -:  446:        /* Now, everyone has the remote_mapping, and can apply that to
        -:  447:           the vcr table. */
        -:  448:
        -:  449:        /* Setup the communicator's local vc table from the local mapping. */
      207:  450:        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(group_ptr->size,
        -:  451:                                                         mapping,
        -:  452:                                                         mapping_vcr,
        -:  453:                                                         &newcomm_ptr->local_vcrt,
        -:  454:                                                         &newcomm_ptr->local_vcr);
        -:  455:
        -:  456:        /* Setup the communicator's vc table.  This is for the remote group */
      207:  457:        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(remote_size,
        -:  458:                                                         remote_mapping,
        -:  459:                                                         remote_mapping_vcr,
        -:  460:                                                         &newcomm_ptr->vcrt,
        -:  461:                                                         &newcomm_ptr->vcr);
        -:  462:
        -:  463:        /* Notify the device of this new communicator */
        -:  464:        MPID_Dev_comm_create_hook( newcomm_ptr );
      207:  465:        mpi_errno = MPIR_Comm_commit(newcomm_ptr);
      207:  466:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  467:
      207:  468:        *newcomm = newcomm_ptr->handle;
        -:  469:    }
        -:  470:    else {
        -:  471:        /* This process is not in the group */
      109:  472:        MPIR_Free_contextid( new_context_id );
      109:  473:        *newcomm = MPI_COMM_NULL;
        -:  474:    }
        -:  475:
        -:  476:fn_exit:
      316:  477:    MPIU_CHKLMEM_FREEALL();
      316:  478:    if (mapping)
      316:  479:        MPIU_Free(mapping);
        -:  480:
        -:  481:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_CREATE_INTER);
      316:  482:    return mpi_errno;
        -:  483:fn_fail:
        -:  484:    goto fn_exit;
        -:  485:}
        -:  486:
        -:  487:#endif /* !defined(MPICH_MPI_FROM_PMPI) */
        -:  488:
        -:  489:#undef FUNCNAME
        -:  490:#define FUNCNAME MPI_Comm_create
        -:  491:#undef FCNAME
        -:  492:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  493:/*@
        -:  494:
        -:  495:MPI_Comm_create - Creates a new communicator
        -:  496:
        -:  497:Input Parameters:
        -:  498:+ comm - communicator (handle) 
        -:  499:- group - group, which is a subset of the group of 'comm'  (handle) 
        -:  500:
        -:  501:Output Parameter:
        -:  502:. comm_out - new communicator (handle) 
        -:  503:
        -:  504:.N ThreadSafe
        -:  505:
        -:  506:.N Fortran
        -:  507:
        -:  508:.N Errors
        -:  509:.N MPI_SUCCESS
        -:  510:.N MPI_ERR_COMM
        -:  511:.N MPI_ERR_GROUP
        -:  512:
        -:  513:.seealso: MPI_Comm_free
        -:  514:@*/
        -:  515:int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm)
    12564:  516:{
    12564:  517:    int mpi_errno = MPI_SUCCESS;
    12564:  518:    MPID_Comm *comm_ptr = NULL;
        -:  519:    MPID_Group *group_ptr;
    12564:  520:    MPIU_THREADPRIV_DECL;
        -:  521:    MPID_MPI_STATE_DECL(MPID_STATE_MPI_COMM_CREATE);
        -:  522:
    12564:  523:    MPIR_ERRTEST_INITIALIZED_ORDIE();
        -:  524:
    12564:  525:    MPIU_THREAD_CS_ENTER(ALLFUNC,);
        -:  526:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_COMM_CREATE);
        -:  527:
        -:  528:    /* Validate parameters, and convert MPI object handles to object pointers */
        -:  529:#   ifdef HAVE_ERROR_CHECKING
        -:  530:    {
        -:  531:        MPID_BEGIN_ERROR_CHECKS;
        -:  532:        {
    12564:  533:	    MPIR_ERRTEST_COMM(comm, mpi_errno);
    12564:  534:            if (mpi_errno) goto fn_fail;
        -:  535:	}
        -:  536:        MPID_END_ERROR_CHECKS;
        -:  537:	
    12563:  538:	MPID_Comm_get_ptr( comm, comm_ptr );
        -:  539:	
        -:  540:        MPID_BEGIN_ERROR_CHECKS;
        -:  541:        {
        -:  542:            /* Validate comm_ptr */
    12563:  543:            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
        -:  544:	    /* If comm_ptr is not valid, it will be reset to null */
        -:  545:
    12563:  546:	    MPIR_ERRTEST_GROUP(group, mpi_errno);
    12557:  547:            if (mpi_errno) goto fn_fail;
        -:  548:	}
        -:  549:        MPID_END_ERROR_CHECKS;
        -:  550:	
    12557:  551:	MPID_Group_get_ptr( group, group_ptr );
        -:  552:
        -:  553:        MPID_BEGIN_ERROR_CHECKS;
        -:  554:        {
        -:  555:	    /* Check the group ptr */
    12557:  556:	    MPID_Group_valid_ptr( group_ptr, mpi_errno );
    12557:  557:            if (mpi_errno) goto fn_fail;
        -:  558:        }
        -:  559:        MPID_END_ERROR_CHECKS;
        -:  560:    }
        -:  561:#   else
        -:  562:    {
        -:  563:	MPID_Comm_get_ptr( comm, comm_ptr );
        -:  564:	MPID_Group_get_ptr( group, group_ptr );
        -:  565:    }
        -:  566:#   endif
        -:  567:
        -:  568:    /* ... body of routine ...  */
    12557:  569:    if (comm_ptr->comm_kind == MPID_INTRACOMM) {
    12241:  570:        mpi_errno = MPIR_Comm_create_intra(comm_ptr, group_ptr, newcomm);
    12241:  571:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  572:    }
        -:  573:    else {
      316:  574:        MPIU_Assert(comm_ptr->comm_kind == MPID_INTERCOMM);
      316:  575:        mpi_errno = MPIR_Comm_create_inter(comm_ptr, group_ptr, newcomm);
      316:  576:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  577:    }
        -:  578:    /* ... end of body of routine ... */
        -:  579:
    12564:  580:  fn_exit:
        -:  581:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_COMM_CREATE);
    12564:  582:    MPIU_THREAD_CS_EXIT(ALLFUNC,);
    12564:  583:    return mpi_errno;
        -:  584:
        9:  585:  fn_fail:
        -:  586:    /* --BEGIN ERROR HANDLING-- */
        -:  587:#   ifdef HAVE_ERROR_CHECKING
        -:  588:    {
        9:  589:	mpi_errno = MPIR_Err_create_code(
        -:  590:	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_comm_create",
        -:  591:	    "**mpi_comm_create %C %G %p", comm, group, newcomm);
        -:  592:    }
        -:  593:#   endif
        9:  594:    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
        9:  595:    goto fn_exit;
        -:  596:    /* --END ERROR HANDLING-- */
        -:  597:}
        -:  598: