root/ompi/communicator/comm_init.c

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

DEFINITIONS

This source file includes following definitions.
  1. ompi_comm_init
  2. ompi_comm_allocate
  3. ompi_comm_finalize
  4. ompi_comm_construct
  5. ompi_comm_destruct
  6. OMPI_COMM_SET_INFO_FN

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   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-2017 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) 2006-2017 University of Houston. All rights reserved.
  14  * Copyright (c) 2007-2018 Cisco Systems, Inc.  All rights reserved
  15  * Copyright (c) 2009      Sun Microsystems, Inc. All rights reserved.
  16  * Copyright (c) 2012-2015 Los Alamos National Security, LLC.
  17  *                         All rights reserved.
  18  * Copyright (c) 2011-2013 Inria.  All rights reserved.
  19  * Copyright (c) 2011-2013 Universite Bordeaux 1
  20  *                         All rights reserved.
  21  * Copyright (c) 2015-2017 Research Organization for Information Science
  22  *                         and Technology (RIST). All rights reserved.
  23  * Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
  24  * Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
  25  * $COPYRIGHT$
  26  *
  27  * Additional copyrights may follow
  28  *
  29  * $HEADER$
  30  */
  31 
  32 #include "ompi_config.h"
  33 
  34 #include <stdio.h>
  35 
  36 #include "opal/util/bit_ops.h"
  37 #include "opal/util/info_subscriber.h"
  38 #include "opal/util/string_copy.h"
  39 #include "opal/mca/pmix/pmix.h"
  40 #include "ompi/constants.h"
  41 #include "ompi/mca/pml/pml.h"
  42 #include "ompi/mca/coll/base/base.h"
  43 #include "ompi/mca/topo/base/base.h"
  44 #include "ompi/runtime/params.h"
  45 #include "ompi/communicator/communicator.h"
  46 #include "ompi/attribute/attribute.h"
  47 #include "ompi/dpm/dpm.h"
  48 #include "ompi/memchecker.h"
  49 
  50 /*
  51 ** Table for Fortran <-> C communicator handle conversion
  52 ** Also used by P2P code to lookup communicator based
  53 ** on cid.
  54 **
  55 */
  56 opal_pointer_array_t ompi_mpi_communicators = {{0}};
  57 opal_pointer_array_t ompi_comm_f_to_c_table = {{0}};
  58 
  59 ompi_predefined_communicator_t  ompi_mpi_comm_world = {{{{0}}}};
  60 ompi_predefined_communicator_t  ompi_mpi_comm_self = {{{{0}}}};
  61 ompi_predefined_communicator_t  ompi_mpi_comm_null = {{{{0}}}};
  62 ompi_communicator_t  *ompi_mpi_comm_parent = NULL;
  63 
  64 ompi_predefined_communicator_t *ompi_mpi_comm_world_addr =
  65     &ompi_mpi_comm_world;
  66 ompi_predefined_communicator_t *ompi_mpi_comm_self_addr =
  67     &ompi_mpi_comm_self;
  68 ompi_predefined_communicator_t *ompi_mpi_comm_null_addr =
  69     &ompi_mpi_comm_null;
  70 
  71 static void ompi_comm_construct(ompi_communicator_t* comm);
  72 static void ompi_comm_destruct(ompi_communicator_t* comm);
  73 
  74 OBJ_CLASS_INSTANCE(ompi_communicator_t, opal_infosubscriber_t,
  75                    ompi_comm_construct,
  76                    ompi_comm_destruct);
  77 
  78 /* This is the counter for the number of communicators, which contain
  79    process with more than one jobid. This counter is a usefull
  80    shortcut for finalize and abort. */
  81 int ompi_comm_num_dyncomm=0;
  82 
  83 /*
  84  * Initialize comm world/self/null/parent.
  85  */
  86 int ompi_comm_init(void)
  87 {
  88     ompi_group_t *group;
  89     size_t size;
  90 
  91     /* Setup communicator array */
  92     OBJ_CONSTRUCT(&ompi_mpi_communicators, opal_pointer_array_t);
  93     if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_communicators, 16,
  94                                                 OMPI_FORTRAN_HANDLE_MAX, 64) ) {
  95         return OMPI_ERROR;
  96     }
  97 
  98     /* Setup f to c table (we can no longer use the cid as the fortran handle) */
  99     OBJ_CONSTRUCT(&ompi_comm_f_to_c_table, opal_pointer_array_t);
 100     if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_comm_f_to_c_table, 8,
 101                                                 OMPI_FORTRAN_HANDLE_MAX, 32) ) {
 102         return OMPI_ERROR;
 103     }
 104 
 105     /* Setup MPI_COMM_WORLD */
 106     OBJ_CONSTRUCT(&ompi_mpi_comm_world, ompi_communicator_t);
 107     assert(ompi_mpi_comm_world.comm.c_f_to_c_index == 0);
 108     group = OBJ_NEW(ompi_group_t);
 109 
 110     size = ompi_process_info.num_procs;
 111     group->grp_proc_pointers = (ompi_proc_t **) calloc (size, sizeof (ompi_proc_t *));
 112     group->grp_proc_count = size;
 113 
 114     for (size_t i = 0 ; i < size ; ++i) {
 115         opal_process_name_t name = {.vpid = i, .jobid = OMPI_PROC_MY_NAME->jobid};
 116         /* look for existing ompi_proc_t that matches this name */
 117         group->grp_proc_pointers[i] = (ompi_proc_t *) ompi_proc_lookup (name);
 118         if (NULL == group->grp_proc_pointers[i]) {
 119             /* set sentinel value */
 120             group->grp_proc_pointers[i] = (ompi_proc_t *) ompi_proc_name_to_sentinel (name);
 121         } else {
 122             OBJ_RETAIN (group->grp_proc_pointers[i]);
 123         }
 124     }
 125 
 126     OMPI_GROUP_SET_INTRINSIC (group);
 127     OMPI_GROUP_SET_DENSE (group);
 128     ompi_set_group_rank(group, ompi_proc_local());
 129 
 130     ompi_mpi_comm_world.comm.c_contextid    = 0;
 131     ompi_mpi_comm_world.comm.c_id_start_index = 4;
 132     ompi_mpi_comm_world.comm.c_id_available = 4;
 133     ompi_mpi_comm_world.comm.c_my_rank      = group->grp_my_rank;
 134     ompi_mpi_comm_world.comm.c_local_group  = group;
 135     ompi_mpi_comm_world.comm.c_remote_group = group;
 136     OBJ_RETAIN(ompi_mpi_comm_world.comm.c_remote_group);
 137     ompi_mpi_comm_world.comm.c_cube_dim     = opal_cube_dim((int)size);
 138     ompi_mpi_comm_world.comm.error_handler  = &ompi_mpi_errors_are_fatal.eh;
 139     OBJ_RETAIN( &ompi_mpi_errors_are_fatal.eh );
 140     OMPI_COMM_SET_PML_ADDED(&ompi_mpi_comm_world.comm);
 141     opal_pointer_array_set_item (&ompi_mpi_communicators, 0, &ompi_mpi_comm_world);
 142 
 143     opal_string_copy(ompi_mpi_comm_world.comm.c_name, "MPI_COMM_WORLD",
 144                      sizeof(ompi_mpi_comm_world.comm.c_name));
 145     ompi_mpi_comm_world.comm.c_flags |= OMPI_COMM_NAMEISSET;
 146     ompi_mpi_comm_world.comm.c_flags |= OMPI_COMM_INTRINSIC;
 147 
 148     /* We have to create a hash (although it is legal to leave this
 149        filed NULL -- the attribute accessor functions will intepret
 150        this as "there are no attributes cached on this object")
 151        because MPI_COMM_WORLD has some predefined attributes. */
 152     ompi_attr_hash_init(&ompi_mpi_comm_world.comm.c_keyhash);
 153 
 154     /* Check for the binding policy used. We are only interested in
 155        whether mapby-node has been set right now (could be extended later)
 156        and only on MPI_COMM_WORLD, since for all other sub-communicators
 157        it is virtually impossible to identify their layout across nodes
 158        in the most generic sense. This is used by OMPIO for deciding which
 159        ranks to use for aggregators
 160     */
 161     opal_process_name_t wildcard = {OMPI_PROC_MY_NAME->jobid, OPAL_VPID_WILDCARD};
 162     char *str=NULL;
 163     int rc;
 164 
 165     OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_MAPBY, &wildcard, &str, OPAL_STRING);
 166     if ( 0 == rc && NULL != str) {
 167         if ( strstr ( str, "BYNODE") ) {
 168             OMPI_COMM_SET_MAPBY_NODE(&ompi_mpi_comm_world.comm);
 169         }
 170         if (NULL != str) {
 171             free(str);
 172         }
 173     }
 174     /* Setup MPI_COMM_SELF */
 175     OBJ_CONSTRUCT(&ompi_mpi_comm_self, ompi_communicator_t);
 176     assert(ompi_mpi_comm_self.comm.c_f_to_c_index == 1);
 177     group = OBJ_NEW(ompi_group_t);
 178     group->grp_proc_pointers = ompi_proc_self(&size);
 179     group->grp_my_rank       = 0;
 180     group->grp_proc_count    = (int)size;
 181     OMPI_GROUP_SET_INTRINSIC (group);
 182     OMPI_GROUP_SET_DENSE (group);
 183 
 184     ompi_mpi_comm_self.comm.c_contextid    = 1;
 185     ompi_mpi_comm_self.comm.c_id_start_index = 20;
 186     ompi_mpi_comm_self.comm.c_id_available = 20;
 187     ompi_mpi_comm_self.comm.c_my_rank      = group->grp_my_rank;
 188     ompi_mpi_comm_self.comm.c_local_group  = group;
 189     ompi_mpi_comm_self.comm.c_remote_group = group;
 190     OBJ_RETAIN(ompi_mpi_comm_self.comm.c_remote_group);
 191     ompi_mpi_comm_self.comm.error_handler  = &ompi_mpi_errors_are_fatal.eh;
 192     OBJ_RETAIN( &ompi_mpi_errors_are_fatal.eh );
 193     OMPI_COMM_SET_PML_ADDED(&ompi_mpi_comm_self.comm);
 194     opal_pointer_array_set_item (&ompi_mpi_communicators, 1, &ompi_mpi_comm_self);
 195 
 196     opal_string_copy(ompi_mpi_comm_self.comm.c_name, "MPI_COMM_SELF",
 197                      sizeof(ompi_mpi_comm_self.comm.c_name));
 198     ompi_mpi_comm_self.comm.c_flags |= OMPI_COMM_NAMEISSET;
 199     ompi_mpi_comm_self.comm.c_flags |= OMPI_COMM_INTRINSIC;
 200 
 201     /* We can set MPI_COMM_SELF's keyhash to NULL because it has no
 202        predefined attributes.  If a user defines an attribute on
 203        MPI_COMM_SELF, the keyhash will automatically be created. */
 204     ompi_mpi_comm_self.comm.c_keyhash = NULL;
 205 
 206     /* Setup MPI_COMM_NULL */
 207     OBJ_CONSTRUCT(&ompi_mpi_comm_null, ompi_communicator_t);
 208     assert(ompi_mpi_comm_null.comm.c_f_to_c_index == 2);
 209     ompi_mpi_comm_null.comm.c_local_group  = &ompi_mpi_group_null.group;
 210     ompi_mpi_comm_null.comm.c_remote_group = &ompi_mpi_group_null.group;
 211     OBJ_RETAIN(&ompi_mpi_group_null.group);
 212     OBJ_RETAIN(&ompi_mpi_group_null.group);
 213 
 214     ompi_mpi_comm_null.comm.c_contextid    = 2;
 215     ompi_mpi_comm_null.comm.c_my_rank      = MPI_PROC_NULL;
 216 
 217     ompi_mpi_comm_null.comm.error_handler  = &ompi_mpi_errors_are_fatal.eh;
 218     OBJ_RETAIN( &ompi_mpi_errors_are_fatal.eh );
 219     opal_pointer_array_set_item (&ompi_mpi_communicators, 2, &ompi_mpi_comm_null);
 220 
 221     opal_string_copy(ompi_mpi_comm_null.comm.c_name, "MPI_COMM_NULL",
 222                      sizeof(ompi_mpi_comm_null.comm.c_name));
 223     ompi_mpi_comm_null.comm.c_flags |= OMPI_COMM_NAMEISSET;
 224     ompi_mpi_comm_null.comm.c_flags |= OMPI_COMM_INTRINSIC;
 225 
 226     /* Initialize the parent communicator to MPI_COMM_NULL */
 227     ompi_mpi_comm_parent = &ompi_mpi_comm_null.comm;
 228     OBJ_RETAIN(&ompi_mpi_comm_null);
 229     OBJ_RETAIN(&ompi_mpi_group_null.group);
 230     OBJ_RETAIN(&ompi_mpi_errors_are_fatal.eh);
 231 
 232     /* initialize communicator requests (for ompi_comm_idup) */
 233     ompi_comm_request_init ();
 234 
 235     return OMPI_SUCCESS;
 236 }
 237 
 238 
 239 ompi_communicator_t *ompi_comm_allocate ( int local_size, int remote_size )
 240 {
 241     ompi_communicator_t *new_comm;
 242 
 243     /* create new communicator element */
 244     new_comm = OBJ_NEW(ompi_communicator_t);
 245     new_comm->super.s_info = NULL;
 246     new_comm->c_local_group = ompi_group_allocate ( local_size );
 247     if ( 0 < remote_size ) {
 248         new_comm->c_remote_group = ompi_group_allocate (remote_size);
 249         new_comm->c_flags |= OMPI_COMM_INTER;
 250     } else {
 251         /*
 252          * simplifies some operations (e.g. p2p), if
 253          * we can always use the remote group
 254          */
 255         new_comm->c_remote_group = new_comm->c_local_group;
 256         OBJ_RETAIN(new_comm->c_remote_group);
 257     }
 258 
 259     /* fill in the inscribing hyper-cube dimensions */
 260     new_comm->c_cube_dim = opal_cube_dim(local_size);
 261 
 262     return new_comm;
 263 }
 264 
 265 int ompi_comm_finalize(void)
 266 {
 267     int max, i;
 268     ompi_communicator_t *comm;
 269 
 270     /* Shut down MPI_COMM_SELF */
 271     OBJ_DESTRUCT( &ompi_mpi_comm_self );
 272 
 273     /* disconnect all dynamic communicators */
 274     ompi_dpm_dyn_finalize();
 275 
 276     /* Free the attributes on comm world. This is not done in the
 277      * destructor as we delete attributes in ompi_comm_free (which
 278      * is not called for comm world) */
 279     if (NULL != ompi_mpi_comm_world.comm.c_keyhash) {
 280         /* Ignore errors when deleting attributes on comm_world */
 281         (void) ompi_attr_delete_all(COMM_ATTR, &ompi_mpi_comm_world.comm, ompi_mpi_comm_world.comm.c_keyhash);
 282         OBJ_RELEASE(ompi_mpi_comm_world.comm.c_keyhash);
 283     }
 284 
 285     /* Shut down MPI_COMM_WORLD */
 286     OBJ_DESTRUCT( &ompi_mpi_comm_world );
 287 
 288     /* Shut down the parent communicator, if it exists */
 289     if( ompi_mpi_comm_parent != &ompi_mpi_comm_null.comm ) {
 290         /* Note that we pass ompi_mpi_comm_parent here
 291            (vs. &ompi_mpi_comm_parent) because it is of type
 292            (ompi_communicator_t*), *NOT* (ompi_communicator_t).  This
 293            is because a parent communicator is created dynamically
 294            during init, and we just set this pointer to it.  Hence, we
 295            just pass in the pointer here. */
 296         OBJ_DESTRUCT (ompi_mpi_comm_parent);
 297 
 298         /* Please note, that the we did increase the reference count
 299            for ompi_mpi_comm_null, ompi_mpi_group_null, and
 300            ompi_mpi_errors_are_fatal in ompi_comm_init because of
 301            ompi_mpi_comm_parent.  In case a
 302            parent communicator is really created, the ref. counters
 303            for these objects are decreased again by one. However, in a
 304            static scenario, we should ideally decrease the ref. counter
 305            for these objects by one here. The problem just is, that
 306            if the app had a parent_comm, and this has been freed/disconnected,
 307            ompi_comm_parent points again to ompi_comm_null, the reference count
 308            for these objects has not been increased again.
 309            So the point is, if ompi_mpi_comm_parent == &ompi_mpi_comm_null
 310            we do not know whether we have to decrease the ref count for
 311            those three objects or not. Since this is a constant, non-increasing
 312            amount of memory, we stick with the current solution for now,
 313            namely don't do anything.
 314         */
 315     }
 316 
 317     /* Shut down MPI_COMM_NULL */
 318     OBJ_DESTRUCT( &ompi_mpi_comm_null );
 319 
 320     /* Check whether we have some communicators left */
 321     max = opal_pointer_array_get_size(&ompi_mpi_communicators);
 322     for ( i=3; i<max; i++ ) {
 323         comm = (ompi_communicator_t *)opal_pointer_array_get_item(&ompi_mpi_communicators, i);
 324         if ( NULL != comm ) {
 325             /* Communicator has not been freed before finalize */
 326             OBJ_RELEASE(comm);
 327             comm=(ompi_communicator_t *)opal_pointer_array_get_item(&ompi_mpi_communicators, i);
 328             if ( NULL != comm ) {
 329                 /* Still here ? */
 330                 if ( !OMPI_COMM_IS_EXTRA_RETAIN(comm)) {
 331 
 332                     /* For communicator that have been marked as "extra retain", we do not further
 333                      * enforce to decrease the reference counter once more. These "extra retain"
 334                      * communicators created e.g. by the hierarch or inter module did increase
 335                      * the reference count by one more than other communicators, on order to
 336                      * allow for deallocation with the parent communicator. Note, that
 337                      * this only occurs if the cid of the local_comm is lower than of its
 338                      * parent communicator. Read the comment in comm_activate for
 339                      * a full explanation.
 340                      */
 341                     if ( ompi_debug_show_handle_leaks && !(OMPI_COMM_IS_FREED(comm)) ){
 342                         opal_output(0,"WARNING: MPI_Comm still allocated in MPI_Finalize\n");
 343                         ompi_comm_dump ( comm);
 344                         OBJ_RELEASE(comm);
 345                     }
 346                 }
 347             }
 348         }
 349     }
 350 
 351     OBJ_DESTRUCT (&ompi_mpi_communicators);
 352     OBJ_DESTRUCT (&ompi_comm_f_to_c_table);
 353 
 354     /* finalize communicator requests */
 355     ompi_comm_request_fini ();
 356 
 357     return OMPI_SUCCESS;
 358 }
 359 
 360 /********************************************************************************/
 361 /********************************************************************************/
 362 /********************************************************************************/
 363 /* static functions */
 364 
 365 static void ompi_comm_construct(ompi_communicator_t* comm)
 366 {
 367     comm->c_f_to_c_index = opal_pointer_array_add(&ompi_comm_f_to_c_table, comm);
 368     comm->c_name[0]      = '\0';
 369     comm->c_contextid    = MPI_UNDEFINED;
 370     comm->c_id_available = MPI_UNDEFINED;
 371     comm->c_id_start_index = MPI_UNDEFINED;
 372     comm->c_flags        = 0;
 373     comm->c_my_rank      = 0;
 374     comm->c_cube_dim     = 0;
 375     comm->c_local_group  = NULL;
 376     comm->c_remote_group = NULL;
 377     comm->error_handler  = NULL;
 378     comm->c_pml_comm     = NULL;
 379     comm->c_topo         = NULL;
 380     comm->c_coll         = NULL;
 381 
 382     /* A keyhash will be created if/when an attribute is cached on
 383        this communicator */
 384     comm->c_keyhash      = NULL;
 385 
 386     comm->errhandler_type  = OMPI_ERRHANDLER_TYPE_COMM;
 387 #ifdef OMPI_WANT_PERUSE
 388     comm->c_peruse_handles = NULL;
 389 #endif
 390     OBJ_CONSTRUCT(&comm->c_lock, opal_mutex_t);
 391 }
 392 
 393 static void ompi_comm_destruct(ompi_communicator_t* comm)
 394 {
 395     /* Note that the attributes were already released on this
 396        communicator in ompi_comm_free() (i.e., from MPI_COMM_FREE /
 397        MPI_COMM_DISCONNECT).  See the lengthy comment in
 398        communicator/comm.c in ompi_comm_free() for the reasons why. */
 399 
 400     /* Release the collective module */
 401 
 402     if ( NULL != comm->c_coll ) {
 403         mca_coll_base_comm_unselect(comm);
 404     }
 405 
 406     /* Tell the PML that this communicator is done.
 407        MCA_PML_CALL(add_comm()) was called explicitly in
 408        ompi_comm_init() when setting up COMM_WORLD and COMM_SELF; it's
 409        called in ompi_comm_set() for all others.  This means that all
 410        communicators must be destroyed before the PML shuts down.
 411 
 412        Also -- do not invoke the pml_del_comm if the corresponding
 413        pml_add_comm was never invoked.  This can happen in an error
 414        situation where, for example, attributes do not copy properly
 415        from one communicator to another and we end up destroying the
 416        new communication while propagating the error up the stack.  We
 417        want to make it all the way up the stack to invoke the MPI
 418        exception, not cause a seg fault in pml_del_comm because it was
 419        never pml_add_com'ed. */
 420 
 421     if ( MPI_COMM_NULL != comm && OMPI_COMM_IS_PML_ADDED(comm) ) {
 422         MCA_PML_CALL(del_comm (comm));
 423     }
 424 
 425     /* Release topology module */
 426     if (NULL != comm->c_topo) {
 427         OBJ_RELEASE(comm->c_topo);
 428         comm->c_topo = NULL;
 429     }
 430 
 431     if (NULL != comm->c_local_group) {
 432         OBJ_RELEASE ( comm->c_local_group );
 433         comm->c_local_group = NULL;
 434         if ( OMPI_COMM_IS_INTRA(comm) ) {
 435             /* We have to decrement the ref count on the remote group
 436                even if it is identical to the local one in case of
 437                intra-comm */
 438             OBJ_RELEASE ( comm->c_remote_group );
 439             comm->c_remote_group = NULL;
 440         }
 441     }
 442 
 443     if (NULL != comm->c_remote_group) {
 444         OBJ_RELEASE ( comm->c_remote_group );
 445         comm->c_remote_group = NULL;
 446     }
 447 
 448     if (NULL != comm->error_handler) {
 449         OBJ_RELEASE ( comm->error_handler );
 450         comm->error_handler = NULL;
 451     }
 452 
 453     /* mark this cid as available */
 454     if ( MPI_UNDEFINED != (int)comm->c_contextid &&
 455          NULL != opal_pointer_array_get_item(&ompi_mpi_communicators,
 456                                              comm->c_contextid)) {
 457         opal_pointer_array_set_item ( &ompi_mpi_communicators,
 458                                       comm->c_contextid, NULL);
 459     }
 460 
 461     /* reset the ompi_comm_f_to_c_table entry */
 462     if ( MPI_UNDEFINED != comm->c_f_to_c_index &&
 463          NULL != opal_pointer_array_get_item(&ompi_comm_f_to_c_table,
 464                                              comm->c_f_to_c_index)) {
 465         opal_pointer_array_set_item ( &ompi_comm_f_to_c_table,
 466                                       comm->c_f_to_c_index, NULL);
 467     }
 468 
 469     OBJ_DESTRUCT(&comm->c_lock);
 470 }
 471 
 472 #define OMPI_COMM_SET_INFO_FN(name, flag)       \
 473     static char *ompi_comm_set_ ## name (opal_infosubscriber_t *obj, char *key, char *value) \
 474     {                                                                   \
 475         ompi_communicator_t *comm = (ompi_communicator_t *) obj;        \
 476                                                                         \
 477         if (opal_str_to_bool(value)) {                                  \
 478             comm->c_assertions |= flag;                                 \
 479         } else {                                                        \
 480             comm->c_assertions &= ~flag;                                \
 481         }                                                               \
 482                                                                         \
 483         return OMPI_COMM_CHECK_ASSERT(comm, flag) ? "true" : "false";   \
 484     }
 485 
 486 OMPI_COMM_SET_INFO_FN(no_any_source, OMPI_COMM_ASSERT_NO_ANY_SOURCE)
 487 OMPI_COMM_SET_INFO_FN(no_any_tag, OMPI_COMM_ASSERT_NO_ANY_TAG)
 488 OMPI_COMM_SET_INFO_FN(allow_overtake, OMPI_COMM_ASSERT_ALLOW_OVERTAKE)
 489 OMPI_COMM_SET_INFO_FN(exact_length, OMPI_COMM_ASSERT_EXACT_LENGTH)
 490 
 491 void ompi_comm_assert_subscribe (ompi_communicator_t *comm, int32_t assert_flag)
 492 {
 493     switch (assert_flag) {
 494     case OMPI_COMM_ASSERT_NO_ANY_SOURCE:
 495         opal_infosubscribe_subscribe (&comm->super, "mpi_assert_no_any_source", "false", ompi_comm_set_no_any_source);
 496         break;
 497     case OMPI_COMM_ASSERT_NO_ANY_TAG:
 498         opal_infosubscribe_subscribe (&comm->super, "mpi_assert_no_any_tag", "false", ompi_comm_set_no_any_tag);
 499         break;
 500     case OMPI_COMM_ASSERT_ALLOW_OVERTAKE:
 501         opal_infosubscribe_subscribe (&comm->super, "mpi_assert_allow_overtaking", "false", ompi_comm_set_allow_overtake);
 502         break;
 503     case OMPI_COMM_ASSERT_EXACT_LENGTH:
 504         opal_infosubscribe_subscribe (&comm->super, "mpi_assert_exact_length", "false", ompi_comm_set_exact_length);
 505         break;
 506     }
 507 }

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