Blame src/mpi/coll/op/op_create.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *  (C) 2001 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
#include "mpiimpl.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* -- Begin Profiling Symbol Block for routine MPI_Op_create */
Packit Service c5cf8c
#if defined(HAVE_PRAGMA_WEAK)
Packit Service c5cf8c
#pragma weak MPI_Op_create = PMPI_Op_create
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
Packit Service c5cf8c
#pragma _HP_SECONDARY_DEF PMPI_Op_create  MPI_Op_create
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_CRI_DUP)
Packit Service c5cf8c
#pragma _CRI duplicate MPI_Op_create as PMPI_Op_create
Packit Service c5cf8c
#elif defined(HAVE_WEAK_ATTRIBUTE)
Packit Service c5cf8c
int MPI_Op_create(MPI_User_function * user_fn, int commute, MPI_Op * op)
Packit Service c5cf8c
    __attribute__ ((weak, alias("PMPI_Op_create")));
Packit Service c5cf8c
#endif
Packit Service c5cf8c
/* -- End Profiling Symbol Block */
Packit Service c5cf8c
Packit Service c5cf8c
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
Packit Service c5cf8c
   the MPI routines */
Packit Service c5cf8c
#ifndef MPICH_MPI_FROM_PMPI
Packit Service c5cf8c
#undef MPI_Op_create
Packit Service c5cf8c
#define MPI_Op_create PMPI_Op_create
Packit Service c5cf8c
Packit Service c5cf8c
#ifndef MPIR_OP_PREALLOC
Packit Service c5cf8c
#define MPIR_OP_PREALLOC 16
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/* Preallocated op objects */
Packit Service c5cf8c
MPIR_Op MPIR_Op_builtin[MPIR_OP_N_BUILTIN] = { {0} };
Packit Service c5cf8c
MPIR_Op MPIR_Op_direct[MPIR_OP_PREALLOC] = { {0} };
Packit Service c5cf8c
Packit Service c5cf8c
MPIR_Object_alloc_t MPIR_Op_mem = { 0, 0, 0, 0, MPIR_OP,
Packit Service c5cf8c
    sizeof(MPIR_Op),
Packit Service c5cf8c
    MPIR_Op_direct,
Packit Service c5cf8c
    MPIR_OP_PREALLOC,
Packit Service c5cf8c
};
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef HAVE_CXX_BINDING
Packit Service c5cf8c
void MPII_Op_set_cxx(MPI_Op op, void (*opcall) (void))
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Op *op_ptr;
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_Op_get_ptr(op, op_ptr);
Packit Service c5cf8c
    op_ptr->language = MPIR_LANG__CXX;
Packit Service c5cf8c
    MPIR_Process.cxx_call_op_fn = (void (*)(const void *, void *, int,
Packit Service c5cf8c
                                            MPI_Datatype, MPI_User_function *)) opcall;
Packit Service c5cf8c
}
Packit Service c5cf8c
#endif
Packit Service c5cf8c
#if defined(HAVE_FORTRAN_BINDING) && !defined(HAVE_FINT_IS_INT)
Packit Service c5cf8c
/* Normally, the C and Fortran versions are the same, by design in the
Packit Service c5cf8c
   MPI Standard.  However, if MPI_Fint and int are not the same size (e.g.,
Packit Service c5cf8c
   MPI_Fint was made 8 bytes but int is 4 bytes), then the C and Fortran
Packit Service c5cf8c
   versions must be distinquished. */
Packit Service c5cf8c
void MPII_Op_set_fc(MPI_Op op)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Op *op_ptr;
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_Op_get_ptr(op, op_ptr);
Packit Service c5cf8c
    op_ptr->language = MPIR_LANG__FORTRAN;
Packit Service c5cf8c
}
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Op_create_impl
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Op_create_impl(MPI_User_function * user_fn, int commute, MPI_Op * op)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Op *op_ptr;
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    op_ptr = (MPIR_Op *) MPIR_Handle_obj_alloc(&MPIR_Op_mem);
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
    if (!op_ptr) {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
Packit Service c5cf8c
                                 "**nomem", "**nomem %s", "MPI_Op");
Packit Service c5cf8c
        goto fn_fail;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
Packit Service c5cf8c
    op_ptr->language = MPIR_LANG__C;
Packit Service c5cf8c
    op_ptr->kind = commute ? MPIR_OP_KIND__USER : MPIR_OP_KIND__USER_NONCOMMUTE;
Packit Service c5cf8c
    op_ptr->function.c_function = (void (*)(const void *, void *,
Packit Service c5cf8c
                                            const int *, const MPI_Datatype *)) user_fn;
Packit Service c5cf8c
    MPIR_Object_set_ref(op_ptr, 1);
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_OBJ_PUBLISH_HANDLE(*op, op_ptr->handle);
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPID_Op_commit_hook
Packit Service c5cf8c
    MPID_Op_commit_hook(op_ptr);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#endif /* MPICH_MPI_FROM_PMPI */
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPI_Op_create
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
/*@
Packit Service c5cf8c
  MPI_Op_create - Creates a user-defined combination function handle
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ user_fn - user defined function (function)
Packit Service c5cf8c
- commute -  true if commutative;  false otherwise. (logical)
Packit Service c5cf8c
Packit Service c5cf8c
Output Parameters:
Packit Service c5cf8c
. op - operation (handle)
Packit Service c5cf8c
Packit Service c5cf8c
  Notes on the user function:
Packit Service c5cf8c
  The calling list for the user function type is
Packit Service c5cf8c
.vb
Packit Service c5cf8c
 typedef void (MPI_User_function) (void * a,
Packit Service c5cf8c
               void * b, int * len, MPI_Datatype *);
Packit Service c5cf8c
.ve
Packit Service c5cf8c
  where the operation is 'b[i] = a[i] op b[i]', for 'i=0,...,len-1'.  A pointer
Packit Service c5cf8c
  to the datatype given to the MPI collective computation routine (i.e.,
Packit Service c5cf8c
  'MPI_Reduce', 'MPI_Allreduce', 'MPI_Scan', or 'MPI_Reduce_scatter') is also
Packit Service c5cf8c
  passed to the user-specified routine.
Packit Service c5cf8c
Packit Service c5cf8c
.N ThreadSafe
Packit Service c5cf8c
Packit Service c5cf8c
.N Fortran
Packit Service c5cf8c
Packit Service c5cf8c
.N collops
Packit Service c5cf8c
Packit Service c5cf8c
.N Errors
Packit Service c5cf8c
.N MPI_SUCCESS
Packit Service c5cf8c
Packit Service c5cf8c
.seealso: MPI_Op_free
Packit Service c5cf8c
@*/
Packit Service c5cf8c
int MPI_Op_create(MPI_User_function * user_fn, int commute, MPI_Op * op)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_OP_CREATE);
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_ERRTEST_INITIALIZED_ORDIE();
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_OP_CREATE);
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... body of routine ...  */
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Op_create_impl(user_fn, commute, op);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        goto fn_fail;
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... end of body of routine ... */
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_OP_CREATE);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
Packit Service c5cf8c
                                 "**mpi_op_create", "**mpi_op_create %p %d %p", user_fn, commute,
Packit Service c5cf8c
                                 op);
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    mpi_errno = MPIR_Err_return_comm(0, FCNAME, mpi_errno);
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
}