Blame src/mpi/debugger/dbginit.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2001 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
#include "mpiimpl.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* style:PMPIuse:PMPI_Get_processor_name:2 sig:0 */
Packit Service c5cf8c
/* style:PMPIuse:PMPI_Recv:2 sig:0 */
Packit Service c5cf8c
/* style:PMPIuse:PMPI_Ssend:2 sig:0 */
Packit Service c5cf8c
/* style: allow:printf:1 sig:0 */
Packit Service c5cf8c
Packit Service c5cf8c
/* For getpid */
Packit Service c5cf8c
#ifdef HAVE_UNISTD_H
Packit Service c5cf8c
#include <unistd.h>
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
=== BEGIN_MPI_T_CVAR_INFO_BLOCK ===
Packit Service c5cf8c
Packit Service c5cf8c
cvars:
Packit Service c5cf8c
    - name        : MPIR_CVAR_PROCTABLE_SIZE
Packit Service c5cf8c
      category    : DEBUGGER
Packit Service c5cf8c
      type        : int
Packit Service c5cf8c
      default     : 64
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : >-
Packit Service c5cf8c
        Size of the "MPIR" debugger interface proctable (process table).
Packit Service c5cf8c
Packit Service c5cf8c
    - name        : MPIR_CVAR_PROCTABLE_PRINT
Packit Service c5cf8c
      category    : DEBUGGER
Packit Service c5cf8c
      type        : boolean
Packit Service c5cf8c
      default     : false
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : >-
Packit Service c5cf8c
        If true, dump the proctable entries at MPII_Wait_for_debugger-time.
Packit Service c5cf8c
Packit Service c5cf8c
=== END_MPI_T_CVAR_INFO_BLOCK ===
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* There are two versions of the debugger startup:
Packit Service c5cf8c
   1. The debugger starts mpiexec - then mpiexec provides the MPIR_proctable
Packit Service c5cf8c
      information
Packit Service c5cf8c
   2. The debugger attaches to an MPI process which contains the
Packit Service c5cf8c
      MPIR_proctable and related variables
Packit Service c5cf8c
Packit Service c5cf8c
   This file is intended to provide both as an option.  The macros that
Packit Service c5cf8c
   control the code for these are
Packit Service c5cf8c
Packit Service c5cf8c
   MPICH_STARTER_MPIEXEC
Packit Service c5cf8c
   MPICH_STARTER_RANK0
Packit Service c5cf8c
 */
Packit Service c5cf8c
#define MPICH_STARTER_MPIEXEC
Packit Service c5cf8c
/* #define MPICH_STARTER_RANK0 */
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPICH_STARTER_RANK0
Packit Service c5cf8c
#define MPIU_PROCTABLE_NEEDED 1
Packit Service c5cf8c
#define MPIU_BREAKPOINT_NEEDED 1
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/* If MPIR_Breakpoint is not defined and called, the message queue information
Packit Service c5cf8c
   will not be properly displayed by the debugger. */
Packit Service c5cf8c
/* I believe this was caused by a poor choice in the dll_mpich.c file */
Packit Service c5cf8c
/* #define MPIU_BREAKPOINT_NEEDED 1 */
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPIU_BREAKPOINT_NEEDED
Packit Service c5cf8c
/* We prototype this routine here because it is only used in this file.  It
Packit Service c5cf8c
   is not static so that the debugger can find it (the debugger will set a
Packit Service c5cf8c
   breakpoint at this routine */
Packit Service c5cf8c
void *MPIR_Breakpoint(void);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * This file contains information and routines used to simplify the interface
Packit Service c5cf8c
 * to a debugger.  This follows the description in "A Standard Interface
Packit Service c5cf8c
 * for Debugger Access to Message Queue Information in MPI", by Jim Cownie
Packit Service c5cf8c
 * and William Gropp.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This file should be compiled with debug information (-g)
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * In addition to the discussion in the paper "A Standard Interface for Debugger
Packit Service c5cf8c
 * Access to Message Queue Inforation in MPI" and the more recent paper "An
