|
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 |
*/
|