Blame src/mpi/attr/type_get_attr.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *
Packit 0848f5
 *  (C) 2001 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
#include "mpiimpl.h"
Packit 0848f5
#include "attr.h"
Packit 0848f5
Packit 0848f5
/* -- Begin Profiling Symbol Block for routine MPI_Type_get_attr */
Packit 0848f5
#if defined(HAVE_PRAGMA_WEAK)
Packit 0848f5
#pragma weak MPI_Type_get_attr = PMPI_Type_get_attr
Packit 0848f5
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
Packit 0848f5
#pragma _HP_SECONDARY_DEF PMPI_Type_get_attr  MPI_Type_get_attr
Packit 0848f5
#elif defined(HAVE_PRAGMA_CRI_DUP)
Packit 0848f5
#pragma _CRI duplicate MPI_Type_get_attr as PMPI_Type_get_attr
Packit 0848f5
#elif defined(HAVE_WEAK_ATTRIBUTE)
Packit 0848f5
int MPI_Type_get_attr(MPI_Datatype datatype, int type_keyval, void *attribute_val, int *flag) __attribute__((weak,alias("PMPI_Type_get_attr")));
Packit 0848f5
#endif
Packit 0848f5
/* -- End Profiling Symbol Block */
Packit 0848f5
Packit 0848f5
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
Packit 0848f5
   the MPI routines */
Packit 0848f5
#ifndef MPICH_MPI_FROM_PMPI
Packit 0848f5
#undef MPI_Type_get_attr
Packit 0848f5
#define MPI_Type_get_attr PMPI_Type_get_attr
Packit 0848f5
Packit 0848f5
#undef FUNCNAME
Packit 0848f5
#define FUNCNAME MPIR_TypeGetAttr
Packit 0848f5
Packit 0848f5
int MPIR_TypeGetAttr( MPI_Datatype datatype, int type_keyval, void *attribute_val,
Packit 0848f5
		      int *flag, MPIR_AttrType outAttrType )
Packit 0848f5
{
Packit 0848f5
#ifdef HAVE_ERROR_CHECKING
Packit 0848f5
    static const char FCNAME[] = "MPI_Type_get_attr";
Packit 0848f5
#endif
Packit 0848f5
    int mpi_errno = MPI_SUCCESS;
Packit 0848f5
    MPID_Datatype *type_ptr = NULL;
Packit 0848f5
    MPID_Attribute *p;
Packit 0848f5
    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_TYPE_GET_ATTR);
Packit 0848f5
Packit 0848f5
    MPIR_ERRTEST_INITIALIZED_ORDIE();
Packit 0848f5
    
Packit 0848f5
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit 0848f5
    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_TYPE_GET_ATTR);
Packit 0848f5
    
Packit 0848f5
    /* Validate parameters, especially handles needing to be converted */
Packit 0848f5
#   ifdef HAVE_ERROR_CHECKING
Packit 0848f5
    {
Packit 0848f5
        MPID_BEGIN_ERROR_CHECKS;
Packit 0848f5
        {
Packit 0848f5
	    MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
Packit 0848f5
	    MPIR_ERRTEST_KEYVAL(type_keyval, MPID_DATATYPE, "datatype", mpi_errno);
Packit 0848f5
#           ifdef NEEDS_POINTER_ALIGNMENT_ADJUST
Packit 0848f5
            /* A common user error is to pass the address of a 4-byte
Packit 0848f5
	       int when the address of a pointer (or an address-sized int)
Packit 0848f5
	       should have been used.  We can test for this specific
Packit 0848f5
	       case.  Note that this code assumes sizeof(MPIU_Pint) is 
Packit 0848f5
	       a power of 2. */
Packit 0848f5
	    if ((MPIU_Pint)attribute_val & (sizeof(MPIU_Pint)-1)) {
Packit 0848f5
		MPIR_ERR_SETANDSTMT(mpi_errno,MPI_ERR_ARG,goto fn_fail,"**attrnotptr");
Packit 0848f5
	    }
Packit 0848f5
#           endif
Packit 0848f5
        }
Packit 0848f5
        MPID_END_ERROR_CHECKS;
Packit 0848f5
    }
