-: 0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/ch3/src/ch3u_recvq.c
-: 0:Graph:ch3u_recvq.gcno
-: 0:Data:ch3u_recvq.gcda
-: 0:Runs:4080
-: 0:Programs:1195
-: 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 "mpidimpl.h"
-: 8:
-: 9:/* These are needed for nemesis to know from where to expect a message */
-: 10:#ifndef MPIDI_POSTED_RECV_ENQUEUE_HOOK
-: 11:#define MPIDI_POSTED_RECV_ENQUEUE_HOOK(x)
-: 12:#endif
-: 13:#ifndef MPIDI_POSTED_RECV_DEQUEUE_HOOK
-: 14:#define MPIDI_POSTED_RECV_DEQUEUE_HOOK(x)
-: 15:#endif
-: 16:
-: 17:/* FIXME:
-: 18: * Recvq_lock/unlock removed because it is not needed for the SINGLE_CS
-: 19: * approach and we might want a different, non-lock-based approach in
-: 20: * a finer-grained thread-sync version. For example,
-: 21: * some routines can be implemented in a lock-free
-: 22: * fashion (because the user is required to guarantee non-conflicting
-: 23: * accesses, such as doing a probe and a receive that matches in different
-: 24: * threads).
-: 25: *
-: 26: * There are a lot of routines here. Do we really need them all?
-: 27: *
-: 28: * The search criteria can be implemented in a single 64 bit compare on
-: 29: * systems with efficient 64-bit operations. The rank and contextid can also
-: 30: * in many cases be combined into a single 32-bit word for the comparison
-: 31: * (in which case the message info should be stored in the queue in a
-: 32: * naturally aligned, 64-bit word.
-: 33: *
-: 34: */
-: 35:
-: 36:static MPID_Request * recvq_posted_head = 0;
-: 37:static MPID_Request * recvq_posted_tail = 0;
-: 38:static MPID_Request * recvq_unexpected_head = 0;
-: 39:static MPID_Request * recvq_unexpected_tail = 0;
-: 40:
-: 41:/* Export the location of the queue heads if debugger support is enabled.
-: 42: * This allows the queue code to rely on the local variables for the
-: 43: * queue heads while also exporting those variables to the debugger.
-: 44: * See src/mpi/debugger/dll_mpich2.c for how this is used to
-: 45: * access the message queues.
-: 46: */
-: 47:#ifdef HAVE_DEBUGGER_SUPPORT
-: 48:MPID_Request ** const MPID_Recvq_posted_head_ptr = &recvq_posted_head;
-: 49:MPID_Request ** const MPID_Recvq_unexpected_head_ptr = &recvq_unexpected_head;
-: 50:#endif
-: 51:
-: 52:/* If the MPIDI_Message_match structure fits into a pointer size, we
-: 53: * can directly work on it */
-: 54:/* MATCH_WITH_NO_MASK compares the match values without masking
-: 55: * them. This is useful for the case where there are no ANY_TAG or
-: 56: * ANY_SOURCE wild cards. */
-: 57:#define MATCH_WITH_NO_MASK(match1, match2) \
-: 58: ((sizeof(MPIDI_Message_match) == SIZEOF_VOID_P && 0) ? ((match1).whole == (match2).whole) : \
-: 59: (((match1).parts.rank == (match2).parts.rank) && \
-: 60: ((match1).parts.tag == (match2).parts.tag) && \
-: 61: ((match1).parts.context_id == (match2).parts.context_id)))
-: 62:
-: 63:/* MATCH_WITH_LEFT_MASK compares the match values after masking only
-: 64: * the left field. This is useful for the case where the right match
-: 65: * is a part of the unexpected queue and has no ANY_TAG or ANY_SOURCE
-: 66: * wild cards, but the left match might have them. */
-: 67:#define MATCH_WITH_LEFT_MASK(match1, match2, mask) \
-: 68: ((sizeof(MPIDI_Message_match) == SIZEOF_VOID_P && 0) ? (((match1).whole & (mask).whole) == (match2).whole) : \
-: 69: ((((match1).parts.rank & (mask).parts.rank) == (match2).parts.rank) && \
-: 70: (((match1).parts.tag & (mask).parts.tag) == (match2).parts.tag) && \
-: 71: ((match1).parts.context_id == (match2).parts.context_id)))
-: 72:
-: 73:/* This is the most general case where both matches have to be
-: 74: * masked. Both matches are masked with the same value. There doesn't
-: 75: * seem to be a need for two different masks at this time. */
-: 76:#define MATCH_WITH_LEFT_RIGHT_MASK(match1, match2, mask) \
-: 77: ((sizeof(MPIDI_Message_match) == SIZEOF_VOID_P && 0) ? (((match1).whole & (mask).whole) == ((match2).whole & (mask).whole)) : \
-: 78: ((((match1).parts.rank & (mask).parts.rank) == ((match2).parts.rank & (mask).parts.rank)) && \
-: 79: (((match1).parts.tag & (mask).parts.tag) == ((match2).parts.tag & (mask).parts.tag)) && \
-: 80: ((match1).parts.context_id == (match2).parts.context_id)))
-: 81:
-: 82:
-: 83:/* FIXME: If this routine is only used by probe/iprobe, then we don't need
-: 84: to set the cancelled field in status (only set for nonblocking requests) */
-: 85:/*
-: 86: * MPIDI_CH3U_Recvq_FU()
-: 87: *
-: 88: * Search for a matching request in the unexpected receive queue. Return
-: 89: * true if one is found, false otherwise. If the status arguement is
-: 90: * not MPI_STATUS_IGNORE, return information about the request in that
-: 91: * parameter. This routine is used by mpid_probe and mpid_iprobe.
-: 92: *
-: 93: * Multithread - As this is a read-only routine, it need not
-: 94: * require an external critical section (careful organization of the
-: 95: * queue updates would not even require a critical section within this
-: 96: * routine). However, this routine is used both from within the progress
-: 97: * engine and from without it. To make that work with the current
-: 98: * design for MSGQUEUE and the brief-global mode, the critical section
-: 99: * is *outside* of this routine.
-: 100: *
-: 101: * This routine is used only in mpid_iprobe and mpid_probe
-: 102: *
-: 103: */
-: 104:#undef FUNCNAME
-: 105:#define FUNCNAME MPIDI_CH3U_Recvq_FU
-: 106:#undef FCNAME
-: 107:#define FCNAME MPIDI_QUOTE(FUNCNAME)
-: 108:int MPIDI_CH3U_Recvq_FU(int source, int tag, int context_id, MPI_Status *s)
7491014: 109:{
-: 110: MPID_Request * rreq;
7491014: 111: int found = 0;
-: 112: MPIDI_Message_match match, mask;
-: 113: MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_RECVQ_FU);
-: 114:
-: 115: MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_RECVQ_FU);
-: 116:
7491014: 117: rreq = recvq_unexpected_head;
-: 118:
7491014: 119: match.parts.context_id = context_id;
7491014: 120: match.parts.tag = tag;
7491014: 121: match.parts.rank = source;
-: 122:
7491014: 123: if (tag != MPI_ANY_TAG && source != MPI_ANY_SOURCE) {
14439694: 124: while (rreq != NULL) {
7212632: 125: if (MATCH_WITH_NO_MASK(rreq->dev.match, match))
1093: 126: break;
7211539: 127: rreq = rreq->dev.next;
-: 128: }
-: 129: }
-: 130: else {
262859: 131: mask.parts.context_id = mask.parts.rank = mask.parts.tag = ~0;
262859: 132: if (tag == MPI_ANY_TAG)
45762: 133: match.parts.tag = mask.parts.tag = 0;
262859: 134: if (source == MPI_ANY_SOURCE)
241165: 135: match.parts.rank = mask.parts.rank = 0;
-: 136:
415950: 137: while (rreq != NULL) {
154395: 138: if (MATCH_WITH_LEFT_MASK(rreq->dev.match, match, mask))
1304: 139: break;
153091: 140: rreq = rreq->dev.next;
-: 141: }
-: 142: }
-: 143:
-: 144: /* Save the information about the request before releasing the
-: 145: queue */
7491014: 146: if (rreq) {
2397: 147: if (s != MPI_STATUS_IGNORE) {
-: 148: /* Avoid setting "extra" fields like MPI_ERROR */
2383: 149: s->MPI_SOURCE = rreq->status.MPI_SOURCE;
2383: 150: s->MPI_TAG = rreq->status.MPI_TAG;
2383: 151: s->count = rreq->status.count;
2383: 152: s->cancelled = rreq->status.cancelled;
-: 153: }
2397: 154: found = 1;
-: 155: }
-: 156:
|
475: 226: return rreq;
-: 227:}
-: 228:
-: 229:
-: 230:/*
-: 231: * MPIDI_CH3U_Recvq_FDU_or_AEP()
-: 232: *
-: 233: * Atomically find a request in the unexpected queue and dequeue it, or
-: 234: * allocate a new request and enqueue it in the posted queue
-: 235: *
-: 236: * Multithread - This routine must be called from within a MSGQUEUE
-: 237: * critical section. If a request is allocated, it must not release
-: 238: * the MSGQUEUE until the request is completely valid, as another thread
-: 239: * may then find it and dequeue it.
-: 240: *
-: 241: * This routine is used in mpid_irecv and mpid_recv.
-: 242: *
-: 243: */
-: 244:#undef FUNCNAME
-: 245:#define FUNCNAME MPIDI_CH3U_Recvq_FDU_or_AEP
-: 246:#undef FCNAME
-: 247:#define FCNAME MPIDI_QUOTE(FUNCNAME)
-: 248:MPID_Request * MPIDI_CH3U_Recvq_FDU_or_AEP(int source, int tag,
-: 249: int context_id, MPID_Comm *comm, void *user_buf,
-: 250: int user_count, MPI_Datatype datatype, int * foundp)
11375436: 251:{
-: 252: int found;
-: 253: MPID_Request *rreq, *prev_rreq;
-: 254: MPIDI_Message_match match;
-: 255: MPIDI_Message_match mask;
-: 256: MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_RECVQ_FDU_OR_AEP);
-: 257:
-: 258: MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_RECVQ_FDU_OR_AEP);
-: 259:
-: 260: /* Optimize this loop for an empty unexpected receive queue */
11375436: 261: rreq = recvq_unexpected_head;
11375436: 262: if (rreq) {
3535472: 263: prev_rreq = NULL;
-: 264:
3535472: 265: match.parts.context_id = context_id;
3535472: 266: match.parts.tag = tag;
3535472: 267: match.parts.rank = source;
-: 268:
3535472: 269: if (tag != MPI_ANY_TAG && source != MPI_ANY_SOURCE) {
-: 270: do {
3498702: 271: if (MATCH_WITH_NO_MASK(rreq->dev.match, match)) {
2652071: 272: if (prev_rreq != NULL) {
86558: 273: prev_rreq->dev.next = rreq->dev.next;
-: 274: }
-: 275: else {
2565513: 276: recvq_unexpected_head = rreq->dev.next;
-: 277: }
-: 278:
2652071: 279: if (rreq->dev.next == NULL) {
2320349: 280: recvq_unexpected_tail = prev_rreq;
-: 281: }
-: 282:
2652071: 283: rreq->comm = comm;
2652071: 284: MPIR_Comm_add_ref(comm);
2652071: 285: rreq->dev.user_buf = user_buf;
2652071: 286: rreq->dev.user_count = user_count;
2652071: 287: rreq->dev.datatype = datatype;
2652071: 288: found = TRUE;
2652071: 289: goto lock_exit;
-: 290: }
846631: 291: prev_rreq = rreq;
846631: 292: rreq = rreq->dev.next;
846631: 293: } while (rreq);
-: 294: }
-: 295: else {
192908: 296: mask.parts.context_id = mask.parts.rank = mask.parts.tag = ~0;
192908: 297: if (tag == MPI_ANY_TAG)
157894: 298: match.parts.tag = mask.parts.tag = 0;
192908: 299: if (source == MPI_ANY_SOURCE)
84960: 300: match.parts.rank = mask.parts.rank = 0;
-: 301:
-: 302: do {
237747: 303: if (MATCH_WITH_LEFT_MASK(rreq->dev.match, match, mask)) {
152046: 304: if (prev_rreq != NULL) {
33913: 305: prev_rreq->dev.next = rreq->dev.next;
-: 306: }
-: 307: else {
118133: 308: recvq_unexpected_head = rreq->dev.next;
-: 309: }
152046: 310: if (rreq->dev.next == NULL) {
114070: 311: recvq_unexpected_tail = prev_rreq;
-: 312: }
152046: 313: rreq->comm = comm;
152046: 314: MPIR_Comm_add_ref(comm);
152046: 315: rreq->dev.user_buf = user_buf;
152046: 316: rreq->dev.user_count = user_count;
152046: 317: rreq->dev.datatype = datatype;
152046: 318: found = TRUE;
152046: 319: goto lock_exit;
-: 320: }
85701: 321: prev_rreq = rreq;
85701: 322: rreq = rreq->dev.next;
85701: 323: } while (rreq);
-: 324: }
-: 325: }
-: 326:
-: 327: /* A matching request was not found in the unexpected queue, so we
-: 328: need to allocate a new request and add it to the posted queue */
-: 329: {
8571319: 330: int mpi_errno=0;
8571319: 331: MPIDI_Request_create_rreq( rreq, mpi_errno,
-: 332: found = FALSE;goto lock_exit );
8571319: 333: rreq->dev.match.parts.tag = tag;
8571319: 334: rreq->dev.match.parts.rank = source;
8571319: 335: rreq->dev.match.parts.context_id = context_id;
-: 336:
-: 337: /* Added a mask for faster search on 64-bit capable
-: 338: * platforms */
8571319: 339: rreq->dev.mask.parts.context_id = ~0;
8571319: 340: if (rreq->dev.match.parts.rank == MPI_ANY_SOURCE)
114316: 341: rreq->dev.mask.parts.rank = 0;
-: 342: else
8457003: 343: rreq->dev.mask.parts.rank = ~0;
8571319: 344: if (rreq->dev.match.parts.tag == MPI_ANY_TAG)
242584: 345: rreq->dev.mask.parts.tag = 0;
-: 346: else
8328735: 347: rreq->dev.mask.parts.tag = ~0;
-: 348:
8571319: 349: rreq->comm = comm;
8571319: 350: MPIR_Comm_add_ref(comm);
8571319: 351: rreq->dev.user_buf = user_buf;
8571319: 352: rreq->dev.user_count = user_count;
8571319: 353: rreq->dev.datatype = datatype;
8571319: 354: rreq->dev.next = NULL;
8571319: 355: if (recvq_posted_tail != NULL) {
186803: 356: recvq_posted_tail->dev.next = rreq;
-: 357: }
-: 358: else {
8384516: 359: recvq_posted_head = rreq;
-: 360: }
8571319: 361: recvq_posted_tail = rreq;
-: 362: /* This is for nemesis to know from where to expect a message */
8571319: 363: MPIDI_POSTED_RECV_ENQUEUE_HOOK (rreq);
-: 364: }
-: 365:
8571319: 366: found = FALSE;
-: 367:
11375436: 368: lock_exit:
-: 369:
11375436: 370: *foundp = found;
-: 371:
|
2292: 427: return found;
-: 428:}
-: 429:
-: 430:/*
-: 431: * MPIDI_CH3U_Recvq_FDP_or_AEU()
-: 432: *
-: 433: * Locate a request in the posted queue and dequeue it, or allocate a new
-: 434: * request and enqueue it in the unexpected queue
-: 435: *
-: 436: * Multithread - This routine must be called from within a MSGQUEUE
-: 437: * critical section. If a request is allocated, it must not release
-: 438: * the MSGQUEUE until the request is completely valid, as another thread
-: 439: * may then find it and dequeue it.
-: 440: *
-: 441: * This routine is used in ch3u_eager, ch3u_eagersync, ch3u_handle_recv_pkt,
-: 442: * ch3u_rndv, and mpidi_isend_self. Routines within the progress engine
-: 443: * will need to be careful to avoid nested critical sections.
-: 444: *
-: 445: * FIXME: Currently, the routines called from within the progress engine
-: 446: * do not use the MSGQUEUE CS, because in the brief-global mode, that
-: 447: * simply uses the global_mutex .
-: 448: */
-: 449:#undef FUNCNAME
-: 450:#define FUNCNAME MPIDI_CH3U_Recvq_FDP_or_AEU
-: 451:#undef FCNAME
-: 452:#define FCNAME MPIDI_QUOTE(FUNCNAME)
-: 453:MPID_Request * MPIDI_CH3U_Recvq_FDP_or_AEU(MPIDI_Message_match * match,
-: 454: int * foundp)
11373628: 455:{
-: 456: int found;
-: 457: MPID_Request * rreq;
-: 458: MPID_Request * prev_rreq;
-: 459: MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_RECVQ_FDP_OR_AEU);
-: 460:
-: 461: MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_RECVQ_FDP_OR_AEU);
-: 462:
11373628: 463: prev_rreq = NULL;
-: 464:
11373628: 465: rreq = recvq_posted_head;
-: 466:
24042447: 467: while (rreq != NULL) {
9864234: 468: if (MATCH_WITH_LEFT_RIGHT_MASK(rreq->dev.match, *match, rreq->dev.mask)) {
8569043: 469: if (prev_rreq != NULL) {
160823: 470: prev_rreq->dev.next = rreq->dev.next;
-: 471: }
-: 472: else {
8408220: 473: recvq_posted_head = rreq->dev.next;
-: 474: }
8569043: 475: if (rreq->dev.next == NULL) {
8540988: 476: recvq_posted_tail = prev_rreq;
-: 477: }
8569043: 478: found = TRUE;
-: 479: /* This is for the channel to know from where to expect a
-: 480: * message */
8569043: 481: MPIDI_POSTED_RECV_DEQUEUE_HOOK (rreq);
8569043: 482: goto lock_exit;
-: 483: }
1295191: 484: prev_rreq = rreq;
1295191: 485: rreq = rreq->dev.next;
-: 486: }
-: 487:
-: 488: /* A matching request was not found in the posted queue, so we
-: 489: need to allocate a new request and add it to the unexpected queue */
-: 490: {
2804585: 491: int mpi_errno=0;
2804585: 492: MPIDI_Request_create_rreq( rreq, mpi_errno,
-: 493: found=FALSE;goto lock_exit );
2804585: 494: rreq->dev.match = *match;
2804585: 495: rreq->dev.next = NULL;
2804585: 496: if (recvq_unexpected_tail != NULL) {
474540: 497: recvq_unexpected_tail->dev.next = rreq;
-: 498: }
-: 499: else {
2330045: 500: recvq_unexpected_head = rreq;
-: 501: }
2804585: 502: recvq_unexpected_tail = rreq;
-: 503: }
-: 504:
2804585: 505: found = FALSE;
-: 506:
11373628: 507: lock_exit:
-: 508:
11373628: 509: *foundp = found;
-: 510:
|
-: 515:/* --BEGIN ERROR HANDLING-- */
-: 516:/* pretty prints tag, returns out for calling convenience */
-: 517:static char *tag_val_to_str(int tag, char *out, int max)
#####: 518:{
#####: 519: if (tag == MPI_ANY_TAG) {
#####: 520: MPIU_Strncpy(out, "MPI_ANY_TAG", max);
-: 521: }
-: 522: else {
#####: 523: MPIU_Snprintf(out, max, "%d", tag);
-: 524: }
#####: 525: return out;
-: 526:}
-: 527:
-: 528:/* pretty prints rank, returns out for calling convenience */
-: 529:static char *rank_val_to_str(int rank, char *out, int max)
#####: 530:{
#####: 531: if (rank == MPI_ANY_SOURCE) {
#####: 532: MPIU_Strncpy(out, "MPI_ANY_SOURCE", max);
-: 533: }
-: 534: else {
#####: 535: MPIU_Snprintf(out, max, "%d", rank);
-: 536: }
#####: 537: return out;
-: 538:}
-: 539:
-: 540:/* satisfy the compiler */
-: 541:void MPIDI_CH3U_Dbg_print_recvq(FILE *stream);
-: 542:
-: 543:/* This function can be called by a debugger to dump the recvq state to the
-: 544: * given stream. */
-: 545:#undef FUNCNAME
-: 546:#define FUNCNAME MPIDI_CH3U_Dbg_print_recvq
-: 547:#undef FCNAME
-: 548:#define FCNAME MPIDI_QUOTE(FUNCNAME)
-: 549:void MPIDI_CH3U_Dbg_print_recvq(FILE *stream)
#####: 550:{
-: 551: MPID_Request * rreq;
-: 552: int i;
-: 553: char tag_buf[128];
-: 554: char rank_buf[128];
-: 555:
#####: 556: fprintf(stream, "========================================\n");
#####: 557: fprintf(stream, "MPI_COMM_WORLD ctx=%#x rank=%d\n", MPIR_Process.comm_world->context_id, MPIR_Process.comm_world->rank);
#####: 558: fprintf(stream, "MPI_COMM_SELF ctx=%#x\n", MPIR_Process.comm_self->context_id);
#####: 559: if (MPIR_Process.comm_parent) {
#####: 560: fprintf(stream, "MPI_COMM_PARENT ctx=%#x recvctx=%#x\n",
-: 561: MPIR_Process.comm_self->context_id,
-: 562: MPIR_Process.comm_parent->recvcontext_id);
-: 563: }
-: 564: else {
#####: 565: fprintf(stream, "MPI_COMM_PARENT (NULL)\n");
-: 566: }
-: 567:
#####: 568: fprintf(stream, "CH3 Posted RecvQ:\n");
#####: 569: rreq = recvq_posted_head;
#####: 570: i = 0;
#####: 571: while (rreq != NULL) {
#####: 572: fprintf(stream, "..[%d] rreq=%p ctx=%#x rank=%s tag=%s\n", i, rreq,
-: 573: rreq->dev.match.parts.context_id,
-: 574: rank_val_to_str(rreq->dev.match.parts.rank, rank_buf, sizeof(rank_buf)),
-: 575: tag_val_to_str(rreq->dev.match.parts.tag, tag_buf, sizeof(tag_buf)));
#####: 576: ++i;
#####: 577: rreq = rreq->dev.next;
-: 578: }
-: 579:
#####: 580: fprintf(stream, "CH3 Unexpected RecvQ:\n");
#####: 581: rreq = recvq_unexpected_head;
#####: 582: i = 0;
#####: 583: while (rreq != NULL) {
#####: 584: fprintf(stream, "..[%d] rreq=%p ctx=%#x rank=%s tag=%s\n", i, rreq,
-: 585: rreq->dev.match.parts.context_id,
-: 586: rank_val_to_str(rreq->dev.match.parts.rank, rank_buf, sizeof(rank_buf)),
-: 587: tag_val_to_str(rreq->dev.match.parts.tag, tag_buf, sizeof(tag_buf)));
#####: 588: fprintf(stream, ".. status.src=%s status.tag=%s\n",
-: 589: rank_val_to_str(rreq->status.MPI_SOURCE, rank_buf, sizeof(rank_buf)),
-: 590: tag_val_to_str(rreq->status.MPI_TAG, tag_buf, sizeof(tag_buf)));
#####: 591: ++i;
#####: 592: rreq = rreq->dev.next;
-: 593: }
#####: 594: fprintf(stream, "========================================\n");
#####: 595:}
-: 596:/* --END ERROR HANDLING-- */
-: 597:
-: 598:/* returns the number of elements in the unexpected queue */
-: 599:#undef FUNCNAME
-: 600:#define FUNCNAME MPIDI_CH3U_Recvq_count_unexp
-: 601:#undef FCNAME
-: 602:#define FCNAME MPIDI_QUOTE(FUNCNAME)
-: 603:int MPIDI_CH3U_Recvq_count_unexp(void)
|