📄 dbginit.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */#include "mpiimpl.h"/* We prototype this routine here because it is only used in this file. It is not static so that the debugger can find it (the debugger will set a breakpoint at this routine */void *MPIR_Breakpoint(void);/* * This file contains information and routines used to simplify the interface * to a debugger. This follows the description in "A Standard Interface * for Debugger Access to Message Queue Information in MPI", by Jim Cownie * and William Gropp. * * This file should be compiled with debug information (-g) *//* The following is used to tell a debugger the location of the shared library that the debugger can load in order to access information about the parallel program, such as message queues */#ifdef HAVE_DEBUGGER_SUPPORT#ifdef MPICH_INFODLL_LOCchar MPIR_dll_name[] = MPICH_INFODLL_LOC;#endif#endif/* * The following variables are used to interact with the debugger. * * MPIR_debug_state * Values are 0 (before MPI_Init), 1 (after MPI_init), and 2 (Aborting). * MPIR_debug_gate * The debugger will set this to 1 when the debugger attaches * to the process to tell the process to proceed. * MPIR_being_debugged * Set to 1 if the process is started or attached under the debugger * MPIR_debug_abort_string * String that the debugger can display on an abort (?) */volatile int MPIR_debug_state = 0;volatile int MPIR_debug_gate = 0;volatile int MPIR_being_debugged = 0;char * MPIR_debug_abort_string = 0;/* Values for the debug_state, this seems to be all we need at the moment * but that may change... */#define MPIR_DEBUG_SPAWNED 1#define MPIR_DEBUG_ABORTING 2#if 0/* * MPIR_PROCDESC is used to pass information to the debugger about * all of the processes. */typedef struct { char *host_name; /* Valid name for inet_addr */ char *executable_name; /* The name of the image */ int pid; /* The process id */} MPIR_PROCDESC;MPIR_PROCDESC *MPIR_proctable = 0;int MPIR_proctable_size = 1;#endif/* Other symbols: * MPIR_i_am_starter - Indicates that this process is not an MPI process * (for example, the forker mpiexec?) * MPIR_acquired_pre_main - * MPIR_partial_attach_ok -*//* * If MPICH2 is built with the --enable-debugger option, MPI_Init and * MPI_Init_thread will call MPIR_WaitForDebugger. This ensures both that * the debugger can gather information on the MPI job before the MPI_Init * returns to the user and that the necessary symbols for providing * information such as message queues is available. * * In addition, the environment variable MPIEXEC_DEBUG, if set, will cause * all MPI processes to wait in this routine until the variable * MPIR_debug_gate is set to 1. */void MPIR_WaitForDebugger( void ){ int rank = MPIR_Process.comm_world->rank; int size = MPIR_Process.comm_world->local_size;#if 0 /* FIXME: In MPICH2, the executables may not have the information on the other processes; this is part of the Process Manager Interface (PMI). We need another way to provide this information to a debugger */ if (rank == 0) { MPIR_proctable = (MPIR_PROCDESC *)MPIU_Malloc( size * sizeof(MPIR_PROCDESC) ); /* Temporary to see if we can get totalview's attention */ MPIR_proctable[0].host_name = 0; MPIR_proctable[0].executable_name = 0; MPIR_proctable[0].pid = getpid(); MPIR_proctable_size = 1; } /* Put the breakpoint after setting up the proctable */ MPIR_debug_state = MPIR_DEBUG_SPAWNED; (void)MPIR_Breakpoint(); /* After we exit the MPIR_Breakpoint routine, the debugger may have set variables such as MPIR_being_debugged */ /* Check to see if we're not the master, * and wait for the debugger to attach if we're * a slave. The debugger will reset the debug_gate. * There is no code in the library which will do it ! * * THIS IS OLD CODE FROM MPICH1 FIXME */ if (MPIR_being_debugged && rank != 0) { while (MPIR_debug_gate == 0) { /* Wait to be attached to, select avoids * signaling and allows a smaller timeout than * sleep(1) */ struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 250000; select( 0, (void *)0, (void *)0, (void *)0, &timeout ); } }#endif if (getenv("MPIEXEC_DEBUG")) { while (!MPIR_debug_gate) ; }}/* * This routine is a special dummy routine that is used to provide a * location for a debugger to set a breakpoint on, allowing a user (and the * debugger) to attach to MPI processes after MPI_Init succeeds but before * MPI_Init returns control to the user. * * This routine can also initialize any datastructures that are required * */void * MPIR_Breakpoint( void ){ return 0;}/* ------------------------------------------------------------------------- *//* * Manage the send queue. * * The send queue is needed only by the debugger. The communication * device has a separate notion of send queue, which are the operations * that it needs to complete, independent of whether the user has called * MPI_Wait/Test/etc on the request. * * This implementation uses a simple linked list of user-visible requests * (more specifically, requests created with MPI_Isend, MPI_Issend, or * MPI_Irsend). * * FIXME: We need to add MPI_Ibsend and the persistent send requests to * the known send requests. * FIXME: We need to register a Finalize call back to free memory. * FIXME: We should exploit this to allow Finalize to report on * send requests that were never completed. *//* We need to save the tag and rank since this information may not be included in the request. Saving the context_id also simplifies matching these entries with a communicator */typedef struct MPIR_Sendq { MPID_Request *sreq; int tag, rank, context_id; struct MPIR_Sendq *next;} MPIR_Sendq;MPIR_Sendq *MPIR_Sendq_head = 0;/* Keep a pool of previous sendq elements to speed allocation of queue elements */static MPIR_Sendq *pool = 0;void MPIR_Sendq_remember( MPID_Request *req, int rank, int tag, int context_id ){ MPIR_Sendq *p; if (pool) { p = pool; pool = p->next; } else { p = (MPIR_Sendq *)MPIU_Malloc( sizeof(MPIR_Sendq) ); if (!p) { /* Just ignore it */ return; } } p->sreq = req; p->tag = tag; p->rank = rank; p->context_id = context_id; p->next = MPIR_Sendq_head; MPIR_Sendq_head = p;}void MPIR_Sendq_forget( MPID_Request *req ){ MPIR_Sendq *p, *prev; p = MPIR_Sendq_head; prev = 0; /* FIXME: Make this thread-safe */ while (p) { if (p->sreq == req) { if (prev) prev->next = p->next; else MPIR_Sendq_head = p->next; /* Return this element to the pool */ p->next = pool; pool = p; break; } prev = p; p = p->next; } /* If we don't find the request, just ignore it */}/* Manage the known communicators *//* Provide a list of all active communicators. This is used only by the debugger message queue interface */typedef struct MPIR_Comm_list { int sequence_number; /* Used to detect changes in the list */ MPID_Comm *head; /* Head of the list */} MPIR_Comm_list;MPIR_Comm_list MPIR_All_communicators = { 0, 0 };void MPIR_CommL_remember( MPID_Comm *comm_ptr ){ MPIU_DBG_MSG_P(COMM,VERBOSE, "Adding communicator %p to remember list",comm_ptr); /* FIXME: (MT) Ensure thread-safe */ if (comm_ptr == MPIR_All_communicators.head) { MPIU_Internal_error_printf( "Internal error: communicator is already on free list\n" ); return; } comm_ptr->comm_next = MPIR_All_communicators.head; MPIR_All_communicators.head = comm_ptr; MPIR_All_communicators.sequence_number++;}void MPIR_CommL_forget( MPID_Comm *comm_ptr ){ MPID_Comm *p, *prev; MPIU_DBG_MSG_P(COMM,VERBOSE, "Forgetting communicator %p from remember list",comm_ptr); /* FIXME: (MT) Ensure thread-safe */ p = MPIR_All_communicators.head; prev = 0; while (p) { if (p == comm_ptr) { if (prev) prev->comm_next = p->comm_next; else MPIR_All_communicators.head = p->comm_next; break; } if (p == p->comm_next) { MPIU_Internal_error_printf( "Mangled pointers to communicators - next is itself for %x\n", p ); break; } prev = p; p = p->comm_next; } /* Record a change to the list */ MPIR_All_communicators.sequence_number++;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -