2007-12-21 09:02:00 +03:00
|
|
|
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
2005-09-01 00:35:15 +04:00
|
|
|
/*
|
2005-11-05 22:57:48 +03:00
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
2008-11-06 03:00:15 +03:00
|
|
|
* Copyright (c) 2004-2008 The University of Tennessee and The University
|
2005-11-05 22:57:48 +03:00
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
2005-09-01 00:35:15 +04:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2011-12-15 22:40:25 +04:00
|
|
|
* Copyright (c) 2007-2011 Cisco Systems, Inc. All rights reserved.
|
2012-06-27 01:42:16 +04:00
|
|
|
* Copyright (c) 2012 Oak Ridge National Labs. All rights reserved.
|
2005-09-01 00:35:15 +04:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2008-08-01 02:11:46 +04:00
|
|
|
/*
|
2008-03-05 15:22:34 +03:00
|
|
|
* MPI portion of debugger support: initially based on the
|
|
|
|
* TotalView/Etnus API for debuggers to attach to MPI jobs.
|
2008-08-01 02:11:46 +04:00
|
|
|
*
|
|
|
|
* There is a lengthy explanation of how OMPI handles parallel
|
|
|
|
* debuggers attaching to MPI jobs in orte/tools/orterun/debuggers.c.
|
2005-09-01 00:35:15 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ompi_config.h"
|
|
|
|
|
2005-12-11 01:36:40 +03:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2005-09-01 00:35:15 +04:00
|
|
|
#include <unistd.h>
|
2005-12-11 01:36:40 +03:00
|
|
|
#endif /* HAVE_UNISTD_H */
|
2008-03-05 15:22:34 +03:00
|
|
|
#ifdef HAVE_DIRENT_H
|
|
|
|
#include <dirent.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
2005-09-01 00:35:15 +04:00
|
|
|
|
|
|
|
#include "opal/mca/base/base.h"
|
2008-03-05 15:22:34 +03:00
|
|
|
#include "opal/util/argv.h"
|
|
|
|
#include "opal/mca/installdirs/installdirs.h"
|
2005-09-01 00:35:15 +04:00
|
|
|
#include "debuggers.h"
|
2007-10-25 20:47:54 +04:00
|
|
|
/**
|
2008-11-06 03:00:15 +03:00
|
|
|
* BEWARE: The following headers are required by optimized builds in order
|
|
|
|
* to get access to the type information. Some compilers remove all type
|
|
|
|
* information on optimized build, and as a result we are unable to access
|
|
|
|
* the fields structure (i.e. to get their displacement). This file is
|
|
|
|
* included in the optimized build just to provide us with this missing
|
|
|
|
* informations. Therefore, it always have to be compiled with the -g flag,
|
|
|
|
* otherwise the type information will be missing and the parallel
|
|
|
|
* debuggers will be unable to initialize the Open MPI debug library.
|
2007-10-25 20:47:54 +04:00
|
|
|
*/
|
|
|
|
#include "opal/class/opal_list.h"
|
|
|
|
#include "ompi/class/ompi_free_list.h"
|
|
|
|
#include "ompi/request/request.h"
|
|
|
|
#include "ompi/mca/pml/base/pml_base_request.h"
|
|
|
|
#include "ompi/mca/pml/base/pml_base_sendreq.h"
|
|
|
|
#include "ompi/mca/pml/base/pml_base_recvreq.h"
|
2007-12-21 09:02:00 +03:00
|
|
|
#include "opal/class/opal_pointer_array.h"
|
2007-10-25 20:47:54 +04:00
|
|
|
#include "ompi/communicator/communicator.h"
|
2009-10-28 22:12:20 +03:00
|
|
|
#include "ompi/mca/topo/topo.h"
|
2007-10-25 20:47:54 +04:00
|
|
|
#include "ompi/group/group.h"
|
2009-10-28 22:12:20 +03:00
|
|
|
#include "opal/datatype/opal_datatype.h"
|
- Split the datatype engine into two parts: an MPI specific part in
OMPI
and a language agnostic part in OPAL. The convertor is completely
moved into OPAL. This offers several benefits as described in RFC
http://www.open-mpi.org/community/lists/devel/2009/07/6387.php
namely:
- Fewer basic types (int* and float* types, boolean and wchar
- Fixing naming scheme to ompi-nomenclature.
- Usability outside of the ompi-layer.
- Due to the fixed nature of simple opal types, their information is
completely
known at compile time and therefore constified
- With fewer datatypes (22), the actual sizes of bit-field types may be
reduced
from 64 to 32 bits, allowing reorganizing the opal_datatype
structure, eliminating holes and keeping data required in convertor
(upon send/recv) in one cacheline...
This has implications to the convertor-datastructure and other parts
of the code.
- Several performance tests have been run, the netpipe latency does not
change with
this patch on Linux/x86-64 on the smoky cluster.
- Extensive tests have been done to verify correctness (no new
regressions) using:
1. mpi_test_suite on linux/x86-64 using clean ompi-trunk and
ompi-ddt:
a. running both trunk and ompi-ddt resulted in no differences
(except for MPI_SHORT_INT and MPI_TYPE_MIX_LB_UB do now run
correctly).
b. with --enable-memchecker and running under valgrind (one buglet
when run with static found in test-suite, commited)
2. ibm testsuite on linux/x86-64 using clean ompi-trunk and ompi-ddt:
all passed (except for the dynamic/ tests failed!! as trunk/MTT)
3. compilation and usage of HDF5 tests on Jaguar using PGI and
PathScale compilers.
4. compilation and usage on Scicortex.
- Please note, that for the heterogeneous case, (-m32 compiled
binaries/ompi), neither
ompi-trunk, nor ompi-ddt branch would successfully launch.
This commit was SVN r21641.
2009-07-13 08:56:31 +04:00
|
|
|
#include "ompi/datatype/ompi_datatype.h"
|
2007-10-25 20:47:54 +04:00
|
|
|
#include "ompi/include/mpi.h"
|
2005-09-01 00:35:15 +04:00
|
|
|
|
2012-06-27 01:42:16 +04:00
|
|
|
#include "orca/include/rte_orca.h"
|
2008-06-18 19:28:46 +04:00
|
|
|
|
2008-03-05 15:22:34 +03:00
|
|
|
#if defined(OMPI_MSGQ_DLL)
|
|
|
|
/* This variable is old/deprecated -- the mpimsgq_dll_locations[]
|
|
|
|
method is preferred because it's more flexible */
|
|
|
|
OMPI_DECLSPEC char MPIR_dll_name[] = OMPI_MSGQ_DLL;
|
|
|
|
#endif /* defined(OMPI_MSGQ_DLL) */
|
|
|
|
OMPI_DECLSPEC char **mpidbg_dll_locations = NULL;
|
|
|
|
OMPI_DECLSPEC char **mpimsgq_dll_locations = NULL;
|
2006-09-18 21:32:04 +04:00
|
|
|
|
2006-10-05 00:01:33 +04:00
|
|
|
OMPI_DECLSPEC int MPIR_debug_typedefs_sizeof[] = {
|
|
|
|
sizeof(short),
|
|
|
|
sizeof(int),
|
|
|
|
sizeof(long),
|
|
|
|
sizeof(long long),
|
2007-08-16 08:33:04 +04:00
|
|
|
sizeof(void*),
|
|
|
|
sizeof(bool),
|
2006-10-05 00:01:33 +04:00
|
|
|
sizeof(size_t)
|
|
|
|
};
|
|
|
|
|
2008-09-20 15:34:37 +04:00
|
|
|
/*
|
|
|
|
* Values defined by the standardized interface; do not change these
|
|
|
|
* values
|
|
|
|
*/
|
|
|
|
#define MPIR_DEBUG_SPAWNED 1
|
|
|
|
#define MPIR_DEBUG_ABORTING 2
|
|
|
|
|
2007-10-25 20:47:54 +04:00
|
|
|
/**
|
2008-11-06 03:00:15 +03:00
|
|
|
* BEWARE: Try to outsmart some compilers. In some cases, when variables
|
|
|
|
* are defined but not used, some compilers will optimized them out from
|
|
|
|
* the build. As we need to be able to access the structure sizes from the
|
|
|
|
* debugged program (in the case where the MPI library and the application
|
|
|
|
* is compiled with a different architecture flag than the parallel
|
|
|
|
* debugger, 32 vs. 64 bits), we have to have these variables defined.
|
2007-10-25 20:47:54 +04:00
|
|
|
*/
|
2008-11-06 03:00:15 +03:00
|
|
|
OMPI_DECLSPEC opal_list_item_t* opal_list_item_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC opal_list_t* opal_list_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC ompi_free_list_item_t* ompi_free_list_item_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC ompi_free_list_t* ompi_free_list_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC ompi_request_t* ompi_request_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC mca_pml_base_request_t* mca_pml_base_request_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC mca_pml_base_send_request_t* mca_pml_base_send_request_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC mca_pml_base_recv_request_t* mca_pml_base_recv_request_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC opal_pointer_array_t* opal_pointer_array_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC ompi_communicator_t* ompi_communicator_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC ompi_group_t* ompi_group_t_type_force_inclusion = NULL;
|
|
|
|
OMPI_DECLSPEC ompi_status_public_t* ompi_status_public_t_type_force_inclusion = NULL;
|
2009-10-28 22:12:20 +03:00
|
|
|
OMPI_DECLSPEC opal_datatype_t* opal_datatype_t_type_force_inclusion = NULL;
|
2008-11-06 03:00:15 +03:00
|
|
|
OMPI_DECLSPEC ompi_datatype_t* ompi_datatype_t_type_force_inclusion = NULL;
|
2007-10-25 20:47:54 +04:00
|
|
|
|
2008-08-01 02:11:46 +04:00
|
|
|
OMPI_DECLSPEC volatile int MPIR_debug_gate = 0;
|
2012-01-11 19:53:09 +04:00
|
|
|
OMPI_DECLSPEC volatile int MPIR_being_debugged = 0;
|
|
|
|
OMPI_DECLSPEC volatile int MPIR_debug_state = 0;
|
2008-09-20 15:34:37 +04:00
|
|
|
OMPI_DECLSPEC char *MPIR_debug_abort_string = "";
|
2008-06-18 07:15:56 +04:00
|
|
|
|
2008-06-19 01:33:08 +04:00
|
|
|
/* Check for a file in few direct ways for portability */
|
2008-03-05 15:22:34 +03:00
|
|
|
static void check(char *dir, char *file, char **locations)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
asprintf(&str, "%s/%s.so", dir, file);
|
|
|
|
|
|
|
|
#if defined(HAVE_SYS_STAT_H)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
|
|
|
|
/* Use stat() */
|
|
|
|
if (0 == stat(str, &buf)) {
|
|
|
|
opal_argv_append_nosize(&locations, file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
/* Just try to open the file */
|
|
|
|
if (NULL != (fp = fopen(str, "r"))) {
|
|
|
|
fclose(fp);
|
|
|
|
opal_argv_append_nosize(&locations, file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* defined(HAVE_SYS_STAT_H) */
|
|
|
|
|
|
|
|
free(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-19 01:33:08 +04:00
|
|
|
/*
|
|
|
|
* Wait for a debugger if asked. We support two ways of waiting for
|
2008-08-01 02:11:46 +04:00
|
|
|
* attaching debuggers -- see big comment in
|
|
|
|
* orte/tools/orterun/debuggers.c explaning the two scenarios.
|
2005-09-01 00:35:15 +04:00
|
|
|
*/
|
2008-03-05 15:22:34 +03:00
|
|
|
void ompi_wait_for_debugger(void)
|
2005-09-01 00:35:15 +04:00
|
|
|
{
|
2011-04-20 20:48:07 +04:00
|
|
|
int i, debugger;
|
2009-03-03 00:29:52 +03:00
|
|
|
char *a, *b, **dirs, **tmp1 = NULL, **tmp2 = NULL;
|
2012-06-27 01:42:16 +04:00
|
|
|
#if ORCA_WITH_FULL_ORTE_SUPPORT
|
2008-06-18 19:28:46 +04:00
|
|
|
opal_buffer_t buf;
|
2011-04-20 20:48:07 +04:00
|
|
|
int rc;
|
|
|
|
#endif
|
2005-09-01 00:35:15 +04:00
|
|
|
|
2008-08-01 02:11:46 +04:00
|
|
|
/* See lengthy comment in orte/tools/orterun/debuggers.c about
|
|
|
|
orte_in_parallel_debugger */
|
2012-06-27 01:42:16 +04:00
|
|
|
#if !ORCA_WITH_FULL_ORTE_SUPPORT
|
2008-08-31 22:06:55 +04:00
|
|
|
debugger = 0;
|
|
|
|
#else
|
2012-06-27 01:42:16 +04:00
|
|
|
debugger = orca_info_in_parallel_debugger();
|
2008-08-31 22:06:55 +04:00
|
|
|
#endif
|
2008-06-19 01:33:08 +04:00
|
|
|
|
|
|
|
/* Add in environment variables for other launchers, such as yod,
|
|
|
|
srun, ...etc. */
|
2008-07-03 16:27:35 +04:00
|
|
|
if (1 == MPIR_being_debugged) {
|
|
|
|
debugger = 1;
|
|
|
|
} else if (NULL != getenv("yod_you_are_being_debugged")) {
|
2008-06-19 01:33:08 +04:00
|
|
|
debugger = 1;
|
|
|
|
}
|
2008-08-01 02:11:46 +04:00
|
|
|
if (1 == MPIR_being_debugged) {
|
|
|
|
debugger = 1;
|
|
|
|
}
|
2008-06-18 19:28:46 +04:00
|
|
|
|
|
|
|
if (!debugger) {
|
|
|
|
/* if not, just return */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we are being debugged, then we need to find
|
2008-06-19 01:33:08 +04:00
|
|
|
* the correct plug-ins
|
2008-06-18 19:28:46 +04:00
|
|
|
*/
|
2008-03-05 15:22:34 +03:00
|
|
|
a = strdup(opal_install_dirs.pkglibdir);
|
|
|
|
mca_base_param_reg_string_name("ompi",
|
|
|
|
"debugger_dll_path",
|
|
|
|
"List of directories where MPI_INIT should search for debugger plugins",
|
|
|
|
false, false, a, &b);
|
|
|
|
free(a);
|
2008-06-18 19:28:46 +04:00
|
|
|
|
2008-03-05 15:22:34 +03:00
|
|
|
/* Search the directory for MPI debugger DLLs */
|
|
|
|
if (NULL != b) {
|
|
|
|
dirs = opal_argv_split(b, ':');
|
|
|
|
for (i = 0; dirs[i] != NULL; ++i) {
|
2009-03-03 00:29:52 +03:00
|
|
|
check(dirs[i], OMPI_MPIHANDLES_DLL_PREFIX, tmp1);
|
|
|
|
check(dirs[i], OMPI_MSGQ_DLL_PREFIX, tmp2);
|
2008-03-05 15:22:34 +03:00
|
|
|
}
|
|
|
|
}
|
2008-06-19 01:33:08 +04:00
|
|
|
|
2009-03-03 00:29:52 +03:00
|
|
|
/* Now that we have a full list of directories, assign the argv
|
|
|
|
arrays to the global variables (since the debugger may read the
|
|
|
|
global variables at any time, we want to ensure that they have
|
|
|
|
non-NULL values only when the entire array is ready). */
|
|
|
|
mpimsgq_dll_locations = tmp1;
|
|
|
|
mpidbg_dll_locations = tmp2;
|
|
|
|
|
2012-06-27 01:42:16 +04:00
|
|
|
#if ORCA_WITH_FULL_ORTE_SUPPORT
|
|
|
|
if (orca_info_standalone_operation()) {
|
2011-04-20 20:48:07 +04:00
|
|
|
#endif
|
2008-06-19 01:33:08 +04:00
|
|
|
/* spin until debugger attaches and releases us */
|
|
|
|
while (MPIR_debug_gate == 0) {
|
2005-12-11 01:10:39 +03:00
|
|
|
#if defined(__WINDOWS__)
|
2008-06-19 01:33:08 +04:00
|
|
|
Sleep(100); /* milliseconds */
|
2008-06-18 07:15:56 +04:00
|
|
|
#elif defined(HAVE_USLEEP)
|
2008-06-19 01:33:08 +04:00
|
|
|
usleep(100000); /* microseconds */
|
2008-06-18 07:15:56 +04:00
|
|
|
#else
|
2008-06-19 01:33:08 +04:00
|
|
|
sleep(1); /* seconds */
|
2005-09-01 00:35:15 +04:00
|
|
|
#endif
|
2008-06-19 01:33:08 +04:00
|
|
|
}
|
2012-06-27 01:42:16 +04:00
|
|
|
#if ORCA_WITH_FULL_ORTE_SUPPORT
|
2008-06-19 01:33:08 +04:00
|
|
|
} else {
|
|
|
|
|
|
|
|
/* only the rank=0 proc waits for either a message from the
|
|
|
|
* HNP or for the debugger to attach - everyone else will just
|
|
|
|
* spin in * the grpcomm barrier in ompi_mpi_init until rank=0
|
|
|
|
* joins them.
|
|
|
|
*/
|
2012-06-27 01:42:16 +04:00
|
|
|
if (0 != orca_process_info_get_vpid(ORCA_PROC_MY_NAME) ) {
|
2008-06-19 01:33:08 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* VPID 0 waits for a message from the HNP */
|
|
|
|
OBJ_CONSTRUCT(&buf, opal_buffer_t);
|
2012-06-27 01:42:16 +04:00
|
|
|
rc = orca_oob_recv_buffer(ORCA_NAME_WILDCARD, &buf,
|
|
|
|
ORCA_OOB_TAG_DEBUGGER_RELEASE, 0);
|
2008-06-19 01:33:08 +04:00
|
|
|
OBJ_DESTRUCT(&buf); /* don't care about contents of message */
|
|
|
|
if (rc < 0) {
|
|
|
|
/* if it failed for some reason, then we are in trouble -
|
|
|
|
* for now, just report the problem and give up waiting
|
|
|
|
*/
|
2011-10-19 17:04:46 +04:00
|
|
|
opal_output(0, "Debugger_attach[rank=%ld]: could not wait for debugger!",
|
2012-06-27 01:42:16 +04:00
|
|
|
(long)orca_process_info_get_vpid(ORCA_PROC_MY_NAME) );
|
2008-06-19 01:33:08 +04:00
|
|
|
}
|
2005-09-01 00:35:15 +04:00
|
|
|
}
|
2011-04-20 20:48:07 +04:00
|
|
|
#endif
|
2008-06-19 01:33:08 +04:00
|
|
|
}
|
2008-09-20 15:34:37 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Tell the debugger that we are about to abort
|
|
|
|
*/
|
|
|
|
void ompi_debugger_notify_abort(char *reason)
|
|
|
|
{
|
|
|
|
MPIR_debug_state = MPIR_DEBUG_ABORTING;
|
|
|
|
|
|
|
|
if (NULL != reason && strlen(reason) > 0) {
|
|
|
|
MPIR_debug_abort_string = reason;
|
|
|
|
} else {
|
|
|
|
MPIR_debug_abort_string = "Unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now tell the debugger */
|
|
|
|
MPIR_Breakpoint();
|
|
|
|
}
|
2012-01-11 19:53:09 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Breakpoint function for parallel debuggers. This function is also
|
|
|
|
* defined in orterun for the starter. It should never conflict with
|
|
|
|
* this
|
|
|
|
*/
|
|
|
|
void* MPIR_Breakpoint(void)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|