Packit Service c5cf8c
 * Interface to Support the Identification of Dynamic {MPI} 2 Processes for
Packit Service c5cf8c
 * Scalable Parallel Debugging", there are a few features that have become
Packit Service c5cf8c
 * defacto standard.  These include the "proctable" (a relic of the way
Packit Service c5cf8c
 * that p4 represented processes that was used in the ch_p4 device in
Packit Service c5cf8c
 * MPICH1), a debugger state (has MPI started or exited), and a routine that
Packit Service c5cf8c
 * has the sole purpose of serving as a break point for a debugger.
Packit Service c5cf8c
 * Specifically, these extensions are:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *  void * MPIR_Breakpoint(void)
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This routine should be called at any point where control should be
Packit Service c5cf8c
 * offered to the debugger.  Typical spots are in MPI_Init/MPI_Init_thread
Packit Service c5cf8c
 * after initialization is completed and in MPI_Abort before exiting.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * MPIR_Debugger_set_aborting(const char *msg)
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This routine should be called when MPI is exiting (either in finalize
Packit Service c5cf8c
 * or abort.  If a message is provided, it will call MPIR_Breakpoint.
Packit Service c5cf8c
 * This routine sets the variables MPIR_debug_state and MPIR_debug_abort_string.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * In MPICH1, the variables MPIR_debug_state, MPIR_debug_abort_string,
Packit Service c5cf8c
 * MPIR_being_debugged, and MPIR_debug_gate where exported globally.
Packit Service c5cf8c
 * In MPICH, while these are global variables (so that the debugger can
Packit Service c5cf8c
 * find them easily), they are not explicitly exported or referenced outside
Packit Service c5cf8c
 * of a few routines.  In particular, MPID_Abort uses MPIR_Debugger_set_aborting
Packit Service c5cf8c
 * instead of directly accessing these variables.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/* The following is used to tell a debugger the location of the shared
Packit Service c5cf8c
   library that the debugger can load in order to access information about
Packit Service c5cf8c
   the parallel program, such as message queues */
Packit Service c5cf8c
#ifdef HAVE_DEBUGGER_SUPPORT
Packit Service c5cf8c
#ifdef MPICH_INFODLL_LOC
Packit Service c5cf8c
char MPIR_dll_name[] = MPICH_INFODLL_LOC;
Packit Service c5cf8c
#endif
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * The following variables are used to interact with the debugger.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * MPIR_debug_state
Packit Service c5cf8c
 *    Values are 0 (before MPI_Init), 1 (after MPI_init), and 2 (Aborting).
Packit Service c5cf8c
 * MPIR_debug_gate
Packit Service c5cf8c
 *    The debugger will set this to 1 when the debugger attaches
Packit Service c5cf8c
 *    to the process to tell the process to proceed.
Packit Service c5cf8c
 * MPIR_being_debugged
Packit Service c5cf8c
 *    Set to 1 if the process is started or attached under the debugger
Packit Service c5cf8c
 * MPIR_debug_abort_string
Packit Service c5cf8c
 *    String that the debugger can display on an abort.
Packit Service c5cf8c
 */
Packit Service c5cf8c
volatile int MPIR_debug_state = 0;
Packit Service c5cf8c
volatile int MPIR_debug_gate = 0;
Packit Service c5cf8c
volatile int MPIR_being_debugged = 0;
Packit Service c5cf8c
const char *MPIR_debug_abort_string = 0;
Packit Service c5cf8c
Packit Service c5cf8c
/* Values for the debug_state, this seems to be all we need at the moment
Packit Service c5cf8c
 * but that may change...
Packit Service c5cf8c
 */
Packit Service c5cf8c
#define MPIR_DEBUG_SPAWNED   1
Packit Service c5cf8c
#define MPIR_DEBUG_ABORTING  2
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPIU_PROCTABLE_NEEDED
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * MPIR_PROCDESC is used to pass information to the debugger about
Packit Service c5cf8c
 * all of the processes.
Packit Service c5cf8c
 */
Packit Service c5cf8c
typedef struct {
Packit Service c5cf8c
    char *host_name;            /* Valid name for inet_addr */
Packit Service c5cf8c
    char *executable_name;      /* The name of the image */
Packit Service c5cf8c
    int pid;                    /* The process id */
Packit Service c5cf8c
} MPIR_PROCDESC;
Packit Service c5cf8c
MPIR_PROCDESC *MPIR_proctable = 0;
Packit Service c5cf8c
int MPIR_proctable_size = 1;
Packit Service c5cf8c
static int MPIR_FreeProctable(void *);
Packit Service c5cf8c
Packit Service c5cf8c
#endif /* MPIR_proctable definition */
Packit Service c5cf8c
Packit Service c5cf8c
/* Other symbols:
Packit Service c5cf8c
 * MPIR_i_am_starter - Indicates that this process is not an MPI process
Packit Service c5cf8c
 *   (for example, the forker mpiexec?)
Packit Service c5cf8c
 * MPIR_acquired_pre_main -
Packit Service c5cf8c
 * MPIR_partial_attach_ok -
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* Forward references */
Packit Service c5cf8c
static void SendqInit(void);
Packit Service c5cf8c
static int SendqFreePool(void *);
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * If MPICH is built with the --enable-debugger option, MPI_Init and
Packit Service c5cf8c
 * MPI_Init_thread will call MPII_Wait_for_debugger.  This ensures both that
Packit Service c5cf8c
 * the debugger can gather information on the MPI job before the MPI_Init
Packit Service c5cf8c
 * returns to the user and that the necessary symbols for providing
Packit Service c5cf8c
 * information such as message queues is available.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * In addition, the environment variable MPIEXEC_DEBUG, if set, will cause
Packit Service c5cf8c
 * all MPI processes to wait in this routine until the variable
Packit Service c5cf8c
 * MPIR_debug_gate is set to 1.
Packit Service c5cf8c
 */
Packit Service c5cf8c
void MPII_Wait_for_debugger(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
#ifdef MPIU_PROCTABLE_NEEDED
Packit Service c5cf8c
    int rank = MPIR_Process.comm_world->rank;
Packit Service c5cf8c
    int size = MPIR_Process.comm_world->local_size;
Packit Service c5cf8c
    int i, maxsize;
Packit Service c5cf8c
Packit Service c5cf8c
    /* FIXME: In MPICH, the executables may not have the information
Packit Service c5cf8c
     * on the other processes; this is part of the Process Manager Interface
Packit Service c5cf8c
     * (PMI).  We need another way to provide this information to
Packit Service c5cf8c
     * a debugger */
Packit Service c5cf8c
    /* The process manager probably has all of this data - the MPI2
Packit Service c5cf8c
     * debugger interface API provides (at least originally) a way
Packit Service c5cf8c
     * to access this. */
Packit Service c5cf8c
    /* Also, to avoid scaling problems, we only populate the first 64
Packit Service c5cf8c
     * entries (default) */
Packit Service c5cf8c
    maxsize = MPIR_CVAR_PROCTABLE_SIZE;
Packit Service c5cf8c
    if (maxsize > size)
Packit Service c5cf8c
        maxsize = size;
Packit Service c5cf8c
Packit Service c5cf8c
    if (rank == 0) {
Packit Service c5cf8c
        char hostname[MPI_MAX_PROCESSOR_NAME + 1];
Packit Service c5cf8c
        int hostlen;
Packit Service c5cf8c
        int val;
Packit Service c5cf8c
Packit Service c5cf8c
        MPIR_proctable = (MPIR_PROCDESC *) MPL_malloc(size * sizeof(MPIR_PROCDESC), MPL_MEM_DEBUG);
Packit Service c5cf8c
        for (i = 0; i < size; i++) {
Packit Service c5cf8c
            /* Initialize the proctable */
Packit Service c5cf8c
            MPIR_proctable[i].host_name = 0;
Packit Service c5cf8c
            MPIR_proctable[i].executable_name = 0;
Packit Service c5cf8c
            MPIR_proctable[i].pid = -1;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        PMPI_Get_processor_name(hostname, &hostlen);
Packit Service c5cf8c
        MPIR_proctable[0].host_name = (char *) MPL_strdup(hostname);
Packit Service c5cf8c
        MPIR_proctable[0].executable_name = 0;
Packit Service c5cf8c
        MPIR_proctable[0].pid = getpid();
Packit Service c5cf8c
Packit Service c5cf8c
        for (i = 1; i < maxsize; i++) {
Packit Service c5cf8c
            int msg[2];
Packit Service c5cf8c
            PMPI_Recv(msg, 2, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
Packit Service c5cf8c
            MPIR_proctable[i].pid = msg[1];
Packit Service c5cf8c
            MPIR_proctable[i].host_name = (char *) MPL_malloc(msg[0] + 1, MPL_MEM_DEBUG);
Packit Service c5cf8c
            PMPI_Recv(MPIR_proctable[i].host_name, msg[0] + 1, MPI_CHAR,
Packit Service c5cf8c
                      i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
Packit Service c5cf8c
            MPIR_proctable[i].host_name[msg[0]] = 0;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        MPIR_proctable_size = size;
Packit Service c5cf8c
        /* Debugging hook */
Packit Service c5cf8c
        if (MPIR_CVAR_PROCTABLE_PRINT) {
Packit Service c5cf8c
            for (i = 0; i < maxsize; i++) {
Packit Service c5cf8c
                printf("PT[%d].pid = %d, .host_name = %s\n",
Packit Service c5cf8c
                       i, MPIR_proctable[i].pid, MPIR_proctable[i].host_name);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            fflush(stdout);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPIR_Add_finalize(MPIR_FreeProctable, MPIR_proctable, 0);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        char hostname[MPI_MAX_PROCESSOR_NAME + 1];
Packit Service c5cf8c
        int hostlen;
Packit Service c5cf8c
        int mypid = getpid();
Packit Service c5cf8c
        int msg[2];
Packit Service c5cf8c
        if (rank < maxsize) {
Packit Service c5cf8c
            PMPI_Get_processor_name(hostname, &hostlen);
Packit Service c5cf8c
            msg[0] = hostlen;
Packit Service c5cf8c
            msg[1] = mypid;
Packit Service c5cf8c
Packit Service c5cf8c
            /* Deliver to the root process the proctable information */
Packit Service c5cf8c
            PMPI_Ssend(msg, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
            PMPI_Ssend(hostname, hostlen, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* MPIU_PROCTABLE_NEEDED */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Put the breakpoint after setting up the proctable */
Packit Service c5cf8c
    MPIR_debug_state = MPIR_DEBUG_SPAWNED;
Packit Service c5cf8c
#ifdef MPIU_BREAKPOINT_NEEDED
Packit Service c5cf8c
    (void) MPIR_Breakpoint();
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    /* After we exit the MPIR_Breakpoint routine, the debugger may have
Packit Service c5cf8c
     * set variables such as MPIR_being_debugged */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize the sendq support */
Packit Service c5cf8c
    SendqInit();
Packit Service c5cf8c
Packit Service c5cf8c
    if (getenv("MPIEXEC_DEBUG")) {
Packit Service c5cf8c
        while (!MPIR_debug_gate);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPIU_BREAKPOINT_NEEDED
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * This routine is a special dummy routine that is used to provide a
Packit Service c5cf8c
 * location for a debugger to set a breakpoint on, allowing a user (and the
Packit Service c5cf8c
 * debugger) to attach to MPI processes after MPI_Init succeeds but before
Packit Service c5cf8c
 * MPI_Init returns control to the user. It may also be called when MPI aborts,
Packit Service c5cf8c
 * also to allow a debugger to regain control of an application.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This routine can also initialize any datastructures that are required
Packit Service c5cf8c
 *
Packit Service c5cf8c
 */
Packit Service c5cf8c
void *MPIR_Breakpoint(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPL_DBG_MSG(MPIR_DBG_OTHER, VERBOSE, "In MPIR_Breakpoint");
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Call this routine to signal to the debugger that the application is aborting.
Packit Service c5cf8c
 * If there is an abort message, call the MPIR_Breakpoint routine (which
Packit Service c5cf8c
 * allows a tool such as a debugger to gain control.
Packit Service c5cf8c
 */
Packit Service c5cf8c
void MPIR_Debugger_set_aborting(const char *msg)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_debug_abort_string = (char *) msg;
Packit Service c5cf8c
    MPIR_debug_state = MPIR_DEBUG_ABORTING;
Packit Service c5cf8c
#ifdef MPIU_BREAKPOINT_NEEDED
Packit Service c5cf8c
    if (msg)
Packit Service c5cf8c
        MPIR_Breakpoint();
Packit Service c5cf8c
#endif
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Manage the send queue.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * The send queue is needed only by the debugger.  The communication
Packit Service c5cf8c
 * device has a separate notion of send queue, which are the operations
Packit Service c5cf8c
 * that it needs to complete, independent of whether the user has called
Packit Service c5cf8c
 * MPI_Wait/Test/etc on the request.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This implementation uses a simple linked list of user-visible requests
Packit Service c5cf8c
 * (more specifically, requests created with MPI_Isend, MPI_Issend, or
Packit Service c5cf8c
 * MPI_Irsend).
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * FIXME: We should exploit this to allow Finalize to report on
Packit Service c5cf8c
 * send requests that were never completed.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/* We need to save the tag and rank since this information may not
Packit Service c5cf8c
   be included in the request.  Saving the context_id also simplifies
Packit Service c5cf8c
   matching these entries with a communicator */
Packit Service c5cf8c
typedef struct MPIR_Sendq {
Packit Service c5cf8c
    MPIR_Request *sreq;
Packit Service c5cf8c
    int tag, rank, context_id;
Packit Service c5cf8c
    struct MPIR_Sendq *next;
Packit Service c5cf8c
    struct MPIR_Sendq *prev;
Packit Service c5cf8c
} MPIR_Sendq;
Packit Service c5cf8c
Packit Service c5cf8c
MPIR_Sendq *MPIR_Sendq_head = 0;
Packit Service c5cf8c
/* Keep a pool of previous sendq elements to speed allocation of queue
Packit Service c5cf8c
   elements */
Packit Service c5cf8c
static MPIR_Sendq *pool = 0;
Packit Service c5cf8c
Packit Service c5cf8c
/* This routine is used to establish a queue of send requests to allow the
Packit Service c5cf8c
   debugger easier access to the active requests.  Some devices may be able
Packit Service c5cf8c
   to provide this information without requiring this separate queue. */
Packit Service c5cf8c
void MPII_Sendq_remember(MPIR_Request * req, int rank, int tag, int context_id)
Packit Service c5cf8c
{
Packit Service c5cf8c
#if defined HAVE_DEBUGGER_SUPPORT
Packit Service c5cf8c
    MPIR_Sendq *p;
Packit Service c5cf8c
Packit Service c5cf8c
/* TODO: We reuse the global lock for the per-vni granularity here instead of a
Packit Service c5cf8c
 * theoritically more scalable approach of creating a separate lock. Whether
Packit Service c5cf8c
 * this brief-global critical section would perturbate debugging is unknown;
Packit Service c5cf8c
 * investigation is needed before attempting to optimize this case. */
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, req->pobj_mutex);
Packit Service c5cf8c
    if (pool) {
Packit Service c5cf8c
        p = pool;
Packit Service c5cf8c
        pool = p->next;
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        p = (MPIR_Sendq *) MPL_malloc(sizeof(MPIR_Sendq), MPL_MEM_DEBUG);
Packit Service c5cf8c
        if (!p) {
Packit Service c5cf8c
            /* Just ignore it */
Packit Service c5cf8c
            if (MPIR_REQUEST_KIND__SEND == req->kind)
Packit Service c5cf8c
                req->u.send.dbg_next = NULL;
Packit Service c5cf8c
            else if (MPIR_REQUEST_KIND__PREQUEST_SEND == req->kind)
Packit Service c5cf8c
                req->u.persist.dbg_next = NULL;
Packit Service c5cf8c
            goto fn_exit;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    p->sreq = req;
Packit Service c5cf8c
    p->tag = tag;
Packit Service c5cf8c
    p->rank = rank;
Packit Service c5cf8c
    p->context_id = context_id;
Packit Service c5cf8c
    p->next = MPIR_Sendq_head;
Packit Service c5cf8c
    p->prev = NULL;
Packit Service c5cf8c
    MPIR_Sendq_head = p;
Packit Service c5cf8c
    if (p->next)
Packit Service c5cf8c
        p->next->prev = p;
Packit Service c5cf8c
    if (MPIR_REQUEST_KIND__SEND == req->kind)
Packit Service c5cf8c
        req->u.send.dbg_next = p;
Packit Service c5cf8c
    else if (MPIR_REQUEST_KIND__PREQUEST_SEND == req->kind)
Packit Service c5cf8c
        req->u.persist.dbg_next = p;
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, req->pobj_mutex);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
#endif /* HAVE_DEBUGGER_SUPPORT */
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void MPII_Sendq_forget(MPIR_Request * req)
Packit Service c5cf8c
{
Packit Service c5cf8c
#if defined HAVE_DEBUGGER_SUPPORT
Packit Service c5cf8c
    MPIR_Sendq *p, *prev;
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, req->pobj_mutex);
Packit Service c5cf8c
    if (MPIR_REQUEST_KIND__SEND == req->kind)
Packit Service c5cf8c
        p = req->u.send.dbg_next;
Packit Service c5cf8c
    else if (MPIR_REQUEST_KIND__PREQUEST_SEND == req->kind)
Packit Service c5cf8c
        p = req->u.persist.dbg_next;
Packit Service c5cf8c
    if (!p) {
Packit Service c5cf8c
        /* Just ignore it */
Packit Service c5cf8c
        MPID_THREAD_CS_EXIT(POBJ, req->pobj_mutex);
Packit Service c5cf8c
        MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
        return;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    prev = p->prev;
Packit Service c5cf8c
    if (prev != NULL)
Packit Service c5cf8c
        prev->next = p->next;
Packit Service c5cf8c
    else
Packit Service c5cf8c
        MPIR_Sendq_head = p->next;
Packit Service c5cf8c
    if (p->next != NULL)
Packit Service c5cf8c
        p->next->prev = prev;
Packit Service c5cf8c
    /* Return this element to the pool */
Packit Service c5cf8c
    p->next = pool;
Packit Service c5cf8c
    pool = p;
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, req->pobj_mutex);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
#endif /* HAVE_DEBUGGER_SUPPORT */
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static int SendqFreePool(void *d)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Sendq *p;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Free the pool */
Packit Service c5cf8c
    p = pool;
Packit Service c5cf8c
    while (p) {
Packit Service c5cf8c
        pool = p->next;
Packit Service c5cf8c
        MPL_free(p);
Packit Service c5cf8c
        p = pool;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* Free the list of pending sends */
Packit Service c5cf8c
    p = MPIR_Sendq_head;
Packit Service c5cf8c
    while (p) {
Packit Service c5cf8c
        MPIR_Sendq_head = p->next;
Packit Service c5cf8c
        MPL_free(p);
Packit Service c5cf8c
        p = MPIR_Sendq_head;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static void SendqInit(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
    MPIR_Sendq *p;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Preallocated a few send requests */
Packit Service c5cf8c
    for (i = 0; i < 10; i++) {
Packit Service c5cf8c
        p = (MPIR_Sendq *) MPL_malloc(sizeof(MPIR_Sendq), MPL_MEM_DEBUG);
Packit Service c5cf8c
        if (!p) {
Packit Service c5cf8c
            /* Just ignore it */
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        p->next = pool;
Packit Service c5cf8c
        pool = p;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Make sure the pool is deleted */
Packit Service c5cf8c
    MPIR_Add_finalize(SendqFreePool, 0, 0);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Manage the known communicators */
Packit Service c5cf8c
/* Provide a list of all active communicators.  This is used only by the
Packit Service c5cf8c
   debugger message queue interface */
Packit Service c5cf8c
typedef struct MPIR_Comm_list {
Packit Service c5cf8c
    int sequence_number;        /* Used to detect changes in the list */
Packit Service c5cf8c
    MPIR_Comm *head;            /* Head of the list */
Packit Service c5cf8c
} MPIR_Comm_list;
Packit Service c5cf8c
Packit Service c5cf8c
MPIR_Comm_list MPIR_All_communicators = { 0, 0 };
Packit Service c5cf8c
Packit Service c5cf8c
void MPII_CommL_remember(MPIR_Comm * comm_ptr)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPL_DBG_MSG_P(MPIR_DBG_COMM, VERBOSE, "Adding communicator %p to remember list", comm_ptr);
Packit Service c5cf8c
    MPL_DBG_MSG_P(MPIR_DBG_COMM, VERBOSE,
Packit Service c5cf8c
                  "Remember list structure address is %p", &MPIR_All_communicators);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
Packit Service c5cf8c
    if (comm_ptr == MPIR_All_communicators.head) {
Packit Service c5cf8c
        MPL_internal_error_printf("Internal error: communicator is already on free list\n");
Packit Service c5cf8c
        return;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    comm_ptr->comm_next = MPIR_All_communicators.head;
Packit Service c5cf8c
    MPIR_All_communicators.head = comm_ptr;
Packit Service c5cf8c
    MPIR_All_communicators.sequence_number++;
Packit Service c5cf8c
    MPL_DBG_MSG_P(MPIR_DBG_COMM, VERBOSE, "master head is %p", MPIR_All_communicators.head);
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void MPII_CommL_forget(MPIR_Comm * comm_ptr)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Comm *p, *prev;
Packit Service c5cf8c
Packit Service c5cf8c
    MPL_DBG_MSG_P(MPIR_DBG_COMM, VERBOSE,
Packit Service c5cf8c
                  "Forgetting communicator %p from remember list", comm_ptr);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
Packit Service c5cf8c
    p = MPIR_All_communicators.head;
Packit Service c5cf8c
    prev = 0;
Packit Service c5cf8c
    while (p) {
Packit Service c5cf8c
        if (p == comm_ptr) {
Packit Service c5cf8c
            if (prev)
Packit Service c5cf8c
                prev->comm_next = p->comm_next;
Packit Service c5cf8c
            else
Packit Service c5cf8c
                MPIR_All_communicators.head = p->comm_next;
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        if (p == p->comm_next) {
Packit Service c5cf8c
            MPL_internal_error_printf("Mangled pointers to communicators - next is itself for %p\n",
Packit Service c5cf8c
                                      p);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        prev = p;
Packit Service c5cf8c
        p = p->comm_next;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* Record a change to the list */
Packit Service c5cf8c
    MPIR_All_communicators.sequence_number++;
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPIU_PROCTABLE_NEEDED
Packit Service c5cf8c
/* This routine is the finalize callback used to free the procable */
Packit Service c5cf8c
static int MPIR_FreeProctable(void *ptable)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
    MPIR_PROCDESC *proctable = (MPIR_PROCDESC *) ptable;
Packit Service c5cf8c
    for (i = 0; i < MPIR_proctable_size; i++) {
Packit Service c5cf8c
        if (proctable[i].host_name) {
Packit Service c5cf8c
            MPL_free(proctable[i].host_name);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPL_free(proctable);
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
#endif /* MPIU_PROCTABLE_NEEDED */
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * There is an MPI-2 process table interface which has been defined; this
Packit Service c5cf8c
 * provides a more scalable, distributed description of the process table.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *
Packit Service c5cf8c
 */