root/ompi/mca/op/base/op_base_op_select.c

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

DEFINITIONS

This source file includes following definitions.
  1. ompi_op_base_op_select
  2. avail_op_compare
  3. check_components
  4. check_one_component
  5. query
  6. query_1_0_0

   1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2009 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 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      Lawrence Livermore National Security, LLC.  All
  14  *                         rights reserved.
  15  * Copyright (c) 2008      Sun Microsystems, Inc.  All rights reserved.
  16  * Copyright (c) 2008-2015 Cisco Systems, Inc.  All rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 #include "ompi_config.h"
  25 
  26 #include <stdio.h>
  27 #include <string.h>
  28 #include <stdlib.h>
  29 
  30 #include "mpi.h"
  31 #include "ompi/constants.h"
  32 
  33 #include "opal/util/output.h"
  34 #include "opal/class/opal_list.h"
  35 #include "opal/class/opal_object.h"
  36 #include "ompi/mca/mca.h"
  37 #include "opal/mca/base/base.h"
  38 
  39 
  40 #include "ompi/op/op.h"
  41 #include "ompi/mca/op/op.h"
  42 #include "ompi/mca/op/base/base.h"
  43 #include "ompi/mca/op/base/functions.h"
  44 
  45 
  46 /*
  47  * Local types
  48  */
  49 typedef struct avail_op_t {
  50     opal_list_item_t super;
  51 
  52     int ao_priority;
  53     ompi_op_base_module_1_0_0_t *ao_module;
  54 } avail_op_t;
  55 
  56 
  57 /*
  58  * Local functions
  59  */
  60 static opal_list_t *check_components(opal_list_t *components,
  61                                      ompi_op_t *op);
  62 static int check_one_component(ompi_op_t *op,
  63                                const mca_base_component_t *component,
  64                                ompi_op_base_module_1_0_0_t **module);
  65 
  66 static int query(const mca_base_component_t *component,
  67                  ompi_op_t *op, int *priority,
  68                  ompi_op_base_module_1_0_0_t **module);
  69 
  70 static int query_1_0_0(const ompi_op_base_component_1_0_0_t *op_component,
  71                        ompi_op_t *op, int *priority,
  72                        ompi_op_base_module_1_0_0_t **module);
  73 
  74 /*
  75  * Stuff for the OBJ interface
  76  */
  77 static OBJ_CLASS_INSTANCE(avail_op_t, opal_list_item_t, NULL, NULL);
  78 
  79 
  80 /*
  81  * This function is called at the initialization time of every
  82  * *intrinsic* MPI_Op (it is *not* used for user-defined MPI_Ops!).
  83  * It is used to select which op component(s) will be active for a
  84  * given MPI_Op.
  85  *
  86  * This selection logic is not for the weak.
  87  */
  88 int ompi_op_base_op_select(ompi_op_t *op)
  89 {
  90     int i, ret;
  91     opal_list_t *selectable;
  92     opal_list_item_t *item;
  93     ompi_op_base_module_t *module;
  94 
  95     /* Announce */
  96     opal_output_verbose(10, ompi_op_base_framework.framework_output,
  97                         "op:base:op_select: new op: %s",
  98                         op->o_name);
  99 
 100     /* Make a module for all the base functions so that other modules
 101        can RETAIN it (vs. having NULL for the base function modules,
 102        and forcing all other modules to check for NULL before calling
 103        RETAIN). */
 104     module = OBJ_NEW(ompi_op_base_module_t);
 105 
 106     /* Initialize all functions to point to the corresponding base
 107        functions.  Set the corresponding module pointers to NULL,
 108        indicating that these are base functions with no corresponding
 109        module. */
 110     memset(&op->o_func, 0, sizeof(op->o_func));
 111     memset(&op->o_3buff_intrinsic, 0, sizeof(op->o_3buff_intrinsic));
 112     for (i = 0; i < OMPI_OP_BASE_TYPE_MAX; ++i) {
 113         op->o_func.intrinsic.fns[i] =
 114             ompi_op_base_functions[op->o_f_to_c_index][i];
 115         op->o_func.intrinsic.modules[i] = module;
 116         OBJ_RETAIN(module);
 117         op->o_3buff_intrinsic.fns[i] =
 118             ompi_op_base_3buff_functions[op->o_f_to_c_index][i];
 119         op->o_3buff_intrinsic.modules[i] = module;
 120         OBJ_RETAIN(module);
 121     }
 122 
 123     /* Offset the initial OBJ_NEW */
 124     OBJ_RELEASE(module);
 125 
 126     /* Check for any components that want to run.  It's not an error
 127        if there are none; we'll just use all the base functions in
 128        this case. */
 129     opal_output_verbose(10, ompi_op_base_framework.framework_output,
 130                         "op:base:op_select: Checking all available components");
 131     selectable = check_components(&ompi_op_base_framework.framework_components, op);
 132 
 133     /* Do the selection loop.  The selectable list is in priority
 134        order; lowest priority first. */
 135     for (item = opal_list_remove_first(selectable);
 136          NULL != item;
 137          item = opal_list_remove_first(selectable)) {
 138         avail_op_t *avail = (avail_op_t*) item;
 139 
 140         /* Enable the module */
 141         if (NULL != avail->ao_module->opm_enable) {
 142             ret = avail->ao_module->opm_enable(avail->ao_module, op);
 143             if (OMPI_SUCCESS != ret) {
 144                 /* If the module fails to enable, just release it and move
 145                    on */
 146                 OBJ_RELEASE(avail->ao_module);
 147                 OBJ_RELEASE(avail);
 148                 continue;
 149             }
 150         }
 151 
 152         /* Copy over the non-NULL pointers */
 153         for (i = 0; i < OMPI_OP_BASE_TYPE_MAX; ++i) {
 154             /* 2-buffer variants */
 155             if (NULL != avail->ao_module->opm_fns[i]) {
 156                 OBJ_RELEASE(op->o_func.intrinsic.modules[i]);
 157                 op->o_func.intrinsic.fns[i] = avail->ao_module->opm_fns[i];
 158                 op->o_func.intrinsic.modules[i] = avail->ao_module;
 159                 OBJ_RETAIN(avail->ao_module);
 160             }
 161 
 162             /* 3-buffer variants */
 163             if (NULL != avail->ao_module->opm_3buff_fns[i]) {
 164                 OBJ_RELEASE(op->o_func.intrinsic.modules[i]);
 165                 op->o_3buff_intrinsic.fns[i] =
 166                     avail->ao_module->opm_3buff_fns[i];
 167                 op->o_3buff_intrinsic.modules[i] = avail->ao_module;
 168                 OBJ_RETAIN(avail->ao_module);
 169             }
 170         }
 171 
 172         /* release the original module reference and the list item */
 173         OBJ_RELEASE(avail->ao_module);
 174         OBJ_RELEASE(avail);
 175     }
 176 
 177     /* Done with the list from the check_components() call so release it. */
 178     OBJ_RELEASE(selectable);
 179 
 180     /* Sanity check: for intrinsic MPI_Ops, we should have exactly the
 181        same pointers non-NULL as the corresponding initial table row
 182        in ompi_op_base_functions / ompi_op_base_3buff_functions.  The
 183        values may be different, of course, but the pattern of
 184        NULL/non-NULL should be exactly the same. */
 185     for (i = 0; i < OMPI_OP_BASE_TYPE_MAX; ++i) {
 186         if ((NULL == ompi_op_base_functions[op->o_f_to_c_index][i] &&
 187              NULL != op->o_func.intrinsic.fns[i]) ||
 188             (NULL != ompi_op_base_functions[op->o_f_to_c_index][i] &&
 189              NULL == op->o_func.intrinsic.fns[i])) {
 190             /* Oops -- we found a mismatch.  This shouldn't happen; so
 191                go release everything and return an error (yes, re-use
 192                the "i" index because we're going to return without
 193                completing the outter loop). */
 194             for (i = 0; i < OMPI_OP_BASE_TYPE_MAX; ++i) {
 195                 OBJ_RELEASE(op->o_func.intrinsic.modules[i]);
 196                 op->o_func.intrinsic.modules[i] = NULL;
 197                 op->o_func.intrinsic.fns[i] = NULL;
 198             }
 199             return OMPI_ERR_NOT_FOUND;
 200         }
 201     }
 202 
 203     return OMPI_SUCCESS;
 204 }
 205 
 206 static int avail_op_compare(opal_list_item_t **itema,
 207                             opal_list_item_t **itemb)
 208 {
 209     avail_op_t *availa = (avail_op_t *) itema;
 210     avail_op_t *availb = (avail_op_t *) itemb;
 211 
 212     if (availa->ao_priority > availb->ao_priority) {
 213         return 1;
 214     } else if (availa->ao_priority < availb->ao_priority) {
 215         return -1;
 216     } else {
 217         return 0;
 218     }
 219 }
 220 
 221 /*
 222  * For each module in the list, check and see if it wants to run, and
 223  * do the resulting priority comparison.  Make a list of modules to be
 224  * only those who returned that they want to run, and put them in
 225  * priority order (lowest to highest).
 226  */
 227 static opal_list_t *check_components(opal_list_t *components,
 228                                      ompi_op_t *op)
 229 {
 230     int priority;
 231     mca_base_component_list_item_t *cli;
 232     const mca_base_component_t *component;
 233     ompi_op_base_module_1_0_0_t *module;
 234     opal_list_t *selectable;
 235     avail_op_t *avail;
 236 
 237     /* Make a list of the components that query successfully */
 238     selectable = OBJ_NEW(opal_list_t);
 239 
 240     /* Scan through the list of components.  This nested loop is O(N^2),
 241        but we should never have too many components and/or names, so this
 242        *hopefully* shouldn't matter... */
 243 
 244     OPAL_LIST_FOREACH(cli, components, mca_base_component_list_item_t) {
 245         component = cli->cli_component;
 246 
 247         priority = check_one_component(op, component, &module);
 248         if (priority >= 0) {
 249             /* We have a component that indicated that it wants to run by
 250                giving us a module */
 251             avail = OBJ_NEW(avail_op_t);
 252             avail->ao_priority = priority;
 253             avail->ao_module = module;
 254 
 255             opal_list_append(selectable, (opal_list_item_t*)avail);
 256         }
 257     }
 258 
 259     opal_list_sort(selectable, avail_op_compare);
 260 
 261     /* All done (even if the list is empty; that's ok) */
 262     return selectable;
 263 }
 264 
 265 
 266 /*
 267  * Check a single component
 268  */
 269 static int check_one_component(ompi_op_t *op,
 270                                const mca_base_component_t *component,
 271                                ompi_op_base_module_1_0_0_t **module)
 272 {
 273     int err;
 274     int priority = -1;
 275 
 276     err = query(component, op, &priority, module);
 277 
 278     if (OMPI_SUCCESS == err) {
 279         priority = (priority < 100) ? priority : 100;
 280         opal_output_verbose(10, ompi_op_base_framework.framework_output,
 281                             "op:base:op_select: component available: %s, priority: %d",
 282                             component->mca_component_name, priority);
 283 
 284     } else {
 285         priority = -1;
 286         opal_output_verbose(10, ompi_op_base_framework.framework_output,
 287                             "op:base:op_select: component not available: %s",
 288                             component->mca_component_name);
 289     }
 290 
 291     return priority;
 292 }
 293 
 294 
 295 /**************************************************************************
 296  * Query functions
 297  **************************************************************************/
 298 
 299 /*
 300  * Take any version of a op module, query it, and return the right
 301  * module struct
 302  */
 303 static int query(const mca_base_component_t *component,
 304                  ompi_op_t *op,
 305                  int *priority, ompi_op_base_module_1_0_0_t **module)
 306 {
 307     *module = NULL;
 308     if (1 == component->mca_type_major_version &&
 309         0 == component->mca_type_minor_version &&
 310         0 == component->mca_type_release_version) {
 311         const ompi_op_base_component_1_0_0_t *op100 =
 312             (ompi_op_base_component_1_0_0_t *) component;
 313 
 314         return query_1_0_0(op100, op, priority, module);
 315     }
 316 
 317     /* Unknown op API version -- return error */
 318 
 319     return OMPI_ERROR;
 320 }
 321 
 322 
 323 static int query_1_0_0(const ompi_op_base_component_1_0_0_t *component,
 324                        ompi_op_t *op, int *priority,
 325                        ompi_op_base_module_1_0_0_t **module)
 326 {
 327     ompi_op_base_module_1_0_0_t *ret;
 328 
 329     /* There's currently no need for conversion */
 330 
 331     ret = component->opc_op_query(op, priority);
 332     if (NULL != ret) {
 333         *module = ret;
 334         return OMPI_SUCCESS;
 335     }
 336 
 337     return OMPI_ERROR;
 338 }

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