-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/attr/attrutil.c
        -:    0:Graph:attrutil.gcno
        -:    0:Data:attrutil.gcda
        -:    0:Runs:2438
        -:    0:Programs:559
        -:    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 "attr.h"
        -:    9:/*
        -:   10: * Keyvals.  These are handled just like the other opaque objects in MPICH
        -:   11: * The predefined keyvals (and their associated attributes) are handled 
        -:   12: * separately, without using the keyval 
        -:   13: * storage
        -:   14: */
        -:   15:
        -:   16:#ifndef MPID_KEYVAL_PREALLOC 
        -:   17:#define MPID_KEYVAL_PREALLOC 16
        -:   18:#endif
        -:   19:
        -:   20:/* Preallocated keyval objects */
        -:   21:MPID_Keyval MPID_Keyval_direct[MPID_KEYVAL_PREALLOC] = { {0} };
        -:   22:MPIU_Object_alloc_t MPID_Keyval_mem = { 0, 0, 0, 0, MPID_KEYVAL, 
        -:   23:					    sizeof(MPID_Keyval), 
        -:   24:					    MPID_Keyval_direct,
        -:   25:					    MPID_KEYVAL_PREALLOC, };
        -:   26:
        -:   27:#ifndef MPID_ATTR_PREALLOC 
        -:   28:#define MPID_ATTR_PREALLOC 32
        -:   29:#endif
        -:   30:
        -:   31:/* Preallocated keyval objects */
        -:   32:MPID_Attribute MPID_Attr_direct[MPID_ATTR_PREALLOC] = { {0} };
        -:   33:MPIU_Object_alloc_t MPID_Attr_mem = { 0, 0, 0, 0, MPID_ATTR, 
        -:   34:					    sizeof(MPID_Attribute), 
        -:   35:					    MPID_Attr_direct,
        -:   36:					    MPID_ATTR_PREALLOC, };
        -:   37:
        -:   38:/* Provides a way to trap all attribute allocations when debugging leaks. */
        -:   39:MPID_Attribute *MPID_Attr_alloc(void)
     6586:   40:{
     6586:   41:    MPID_Attribute *attr = (MPID_Attribute *)MPIU_Handle_obj_alloc(&MPID_Attr_mem);
        -:   42:    /* attributes don't have refcount semantics, but let's keep valgrind and
        -:   43:     * the debug logging pacified */
     6586:   44:    MPIU_Object_set_ref(attr, 0);
     6586:   45:    return attr;
        -:   46:}
        -:   47:
        -:   48:void MPID_Attr_free(MPID_Attribute *attr_ptr)
      177:   49:{
      177:   50:    MPIU_Handle_obj_free(&MPID_Attr_mem, attr_ptr);
      177:   51:}
        -:   52:
        -:   53:#undef FUNCNAME
        -:   54:#define FUNCNAME MPIR_Call_attr_delete
        -:   55:#undef FCNAME
        -:   56:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:   57:/*
        -:   58:  This function deletes a single attribute.
        -:   59:  It is called by both the function to delete a list and attribute set/put 
        -:   60:  val.  Return the return code from the delete function; 0 if there is no
        -:   61:  delete function.
        -:   62:
        -:   63:  Even though there are separate keyvals for communicators, types, and files,
        -:   64:  we can use the same function because the handle for these is always an int
        -:   65:  in MPICH2.  
        -:   66:
        -:   67:  Note that this simply invokes the attribute delete function.  It does not
        -:   68:  remove the attribute from the list of attributes.
        -:   69:*/
        -:   70:int MPIR_Call_attr_delete( int handle, MPID_Attribute *attr_p )
     6738:   71:{
        -:   72:    int rc;
     6738:   73:    int mpi_errno = MPI_SUCCESS;
     6738:   74:    MPID_Keyval* kv = attr_p->keyval;
        -:   75:
     6738:   76:    MPIU_THREADPRIV_DECL;
        -:   77:
     6738:   78:    MPIU_THREADPRIV_GET;
        -:   79:
     6738:   80:    MPIR_Nest_incr();
        -:   81:    
     6738:   82:    if(kv->delfn.user_function == NULL)
      193:   83:        goto fn_exit;
        -:   84:
     6545:   85:    rc = kv->delfn.proxy(
        -:   86:                kv->delfn.user_function,
        -:   87:                handle,
        -:   88:                attr_p->keyval->handle,
        -:   89:                attr_p->attrType,
        -:   90:                (void *)attr_p->value,
        -:   91:                attr_p->keyval->extra_state
        -:   92:                );
        -:   93:    /* --BEGIN ERROR HANDLING-- */
     6545:   94:    if(rc != 0){
       12:   95:        mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**user", "**userdel %d", rc);
       12:   96:        goto fn_fail;
        -:   97:    }
        -:   98:    /* --END ERROR HANDLING-- */
        -:   99:
     6738:  100:  fn_exit:
     6738:  101:    MPIR_Nest_decr();
     6738:  102:    return mpi_errno;
        -:  103:  fn_fail:
        -:  104:    goto fn_exit;
        -:  105:}
        -:  106:
        -:  107:/*
        -:  108:  This function copies a single attribute.
        -:  109:  It is called by the function to copy a list of attribute
        -:  110:  Return the return code from the copy function; MPI_SUCCESS if there is
        -:  111:  no copy function.
        -:  112:
        -:  113:  Even though there are separate keyvals for communicators, types, and files,
        -:  114:  we can use the same function because the handle for these is always an int
        -:  115:  in MPICH2.
        -:  116:
        -:  117:  Note that this simply invokes the attribute copy function.
        -:  118:*/
        -:  119:#undef FUNCNAME
        -:  120:#define FUNCNAME MPIR_Call_attr_copy
        -:  121:#undef FCNAME
        -:  122:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  123:int MPIR_Call_attr_copy( int handle, MPID_Attribute *attr_p, void** value_copy, int* flag)
     5140:  124:{
     5140:  125:    int mpi_errno = MPI_SUCCESS;
        -:  126:    int rc;
     5140:  127:    MPID_Keyval* kv = attr_p->keyval;
        -:  128:
     5140:  129:    MPIU_THREADPRIV_DECL;
        -:  130:    
     5140:  131:    MPIU_THREADPRIV_GET;
        -:  132:    
     5140:  133:    MPIR_Nest_incr();
        -:  134:
     5140:  135:    if(kv->copyfn.user_function == NULL)
     1004:  136:        goto fn_exit;
        -:  137:
     4136:  138:    rc = kv->copyfn.proxy(
        -:  139:                kv->copyfn.user_function,
        -:  140:                handle,
        -:  141:                attr_p->keyval->handle,
        -:  142:                attr_p->keyval->extra_state,
        -:  143:                attr_p->attrType,
        -:  144:                (void *)attr_p->value,
        -:  145:                value_copy,
        -:  146:                flag
        -:  147:                );
        -:  148:
        -:  149:    /* --BEGIN ERROR HANDLING-- */
     4136:  150:    if(rc != 0){
       13:  151:        mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**user", "**usercopy %d", rc);
       13:  152:        goto fn_fail;
        -:  153:    }
        -:  154:    /* --END ERROR HANDLING-- */
     5140:  155:fn_exit:
     5140:  156:    MPIR_Nest_decr();
     5140:  157:    return mpi_errno;
        -:  158:fn_fail:
        -:  159:    goto fn_exit;
        -:  160:}
        -:  161:
        -:  162:#undef FUNCNAME
        -:  163:#define FUNCNAME MPIR_Attr_dup_list
        -:  164:#undef FCNAME
        -:  165:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  166:/* Routine to duplicate an attribute list */
        -:  167:int MPIR_Attr_dup_list( int handle, MPID_Attribute *old_attrs, 
        -:  168:			MPID_Attribute **new_attr )
     4700:  169:{
     4700:  170:    MPID_Attribute *p, *new_p, **next_new_attr_ptr=new_attr;
     4700:  171:    void* new_value = NULL;
     4700:  172:    int mpi_errno = MPI_SUCCESS;
        -:  173:
     9827:  174:    for(p = old_attrs; p != NULL; p = p->next)
        -:  175:    {
        -:  176:        /* call the attribute copy function (if any) */
     5140:  177:        int flag = 0;
     5140:  178:        mpi_errno = MPIR_Call_attr_copy(
        -:  179:                        handle,
        -:  180:                        p,
        -:  181:                        &new_value,
        -:  182:                        &flag
        -:  183:                        );
        -:  184:
     5140:  185:        if(mpi_errno != MPI_SUCCESS)
       13:  186:            goto fn_fail;
        -:  187:
     5127:  188:        if(!flag)
     1020:  189:            continue;
        -:  190:        /* If flag was returned as true, then insert this attribute into the 
        -:  191:	   new list (new_attr) */
        -:  192:
        -:  193:        /* duplicate the attribute by creating new storage, copying the
        -:  194:        attribute value, and invoking the copy function */
     4107:  195:        new_p = MPID_Attr_alloc();
        -:  196:        /* --BEGIN ERROR HANDLING-- */
     4107:  197:        if (!new_p){
    #####:  198:            mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0 );
    #####:  199:            goto fn_fail;
        -:  200:        }
        -:  201:        /* --END ERROR HANDLING-- */
     4107:  202:        if(!*new_attr){
     4107:  203:            *new_attr = new_p;
        -:  204:        }
     4107:  205:        *(next_new_attr_ptr) = new_p;
        -:  206:
     4107:  207:        new_p->keyval = p->keyval;
        -:  208:        /* Remember that we need this keyval */
     4107:  209:        MPIR_Keyval_add_ref(p->keyval);
        -:  210:
     4107:  211:        new_p->attrType         = p->attrType;
     4107:  212:        new_p->pre_sentinal     = 0;
     4107:  213:        new_p->value            = (MPID_AttrVal_t)new_value;
     4107:  214:        new_p->post_sentinal    = 0;
     4107:  215:        new_p->next             = 0;
        -:  216:
     4107:  217:        next_new_attr_ptr = &(new_p->next);
        -:  218:    } /* for(;;) */
        -:  219:
     4700:  220:  fn_exit:
     4700:  221:    return mpi_errno;
        -:  222:  fn_fail:
        -:  223:    goto fn_exit;
        -:  224:}
        -:  225:
        -:  226:#undef FUNCNAME
        -:  227:#define FUNCNAME MPIR_Attr_delete_list
        -:  228:#undef FCNAME
        -:  229:#define FCNAME MPIU_QUOTE(FUNCNAME)
        -:  230:/* Routine to delete an attribute list */
        -:  231:int MPIR_Attr_delete_list( int handle, MPID_Attribute **attr )
     5996:  232:{
        -:  233:    MPID_Attribute *p, *new_p;
     5996:  234:    int mpi_errno = MPI_SUCCESS;
        -:  235:
     5996:  236:    p = *attr;
    18365:  237:    while (p) {
        -:  238:	/* delete the attribute by first executing the delete routine, if any,
        -:  239:	   determine the the next attribute, and recover the attributes 
        -:  240:	   storage */
     6373:  241:	new_p = p->next;
        -:  242:	
        -:  243:	/* Check the sentinals first */
        -:  244:	/* --BEGIN ERROR HANDLING-- */
     6373:  245:	if (p->pre_sentinal != 0 || p->post_sentinal != 0) {
    #####:  246:	    MPIU_ERR_SET(mpi_errno,MPI_ERR_OTHER,"**attrsentinal");
        -:  247:	    /* We could keep trying to free the attributes, but for now
        -:  248:	       we'll just bag it */
    #####:  249:	    return mpi_errno;
        -:  250:	}
        -:  251:	/* --END ERROR HANDLING-- */
        -:  252:	/* For this attribute, find the delete function for the 
        -:  253:	   corresponding keyval */
        -:  254:	/* Still to do: capture any error returns but continue to 
        -:  255:	   process attributes */
     6373:  256:	mpi_errno = MPIR_Call_attr_delete( handle, p );
        -:  257:
        -:  258:	/* We must also remove the keyval reference.  If the keyval
        -:  259:	   was freed earlier (reducing the refcount), the actual 
        -:  260:	   release and free will happen here.  We must free the keyval
        -:  261:	   even if the attr delete failed, as we then remove the 
        -:  262:	   attribute.
        -:  263:	*/
        -:  264:	{
        -:  265:	    int in_use;
        -:  266:	    /* Decrement the use of the keyval */
     6373:  267:	    MPIR_Keyval_release_ref( p->keyval, &in_use);
     6373:  268:	    if (!in_use) {
      661:  269:		MPIU_Handle_obj_free( &MPID_Keyval_mem, p->keyval );
        -:  270:	    }
        -:  271:	}
        -:  272:	
     6373:  273:	MPIU_Handle_obj_free( &MPID_Attr_mem, p );
        -:  274:	
     6373:  275:	p = new_p;
        -:  276:    }
        -:  277:
        -:  278:    /* We must zero out the attribute list pointer or we could attempt to use it
        -:  279:       later.  This normally can't happen because the communicator usually
        -:  280:       disappears after a call to MPI_Comm_free.  But if the attribute keyval
        -:  281:       has an associated delete function that returns an error then we don't
        -:  282:       actually free the communicator despite having freed all the attributes
        -:  283:       associated with the communicator.
        -:  284:
        -:  285:       This function is also used for Win and Type objects, but the idea is the
        -:  286:       same in those cases as well. */
     5996:  287:    *attr = NULL;
     5996:  288:    return mpi_errno;
        -:  289:}
        -:  290:
        -:  291:int
        -:  292:MPIR_Attr_copy_c_proxy(
        -:  293:    MPI_Comm_copy_attr_function* user_function,
        -:  294:    int handle,
        -:  295:    int keyval,
        -:  296:    void* extra_state,
        -:  297:    MPIR_AttrType attrib_type,
        -:  298:    void* attrib,
        -:  299:    void** attrib_copy,
        -:  300:    int* flag
        -:  301:    )
     4112:  302:{
     4112:  303:    void *attrib_val = NULL;
        -:  304:    /* Make sure that the attribute value is delieverd as a pointer */
     4112:  305:    if (MPIR_ATTR_KIND(attrib_type) == MPIR_ATTR_KIND(MPIR_ATTR_INT)){
    #####:  306:        attrib_val = &attrib;
        -:  307:    }
        -:  308:    else{
     4112:  309:        attrib_val = attrib;
        -:  310:    }
     4112:  311:    return user_function(handle, keyval, extra_state, attrib_val, attrib_copy, flag);
        -:  312:}
        -:  313:
        -:  314:
        -:  315:int
        -:  316:MPIR_Attr_delete_c_proxy(
        -:  317:    MPI_Comm_delete_attr_function* user_function,
        -:  318:    int handle,
        -:  319:    int keyval,
        -:  320:    MPIR_AttrType attrib_type,
        -:  321:    void* attrib,
        -:  322:    void* extra_state
        -:  323:    )
     6482:  324:{
     6482:  325:    void *attrib_val = NULL;
        -:  326:    /* Make sure that the attribute value is delieverd as a pointer */
     6482:  327:    if (MPIR_ATTR_KIND(attrib_type) == MPIR_ATTR_KIND(MPIR_ATTR_INT))
    #####:  328:        attrib_val = &attrib;
        -:  329:    else
     6482:  330:        attrib_val = attrib;
     6482:  331:    return user_function(handle, keyval, attrib_val, extra_state);
        -:  332:}
        -:  333:
        -:  334:
        -:  335:void
        -:  336:MPIR_Keyval_set_proxy(
        -:  337:    int keyval,
        -:  338:    MPID_Attr_copy_proxy copy_proxy,
        -:  339:    MPID_Attr_delete_proxy delete_proxy
        -:  340:    )
      513:  341:{
        -:  342:    MPID_Keyval*  keyval_ptr;
      513:  343:    MPID_Keyval_get_ptr( keyval, keyval_ptr );
      513:  344:    if(keyval_ptr == NULL)
    #####:  345:        return;
        -:  346:
      513:  347:    keyval_ptr->copyfn.proxy = copy_proxy;
      513:  348:    keyval_ptr->delfn.proxy = delete_proxy;
        -:  349:}