-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/datatype/typeutil.c
        -:    0:Graph:typeutil.gcno
        -:    0:Data:typeutil.gcda
        -:    0:Runs:4383
        -:    0:Programs:1376
        -:    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 "datatype.h"
        -:   10:
        -:   11:/* This is the utility file for datatypes that contains the basic datatype 
        -:   12:   items and storage management.  It also contains a temporary routine
        -:   13:   that is used by ROMIO to test to see if datatypes are contiguous */
        -:   14:#ifndef MPID_DATATYPE_PREALLOC 
        -:   15:#define MPID_DATATYPE_PREALLOC 8
        -:   16:#endif
        -:   17:
        -:   18:/* Preallocated datatype objects */
        -:   19:MPID_Datatype MPID_Datatype_builtin[MPID_DATATYPE_N_BUILTIN + 1] = { {0} };
        -:   20:MPID_Datatype MPID_Datatype_direct[MPID_DATATYPE_PREALLOC] = { {0} };
        -:   21:MPIU_Object_alloc_t MPID_Datatype_mem = { 0, 0, 0, 0, MPID_DATATYPE, 
        -:   22:			      sizeof(MPID_Datatype), MPID_Datatype_direct,
        -:   23:					  MPID_DATATYPE_PREALLOC};
        -:   24:
        -:   25:static int MPIR_Datatype_finalize(void *dummy );
        -:   26:static int MPIR_DatatypeAttrFinalizeCallback(void *dummy );
        -:   27:
        -:   28:/* Call this routine to associate a MPID_Datatype with each predefined 
        -:   29:   datatype.  We do this with lazy initialization because many MPI 
        -:   30:   programs do not require anything except the predefined datatypes, and
        -:   31:   all of the necessary information about those is stored within the
        -:   32:   MPI_Datatype handle.  However, if the user wants to change the name
        -:   33:   (character string, set with MPI_Type_set_name) associated with a
        -:   34:   predefined name, then the structures must be allocated.
        -:   35:*/
        -:   36:/* FIXME does the order of this list need to correspond to anything in
        -:   37:   particular?  There are several lists of predefined types sprinkled throughout
        -:   38:   the codebase and it's unclear which (if any) of them must match exactly.
        -:   39:   [goodell@ 2009-03-17] */
        -:   40:static MPI_Datatype mpi_dtypes[] = {
        -:   41:    MPI_CHAR,
        -:   42:    MPI_UNSIGNED_CHAR,
        -:   43:    MPI_SIGNED_CHAR,
        -:   44:    MPI_BYTE,
        -:   45:    MPI_WCHAR,
        -:   46:    MPI_SHORT,
        -:   47:    MPI_UNSIGNED_SHORT,
        -:   48:    MPI_INT,
        -:   49:    MPI_UNSIGNED,
        -:   50:    MPI_LONG,
        -:   51:    MPI_UNSIGNED_LONG,
        -:   52:    MPI_FLOAT,
        -:   53:    MPI_DOUBLE,
        -:   54:    MPI_LONG_DOUBLE,
        -:   55:    MPI_LONG_LONG,
        -:   56:    MPI_UNSIGNED_LONG_LONG,
        -:   57:    MPI_PACKED,
        -:   58:    MPI_LB,
        -:   59:    MPI_UB,
        -:   60:    MPI_2INT,
        -:   61:
        -:   62:    /* C99 types */
        -:   63:    MPI_INT8_T,
        -:   64:    MPI_INT16_T,
        -:   65:    MPI_INT32_T,
        -:   66:    MPI_INT64_T,
        -:   67:    MPI_UINT8_T,
        -:   68:    MPI_UINT16_T,
        -:   69:    MPI_UINT32_T,
        -:   70:    MPI_UINT64_T,
        -:   71:    MPI_C_BOOL,
        -:   72:    MPI_C_FLOAT_COMPLEX,
        -:   73:    MPI_C_DOUBLE_COMPLEX,
        -:   74:    MPI_C_LONG_DOUBLE_COMPLEX,
        -:   75:
        -:   76:    /* address/offset types */
        -:   77:    MPI_AINT,
        -:   78:    MPI_OFFSET,
        -:   79:
        -:   80:    /* Fortran types */
        -:   81:    MPI_COMPLEX,
        -:   82:    MPI_DOUBLE_COMPLEX,
        -:   83:    MPI_LOGICAL,
        -:   84:    MPI_REAL,
        -:   85:    MPI_DOUBLE_PRECISION,
        -:   86:    MPI_INTEGER,
        -:   87:    MPI_2INTEGER,
        -:   88:    MPI_2COMPLEX,
        -:   89:    MPI_2DOUBLE_COMPLEX,
        -:   90:    MPI_2REAL,
        -:   91:    MPI_2DOUBLE_PRECISION,
        -:   92:    MPI_CHARACTER,
        -:   93:#ifdef HAVE_FORTRAN_BINDING
        -:   94:    /* Size-specific types; these are in section 10.2.4 (Extended Fortran Support)
        -:   95:       as well as optional in MPI-1
        -:   96:    */
        -:   97:    MPI_REAL4,
        -:   98:    MPI_REAL8,
        -:   99:    MPI_REAL16,
        -:  100:    MPI_COMPLEX8,
        -:  101:    MPI_COMPLEX16,
        -:  102:    MPI_COMPLEX32,
        -:  103:    MPI_INTEGER1,
        -:  104:    MPI_INTEGER2,
        -:  105:    MPI_INTEGER4,
        -:  106:    MPI_INTEGER8,
        -:  107:    MPI_INTEGER16,
        -:  108:#endif
        -:  109:    /* This entry is a guaranteed end-of-list item */
        -:  110:    (MPI_Datatype) -1,
        -:  111:};
        -:  112:
        -:  113:/*
        -:  114:  MPIR_Datatype_init()
        -:  115:
        -:  116:  Main purpose of this function is to set up the following pair types:
        -:  117:  - MPI_FLOAT_INT
        -:  118:  - MPI_DOUBLE_INT
        -:  119:  - MPI_LONG_INT
        -:  120:  - MPI_SHORT_INT
        -:  121:  - MPI_LONG_DOUBLE_INT
        -:  122:
        -:  123:  The assertions in this code ensure that:
        -:  124:  - this function is called before other types are allocated
        -:  125:  - there are enough spaces in the direct block to hold our types
        -:  126:  - we actually get the values we expect (otherwise errors regarding
        -:  127:    these types could be terribly difficult to track down!)
        -:  128:
        -:  129: */
        -:  130:static MPI_Datatype mpi_pairtypes[] = {
        -:  131:    MPI_FLOAT_INT,
        -:  132:    MPI_DOUBLE_INT,
        -:  133:    MPI_LONG_INT,
        -:  134:    MPI_SHORT_INT,
        -:  135:    MPI_LONG_DOUBLE_INT,
        -:  136:    (MPI_Datatype) -1
        -:  137:};
        -:  138:
        -:  139:int MPIR_Datatype_init(void)
     4383:  140:{
        -:  141:    int i;
        -:  142:    MPID_Datatype *ptr;
        -:  143:
     4383:  144:    MPIU_Assert(MPID_Datatype_mem.initialized == 0);
        -:  145:    MPIU_Assert(MPID_DATATYPE_PREALLOC >= 5);
        -:  146:
    26298:  147:    for (i=0; mpi_pairtypes[i] != (MPI_Datatype) -1; ++i) {
        -:  148:        /* types based on 'long long' and 'long double', may be disabled at
        -:  149:           configure time, and their values set to MPI_DATATYPE_NULL.  skip any
        -:  150:           such types. */
    21915:  151:        if (mpi_pairtypes[i] == MPI_DATATYPE_NULL) continue;
        -:  152:        /* XXX: this allocation strategy isn't right if one or more of the
        -:  153:           pairtypes is MPI_DATATYPE_NULL.  in fact, the assert below will
        -:  154:           fail if any type other than the las in the list is equal to
        -:  155:           MPI_DATATYPE_NULL.  obviously, this should be fixed, but I need
        -:  156:           to talk to Rob R. first. -- BRT */
        -:  157:        /* XXX DJG it does work, but only because MPI_LONG_DOUBLE_INT is the
        -:  158:         * only one that is ever optional and it comes last */
        -:  159:
        -:  160:        /* we use the _unsafe version because we are still in MPI_Init, before
        -:  161:         * multiple threads are permitted and possibly before support for
        -:  162:         * critical sections is entirely setup */
    21915:  163:        ptr = (MPID_Datatype *)MPIU_Handle_obj_alloc_unsafe( &MPID_Datatype_mem );
        -:  164:
    21915:  165:        MPIU_Assert(ptr);
    21915:  166:        MPIU_Assert(ptr->handle == mpi_pairtypes[i]);
        -:  167:        /* this is a redundant alternative to the previous statement */
    21915:  168:        MPIU_Assert((void *) ptr == (void *) (MPID_Datatype_direct + HANDLE_INDEX(mpi_pairtypes[i])));
        -:  169:
    21915:  170:        MPID_Type_create_pairtype(mpi_pairtypes[i], (MPID_Datatype *) ptr);
        -:  171:    }
        -:  172:
     4383:  173:    MPIR_Add_finalize(MPIR_Datatype_finalize, 0,
        -:  174:                      MPIR_FINALIZE_CALLBACK_PRIO-1);
        -:  175:
     4383:  176:    return MPI_SUCCESS;
        -:  177:}
        -:  178:
        -:  179:static int MPIR_Datatype_finalize(void *dummy ATTRIBUTE((unused)) )
     4374:  180:{
        -:  181:    int i;
        -:  182:    MPID_Datatype *dptr;
        -:  183:
    26244:  184:    for (i=0; mpi_pairtypes[i] != (MPI_Datatype) -1; i++) {
    21870:  185:	if (mpi_pairtypes[i] != MPI_DATATYPE_NULL) {
    21870:  186:	    MPID_Datatype_get_ptr(mpi_pairtypes[i], dptr);
    21870:  187:	    MPID_Datatype_release(dptr);
    21870:  188:	    mpi_pairtypes[i] = MPI_DATATYPE_NULL;
        -:  189:	}
        -:  190:    }
     4374:  191:    return 0;
        -:  192:}
        -:  193:
        -:  194:/* Called ONLY from MPIR_Datatype_init_names (type_get_name.c).  
        -:  195:   That routine calls it from within a single-init section to 
        -:  196:   ensure thread-safety. */
        -:  197:
        -:  198:int MPIR_Datatype_builtin_fillin(void)
       58:  199:{
        -:  200:    static const char FCNAME[] = "MPIR_Datatype_builtin_fillin";
       58:  201:    int mpi_errno = MPI_SUCCESS;
        -:  202:    int i;
        -:  203:    MPID_Datatype *dptr;
       58:  204:    MPI_Datatype  d = MPI_DATATYPE_NULL;
        -:  205:    static int is_init = 0;
        -:  206:    char error_msg[1024];
        -:  207:
        -:  208:    /* FIXME: This is actually an error, since this routine 
        -:  209:       should only be called once */
       58:  210:    if (is_init)
        -:  211:    {
    #####:  212:	return MPI_SUCCESS;
        -:  213:    }
        -:  214:
       58:  215:    if (!is_init) { 
     3364:  216:	for (i=0; i<MPID_DATATYPE_N_BUILTIN; i++) {
        -:  217:	    /* Compute the index from the value of the handle */
     3364:  218:	    d = mpi_dtypes[i];
     3364:  219:	    if (d == -1) {
        -:  220:		/* At the end of mpi_dtypes */
       58:  221:		break;
        -:  222:	    }
        -:  223:	    /* Some of the size-specific types may be null, as might be types
        -:  224:	       based on 'long long' and 'long double' if those types were
        -:  225:	       disabled at configure time.  skip those cases. */
     3306:  226:	    if (d == MPI_DATATYPE_NULL) continue;
        -:  227:	    
     3132:  228:	    MPID_Datatype_get_ptr(d,dptr);
        -:  229:	    /* --BEGIN ERROR HANDLING-- */
     3132:  230:	    if (dptr < MPID_Datatype_builtin || 
        -:  231:		dptr > MPID_Datatype_builtin + MPID_DATATYPE_N_BUILTIN)
        -:  232:		{
    #####:  233:		    MPIU_Snprintf(error_msg, 1024,
        -:  234:				  "%dth builtin datatype handle references invalid memory",
        -:  235:				  i);
    #####:  236:		    mpi_errno = MPIR_Err_create_code(MPI_SUCCESS,
        -:  237:						     MPIR_ERR_FATAL, FCNAME,
        -:  238:						     __LINE__, MPI_ERR_INTERN,
        -:  239:						     "**fail", "**fail %s",
        -:  240:						     error_msg);
    #####:  241:		    return mpi_errno;
        -:  242:		}
        -:  243:	    /* --END ERROR HANDLING-- */
        -:  244:	    
        -:  245:	    /* dptr will point into MPID_Datatype_builtin */
     3132:  246:	    dptr->handle	   = d;
     3132:  247:	    dptr->is_permanent = 1;
     3132:  248:	    dptr->is_contig	   = 1;
     3132:  249:	    MPIU_Object_set_ref( dptr, 1 );
     3132:  250:	    MPID_Datatype_get_size_macro(mpi_dtypes[i], dptr->size);
     3132:  251:	    dptr->extent	   = dptr->size;
     3132:  252:	    dptr->ub	   = dptr->size;
     3132:  253:	    dptr->true_ub	   = dptr->size;
     3132:  254:	    dptr->contents     = NULL; /* should never get referenced? */
        -:  255:	}
        -:  256:	/* --BEGIN ERROR HANDLING-- */
       58:  257: 	if (d != -1 && i < sizeof(mpi_dtypes)/sizeof(*mpi_dtypes) && mpi_dtypes[i] != -1) { 
        -:  258:	    /* We did not hit the end-of-list */
        -:  259:	    /*MPIU_Internal_error_printf( "Did not initialize all of the predefined datatypes (only did first %d)\n", i-1 );*/
    #####:  260:	    MPIU_Snprintf(error_msg, 1024,
        -:  261:			  "Did not initialize all of the predefined datatypes (only did first %d)\n",
        -:  262:			      i-1);
        -:  263:
    #####:  264:		mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL,
        -:  265:						 FCNAME, __LINE__,
        -:  266:						 MPI_ERR_INTERN, "**fail",
        -:  267:						 "**fail %s", error_msg);
    #####:  268:		return mpi_errno;
        -:  269:	}
        -:  270:	/* --END ERROR HANDLING-- */
       58:  271:	is_init = 1;
        -:  272:    }
       58:  273:    return mpi_errno;
        -:  274:}
        -:  275:
        -:  276:/* This will eventually be removed once ROMIO knows more about MPICH2 */
        -:  277:void MPIR_Datatype_iscontig(MPI_Datatype datatype, int *flag)
 14790186:  278:{
        -:  279:    MPID_Datatype *datatype_ptr;
 14790186:  280:    if (HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN)
 13678516:  281:        *flag = 1;
        -:  282:    else  {
  1111670:  283:        MPID_Datatype_get_ptr(datatype, datatype_ptr);
  1111670:  284:        *flag = datatype_ptr->is_contig;
        -:  285:    }
 14790186:  286:}
        -:  287:
        -:  288:/* If an attribute is added to a predefined type, we free the attributes 
        -:  289:   in Finalize */
        -:  290:static int MPIR_DatatypeAttrFinalizeCallback(void *dummy ATTRIBUTE((unused)) )
       10:  291:{
        -:  292:    MPID_Datatype *dtype;
       10:  293:    int i, mpi_errno=MPI_SUCCESS;
        -:  294:
      690:  295:    for (i=0; i<MPID_DATATYPE_N_BUILTIN; i++) {
      680:  296:	dtype = &MPID_Datatype_builtin[i];
      680:  297:	if (dtype && MPIR_Process.attr_free && dtype->attributes) {
        3:  298:	    mpi_errno = MPIR_Process.attr_free( dtype->handle, 
        -:  299:						&dtype->attributes );
        -:  300:	    /* During finalize, we ignore error returns from the free */
        -:  301:	}
        -:  302:    }
       10:  303:    return mpi_errno;
        -:  304:}
        -:  305:
        -:  306:void MPIR_DatatypeAttrFinalize( void )
      506:  307:{
        -:  308:    static int called=0;
        -:  309:
        -:  310:    /* FIXME: This needs to be make thread safe */
      506:  311:    if (!called) {
       10:  312:	called = 1;
       10:  313:	MPIR_Add_finalize(MPIR_DatatypeAttrFinalizeCallback, 0, 
        -:  314:			  MPIR_FINALIZE_CALLBACK_PRIO-1);
        -:  315:    }
      506:  316:}