-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/topo/topoutil.c
        -:    0:Graph:topoutil.gcno
        -:    0:Data:topoutil.gcda
        -:    0:Runs:823
        -:    0:Programs:228
        -:    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:#include "mpiimpl.h"
        -:    8:#include "topo.h"
        -:    9:
        -:   10:/* Keyval for topology information */
        -:   11:static int MPIR_Topology_keyval = MPI_KEYVAL_INVALID;  
        -:   12:
        -:   13:/* Local functions */
        -:   14:static int MPIR_Topology_copy_fn ( MPI_Comm, int, void *, void *, void *, 
        -:   15:				   int * );
        -:   16:static int MPIR_Topology_delete_fn ( MPI_Comm, int, void *, void * );
        -:   17:static int MPIR_Topology_finalize ( void * );
        -:   18:
        -:   19:/*
        -:   20:  Return a poiner to the topology structure on a communicator.
        -:   21:  Returns null if no topology structure is defined 
        -:   22:*/
        -:   23:MPIR_Topology *MPIR_Topology_get( MPID_Comm *comm_ptr )
     4531:   24:{
        -:   25:    MPIR_Topology *topo_ptr;
        -:   26:    int flag;
     4531:   27:    MPIU_THREADPRIV_DECL;
        -:   28:
     4531:   29:    if (MPIR_Topology_keyval == MPI_KEYVAL_INVALID) {
       36:   30:	return 0;
        -:   31:    }
        -:   32:
     4495:   33:    MPIU_THREADPRIV_GET;
     4495:   34:    MPIR_Nest_incr();
     4495:   35:    (void)NMPI_Comm_get_attr(comm_ptr->handle, MPIR_Topology_keyval,
        -:   36:			     &topo_ptr, &flag );
     4495:   37:    MPIR_Nest_decr();
        -:   38:
     4495:   39:    if (flag) return topo_ptr;
    #####:   40:    return 0;
        -:   41:}
        -:   42:
        -:   43:int MPIR_Topology_put( MPID_Comm *comm_ptr, MPIR_Topology *topo_ptr )
      824:   44:{
        -:   45:    int mpi_errno;
      824:   46:    MPIU_THREADPRIV_DECL;
        -:   47:
      824:   48:    MPIU_THREADPRIV_GET;
        -:   49:
      824:   50:    MPIU_Assert(comm_ptr != NULL);
        -:   51:
      824:   52:    if (MPIR_Topology_keyval == MPI_KEYVAL_INVALID) {
        -:   53:	/* Create a new keyval */
        -:   54:	/* FIXME - thread safe code needs a thread lock here, followed
        -:   55:	   by another test on the keyval to see if a different thread
        -:   56:	   got there first */
      222:   57:	MPIR_Nest_incr();
      222:   58:	mpi_errno = NMPI_Comm_create_keyval( MPIR_Topology_copy_fn, 
        -:   59:					     MPIR_Topology_delete_fn,
        -:   60:					     &MPIR_Topology_keyval, 0 );
      222:   61:	MPIR_Nest_decr();
        -:   62:	/* Register the finalize handler */
      222:   63:	if (mpi_errno) return mpi_errno;
      222:   64:	MPIR_Add_finalize( MPIR_Topology_finalize, (void*)0, 
        -:   65:			   MPIR_FINALIZE_CALLBACK_PRIO-1);
        -:   66:    }
      824:   67:    MPIR_Nest_incr();
      824:   68:    mpi_errno = NMPI_Comm_set_attr(comm_ptr->handle, MPIR_Topology_keyval, 
        -:   69:				   topo_ptr );
      824:   70:    MPIR_Nest_decr();
      824:   71:    return mpi_errno;
        -:   72:}
        -:   73:
        -:   74:/* Ignore p */
        -:   75:/* begin:nested */
        -:   76:static int MPIR_Topology_finalize( void *p ATTRIBUTE((unused)) )
      222:   77:{
      222:   78:    MPIU_THREADPRIV_DECL;
        -:   79:
      222:   80:    MPIU_THREADPRIV_GET;
        -:   81:
      222:   82:    MPIR_Nest_incr();
        -:   83:
        -:   84:    MPIU_UNREFERENCED_ARG(p);
        -:   85:
      222:   86:    if (MPIR_Topology_keyval != MPI_KEYVAL_INVALID) {
        -:   87:	/* Just in case */
      222:   88:	NMPI_Comm_free_keyval( &MPIR_Topology_keyval );
        -:   89:    }
      222:   90:    MPIR_Nest_decr();
      222:   91:    return 0;
        -:   92:}
        -:   93:/* end:nested */
        -:   94:
        -:   95:static int *MPIR_Copy_array( int n, const int a[], int *err )
     1388:   96:{
        -:   97:    int *new_p;
        -:   98:
        -:   99:    /* the copy of NULL is NULL */
     1388:  100:    if (a == NULL) {
      192:  101:        MPIU_Assert(n == 0);
      192:  102:        return NULL;
        -:  103:    }
        -:  104:
     1196:  105:    new_p = (int *)MPIU_Malloc( n * sizeof(int) );
        -:  106:
        -:  107:    /* --BEGIN ERROR HANDLING-- */
     1196:  108:    if (!new_p) {
    #####:  109:	*err = MPI_ERR_OTHER;
    #####:  110:	return 0;
        -:  111:    }
        -:  112:    /* --END ERROR HANDLING-- */
     1196:  113:    MPIU_Memcpy(new_p, a, n * sizeof(int));
     1196:  114:    return new_p;
        -:  115:}
        -:  116:
        -:  117:/* The keyval copy and delete functions must handle copying and deleting 
        -:  118:   the associated topology structures 
        -:  119:   
        -:  120:   We can reduce the number of allocations by making a single allocation
        -:  121:   of enough integers for all fields (including the ones in the structure)
        -:  122:   and freeing the single object later.
        -:  123:*/
        -:  124:#undef FUNCNAME
        -:  125:#define FUNCNAME MPIR_Topology_copy_fn
        -:  126:#undef FCNAME
        -:  127:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  128:static int MPIR_Topology_copy_fn ( MPI_Comm comm ATTRIBUTE((unused)), 
        -:  129:				   int keyval ATTRIBUTE((unused)), 
        -:  130:				   void *extra_data ATTRIBUTE((unused)),
        -:  131:				   void *attr_in, void *attr_out, 
        -:  132:				   int *flag )
      360:  133:{
      360:  134:    MPIR_Topology *old_topology = (MPIR_Topology *)attr_in;
      360:  135:    MPIR_Topology *copy_topology = NULL;
      360:  136:    MPIU_CHKPMEM_DECL(5);
      360:  137:    int mpi_errno = 0;
        -:  138:
        -:  139:    MPIU_UNREFERENCED_ARG(comm);
        -:  140:    MPIU_UNREFERENCED_ARG(keyval);
        -:  141:    MPIU_UNREFERENCED_ARG(extra_data);
        -:  142:
      360:  143:    *flag = 0;
      360:  144:    *(void **)attr_out = NULL;
        -:  145:
      360:  146:    MPIU_CHKPMEM_MALLOC(copy_topology, MPIR_Topology *, sizeof(MPIR_Topology), mpi_errno, "copy_topology");
        -:  147:
        -:  148:    /* simplify copying and error handling */
        -:  149:#define MPIR_ARRAY_COPY_HELPER(kind_,array_field_,count_field_) \
        -:  150:        do { \
        -:  151:            copy_topology->topo.kind_.array_field_ = \
        -:  152:                MPIR_Copy_array(old_topology->topo.kind_.count_field_, \
        -:  153:                                old_topology->topo.kind_.array_field_, \
        -:  154:                                &mpi_errno); \
        -:  155:            if (mpi_errno) MPIU_ERR_POP(mpi_errno); \
        -:  156:            MPIU_CHKPMEM_REGISTER(copy_topology->topo.kind_.array_field_); \
        -:  157:        } while (0)
        -:  158:
      360:  159:    copy_topology->kind = old_topology->kind;
      360:  160:    if (old_topology->kind == MPI_CART) {
       28:  161:        copy_topology->topo.cart.ndims  = old_topology->topo.cart.ndims;
       28:  162:        copy_topology->topo.cart.nnodes = old_topology->topo.cart.nnodes;
       28:  163:        MPIR_ARRAY_COPY_HELPER(cart, dims, ndims);
       28:  164:        MPIR_ARRAY_COPY_HELPER(cart, periodic, ndims);
       28:  165:        MPIR_ARRAY_COPY_HELPER(cart, position, ndims);
        -:  166:    }
      332:  167:    else if (old_topology->kind == MPI_GRAPH) {
       12:  168:        copy_topology->topo.graph.nnodes = old_topology->topo.graph.nnodes;
       12:  169:        copy_topology->topo.graph.nedges = old_topology->topo.graph.nedges;
       12:  170:        MPIR_ARRAY_COPY_HELPER(graph, index, nnodes);
       12:  171:        MPIR_ARRAY_COPY_HELPER(graph, edges, nedges);
        -:  172:    }
      320:  173:    else if (old_topology->kind == MPI_DIST_GRAPH) {
      320:  174:        copy_topology->topo.dist_graph.indegree = old_topology->topo.dist_graph.indegree;
      320:  175:        copy_topology->topo.dist_graph.outdegree = old_topology->topo.dist_graph.outdegree;
      320:  176:        MPIR_ARRAY_COPY_HELPER(dist_graph, in, indegree);
      320:  177:        MPIR_ARRAY_COPY_HELPER(dist_graph, in_weights, indegree);
      320:  178:        MPIR_ARRAY_COPY_HELPER(dist_graph, out, outdegree);
      320:  179:        MPIR_ARRAY_COPY_HELPER(dist_graph, out_weights, outdegree);
        -:  180:    }
        -:  181:    /* --BEGIN ERROR HANDLING-- */
        -:  182:    else {
        -:  183:	/* Unknown topology */
    #####:  184:	return MPI_ERR_TOPOLOGY;
        -:  185:    }
        -:  186:    /* --END ERROR HANDLING-- */
        -:  187:#undef MPIR_ARRAY_COPY_HELPER
        -:  188:
      360:  189:    *(void **)attr_out = (void *)copy_topology;
      360:  190:    *flag = 1;
      360:  191:    MPIU_CHKPMEM_COMMIT();
      360:  192:fn_exit:
        -:  193:    /* Return mpi_errno in case one of the copy array functions failed */
      360:  194:    return mpi_errno;
        -:  195:fn_fail:
    #####:  196:    MPIU_CHKPMEM_REAP();
        -:  197:    goto fn_exit;
        -:  198:}
        -:  199:
        -:  200:#undef FUNCNAME
        -:  201:#define FUNCNAME MPIR_Topology_delete_fn
        -:  202:#undef FCNAME
        -:  203:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  204:static int MPIR_Topology_delete_fn ( MPI_Comm comm ATTRIBUTE((unused)), 
        -:  205:				     int keyval ATTRIBUTE((unused)), 
        -:  206:				     void *attr_val, 
        -:  207:				     void *extra_data ATTRIBUTE((unused)) )
     1148:  208:{
     1148:  209:    MPIR_Topology *topology = (MPIR_Topology *)attr_val;
        -:  210:
        -:  211:    MPIU_UNREFERENCED_ARG(comm);
        -:  212:    MPIU_UNREFERENCED_ARG(keyval);
        -:  213:    MPIU_UNREFERENCED_ARG(extra_data);
        -:  214:
        -:  215:    /* FIXME - free the attribute data structure */
        -:  216:    
     1148:  217:    if (topology->kind == MPI_CART) {
      345:  218:	MPIU_Free( topology->topo.cart.dims );
      345:  219:	MPIU_Free( topology->topo.cart.periodic );
      345:  220:	MPIU_Free( topology->topo.cart.position );
      345:  221:	MPIU_Free( topology );
        -:  222:    }
      803:  223:    else if (topology->kind == MPI_GRAPH) {
       83:  224:	MPIU_Free( topology->topo.graph.index );
       83:  225:	MPIU_Free( topology->topo.graph.edges );
       83:  226:	MPIU_Free( topology );
        -:  227:    }
      720:  228:    else if (topology->kind == MPI_DIST_GRAPH) {
      720:  229:        MPIU_Free(topology->topo.dist_graph.in);
      720:  230:        MPIU_Free(topology->topo.dist_graph.out);
      720:  231:        if (topology->topo.dist_graph.in_weights)
      532:  232:            MPIU_Free(topology->topo.dist_graph.in_weights);
      720:  233:        if (topology->topo.dist_graph.out_weights)
      556:  234:            MPIU_Free(topology->topo.dist_graph.out_weights);
      720:  235:        MPIU_Free(topology );
        -:  236:    }
        -:  237:    /* --BEGIN ERROR HANDLING-- */
        -:  238:    else {
    #####:  239:	return MPI_ERR_TOPOLOGY;
        -:  240:    }
        -:  241:    /* --END ERROR HANDLING-- */
     1148:  242:    return MPI_SUCCESS;
        -:  243:}
        -:  244:
        -:  245: