-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/ch3/src/mpid_init.c
        -:    0:Graph:mpid_init.gcno
        -:    0:Data:mpid_init.gcda
        -:    0:Runs:3459
        -:    0:Programs:899
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *  (C) 2001 by Argonne National Laboratory.
        -:    4: *      See COPYRIGHT in top-level directory.
        -:    5: */
        -:    6:
        -:    7:#include "mpidimpl.h"
        -:    8:
        -:    9:#define MAX_JOBID_LEN 1024
        -:   10:
        -:   11:#if defined(HAVE_LIMITS_H)
        -:   12:#include <limits.h>
        -:   13:#endif
        -:   14:#if defined(HAVE_UNISTD_H)
        -:   15:#include <unistd.h>
        -:   16:#endif
        -:   17:
        -:   18:/* FIXME: This does not belong here */
        -:   19:#ifdef USE_MPIU_DBG_PRINT_VC
        -:   20:char *MPIU_DBG_parent_str = "?";
        -:   21:#endif
        -:   22:
        -:   23:/* FIXME: the PMI init function should ONLY do the PMI operations, not the 
        -:   24:   process group or bc operations.  These should be in a separate routine */
        -:   25:#ifdef USE_PMI2_API
        -:   26:#include "pmi2.h"
        -:   27:#else
        -:   28:#include "pmi.h"
        -:   29:#endif
        -:   30:
        -:   31:int MPIDI_Use_pmi2_api = 0;
        -:   32:
        -:   33:static int InitPG( int *argc_p, char ***argv_p,
        -:   34:		   int *has_args, int *has_env, int *has_parent, 
        -:   35:		   int *pg_rank_p, MPIDI_PG_t **pg_p );
        -:   36:static int MPIDI_CH3I_PG_Compare_ids(void * id1, void * id2);
        -:   37:static int MPIDI_CH3I_PG_Destroy(MPIDI_PG_t * pg );
        -:   38:
        -:   39:MPIDI_Process_t MPIDI_Process = { NULL };
        -:   40:MPIDI_CH3U_SRBuf_element_t * MPIDI_CH3U_SRBuf_pool = NULL;
        -:   41:
        -:   42:#undef FUNCNAME
        -:   43:#define FUNCNAME MPID_Init
        -:   44:#undef FCNAME
        -:   45:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   46:int MPID_Init(int *argc, char ***argv, int requested, int *provided, 
        -:   47:	      int *has_args, int *has_env)
     3459:   48:{
     3459:   49:    int mpi_errno = MPI_SUCCESS;
        -:   50:    int has_parent;
     3459:   51:    MPIDI_PG_t * pg=NULL;
     3459:   52:    int pg_rank=-1;
        -:   53:    int pg_size;
        -:   54:    MPID_Comm * comm;
        -:   55:    int p;
        -:   56:    MPIDI_STATE_DECL(MPID_STATE_MPID_INIT);
        -:   57:
        -:   58:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_INIT);
        -:   59:
        -:   60:    /* FIXME: This is a good place to check for environment variables
        -:   61:       and command line options that may control the device */
     3459:   62:    MPIDI_Use_pmi2_api = FALSE;
        -:   63:#ifdef USE_PMI2_API
        -:   64:    MPIDI_Use_pmi2_api = TRUE;
        -:   65:#else
        -:   66:    {
        -:   67:        int ret, val;
     3459:   68:        ret = MPIU_GetEnvBool("MPICH_USE_PMI2_API", &val);
     3459:   69:        if (ret == 1 && val)
    #####:   70:            MPIDI_Use_pmi2_api = TRUE;
        -:   71:    }
        -:   72:#endif
        -:   73:    
        -:   74:#if 1
        -:   75:    /* This is a sanity check because we define a generic packet size
        -:   76:     */
        -:   77:    if (sizeof(MPIDI_CH3_PktGeneric_t) < sizeof(MPIDI_CH3_Pkt_t)) {
        -:   78:	fprintf( stderr, "Internal error - packet definition is too small.  Generic is %ld bytes, MPIDI_CH3_Pkt_t is %ld\n", (long int)sizeof(MPIDI_CH3_PktGeneric_t),
        -:   79:		 (long int)sizeof(MPIDI_CH3_Pkt_t) );
        -:   80:	exit(1);
        -:   81:    }
        -:   82:#endif
        -:   83:
        -:   84:    /*
        -:   85:     * Set global process attributes.  These can be overridden by the channel 
        -:   86:     * if necessary.
        -:   87:     */
     3459:   88:    MPIR_Process.attrs.tag_ub          = MPIDI_TAG_UB;
        -:   89:
        -:   90:    /* If the channel requires any setup before making any other 
        -:   91:       channel calls (including CH3_PG_Init), the channel will define
        -:   92:       this routine (the dynamically loaded channel uses this) */
        -:   93:#ifdef HAVE_CH3_PRELOAD
        -:   94:    mpi_errno = MPIDI_CH3_PreLoad();
        -:   95:    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
        -:   96:#endif
        -:   97:    /*
        -:   98:     * Perform channel-independent PMI initialization
        -:   99:     */
     3459:  100:    mpi_errno = InitPG( argc, argv, 
        -:  101:			has_args, has_env, &has_parent, &pg_rank, &pg );
     3459:  102:    if (mpi_errno) {
    #####:  103:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**ch3|ch3_init");
        -:  104:    }
        -:  105:    
        -:  106:    /* FIXME: Why are pg_size and pg_rank handled differently? */
     3459:  107:    pg_size = MPIDI_PG_Get_size(pg);
     3459:  108:    MPIDI_Process.my_pg = pg;  /* brad : this is rework for shared memories 
        -:  109:				* because they need this set earlier
        -:  110:                                * for getting the business card
        -:  111:                                */
     3459:  112:    MPIDI_Process.my_pg_rank = pg_rank;
        -:  113:    /* FIXME: Why do we add a ref to pg here? */
     3459:  114:    MPIDI_PG_add_ref(pg);
        -:  115:
        -:  116:    /* We intentionally call this before the channel init so that the channel
        -:  117:       can use the node_id info. */
        -:  118:    /* Ideally this wouldn't be needed.  Once we have PMIv2 support for node
        -:  119:       information we should probably eliminate this function. */
     3459:  120:    mpi_errno = MPIDI_Populate_vc_node_ids(pg, pg_rank);
     3459:  121:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  122:
        -:  123:    /* Initialize FTB after PMI init */
     3459:  124:    mpi_errno = MPIDU_Ftb_init();
     3459:  125:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  126:    
        -:  127:    /*
        -:  128:     * Let the channel perform any necessary initialization
        -:  129:     * The channel init should assume that PMI_Init has been called and that
        -:  130:     * the basic information about the job has been extracted from PMI (e.g.,
        -:  131:     * the size and rank of this process, and the process group id)
        -:  132:     */
     3459:  133:    mpi_errno = MPIU_CALL(MPIDI_CH3,Init(has_parent, pg, pg_rank));
     3459:  134:    if (mpi_errno != MPI_SUCCESS) {
    #####:  135:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**ch3|ch3_init");
        -:  136:    }
        -:  137:
        -:  138:    /*
        -:  139:     * Initialize the MPI_COMM_WORLD object
        -:  140:     */
     3459:  141:    comm = MPIR_Process.comm_world;
        -:  142:
     3459:  143:    comm->rank        = pg_rank;
     3459:  144:    comm->remote_size = pg_size;
     3459:  145:    comm->local_size  = pg_size;
        -:  146:    
     3459:  147:    mpi_errno = MPID_VCRT_Create(comm->remote_size, &comm->vcrt);
     3459:  148:    if (mpi_errno != MPI_SUCCESS)
        -:  149:    {
    #####:  150:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,"**dev|vcrt_create", 
        -:  151:			     "**dev|vcrt_create %s", "MPI_COMM_WORLD");
        -:  152:    }
        -:  153:    
     3459:  154:    mpi_errno = MPID_VCRT_Get_ptr(comm->vcrt, &comm->vcr);
     3459:  155:    if (mpi_errno != MPI_SUCCESS)
        -:  156:    {
    #####:  157:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,"**dev|vcrt_get_ptr", 
        -:  158:			     "dev|vcrt_get_ptr %s", "MPI_COMM_WORLD");
        -:  159:    }
        -:  160:    
        -:  161:    /* Initialize the connection table on COMM_WORLD from the process group's
        -:  162:       connection table */
    19587:  163:    for (p = 0; p < pg_size; p++)
        -:  164:    {
    16128:  165:	MPID_VCR_Dup(&pg->vct[p], &comm->vcr[p]);
        -:  166:    }
        -:  167:
        -:  168:    MPID_Dev_comm_create_hook (comm);
     3459:  169:    mpi_errno = MPIR_Comm_commit(comm);
     3459:  170:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  171:
        -:  172:    /*
        -:  173:     * Initialize the MPI_COMM_SELF object
        -:  174:     */
     3459:  175:    comm = MPIR_Process.comm_self;
     3459:  176:    comm->rank        = 0;
     3459:  177:    comm->remote_size = 1;
     3459:  178:    comm->local_size  = 1;
        -:  179:    
     3459:  180:    mpi_errno = MPID_VCRT_Create(comm->remote_size, &comm->vcrt);
     3459:  181:    if (mpi_errno != MPI_SUCCESS)
        -:  182:    {
    #####:  183:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**dev|vcrt_create", 
        -:  184:			     "**dev|vcrt_create %s", "MPI_COMM_SELF");
        -:  185:    }
        -:  186:    
     3459:  187:    mpi_errno = MPID_VCRT_Get_ptr(comm->vcrt, &comm->vcr);
     3459:  188:    if (mpi_errno != MPI_SUCCESS)
        -:  189:    {
    #####:  190:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**dev|vcrt_get_ptr", 
        -:  191:			     "dev|vcrt_get_ptr %s", "MPI_COMM_WORLD");
        -:  192:    }
        -:  193:    
     3459:  194:    MPID_VCR_Dup(&pg->vct[pg_rank], &comm->vcr[0]);
        -:  195:
        -:  196:    /* Currently, mpidpre.h always defines MPID_NEEDS_ICOMM_WORLD. */
        -:  197:#ifdef MPID_NEEDS_ICOMM_WORLD
        -:  198:    /*
        -:  199:     * Initialize the MPIR_ICOMM_WORLD object (an internal, private version
        -:  200:     * of MPI_COMM_WORLD) 
        -:  201:     */
     3459:  202:    comm = MPIR_Process.icomm_world;
        -:  203:
     3459:  204:    comm->rank        = pg_rank;
     3459:  205:    comm->remote_size = pg_size;
     3459:  206:    comm->local_size  = pg_size;
        -:  207:#if 0    
        -:  208:    mpi_errno = MPID_VCRT_Create(comm->remote_size, &comm->vcrt);
        -:  209:    if (mpi_errno != MPI_SUCCESS)
        -:  210:    {
        -:  211:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,"**dev|vcrt_create", 
        -:  212:			     "**dev|vcrt_create %s", "MPI_COMM_WORLD");
        -:  213:    }
        -:  214:    
        -:  215:    mpi_errno = MPID_VCRT_Get_ptr(comm->vcrt, &comm->vcr);
        -:  216:    if (mpi_errno != MPI_SUCCESS)
        -:  217:    {
        -:  218:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,"**dev|vcrt_get_ptr", 
        -:  219:			     "dev|vcrt_get_ptr %s", "MPI_COMM_WORLD");
        -:  220:    }
        -:  221:    
        -:  222:    /* Initialize the connection table on COMM_WORLD from the process group's
        -:  223:       connection table */
        -:  224:    for (p = 0; p < pg_size; p++)
        -:  225:    {
        -:  226:	MPID_VCR_Dup(&pg->vct[p], &comm->vcr[p]);
        -:  227:    }
        -:  228:#endif
     3459:  229:    MPID_VCRT_Add_ref( MPIR_Process.comm_world->vcrt );
     3459:  230:    comm->vcrt = MPIR_Process.comm_world->vcrt;
     3459:  231:    comm->vcr  = MPIR_Process.comm_world->vcr;
        -:  232:    
        -:  233:    MPID_Dev_comm_create_hook (comm);
     3459:  234:    mpi_errno = MPIR_Comm_commit(comm);
     3459:  235:    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  236:#endif
        -:  237:    
        -:  238:    /*
        -:  239:     * If this process group was spawned by a MPI application, then
        -:  240:     * form the MPI_COMM_PARENT inter-communicator.
        -:  241:     */
        -:  242:
        -:  243:    /*
        -:  244:     * FIXME: The code to handle the parent case should be in a separate 
        -:  245:     * routine and should not rely on #ifdefs
        -:  246:     */
        -:  247:#ifndef MPIDI_CH3_HAS_NO_DYNAMIC_PROCESS
     3459:  248:    if (has_parent) {
        -:  249:	char * parent_port;
        -:  250:
        -:  251:	/* FIXME: To allow just the "root" process to 
        -:  252:	   request the port and then use MPIR_Bcast to 
        -:  253:	   distribute it to the rest of the processes,
        -:  254:	   we need to perform the Bcast after MPI is
        -:  255:	   otherwise initialized.  We could do this
        -:  256:	   by adding another MPID call that the MPI_Init(_thread)
        -:  257:	   routine would make after the rest of MPI is 
        -:  258:	   initialized, but before MPI_Init returns.
        -:  259:	   In fact, such a routine could be used to 
        -:  260:	   perform various checks, including parameter
        -:  261:	   consistency value (e.g., all processes have the
        -:  262:	   same environment variable values). Alternately,
        -:  263:	   we could allow a few routines to operate with 
        -:  264:	   predefined parameter choices (e.g., bcast, allreduce)
        -:  265:	   for the purposes of initialization. */
      406:  266:	mpi_errno = MPIDI_CH3_GetParentPort(&parent_port);
      406:  267:	if (mpi_errno != MPI_SUCCESS) {
    #####:  268:	    MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, 
        -:  269:				"**ch3|get_parent_port");
        -:  270:	}
        -:  271:	MPIU_DBG_MSG_S(CH3_CONNECT,VERBOSE,"Parent port is %s\n", parent_port);
        -:  272:	    
      406:  273:	mpi_errno = MPID_Comm_connect(parent_port, NULL, 0, 
        -:  274:				      MPIR_Process.comm_world, &comm);
      406:  275:	if (mpi_errno != MPI_SUCCESS) {
    #####:  276:	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,
        -:  277:				 "**ch3|conn_parent", 
        -:  278:				 "**ch3|conn_parent %s", parent_port);
        -:  279:	}
        -:  280:
      406:  281:	MPIR_Process.comm_parent = comm;
      406:  282:	MPIU_Assert(MPIR_Process.comm_parent != NULL);
      406:  283:	MPIU_Strncpy(comm->name, "MPI_COMM_PARENT", MPI_MAX_OBJECT_NAME);
        -:  284:	
        -:  285:	/* FIXME: Check that this intercommunicator gets freed in MPI_Finalize
        -:  286:	   if not already freed.  */
        -:  287:    }
        -:  288:#endif	
        -:  289:    
        -:  290:    /*
        -:  291:     * Set provided thread level
        -:  292:     */
     3459:  293:    if (provided != NULL)
        -:  294:    {
        -:  295:	/* This must be min(requested,MPICH_THREAD_LEVEL) if runtime
        -:  296:	   control of thread level is available */
     3459:  297:	*provided = (MPICH_THREAD_LEVEL < requested) ? 
        -:  298:	    MPICH_THREAD_LEVEL : requested;
        -:  299:    }
        -:  300:
     3459:  301:  fn_exit:
        -:  302:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_INIT);
     3459:  303:    return mpi_errno;
        -:  304:
        -:  305:    /* --BEGIN ERROR HANDLING-- */
        -:  306:  fn_fail:
        -:  307:    goto fn_exit;
        -:  308:    /* --END ERROR HANDLING-- */
        -:  309:}
        -:  310:
        -:  311:/* This allows each channel to perform final initialization after the
        -:  312: rest of MPI_Init completes.  */
        -:  313:int MPID_InitCompleted( void )
     3459:  314:{
        -:  315:    int mpi_errno;
     3459:  316:    mpi_errno = MPIU_CALL(MPIDI_CH3,InitCompleted());
     3459:  317:    return mpi_errno;
        -:  318:}
        -:  319:
        -:  320:/*
        -:  321: * Initialize the process group structure by using PMI calls.
        -:  322: * This routine initializes PMI and uses PMI calls to setup the 
        -:  323: * process group structures.
        -:  324: * 
        -:  325: */
        -:  326:static int InitPG( int *argc, char ***argv, 
        -:  327:		   int *has_args, int *has_env, int *has_parent, 
        -:  328:		   int *pg_rank_p, MPIDI_PG_t **pg_p )
     3459:  329:{
        -:  330:    int pmi_errno;
     3459:  331:    int mpi_errno = MPI_SUCCESS;
        -:  332:    int pg_rank, pg_size, appnum, pg_id_sz;
     3459:  333:    int usePMI=1;
        -:  334:    char *pg_id;
     3459:  335:    MPIDI_PG_t *pg = 0;
        -:  336:
        -:  337:    /* See if the channel will provide the PMI values.  The channel
        -:  338:     is responsible for defining HAVE_CH3_PRE_INIT and providing 
        -:  339:    the MPIDI_CH3_Pre_init function.  */
        -:  340:    /* FIXME: Document this */
        -:  341:#ifdef HAVE_CH3_PRE_INIT
        -:  342:    {
        -:  343:	int setvals;
        -:  344:	mpi_errno = MPIDI_CH3_Pre_init( &setvals, has_parent, &pg_rank, 
        -:  345:					&pg_size );
        -:  346:	if (mpi_errno) {
        -:  347:	    goto fn_fail;
        -:  348:	}
        -:  349:	if (setvals) usePMI = 0;
        -:  350:    }
        -:  351:#endif 
        -:  352:
        -:  353:    /* If we use PMI here, make the PMI calls to get the
        -:  354:       basic values.  Note that systems that return setvals == true
        -:  355:       do not make use of PMI for the KVS routines either (it is
        -:  356:       assumed that the discover connection information through some
        -:  357:       other mechanism */
        -:  358:    /* FIXME: We may want to allow the channel to ifdef out the use
        -:  359:       of PMI calls, or ask the channel to provide stubs that 
        -:  360:       return errors if the routines are in fact used */
     3459:  361:    if (usePMI) {
        -:  362:	/*
        -:  363:	 * Initialize the process manangement interface (PMI), 
        -:  364:	 * and get rank and size information about our process group
        -:  365:	 */
        -:  366:
        -:  367:#ifdef USE_PMI2_API
        -:  368:        mpi_errno = PMI2_Init(has_parent, &pg_size, &pg_rank, &appnum);
        -:  369:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  370:#else
     3459:  371:	pmi_errno = PMI_Init(has_parent);
     3459:  372:	if (pmi_errno != PMI_SUCCESS) {
    #####:  373:	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**pmi_init",
        -:  374:			     "**pmi_init %d", pmi_errno);
        -:  375:	}
        -:  376:
     3459:  377:	pmi_errno = PMI_Get_rank(&pg_rank);
     3459:  378:	if (pmi_errno != PMI_SUCCESS) {
    #####:  379:	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**pmi_get_rank",
        -:  380:			     "**pmi_get_rank %d", pmi_errno);
        -:  381:	}
        -:  382:
     3459:  383:	pmi_errno = PMI_Get_size(&pg_size);
     3459:  384:	if (pmi_errno != 0) {
    #####:  385:	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**pmi_get_size",
        -:  386:			     "**pmi_get_size %d", pmi_errno);
        -:  387:	}
        -:  388:	
     3459:  389:	pmi_errno = PMI_Get_appnum(&appnum);
     3459:  390:	if (pmi_errno != PMI_SUCCESS) {
    #####:  391:	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**pmi_get_appnum",
        -:  392:				 "**pmi_get_appnum %d", pmi_errno);
        -:  393:	}
        -:  394:#endif
        -:  395:	/* Note that if pmi is not availble, the value of MPI_APPNUM is 
        -:  396:	   not set */
     3459:  397:	if (appnum != -1) {
     3459:  398:	    MPIR_Process.attrs.appnum = appnum;
        -:  399:	}
        -:  400:
        -:  401:#ifdef USE_PMI2_API
        -:  402:        
        -:  403:        /* This memory will be freed by the PG_Destroy if there is an error */
        -:  404:	pg_id = MPIU_Malloc(MAX_JOBID_LEN);
        -:  405:	if (pg_id == NULL) {
        -:  406:	    MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**nomem");
        -:  407:	}
        -:  408:
        -:  409:        mpi_errno = PMI2_Job_GetId(pg_id, MAX_JOBID_LEN);
        -:  410:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  411:        
        -:  412:
        -:  413:#else
        -:  414:	/* Now, initialize the process group information with PMI calls */
        -:  415:	/*
        -:  416:	 * Get the process group id
        -:  417:	 */
     3459:  418:	pmi_errno = PMI_Get_id_length_max(&pg_id_sz);
     3459:  419:	if (pmi_errno != PMI_SUCCESS) {
    #####:  420:	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,
        -:  421:				 "**pmi_get_id_length_max", 
        -:  422:				 "**pmi_get_id_length_max %d", pmi_errno);
        -:  423:	}
        -:  424:
        -:  425:	/* This memory will be freed by the PG_Destroy if there is an error */
     3459:  426:	pg_id = MPIU_Malloc(pg_id_sz + 1);
     3459:  427:	if (pg_id == NULL) {
    #####:  428:	    MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**nomem");
        -:  429:	}
        -:  430:
        -:  431:	/* Note in the singleton init case, the pg_id is a dummy.
        -:  432:	   We'll want to replace this value if we join an 
        -:  433:	   Process manager */
     3459:  434:	pmi_errno = PMI_Get_id(pg_id, pg_id_sz);
     3459:  435:	if (pmi_errno != PMI_SUCCESS) {
    #####:  436:	    MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**pmi_get_id",
        -:  437:				 "**pmi_get_id %d", pmi_errno);
        -:  438:	}
        -:  439:#endif
        -:  440:    }
        -:  441:    else {
        -:  442:	/* Create a default pg id */
    #####:  443:	pg_id = MPIU_Malloc(2);
    #####:  444:	if (pg_id == NULL) {
    #####:  445:	    MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**nomem");
        -:  446:	}
    #####:  447:	MPIU_Strncpy( pg_id, "0", 2 );
        -:  448:    }
        -:  449:
        -:  450:    /*
        -:  451:     * Initialize the process group tracking subsystem
        -:  452:     */
     3459:  453:    mpi_errno = MPIDI_PG_Init(argc, argv, 
        -:  454:			     MPIDI_CH3I_PG_Compare_ids, MPIDI_CH3I_PG_Destroy);
     3459:  455:    if (mpi_errno != MPI_SUCCESS) {
    #####:  456:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**dev|pg_init");
        -:  457:    }
        -:  458:
        -:  459:    /*
        -:  460:     * Create a new structure to track the process group for our MPI_COMM_WORLD
        -:  461:     */
     3459:  462:    mpi_errno = MPIDI_PG_Create(pg_size, pg_id, &pg);
     3459:  463:    if (mpi_errno != MPI_SUCCESS) {
    #####:  464:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**dev|pg_create");
        -:  465:    }
        -:  466:
        -:  467:    /* FIXME: We can allow the channels to tell the PG how to get
        -:  468:       connection information by passing the pg to the channel init routine */
     3459:  469:    if (usePMI) {
        -:  470:	/* Tell the process group how to get connection information */
     3459:  471:        mpi_errno = MPIDI_PG_InitConnKVS( pg );
     3459:  472:        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
        -:  473:    }
        -:  474:
        -:  475:    /* FIXME: Who is this for and where does it belong? */
        -:  476:#ifdef USE_MPIU_DBG_PRINT_VC
        -:  477:    MPIU_DBG_parent_str = (*has_parent) ? "+" : "";
        -:  478:#endif
        -:  479:
        -:  480:    /* FIXME: has_args and has_env need to come from PMI eventually... */
     3459:  481:    *has_args = TRUE;
     3459:  482:    *has_env  = TRUE;
        -:  483:
     3459:  484:    *pg_p      = pg;
     3459:  485:    *pg_rank_p = pg_rank;
        -:  486:    
     3459:  487: fn_exit:
     3459:  488:    return mpi_errno;
    #####:  489: fn_fail:
        -:  490:    /* --BEGIN ERROR HANDLING-- */
    #####:  491:    if (pg) {
    #####:  492:	MPIDI_PG_Destroy( pg );
        -:  493:    }
        -:  494:    goto fn_exit;
        -:  495:    /* --END ERROR HANDLING-- */
        -:  496:}
        -:  497:
        -:  498:/*
        -:  499: * Create the storage for the business card. 
        -:  500: *
        -:  501: * The routine MPIDI_CH3I_BCFree should be called with the original 
        -:  502: * value *bc_val_p .  Note that the routines that set the value 
        -:  503: * of the businesscard return a pointer to the first free location,
        -:  504: * so you need to remember the original location in order to free 
        -:  505: * it later.
        -:  506: *
        -:  507: */
        -:  508:int MPIDI_CH3I_BCInit( char **bc_val_p, int *val_max_sz_p )
     3459:  509:{
        -:  510:    int pmi_errno;
     3459:  511:    int mpi_errno = MPI_SUCCESS;
        -:  512:#ifdef USE_PMI2_API
        -:  513:    *val_max_sz_p = PMI2_MAX_VALLEN;
        -:  514:#else
     3459:  515:    pmi_errno = PMI_KVS_Get_value_length_max(val_max_sz_p);
     3459:  516:    if (pmi_errno != PMI_SUCCESS)
        -:  517:    {
    #####:  518:        MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,
        -:  519:                             "**pmi_kvs_get_value_length_max",
        -:  520:                             "**pmi_kvs_get_value_length_max %d", pmi_errno);
        -:  521:    }
        -:  522:#endif
        -:  523:    /* This memroy is returned by this routine */
     3459:  524:    *bc_val_p = MPIU_Malloc(*val_max_sz_p);
     3459:  525:    if (*bc_val_p == NULL) {
    #####:  526:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**nomem");
        -:  527:    }
        -:  528:    
        -:  529:    /* Add a null to simplify looking at the bc */
     3459:  530:    **bc_val_p = 0;
        -:  531:
     3459:  532:  fn_exit:
     3459:  533:    return mpi_errno;
        -:  534:
        -:  535:  fn_fail:
        -:  536:    goto fn_exit;
        -:  537:}
        -:  538:
        -:  539:/* Free the business card.  This routine should be called once the business
        -:  540:   card is published. */
        -:  541:int MPIDI_CH3I_BCFree( char *bc_val )
     3459:  542:{
        -:  543:    /* */
     3459:  544:    if (bc_val) {
     3459:  545:	MPIU_Free( bc_val );
        -:  546:    }
        -:  547:    
     3459:  548:    return 0;
        -:  549:}
        -:  550:
        -:  551:/* FIXME: The PG code should supply these, since it knows how the 
        -:  552:   pg_ids and other data are represented */
        -:  553:static int MPIDI_CH3I_PG_Compare_ids(void * id1, void * id2)
    13749:  554:{
    13749:  555:    return (strcmp((char *) id1, (char *) id2) == 0) ? TRUE : FALSE;
        -:  556:}
        -:  557:
        -:  558:
        -:  559:static int MPIDI_CH3I_PG_Destroy(MPIDI_PG_t * pg)
     5439:  560:{
     5439:  561:    if (pg->id != NULL)
        -:  562:    { 
     5439:  563:	MPIU_Free(pg->id);
        -:  564:    }
        -:  565:    
     5439:  566:    return MPI_SUCCESS;
        -:  567:}