root/ompi/op/op.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ompi_op_init
  2. ompi_op_finalize
  3. ompi_op_create_user
  4. ompi_op_set_cxx_callback
  5. ompi_op_set_java_callback
  6. add_intrinsic
  7. ompi_op_construct
  8. ompi_op_destruct

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2010 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2007-2018 Cisco Systems, Inc.  All rights reserved
  14  * Copyright (c) 2009      Sun Microsystems, Inc.  All rights reserved.
  15  * Copyright (c) 2013      Los Alamos National Security, LLC. All rights
  16  *                         reserved.
  17  * Copyright (c) 2015      Research Organization for Information Science
  18  *                         and Technology (RIST). All rights reserved.
  19  * Copyright (c) 2018      FUJITSU LIMITED.  All rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  25  */
  26 
  27 #include "ompi_config.h"
  28 
  29 #include "opal/class/opal_pointer_array.h"
  30 #include "opal/util/string_copy.h"
  31 
  32 #include "ompi/constants.h"
  33 #include "ompi/op/op.h"
  34 #include "ompi/mca/op/base/base.h"
  35 #include "ompi/datatype/ompi_datatype_internal.h"
  36 
  37 
  38 /*
  39  * Table for Fortran <-> C op handle conversion
  40  */
  41 opal_pointer_array_t *ompi_op_f_to_c_table = {0};
  42 
  43 
  44 /*
  45  * Create intrinsic op
  46  */
  47 static int add_intrinsic(ompi_op_t *op, int fort_handle, int flags,
  48                          const char *name);
  49 
  50 
  51 /*
  52  * Class information
  53  */
  54 static void ompi_op_construct(ompi_op_t *eh);
  55 static void ompi_op_destruct(ompi_op_t *eh);
  56 
  57 
  58 /*
  59  * Class instance
  60  */
  61 OBJ_CLASS_INSTANCE(ompi_op_t, opal_object_t,
  62                    ompi_op_construct, ompi_op_destruct);
  63 
  64 
  65 /*
  66  * Intrinsic MPI_Op objects (_addr flavors are for F03 bindings)
  67  */
  68 ompi_predefined_op_t ompi_mpi_op_null = {{{0}}};
  69 ompi_predefined_op_t *ompi_mpi_op_null_addr = &ompi_mpi_op_null;
  70 ompi_predefined_op_t ompi_mpi_op_max = {{{0}}};
  71 ompi_predefined_op_t *ompi_mpi_op_max_addr = &ompi_mpi_op_max;
  72 ompi_predefined_op_t ompi_mpi_op_min = {{{0}}};
  73 ompi_predefined_op_t *ompi_mpi_op_min_addr = &ompi_mpi_op_min;
  74 ompi_predefined_op_t ompi_mpi_op_sum = {{{0}}};
  75 ompi_predefined_op_t *ompi_mpi_op_sum_addr = &ompi_mpi_op_sum;
  76 ompi_predefined_op_t ompi_mpi_op_prod = {{{0}}};
  77 ompi_predefined_op_t *ompi_mpi_op_prod_addr = &ompi_mpi_op_prod;
  78 ompi_predefined_op_t ompi_mpi_op_land = {{{0}}};
  79 ompi_predefined_op_t *ompi_mpi_op_land_addr = &ompi_mpi_op_land;
  80 ompi_predefined_op_t ompi_mpi_op_band = {{{0}}};
  81 ompi_predefined_op_t *ompi_mpi_op_band_addr = &ompi_mpi_op_band;
  82 ompi_predefined_op_t ompi_mpi_op_lor = {{{0}}};
  83 ompi_predefined_op_t *ompi_mpi_op_lor_addr = &ompi_mpi_op_lor;
  84 ompi_predefined_op_t ompi_mpi_op_bor = {{{0}}};
  85 ompi_predefined_op_t *ompi_mpi_op_bor_addr = &ompi_mpi_op_bor;
  86 ompi_predefined_op_t ompi_mpi_op_lxor = {{{0}}};
  87 ompi_predefined_op_t *ompi_mpi_op_lxor_addr = &ompi_mpi_op_lxor;
  88 ompi_predefined_op_t ompi_mpi_op_bxor = {{{0}}};
  89 ompi_predefined_op_t *ompi_mpi_op_bxor_addr = &ompi_mpi_op_bxor;
  90 ompi_predefined_op_t ompi_mpi_op_maxloc = {{{0}}};
  91 ompi_predefined_op_t *ompi_mpi_op_maxloc_addr = &ompi_mpi_op_maxloc;
  92 ompi_predefined_op_t ompi_mpi_op_minloc = {{{0}}};
  93 ompi_predefined_op_t *ompi_mpi_op_minloc_addr = &ompi_mpi_op_minloc;
  94 ompi_predefined_op_t ompi_mpi_op_replace = {{{0}}};
  95 ompi_predefined_op_t *ompi_mpi_op_replace_addr = &ompi_mpi_op_replace;
  96 ompi_predefined_op_t ompi_mpi_op_no_op = {{{0}}};
  97 ompi_predefined_op_t *ompi_mpi_op_no_op_addr = &ompi_mpi_op_no_op;
  98 
  99 /*
 100  * Map from ddt->id to position in op function pointer array
 101  */
 102 int ompi_op_ddt_map[OMPI_DATATYPE_MAX_PREDEFINED] = {0};
 103 
 104 /* Get the c complex operator associated with a fortran complex type */
 105 #define FORTRAN_COMPLEX_OP_TYPE_X(type) OMPI_OP_BASE_TYPE_ ## type
 106 /* Preprocessor hack to ensure type gets expanded correctly */
 107 #define FORTRAN_COMPLEX_OP_TYPE(type) FORTRAN_COMPLEX_OP_TYPE_X(type)
 108 
 109 #define FLAGS_NO_FLOAT \
 110     (OMPI_OP_FLAGS_INTRINSIC | OMPI_OP_FLAGS_ASSOC | OMPI_OP_FLAGS_COMMUTE)
 111 #define FLAGS \
 112     (OMPI_OP_FLAGS_INTRINSIC | OMPI_OP_FLAGS_ASSOC | \
 113      OMPI_OP_FLAGS_FLOAT_ASSOC | OMPI_OP_FLAGS_COMMUTE)
 114 
 115 /*
 116  * Initialize OMPI op infrastructure
 117  */
 118 int ompi_op_init(void)
 119 {
 120     int i;
 121 
 122   /* initialize ompi_op_f_to_c_table */
 123 
 124     ompi_op_f_to_c_table = OBJ_NEW(opal_pointer_array_t);
 125     if (NULL == ompi_op_f_to_c_table){
 126         return OMPI_ERROR;
 127     }
 128 
 129     /* Fill in the ddt.id->op_position map */
 130 
 131     for (i = 0; i < OMPI_DATATYPE_MAX_PREDEFINED; ++i) {
 132         ompi_op_ddt_map[i] = -1;
 133     }
 134 
 135     ompi_op_ddt_map[OMPI_DATATYPE_MPI_INT8_T] = OMPI_OP_BASE_TYPE_INT8_T;
 136     ompi_op_ddt_map[OMPI_DATATYPE_MPI_UINT8_T] = OMPI_OP_BASE_TYPE_UINT8_T;
 137     ompi_op_ddt_map[OMPI_DATATYPE_MPI_INT16_T] = OMPI_OP_BASE_TYPE_INT16_T;
 138     ompi_op_ddt_map[OMPI_DATATYPE_MPI_UINT16_T] = OMPI_OP_BASE_TYPE_UINT16_T;
 139     ompi_op_ddt_map[OMPI_DATATYPE_MPI_INT32_T] = OMPI_OP_BASE_TYPE_INT32_T;
 140     ompi_op_ddt_map[OMPI_DATATYPE_MPI_UINT32_T] = OMPI_OP_BASE_TYPE_UINT32_T;
 141     ompi_op_ddt_map[OMPI_DATATYPE_MPI_INT64_T] = OMPI_OP_BASE_TYPE_INT64_T;
 142     ompi_op_ddt_map[OMPI_DATATYPE_MPI_UINT64_T] = OMPI_OP_BASE_TYPE_UINT64_T;
 143 
 144     ompi_op_ddt_map[OMPI_DATATYPE_MPI_FLOAT] = OMPI_OP_BASE_TYPE_FLOAT;
 145     ompi_op_ddt_map[OMPI_DATATYPE_MPI_DOUBLE] = OMPI_OP_BASE_TYPE_DOUBLE;
 146     ompi_op_ddt_map[OMPI_DATATYPE_MPI_LONG_DOUBLE] = OMPI_OP_BASE_TYPE_LONG_DOUBLE;
 147 
 148 #if OMPI_HAVE_FORTRAN_COMPLEX4
 149     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COMPLEX4] = FORTRAN_COMPLEX_OP_TYPE(OMPI_KIND_FORTRAN_COMPLEX4);
 150 #endif
 151 
 152 #if OMPI_HAVE_FORTRAN_COMPLEX8
 153     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COMPLEX8] = FORTRAN_COMPLEX_OP_TYPE(OMPI_KIND_FORTRAN_COMPLEX8);
 154 #endif
 155 
 156 #if OMPI_HAVE_FORTRAN_COMPLEX16
 157     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COMPLEX16] = FORTRAN_COMPLEX_OP_TYPE(OMPI_KIND_FORTRAN_COMPLEX16);
 158 #endif
 159 
 160     /* Only enable reductions on COMPLEX32 if the REAL*16 matches the equivalent C type */
 161 #if OMPI_REAL16_MATCHES_C && OMPI_HAVE_FORTRAN_COMPLEX32
 162     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COMPLEX32] = FORTRAN_COMPLEX_OP_TYPE(OMPI_KIND_FORTRAN_COMPLEX32);
 163 #endif
 164 
 165     ompi_op_ddt_map[OMPI_DATATYPE_MPI_WCHAR] = OMPI_OP_BASE_TYPE_WCHAR;
 166     ompi_op_ddt_map[OMPI_DATATYPE_MPI_BOOL] = OMPI_OP_BASE_TYPE_BOOL;
 167     ompi_op_ddt_map[OMPI_DATATYPE_MPI_LOGICAL] = OMPI_OP_BASE_TYPE_LOGICAL;
 168     ompi_op_ddt_map[OMPI_DATATYPE_MPI_CHARACTER] = OMPI_OP_BASE_TYPE_UINT8_T;
 169     ompi_op_ddt_map[OMPI_DATATYPE_MPI_INTEGER] = OMPI_OP_BASE_TYPE_INTEGER;
 170     ompi_op_ddt_map[OMPI_DATATYPE_MPI_REAL] = OMPI_OP_BASE_TYPE_REAL;
 171     ompi_op_ddt_map[OMPI_DATATYPE_MPI_DOUBLE_PRECISION] = OMPI_OP_BASE_TYPE_DOUBLE_PRECISION;
 172 
 173 #if OMPI_HAVE_FORTRAN_COMPLEX
 174     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COMPLEX] = FORTRAN_COMPLEX_OP_TYPE(OMPI_KIND_FORTRAN_COMPLEX);
 175 #endif
 176 
 177 #if OMPI_HAVE_FORTRAN_DOUBLE_COMPLEX
 178     ompi_op_ddt_map[OMPI_DATATYPE_MPI_DOUBLE_COMPLEX] = FORTRAN_COMPLEX_OP_TYPE(OMPI_KIND_FORTRAN_DOUBLE_COMPLEX);
 179 #endif
 180 
 181     ompi_op_ddt_map[OMPI_DATATYPE_MPI_LONG_DOUBLE_COMPLEX] = OMPI_OP_BASE_TYPE_C_LONG_DOUBLE_COMPLEX;
 182 
 183     ompi_op_ddt_map[OMPI_DATATYPE_MPI_2INT] = OMPI_OP_BASE_TYPE_2INT;
 184     ompi_op_ddt_map[OMPI_DATATYPE_MPI_2INTEGER] = OMPI_OP_BASE_TYPE_2INTEGER;
 185     ompi_op_ddt_map[OMPI_DATATYPE_MPI_2REAL] = OMPI_OP_BASE_TYPE_2REAL;
 186     ompi_op_ddt_map[OMPI_DATATYPE_MPI_2DBLPREC] = OMPI_OP_BASE_TYPE_2DOUBLE_PRECISION;
 187     ompi_op_ddt_map[OMPI_DATATYPE_MPI_2COMPLEX] = -1;         /* Not defined */
 188     ompi_op_ddt_map[OMPI_DATATYPE_MPI_2DOUBLE_COMPLEX] = -1;  /* Not defined */
 189 
 190     ompi_op_ddt_map[OMPI_DATATYPE_MPI_FLOAT_INT] = OMPI_OP_BASE_TYPE_FLOAT_INT;
 191     ompi_op_ddt_map[OMPI_DATATYPE_MPI_DOUBLE_INT] = OMPI_OP_BASE_TYPE_DOUBLE_INT;
 192     ompi_op_ddt_map[OMPI_DATATYPE_MPI_LONG_DOUBLE_INT] = OMPI_OP_BASE_TYPE_LONG_DOUBLE_INT;
 193     ompi_op_ddt_map[OMPI_DATATYPE_MPI_LONG_INT] = OMPI_OP_BASE_TYPE_LONG_INT;
 194     ompi_op_ddt_map[OMPI_DATATYPE_MPI_SHORT_INT] = OMPI_OP_BASE_TYPE_SHORT_INT;
 195 
 196 #if SIZEOF_PTRDIFF_T == 4
 197     ompi_op_ddt_map[OMPI_DATATYPE_MPI_AINT] = OMPI_OP_BASE_TYPE_INT32_T;
 198 #elif SIZEOF_PTRDIFF_T == 8
 199     ompi_op_ddt_map[OMPI_DATATYPE_MPI_AINT] = OMPI_OP_BASE_TYPE_INT64_T;
 200 #else
 201 #warning Unsupported definition for MPI_AINT
 202 #endif
 203 #if OMPI_MPI_OFFSET_SIZE == 4
 204     ompi_op_ddt_map[OMPI_DATATYPE_MPI_OFFSET] = OMPI_OP_BASE_TYPE_UINT32_T;
 205 #elif OMPI_MPI_OFFSET_SIZE == 8
 206     ompi_op_ddt_map[OMPI_DATATYPE_MPI_OFFSET] = OMPI_OP_BASE_TYPE_UINT64_T;
 207 #else
 208 #warning Unsupported definition for MPI_OFFSET
 209 #endif
 210     ompi_op_ddt_map[OMPI_DATATYPE_MPI_C_BOOL] = OMPI_OP_BASE_TYPE_BOOL;
 211     ompi_op_ddt_map[OMPI_DATATYPE_MPI_C_COMPLEX] = OMPI_OP_BASE_TYPE_C_FLOAT_COMPLEX;
 212     ompi_op_ddt_map[OMPI_DATATYPE_MPI_C_FLOAT_COMPLEX] = OMPI_OP_BASE_TYPE_C_FLOAT_COMPLEX;
 213     ompi_op_ddt_map[OMPI_DATATYPE_MPI_C_DOUBLE_COMPLEX] = OMPI_OP_BASE_TYPE_C_DOUBLE_COMPLEX;
 214     ompi_op_ddt_map[OMPI_DATATYPE_MPI_C_LONG_DOUBLE_COMPLEX] = OMPI_OP_BASE_TYPE_C_LONG_DOUBLE_COMPLEX;
 215 
 216     /* MPI 3.0 datatypes */
 217 #if OMPI_MPI_COUNT_SIZE == 4
 218     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COUNT] = OMPI_OP_BASE_TYPE_INT32_T;
 219 #elif OMPI_MPI_COUNT_SIZE == 8
 220     ompi_op_ddt_map[OMPI_DATATYPE_MPI_COUNT] = OMPI_OP_BASE_TYPE_INT64_T;
 221 #else
 222 #warning Unsupported definition for MPI_COUNT
 223 #endif
 224 
 225     /* Datatypes proposed to the MPI Forum in June 2017 for proposal in
 226      * the MPI 4.0 standard. As of February 2019, it is not accepted yet.
 227      * See https://github.com/mpi-forum/mpi-issues/issues/65 */
 228     ompi_op_ddt_map[OMPI_DATATYPE_MPI_SHORT_FLOAT] = OMPI_OP_BASE_TYPE_SHORT_FLOAT;
 229     ompi_op_ddt_map[OMPI_DATATYPE_MPI_C_SHORT_FLOAT_COMPLEX] = OMPI_OP_BASE_TYPE_C_SHORT_FLOAT_COMPLEX;
 230 
 231     /* Create the intrinsic ops */
 232 
 233     if (OMPI_SUCCESS !=
 234         add_intrinsic(&ompi_mpi_op_null.op, OMPI_OP_BASE_FORTRAN_NULL,
 235                       FLAGS, "MPI_NULL") ||
 236         OMPI_SUCCESS !=
 237         add_intrinsic(&ompi_mpi_op_max.op, OMPI_OP_BASE_FORTRAN_MAX,
 238                       FLAGS, "MPI_MAX") ||
 239         OMPI_SUCCESS !=
 240         add_intrinsic(&ompi_mpi_op_min.op, OMPI_OP_BASE_FORTRAN_MIN,
 241                       FLAGS, "MPI_MIN") ||
 242         OMPI_SUCCESS !=
 243         add_intrinsic(&ompi_mpi_op_sum.op, OMPI_OP_BASE_FORTRAN_SUM,
 244                       FLAGS_NO_FLOAT, "MPI_SUM") ||
 245         OMPI_SUCCESS !=
 246         add_intrinsic(&ompi_mpi_op_prod.op, OMPI_OP_BASE_FORTRAN_PROD,
 247                       FLAGS_NO_FLOAT, "MPI_PROD") ||
 248         OMPI_SUCCESS !=
 249         add_intrinsic(&ompi_mpi_op_land.op, OMPI_OP_BASE_FORTRAN_LAND,
 250                       FLAGS, "MPI_LAND") ||
 251         OMPI_SUCCESS !=
 252         add_intrinsic(&ompi_mpi_op_band.op, OMPI_OP_BASE_FORTRAN_BAND,
 253                       FLAGS, "MPI_BAND") ||
 254         OMPI_SUCCESS !=
 255         add_intrinsic(&ompi_mpi_op_lor.op, OMPI_OP_BASE_FORTRAN_LOR,
 256                       FLAGS, "MPI_LOR") ||
 257         OMPI_SUCCESS !=
 258         add_intrinsic(&ompi_mpi_op_bor.op, OMPI_OP_BASE_FORTRAN_BOR,
 259                       FLAGS, "MPI_BOR") ||
 260         OMPI_SUCCESS !=
 261         add_intrinsic(&ompi_mpi_op_lxor.op, OMPI_OP_BASE_FORTRAN_LXOR,
 262                       FLAGS, "MPI_LXOR") ||
 263         OMPI_SUCCESS !=
 264         add_intrinsic(&ompi_mpi_op_bxor.op, OMPI_OP_BASE_FORTRAN_BXOR,
 265                       FLAGS, "MPI_BXOR") ||
 266         OMPI_SUCCESS !=
 267         add_intrinsic(&ompi_mpi_op_maxloc.op, OMPI_OP_BASE_FORTRAN_MAXLOC,
 268                       FLAGS, "MPI_MAXLOC") ||
 269         OMPI_SUCCESS !=
 270         add_intrinsic(&ompi_mpi_op_minloc.op, OMPI_OP_BASE_FORTRAN_MINLOC,
 271                       FLAGS, "MPI_MINLOC") ||
 272         OMPI_SUCCESS !=
 273         add_intrinsic(&ompi_mpi_op_replace.op, OMPI_OP_BASE_FORTRAN_REPLACE,
 274                       FLAGS, "MPI_REPLACE") ||
 275         OMPI_SUCCESS !=
 276         add_intrinsic(&ompi_mpi_op_no_op.op, OMPI_OP_BASE_FORTRAN_NO_OP,
 277                       FLAGS, "MPI_NO_OP")) {
 278         return OMPI_ERROR;
 279     }else{
 280 /* This code is placed back here to support
 281  * HCOL allreduce at the moment. It is a part of bgate repository only. This conflict with OMPI v1.7
 282  * is to be resolved some other way.
 283  * */
 284         ompi_mpi_op_null.op.op_type = OMPI_OP_NULL;
 285         ompi_mpi_op_max.op.op_type = OMPI_OP_MAX;
 286         ompi_mpi_op_min.op.op_type = OMPI_OP_MIN;
 287         ompi_mpi_op_sum.op.op_type = OMPI_OP_SUM;
 288         ompi_mpi_op_prod.op.op_type = OMPI_OP_PROD;
 289         ompi_mpi_op_land.op.op_type = OMPI_OP_LAND;
 290         ompi_mpi_op_band.op.op_type = OMPI_OP_BAND;
 291         ompi_mpi_op_lor.op.op_type = OMPI_OP_LOR;
 292         ompi_mpi_op_bor.op.op_type = OMPI_OP_BOR;
 293         ompi_mpi_op_lxor.op.op_type = OMPI_OP_LXOR;
 294         ompi_mpi_op_bxor.op.op_type = OMPI_OP_BXOR;
 295         ompi_mpi_op_maxloc.op.op_type = OMPI_OP_MAXLOC;
 296         ompi_mpi_op_minloc.op.op_type = OMPI_OP_MINLOC;
 297         ompi_mpi_op_replace.op.op_type = OMPI_OP_REPLACE;
 298     }
 299 
 300     /* All done */
 301     return OMPI_SUCCESS;
 302 }
 303 
 304 
 305 /*
 306  * Clean up the op resources
 307  */
 308 int ompi_op_finalize(void)
 309 {
 310     /* clean up the intrinsic ops */
 311     OBJ_DESTRUCT(&ompi_mpi_op_no_op);
 312     OBJ_DESTRUCT(&ompi_mpi_op_replace);
 313     OBJ_DESTRUCT(&ompi_mpi_op_minloc);
 314     OBJ_DESTRUCT(&ompi_mpi_op_maxloc);
 315     OBJ_DESTRUCT(&ompi_mpi_op_bxor);
 316     OBJ_DESTRUCT(&ompi_mpi_op_lxor);
 317     OBJ_DESTRUCT(&ompi_mpi_op_bor);
 318     OBJ_DESTRUCT(&ompi_mpi_op_lor);
 319     OBJ_DESTRUCT(&ompi_mpi_op_band);
 320     OBJ_DESTRUCT(&ompi_mpi_op_land);
 321     OBJ_DESTRUCT(&ompi_mpi_op_prod);
 322     OBJ_DESTRUCT(&ompi_mpi_op_sum);
 323     OBJ_DESTRUCT(&ompi_mpi_op_min);
 324     OBJ_DESTRUCT(&ompi_mpi_op_max);
 325     OBJ_DESTRUCT(&ompi_mpi_op_null);
 326 
 327     /* Remove op F2C table */
 328 
 329     OBJ_RELEASE(ompi_op_f_to_c_table);
 330 
 331     /* All done */
 332 
 333     return OMPI_SUCCESS;
 334 }
 335 
 336 
 337 /*
 338  * Create a new MPI_Op
 339  */
 340 ompi_op_t *ompi_op_create_user(bool commute,
 341                                ompi_op_fortran_handler_fn_t func)
 342 {
 343     ompi_op_t *new_op;
 344 
 345     /* Create a new object and ensure that it's valid */
 346     new_op = OBJ_NEW(ompi_op_t);
 347     if (NULL == new_op) {
 348         goto error;
 349     }
 350 
 351     if (0 > new_op->o_f_to_c_index) {
 352         OBJ_RELEASE(new_op);
 353         new_op = NULL;
 354         goto error;
 355     }
 356 
 357     /*
 358      * The new object is valid -- initialize it.  If this is being
 359      *  created from fortran, the fortran MPI API wrapper function
 360      *  will override the o_flags field directly.  We cast the
 361      *  function pointer type to the fortran type arbitrarily -- it
 362      *  only has to be a function pointer in order to store properly,
 363      *  it doesn't matter what type it is (we'll cast it to the Right
 364      *  type when we *use* it).
 365      */
 366     new_op->o_flags = OMPI_OP_FLAGS_ASSOC;
 367     if (commute) {
 368         new_op->o_flags |= OMPI_OP_FLAGS_COMMUTE;
 369     }
 370 
 371     opal_string_copy(new_op->o_name, "USER OP", sizeof(new_op->o_name));
 372     new_op->o_name[sizeof(new_op->o_name) - 1] = '\0';
 373 
 374     /* Set the user-defined callback function.  The "fort_fn" member
 375        is part of a union, so it doesn't matter if this is a C or
 376        Fortan callback; we'll call the right flavor (per o_flags) at
 377        invocation time. */
 378     new_op->o_func.fort_fn = func;
 379 
 380 error:
 381     /* All done */
 382     return new_op;
 383 }
 384 
 385 
 386 /*
 387  * See lengthy comment in mpi/cxx/intercepts.cc for how the C++ MPI::Op
 388  * callbacks work.
 389  */
 390 void ompi_op_set_cxx_callback(ompi_op_t *op, MPI_User_function *fn)
 391 {
 392     op->o_flags |= OMPI_OP_FLAGS_CXX_FUNC;
 393     /* The OMPI C++ intercept was previously stored in
 394        op->o_func.fort_fn by ompi_op_create_user().  So save that in
 395        cxx.intercept_fn and put the user's fn in cxx.user_fn. */
 396     op->o_func.cxx_data.intercept_fn =
 397         (ompi_op_cxx_handler_fn_t *) op->o_func.fort_fn;
 398     op->o_func.cxx_data.user_fn = fn;
 399 }
 400 
 401 
 402 /*
 403  * See lengthy comment in mpi/cxx/intercepts.cc for how the C++ MPI::Op
 404  * callbacks work.
 405  */
 406 void ompi_op_set_java_callback(ompi_op_t *op, void *jnienv,
 407                                void *object, int baseType)
 408 {
 409     op->o_flags |= OMPI_OP_FLAGS_JAVA_FUNC;
 410     /* The OMPI Java intercept was previously stored in
 411        op->o_func.fort_fn by ompi_op_create_user().  So save that in
 412        cxx.intercept_fn and put the user's fn in cxx.user_fn. */
 413     op->o_func.java_data.intercept_fn =
 414         (ompi_op_java_handler_fn_t *) op->o_func.fort_fn;
 415     op->o_func.java_data.jnienv = jnienv;
 416     op->o_func.java_data.object = object;
 417     op->o_func.java_data.baseType = baseType;
 418 }
 419 
 420 
 421 /**************************************************************************
 422  *
 423  * Static functions
 424  *
 425  **************************************************************************/
 426 
 427 static int add_intrinsic(ompi_op_t *op, int fort_handle, int flags,
 428                          const char *name)
 429 {
 430     /* Add the op to the table */
 431     OBJ_CONSTRUCT(op, ompi_op_t);
 432     if (op->o_f_to_c_index != fort_handle) {
 433         return OMPI_ERROR;
 434     }
 435 
 436     /* Set the members */
 437     op->o_flags = flags;
 438     opal_string_copy(op->o_name, name, sizeof(op->o_name));
 439     op->o_name[sizeof(op->o_name) - 1] = '\0';
 440 
 441     /* Perform the selection on this op to fill in the function
 442        pointers (except for NULL and REPLACE, which don't get
 443        components) */
 444     if (OMPI_OP_BASE_FORTRAN_NULL != op->o_f_to_c_index &&
 445         OMPI_OP_BASE_FORTRAN_REPLACE != op->o_f_to_c_index &&
 446         OMPI_OP_BASE_FORTRAN_NO_OP != op->o_f_to_c_index) {
 447         return ompi_op_base_op_select(op);
 448     } else {
 449         return OMPI_SUCCESS;
 450     }
 451 }
 452 
 453 
 454 /*
 455  * Op constructor
 456  */
 457 static void ompi_op_construct(ompi_op_t *new_op)
 458 {
 459     int i;
 460 
 461     /* Provide a default of a high value. Useful for non-predefined ops. */
 462     new_op->op_type = OMPI_OP_NUM_OF_TYPES;
 463     new_op->o_flags = 0;
 464     new_op->o_name[0] = '\0';
 465 
 466     /* assign entry in fortran <-> c translation array */
 467 
 468     new_op->o_f_to_c_index =
 469         opal_pointer_array_add(ompi_op_f_to_c_table, new_op);
 470 
 471     /* Set everything to NULL so that we can intelligently free
 472        non-NULL's in the destructor */
 473     for (i = 0; i < OMPI_OP_BASE_TYPE_MAX; ++i) {
 474         new_op->o_func.intrinsic.fns[i] = NULL;
 475         new_op->o_func.intrinsic.modules[i] = NULL;
 476         new_op->o_3buff_intrinsic.fns[i] = NULL;
 477         new_op->o_3buff_intrinsic.modules[i] = NULL;
 478     }
 479 }
 480 
 481 
 482 /*
 483  * Op destructor
 484  */
 485 static void ompi_op_destruct(ompi_op_t *op)
 486 {
 487     int i;
 488 
 489     /* reset the ompi_op_f_to_c_table entry - make sure that the
 490        entry is in the table */
 491 
 492     if (NULL != opal_pointer_array_get_item(ompi_op_f_to_c_table,
 493                                             op->o_f_to_c_index)) {
 494         opal_pointer_array_set_item(ompi_op_f_to_c_table,
 495                                     op->o_f_to_c_index, NULL);
 496     }
 497 
 498     for (i = 0; i < OMPI_OP_BASE_TYPE_MAX; ++i) {
 499         op->o_func.intrinsic.fns[i] = NULL;
 500         if( NULL != op->o_func.intrinsic.modules[i] ) {
 501             OBJ_RELEASE(op->o_func.intrinsic.modules[i]);
 502             op->o_func.intrinsic.modules[i] = NULL;
 503         }
 504         op->o_3buff_intrinsic.fns[i] = NULL;
 505         if( NULL != op->o_3buff_intrinsic.modules[i] ) {
 506             OBJ_RELEASE(op->o_3buff_intrinsic.modules[i]);
 507             op->o_3buff_intrinsic.modules[i] = NULL;
 508         }
 509     }
 510 }

/* [<][>][^][v][top][bottom][index][help] */