-: 0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/comm/commutil.c
-: 0:Graph:commutil.gcno
-: 0:Data:commutil.gcda
-: 0:Runs:4383
-: 0:Programs:1376
-: 1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
-: 2:/*
-: 3: * (C) 2001 by Argonne National Laboratory.
-: 4: * See COPYRIGHT in top-level directory.
-: 5: */
-: 6:
-: 7:#include "mpiimpl.h"
-: 8:#include "mpicomm.h"
-: 9:
-: 10:/* This is the utility file for comm that contains the basic comm items
-: 11: and storage management */
-: 12:#ifndef MPID_COMM_PREALLOC
-: 13:#define MPID_COMM_PREALLOC 8
-: 14:#endif
-: 15:
-: 16:/* Preallocated comm objects */
-: 17:MPID_Comm MPID_Comm_builtin[MPID_COMM_N_BUILTIN] = { { MPIU_OBJECT_HEADER_INITIALIZER(0,0) } };
-: 18:MPID_Comm MPID_Comm_direct[MPID_COMM_PREALLOC] = { { MPIU_OBJECT_HEADER_INITIALIZER(0,0) } };
-: 19:MPIU_Object_alloc_t MPID_Comm_mem = { 0, 0, 0, 0, MPID_COMM,
-: 20: sizeof(MPID_Comm), MPID_Comm_direct,
-: 21: MPID_COMM_PREALLOC};
-: 22:
-: 23:/* utility function to pretty print a context ID for debugging purposes, see
-: 24: * mpiimpl.h for more info on the various fields */
-: 25:static void MPIR_Comm_dump_context_id(MPIR_Context_id_t context_id, char *out_str, int len)
-: 26:{
-: 27: int subcomm_type = MPID_CONTEXT_READ_FIELD(SUBCOMM,context_id);
-: 28: const char *subcomm_type_name = NULL;
-: 29:
-: 30: switch (subcomm_type) {
-: 31: case 0: subcomm_type_name = "parent"; break;
-: 32: case 1: subcomm_type_name = "intranode"; break;
-: 33: case 2: subcomm_type_name = "internode"; break;
-: 34: default: MPIU_Assert(FALSE); break;
-: 35: }
-: 36: MPIU_Snprintf(out_str, len,
-: 37: "context_id=%d (%#x): DYNAMIC_PROC=%d PREFIX=%#x IS_LOCALCOMM=%d SUBCOMM=%s SUFFIX=%s",
-: 38: context_id,
-: 39: context_id,
-: 40: MPID_CONTEXT_READ_FIELD(DYNAMIC_PROC,context_id),
-: 41: MPID_CONTEXT_READ_FIELD(PREFIX,context_id),
-: 42: MPID_CONTEXT_READ_FIELD(IS_LOCALCOMM,context_id),
-: 43: subcomm_type_name,
-: 44: (MPID_CONTEXT_READ_FIELD(SUFFIX,context_id) ? "coll" : "pt2pt"));
-: 45:}
-: 46:
-: 47:/* FIXME :
-: 48: Reusing context ids can lead to a race condition if (as is desirable)
-: 49: MPI_Comm_free does not include a barrier. Consider the following:
-: 50: Process A frees the communicator.
-: 51: Process A creates a new communicator, reusing the just released id
-: 52: Process B sends a message to A on the old communicator.
-: 53: Process A receives the message, and believes that it belongs to the
-: 54: new communicator.
-: 55: Process B then cancels the message, and frees the communicator.
-: 56:
-: 57: The likelyhood of this happening can be reduced by introducing a gap
-: 58: between when a context id is released and when it is reused. An alternative
-: 59: is to use an explicit message (in the implementation of MPI_Comm_free)
-: 60: to indicate that a communicator is being freed; this will often require
-: 61: less communication than a barrier in MPI_Comm_free, and will ensure that
-: 62: no messages are later sent to the same communicator (we may also want to
-: 63: have a similar check when building fault-tolerant versions of MPI).
-: 64: */
-: 65:
-: 66:/* Create a new communicator with a context.
-: 67: Do *not* initialize the other fields except for the reference count.
-: 68: See MPIR_Comm_copy for a function to produce a copy of part of a
-: 69: communicator
-: 70:*/
-: 71:
-: 72:
-: 73:/*
-: 74: Create a communicator structure and perform basic initialization
-: 75: (mostly clearing fields and updating the reference count).
-: 76: */
-: 77:#undef FUNCNAME
-: 78:#define FUNCNAME MPIR_Comm_create
-: 79:#undef FCNAME
-: 80:#define FCNAME "MPIR_Comm_create"
-: 81:int MPIR_Comm_create( MPID_Comm **newcomm_ptr )
1652591: 82:{
1652591: 83: int mpi_errno = MPI_SUCCESS;
-: 84: MPID_Comm *newptr;
-: 85: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE);
-: 86:
-: 87: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_CREATE);
-: 88:
1652591: 89: newptr = (MPID_Comm *)MPIU_Handle_obj_alloc( &MPID_Comm_mem );
|
-: 90: /* --BEGIN ERROR HANDLING-- */
1652591: 91: if (!newptr) {
#####: 92: mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
-: 93: FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0 );
#####: 94: goto fn_fail;
-: 95: }
-: 96: /* --END ERROR HANDLING-- */
|
1652591: 97: *newcomm_ptr = newptr;
1652591: 98: MPIU_Object_set_ref( newptr, 1 );
-: 99:
-: 100: /* Clear many items (empty means to use the default; some of these
-: 101: may be overridden within the communicator initialization) */
1652591: 102: newptr->errhandler = 0;
1652591: 103: newptr->attributes = 0;
1652591: 104: newptr->remote_group = 0;
1652591: 105: newptr->local_group = 0;
1652591: 106: newptr->coll_fns = 0;
1652591: 107: newptr->topo_fns = 0;
1652591: 108: newptr->name[0] = 0;
-: 109:
1652591: 110: newptr->is_node_aware = 0;
1652591: 111: newptr->node_comm = NULL;
1652591: 112: newptr->node_roots_comm = NULL;
1652591: 113: newptr->intranode_table = NULL;
1652591: 114: newptr->internode_table = NULL;
-: 115:
-: 116: /* Fields not set include context_id, remote and local size, and
-: 117: kind, since different communicator construction routines need
-: 118: different values */
-: 119:
-: 120: /* Insert this new communicator into the list of known communicators.
-: 121: Make this conditional on debugger support to match the test in
-: 122: MPIR_Comm_release . */
-: 123: MPIR_COMML_REMEMBER( newptr );
-: 124:
|
1652591: 125: fn_fail:
-: 126: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_CREATE);
-: 127:
|
1652591: 128: return mpi_errno;
-: 129:}
-: 130:
-: 131:/* Create a local intra communicator from the local group of the
-: 132: specified intercomm. */
-: 133:/* FIXME this is an alternative constructor that doesn't use MPIR_Comm_create! */
-: 134:#undef FUNCNAME
-: 135:#define FUNCNAME MPIR_Setup_intercomm_localcomm
-: 136:#undef FCNAME
-: 137:#define FCNAME "MPIR_Setup_intercomm_localcomm"
-: 138:int MPIR_Setup_intercomm_localcomm( MPID_Comm *intercomm_ptr )
2335: 139:{
-: 140: MPID_Comm *localcomm_ptr;
2335: 141: int mpi_errno = MPI_SUCCESS;
-: 142: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
-: 143:
-: 144: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
-: 145:
2335: 146: localcomm_ptr = (MPID_Comm *)MPIU_Handle_obj_alloc( &MPID_Comm_mem );
2335: 147: MPIU_ERR_CHKANDJUMP(!localcomm_ptr,mpi_errno,MPI_ERR_OTHER,"**nomem");
-: 148:
2335: 149: MPIU_Object_set_ref( localcomm_ptr, 1 );
-: 150: /* use the parent intercomm's recv ctx as the basis for our ctx */
2335: 151: localcomm_ptr->recvcontext_id = MPID_CONTEXT_SET_FIELD(IS_LOCALCOMM, intercomm_ptr->recvcontext_id, 1);
2335: 152: localcomm_ptr->context_id = localcomm_ptr->recvcontext_id;
-: 153:
-: 154: /* Duplicate the VCRT references */
2335: 155: MPID_VCRT_Add_ref( intercomm_ptr->local_vcrt );
2335: 156: localcomm_ptr->vcrt = intercomm_ptr->local_vcrt;
2335: 157: localcomm_ptr->vcr = intercomm_ptr->local_vcr;
-: 158:
-: 159: /* Save the kind of the communicator */
2335: 160: localcomm_ptr->comm_kind = MPID_INTRACOMM;
-: 161:
-: 162: /* Set the sizes and ranks */
2335: 163: localcomm_ptr->remote_size = intercomm_ptr->local_size;
2335: 164: localcomm_ptr->local_size = intercomm_ptr->local_size;
2335: 165: localcomm_ptr->rank = intercomm_ptr->rank;
-: 166:
-: 167: /* More advanced version: if the group is available, dup it by
-: 168: increasing the reference count */
2335: 169: localcomm_ptr->local_group = 0;
2335: 170: localcomm_ptr->remote_group = 0;
-: 171:
-: 172: /* This is an internal communicator, so ignore */
2335: 173: localcomm_ptr->errhandler = 0;
-: 174:
-: 175: /* FIXME : No local functions for the collectives */
2335: 176: localcomm_ptr->coll_fns = 0;
-: 177:
-: 178: /* FIXME : No local functions for the topology routines */
2335: 179: localcomm_ptr->topo_fns = 0;
-: 180:
-: 181: /* We do *not* inherit any name */
2335: 182: localcomm_ptr->name[0] = 0;
-: 183:
2335: 184: localcomm_ptr->attributes = 0;
-: 185:
2335: 186: intercomm_ptr->local_comm = localcomm_ptr;
-: 187:
2335: 188: localcomm_ptr->is_node_aware = 0;
2335: 189: localcomm_ptr->node_comm = NULL;
2335: 190: localcomm_ptr->node_roots_comm = NULL;
2335: 191: localcomm_ptr->intranode_table = NULL;
2335: 192: localcomm_ptr->internode_table = NULL;
-: 193:
-: 194: /* sets up the SMP-aware sub-communicators and tables */
2335: 195: mpi_errno = MPIR_Comm_commit(localcomm_ptr);
|
2335: 196: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 197:
2335: 198: fn_fail:
-: 199: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
-: 200:
|
2335: 201: return mpi_errno;
-: 202:}
-: 203:
-: 204:/* Provides a hook for the top level functions to perform some manipulation on a
-: 205: communicator just before it is given to the application level.
-: 206:
-: 207: For example, we create sub-communicators for SMP-aware collectives at this
-: 208: step. */
-: 209:int MPIR_Comm_commit(MPID_Comm *comm)
695941: 210:{
695941: 211: int mpi_errno = MPI_SUCCESS;
-: 212: int i;
695941: 213: int num_local = -1, num_external = -1;
695941: 214: int local_rank = -1, external_rank = -1;
695941: 215: int *local_procs = NULL, *external_procs = NULL;
-: 216: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_COMMIT);
-: 217:
-: 218: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_COMMIT);
-: 219:
-: 220: /* It's OK to relax these assertions, but we should do so very
-: 221: intentionally. For now this function is the only place that we create
-: 222: our hierarchy of communicators */
695941: 223: MPIU_Assert(comm->node_comm == NULL);
695941: 224: MPIU_Assert(comm->node_roots_comm == NULL);
-: 225:
695941: 226: if (comm->comm_kind == MPID_INTRACOMM) {
-: 227:
692280: 228: mpi_errno = MPIU_Find_local_and_external(comm,
-: 229: &num_local, &local_rank, &local_procs,
-: 230: &num_external, &external_rank, &external_procs,
-: 231: &comm->intranode_table, &comm->internode_table);
692280: 232: if (mpi_errno) {
|
63: 233: if (MPIR_Err_is_fatal(mpi_errno)) MPIU_ERR_POP(mpi_errno);
-: 234:
-: 235: /* Non-fatal errors simply mean that this communicator will not have
-: 236: any node awareness. Node-aware collectives are an optimization. */
-: 237: MPIU_DBG_MSG_P(COMM,VERBOSE,"MPIU_Find_local_and_external failed for comm_ptr=%p", comm);
|
63: 238: if (comm->intranode_table)
|
#####: 239: MPIU_Free(comm->intranode_table);
|
63: 240: if (comm->internode_table)
|
#####: 241: MPIU_Free(comm->internode_table);
-: 242:
|
63: 243: mpi_errno = MPI_SUCCESS;
63: 244: goto fn_exit;
-: 245: }
-: 246:
-: 247: /* defensive checks */
692217: 248: MPIU_Assert(num_local > 0);
692217: 249: MPIU_Assert(num_local > 1 || external_rank >= 0);
692217: 250: MPIU_Assert(external_rank < 0 || external_procs != NULL);
-: 251:
-: 252: /* if the node_roots_comm and comm would be the same size, then creating
-: 253: the second communicator is useless and wasteful. */
692217: 254: if (num_external == comm->remote_size) {
37535: 255: MPIU_Assert(num_local == 1);
-: 256: goto fn_exit;
-: 257: }
-: 258:
-: 259: /* we don't need a local comm if this process is the only one on this node */
654682: 260: if (num_local > 1) {
654682: 261: mpi_errno = MPIR_Comm_create(&comm->node_comm);
|
654682: 262: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 263:
|
654682: 264: comm->node_comm->context_id = comm->context_id + MPID_CONTEXT_INTRANODE_OFFSET;
654682: 265: comm->node_comm->recvcontext_id = comm->node_comm->context_id;
654682: 266: comm->node_comm->rank = local_rank;
654682: 267: comm->node_comm->comm_kind = MPID_INTRACOMM;
654682: 268: comm->node_comm->local_comm = NULL;
-: 269:
654682: 270: comm->node_comm->local_size = num_local;
654682: 271: comm->node_comm->remote_size = num_local;
-: 272:
654682: 273: MPID_VCRT_Create( num_local, &comm->node_comm->vcrt );
654682: 274: MPID_VCRT_Get_ptr( comm->node_comm->vcrt, &comm->node_comm->vcr );
2209306: 275: for (i = 0; i < num_local; ++i) {
-: 276: /* For rank i in the new communicator, find the corresponding
-: 277: rank in the input communicator */
1554624: 278: MPID_VCR_Dup( comm->vcr[local_procs[i]],
-: 279: &comm->node_comm->vcr[i] );
-: 280: }
-: 281:
-: 282: MPID_Dev_comm_create_hook( comm->node_comm );
-: 283: /* don't call MPIR_Comm_commit here */
-: 284: }
-: 285:
-: 286:
-: 287: /* this process may not be a member of the node_roots_comm */
654682: 288: if (local_rank == 0) {
309029: 289: mpi_errno = MPIR_Comm_create(&comm->node_roots_comm);
|
309029: 290: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 291:
|
309029: 292: comm->node_roots_comm->context_id = comm->context_id + MPID_CONTEXT_INTERNODE_OFFSET;
309029: 293: comm->node_roots_comm->recvcontext_id = comm->node_roots_comm->context_id;
309029: 294: comm->node_roots_comm->rank = external_rank;
309029: 295: comm->node_roots_comm->comm_kind = MPID_INTRACOMM;
309029: 296: comm->node_roots_comm->local_comm = NULL;
-: 297:
309029: 298: comm->node_roots_comm->local_size = num_external;
309029: 299: comm->node_roots_comm->remote_size = num_external;
-: 300:
309029: 301: MPID_VCRT_Create( num_external, &comm->node_roots_comm->vcrt );
309029: 302: MPID_VCRT_Get_ptr( comm->node_roots_comm->vcrt, &comm->node_roots_comm->vcr );
618058: 303: for (i = 0; i < num_external; ++i) {
-: 304: /* For rank i in the new communicator, find the corresponding
-: 305: rank in the input communicator */
309029: 306: MPID_VCR_Dup( comm->vcr[external_procs[i]],
-: 307: &comm->node_roots_comm->vcr[i] );
-: 308: }
-: 309:
-: 310: MPID_Dev_comm_create_hook( comm->node_roots_comm );
-: 311: /* don't call MPIR_Comm_commit here */
-: 312: }
-: 313:
654682: 314: comm->is_node_aware = 1;
-: 315: }
-: 316:
695941: 317:fn_exit:
695941: 318: if (external_procs != NULL)
692217: 319: MPIU_Free(external_procs);
695941: 320: if (local_procs != NULL)
692217: 321: MPIU_Free(local_procs);
-: 322:
|
-: 323: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_COMMIT);
|
695941: 324: return mpi_errno;
|
-: 325:fn_fail:
-: 326: goto fn_exit;
-: 327:}
-: 328:
-: 329:/* Returns true if the given communicator is aware of node topology information,
-: 330: false otherwise. Such information could be used to implement more efficient
-: 331: collective communication, for example. */
-: 332:int MPIR_Comm_is_node_aware(MPID_Comm * comm)
|
4176576: 333:{
4176576: 334: return comm->is_node_aware;
-: 335:}
-: 336:
-: 337:/* Returns true if the communicator is node-aware and processes in all the nodes
-: 338: are consecutive. For example, if node 0 contains "0, 1, 2, 3", node 1
-: 339: contains "4, 5, 6", and node 2 contains "7", we shall return true. */
-: 340:int MPIR_Comm_is_node_consecutive(MPID_Comm * comm)
18217: 341:{
18217: 342: int i = 0, curr_nodeidx = 0;
18217: 343: int *internode_table = comm->internode_table;
-: 344:
18217: 345: if (!comm->is_node_aware)
7173: 346: return 0;
-: 347:
22646: 348: for (; i < comm->local_size; i++)
-: 349: {
22646: 350: if (internode_table[i] == curr_nodeidx + 1)
|
#####: 351: curr_nodeidx++;
|
22646: 352: else if (internode_table[i] != curr_nodeidx)
|
#####: 353: return 0;
-: 354: }
-: 355:
|
11044: 356: return 1;
-: 357:}
-: 358:
-: 359:/*
-: 360: * Here are the routines to find a new context id. The algorithm is discussed
-: 361: * in detail in the mpich2 coding document. There are versions for
-: 362: * single threaded and multithreaded MPI.
-: 363: *
-: 364: * Both the threaded and non-threaded routines use the same mask of
-: 365: * available context id values.
-: 366: */
-: 367:static uint32_t context_mask[MPIR_MAX_CONTEXT_MASK];
-: 368:static int initialize_context_mask = 1;
-: 369:
-: 370:#ifdef USE_DBG_LOGGING
-: 371:/* Create a string that contains the context mask. This is
-: 372: used only with the logging interface, and must be used by one thread at
-: 373: a time (should this be enforced by the logging interface?).
-: 374: Converts the mask to hex and returns a pointer to that string */
-: 375:static char *MPIR_ContextMaskToStr( void )
-: 376:{
-: 377: static char bufstr[MPIR_MAX_CONTEXT_MASK*8+1];
-: 378: int i;
-: 379: int maxset=0;
-: 380:
-: 381: for (maxset=MPIR_MAX_CONTEXT_MASK-1; maxset>=0; maxset--) {
-: 382: if (context_mask[maxset] != 0) break;
-: 383: }
-: 384:
-: 385: for (i=0; i<maxset; i++) {
-: 386: MPIU_Snprintf( &bufstr[i*8], 9, "%.8x", context_mask[i] );
-: 387: }
-: 388: return bufstr;
-: 389:}
-: 390:#endif
-: 391:
-: 392:#ifdef MPICH_DEBUG_HANDLEALLOC
-: 393:static int MPIU_CheckContextIDsOnFinalize(void *context_mask_ptr)
-: 394:{
-: 395: int i;
-: 396: uint32_t *mask = context_mask_ptr;
-: 397: /* the predefined communicators should be freed by this point, so we don't
-: 398: * need to special case bits 0,1, and 2 */
-: 399: for (i = 0; i < MPIR_MAX_CONTEXT_MASK; ++i) {
-: 400: if (~mask[i]) {
-: 401: /* some bits were still cleared */
-: 402: printf("leaked context IDs detected: mask=%p mask[%d]=%#x\n", mask, i, (int)mask[i]);
-: 403: }
-: 404: }
-: 405: return MPI_SUCCESS;
-: 406:}
-: 407:#endif
-: 408:
-: 409:static void MPIR_Init_contextid(void)
2426: 410:{
-: 411: int i;
-: 412:
155264: 413: for (i=1; i<MPIR_MAX_CONTEXT_MASK; i++) {
152838: 414: context_mask[i] = 0xFFFFFFFF;
-: 415: }
-: 416: /* the first three values are already used (comm_world, comm_self,
-: 417: and the internal-only copy of comm_world) */
2426: 418: context_mask[0] = 0xFFFFFFF8;
2426: 419: initialize_context_mask = 0;
-: 420:
-: 421:#ifdef MPICH_DEBUG_HANDLEALLOC
-: 422: /* check for context ID leaks in MPI_Finalize. Use (_PRIO-1) to make sure
-: 423: * that we run after MPID_Finalize. */
-: 424: MPIR_Add_finalize(MPIU_CheckContextIDsOnFinalize, context_mask,
-: 425: MPIR_FINALIZE_CALLBACK_PRIO - 1);
-: 426:#endif
2426: 427:}
-: 428:
-: 429:/* Return the context id corresponding to the first set bit in the mask.
-: 430: Return 0 if no bit found. This function does _not_ alter local_mask. */
-: 431:static int MPIR_Locate_context_bit(uint32_t local_mask[])
982446: 432:{
982446: 433: int i, j, context_id = 0;
2583318: 434: for (i=0; i<MPIR_MAX_CONTEXT_MASK; i++) {
2580402: 435: if (local_mask[i]) {
-: 436: /* There is a bit set in this word. */
-: 437: register uint32_t val, nval;
-: 438: /* The following code finds the highest set bit by recursively
-: 439: checking the top half of a subword for a bit, and incrementing
-: 440: the bit location by the number of bit of the lower sub word if
-: 441: the high subword contains a set bit. The assumption is that
-: 442: full-word bitwise operations and compares against zero are
-: 443: fast */
979530: 444: val = local_mask[i];
979530: 445: j = 0;
979530: 446: nval = val & 0xFFFF0000;
979530: 447: if (nval) {
785718: 448: j += 16;
785718: 449: val = nval;
-: 450: }
979530: 451: nval = val & 0xFF00FF00;
979530: 452: if (nval) {
775858: 453: j += 8;
775858: 454: val = nval;
-: 455: }
979530: 456: nval = val & 0xF0F0F0F0;
979530: 457: if (nval) {
664705: 458: j += 4;
664705: 459: val = nval;
-: 460: }
979530: 461: nval = val & 0xCCCCCCCC;
979530: 462: if (nval) {
765961: 463: j += 2;
765961: 464: val = nval;
-: 465: }
979530: 466: if (val & 0xAAAAAAAA) {
745438: 467: j += 1;
-: 468: }
979530: 469: context_id = (MPIR_CONTEXT_INT_BITS * i + j) << MPID_CONTEXT_PREFIX_SHIFT;
979530: 470: return context_id;
-: 471: }
-: 472: }
2916: 473: return 0;
-: 474:}
-: 475:
-: 476:/* Allocates a context ID from the given mask by clearing the bit
-: 477: * corresponding to the the given id. Returns 0 on failure, id on
-: 478: * success. */
-: 479:static int MPIR_Allocate_context_bit(uint32_t mask[], MPIR_Context_id_t id)
967236: 480:{
-: 481: int raw_prefix, idx, bitpos;
967236: 482: raw_prefix = MPID_CONTEXT_READ_FIELD(PREFIX,id);
967236: 483: idx = raw_prefix / MPIR_CONTEXT_INT_BITS;
967236: 484: bitpos = raw_prefix % MPIR_CONTEXT_INT_BITS;
-: 485:
-: 486: /* the bit should not already be cleared (allocated) */
967236: 487: MPIU_Assert(mask[idx] & (1<<bitpos));
-: 488:
-: 489: /* clear the bit */
967236: 490: mask[idx] &= ~(1<<bitpos);
-: 491:
-: 492: MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,
-: 493: "allocating contextid = %d, (mask=%p, mask[%d], bit %d)",
-: 494: id, mask, idx, bitpos));
967236: 495: return id;
-: 496:}
-: 497:
-: 498:/* Allocates the first available context ID from context_mask based on the available
-: 499: * bits given in local_mask. This function will clear the corresponding bit in
-: 500: * context_mask if allocation was successful.
-: 501: *
-: 502: * Returns 0 on failure. Returns the allocated context ID on success. */
-: 503:static int MPIR_Find_and_allocate_context_id(uint32_t local_mask[])
970152: 504:{
-: 505: MPIR_Context_id_t context_id;
970152: 506: context_id = MPIR_Locate_context_bit(local_mask);
970152: 507: if (context_id != 0) {
967236: 508: context_id = MPIR_Allocate_context_bit(context_mask, context_id);
-: 509: }
970152: 510: return context_id;
-: 511:}
-: 512:
-: 513:#ifndef MPICH_IS_THREADED
-: 514:/* Unthreaded (only one MPI call active at any time) */
-: 515:
-: 516:#undef FUNCNAME
-: 517:#define FUNCNAME MPIR_Get_contextid
-: 518:#undef FCNAME
-: 519:#define FCNAME "MPIR_Get_contextid"
-: 520:int MPIR_Get_contextid( MPID_Comm *comm_ptr, MPIR_Context_id_t *context_id )
-: 521:{
-: 522: int mpi_errno = MPI_SUCCESS;
-: 523: uint32_t local_mask[MPIR_MAX_CONTEXT_MASK];
-: 524: MPIU_THREADPRIV_DECL;
-: 525: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_CONTEXTID);
-: 526:
-: 527: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_CONTEXTID);
-: 528:
-: 529: *context_id = 0;
-: 530:
-: 531: if (initialize_context_mask) {
-: 532: MPIR_Init_contextid();
-: 533: }
-: 534: MPIU_Memcpy( local_mask, context_mask, MPIR_MAX_CONTEXT_MASK * sizeof(int) );
-: 535:
-: 536: /* Note that this is the unthreaded version */
-: 537: MPIU_THREADPRIV_GET;
-: 538: MPIR_Nest_incr();
-: 539: /* Comm must be an intracommunicator */
-: 540: mpi_errno = NMPI_Allreduce( MPI_IN_PLACE, local_mask, MPIR_MAX_CONTEXT_MASK,
-: 541: MPI_INT, MPI_BAND, comm_ptr->handle );
-: 542: MPIR_Nest_decr();
|
-: 543: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 544:
-: 545: *context_id = MPIR_Find_and_allocate_context_id(local_mask);
-: 546: MPIU_ERR_CHKANDJUMP(!(*context_id), mpi_errno, MPIR_ERR_RECOVERABLE, "**toomanycomm");
-: 547:
-: 548:fn_exit:
-: 549: MPIU_DBG_MSG_S(COMM,VERBOSE,"Context mask = %s",MPIR_ContextMaskToStr());
-: 550:
-: 551: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_CONTEXTID);
-: 552: return mpi_errno;
-: 553:fn_fail:
-: 554: goto fn_exit;
-: 555:}
-: 556:
-: 557:#else /* MPICH_IS_THREADED is set and true */
-: 558:
-: 559:/* Additional values needed to maintain thread safety */
-: 560:static volatile int mask_in_use = 0;
-: 561:/* lowestContextId is used to break ties when multiple threads
-: 562: are contending for the mask */
-: 563:#define MPIR_MAXID (1 << 30)
-: 564:static volatile int lowestContextId = MPIR_MAXID;
-: 565:
-: 566:#undef FUNCNAME
-: 567:#define FUNCNAME MPIR_Get_contextid
-: 568:#undef FCNAME
-: 569:#define FCNAME "MPIR_Get_contextid"
-: 570:int MPIR_Get_contextid( MPID_Comm *comm_ptr, MPIR_Context_id_t *context_id )
|
967236: 571:{
967236: 572: int mpi_errno = MPI_SUCCESS;
-: 573: uint32_t local_mask[MPIR_MAX_CONTEXT_MASK];
967236: 574: int own_mask = 0;
967236: 575: int testCount = 10; /* if you change this value, you need to also change
-: 576: it below where it is reinitialized */
-: 577:
967236: 578: MPIU_THREADPRIV_DECL;
-: 579: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_CONTEXTID);
-: 580:
-: 581: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_CONTEXTID);
-: 582:
967236: 583: MPIU_THREADPRIV_GET;
-: 584:
967236: 585: *context_id = 0;
-: 586:
-: 587: /* We increment the nest level now because we need to know that we're
-: 588: within another MPI routine before calling the CS_ENTER macro */
967236: 589: MPIR_Nest_incr();
-: 590:
-: 591: /* We lock only around access to the mask. If another thread is
-: 592: using the mask, we take a mask of zero */
-: 593: MPIU_DBG_MSG_FMT( COMM, VERBOSE, (MPIU_DBG_FDEST,
-: 594: "Entering; shared state is %d:%d", mask_in_use, lowestContextId ) );
-: 595: /* We need a special test in this loop for the case where some process
-: 596: has exhausted its supply of context ids. In the single threaded case,
-: 597: this is simple, because the algorithm is deterministic (see above). In
-: 598: the multithreaded case, it is more complicated, because we may get a
-: 599: zero for the context mask because some other thread holds the mask.
-: 600: In addition, we can't check for the case where this process did not
-: 601: select MPI_THREAD_MULTIPLE, because one of the other processes
-: 602: may have selected MPI_THREAD_MULTIPLE. To handle this case, after a
-: 603: fixed number of failures, we test to see if some process has exhausted
-: 604: its supply of context ids. If so, all processes can invoke the
-: 605: out-of-context-id error. That fixed number of tests is in testCount */
3038824: 606: while (*context_id == 0) {
-: 607: /* In all but the global-critical-section case, we must ensure that
-: 608: only one thread access the context id mask at a time */
-: 609: MPIU_THREAD_CS_ENTER(CONTEXTID,);
1104352: 610: if (initialize_context_mask) {
2426: 611: MPIR_Init_contextid();
-: 612: }
1104352: 613: if (mask_in_use || comm_ptr->context_id > lowestContextId) {
134200: 614: memset( local_mask, 0, MPIR_MAX_CONTEXT_MASK * sizeof(int) );
134200: 615: own_mask = 0;
134200: 616: if (comm_ptr->context_id < lowestContextId) {
948: 617: lowestContextId = comm_ptr->context_id;
-: 618: }
-: 619: MPIU_DBG_MSG_D( COMM, VERBOSE,
-: 620: "In in-use, set lowestContextId to %d", lowestContextId );
-: 621: }
-: 622: else {
970152: 623: MPIU_Memcpy( local_mask, context_mask, MPIR_MAX_CONTEXT_MASK * sizeof(int) );
970152: 624: mask_in_use = 1;
970152: 625: own_mask = 1;
970152: 626: lowestContextId = comm_ptr->context_id;
-: 627: MPIU_DBG_MSG( COMM, VERBOSE, "Copied local_mask" );
-: 628: }
-: 629: MPIU_THREAD_CS_EXIT(CONTEXTID,);
-: 630:
-: 631: /* Now, try to get a context id */
1104352: 632: MPIU_Assert(comm_ptr->comm_kind == MPID_INTRACOMM);
-: 633: /* In the global and brief-global cases, note that this routine will
-: 634: release that global lock when it needs to wait. That will allow
-: 635: other processes to enter the global or brief global critical section.
-: 636: */
1104352: 637: mpi_errno = NMPI_Allreduce( MPI_IN_PLACE, local_mask, MPIR_MAX_CONTEXT_MASK,
-: 638: MPI_INT, MPI_BAND, comm_ptr->handle );
|
1104352: 639: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 640:
|
1104352: 641: if (own_mask) {
-: 642: /* There is a chance that we've found a context id */
-: 643: MPIU_THREAD_CS_ENTER(CONTEXTID,);
-: 644: /* Find_and_allocate_context_id updates the context_mask if it finds a match */
970152: 645: *context_id = MPIR_Find_and_allocate_context_id(local_mask);
-: 646: MPIU_DBG_MSG_D( COMM, VERBOSE,
-: 647: "Context id is now %hd", *context_id );
970152: 648: if (*context_id > 0) {
-: 649: /* If we were the lowest context id, reset the value to
-: 650: allow the other threads to compete for the mask */
967236: 651: if (lowestContextId == comm_ptr->context_id) {
967226: 652: lowestContextId = MPIR_MAXID;
-: 653: /* Else leave it alone; there is another thread waiting */
-: 654: }
-: 655: }
-: 656: else {
-: 657: /* else we did not find a context id. Give up the mask in case
-: 658: there is another thread (with a lower context id) waiting for
-: 659: it.
-: 660:
-: 661: We need to ensure that any other threads have the
-: 662: opportunity to run. We do this by releasing the single
-: 663: mutex, yielding, and then reaquiring the mutex.
-: 664: We might want to do something more sophisticated, such
-: 665: as using a condition variable (if we know for sure that
-: 666: there is another thread on this process that is waiting).
-: 667: */
2916: 668: MPIU_THREAD_CS_YIELD(CONTEXTID,);
-: 669:#if 0
-: 670: /* The old code */
-: 671: MPID_Thread_mutex_unlock(&MPIR_ThreadInfo.global_mutex);
-: 672: MPID_Thread_yield();
-: 673: MPID_Thread_mutex_lock(&MPIR_ThreadInfo.global_mutex);
-: 674:#endif
-: 675: }
970152: 676: mask_in_use = 0;
-: 677: MPIU_THREAD_CS_EXIT(CONTEXTID,);
-: 678: }
-: 679: else {
-: 680: /* As above, force this thread to yield */
-: 681: /* FIXME: TEMP for current yield definition*/
-: 682: MPIU_THREAD_CS_ENTER(CONTEXTID,);
134200: 683: MPIU_THREAD_CS_YIELD(CONTEXTID,);
-: 684: MPIU_THREAD_CS_EXIT(CONTEXTID,);
-: 685:#if 0
-: 686: MPID_Thread_mutex_unlock(&MPIR_ThreadInfo.global_mutex);
-: 687: MPID_Thread_yield();
-: 688: MPID_Thread_mutex_lock(&MPIR_ThreadInfo.global_mutex);
-: 689:#endif
-: 690: }
-: 691: /* Here is the test for out-of-context ids */
1104352: 692: if ((testCount-- == 0) && (*context_id == 0)) {
-: 693: int hasNoId, totalHasNoId;
-: 694: /* We don't need to lock on this because we're just looking for
-: 695: zero or nonzero */
12294: 696: hasNoId = MPIR_Locate_context_bit(context_mask) == 0;
12294: 697: mpi_errno = NMPI_Allreduce( &hasNoId, &totalHasNoId, 1, MPI_INT,
-: 698: MPI_MAX, comm_ptr->handle );
|
12294: 699: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
|
12294: 700: if (totalHasNoId == 1) {
-: 701: /* Release the mask for use by other threads */
|
#####: 702: if (own_mask) {
#####: 703: mask_in_use = 0;
-: 704: }
|
#####: 705: MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**toomanycomm");
-: 706: }
-: 707: else { /* reinitialize testCount */
|
12294: 708: testCount = 10;
-: 709: MPIU_DBG_MSG_D(COMM, VERBOSE, "reinitialized testCount to %d", testCount);
-: 710: }
-: 711: }
-: 712: }
-: 713:
967236: 714:fn_exit:
-: 715: MPIU_DBG_MSG_S(COMM,VERBOSE,"Context mask = %s",MPIR_ContextMaskToStr());
967236: 716: MPIR_Nest_decr();
|
-: 717: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_CONTEXTID);
|
967236: 718: return mpi_errno;
|
#####: 719:fn_fail:
-: 720: /* Release the masks */
|
#####: 721: if (own_mask) {
#####: 722: mask_in_use = 0;
-: 723: }
-: 724: goto fn_exit;
-: 725:}
-: 726:#endif
-: 727:
-: 728:/* Get a context for a new intercomm. There are two approaches
-: 729: here (for MPI-1 codes only)
-: 730: (a) Each local group gets a context; the groups exchange, and
-: 731: the low value is accepted and the high one returned. This
-: 732: works because the context ids are taken from the same pool.
-: 733: (b) Form a temporary intracomm over all processes and use that
-: 734: with the regular algorithm.
-: 735:
-: 736: In some ways, (a) is the better approach because it is the one that
-: 737: extends to MPI-2 (where the last step, returning the context, is
-: 738: not used and instead separate send and receive context id value
-: 739: are kept). For this reason, we'll use (a).
-: 740:
-: 741: Even better is to separate the local and remote context ids. Then
-: 742: each group of processes can manage their context ids separately.
-: 743:*/
-: 744:/*
-: 745: * This uses the thread-safe (if necessary) routine to get a context id
-: 746: * and does not need its own thread-safe version.
-: 747: */
-: 748:#undef FUNCNAME
-: 749:#define FUNCNAME MPIR_Get_intercomm_contextid
-: 750:#undef FCNAME
-: 751:#define FCNAME "MPIR_Get_intercomm_contextid"
-: 752:int MPIR_Get_intercomm_contextid( MPID_Comm *comm_ptr, MPIR_Context_id_t *context_id,
-: 753: MPIR_Context_id_t *recvcontext_id )
|
331: 754:{
-: 755: MPIR_Context_id_t mycontext_id, remote_context_id;
331: 756: int mpi_errno = MPI_SUCCESS;
331: 757: int tag = 31567; /* FIXME - we need an internal tag or
-: 758: communication channel. Can we use a different
-: 759: context instead?. Or can we use the tag
-: 760: provided in the intercomm routine? (not on a dup,
-: 761: but in that case it can use the collective context) */
331: 762: MPIU_THREADPRIV_DECL;
-: 763: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);
-: 764:
-: 765: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);
-: 766:
331: 767: if (!comm_ptr->local_comm) {
-: 768: /* Manufacture the local communicator */
321: 769: mpi_errno = MPIR_Setup_intercomm_localcomm( comm_ptr );
|
321: 770: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 771: }
-: 772:
|
331: 773: mpi_errno = MPIR_Get_contextid( comm_ptr->local_comm, &mycontext_id );
|
331: 774: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
|
331: 775: MPIU_Assert(mycontext_id != 0);
-: 776:
331: 777: MPIU_THREADPRIV_GET;
-: 778:
-: 779: /* MPIC routine uses an internal context id. The local leads (process 0)
-: 780: exchange data */
331: 781: remote_context_id = -1;
331: 782: if (comm_ptr->rank == 0) {
150: 783: mpi_errno = MPIC_Sendrecv( &mycontext_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, 0, tag,
-: 784: &remote_context_id, 1, MPIR_CONTEXT_ID_T_DATATYPE, 0, tag,
-: 785: comm_ptr->handle, MPI_STATUS_IGNORE );
|
150: 786: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 787: }
-: 788:
-: 789: /* Make sure that all of the local processes now have this
-: 790: id */
|
331: 791: MPIR_Nest_incr();
331: 792: mpi_errno = NMPI_Bcast( &remote_context_id, 1, MPIR_CONTEXT_ID_T_DATATYPE,
-: 793: 0, comm_ptr->local_comm->handle );
331: 794: MPIR_Nest_decr();
|
331: 795: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 796:
-: 797: /* The recvcontext_id must be the one that was allocated out of the local
-: 798: * group, not the remote group. Otherwise we could end up posting two
-: 799: * MPI_ANY_SOURCE,MPI_ANY_TAG recvs on the same context IDs even though we
-: 800: * are attempting to post them for two separate communicators. */
|
331: 801: *context_id = remote_context_id;
331: 802: *recvcontext_id = mycontext_id;
|
331: 803: fn_fail:
-: 804: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);
|
331: 805: return mpi_errno;
-: 806:}
-: 807:
-: 808:#undef FUNCNAME
-: 809:#define FUNCNAME MPIR_Free_contextid
-: 810:#undef FCNAME
-: 811:#define FCNAME MPIU_QUOTE(FUNCNAME)
-: 812:void MPIR_Free_contextid( MPIR_Context_id_t context_id )
1947385: 813:{
-: 814: int idx, bitpos, raw_prefix;
-: 815: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_FREE_CONTEXTID);
-: 816:
-: 817: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_FREE_CONTEXTID);
-: 818:
-: 819: /* Convert the context id to the bit position */
1947385: 820: raw_prefix = MPID_CONTEXT_READ_FIELD(PREFIX,context_id);
1947385: 821: idx = raw_prefix / MPIR_CONTEXT_INT_BITS;
1947385: 822: bitpos = raw_prefix % MPIR_CONTEXT_INT_BITS;
-: 823:
|
-: 824: /* --BEGIN ERROR HANDLING-- */
1947385: 825: if (idx < 0 || idx >= MPIR_MAX_CONTEXT_MASK) {
#####: 826: MPID_Abort( 0, MPI_ERR_INTERN, 1,
-: 827: "In MPIR_Free_contextid, idx is out of range" );
-: 828: }
-: 829:
-: 830: /* The low order bits for dynamic context IDs don't have meaning the
-: 831: * same way that low bits of non-dynamic ctx IDs do. So we have to
-: 832: * check the dynamic case first. */
1947385: 833: if (MPID_CONTEXT_READ_FIELD(DYNAMIC_PROC, context_id)) {
-: 834: MPIU_DBG_MSG_D(COMM,VERBOSE,"skipping dynamic process ctx id, context_id=%d", context_id);
1336: 835: goto fn_exit;
-: 836: }
-: 837: else { /* non-dynamic context ID */
-: 838: /* In terms of the context ID bit vector, intercomms and their constituent
-: 839: * localcomms have the same value. To avoid a double-free situation we just
-: 840: * don't free the context ID for localcomms and assume it will be cleaned up
-: 841: * when the parent intercomm is itself completely freed. */
1946049: 842: if (MPID_CONTEXT_READ_FIELD(IS_LOCALCOMM, context_id)) {
-: 843:#ifdef USE_DBG_LOGGING
-: 844: char dump_str[1024];
-: 845: MPIR_Comm_dump_context_id(context_id, dump_str, sizeof(dump_str));
-: 846: MPIU_DBG_MSG_S(COMM,VERBOSE,"skipping localcomm id: %s", dump_str);
-: 847:#endif
4840: 848: goto fn_exit;
-: 849: }
1941209: 850: else if (MPID_CONTEXT_READ_FIELD(SUBCOMM, context_id)) {
-: 851: MPIU_DBG_MSG_D(COMM,VERBOSE,"skipping non-parent communicator ctx id, context_id=%d", context_id);
961074: 852: goto fn_exit;
-: 853: }
-: 854: }
-: 855:
-: 856: /* Check that this context id has been allocated */
980135: 857: if ( (context_mask[idx] & (0x1 << bitpos)) != 0 ) {
-: 858:#ifdef USE_DBG_LOGGING
-: 859: char dump_str[1024];
-: 860: MPIR_Comm_dump_context_id(context_id, dump_str, sizeof(dump_str));
-: 861: MPIU_DBG_MSG_S(COMM,VERBOSE,"context dump: %s", dump_str);
-: 862: MPIU_DBG_MSG_S(COMM,VERBOSE,"context mask = %s",MPIR_ContextMaskToStr());
-: 863:#endif
#####: 864: MPID_Abort( 0, MPI_ERR_INTERN, 1,
-: 865: "In MPIR_Free_contextid, the context id is not in use" );
-: 866: }
-: 867: /* --END ERROR HANDLING-- */
-: 868:
-: 869: MPIU_THREAD_CS_ENTER(CONTEXTID,);
-: 870: /* MT: Note that this update must be done atomically in the multithreaedd
-: 871: case. In the "one, single lock" implementation, that lock is indeed
-: 872: held when this operation is called. */
|
980135: 873: context_mask[idx] |= (0x1 << bitpos);
-: 874: MPIU_THREAD_CS_EXIT(CONTEXTID,);
-: 875:
-: 876: MPIU_DBG_MSG_FMT(COMM,VERBOSE,
-: 877: (MPIU_DBG_FDEST,
-: 878: "Freed context %d, mask[%d] bit %d (prefix=%#x)",
-: 879: context_id, idx, bitpos, raw_prefix));
1947385: 880:fn_exit:
|
-: 881: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_FREE_CONTEXTID);
|
1947385: 882:}
-: 883:
-: 884:/*
-: 885: * Copy a communicator, including creating a new context and copying the
-: 886: * virtual connection tables and clearing the various fields.
-: 887: * Does *not* copy attributes. If size is < the size of the local group
-: 888: * in the input communicator, copy only the first size elements.
-: 889: * If this process is not a member, return a null pointer in outcomm_ptr.
-: 890: * This is only supported in the case where the communicator is in
-: 891: * Intracomm (not an Intercomm). Note that this is all that is required
-: 892: * for cart_create and graph_create.
-: 893: *
-: 894: * Used by cart_create, graph_create, and dup_create
-: 895: */
-: 896:#undef FUNCNAME
-: 897:#define FUNCNAME MPIR_Comm_copy
-: 898:#undef FCNAME
-: 899:#define FCNAME "MPIR_Comm_copy"
-: 900:int MPIR_Comm_copy( MPID_Comm *comm_ptr, int size, MPID_Comm **outcomm_ptr )
530919: 901:{
530919: 902: int mpi_errno = MPI_SUCCESS;
-: 903: MPIR_Context_id_t new_context_id, new_recvcontext_id;
530919: 904: MPID_Comm *newcomm_ptr = NULL;
-: 905: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_COPY);
-: 906:
-: 907: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_COPY);
-: 908:
-: 909: /* Get a new context first. We need this to be collective over the
-: 910: input communicator */
-: 911: /* If there is a context id cache in oldcomm, use it here. Otherwise,
-: 912: use the appropriate algorithm to get a new context id. Be careful
-: 913: of intercomms here */
530919: 914: if (comm_ptr->comm_kind == MPID_INTERCOMM) {
331: 915: mpi_errno =
-: 916: MPIR_Get_intercomm_contextid(
-: 917: comm_ptr, &new_context_id, &new_recvcontext_id );
|
331: 918: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 919: }
-: 920: else {
|
530588: 921: mpi_errno = MPIR_Get_contextid( comm_ptr, &new_context_id );
530588: 922: new_recvcontext_id = new_context_id;
|
530588: 923: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
|
530588: 924: MPIU_Assert(new_context_id != 0);
-: 925: }
|
-: 926: /* --BEGIN ERROR HANDLING-- */
530919: 927: if (new_context_id == 0) {
#####: 928: MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**toomanycomm" );
-: 929: }
-: 930: /* --END ERROR HANDLING-- */
-: 931:
-: 932: /* This is the local size, not the remote size, in the case of
-: 933: an intercomm */
|
530919: 934: if (comm_ptr->rank >= size) {
1: 935: *outcomm_ptr = 0;
-: 936: /* always free the recvcontext ID, never the "send" ID */
1: 937: MPIR_Free_contextid(new_recvcontext_id);
1: 938: goto fn_exit;
-: 939: }
-: 940:
-: 941: /* We're left with the processes that will have a non-null communicator.
-: 942: Create the object, initialize the data, and return the result */
-: 943:
530918: 944: mpi_errno = MPIR_Comm_create( &newcomm_ptr );
|
530918: 945: if (mpi_errno) goto fn_fail;
-: 946:
|
530918: 947: newcomm_ptr->context_id = new_context_id;
530918: 948: newcomm_ptr->recvcontext_id = new_recvcontext_id;
-: 949:
-: 950: /* Save the kind of the communicator */
530918: 951: newcomm_ptr->comm_kind = comm_ptr->comm_kind;
530918: 952: newcomm_ptr->local_comm = 0;
-: 953:
-: 954: /* There are two cases here - size is the same as the old communicator,
-: 955: or it is smaller. If the size is the same, we can just add a reference.
-: 956: Otherwise, we need to create a new VCRT. Note that this is the
-: 957: test that matches the test on rank above. */
530918: 958: if (size == comm_ptr->local_size) {
-: 959: /* Duplicate the VCRT references */
530915: 960: MPID_VCRT_Add_ref( comm_ptr->vcrt );
530915: 961: newcomm_ptr->vcrt = comm_ptr->vcrt;
530915: 962: newcomm_ptr->vcr = comm_ptr->vcr;
-: 963: }
-: 964: else {
-: 965: int i;
-: 966: /* The "remote" vcr gets the shortened vcrt */
3: 967: MPID_VCRT_Create( size, &newcomm_ptr->vcrt );
3: 968: MPID_VCRT_Get_ptr( newcomm_ptr->vcrt,
-: 969: &newcomm_ptr->vcr );
12: 970: for (i=0; i<size; i++) {
-: 971: /* For rank i in the new communicator, find the corresponding
-: 972: rank in the input communicator */
9: 973: MPID_VCR_Dup( comm_ptr->vcr[i], &newcomm_ptr->vcr[i] );
-: 974: }
-: 975: }
-: 976:
-: 977: /* If it is an intercomm, duplicate the local vcrt references */
530918: 978: if (comm_ptr->comm_kind == MPID_INTERCOMM) {
331: 979: MPID_VCRT_Add_ref( comm_ptr->local_vcrt );
331: 980: newcomm_ptr->local_vcrt = comm_ptr->local_vcrt;
331: 981: newcomm_ptr->local_vcr = comm_ptr->local_vcr;
-: 982: }
-: 983:
-: 984: /* Set the sizes and ranks */
530918: 985: newcomm_ptr->rank = comm_ptr->rank;
530918: 986: if (comm_ptr->comm_kind == MPID_INTERCOMM) {
331: 987: newcomm_ptr->local_size = comm_ptr->local_size;
331: 988: newcomm_ptr->remote_size = comm_ptr->remote_size;
331: 989: newcomm_ptr->is_low_group = comm_ptr->is_low_group;
-: 990: }
-: 991: else {
530587: 992: newcomm_ptr->local_size = size;
530587: 993: newcomm_ptr->remote_size = size;
-: 994: }
-: 995:
-: 996: /* Inherit the error handler (if any) */
530918: 997: newcomm_ptr->errhandler = comm_ptr->errhandler;
530918: 998: if (comm_ptr->errhandler) {
409669: 999: MPIR_Errhandler_add_ref( comm_ptr->errhandler );
-: 1000: }
-: 1001:
-: 1002: /* Notify the device of the new communicator */
-: 1003: MPID_Dev_comm_create_hook(newcomm_ptr);
530918: 1004: mpi_errno = MPIR_Comm_commit(newcomm_ptr);
|
530918: 1005: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 1006:
-: 1007: /* Start with no attributes on this communicator */
|
530918: 1008: newcomm_ptr->attributes = 0;
530918: 1009: *outcomm_ptr = newcomm_ptr;
-: 1010:
|
530919: 1011: fn_fail:
|
530919: 1012: fn_exit:
-: 1013:
|
-: 1014: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_COPY);
-: 1015:
|
530919: 1016: return mpi_errno;
-: 1017:}
-: 1018:
-: 1019:/* Common body between MPIR_Comm_release and MPIR_comm_release_always. This
-: 1020: * helper function frees the actual MPID_Comm structure and any associated
-: 1021: * storage. It also releases any refernces to other objects, such as the VCRT.
-: 1022: * This function should only be called when the communicator's reference count
-: 1023: * has dropped to 0. */
-: 1024:#undef FUNCNAME
-: 1025:#define FUNCNAME comm_delete
-: 1026:#undef FCNAME
-: 1027:#define FCNAME MPIU_QUOTE(FUNCNAME)
-: 1028:static int comm_delete(MPID_Comm * comm_ptr, int isDisconnect)
1667695: 1029:{
-: 1030: int in_use;
1667695: 1031: int mpi_errno = MPI_SUCCESS;
-: 1032: MPID_MPI_STATE_DECL(MPID_STATE_COMM_DELETE);
-: 1033:
-: 1034: MPID_MPI_FUNC_ENTER(MPID_STATE_COMM_DELETE);
-: 1035:
1667695: 1036: MPIU_Assert(MPIU_Object_get_ref(comm_ptr) == 0); /* sanity check */
-: 1037:
-: 1038: /* Remove the attributes, executing the attribute delete routine.
-: 1039: Do this only if the attribute functions are defined.
-: 1040: This must be done first, because if freeing the attributes
-: 1041: returns an error, the communicator is not freed */
1667695: 1042: if (MPIR_Process.attr_free && comm_ptr->attributes) {
-: 1043: /* Temporarily add a reference to this communicator because
-: 1044: the attr_free code requires a valid communicator */
5507: 1045: MPIU_Object_add_ref( comm_ptr );
5507: 1046: mpi_errno = MPIR_Process.attr_free( comm_ptr->handle,
-: 1047: &comm_ptr->attributes );
-: 1048: /* Release the temporary reference added before the call to
-: 1049: attr_free */
5507: 1050: MPIU_Object_release_ref( comm_ptr, &in_use);
-: 1051: }
-: 1052:
-: 1053: /* If the attribute delete functions return failure, the
-: 1054: communicator must not be freed. That is the reason for the
-: 1055: test on mpi_errno here. */
1667695: 1056: if (mpi_errno == MPI_SUCCESS) {
-: 1057: /* If this communicator is our parent, and we're disconnecting
-: 1058: from the parent, mark that fact */
1667693: 1059: if (MPIR_Process.comm_parent == comm_ptr)
406: 1060: MPIR_Process.comm_parent = NULL;
-: 1061:
-: 1062: /* Notify the device that the communicator is about to be
-: 1063: destroyed */
-: 1064: MPID_Dev_comm_destroy_hook(comm_ptr);
-: 1065:
-: 1066: /* Free the VCRT */
1667693: 1067: mpi_errno = MPID_VCRT_Release(comm_ptr->vcrt, isDisconnect);
1667693: 1068: if (mpi_errno != MPI_SUCCESS) {
|
#####: 1069: MPIU_ERR_POP(mpi_errno);
-: 1070: }
|
1667693: 1071: if (comm_ptr->comm_kind == MPID_INTERCOMM) {
7568: 1072: mpi_errno = MPID_VCRT_Release(
-: 1073: comm_ptr->local_vcrt, isDisconnect);
7568: 1074: if (mpi_errno != MPI_SUCCESS) {
|
#####: 1075: MPIU_ERR_POP(mpi_errno);
-: 1076: }
|
7568: 1077: if (comm_ptr->local_comm)
2331: 1078: MPIR_Comm_release(comm_ptr->local_comm, isDisconnect );
-: 1079: }
-: 1080:
-: 1081: /* Free the local and remote groups, if they exist */
1667693: 1082: if (comm_ptr->local_group)
8899: 1083: MPIR_Group_release(comm_ptr->local_group);
1667693: 1084: if (comm_ptr->remote_group)
4252: 1085: MPIR_Group_release(comm_ptr->remote_group);
-: 1086:
-: 1087: /* free the intra/inter-node communicators, if they exist */
1667693: 1088: if (comm_ptr->node_comm)
654594: 1089: MPIR_Comm_release(comm_ptr->node_comm, isDisconnect);
1667693: 1090: if (comm_ptr->node_roots_comm)
308989: 1091: MPIR_Comm_release(comm_ptr->node_roots_comm, isDisconnect);
1667693: 1092: if (comm_ptr->intranode_table != NULL)
692105: 1093: MPIU_Free(comm_ptr->intranode_table);
1667693: 1094: if (comm_ptr->internode_table != NULL)
692105: 1095: MPIU_Free(comm_ptr->internode_table);
-: 1096:
-: 1097: /* Free the context value. This should come after freeing the
-: 1098: * intra/inter-node communicators since those free calls won't
-: 1099: * release this context ID and releasing this before then could lead
-: 1100: * to races once we make threading finer grained. */
-: 1101: /* This must be the recvcontext_id (i.e. not the (send)context_id)
-: 1102: * because in the case of intercommunicators the send context ID is
-: 1103: * allocated out of the remote group's bit vector, not ours. */
1667693: 1104: MPIR_Free_contextid( comm_ptr->recvcontext_id );
-: 1105:
-: 1106: /* We need to release the error handler */
1667693: 1107: if (comm_ptr->errhandler &&
-: 1108: ! (HANDLE_GET_KIND(comm_ptr->errhandler->handle) ==
-: 1109: HANDLE_KIND_BUILTIN) ) {
-: 1110: int errhInuse;
6010: 1111: MPIR_Errhandler_release_ref( comm_ptr->errhandler,&errhInuse);
6010: 1112: if (!errhInuse) {
4006: 1113: MPIU_Handle_obj_free( &MPID_Errhandler_mem,
-: 1114: comm_ptr->errhandler );
-: 1115: }
-: 1116: }
-: 1117:
-: 1118: /* Check for predefined communicators - these should not
-: 1119: be freed */
1667693: 1120: if (! (HANDLE_GET_KIND(comm_ptr->handle) == HANDLE_KIND_BUILTIN) )
1654581: 1121: MPIU_Handle_obj_free( &MPID_Comm_mem, comm_ptr );
-: 1122:
-: 1123: /* Remove from the list of active communicators if
-: 1124: we are supporting message-queue debugging. We make this
-: 1125: conditional on having debugger support since the
-: 1126: operation is not constant-time */
-: 1127: MPIR_COMML_FORGET( comm_ptr );
-: 1128: }
-: 1129: else {
-: 1130: /* If the user attribute free function returns an error,
-: 1131: then do not free the communicator */
2: 1132: MPIR_Comm_add_ref( comm_ptr );
-: 1133: }
-: 1134:
1667695: 1135: fn_exit:
|
-: 1136: MPID_MPI_FUNC_EXIT(MPID_STATE_COMM_DELETE);
|
1667695: 1137: return mpi_errno;
|
-: 1138: fn_fail:
-: 1139: goto fn_exit;
-: 1140:}
-: 1141:
-: 1142:/* Release a reference to a communicator. If there are no pending
-: 1143: references, delete the communicator and recover all storage and
-: 1144: context ids */
-: 1145:#undef FUNCNAME
-: 1146:#define FUNCNAME MPIR_Comm_release
-: 1147:#undef FCNAME
-: 1148:#define FCNAME "MPIR_Comm_release"
-: 1149:int MPIR_Comm_release(MPID_Comm * comm_ptr, int isDisconnect)
|
27236309: 1150:{
27236309: 1151: int mpi_errno = MPI_SUCCESS;
-: 1152: int in_use;
-: 1153: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_RELEASE);
-: 1154:
-: 1155: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_RELEASE);
-: 1156:
27236309: 1157: MPIR_Comm_release_ref(comm_ptr, &in_use);
27236309: 1158: if (!in_use) {
1654584: 1159: mpi_errno = comm_delete(comm_ptr, isDisconnect);
|
1654584: 1160: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 1161: }
-: 1162:
|
27236309: 1163: fn_exit:
|
-: 1164: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_RELEASE);
|
27236309: 1165: return mpi_errno;
|
-: 1166: fn_fail:
-: 1167: goto fn_exit;
-: 1168:}
-: 1169:
-: 1170:/* Release a reference to a communicator. If there are no pending
-: 1171: references, delete the communicator and recover all storage and
-: 1172: context ids. This version of the function always manipulates the reference
-: 1173: counts, even for predefined objects. */
-: 1174:#undef FUNCNAME
-: 1175:#define FUNCNAME MPIR_Comm_release_always
-: 1176:#undef FCNAME
-: 1177:#define FCNAME MPIU_QUOTE(FUNCNAME)
-: 1178:int MPIR_Comm_release_always(MPID_Comm *comm_ptr, int isDisconnect)
|
13122: 1179:{
13122: 1180: int mpi_errno = MPI_SUCCESS;
-: 1181: int in_use;
-: 1182: MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
-: 1183:
-: 1184: MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
-: 1185:
-: 1186: /* we want to short-circuit any optimization that avoids reference counting
-: 1187: * predefined communicators, such as MPI_COMM_WORLD or MPI_COMM_SELF. */
13122: 1188: MPIU_Object_release_ref_always(comm_ptr, &in_use);
13122: 1189: if (!in_use) {
13111: 1190: mpi_errno = comm_delete(comm_ptr, isDisconnect);
|
13111: 1191: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 1192: }
-: 1193:
|
13122: 1194: fn_exit:
|
-: 1195: MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
|
13122: 1196: return mpi_errno;
|
-: 1197: fn_fail:
-: 1198: goto fn_exit;
-: 1199:}
-: 1200:
|