Packit 0848f5
#   endif
Packit 0848f5
Packit 0848f5
    /* Convert MPI object handles to object pointers */
Packit 0848f5
    MPID_Datatype_get_ptr( datatype, type_ptr );
Packit 0848f5
    
Packit 0848f5
    /* Validate parameters and objects (post conversion) */
Packit 0848f5
#   ifdef HAVE_ERROR_CHECKING
Packit 0848f5
    {
Packit 0848f5
        MPID_BEGIN_ERROR_CHECKS;
Packit 0848f5
        {
Packit 0848f5
	    /* Validate datatype pointer */
Packit 0848f5
	    MPID_Datatype_valid_ptr( type_ptr, mpi_errno );
Packit 0848f5
	    /* If type_ptr is not valid, it will be reset to null */
Packit 0848f5
            if (mpi_errno) goto fn_fail;
Packit 0848f5
        }
Packit 0848f5
        MPID_END_ERROR_CHECKS;
Packit 0848f5
    }
Packit 0848f5
#   endif /* HAVE_ERROR_CHECKING */
Packit 0848f5
Packit 0848f5
    /* ... body of routine ...  */
Packit 0848f5
    
Packit 0848f5
    *flag = 0;
Packit 0848f5
    p = type_ptr->attributes;
Packit 0848f5
    while (p) {
Packit 0848f5
	if (p->keyval->handle == type_keyval) {
Packit 0848f5
	    *flag = 1;
Packit 0848f5
	    if (outAttrType == MPIR_ATTR_PTR) {
Packit 0848f5
		if (p->attrType == MPIR_ATTR_INT) {
Packit 0848f5
		    /* This is the tricky case: if the system is
Packit 0848f5
		       bigendian, and we have to return a pointer to
Packit 0848f5
		       an int, then we may need to point to the 
Packit 0848f5
		       correct location in the word. */
Packit 0848f5
#if defined(WORDS_LITTLEENDIAN) || (SIZEOF_VOID_P == SIZEOF_INT)
Packit 0848f5
		    *(void**)attribute_val = &(p->value);
Packit 0848f5
#else
Packit 0848f5
		    int *p_loc = (int *)&(p->value);
Packit 0848f5
#if SIZEOF_VOID_P == 2 * SIZEOF_INT
Packit 0848f5
		    p_loc++;
Packit 0848f5
#else 
Packit 0848f5
#error Expected sizeof(void*) to be either sizeof(int) or 2*sizeof(int)
Packit 0848f5
#endif
Packit 0848f5
		    *(void **)attribute_val = p_loc;
Packit 0848f5
#endif
Packit 0848f5
		}
Packit 0848f5
		else if (p->attrType == MPIR_ATTR_AINT) {
Packit 0848f5
		    *(void**)attribute_val = &(p->value);
Packit 0848f5
		}
Packit 0848f5
		else {
Packit 0848f5
		    *(void**)attribute_val = (void *)(MPIU_Pint)(p->value);
Packit 0848f5
		}
Packit 0848f5
	    }
Packit 0848f5
	    else
Packit 0848f5
		*(void**)attribute_val = (void *)(MPIU_Pint)(p->value);
Packit 0848f5
	    
Packit 0848f5
	    break;
Packit 0848f5
	}
Packit 0848f5
	p = p->next;
Packit 0848f5
    }
Packit 0848f5
    
Packit 0848f5
    /* ... end of body of routine ... */
Packit 0848f5
Packit 0848f5
#ifdef HAVE_ERROR_CHECKING
Packit 0848f5
  fn_exit:
Packit 0848f5
#endif
Packit 0848f5
    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_TYPE_GET_ATTR);
Packit 0848f5
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit 0848f5
    return mpi_errno;
Packit 0848f5
Packit 0848f5
    /* --BEGIN ERROR HANDLING-- */
Packit 0848f5
#   ifdef HAVE_ERROR_CHECKING
Packit 0848f5
  fn_fail:
Packit 0848f5
    {
Packit 0848f5
	mpi_errno = MPIR_Err_create_code(
Packit 0848f5
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 
Packit 0848f5
	    "**mpir_type_get_attr",
Packit 0848f5
	    "**mpir_type_get_attr %D %d %p %p", 
Packit 0848f5
	    datatype, type_keyval, attribute_val, flag);
Packit 0848f5
    }
Packit 0848f5
    mpi_errno = MPIR_Err_return_comm( NULL, FCNAME, mpi_errno );
Packit 0848f5
    goto fn_exit;
Packit 0848f5
#   endif
Packit 0848f5
    /* --END ERROR HANDLING-- */
Packit 0848f5
}
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
#undef FUNCNAME
Packit 0848f5
#define FUNCNAME MPI_Type_get_attr
Packit 0848f5
#undef FCNAME
Packit 0848f5
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit 0848f5
Packit 0848f5
/*@
Packit 0848f5
   MPI_Type_get_attr - Retrieves attribute value by key
Packit 0848f5
Packit 0848f5
Input Parameters:
Packit 0848f5
+ datatype - datatype to which the attribute is attached (handle)
Packit 0848f5
- type_keyval - key value (integer) 
Packit 0848f5
Packit 0848f5
Output Parameters:
Packit 0848f5
+ attribute_val - attribute value, unless flag = false 
Packit 0848f5
- flag - false if no attribute is associated with the key (logical) 
Packit 0848f5
Packit 0848f5
   Notes:
Packit 0848f5
    Attributes must be extracted from the same language as they were inserted  
Packit 0848f5
    in with 'MPI_Type_set_attr'.  The notes for C and Fortran below explain 
Packit 0848f5
    why. 
Packit 0848f5
Packit 0848f5
Notes for C:
Packit 0848f5
    Even though the 'attr_value' argument is declared as 'void *', it is
Packit 0848f5
    really the address of a void pointer.  See the rationale in the 
Packit 0848f5
    standard for more details. 
Packit 0848f5
Packit 0848f5
.N ThreadSafe
Packit 0848f5
Packit 0848f5
.N Fortran
Packit 0848f5
Packit 0848f5
.N Errors
Packit 0848f5
.N MPI_SUCCESS
Packit 0848f5
.N MPI_ERR_KEYVAL
Packit 0848f5
.N MPI_ERR_ARG
Packit 0848f5
@*/
Packit 0848f5
int MPI_Type_get_attr(MPI_Datatype datatype, int type_keyval, void *attribute_val,
Packit 0848f5
		      int *flag)
Packit 0848f5
{
Packit 0848f5
    int mpi_errno = MPI_SUCCESS;
Packit 0848f5
    MPID_MPI_STATE_DECL(MPID_STATE_MPI_TYPE_GET_ATTR);
Packit 0848f5
Packit 0848f5
    MPIR_ERRTEST_INITIALIZED_ORDIE();
Packit 0848f5
    
Packit 0848f5
    MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_TYPE_GET_ATTR);
Packit 0848f5
    
Packit 0848f5
    /* ... body of routine ...  */
Packit 0848f5
    mpi_errno = MPIR_TypeGetAttr( datatype, type_keyval, attribute_val, flag,
Packit 0848f5
				  MPIR_ATTR_PTR );
Packit 0848f5
    if (mpi_errno) goto fn_fail;
Packit 0848f5
    
Packit 0848f5
    /* ... end of body of routine ... */
Packit 0848f5
Packit 0848f5
  fn_exit:
Packit 0848f5
    MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_TYPE_GET_ATTR);
Packit 0848f5
    return mpi_errno;
Packit 0848f5
Packit 0848f5
    /* --BEGIN ERROR HANDLING-- */
Packit 0848f5
  fn_fail:
Packit 0848f5
#ifdef HAVE_ERROR_CHECKING
Packit 0848f5
    {
Packit 0848f5
	mpi_errno = MPIR_Err_create_code(
Packit 0848f5
	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 
Packit 0848f5
	    "**mpi_type_get_attr",
Packit 0848f5
	    "**mpi_type_get_attr %D %d %p %p", 
Packit 0848f5
	    datatype, type_keyval, attribute_val, flag);
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
    mpi_errno = MPIR_Err_return_comm( NULL, FCNAME, mpi_errno );
Packit 0848f5
    goto fn_exit;
Packit 0848f5
    /* --END ERROR HANDLING-- */
Packit 0848f5
}