diff --git a/ompi/communicator/comm.c b/ompi/communicator/comm.c index ab37e8d86c..4aa5688411 100644 --- a/ompi/communicator/comm.c +++ b/ompi/communicator/comm.c @@ -1402,7 +1402,7 @@ int ompi_topo_create (ompi_communicator_t *old_comm, } memcpy (new_comm->c_topo_comm->mtc_dims_or_index, dims_or_index, ndims_or_nnodes * sizeof(int)); - + /* Now the topology component has been selected, let the component * re-arrange the proc ranks if need be. This is a down-call into * the topo component and does not have anything to do with this @@ -1446,15 +1446,14 @@ int ompi_topo_create (ompi_communicator_t *old_comm, * it as they deem fit */ new_comm->c_topo_comm->mtc_periods_or_edges = (int *) - malloc (sizeof(int) * dims_or_index[ndims_or_nnodes - 1]); + malloc (sizeof(int) * ndims_or_nnodes); if (NULL == new_comm->c_topo_comm->mtc_periods_or_edges) { ompi_comm_free (&new_comm); *comm_topo = new_comm; return OMPI_ERROR; } memcpy (new_comm->c_topo_comm->mtc_periods_or_edges, - periods_or_edges, - dims_or_index[ndims_or_nnodes - 1] * sizeof(int)); + periods_or_edges, ndims_or_nnodes * sizeof(int)); new_comm->c_topo_comm->mtc_coords = (int *)malloc (sizeof(int) * ndims_or_nnodes); if (NULL == new_comm->c_topo_comm->mtc_coords) { @@ -1561,8 +1560,6 @@ int ompi_topo_create (ompi_communicator_t *old_comm, } - /* finally, set the communicator to comm_cart */ - /* if the returned rank is -1, then this process is not in the * new topology, so free everything we have allocated and return */ if (MPI_UNDEFINED == new_rank) { diff --git a/ompi/debuggers/MPI_Handles_interface.txt b/ompi/debuggers/MPI_Handles_interface.txt new file mode 100644 index 0000000000..2b3463a0a4 --- /dev/null +++ b/ompi/debuggers/MPI_Handles_interface.txt @@ -0,0 +1,663 @@ +1. George questions the need for the mpidbg_process_t structure (and + the mapping that it provides to MPI_COMM_WORLD). What does Allinea + think of this? + +2. 3 Aug 2007: Random notes: + - I kept the prefix MPIDBG/mpidbg (vs. converting to mqs to be the + same as the message queue functionality) to allow this + functionality to be in a different DLL/plugin than the message + queue DLL/plugin. + - I therefore also kept our own MPIDBG return codes (the existing + mqs_* return codes are not sufficient). + +3. Some additional open issues throughout the text and header file are + marked with "JMS". + +4. 30 Aug 2007: Added questions about uninitialized / already-freed + handles. + +*************************************************************************** + +Premise +======= + +Debuggers can display the value of intrinsic datatypes (e.g., int, +double, etc.). Even composite struct instances can be displayed. A +logical extension to this concept is that the debugger should be able +to show information about MPI opaque handles in a running application +(and possibly cache such values for playback when the application is +not running, such as during corefile analysis). Similar in spirit to +the API for obtaining the message passing queues, a simple API can be +used between the debugger and the MPI application to obtain +information about specific MPI handle instances. + +*************************************************************************** + +Background +========== + +MPI defines several types of opaque handles that are used in +applications (e.g., MPI_Comm, MPI_Request, etc.). The opaque handles +are references to underlying MPI objects that are private to the MPI +implementation. These objects contain a wealth of information that +can be valuable to display in a debugging context. + +Implementations typically have a different underlying type and then +typedef the MPI-specified name to the underlying type. For example, +Open MPI has the following in mpi.h: + + typedef struct ompi_communicator_t *MPI_Comm; + +The MPI-specified type is "MPI_Comm"; the OMPI-specific type is +"struct ompi_communicator_t *". The debugger cannot simply deduce the +"real" types of MPI handles by looking at the types of well-known +global variables (such as MPI_COMM_WORLD) because these names may be +preprocessor macros in mpi.h; the real name of the symbol may be +implementation-dependent and not easy to guess. + +Hence, if "MPI_*" types are unable to be found by the debugger within +the application image, the MPI implementation will need to provide a +list of the actual types to the debugger when the MPI handle +interpretation functionality is initialized. Once the debugger knows +the types of MPI handles, it can provide context-sensitive information +when displaying the values of variables within the application image. + +Some MPI implementations use integers for handles in C. Such +implementations are strongly encouraged to use "typedef" for creating +handle types in mpi.h (vs. using #define), such as: + + typedef int MPI_Comm; + typedef int MPI_Datatype; + /* etc. */ + +So that the debugger can identify a variable as an MPI_Comm (vs. an +int) and therefore know that it is an MPI communicator. + +In Fortran, however, all MPI handles are defined by the MPI standard +to be of type INTEGER. As such, there is no way for the debugger to +automatically know that a given INTEGER variable is an MPI handle, nor +which kind of MPI handle. It is therefore up to the debugger's UI to +allow users to designate specific INTEGER variables as a given MPI +handle type. + +MPI handles can be "freed" by the application, but this actually only +marks the underlying MPI object for freeing; the object itself may not +be freed until all corresponding handles and pending actions have +completed. Additionally, for debugging purposes, an MPI +implementation can choose to *never* free MPI objects (in order to +show that they were marked as freed and/or actually freed). + +*************************************************************************** + +Assumptions +=========== + +Some terminology: + - host: machine and process on which debugging process is executing. + - debugger: machine and debugging UI, where the debugger is running. + The two machines may be distinct from a hardware point of view, + they may have differing endinanness, word-size, etc. + +MPI typically denotes function names in all capitol letters (MPI_INIT) +as a language-neutral form. The Fortran binding for the function is +dependent upon the compiler; the C binding for the function +capitolizes the "MPI" and the first letter of the next token (e.g., +"MPI_Init"). This text will use the language-neutral names for all +MPI function names. + +The debugger will access the handle-interpretation functionality by +loading a plugin provided by the MPI implementation into its process +space. The plugin will contain "query" functions that the debugger +can invoke to obtain information about various MPI handle types. The +query functions generally return the additional information or "not +found" kinds of errors. + +The MPI-implementation-provided plugin shares many of the same +characteristics as the Etnus MPI message queue plugin design, but is +loaded slightly differently. The plugin will use the mqs_* functions +defined by the Etnus message queue access interface to read the +process image to obtain MPI object information that is then passed +back to the debugger. + +The plugin's query functions should not be called before MPI_INIT has +completed nor after MPI_FINALIZE has started. MPI handles are only +meaningful between the time that MPI_INIT completes and MPI_FINALIZE +starts, anyway. + +When MPI handles are marked for freeing by the MPI implementation, +there should be some notice from the debugger that the underlying +objects should not *actually* be freed, but rather orphaned. The +debugger can track these objects and keep a reference count of +how many handles are still referring to the underlying objects. When +the reference count goes to 0, the debugger can call a function in the +application telling the MPI implementation that the object is safe to +be freed. + +In this way, valuable debugging information is still available to the +user if they have stale MPI handles because the underlying object will +still be available in memory (marked as "stale"); but MPI object +memory usage is not cumulative. + +The debugger may not be able to provide any additional information in +Fortran applications because all MPI handles are of type INTEGER (and +there's no way to tell that any given integer is an MPI communicator +handle, for example) unless the debugger provides some way in the UI +to indicate that a given INTEGER variable is a specific type of MPI +handle. + +Note that the following pattern is valid in MPI: + + MPI_Request a, b; + MPI_Isend(..., &a); + b = a; + MPI_Request_free(&a); + +After executing MPI_REQUEST_FREE, the handle "a" has been set to +MPI_REQUEST_NULL, but the handle "b" still points to the [potentially +ongoing] request. "b" would therefore report that it has been marked +for freeing by the application, but would not report that it was +completed / marked for freeing by the MPI implementation until the +corresponding ISEND actually completes. + +The query functions will return newly-allocated structs of information +to the debugger (allocated via mqs_malloc). The debugger will be +responsible for freeing this memory. Arrays/lists of information +contained in the structs must be individually freed if they are not +NULL (i.e., they will each be allocated via mqs_malloc). + +Finally, note that not all of this needs to be supported by the +debugger at once. Interpretation of some of the more common handle +types can be implemented first (e.g., communicators and requests), +followed by more types over time. + +*************************************************************************** + +MPI handle types +================ + +Communicator +============ + +C: MPI_Comm +C++: MPI::Comm, MPI::Intracomm, MPI::Intercomm, MPI::Cartcomm, + MPI::Graphcomm + +A communicator is an ordered set of MPI processes and a unique +communication context. There are 3 predefined communicators +(MPI_COMM_WORLD, MPI_COMM_SELF, MPI_COMM_PARENT), and applications can +create their own communicators. There are two types of communicators: + +1. Intracommunicator: contains one group of processes. + Intracommunicators may optionally have a topology: + - Cartesian: a dense, N-dimensional Cartesian topology + - Graph: an arbitrary unweighted, undirected, connected graph + +2. Intercommunicator: contains a local group and a remote group of + processes. + +--> Information available from communicators: + + - String name of length MPI_MAX_OBJECT_NAME + - Flag indicating whether it's a predefined communicator or not + - Whether the handle has been marked for freeing by the + application or not + - This process' unique ID within the communicator ("rank", from 0-(N-1)) + - This process' unique ID in the entire MPI universe + - Number of peer processes in the communicator + - Type of communicator: inter or intra + - If Inter, the number and list of peer processes in the communicator + - If intra, whether the communicator has a graph or cartesian + topology + - If have a Cartesian toplogy (mutually exclusive with having a + graph topology), the topology information: + - "ndims", "dims", periods" arguments from the corresponding + call to MPI_CART_CREATE, describing the Cartesian topology. + - If have a graph topology (mutually exclusive with having a + cartesian topology): + - "index" and "edges" arguments from the corresponding call to + MPI_GRAPH_CREATE, describing the nodes and edges in the graph + topology + - Cross reference to the underlying MPI group(s) + - Cross reference to the underlying MPI error handler + + - C handle (if available) + - Fortran integer index for this handle (if available) + +--> Extra/bonus information that the MPI may be able to provide: + + - A list of MPI "attributes" that are attached to the communicator + - A list of any MPI requests currently associated with the + communicator (e.g., ongoing or completed but not released + communicator requests, or, in multi-threaded scenarios, ongoing + communicator operations potentially from other threads) + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - A list of MPI windows using this communicator + - A list of MPI files using this communicator + +--> Suggested data types + See mpihandles_interface.h + +--> Suggested API functions + See mpihandles_interface.h + +--------------------------------------------------------------------------- + +Datatype +======== + +C: MPI_Datatype +C++: MPI::Datatype + +MPI datatypes are used to express the size and shape of user-defind +messages. For example, a user can define an MPI datatype that +describes a C structure, and can then use that MPI datatype to send +and receive instances (or arrays) of that struct. There are many +predefined datatypes, and applications can create their own datatypes. + +--> Information available from datatypes: + + - String name + - Flag indicating whether it's a predefined datatype or not + - C handle (if available) + - Fortran integer index for this handle (if available) + - A type map of the overall datatype, composed of *only* intrinsic MPI + datatypes (MPI_INT, MPI_DOUBLE, etc.) that can be rendered by the + debugger into a form similar to MPI-1:3.12 + - What function was used to create the datatype: + - CREATE_DARRAY, CREATE_F90_COMPLEX, + CREATE_F90_INTEGER, CREATE_F90_REAL, CREATE_HINDEXED, + CREATE_HVACTOR, CREATE_INDEXED_BLOCK, CREATE_RESIZED, + CREATE_STRUCT, CREATE_SUBARRAY + --> JMS: Do we need to differentiate between the MPI-1 and MPI-2 + functions? Probably worthwhile, if for nothing other than + completeness (e.g., don't confuse the user saying that a + datatype was created by MPI_TYPE_CREATE_STRUCT when it was + creally created with MPI_TYPE_STRUCT, even though they're + effectively equivalent). + - TYPE_HINDEXED, TYPE_INDEXED, TYPE_HVECTOR, TYPE_VECTOR, + TYPE_STRUCT, TYPE_CONTIGUOUS, + + JMS: with the type map provided by MPI, a debugger can show "holes" + in a datatype (potentially indicating missed optimizations by + the application). Very cool/useful! + +--> Extra/bonus information that the MPI may be able to provide: + + - Ongoing communication actions involving the datatype + (point-to-point, collective, one-sided) + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - Whether the datatype has been "committed" or not + - A list of datatypes used to create this datatype (JMS: may + require caching by the debugger!!) + +--> Suggested data types + + ***TO BE FILLED IN*** + +--> Suggested API functions + + ***TO BE FILLED IN*** + +--------------------------------------------------------------------------- + +Error handler +============= + +C: MPI_Errhandler +C++: MPI::Errhandler + +MPI allows applications to define their own error handlers. The +default error handler is to abort the MPI job. Error handlers can be +attached to communicators, files, and windows. There are 3 predefined +error handlers (MPI_ERRORS_ARE_FATAL, MPI_ERRORS_RETURN, +MPI::ERRORS_THROW_EXCEPTIONS), and applications can create their own +error handlers. + +--> Information available from error handlers: + + - Flag indicating whether it's a predefined error handler or not + - C handle (if available) + - Fortran integer index for this handle (if available) + - Type of errorhandler: communicator, file, window + - If user-defined (i.e., not predefined), the function pointer for + the user function that MPI will invoke upon error + - Whether the callback function is in Fortran or C/C++ + +--> Extra/bonus information that the MPI may be able to provide: + + - String name for predefined handles + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - List of communicators/files/windows that this error handler is + currently attached to + +--> Suggested data types + See mpihandles_interface.h + +--> Suggested API functions + See mpihandles_interface.h + +--------------------------------------------------------------------------- + +File +==== + +C: MPI_File +C++: MPI::File + +MPI has the concept of parallel IO, where a group of processes +collectively open, read/write, and close files. An MPI_File handle +represents both an ordered set of processes and a file to which they +are accessing. There is one pre-defined file: MPI_FILE_NULL; +applications can open their own files. + +--> Information available from files: + + - String file name (or "MPI_FILE_NULL") + - Flag indicating whether it's a predefined file or not + - C handle (if available) + - Fortran integer index for this handle (if available) + - Communicator that the file was opened with + - Info key=value pairs that the file was opened with + - Mode that the file was opened with + +--> Extra/bonus information that the MPI may be able to provide: + + - Whether the handle has been marked for freeing (closing) by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - A list of any MPI requests currently associated with the file + (e.g., ongoing or completed but not released file requests, or, in + multi-threaded scenarios, ongoing file operations potentially from + other threads) + +--> Suggested data types + + ***TO BE FILLED IN*** + +--> Suggested API functions + + ***TO BE FILLED IN*** + +--------------------------------------------------------------------------- + +Group +===== + +C: MPI_Group +C++: MPI::Group + +An unordered set of processes. There are predefined and user-defined +groups. Every communicator contains exactly 1 or 2 groups (depending +on the type of communicator). There are 2 predefined groups +(MPI_GROUP_NULL and MPI_GROUP_EMPTY); applications can create their +own groups. + +--> Information available from groups: + + - C handle (if available) + - Fortran integer index for this handle (if available) + - This process' unique ID in this group + - List of peer processes in this group + +--> Extra/bonus information that the MPI may be able to provide: + + - String name for predefined handles + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - A list of MPI communicators using this group + +--> Suggested data types + + ***TO BE FILLED IN*** + +--> Suggested API functions + + ***TO BE FILLED IN*** + +--------------------------------------------------------------------------- + +Info +==== + +C: MPI_Info +C++: MPI::Info + +A set of key=value pairs (the key and value are separate strings) that +can be used to pass "hints" to MPI. There are no predefined info +handles; applications can create their own info handles. + +--> Information available from info: + + - C handle (if available) + - Fortran integer index for this handle (if available) + - Number of key=value pairs on the info + - List of key=value pairs (each key and value is an individual + string) + +--> Extra/bonus information that the MPI may be able to provide: + + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - A list of places where the info object is currently being used + +--> Suggested data types + + ***TO BE FILLED IN*** + +--> Suggested API functions + + ***TO BE FILLED IN*** + +--------------------------------------------------------------------------- + +Request +======= + +C: MPI_Request +C++:: MPI::Request, MPI::Grequest, MPI::Prequest + +A pointer to an ongoing or completed-but-not-yet-released action. +There are three types of requests: + + - Point-to-point communication: non-blocking sends, receives + - File actions: non-blocking reads, writes + - Generalized actions: Users can define their own asynchronous actions + that can be subject to MPI completion semantics + +There is one predefined request (MPI_REQUEST_NULL); applications can +create their own requests. + +--> Information available from requests: + + - Flag indicating whether it's a predefined request or not + - Flag indicating whether the request is persistent or not + - C handle (if available) + - Fortran integer index for this handle (if available) + - Type of the request: pt2pt, file, generalized + - Function that created this request: + - Pt2pt: ISEND, IBSEND, ISSEND, IRSEND, IRECV, SEND_INIT, + BSEND_INIT, SSEND_INIT, RSEND_INIT, RECV_INIT + - File: IREAD, IREAD_AT, IREAD_SHARED, IWRITE, + IWRITE_AT, IWRITE_SHARED + - Whether the request has been marked "complete" or not + +--> Extra/bonus information that the MPI may be able to provide: + + - String name for predefined handles + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - Peer process(es) invovled with the request (if available) + - If pt2pt, communicator associated with the request + - If file, file associated with the request + - If pt2pt or file, whether the data transfer has started yet + - If pt2pt or file, whether the data transfer has completed yet + +--> Suggested data types + See mpihandles_interface.h + +--> Suggested API functions + See mpihandles_interface.h + +--------------------------------------------------------------------------- + +Operation +========= + +C: MPI_Op +C++:: MPI::Op + +A reduction operator used in MPI collective and one-sided operations +(e.g., sum, multiply, etc.). There are several predefined operators; +applications can also create their own operators. + +--> Information available from operators: + + - Flag indicating whether it's a predefined operator or not + - C handle (if available) + - Fortran integer index for this handle (if available) + - If user-defined, the function pointer for the user function that + MPI will invoke + - Whether the callback function is in Fortran or C/C++ + - Whether the operator is commutative or not + +--> Extra/bonus information that the MPI may be able to provide: + + - String name for predefined handles + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - List of ongoing collective / one-sided communications associated + with this operator + +--> Suggested data types + + ***TO BE FILLED IN*** + +--> Suggested API functions + + ***TO BE FILLED IN*** + +--------------------------------------------------------------------------- + +Status +====== + +C: MPI_Status +C++: MPI::Status + +A user-accessible struct that contains information about a completed +communication. The MPI status is a little different from other MPI +handles in that it is the object itselt; not a handle to an underlying +MPI status. For example, if a point-to-point communication was +started with a wildcard receive, the status will contain information +about the peer to whom the communication completed. There are no +predefined statuses. + +--> Information available from status: + + - Public member MPI_SOURCE: source of the communication + - Public member MPI_TAG: tag of the communication + - Public member MPI_ERROR: error status of the communication + - Number of bytes in the communication + +--> Extra/bonus information that the MPI may be able to provide: + + - Number of data elements in the communication + +--> Suggested data types + See mpihandles_interface.h + +--> Suggested API functions + See mpihandles_interface.h + +--------------------------------------------------------------------------- + +Window +====== + +C: MPI_Win +C++: MPI::Win + +An ordered set of processes, each defining their own "window" of +memory for one-sided operations. + +--> Information available from windows: + + - Communicator that the window was created with + - Base address, length, and displacement units of the window *in this + process* + - Info key=value pairs that the file was opened with + + +--> Extra/bonus information that the MPI may be able to provide: + + - Whether the handle has been marked for freeing by the + application or not + - Whether the underlying object has been "freed" by the MPI + implementation (i.e., made inactive, and would have actually been + freed if not running under a debugger) + - Whether LOCK has been called on this window without a + corresponding UNLOCK yet + - Whether START has been called on this window without a + corresponding COMPLETE yet + - Whether POST has been called on this window without a + corresopnding TEST/WAIT yet + - What the last synchronization call was on the window: FENCE, + LOCK/UNLOCK, START/COMPLETE, POST/TEST/WAIT + +--> Suggested data types + + ***TO BE FILLED IN*** + +--> Suggested API functions + + ***TO BE FILLED IN*** + +--------------------------------------------------------------------------- + +Address integer +=============== + +C: MPI_Aint +C++: MPI::Aint + +This is an MPI-specific type, but is always an integer value that is +large enough to hold addresses. It is typically an 32 or 64 bits +long. Hence, the debugger should be able to directly display this +value. + +--------------------------------------------------------------------------- + +Offset +====== + +C: MPI_Offset +C++: MPI::Offset + +This is a MPI-specific type, but is always an integer value that is +large enough to hold file offsets. It is typically an 32 or 64 bits +long. Hence, the debugger should be able to directly display this +value. diff --git a/ompi/debuggers/Makefile.am b/ompi/debuggers/Makefile.am index 4369bcbfb9..9a46931c9e 100644 --- a/ompi/debuggers/Makefile.am +++ b/ompi/debuggers/Makefile.am @@ -9,6 +9,7 @@ # University of Stuttgart. All rights reserved. # Copyright (c) 2004-2005 The Regents of the University of California. # All rights reserved. +# Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -17,7 +18,7 @@ # noinst_LTLIBRARIES = libdebuggers.la -inst_LTLIBRARIES = libompitv.la +pkglib_LTLIBRARIES = libompi_dbg_msgq.la # This is not quite in the Automake spirit, but we have to do it. # Since the totalview portion of the library must be built with -g, we @@ -30,18 +31,25 @@ CFLAGS = $(CFLAGS_WITHOUT_OPTFLAGS) $(TOTALVIEW_DEBUG_FLAGS) # Source code files -headers = debuggers.h mpi_interface.h ompi_dll_defs.h - -instdir = $(libdir)/openmpi +headers = \ + debuggers.h \ + ompi_common_dll_defs.h \ + msgq_interface.h ompi_msgq_dll_defs.h libdebuggers_la_SOURCES = \ $(headers) \ - ompi_totalview.c -libdebuggers_la_CFLAGS = -DOMPI_TV_DLL=\"$(instdir)/libompitv.so\" + ompi_debuggers.c +libdebuggers_la_CPPFLAGS = \ + -DOMPI_MSGQ_DLL=\"$(pkglibdir)/libompi_dbg_msgq.so\" \ + -DOMPI_MSGQ_DLL_PREFIX=\"libompi_dbg_msgq\" \ + -DOMPI_MPIHANDLES_DLL_PREFIX=\"libompi_dbg_mpihandles\" -libompitv_la_SOURCES = ompi_dll.c -libompitv_la_CFLAGS = -g -libompitv_la_LDFLAGS = -module -avoid-version +common = ompi_common_dll_defs.h ompi_common_dll.c + +# MPI message queue DLL +libompi_dbg_msgq_la_SOURCES = ompi_msgq_dll.c ompi_msgq_dll_defs.h $(common) +libompi_dbg_msgq_la_CFLAGS = -g +libompi_dbg_msgq_la_LDFLAGS = -module -avoid-version # Conditionally install the header files diff --git a/ompi/debuggers/debuggers.h b/ompi/debuggers/debuggers.h index 50daa7efde..13e999fb8a 100644 --- a/ompi/debuggers/debuggers.h +++ b/ompi/debuggers/debuggers.h @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -27,16 +28,13 @@ #include "ompi_config.h" -#if defined(c_plusplus) || defined(__cplusplus) -extern "C" { -#endif - /** - * Wait for a TotalView-like debugger if asked. - */ - OMPI_DECLSPEC void ompi_wait_for_totalview(void); +BEGIN_C_DECLS -#if defined(c_plusplus) || defined(__cplusplus) -} -#endif + /** + * Wait for a debugger if asked. + */ + OMPI_DECLSPEC void ompi_wait_for_debugger(void); + +END_C_DECLS #endif /* OMPI_DEBUGGERS_H */ diff --git a/ompi/debuggers/mpihandles_interface.h b/ompi/debuggers/mpihandles_interface.h new file mode 100644 index 0000000000..38831e7084 --- /dev/null +++ b/ompi/debuggers/mpihandles_interface.h @@ -0,0 +1,876 @@ +/* + * Copyright (c) 2007 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2007-2008 Cisco, Inc. All rights reserved. + * Copyright (c) 2007 The University of Tennessee and The University of + * Tennessee Research Foundation. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * Some text copied from and references made to mpi_interface.h. + * + * Copyright (C) 2000-2004 by Etnus, LLC + * Copyright (C) 1999 by Etnus, Inc. + * Copyright (C) 1997-1998 Dolphin Interconnect Solutions Inc. + * + * $HEADER$ + */ + +#ifndef __MPIDBG_INTERFACE_H__ +#define __MPIDBG_INTERFACE_H__ 1 + +/* + * This file provides interface functions for a debugger to gather + * additional information about MPI handles. + */ +#include + +/* Include the Etnus debugger message queue interface so that we can + use much of its infrastructure (e.g., the mqs_basic_callbacks, + mqs_image_callbacks, and mqs_process_callbacks). */ +#define FOR_MPI2 0 +#include "msgq_interface.h" + +/************************************************************************** + * Types and macros + **************************************************************************/ + +enum { + MPIDBG_MAX_OBJECT_NAME = 64 +}; +enum { + MPIDBG_MAX_FILENAME = 1024 +}; +enum { + MPIDBG_INTERFACE_VERSION = 1 +}; + + +/*----------------------------------------------------------------------- + * Global initialization information for the DLL + *-----------------------------------------------------------------------*/ + +/* Structure containing types for C and C++ MPI handles */ +struct mpidbg_handle_info_t { + /* C handle types. They are typically pointers to something or + integers. */ + /* Back-end type for MPI_Aint */ + mqs_type *hi_c_aint; + /* Back-end type for MPI_Comm */ + mqs_type *hi_c_comm; + /* Back-end type for MPI_Datatype */ + mqs_type *hi_c_datatype; + /* Back-end type for MPI_Errhandler */ + mqs_type *hi_c_errhandler; + /* Back-end type for MPI_File */ + mqs_type *hi_c_file; + /* Back-end type for MPI_Group */ + mqs_type *hi_c_group; + /* Back-end type for MPI_Info */ + mqs_type *hi_c_info; + /* Back-end type for MPI_Offset */ + mqs_type *hi_c_offset; + /* Back-end type for MPI_Op */ + mqs_type *hi_c_op; + /* Back-end type for MPI_Request */ + mqs_type *hi_c_request; + /* Back-end type for MPI_Status */ + mqs_type *hi_c_status; + /* Back-end type for MPI_Win */ + mqs_type *hi_c_win; + + /* C++ handle types. Note that these will always be *objects*, + never pointers. */ + /* Back-end type for MPI::Aint */ + mqs_type *hi_cxx_aint; + /* Back-end type for MPI::Comm */ + mqs_type *hi_cxx_comm; + /* Back-end type for MPI::Intracomm */ + mqs_type *hi_cxx_intracomm; + /* Back-end type for MPI::Intercomm */ + mqs_type *hi_cxx_intercomm; + /* Back-end type for MPI::Graphcomm */ + mqs_type *hi_cxx_graphcomm; + /* Back-end type for MPI::Cartcomm */ + mqs_type *hi_cxx_cartcomm; + /* Back-end type for MPI::Datatype */ + mqs_type *hi_cxx_datatype; + /* Back-end type for MPI::Errhandler */ + mqs_type *hi_cxx_errhandler; + /* Back-end type for MPI::File */ + mqs_type *hi_cxx_file; + /* Back-end type for MPI::Group */ + mqs_type *hi_cxx_group; + /* Back-end type for MPI::Info */ + mqs_type *hi_cxx_info; + /* Back-end type for MPI::Offset */ + mqs_type *hi_cxx_offset; + /* Back-end type for MPI::Op */ + mqs_type *hi_cxx_op; + /* Back-end type for MPI::Request */ + mqs_type *hi_cxx_request; + /* Back-end type for MPI::Prequest */ + mqs_type *hi_cxx_prequest; + /* Back-end type for MPI::Grequest */ + mqs_type *hi_cxx_grequest; + /* Back-end type for MPI::Status */ + mqs_type *hi_cxx_status; + /* Back-end type for MPI::Win */ + mqs_type *hi_cxx_win; +}; + +enum mpidbg_return_codes_t { + /* Success */ + MPIDBG_SUCCESS, + /* Something was not found */ + MPIDBG_ERR_NOT_FOUND, + /* Something is not supported */ + MPIDBG_ERR_NOT_SUPPORTED, + /* Something is out of range */ + MPIDBG_ERR_OUT_OF_RANGE, + /* Something is not available */ + MPIDBG_ERR_UNAVAILABLE, + /* Ran out of memory */ + MPIDBG_ERR_NO_MEM, + /* Sentinel max value */ + MPIDBG_MAX_RETURN_CODE +}; + +/*----------------------------------------------------------------------- + * General data structures + *-----------------------------------------------------------------------*/ + +/* Information about MPI processes */ +struct mpidbg_process_t { + /* JMS: need something to uniquely ID MPI processes in the + presence of MPI_COMM_SPAWN */ + + /* Global rank in MPI_COMM_WORLD */ + int mpi_comm_world_rank; +}; +/* ==> JMS Should we just use mqs_process_location instead? George + thinks that this is unncessary -- perhaps due to the fact that we + could use mqs_process_location...? Need to get some feedback from + Allinea on this one. */ + +/* General name -> handle address mappings. This is an optional type + that is used to describe MPI's predefined handles if the + pre-defined names do not appear as symbols in the MPI process. + E.g., if MPI_COMM_WORLD is a #define that maps to some other value, + this data structure can be used to map the string "MPI_COMM_WORLD" + to the actual value of the handle that it corresponds to (e.g., 0 + or a pointer value). */ +struct mpidbg_name_map_t { + /* Name of the handle */ + char *map_name; + + /* Handle that the name corresponds to. Will be 0/NULL if there + is no corresponding back-end object. */ + mqs_taddr_t map_handle; +}; + +/* MPI attribute / value pairs. Include both a numeric and string + key; pre-defined MPI keyvals (e.g., MPI_TAG_MAX) have a + human-readable string name. The string will be NULL for + non-predefined keyvals. */ +struct mpidbg_attribute_pair_t { + /* Keyval */ + int keyval; + /* Keyval name; will be non-NULL for attributes that have a + human-readable name (e.g., MPI predefined keyvals) */ + char *keyval_name; + /* Value */ + char *value; +}; + +/*----------------------------------------------------------------------- + * Communicators + *-----------------------------------------------------------------------*/ + +/* Using an enum instead of #define because debuggers can show the + *names* of enum values, not just the values. */ +enum mpidbg_comm_capabilities_t { + /* Whether this MPI DLL supports returning basic information about + communicators */ + MPIDBG_COMM_CAP_BASIC = 0x01, + /* Whether this MPI DLL supports returning names of + communicators */ + MPIDBG_COMM_CAP_STRING_NAMES = 0x02, + /* Whether this MPI DLL supports indicating whether a communicator + has been freed by the user application */ + MPIDBG_COMM_CAP_FREED_HANDLE = 0x04, + /* Whether this MPI DLL supports indicating whether a communicator + object has been freed by the MPI implementation or not */ + MPIDBG_COMM_CAP_FREED_OBJECT = 0x08, + /* Whether this MPI DLL supports returning the list of MPI request + handles that are pending on a communicator */ + MPIDBG_COMM_CAP_REQUEST_LIST = 0x10, + /* Whether this MPI DLL supports returning the list of MPI window + handles that were derived from a given communicator */ + MPIDBG_COMM_CAP_WINDOW_LIST = 0x20, + /* Whether this MPI DLL supports returning the list of MPI file + handles that were derived from a given communicator */ + MPIDBG_COMM_CAP_FILE_LIST = 0x40, + /* Sentinel max value */ + MPIDBG_COMM_CAP_MAX +}; + +enum mpidbg_comm_info_bitmap_t { + /* Predefined communicator if set (user-defined if not set) */ + MPIDBG_COMM_INFO_PREDEFINED = 0x01, + /* Whether this communicator is a cartesian communicator or not + (mutually exclusive with _GRAPH and _INTERCOMM) */ + MPIDBG_COMM_INFO_CARTESIAN = 0x02, + /* Whether this communicator is a graph communicator or not + (mutually exclusive with _CARTESIAN and _INTERCOMM) */ + MPIDBG_COMM_INFO_GRAPH = 0x04, + /* If a cartesian or graph communicator, whether the processes in + this communicator were re-ordered when the topology was + assigned. */ + MPIDBG_COMM_INFO_TOPO_REORDERED = 0x08, + /* Whether this is an intercommunicator or not (this communicator + is an intracommunicator if this flag is not yet). */ + MPIDBG_COMM_INFO_INTERCOMM = 0x10, + /* This communicator has been marked for freeing by the user + application if set */ + MPIDBG_COMM_INFO_FREED_HANDLE = 0x20, + /* This communicator has actually been freed by the MPI + implementation if set */ + MPIDBG_COMM_INFO_FREED_OBJECT = 0x40, + /* The queried communicator is MPI_COMM_NULL */ + MPIDBG_COMM_INFO_COMM_NULL = 0x80, + /* Sentinel max value */ + MPIDBG_COMM_INFO_MAX +}; + +struct mpidbg_comm_info_t { + /* Name of the MPI_COMM */ + char comm_name[MPIDBG_MAX_OBJECT_NAME]; + + /* Bit flags describing the communicator */ + enum mpidbg_comm_info_bitmap_t comm_bitflags; + + /* This process' rank within this communicator */ + int comm_rank; + /* The communicator's size */ + int comm_size; + + /* Number of processes in the local group */ + int comm_num_local_procs; + /* Information about each process in the local group (in + communicator rank order, length: comm_num_local_procs) */ + struct mpidbg_process_t *comm_local_procs; + + /* For intercommunicators, the number of processes in the remote + group */ + int comm_num_remote_procs; + /* For intercommunicators, information about each process in the + remote group (in communicator rank order, length: + comm_num_remote_procs) */ + struct mpidbg_process_t *comm_remote_procs; + + /* For cartesian communicators, the number of dimensions */ + int comm_cart_num_dims; + /* For cartesian communicators, an array of dimension lengths + (length: cart_comm_num_dims) */ + int *comm_cart_dims; + /* For cartesian communicators, an array of boolean values + indicating whether each dimension is periodic or not (length: + cart_comm_num_dims) */ + int8_t *comm_cart_periods; + + /* For graph communicators, the number of nodes */ + int comm_graph_num_nodes; + /* For graph communicators, an array of the node degrees (length: + comm_graph_num_nodes) */ + int *comm_graph_index; + /* For graph communicators, an array of the edges (length: + comm_graph_num_nodes) */ + int *comm_graph_edges; + + /* C handle */ + mqs_taddr_t comm_c_handle; + /* Fortran handle; will be MPIDBG_ERR_UNAVAILABLE if currently + unavailable or MPIDBG_ERR_NOT_SUPPORTED if not supported */ + int comm_fortran_handle; + + /* Number of attributes defined on this communicator */ + int comm_num_attrs; + /* Array of attribute keyval/value pairs defined on this + communicator (length: comm_num_attrs) */ + struct mpidbg_attribute_pair_t *comm_attrs; + + /* Number of ongoing requests within this communicator, or + MPIDBG_ERR_NOT_SUPPORTED */ + int comm_num_pending_requests; + /* If comm_num_pending_requests != MPIDBG_ERR_NOT_SUPPORTED, an + array of ongoing request handles attached on this + communicator (length: comm_num_pending_requests) */ + mqs_taddr_t *comm_pending_requests; + + /* Number of MPI windows derived from this communicator, or + MPIDBG_ERR_NOT_SUPPORTED */ + int comm_num_derived_windows; + /* If comm_num_derived_windows != MPIDBG_ERR_NOT_SUPPORTED, an + array of window handles derived from this communicator (length: + com_num_derived_windows) */ + mqs_taddr_t *comm_derived_windows; + + /* Number of MPI files derived from this communicator, or + MPIDBG_ERR_NOT_SUPPORTED */ + int comm_num_derived_files; + /* If comm_num_derived_files != MPIDBG_ERR_NOT_SUPPORTED, an array + of file handles derived from this communicator (length: + comm_num_derived_files) */ + mqs_taddr_t *comm_derived_files; +}; + + +/*----------------------------------------------------------------------- + * Requests + *-----------------------------------------------------------------------*/ + +/* Using an enum instead of #define because debuggers can show the + *names* of enum values, not just the values. */ +enum mpidbg_request_capabilities_t { + /* Whether this MPI DLL supports returning basic information about + requests */ + MPIDBG_REQUEST_CAP_BASIC = 0x01, + /* Sentinel max value */ + MPIDBG_REQUEST_CAP_MAX +}; + +enum mpidbg_request_info_bitmap_t { + /* Predefined request if set (user-defined if not set) */ + MPIDBG_REQUEST_INFO_PREDEFINED = 0x01, + /* Sentinel max value */ + MPIDBG_REQUEST_INFO_MAX +}; + +struct mpidbg_request_info_t { + /* Bit flags describing the error handler */ + enum mpidbg_request_info_bitmap_t req_bitflags; + + /* C handle */ + mqs_taddr_t req_c_handle; + /* Fortran handle; will be MPIDBG_ERR_UNAVAILABLE if currently + unavailable or MPIDBG_ERR_NOT_SUPPORTED if not supported */ + int req_fortran_handle; +}; + +/*----------------------------------------------------------------------- + * Statuses + *-----------------------------------------------------------------------*/ + +enum mpidbg_status_capabilities_t { + /* Whether this MPI DLL supports returning basic information about + statuses */ + MPIDBG_STATUS_CAP_BASIC = 0x01, + /* Sentinel max value */ + MPIDBG_STATUS_CAP_MAX +}; + +enum mpidbg_status_info_bitmap_t { + /* Predefined status if set (user-defined if not set) */ + MPIDBG_STATUS_INFO_PREDEFINED = 0x01, + /* Sentinel max value */ + MPIDBG_STATUS_INFO_MAX +}; + +struct mpidbg_status_info_t { + /* Bit flags describing the error handler */ + enum mpidbg_status_info_bitmap_t status_bitflags; +}; + +/*----------------------------------------------------------------------- + * Error handlers + *-----------------------------------------------------------------------*/ + +/* Using an enum instead of #define because debuggers can show the + *names* of enum values, not just the values. */ +enum mpidbg_errhandler_capabilities_t { + /* Whether this MPI DLL supports returning basic information about + error handlers */ + MPIDBG_ERRH_CAP_BASIC = 0x01, + /* Whether this MPI DLL supports returning names of the predefined + error handlers */ + MPIDBG_ERRH_CAP_STRING_NAMES = 0x02, + /* Whether this MPI DLL supports indicating whether an error + handler has been freed by the user application */ + MPIDBG_ERRH_CAP_FREED_HANDLE = 0x04, + /* Whether this MPI DLL supports indicating whether an error + handler object has been freed by the MPI implementation or + not */ + MPIDBG_ERRH_CAP_FREED_OBJECT = 0x08, + /* Whether this MPI DLL supports returning the list of MPI handles + that an MPI error handler is attached to */ + MPIDBG_ERRH_CAP_HANDLE_LIST = 0x10, + /* Sentinel max value */ + MPIDBG_ERRH_CAP_MAX +}; + +enum mpidbg_errhandler_info_bitmap_t { + /* Predefined error handler if set (user-defined if not set) */ + MPIDBG_ERRH_INFO_PREDEFINED = 0x01, + /* Communicator error handler if set */ + MPIDBG_ERRH_INFO_COMMUNICATOR = 0x02, + /* File error handler if set */ + MPIDBG_ERRH_INFO_FILE = 0x04, + /* Window error handler if set */ + MPIDBG_ERRH_INFO_WINDOW = 0x08, + /* Callback is in C if set (Fortran if not set) */ + MPIDBG_ERRH_INFO_C_CALLBACK = 0x10, + /* This errorhandler has been marked for freeing by the user + application if set */ + MPIDBG_ERRH_INFO_FREED_HANDLE = 0x20, + /* This errorhandler has actually been freed by the MPI + implementation if set */ + MPIDBG_ERRH_INFO_FREED_OBJECT = 0x40, + /* Sentinel max value */ + MPIDBG_ERRH_INFO_MAX +}; + +struct mpidbg_errhandler_info_t { + /* String name; only relevant for predefined errorhandlers. If + not a predefined errorhandler, eh_name[0] will be '\0'; */ + char eh_name[MPIDBG_MAX_OBJECT_NAME]; + + /* Bit flags describing the error handler */ + enum mpidbg_errhandler_info_bitmap_t eh_bitflags; + + /* C handle */ + mqs_taddr_t eh_c_handle; + /* Fortran handle; will be MPIDBG_ERR_UNAVAILABLE if currently + unavailable or MPIDBG_ERR_NOT_SUPPORTED if not supported */ + int eh_fortran_handle; + + /* Number of MPI handles that this error handler is attached to. + MPIDBG_ERR_NOT_SUPPORTED means that this information is not + supported by the DLL. */ + int16_t eh_refcount; + /* If eh_refcount != MPIDBG_ERR_NOT_SUPPORTED, list of handles + that are using this error handler (length: eh_refcount). */ + mqs_taddr_t *eh_handles; + + /* Address of the user-defined error handler (will be 0 for + predefined error handlers). Note that each of the 3 C + callbacks contain an MPI handle; the debugger will need to + figure out the appropriate size for these types depending on + the platform and MPI implementation. This value will be NULL + if MPIDBG_ERRH_INFO_PREDEFINED is set on the flags. */ + mqs_taddr_t eh_callback_func; +}; + +/************************************************************************** + * Global variables + * + * mpidbg_dll_locations is in the MPI application; all others are in + * the DLL. + **************************************************************************/ + +/* Array of filenames instantiated IN THE MPI APPLICATION (*NOT* in + the DLL) that provides an set of locations where DLLs may be found. + The last pointer in the array will be a NULL sentinel value. The + debugger can scan the entries in the array, find one that matches + the debugger (by examining a) whether the dlopen works or not, and + b) if the dlopen succeeds, examine mpidbg_dll_is_big_endian and + mpidbg_dll_bitness), and try to dynamically open the dl_filename. + Notes: + + 1. It is not an error if a dl_filename either does not exist or is + otherwise un-openable (the debugger can just try the next + match). + 2. This array values are not valid until MPIR_Breakpoint. + 3. If a filename is absolute, the debugger will attempt to load + exactly that. If the filename is relative, the debugger may try + a few prefix variations to find the DLL. + */ +extern char **mpidbg_dll_locations; + +/* Global variable *in the DLL* describing whether this DLL is big or + little endian (1 = big endian, 0 = little endian). This value is + valid immediately upon opening of the DLL. */ +extern char mpidbg_dll_is_big_endian; + +/* Global variable *in the DLL* describing the bitness of the DLL (8, + 16, 32, 64, ...). This value is valid immediately upon opening of + the DLL. */ +extern char mpidbg_dll_bitness; + +/* Global variable *in the DLL* describing the DLL's capabilties with + regards to communicators. This value is valid after a successfull + call to mpidbg_init_per_process(). */ +extern enum mpidbg_comm_capabilities_t mpidbg_comm_capabilities; + +/* Global variable *in the DLL* that is an array of MPI communicator + handle names -> handle mappings (the last entry in the array is + marked by a NULL string value). For example, MPI_COMM_WORLD may + not appear as a symbol in an MPI process, but the debugger needs to + be able to map this name to a valid handle. MPI implementations + not requiring this mapping can either have a NULL value for this + variable or have a single entry that has a NULL string value. This + variable is not valid until after a successfull call to + mpidbg_init_per_process(). */ +extern struct mpidbg_name_map_t *mpidbg_comm_name_map; + +/* Global variable *in the DLL* describing the DLL's capabilties with + regards to error handlers. This value is valid after a successfull + call to mpidbg_init_per_process(). */ +extern enum mpidbg_errhandler_capabilities_t mpidbg_errhandler_capabilities; + +/* Global variable *in the DLL* that is an array of MPI error handler + handle names -> handle mappings. It is analogous to + mpidbg_comm_name_map; see above for details. */ +extern struct mpidbg_name_map_t *mpidbg_errhandler_name_map; + +/************************************************************************** + * Functions + **************************************************************************/ + +/*----------------------------------------------------------------------- + * DLL infrastructure functions + *-----------------------------------------------------------------------*/ + +/* This function must be called once before any other mpidbg_*() + function is called, and before any other global mpidbg_* data is + read. It is only necessary to call this function once for a given + debugger instantiation. This function will initialize all mpidbg + global state, to include setting all relevant global capability + flags. + + Parameters: + + IN: callbacks: Table of pointers to the debugger functions. The DLL + need only save the pointer, the debugger promises to + maintain the table of functions valid for as long as + needed. The table remains the property of the + debugger, and should not be altered or deallocated + by the DLL. This applies to all of the callback + tables. + + This function will return: + + MPIDBG_SUCCESS: if all initialization went well + MPIDBG_ERR_*: if something went wrong. +*/ +int mpidbg_init_once(const mqs_basic_callbacks *callbacks); + +/*-----------------------------------------------------------------------*/ + +/* Query the DLL to find out what version of the interface it + supports. + + Parameters: + + None. + + This function will return: + + MPIDBG_INTERFACE_VERSION +*/ + +int mpidbg_interface_version_compatibility(void); + +/*-----------------------------------------------------------------------*/ + +/* Returns a string describing this DLL. + + Parameters: + + None + + This function will return: + + A null-terminated string describing this DLL. +*/ +char *mpidbg_version_string(void); + +/*-----------------------------------------------------------------------*/ + +/* Returns the address width that this DLL was compiled with. + + Parameters: + + None + + This function will return: + + sizeof(mqs_taddr_t) +*/ + +int mpidbg_dll_taddr_width(void); + +/*-----------------------------------------------------------------------*/ + +/* Setup debug information for a specific image, this must save the + callbacks (probably in the mqs_image_info), and use those functions + for accessing this image. + + The DLL should use the mqs_put_image_info and mqs_get_image_info + functions to associate whatever information it wants to keep with + the image. (For instance all of the type offsets it needs could be + kept here). the debugger will call mqs_destroy_image_info when it + no longer wants to keep information about the given executable. + + This will be called once for each executable image in the parallel + program. + + Parameters: + + IN: image: the application image. + IN: callbacks: Table of pointers to the debugger image-specific + functions. The DLL need only save the pointer, the + debugger promises to maintain the table of functions + valid for as long as needed. The table remains the + property of the debugger, and should not be altered + or deallocated by the DLL. This applies to all of + the callback tables. + IN/OUT: handle_types: a pointer to a pre-allocated struct + containing mqs_types for each of the MPI handle types. + Must be filled in with results from mqs_find_type for each + MPI handle type. + + This function will return: + + MPIDBG_SUCCESS: if all initialization went well + MPIDBG_ERR_NOT_SUPPORTED: if the image does not support the MPIDBG + interface. In this case, no other mpidbg functions + will be invoked on this image (not even + mpidbg_finalize_per_image()). + MPIDBG_ERR_*: if something went wrong. +*/ +int mpidbg_init_per_image(mqs_image *image, + const mqs_image_callbacks *callbacks, + struct mpidbg_handle_info_t *handle_types); + +/* This function will be called once when an application image that + previously had mpidbg_init_per_image() successfully invoked that is + now ending (e.g., the debugger is exiting, the debugger has + unloaded this image, etc.). This function can be used to clean up + any image-specific data. + + Parameters: + + IN: image: the application image. + IN: image_info: the info associated with the application image. +*/ +void mpidbg_finalize_per_image(mqs_image *image, mqs_image_info *image_info); + +/*-----------------------------------------------------------------------*/ + +/* This function will only be called if mpidbg_init_per_image() + returned successfully, indicating that the image contains + information for MPI handle information. If you cannot tell whether + a process will have MPI handle information in it by examining the + image, you should return SUCCESS from mpidbg_init_per_image() and + use this function to check whether MPI handle information is + available in the process. + + Set up whatever process specific information we need. For instance + addresses of global variables should be handled here rather than in + the image information, because if data may be in dynamic libraries + which could end up mapped differently in different processes. + + Note that certain global variables are not valid until after this + call completes successfully (see above; e.g., + mpidbg_comm_capabilities, mpidbg_comm_name_mapping, etc.). + + Parameters: + + IN: process: the process + IN: callbacks: Table of pointers to the debugger process-specific + functions. The DLL need only save the pointer, the + debugger promises to maintain the table of functions + valid for as long as needed. The table remains the + property of the debugger, and should not be altered + or deallocated by the DLL. This applies to all of + the callback tables. + IN/OUT: handle_types: the same handle_types that was passed to + mqs_init_per_image. It can be left unaltered if the + results from mqs_init_per_image were sufficient, or + modified if necessary to be specific to this process. + + This function will return: + + MPIDBG_SUCCESS: if all initialization went well + MPIDBG_ERR_NOT_SUPPORTED: if the process does not support the MPIDBG + interface. In this case, no other mpidbg functions + will be invoked on this image (not even + mpidbg_finalize_per_process()). + MPIDBG_ERR_*: if something went wrong. +*/ +int mpidbg_init_per_process(mqs_process *process, + const mqs_process_callbacks *callbacks, + struct mpidbg_handle_info_t *handle_types); + +/* This function will be called once when an application image that + previously had mpidbg_init_per_process() successfully invoked that + is now ending (e.g., the debugger is exiting, the debugger has + stopped executing this process, etc.). This function can be used + to clean up any process-specific data. + + Parameters: + + IN: process: the application process. + IN: process_info: the info associated with the application process. +*/ +void mpidbg_finalize_per_process(mqs_process *process, + mqs_process_info *process_info); + +/*----------------------------------------------------------------------- + * MPI handle query functions + * MPI_Comm + *-----------------------------------------------------------------------*/ + +/* Query a specific MPI_Comm handle and, if found and valid, allocate + a new instance of the mpidbg_comm_info_t struct and all of its + internal data, and fill it in with information about the underlying + corresponding MPI communicator object. + + Parameters: + + IN: image: image + IN: image_info: image info that was previously "put" + IN: process: process + IN: process_info: process info that was previously "put" + IN: comm: communicator handle + OUT: info: pointer to be filled with a newly-allocated struct + mpidbg_comm_info_t + + This function will return: + + MPIDBG_SUCCESS: if the handle is valid, was found, and the info + parameter was filled in successfully. + MPIDBG_ERR_NOT_FOUND: if the handle is not valid / found. + MPIDBG_ERR_UNSUPPORTED: if this function is unsupported. +*/ +int mpidbg_comm_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t c_comm, struct mpidbg_comm_info_t **info); + +/* Query function to turn a Fortran INTEGER handle into its equivalent + C handle (that can then be queried with mpidbg_comm_query()). + mqs_taddr_t is used in order to guarantee to be large enough to + hold a Fortran INTEGER. + + Parameters: + + IN: image: image + IN: image_info: image info that was previously "put" + IN: process: process + IN: process_info: process info that was previously "put" + IN: f77_comm: a zero-padded Fortran integer containing the Fortran + handle of the communicator. + OUT: c_comm: a C handle suitable to pass to mpidbg_comm_query(). + + This function returns: + + MPIDBG_SUCCESS: if the handle is valid, was found, and the c_comm + parameter was filled in successfully. + MPIDBG_ERR_NOT_FOUND: if the handle is not valid / found. + MPIDBG_ERR_UNSUPPORTED: if this function is unsupported. +*/ +int mpidbg_comm_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_comm, mqs_taddr_t *c_comm); + +/* Query function to turn a C++ handle into its equivalent C handle + (that can then be queried with mpidbg_comm_query()). Pass the + pointer to the object as the cxx_comm (because we can't pass the + object itself); we return the C handle. + + --> JMS Need more discussion here -- George has some opinion. He + thinks we don't need this. + Parameters: + + IN: image: image + IN: image_info: image info that was previously "put" + IN: process: process + IN: process_info: process info that was previously "put" + IN: cxx_comm: a pointer to the MPI handle object + IN: comm_type: one of 0, MPIDBG_COMM_INFO_CARTESION, + MPIDBG_COMM_INFO_GRAPH, or + MPIDBG_COMM_INFO_INTERCOMM indicating whether the + object is an MPI::Comm, MPI::Cartcomm, + MPI::Graphcomm, or MPI::Intercomm. + OUT: c_comm: a C handle suitable to pass to mpidbg_comm_query(). + + This function returns: + + MPIDBG_SUCCESS: if the handle is valid, was found, and the c_comm + parameter was filled in successfully. + MPIDBG_ERR_NOT_FOUND: if the handle is not valid / found. + MPIDBG_ERR_UNSUPPORTED: if this function is unsupported. +*/ +int mpidbg_comm_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_comm, + enum mpidbg_comm_info_bitmap_t comm_type, + mqs_taddr_t *c_comm); + +/*----------------------------------------------------------------------- + * MPI handle query functions + * MPI_Errhandler + *-----------------------------------------------------------------------*/ + +/* These functions are analogous to the mpidbg_comm_* functions, but + for MPI_Errhandler. Note that there is no need for a + "errhandler_type" argument to the cxx2c function because + MPI::Errhandler has no derived classes. */ + +int mpidbg_errhandler_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t errhandler, + struct mpidbg_errhandler_info_t **info); +int mpidbg_errhandler_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_errhandler, + mqs_taddr_t *c_errhandler); +int mpidbg_errhandler_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_errhandler, + mqs_taddr_t *c_errhandler); + +/*----------------------------------------------------------------------- + * MPI handle query functions + * MPI_Request + *-----------------------------------------------------------------------*/ + +/* These functions are analogous to the mpidbg_comm_* functions, but + for MPI_Request. */ + +int mpidbg_request_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t request, + struct mpidbg_request_info_t **info); +int mpidbg_request_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_request, mqs_taddr_t *c_request); +int mpidbg_request_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_request, + enum mpidbg_request_info_bitmap_t request_type, + mqs_taddr_t *c_request); + +/*----------------------------------------------------------------------- + * MPI handle query functions + * MPI_Status + *-----------------------------------------------------------------------*/ + +/* These functions are analogous to the mpidbg_comm_* functions, but + for MPI_Status. */ + +int mpidbg_status_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t status, + struct mpidbg_status_info_t **info); +int mpidbg_status_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_status, mqs_taddr_t *c_status); +int mpidbg_status_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_status, + mqs_taddr_t *c_status); + +#endif /* __MPIDBG_INTERFACE_H__ */ diff --git a/ompi/debuggers/mpi_interface.h b/ompi/debuggers/msgq_interface.h similarity index 94% rename from ompi/debuggers/mpi_interface.h rename to ompi/debuggers/msgq_interface.h index 5a59b167f0..55b21f0bc8 100644 --- a/ompi/debuggers/mpi_interface.h +++ b/ompi/debuggers/msgq_interface.h @@ -1,3 +1,15 @@ +/* + * Copyright (c) 2007 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + /* $Header: /home/tv/src/mpi/src/mpi_interface.h,v 1.13 2003/03/12 14:03:42 jcownie Exp $ */ /* $Locker: $ */ @@ -108,6 +120,9 @@ #include /* For FILENAME_MAX */ +/* No MPI2 support yet */ +#define FOR_MPI2 0 + #ifdef __cplusplus extern "C" { #endif @@ -256,6 +271,68 @@ enum mqs_status mqs_st_pending, mqs_st_matched, mqs_st_complete }; +/* Additional error codes and error string conversion. */ +enum { + err_silent_failure = mqs_first_user_code, + + err_no_current_communicator, + err_bad_request, + err_no_store, + + err_failed_qhdr, + err_unexpected, + err_posted, + + err_failed_queue, + err_first, + + err_context_id, + err_tag, + err_tagmask, + err_lsrc, + err_srcmask, + err_next, + err_ptr, + + err_missing_type, + err_missing_symbol, + + err_db_shandle, + err_db_comm, + err_db_target, + err_db_tag, + err_db_data, + err_db_byte_length, + err_db_next, + + err_failed_rhandle, + err_is_complete, + err_buf, + err_len, + err_s, + + err_failed_status, + err_count, + err_MPI_SOURCE, + err_MPI_TAG, + + err_failed_commlist, + err_sequence_number, + err_comm_first, + + err_failed_communicator, + err_lrank_to_grank, + err_send_context, + err_recv_context, + err_comm_next, + err_comm_name, + + err_all_communicators, + err_mpid_sends, + err_mpid_recvs, + err_group_corrupt +}; + /* A structure to represent a communicator */ typedef struct { diff --git a/ompi/debuggers/ompi_common_dll.c b/ompi/debuggers/ompi_common_dll.c new file mode 100644 index 0000000000..5146cb775b --- /dev/null +++ b/ompi/debuggers/ompi_common_dll.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2007-2008 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +/********************************************************************** + * Copyright (C) 2000-2004 by Etnus, LLC. + * Copyright (C) 1999 by Etnus, Inc. + * Copyright (C) 1997-1998 Dolphin Interconnect Solutions Inc. + * + * Permission is hereby granted to use, reproduce, prepare derivative + * works, and to redistribute to others. + * + * DISCLAIMER + * + * Neither Dolphin Interconnect Solutions, Etnus LLC, nor any of their + * employees, makes any warranty express or implied, or assumes any + * legal liability or responsibility for the accuracy, completeness, + * or usefulness of any information, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately + * owned rights. + * + * This code was written by + * James Cownie: Dolphin Interconnect Solutions. + * Etnus LLC + **********************************************************************/ + +#include "ompi_config.h" + +#include "ompi_common_dll_defs.h" + +/* Basic callbacks into the debugger */ +const mqs_basic_callbacks *mqs_basic_entrypoints; + +#if defined(WORDS_BIGENDIAN) +static int host_is_big_endian = 1; +#else +static int host_is_big_endian = 0; +#endif + +/* + * Open MPI use a bunch of lists in order to keep track of the + * internal objects. We have to make sure we're able to find all of + * them in the image and compute their ofset in order to be able to + * parse them later. We need to find the opal_list_item_t, the + * opal_list_t, the ompi_free_list_item_t, and the ompi_free_list_t. + * + * Once we have these offsets, we should make sure that we have access + * to all requests lists and types. We're looking here only at the + * basic type for the requests as they hold all the information we + * need to export to the debugger. + */ +int ompi_fill_in_type_info(mqs_image *image, char **message) +{ + char* missing_in_action; + mpi_image_info * i_info = (mpi_image_info *)mqs_get_image_info (image); + + { + mqs_type* qh_type = mqs_find_type( image, "opal_list_item_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "opal_list_item_t"; + goto type_missing; + } + i_info->opal_list_item_t.type = qh_type; + i_info->opal_list_item_t.size = mqs_sizeof(qh_type); + i_info->opal_list_item_t.offset.opal_list_next = mqs_field_offset(qh_type, "opal_list_next"); + } + { + mqs_type* qh_type = mqs_find_type( image, "opal_list_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "opal_list_t"; + goto type_missing; + } + i_info->opal_list_t.type = qh_type; + i_info->opal_list_t.size = mqs_sizeof(qh_type); + i_info->opal_list_t.offset.opal_list_sentinel = mqs_field_offset(qh_type, "opal_list_sentinel"); + } + { + mqs_type* qh_type = mqs_find_type( image, "ompi_free_list_item_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_free_list_item_t"; + goto type_missing; + } + /* This is just an overloaded opal_list_item_t */ + i_info->ompi_free_list_item_t.type = qh_type; + i_info->ompi_free_list_item_t.size = mqs_sizeof(qh_type); + } + { + mqs_type* qh_type = mqs_find_type( image, "ompi_free_list_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_free_list_t"; + goto type_missing; + } + i_info->ompi_free_list_t.type = qh_type; + i_info->ompi_free_list_t.size = mqs_sizeof(qh_type); + i_info->ompi_free_list_t.offset.fl_elem_class = mqs_field_offset(qh_type, "fl_elem_class"); + i_info->ompi_free_list_t.offset.fl_mpool = mqs_field_offset(qh_type, "fl_mpool"); + i_info->ompi_free_list_t.offset.fl_elem_size = mqs_field_offset(qh_type, "fl_elem_size"); + i_info->ompi_free_list_t.offset.fl_alignment = mqs_field_offset(qh_type, "fl_alignment"); + i_info->ompi_free_list_t.offset.fl_allocations = mqs_field_offset(qh_type, "fl_allocations"); + i_info->ompi_free_list_t.offset.fl_max_to_alloc = mqs_field_offset(qh_type, "fl_max_to_alloc"); + i_info->ompi_free_list_t.offset.fl_num_per_alloc = mqs_field_offset(qh_type, "fl_num_per_alloc"); + i_info->ompi_free_list_t.offset.fl_num_allocated = mqs_field_offset(qh_type, "fl_num_allocated"); + } + { + mqs_type* qh_type = mqs_find_type( image, "opal_hash_table_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "opal_hash_table_t"; + goto type_missing; + } + i_info->opal_hash_table_t.type = qh_type; + i_info->opal_hash_table_t.size = mqs_sizeof(qh_type); + i_info->opal_hash_table_t.offset.ht_table = mqs_field_offset(qh_type, "ht_table"); + i_info->opal_hash_table_t.offset.ht_table_size = mqs_field_offset(qh_type, "ht_table_size"); + i_info->opal_hash_table_t.offset.ht_size = mqs_field_offset(qh_type, "ht_size"); + i_info->opal_hash_table_t.offset.ht_mask = mqs_field_offset(qh_type, "ht_mask"); + } + /* + * Now let's look for all types required for reading the requests. + */ + { + mqs_type* qh_type = mqs_find_type( image, "ompi_request_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_request_t"; + goto type_missing; + } + i_info->ompi_request_t.type = qh_type; + i_info->ompi_request_t.size = mqs_sizeof(qh_type); + i_info->ompi_request_t.offset.req_type = mqs_field_offset(qh_type, "req_type"); + i_info->ompi_request_t.offset.req_status = mqs_field_offset(qh_type, "req_status"); + i_info->ompi_request_t.offset.req_complete = mqs_field_offset(qh_type, "req_complete"); + i_info->ompi_request_t.offset.req_state = mqs_field_offset(qh_type, "req_state"); + i_info->ompi_request_t.offset.req_f_to_c_index = mqs_field_offset(qh_type, "req_f_to_c_index"); + } + { + mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_request_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_pml_base_request_t"; + goto type_missing; + } + i_info->mca_pml_base_request_t.type = qh_type; + i_info->mca_pml_base_request_t.size = mqs_sizeof(qh_type); + i_info->mca_pml_base_request_t.offset.req_addr = mqs_field_offset(qh_type, "req_addr"); + i_info->mca_pml_base_request_t.offset.req_count = mqs_field_offset(qh_type, "req_count"); + i_info->mca_pml_base_request_t.offset.req_peer = mqs_field_offset(qh_type, "req_peer"); + i_info->mca_pml_base_request_t.offset.req_tag = mqs_field_offset(qh_type, "req_tag"); + i_info->mca_pml_base_request_t.offset.req_comm = mqs_field_offset(qh_type, "req_comm"); + i_info->mca_pml_base_request_t.offset.req_datatype = mqs_field_offset(qh_type, "req_datatype"); + i_info->mca_pml_base_request_t.offset.req_proc = mqs_field_offset(qh_type, "req_proc"); + i_info->mca_pml_base_request_t.offset.req_sequence = mqs_field_offset(qh_type, "req_sequence"); + i_info->mca_pml_base_request_t.offset.req_type = mqs_field_offset(qh_type, "req_type"); + i_info->mca_pml_base_request_t.offset.req_pml_complete = mqs_field_offset(qh_type, "req_pml_complete"); + } + { + mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_send_request_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_pml_base_send_request_t"; + goto type_missing; + } + i_info->mca_pml_base_send_request_t.type = qh_type; + i_info->mca_pml_base_send_request_t.size = mqs_sizeof(qh_type); + i_info->mca_pml_base_send_request_t.offset.req_addr = mqs_field_offset(qh_type, "req_addr"); + i_info->mca_pml_base_send_request_t.offset.req_bytes_packed = mqs_field_offset(qh_type, "req_bytes_packed"); + i_info->mca_pml_base_send_request_t.offset.req_send_mode = mqs_field_offset(qh_type, "req_send_mode"); + } + { + mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_recv_request_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_pml_base_recv_request_t"; + goto type_missing; + } + i_info->mca_pml_base_recv_request_t.type = qh_type; + i_info->mca_pml_base_recv_request_t.size = mqs_sizeof(qh_type); + i_info->mca_pml_base_recv_request_t.offset.req_bytes_packed = mqs_field_offset(qh_type, "req_bytes_packed"); + } + /* + * Gather information about the received fragments and theirs headers. + */ +#if 0 /* Disabled until I find a better way */ + { + mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_common_hdr_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_pml_ob1_common_hdr_t"; + goto type_missing; + } + i_info->mca_pml_ob1_common_hdr_t.type = qh_type; + i_info->mca_pml_ob1_common_hdr_t.size = mqs_sizeof(qh_type); + i_info->mca_pml_ob1_common_hdr_t.offset.hdr_type = mqs_field_offset(qh_type, "hdr_type"); + i_info->mca_pml_ob1_common_hdr_t.offset.hdr_flags = mqs_field_offset(qh_type, "hdr_flags"); + } + { + mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_match_hdr_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_pml_ob1_match_hdr_t"; + goto type_missing; + } + i_info->mca_pml_ob1_match_hdr_t.type = qh_type; + i_info->mca_pml_ob1_match_hdr_t.size = mqs_sizeof(qh_type); + i_info->mca_pml_ob1_match_hdr_t.offset.hdr_common = mqs_field_offset(qh_type, "hdr_common"); + i_info->mca_pml_ob1_match_hdr_t.offset.hdr_ctx = mqs_field_offset(qh_type, "hdr_ctx"); + i_info->mca_pml_ob1_match_hdr_t.offset.hdr_src = mqs_field_offset(qh_type, "hdr_src"); + i_info->mca_pml_ob1_match_hdr_t.offset.hdr_tag = mqs_field_offset(qh_type, "hdr_tag"); + i_info->mca_pml_ob1_match_hdr_t.offset.hdr_seq = mqs_field_offset(qh_type, "hdr_seq"); + } + { + mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_recv_frag_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_pml_ob1_recv_frag_t"; + goto type_missing; + } + i_info->mca_pml_ob1_recv_frag_t.type = qh_type; + i_info->mca_pml_ob1_recv_frag_t.size = mqs_sizeof(qh_type); + i_info->mca_pml_ob1_recv_frag_t.offset.hdr = mqs_field_offset(qh_type, "hdr"); + i_info->mca_pml_ob1_recv_frag_t.offset.request = mqs_field_offset(qh_type, "request"); + } +#endif + /* + * And now let's look at the communicator and group structures. + */ + { + mqs_type* qh_type = mqs_find_type( image, "opal_pointer_array_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "opal_pointer_array_t"; + goto type_missing; + } + i_info->opal_pointer_array_t.type = qh_type; + i_info->opal_pointer_array_t.size = mqs_sizeof(qh_type); + i_info->opal_pointer_array_t.offset.lowest_free = mqs_field_offset(qh_type, "lowest_free"); + i_info->opal_pointer_array_t.offset.number_free = mqs_field_offset(qh_type, "number_free"); + i_info->opal_pointer_array_t.offset.size = mqs_field_offset(qh_type, "size"); + i_info->opal_pointer_array_t.offset.addr = mqs_field_offset(qh_type, "addr"); + } + { + mqs_type* qh_type = mqs_find_type( image, "ompi_communicator_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_communicator_t"; + goto type_missing; + } + i_info->ompi_communicator_t.type = qh_type; + i_info->ompi_communicator_t.size = mqs_sizeof(qh_type); + i_info->ompi_communicator_t.offset.c_name = mqs_field_offset(qh_type, "c_name"); + i_info->ompi_communicator_t.offset.c_contextid = mqs_field_offset(qh_type, "c_contextid"); + i_info->ompi_communicator_t.offset.c_my_rank = mqs_field_offset(qh_type, "c_my_rank" ); + i_info->ompi_communicator_t.offset.c_local_group = mqs_field_offset(qh_type, "c_local_group" ); + i_info->ompi_communicator_t.offset.c_remote_group = mqs_field_offset(qh_type, "c_remote_group" ); + i_info->ompi_communicator_t.offset.c_flags = mqs_field_offset(qh_type, "c_flags" ); + + i_info->ompi_communicator_t.offset.c_f_to_c_index = mqs_field_offset(qh_type, "c_f_to_c_index" ); + + i_info->ompi_communicator_t.offset.c_topo_comm = mqs_field_offset(qh_type, "c_topo_comm" ); + i_info->ompi_communicator_t.offset.c_keyhash = mqs_field_offset(qh_type, "c_keyhash" ); + } + { + mqs_type* qh_type = mqs_find_type( image, "mca_topo_base_comm_1_0_0_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "mca_topo_base_comm_1_0_0_t"; + goto type_missing; + } + i_info->ompi_mca_topo_base_comm_1_0_0_t.type = qh_type; + i_info->ompi_mca_topo_base_comm_1_0_0_t.size = mqs_sizeof(qh_type); + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_ndims_or_nnodes = + mqs_field_offset(qh_type, "mtc_ndims_or_nnodes"); + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_dims_or_index = + mqs_field_offset(qh_type, "mtc_dims_or_index"); + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_periods_or_edges = + mqs_field_offset(qh_type, "mtc_periods_or_edges" ); + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_reorder = + mqs_field_offset(qh_type, "mtc_reorder" ); + } + { + mqs_type* qh_type = mqs_find_type( image, "ompi_group_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_group_t"; + goto type_missing; + } + i_info->ompi_group_t.type = qh_type; + i_info->ompi_group_t.size = mqs_sizeof(qh_type); + i_info->ompi_group_t.offset.grp_proc_count = mqs_field_offset(qh_type, "grp_proc_count"); + i_info->ompi_group_t.offset.grp_my_rank = mqs_field_offset(qh_type, "grp_my_rank"); + i_info->ompi_group_t.offset.grp_flags = mqs_field_offset(qh_type, "grp_flags" ); + } + { + mqs_type* qh_type = mqs_find_type( image, "ompi_status_public_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_status_public_t"; + goto type_missing; + } + i_info->ompi_status_public_t.type = qh_type; + i_info->ompi_status_public_t.size = mqs_sizeof(qh_type); + i_info->ompi_status_public_t.offset.MPI_SOURCE = mqs_field_offset(qh_type, "MPI_SOURCE"); + i_info->ompi_status_public_t.offset.MPI_TAG = mqs_field_offset(qh_type, "MPI_TAG"); + i_info->ompi_status_public_t.offset.MPI_ERROR = mqs_field_offset(qh_type, "MPI_ERROR" ); + i_info->ompi_status_public_t.offset._count = mqs_field_offset(qh_type, "_count" ); + i_info->ompi_status_public_t.offset._cancelled = mqs_field_offset(qh_type, "_cancelled" ); + } + { + mqs_type* qh_type = mqs_find_type( image, "ompi_datatype_t", mqs_lang_c ); + if( !qh_type ) { + missing_in_action = "ompi_datatype_t"; + goto type_missing; + } + i_info->ompi_datatype_t.type = qh_type; + i_info->ompi_datatype_t.size = mqs_sizeof(qh_type); + i_info->ompi_datatype_t.offset.size = mqs_field_offset(qh_type, "size"); + i_info->ompi_datatype_t.offset.name = mqs_field_offset(qh_type, "name"); + } + + /* All the types are here. Let's succesfully return. */ + return mqs_ok; + + type_missing: + /* + * One of the required types is missing in the image. We are + * unable to extract the information we need from the pointers. We + * did our best but here we're at our limit. Give up! + */ + *message = missing_in_action; + printf( "The following type is missing %s\n", missing_in_action ); + return err_missing_type; +} + +/*********************************************************************** + * Functions to access the image memory. They are specialized based * + * on the type we want to access and the debugged process architecture * + ***********************************************************************/ +mqs_taddr_t ompi_fetch_pointer (mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info) +{ + int isize = p_info->sizes.pointer_size; + char buffer[8]; /* ASSUME the type fits in 8 bytes */ + mqs_taddr_t res = 0; + + if (mqs_ok == mqs_fetch_data (proc, addr, isize, buffer)) + mqs_target_to_host (proc, buffer, + ((char *)&res) + (host_is_big_endian ? sizeof(mqs_taddr_t)-isize : 0), + isize); + + return res; +} /* fetch_pointer */ + +/***********************************************************************/ +mqs_tword_t ompi_fetch_int (mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info) +{ + int isize = p_info->sizes.int_size; + char buffer[8]; /* ASSUME the type fits in 8 bytes */ + mqs_tword_t res = 0; + + if (mqs_ok == mqs_fetch_data (proc, addr, isize, buffer)) { + mqs_target_to_host (proc, buffer, + ((char *)&res) + (host_is_big_endian ? sizeof(mqs_tword_t)-isize : 0), + isize); + } + return res; +} /* fetch_int */ + +/***********************************************************************/ +mqs_tword_t ompi_fetch_bool(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info) +{ + int isize = p_info->sizes.bool_size; + mqs_tword_t res = 0; + + mqs_fetch_data (proc, addr, isize, &res); + return (0 == res ? 0 : 1); +} /* fetch_bool */ + +/***********************************************************************/ +mqs_taddr_t ompi_fetch_size_t(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info) +{ + int isize = p_info->sizes.size_t_size; + char buffer[8]; /* ASSUME the type fits in 8 bytes */ + mqs_taddr_t res = 0; + + if (mqs_ok == mqs_fetch_data (proc, addr, isize, buffer)) + mqs_target_to_host (proc, buffer, + ((char *)&res) + (host_is_big_endian ? sizeof(mqs_taddr_t)-isize : 0), + isize); + + return res; +} /* fetch_size_t */ + +/***********************************************************************/ + +int ompi_fetch_opal_pointer_array_info(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info, + int *size, int *lowest_free, + int *number_free) +{ + mqs_image *image = mqs_get_image(proc); + mpi_image_info *i_info = (mpi_image_info *) mqs_get_image_info(image); + + *size = ompi_fetch_int(proc, + addr + i_info->opal_pointer_array_t.offset.size, + p_info); + *lowest_free = ompi_fetch_int(proc, + addr + i_info->opal_pointer_array_t.offset.lowest_free, + p_info); + *number_free = ompi_fetch_int(proc, + addr + i_info->opal_pointer_array_t.offset.number_free, + p_info); + return mqs_ok; +} + +/***********************************************************************/ + +int ompi_fetch_opal_pointer_array_item(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info, int index, + mqs_taddr_t *item) +{ + mqs_image *image = mqs_get_image(proc); + mpi_image_info *i_info = (mpi_image_info *) mqs_get_image_info(image); + int size, lowest_free, number_free; + mqs_taddr_t base; + + if (index < 0) { + return mqs_no_information; + } + + ompi_fetch_opal_pointer_array_info(proc, addr, p_info, &size, + &lowest_free, &number_free); + if (index >= size) { + return mqs_no_information; + } + + base = ompi_fetch_pointer(proc, + addr + i_info->opal_pointer_array_t.offset.addr, + p_info); + *item = ompi_fetch_pointer(proc, + base + index * p_info->sizes.pointer_size, + p_info); + + return mqs_ok; +} diff --git a/ompi/debuggers/ompi_common_dll_defs.h b/ompi/debuggers/ompi_common_dll_defs.h new file mode 100644 index 0000000000..450f46755b --- /dev/null +++ b/ompi/debuggers/ompi_common_dll_defs.h @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2007-2008 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +/********************************************************************** + * Copyright (C) 2000-2004 by Etnus, LLC. + * Copyright (C) 1999 by Etnus, Inc. + * Copyright (C) 1997-1998 Dolphin Interconnect Solutions Inc. + * + * Permission is hereby granted to use, reproduce, prepare derivative + * works, and to redistribute to others. + * + * DISCLAIMER + * + * Neither Dolphin Interconnect Solutions, Etnus LLC, nor any of their + * employees, makes any warranty express or implied, or assumes any + * legal liability or responsibility for the accuracy, completeness, + * or usefulness of any information, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately + * owned rights. + * + * This code was written by + * James Cownie: Dolphin Interconnect Solutions. + * Etnus LLC + **********************************************************************/ + +#ifndef OMPI_COMMON_DLL_DEFS_H +#define OMPI_COMMON_DLL_DEFS_H + +#include "msgq_interface.h" + +/*********************************************************************** + * Information associated with a specific executable image. Common + * across all DLLs. + */ +typedef struct +{ + /* Functions needed here */ + const struct mqs_image_callbacks * image_callbacks; + + /* basic structures */ + struct { + mqs_type *type; + int size; + struct { + int opal_list_next; + } offset; + } opal_list_item_t; + struct { + mqs_type *type; + int size; + struct { + int opal_list_sentinel; + } offset; + } opal_list_t; + struct { + mqs_type *type; + int size; + } ompi_free_list_item_t; + struct { + mqs_type *type; + int size; + struct { + int fl_elem_class; /* opal_class_t* */ + int fl_mpool; /* struct mca_mpool_base_module_t* */ + int fl_elem_size; /* size_t */ + int fl_alignment; /* size_t */ + int fl_allocations; /* opal_list_t */ + int fl_max_to_alloc; /* size_t */ + int fl_num_per_alloc; /* size_t */ + int fl_num_allocated; /* size_t */ + } offset; + } ompi_free_list_t; + struct { + mqs_type *type; + int size; + struct { + int ht_table; + int ht_table_size; + int ht_size; + int ht_mask; + } offset; + } opal_hash_table_t; + /* requests structures */ + struct { + mqs_type *type; + int size; + struct { + int req_type; + int req_status; + int req_complete; + int req_state; + int req_f_to_c_index; + } offset; + } ompi_request_t; + struct { + mqs_type *type; + int size; + struct { + int req_addr; + int req_count; + int req_peer; + int req_tag; + int req_comm; + int req_datatype; + int req_proc; + int req_sequence; + int req_type; + int req_pml_complete; + } offset; + } mca_pml_base_request_t; + struct { + mqs_type *type; + int size; + struct { + int req_addr; + int req_bytes_packed; + int req_send_mode; + } offset; + } mca_pml_base_send_request_t; + struct { + mqs_type *type; + int size; + struct { + int req_bytes_packed; + } offset; + } mca_pml_base_recv_request_t; +#if 0 + /* fragments for unexpected messages (as well as theirs headers) */ + struct { + mqs_type *type; + int size; + struct { + int hdr; + int request; + } offset; + } mca_pml_ob1_recv_frag_t; + struct { + mqs_type *type; + int size; + struct { + int hdr_type; + int hdr_flags; + } offset; + } mca_pml_ob1_common_hdr_t; + struct { + mqs_type *type; + int size; + struct { + int hdr_common; + int hdr_ctx; + int hdr_src; + int hdr_tag; + int hdr_seq; + } offset; + } mca_pml_ob1_match_hdr_t; +#endif + /* opal_pointer_array structure */ + struct { + mqs_type *type; + int size; + struct { + int lowest_free; + int number_free; + int size; + int addr; + } offset; + } opal_pointer_array_t; + /* group structure */ + struct { + mqs_type *type; + int size; + struct { + int grp_proc_count; + int grp_my_rank; + int grp_flags; + } offset; + } ompi_group_t; + /* communicator structure */ + struct { + mqs_type *type; + int size; + struct { + int c_name; + int c_contextid; + int c_my_rank; + int c_local_group; + int c_remote_group; + int c_flags; + int c_f_to_c_index; + int c_topo_comm; + int c_keyhash; + } offset; + } ompi_communicator_t; + /* base topology information in a communicator */ + struct { + mqs_type *type; + int size; + struct { + int mtc_ndims_or_nnodes; + int mtc_dims_or_index; + int mtc_periods_or_edges; + int mtc_reorder; + } offset; + } ompi_mca_topo_base_comm_1_0_0_t; + /* MPI_Status */ + struct { + mqs_type *type; + int size; + struct { + int MPI_SOURCE; + int MPI_TAG; + int MPI_ERROR; + int _count; + int _cancelled; + } offset; + } ompi_status_public_t; + /* datatype structure */ + struct { + mqs_type *type; + int size; + struct { + int size; + int name; + } offset; + } ompi_datatype_t; + + /* For the caller to hang their own stuff */ + void *extra; +} mpi_image_info; + +/***********************************************************************/ +/* Information for a single process. Common across all DLLs. + */ +typedef struct +{ + const struct mqs_process_callbacks * process_callbacks; /* Functions needed here */ + + mqs_target_type_sizes sizes; /* Process architecture information */ + + /* For the caller to hang their own stuff */ + void *extra; +} mpi_process_info; + +/**********************************************************************/ +/* Macros to make it transparent that we're calling the TV functions + * through function pointers. + */ +#define mqs_malloc (mqs_basic_entrypoints->mqs_malloc_fp) +#define mqs_free (mqs_basic_entrypoints->mqs_free_fp) +#define mqs_prints (mqs_basic_entrypoints->mqs_dprints_fp) +#define mqs_put_image_info (mqs_basic_entrypoints->mqs_put_image_info_fp) +#define mqs_get_image_info (mqs_basic_entrypoints->mqs_get_image_info_fp) +#define mqs_put_process_info (mqs_basic_entrypoints->mqs_put_process_info_fp) +#define mqs_get_process_info (mqs_basic_entrypoints->mqs_get_process_info_fp) + +/* These macros *RELY* on the function already having set up the conventional + * local variables i_info or p_info. + */ +#define mqs_find_type (i_info->image_callbacks->mqs_find_type_fp) +#define mqs_field_offset (i_info->image_callbacks->mqs_field_offset_fp) +#define mqs_sizeof (i_info->image_callbacks->mqs_sizeof_fp) +#define mqs_get_type_sizes (i_info->image_callbacks->mqs_get_type_sizes_fp) +#define mqs_find_function (i_info->image_callbacks->mqs_find_function_fp) +#define mqs_find_symbol (i_info->image_callbacks->mqs_find_symbol_fp) + +#define mqs_get_image (p_info->process_callbacks->mqs_get_image_fp) +#define mqs_get_global_rank (p_info->process_callbacks->mqs_get_global_rank_fp) +#define mqs_fetch_data (p_info->process_callbacks->mqs_fetch_data_fp) +#define mqs_target_to_host (p_info->process_callbacks->mqs_target_to_host_fp) + +/* Basic callbacks into the debugger */ +extern const mqs_basic_callbacks *mqs_basic_entrypoints; + +/* OMPI-specific functions */ +int ompi_fill_in_type_info(mqs_image *image, char **message); + +/* Fetch a pointer from the process */ +mqs_taddr_t ompi_fetch_pointer(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info); + +/* Fetch an int from the process */ +mqs_tword_t ompi_fetch_int(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info); + +/* Fetch a bool from the process */ +mqs_tword_t ompi_fetch_bool(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info); + +/* Fetch a size_t from the process */ +mqs_taddr_t ompi_fetch_size_t(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info); + +/* Helpers to fetch stuff from an opal_pointer_array_t */ +int ompi_fetch_opal_pointer_array_info(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info, + int *size, int *lowest_free, + int *number_free); +int ompi_fetch_opal_pointer_array_item(mqs_process *proc, mqs_taddr_t addr, + mpi_process_info *p_info, int index, + mqs_taddr_t *item); +#endif diff --git a/ompi/debuggers/ompi_totalview.c b/ompi/debuggers/ompi_debuggers.c similarity index 61% rename from ompi/debuggers/ompi_totalview.c rename to ompi/debuggers/ompi_debuggers.c index 91bc46e2d7..9f7c6a1553 100644 --- a/ompi/debuggers/ompi_totalview.c +++ b/ompi/debuggers/ompi_debuggers.c @@ -10,6 +10,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2007 Cisco, Inc. All rights resereved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -18,7 +19,8 @@ */ /** - * MPI portion of debugger support: TotalView + * MPI portion of debugger support: initially based on the + * TotalView/Etnus API for debuggers to attach to MPI jobs. */ #include "ompi_config.h" @@ -26,8 +28,22 @@ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif #include "opal/mca/base/base.h" +#include "opal/util/argv.h" +#include "opal/mca/installdirs/installdirs.h" #include "debuggers.h" /** * A lot of include files that are required by al optimized builds in order @@ -51,9 +67,13 @@ OMPI_DECLSPEC int MPIR_being_debugged = 0; OMPI_DECLSPEC volatile int MPIR_debug_gate = 0; OMPI_DECLSPEC volatile int MPIR_debug_state = 0; -#if defined(OMPI_TV_DLL) -OMPI_DECLSPEC char MPIR_dll_name[] = OMPI_TV_DLL; -#endif /* defined(OMPI_TV_DLL) */ +#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; OMPI_DECLSPEC int MPIR_debug_typedefs_sizeof[] = { sizeof(short), @@ -95,21 +115,78 @@ OMPI_DECLSPEC ompi_group_t* ompi_group_t_type_inclusion = NULL; OMPI_DECLSPEC ompi_status_public_t* ompi_status_public_t_type_inclusion = NULL; OMPI_DECLSPEC ompi_datatype_t* ompi_datatype_t_type_inclusion = NULL; -/** - * Wait for a TotalView-like debugger if asked. - */ -void ompi_wait_for_totalview(void) +/* Check for a file in few dirrect ways for portability */ +static void check(char *dir, char *file, char **locations) { - int wait_for_totalview; + 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); +} + + +/** + * Wait for a debugger if asked. + */ +void ompi_wait_for_debugger(void) +{ + int i, wait_for_debugger, wait_for_tv; + char *a, *b, **dirs; /* Do we need to wait for a TotalView-like debugger? */ mca_base_param_reg_int_name("orte", - "mpi_wait_for_totalview", + "mpi_wait_for_debugger", "Whether the MPI application " "should wait for a debugger or not", false, false, (int) false, - &wait_for_totalview); - if (wait_for_totalview) { + &wait_for_debugger); + mca_base_param_reg_int_name("orte", + "mpi_wait_for_totalview", + "Deprecated synonym for mpi_wait_for_debugger", + false, false, (int) false, + &wait_for_tv); + wait_for_debugger |= wait_for_tv; + + 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); + + /* Search the directory for MPI debugger DLLs */ + if (NULL != b) { + dirs = opal_argv_split(b, ':'); + for (i = 0; dirs[i] != NULL; ++i) { + check(dirs[i], OMPI_MPIHANDLES_DLL_PREFIX, mpidbg_dll_locations); + check(dirs[i], OMPI_MSGQ_DLL_PREFIX, mpimsgq_dll_locations); + } + } + + /* If we're waiting for the debugger, then, well, wait for it. :-) */ + if (wait_for_debugger) { while (MPIR_debug_gate == 0) { #if defined(__WINDOWS__) Sleep(100); /* milliseconds */ @@ -119,3 +196,4 @@ void ompi_wait_for_totalview(void) } } } + diff --git a/ompi/debuggers/ompi_mpihandles_dll.c b/ompi/debuggers/ompi_mpihandles_dll.c new file mode 100644 index 0000000000..47f15af29e --- /dev/null +++ b/ompi/debuggers/ompi_mpihandles_dll.c @@ -0,0 +1,751 @@ +/* + * Copyright (c) 2007-2008 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +/********************************************************************** + * Copyright (C) 2000-2004 by Etnus, LLC. + * Copyright (C) 1999 by Etnus, Inc. + * Copyright (C) 1997-1998 Dolphin Interconnect Solutions Inc. + * + * Permission is hereby granted to use, reproduce, prepare derivative + * works, and to redistribute to others. + * + * DISCLAIMER + * + * Neither Dolphin Interconnect Solutions, Etnus LLC, nor any of their + * employees, makes any warranty express or implied, or assumes any + * legal liability or responsibility for the accuracy, completeness, + * or usefulness of any information, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately + * owned rights. + * + * This code was written by + * James Cownie: Dolphin Interconnect Solutions. + * Etnus LLC + **********************************************************************/ + +#include "ompi_config.h" + +#if defined(HAVE_STRING_H) +#include +#endif /* defined(HAVE_STRING_H) */ +#if defined(HAVE_STDLIB_H) +#include +#endif /* defined(HAVE_STDLIB_H) */ + +#include "ompi/mca/pml/base/pml_base_request.h" +#include "mpihandles_interface.h" +#include "ompi_mpihandles_dll_defs.h" +#include "ompi/communicator/communicator.h" +#include "ompi/group/group.h" + + +#define OPAL_ALIGN(x,a,t) (((x)+((t)(a)-1)) & ~(((t)(a)-1))) + +/* Globals that the debugger expects to find in the DLL */ +#if defined(WORDS_BIGENDIAN) +char mpidbg_dll_is_big_endian = 1; +#else +char mpidbg_dll_is_big_endian = 0; +#endif +char mpidbg_dll_bitness = (char) (sizeof(void*) * 8); +enum mpidbg_comm_capabilities_t mpidbg_comm_capabilities = 0; +struct mpidbg_name_map_t *mpidbg_comm_name_map = NULL; +enum mpidbg_errhandler_capabilities_t mpidbg_errhandler_capabilities = 0; +struct mpidbg_name_map_t *mpidbg_errhandler_name_map = NULL; +enum mpidbg_request_capabilities_t mpidbg_request_capabilities = 0; +struct mpidbg_name_map_t *mpidbg_request_name_map = NULL; +enum mpidbg_status_capabilities_t mpidbg_status_capabilities = 0; +struct mpidbg_name_map_t *mpidbg_status_name_map = NULL; + +/* Temporary workaround for making Totalview to load these symbols in + the library when this is compiled with the Sun Studio C compiler */ +#if defined(__SUNPRO_C) +bool opal_uses_threads; +bool opal_mutex_check_locks; +volatile int32_t opal_progress_thread_count; +int opal_progress_spin_count; +#endif + +/*---------------------------------------------------------------------*/ + +/* Small helper function: allocate a map of a given length */ +static struct mpidbg_name_map_t *alloc_map(mqs_image *image, int len) +{ + mpi_image_info *i_info = (mpi_image_info *) mqs_get_image_info(image); + struct mpidbg_name_map_t *m = NULL; + + if (NULL != i_info) { + m = mqs_malloc(len * sizeof(struct mpidbg_name_map_t)); + } + + return m; +} + +/* Small helper function: look up a symbol, and if we find it, put it + in a map entry */ +static void fill_map(mqs_image *image, + char *public_name, char *private_name, + struct mpidbg_name_map_t *map) +{ + mqs_taddr_t value; + mpi_image_info *i_info = (mpi_image_info *) mqs_get_image_info(image); + + if (NULL != i_info) { + map->map_name = strdup(public_name); + if (NULL != private_name) { + if (mqs_ok == mqs_find_symbol(image, private_name, &value)) { + map->map_handle = value; + return; + } + } else { + map->map_handle = 0; + return; + } + } + + printf("OMPI MPI handles DLL: fill_map: Unable to find symbol: %s\n", + private_name); +} + +/* Helper function to lookup MPI attributes and fill an + mpidbg_attribute_pair_t array with their keys/values */ +static int fill_attributes(int *num_attrs, + struct mpidbg_attribute_pair_t **attrs, + mqs_taddr_t table) +{ + /* JMS fill me in */ + return mqs_ok; +} + +/*---------------------------------------------------------------------*/ + +int mpidbg_init_once(const mqs_basic_callbacks *cb) +{ + mqs_basic_entrypoints = cb; + printf("mpidbg_init_once\n"); + return MPIDBG_SUCCESS; +} + +/*---------------------------------------------------------------------*/ + +/* Returns the fixed value */ +int mpidbg_interface_version_compatibility(void) +{ + printf("mpidbg_interface_version_compatibility\n"); + return MPIDBG_INTERFACE_VERSION; +} + + +/* Returns a string specific to OMPI */ +char *mpidbg_version_string(void) +{ + printf("mpidbg_version_string\n"); + return "Open MPI handle interpretation support for parallel" + " debuggers compiled on " __DATE__; +} + + +/* So the debugger can tell what interface width the library was + compiled with */ +int mpidbg_dll_taddr_width(void) +{ + printf("mpidbg_dll_taddr_width\n"); + return sizeof(mqs_taddr_t); +} + +/*---------------------------------------------------------------------*/ + +/* Once-per-image setup */ +int mpidbg_init_per_image(mqs_image *image, const mqs_image_callbacks *icb, + struct mpidbg_handle_info_t *handle_types) +{ + char **message; + mpi_image_info *i_info = + (mpi_image_info *) mqs_malloc(sizeof(mpi_image_info)); + printf("mpidbg_init_per_image\n"); + + if (NULL == i_info) { + printf("mpidbg_init_per_image: malloc failed!\n"); + return MPIDBG_ERR_NO_MEM; + } + + memset((void *)i_info, 0, sizeof(mpi_image_info)); + /* Before we do *ANYTHING* else */ + i_info->image_callbacks = icb; + + /* Nothing extra (yet) */ + i_info->extra = NULL; + + /* Save the info */ + mqs_put_image_info(image, (mqs_image_info *)i_info); + + /* Fill in the OMPI type information */ + if (mqs_ok != ompi_fill_in_type_info(image, message)) { + printf("mpidbg_init_per_image: failed to get all type info\n"); + return MPIDBG_ERR_NOT_SUPPORTED; + } + + /* Fill in the handle_types struct with our types */ + /* JMS: "MPI_Aint" is a typedef -- is that enough? (the actual + type is a #define, so it's not easy to put into the + mqs_find_type call as a string) */ + handle_types->hi_c_aint = mqs_find_type(image, "MPI_Aint", mqs_lang_c); + /* JMS: these ompi types are just the "foo" types; but OMPI MPI + types are all "foo*"'s -- is this right? If this is wrong, I + *suspect* that something like the following may be right: + + handle_types->hi_c_comm = mqs_find_type(image, "ompi_communicator_t*", mqs_lang_c); + + Need to confirm this with the DDT guys... + */ + handle_types->hi_c_comm = i_info->ompi_communicator_t.type; + handle_types->hi_c_datatype = i_info->ompi_datatype_t.type; + handle_types->hi_c_errhandler = + mqs_find_type(image, "ompi_errhandler_t", mqs_lang_c); + handle_types->hi_c_file = + mqs_find_type(image, "ompi_file_t", mqs_lang_c); + handle_types->hi_c_group = i_info->ompi_group_t.type; + handle_types->hi_c_info = + mqs_find_type(image, "ompi_info_t", mqs_lang_c); + /* JMS: "MPI_Offset" is a typedef (see comment about MPI_Aint above) */ + handle_types->hi_c_offset = + mqs_find_type(image, "MPI_Offset", mqs_lang_c); + handle_types->hi_c_op = + mqs_find_type(image, "ompi_op_t", mqs_lang_c); + handle_types->hi_c_request = i_info->ompi_request_t.type; + handle_types->hi_c_status = i_info->ompi_status_public_t.type; + handle_types->hi_c_win = + mqs_find_type(image, "ompi_win_t", mqs_lang_c); + + /* MPI::Aint is a typedef to MPI_Aint */ + handle_types->hi_cxx_aint = handle_types->hi_cxx_aint; + handle_types->hi_cxx_comm = + mqs_find_type(image, "MPI::Comm", mqs_lang_cplus); + handle_types->hi_cxx_intracomm = + mqs_find_type(image, "MPI::Intracomm", mqs_lang_cplus); + handle_types->hi_cxx_intercomm = + mqs_find_type(image, "MPI::Intercomm", mqs_lang_cplus); + handle_types->hi_cxx_graphcomm = + mqs_find_type(image, "MPI::Graphcomm", mqs_lang_cplus); + handle_types->hi_cxx_cartcomm = + mqs_find_type(image, "MPI::Cartcomm", mqs_lang_cplus); + handle_types->hi_cxx_datatype = + mqs_find_type(image, "MPI::Datatype", mqs_lang_cplus); + handle_types->hi_cxx_errhandler = + mqs_find_type(image, "MPI::Errhandler", mqs_lang_cplus); + handle_types->hi_cxx_file = + mqs_find_type(image, "MPI::File", mqs_lang_cplus); + handle_types->hi_cxx_group = + mqs_find_type(image, "MPI::Group", mqs_lang_cplus); + handle_types->hi_cxx_info = + mqs_find_type(image, "MPI::Info", mqs_lang_cplus); + /* MPI::Offset is a typedef to MPI_Offset */ + handle_types->hi_cxx_offset = handle_types->hi_c_offset; + handle_types->hi_cxx_op = + mqs_find_type(image, "MPI::Op", mqs_lang_cplus); + handle_types->hi_cxx_request = + mqs_find_type(image, "MPI::Request", mqs_lang_cplus); + handle_types->hi_cxx_prequest = + mqs_find_type(image, "MPI::Prequest", mqs_lang_cplus); + handle_types->hi_cxx_grequest = + mqs_find_type(image, "MPI::Grequest", mqs_lang_cplus); + handle_types->hi_cxx_status = + mqs_find_type(image, "MPI::Status", mqs_lang_cplus); + handle_types->hi_cxx_win = + mqs_find_type(image, "MPI::Win", mqs_lang_cplus); + + /* Tell the debuger what capabilities we have */ + mpidbg_comm_capabilities = + MPIDBG_COMM_CAP_BASIC | + MPIDBG_COMM_CAP_STRING_NAMES | + MPIDBG_COMM_CAP_FREED_HANDLE | + MPIDBG_COMM_CAP_FREED_OBJECT; + mpidbg_errhandler_capabilities = + MPIDBG_ERRH_CAP_BASIC | + MPIDBG_ERRH_CAP_STRING_NAMES | + MPIDBG_ERRH_CAP_FREED_HANDLE | + MPIDBG_ERRH_CAP_FREED_OBJECT; + mpidbg_request_capabilities = + MPIDBG_REQUEST_CAP_BASIC; + mpidbg_status_capabilities = + MPIDBG_STATUS_CAP_BASIC; + + /* All done */ + printf("mpidbg_init_per_image: init succeeded -- ready!\n"); + return MPIDBG_SUCCESS; +} + + +/* This image is now dead; free all the state associated with it */ +void mpidbg_finalize_per_image(mqs_image *image, mqs_image_info *info) +{ + mpi_image_info *i_info = (mpi_image_info *)info; + + printf("mpidbg_finalize_per_image\n"); + if (NULL != i_info->extra) { + mqs_free(i_info->extra); + } + mqs_free(info); +} + +/*---------------------------------------------------------------------*/ + +/* Setup information needed for a specific process. The debugger + * assumes that this will hang something onto the process, if nothing + * is attached to it, then TV will believe that this process has no + * message queue information. + */ +int mpidbg_init_per_process(mqs_process *process, + const mqs_process_callbacks *pcb, + struct mpidbg_handle_info_t *handle_types) +{ + mqs_image *image; + mpi_image_info *i_info; + + /* Extract the addresses of the global variables we need and save + them away */ + mpi_process_info *p_info = + (mpi_process_info *) mqs_malloc(sizeof(mpi_process_info)); + printf("mpidbg_init_per_process\n"); + + if (NULL == p_info) { + return MPIDBG_ERR_NO_MEM; + } + + /* Setup the callbacks first */ + p_info->process_callbacks = pcb; + + /* Nothing extra (yet) */ + p_info->extra = NULL; + + /* Now we can get the rest of the info */ + image = mqs_get_image(process); + i_info = (mpi_image_info *) mqs_get_image_info(image); + + /* Get process info sizes */ + mqs_get_type_sizes (process, &p_info->sizes); + + /* Save the info */ + mqs_put_process_info(process, (mqs_process_info *) p_info); + + /* Fill in pre-defined MPI handle name mappings (because OMPI uses + #define's for the pre-defined names, such as "#define + MPI_COMM_WORLD &ompi_mpi_comm_world"). */ + /* Communicators */ + mpidbg_comm_name_map = alloc_map(image, 4); + if (NULL != mpidbg_comm_name_map) { + int i = 0; + fill_map(image, "MPI_COMM_WORLD", "ompi_mpi_comm_world", + &mpidbg_comm_name_map[i++]); + fill_map(image, "MPI_COMM_SELF", "ompi_mpi_comm_self", + &mpidbg_comm_name_map[i++]); + fill_map(image, "MPI_COMM_NULL", "ompi_mpi_comm_null", + &mpidbg_comm_name_map[i++]); + + /* Sentinel value */ + mpidbg_comm_name_map[i].map_name = NULL; + } + + /* Error handlers */ + mpidbg_errhandler_name_map = alloc_map(image, 4); + if (NULL != mpidbg_errhandler_name_map) { + int i = 0; + fill_map(image, "MPI_ERRORS_ARE_FATAL", "ompi_mpi_errors_are_fatal", + &mpidbg_errhandler_name_map[i++]); + fill_map(image, "MPI_ERRORS_RETURN", "ompi_mpi_errors_return", + &mpidbg_errhandler_name_map[i++]); + fill_map(image, "MPI_ERRHANDLER_NULL", "ompi_mpi_errhandler_null", + &mpidbg_errhandler_name_map[i++]); + /* MPI::ERRORS_THROW_EXCEPTIONS exists as a symbol in OMPI; no + need to alias it here */ + + /* Sentinel value */ + mpidbg_errhandler_name_map[i].map_name = NULL; + } + + /* Requests */ + mpidbg_request_name_map = alloc_map(image, 2); + if (NULL != mpidbg_request_name_map) { + int i = 0; + fill_map(image, "MPI_REQUEST_NULL", "ompi_request_null", + &mpidbg_request_name_map[i++]); + + /* Sentinel value */ + mpidbg_request_name_map[i].map_name = NULL; + } + + /* Statuses */ + mpidbg_status_name_map = alloc_map(image, 2); + if (NULL != mpidbg_status_name_map) { + int i = 0; + fill_map(image, "MPI_STATUS_IGNORE", NULL, + &mpidbg_status_name_map[i++]); + + /* Sentinel value */ + mpidbg_status_name_map[i].map_name = NULL; + } + + /* All done */ + return MPIDBG_SUCCESS; +} + + +/* This process is now done; free all the state associated with it */ +void mpidbg_finalize_per_process(mqs_process *process, mqs_process_info *info) +{ + mpi_process_info *p_info = (mpi_process_info *)info; + + printf("mpidbg_finalize_per_process\n"); + if (NULL != p_info->extra) { + mqs_free(p_info->extra); + } + mqs_free(info); +} + + +/*---------------------------------------------------------------------*/ + +int mpidbg_comm_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t c_comm, struct mpidbg_comm_info_t **info) +{ + int flags; + mpi_image_info *i_info = (mpi_image_info*) image_info; + mpi_process_info *p_info = (mpi_process_info*) process_info; + mqs_taddr_t group, topo, keyhash; + + /* Get the comm name */ + + *info = mqs_malloc(sizeof(struct mpidbg_comm_info_t)); + if (NULL == *info) { + return MPIDBG_ERR_NO_MEM; + } + /* JMS temporarily zero everything out. Remove this when we fill + in all the fields */ + memset(*info, 0, sizeof(struct mpidbg_comm_info_t)); + (*info)->comm_c_handle = c_comm; + + printf("mpidbg_comm_query: %p\n", (void*) c_comm); + mqs_fetch_data(process, c_comm + i_info->ompi_communicator_t.offset.c_name, + MPIDBG_MAX_OBJECT_NAME, (*info)->comm_name); + + /* Get this process' rank in the comm */ + (*info)->comm_rank = ompi_fetch_int(process, + c_comm + i_info->ompi_communicator_t.offset.c_my_rank, + p_info); + + /* Analyze the flags on the comm */ + flags = ompi_fetch_int(process, + c_comm + i_info->ompi_communicator_t.offset.c_flags, + p_info); + (*info)->comm_bitflags = 0; + if (MPI_PROC_NULL == (*info)->comm_rank) { + /* This communicator is MPI_COMM_NULL */ + (*info)->comm_rank = (*info)->comm_size = 0; + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_COMM_NULL; + } else if (0 != (flags & OMPI_COMM_INTER)) { + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_INTERCOMM; + } else { + if (0 != (flags & OMPI_COMM_CART)) { + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_CARTESIAN; + } else if (0 != (flags & OMPI_COMM_GRAPH)) { + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_GRAPH; + } + } + if (0 != (flags & OMPI_COMM_ISFREED)) { + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_FREED_HANDLE; + } + if (0 != (flags & OMPI_COMM_INTRINSIC)) { + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_PREDEFINED; + } + if (0 != (flags & OMPI_COMM_INVALID)) { + (*info)->comm_bitflags |= MPIDBG_COMM_INFO_FREED_OBJECT; + } + + /* Look up the local group */ + group = ompi_fetch_pointer(process, + c_comm + i_info->ompi_communicator_t.offset.c_local_group, + p_info); + (*info)->comm_rank = ompi_fetch_int(process, + group + i_info->ompi_group_t.offset.grp_my_rank, + p_info); + (*info)->comm_num_local_procs = ompi_fetch_int(process, + group + i_info->ompi_group_t.offset.grp_proc_count, + p_info); + + /* Fill in the comm_size with the size of the local group. We'll + override below if this is an intercommunicator. */ + (*info)->comm_size = (*info)->comm_num_local_procs; + + /* JMS fill this in: waiting to decide between mpidbg_process_t + and mqs_process_location */ + (*info)->comm_local_procs = NULL; + + /* Look up the remote group (if relevant) */ + if (0 != (flags & OMPI_COMM_INTER)) { + group = ompi_fetch_pointer(process, + c_comm + i_info->ompi_communicator_t.offset.c_remote_group, + p_info); + (*info)->comm_num_remote_procs = ompi_fetch_int(process, + group + i_info->ompi_group_t.offset.grp_proc_count, + p_info); + (*info)->comm_size = (*info)->comm_num_remote_procs; + + /* JMS fill this in: waiting to decide between + mpidbg_process_t and mqs_process_location */ + (*info)->comm_remote_procs = NULL; + } else { + (*info)->comm_num_remote_procs = 0; + (*info)->comm_remote_procs = NULL; + } + + /* Fill in cartesian/graph info, if relevant. The cartesian and + graph data is just slightly different from each other; it's + [slightly] easier (and less confusing!) to have separate + retrieval code blocks. */ + topo = ompi_fetch_pointer(process, + c_comm + i_info->ompi_communicator_t.offset.c_topo_comm, + p_info); + if (0 != topo && + 0 != ((*info)->comm_bitflags & MPIDBG_COMM_INFO_CARTESIAN)) { + int i, ndims, tmp; + mqs_taddr_t dims, periods; + + /* Alloc space for copying arrays */ + (*info)->comm_cart_num_dims = ndims = + ompi_fetch_int(process, + topo + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_ndims_or_nnodes, + p_info); + (*info)->comm_cart_dims = mqs_malloc(ndims * sizeof(int)); + if (NULL == (*info)->comm_cart_dims) { + return MPIDBG_ERR_NO_MEM; + } + (*info)->comm_cart_periods = mqs_malloc(ndims * sizeof(int8_t)); + if (NULL == (*info)->comm_cart_periods) { + mqs_free((*info)->comm_cart_dims); + (*info)->comm_cart_dims = NULL; + return MPIDBG_ERR_NO_MEM; + } + + /* Retrieve the dimension and periodic description data from + the two arrays on the image's communicator */ + dims = ompi_fetch_pointer(process, + topo + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_dims_or_index, + p_info); + periods = ompi_fetch_pointer(process, + topo + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_periods_or_edges, + p_info); + + for (i = 0; i < ndims; ++i) { + (*info)->comm_cart_dims[i] = + ompi_fetch_int(process, dims + (sizeof(int) * i), p_info); + tmp = ompi_fetch_int(process, periods + (sizeof(int) * i), p_info); + (*info)->comm_cart_periods[i] = (int8_t) tmp; + printf("mpidbg: cart comm: dimension %d: (length %d, periodic: %d)\n", i, (*info)->comm_cart_dims[i], tmp); + } + } else if (0 != topo && + 0 != ((*info)->comm_bitflags & MPIDBG_COMM_INFO_GRAPH)) { + int i, nnodes; + mqs_taddr_t index, edges; + + /* Alloc space for copying the indexes */ + (*info)->comm_graph_num_nodes = nnodes = + ompi_fetch_int(process, + topo + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_ndims_or_nnodes, + p_info); + (*info)->comm_graph_index = mqs_malloc(nnodes * sizeof(int)); + if (NULL == (*info)->comm_graph_index) { + return MPIDBG_ERR_NO_MEM; + } + + /* Retrieve the index data */ + index = ompi_fetch_pointer(process, + topo + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_dims_or_index, + p_info); + for (i = 0; i < nnodes; ++i) { + (*info)->comm_graph_index[i] = + ompi_fetch_int(process, index + (sizeof(int) * i), p_info); + } + + /* Allocate space for the edges */ + (*info)->comm_graph_edges = mqs_malloc((*info)->comm_graph_index[(*info)->comm_graph_num_nodes - 1] * sizeof(int)); + if (NULL == (*info)->comm_graph_edges) { + mqs_free((*info)->comm_graph_index); + (*info)->comm_graph_index = NULL; + return MPIDBG_ERR_NO_MEM; + } + + /* Retrieve the edge data */ + edges = ompi_fetch_pointer(process, + topo + i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_periods_or_edges, + p_info); + for (i = 0; + i < (*info)->comm_graph_index[(*info)->comm_graph_num_nodes - 1]; + ++i) { + (*info)->comm_graph_edges[i] = + ompi_fetch_int(process, edges + (sizeof(int) * i), p_info); + } + } + + /* Fortran handle */ + (*info)->comm_fortran_handle = + ompi_fetch_int(process, + c_comm + i_info->ompi_communicator_t.offset.c_f_to_c_index, + p_info); + printf("mpdbg: comm fortran handle: %d\n", (*info)->comm_fortran_handle); + + /* Fill in attributes */ + keyhash = ompi_fetch_pointer(process, + c_comm + i_info->ompi_communicator_t.offset.c_keyhash, + p_info); + fill_attributes(&((*info)->comm_num_attrs), &((*info)->comm_attrs), + keyhash); + + /* JMS temporary */ + (*info)->comm_num_pending_requests = MPIDBG_ERR_NOT_SUPPORTED; + (*info)->comm_pending_requests = NULL; + (*info)->comm_num_derived_windows = MPIDBG_ERR_NOT_SUPPORTED; + (*info)->comm_derived_windows = NULL; + (*info)->comm_num_derived_files = MPIDBG_ERR_NOT_SUPPORTED; + (*info)->comm_derived_files = NULL; + + return MPIDBG_SUCCESS; +} + +int mpidbg_comm_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_comm, mqs_taddr_t *c_comm) +{ + mqs_taddr_t comm_list; + mpi_image_info *i_info = (mpi_image_info *) image_info; + mpi_process_info *p_info = (mpi_process_info*) process_info; + + mqs_find_symbol(image, "ompi_mpi_communicators", &comm_list); + if (mqs_ok != ompi_fetch_opal_pointer_array_item(process, comm_list, + p_info, f77_comm, + c_comm) || + NULL == c_comm) { + printf("mpidbg_comm_f2c: %lu -> not found\n", + (long unsigned int) f77_comm); + return MPIDBG_ERR_NOT_FOUND; + } + printf("mpidbg_comm_f2c: %lu -> %lu\n", + (long unsigned int) f77_comm, (long unsigned int) c_comm); + return MPIDBG_SUCCESS; +} + +int mpidbg_comm_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_comm, + enum mpidbg_comm_info_bitmap_t comm_type, + mqs_taddr_t *c_comm) +{ + /* David tells me that any type of communicator (MPI::Comm, + MPI::Intracomm, etc.) should have the offset to the mpi_comm + member in the same place. */ + printf("mpidbg_comm_cxx2c: %p\n", (void*) cxx_comm); + return MPIDBG_ERR_NOT_FOUND; +} + +/*---------------------------------------------------------------------*/ + +int mpidbg_errhandler_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t c_errhandler, + struct mpidbg_errhandler_info_t **info) +{ + printf("mpidbg_errhandler_query: %p\n", (void*) c_errhandler); + printf("mpidbg_errhandler_query: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +int mpidbg_errhandler_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_errhandler, mqs_taddr_t *c_errhandler) +{ + printf("mpidbg_errhandler_f2c: %lu\n", (long unsigned int) f77_errhandler); + printf("mpidbg_errhandler_f2c: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +int mpidbg_errhandler_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_errhandler, + mqs_taddr_t *c_errhandler) +{ + printf("mpidbg_errhandler_cxx2c: %p\n", (void*) cxx_errhandler); + printf("mpidbg_errhandler_cxx2c: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +/*---------------------------------------------------------------------*/ + +int mpidbg_request_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t c_request, + struct mpidbg_request_info_t **info) +{ + printf("mpidbg_request_query: %p\n", (void*) c_request); + printf("mpidbg_request_query: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +int mpidbg_request_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_request, mqs_taddr_t *c_request) +{ + printf("mpidbg_request_f2c: %lu\n", (long unsigned int) f77_request); + printf("mpidbg_request_f2c: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +int mpidbg_request_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_request, + enum mpidbg_request_info_bitmap_t request_type, + mqs_taddr_t *c_request) +{ + printf("mpidbg_request_cxx2c: %p\n", (void*) cxx_request); + printf("mpidbg_request_cxx2c: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +/*---------------------------------------------------------------------*/ + +int mpidbg_status_query(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t c_status, + struct mpidbg_status_info_t **info) +{ + printf("mpidbg_status_query: %p\n", (void*) c_status); + printf("mpidbg_status_query: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +int mpidbg_status_f2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t f77_status, mqs_taddr_t *c_status) +{ + printf("mpidbg_status_f2c: %lu\n", (long unsigned int) f77_status); + printf("mpidbg_status_f2c: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} + +int mpidbg_status_cxx2c(mqs_image *image, mqs_image_info *image_info, + mqs_process *process, mqs_process_info *process_info, + mqs_taddr_t cxx_status, + mqs_taddr_t *c_status) +{ + printf("mpidbg_status_cxx2c: %p\n", (void*) cxx_status); + printf("mpidbg_status_cxx2c: not [yet] found\n"); + return MPIDBG_ERR_NOT_FOUND; +} diff --git a/ompi/debuggers/ompi_mpihandles_dll_defs.h b/ompi/debuggers/ompi_mpihandles_dll_defs.h new file mode 100644 index 0000000000..238485177c --- /dev/null +++ b/ompi/debuggers/ompi_mpihandles_dll_defs.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2007-2008 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +/********************************************************************** + * Copyright (C) 2000-2004 by Etnus, LLC. + * Copyright (C) 1999 by Etnus, Inc. + * Copyright (C) 1997-1998 Dolphin Interconnect Solutions Inc. + * + * Permission is hereby granted to use, reproduce, prepare derivative + * works, and to redistribute to others. + * + * DISCLAIMER + * + * Neither Dolphin Interconnect Solutions, Etnus LLC, nor any of their + * employees, makes any warranty express or implied, or assumes any + * legal liability or responsibility for the accuracy, completeness, + * or usefulness of any information, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately + * owned rights. + * + * This code was written by + * James Cownie: Dolphin Interconnect Solutions. + * Etnus LLC + **********************************************************************/ + +#ifndef OMPI_MPIHANDLES_DLL_DEFS_H +#define OMPI_MPIHANDLES_DLL_DEFS_H + +#include "ompi_common_dll_defs.h" + +/* JMS nothing specific yet */ + +#endif diff --git a/ompi/debuggers/ompi_dll.c b/ompi/debuggers/ompi_msgq_dll.c similarity index 62% rename from ompi/debuggers/ompi_dll.c rename to ompi/debuggers/ompi_msgq_dll.c index 20fcf7d0a5..bfddecd7d4 100644 --- a/ompi/debuggers/ompi_dll.c +++ b/ompi/debuggers/ompi_msgq_dll.c @@ -1,4 +1,15 @@ -/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2007 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + /********************************************************************** * Copyright (C) 2000-2004 by Etnus, LLC. * Copyright (C) 1999 by Etnus, Inc. @@ -46,11 +57,6 @@ * Oct 27 1997 JHC: Created by exploding db_message_state_mpich.cxx */ -/** - * Right now there is no MPI2 support - */ -#define FOR_MPI2 0 - /* The following was added by William Gropp to improve the portability to systems with non-ANSI C compilers @@ -69,8 +75,8 @@ #endif /* defined(HAVE_STDLIB_H) */ #include "ompi/mca/pml/base/pml_base_request.h" -#include "mpi_interface.h" -#include "ompi_dll_defs.h" +#include "msgq_interface.h" +#include "ompi_msgq_dll_defs.h" /* End of inclusion @@ -116,13 +122,9 @@ #endif /* VERBOSE */ /**********************************************************************/ -/* Set up the basic callbacks into the debugger, also work out - * one crucial piece of info about the machine we're running on. - */ -static const mqs_basic_callbacks *mqs_basic_entrypoints; -static int host_is_big_endian; -/* Temporary workaround for making Totalview to load these symbols in the library - * when this is compiled with the Sun Studio C compiler */ +/* Set up the basic callbacks into the debugger */ +/* Temporary workaround for making Totalview to load these symbols in + * the library when this is compiled with the Sun Studio C compiler */ #if defined(__SUNPRO_C) bool opal_uses_threads; bool opal_mutex_check_locks; @@ -132,38 +134,9 @@ int opal_progress_spin_count; void mqs_setup_basic_callbacks (const mqs_basic_callbacks * cb) { - int t = 1; - - host_is_big_endian = (*(char *)&t) != 1; - mqs_basic_entrypoints = cb; + mqs_basic_entrypoints = cb; } /* mqs_setup_callbacks */ -/**********************************************************************/ -/* Macros to make it transparent that we're calling the TV functions - * through function pointers. - */ -#define mqs_malloc (mqs_basic_entrypoints->mqs_malloc_fp) -#define mqs_free (mqs_basic_entrypoints->mqs_free_fp) -#define mqs_prints (mqs_basic_entrypoints->mqs_dprints_fp) -#define mqs_put_image_info (mqs_basic_entrypoints->mqs_put_image_info_fp) -#define mqs_get_image_info (mqs_basic_entrypoints->mqs_get_image_info_fp) -#define mqs_put_process_info (mqs_basic_entrypoints->mqs_put_process_info_fp) -#define mqs_get_process_info (mqs_basic_entrypoints->mqs_get_process_info_fp) - -/* These macros *RELY* on the function already having set up the conventional - * local variables i_info or p_info. - */ -#define mqs_find_type (i_info->image_callbacks->mqs_find_type_fp) -#define mqs_field_offset (i_info->image_callbacks->mqs_field_offset_fp) -#define mqs_sizeof (i_info->image_callbacks->mqs_sizeof_fp) -#define mqs_get_type_sizes (i_info->image_callbacks->mqs_get_type_sizes_fp) -#define mqs_find_function (i_info->image_callbacks->mqs_find_function_fp) -#define mqs_find_symbol (i_info->image_callbacks->mqs_find_symbol_fp) - -#define mqs_get_image (p_info->process_callbacks->mqs_get_image_fp) -#define mqs_get_global_rank (p_info->process_callbacks->mqs_get_global_rank_fp) -#define mqs_fetch_data (p_info->process_callbacks->mqs_fetch_data_fp) -#define mqs_target_to_host (p_info->process_callbacks->mqs_target_to_host_fp) /**********************************************************************/ /* Version handling functions. @@ -187,128 +160,6 @@ int mqs_dll_taddr_width (void) return sizeof (mqs_taddr_t); } /* mqs_dll_taddr_width */ -/**********************************************************************/ -/* Additional error codes and error string conversion. - */ -enum { - err_silent_failure = mqs_first_user_code, - - err_no_current_communicator, - err_bad_request, - err_no_store, - - err_failed_qhdr, - err_unexpected, - err_posted, - - err_failed_queue, - err_first, - - err_context_id, - err_tag, - err_tagmask, - err_lsrc, - err_srcmask, - err_next, - err_ptr, - - err_missing_type, - err_missing_symbol, - - err_db_shandle, - err_db_comm, - err_db_target, - err_db_tag, - err_db_data, - err_db_byte_length, - err_db_next, - - err_failed_rhandle, - err_is_complete, - err_buf, - err_len, - err_s, - - err_failed_status, - err_count, - err_MPI_SOURCE, - err_MPI_TAG, - - err_failed_commlist, - err_sequence_number, - err_comm_first, - - err_failed_communicator, - err_lrank_to_grank, - err_send_context, - err_recv_context, - err_comm_next, - err_comm_name, - - err_all_communicators, - err_mpid_sends, - err_mpid_recvs, - err_group_corrupt -}; - -/*********************************************************************** - * Functions to access the image memory. They are specialized based * - * on the type we want to access and the debugged process architecture * - ***********************************************************************/ -static mqs_taddr_t fetch_pointer (mqs_process * proc, mqs_taddr_t addr, mpi_process_info *p_info) -{ - int isize = p_info->sizes.pointer_size; - char buffer[8]; /* ASSUME the type fits in 8 bytes */ - mqs_taddr_t res = 0; - - if (mqs_ok == mqs_fetch_data (proc, addr, isize, buffer)) - mqs_target_to_host (proc, buffer, - ((char *)&res) + (host_is_big_endian ? sizeof(mqs_taddr_t)-isize : 0), - isize); - - return res; -} /* fetch_pointer */ - -/***********************************************************************/ -static mqs_tword_t fetch_int (mqs_process * proc, mqs_taddr_t addr, mpi_process_info *p_info) -{ - int isize = p_info->sizes.int_size; - char buffer[8]; /* ASSUME the type fits in 8 bytes */ - mqs_tword_t res = 0; - - if (mqs_ok == mqs_fetch_data (proc, addr, isize, buffer)) { - mqs_target_to_host (proc, buffer, - ((char *)&res) + (host_is_big_endian ? sizeof(mqs_tword_t)-isize : 0), - isize); - } - return res; -} /* fetch_int */ - -/***********************************************************************/ -static mqs_tword_t fetch_bool(mqs_process * proc, mqs_taddr_t addr, mpi_process_info *p_info) -{ - int isize = p_info->sizes.bool_size; - mqs_tword_t res = 0; - - mqs_fetch_data (proc, addr, isize, &res); - return (0 == res ? 0 : 1); -} /* fetch_bool */ - -/***********************************************************************/ -static mqs_taddr_t fetch_size_t(mqs_process * proc, mqs_taddr_t addr, mpi_process_info *p_info) -{ - int isize = p_info->sizes.size_t_size; - char buffer[8]; /* ASSUME the type fits in 8 bytes */ - mqs_taddr_t res = 0; - - if (mqs_ok == mqs_fetch_data (proc, addr, isize, buffer)) - mqs_target_to_host (proc, buffer, - ((char *)&res) + (host_is_big_endian ? sizeof(mqs_taddr_t)-isize : 0), - isize); - - return res; -} /* fetch_size_t */ - /**********************************************************************/ /* Functions to handle translation groups. * We have a list of these on the process info, so that we can @@ -331,18 +182,19 @@ static group_t * find_or_create_group( mqs_process *proc, mqs_taddr_t table ) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; mqs_image * image = mqs_get_image (proc); mpi_image_info *i_info = (mpi_image_info *)mqs_get_image_info (image); - communicator_t *comm = p_info->communicator_list; + communicator_t *comm = extra->communicator_list; int *tr; char *trbuffer; int i, np; group_t *group; mqs_taddr_t value; - np = fetch_int( proc, - table + i_info->ompi_group_t.offset.grp_proc_count, - p_info ); + np = ompi_fetch_int( proc, + table + i_info->ompi_group_t.offset.grp_proc_count, + p_info ); if( np < 0 ) { DEBUG(VERBOSE_COMM, ("Get a size for the communicator = %d\n", np)); return NULL; /* Makes no sense ! */ @@ -384,15 +236,15 @@ static group_t * find_or_create_group( mqs_process *proc, * structure. By comparing this pointers to the MPI_COMM_WORLD group * we can figure out the global rank in the MPI_COMM_WORLD of the process. */ - if( NULL == p_info->world_proc_array ) { - p_info->world_proc_array = mqs_malloc( np * sizeof(mqs_taddr_t) ); + if( NULL == extra->world_proc_array ) { + extra->world_proc_array = mqs_malloc( np * sizeof(mqs_taddr_t) ); for( i = 0; i < np; i++ ) { mqs_target_to_host( proc, trbuffer + p_info->sizes.pointer_size*i, &value, p_info->sizes.pointer_size ); - p_info->world_proc_array[i] = value; + extra->world_proc_array[i] = value; group->local_to_global[i] = i; } - p_info->world_proc_array_entries = np; + extra->world_proc_array_entries = np; } else { int j; @@ -400,8 +252,8 @@ static group_t * find_or_create_group( mqs_process *proc, mqs_target_to_host( proc, trbuffer + p_info->sizes.pointer_size*i, &value, p_info->sizes.pointer_size ); /* get the global rank this MPI process */ - for( j = 0; j < p_info->world_proc_array_entries; j++ ) { - if( value == p_info->world_proc_array[j] ) { + for( j = 0; j < extra->world_proc_array_entries; j++ ) { + if( value == extra->world_proc_array[j] ) { group->local_to_global[i] = j; break; } @@ -441,6 +293,7 @@ int mqs_setup_image (mqs_image *image, const mqs_image_callbacks *icb) memset ((void *)i_info, 0, sizeof (mpi_image_info)); i_info->image_callbacks = icb; /* Before we do *ANYTHING* */ + i_info->extra = NULL; mqs_put_image_info (image, (mqs_image_info *)i_info); @@ -456,7 +309,8 @@ int mqs_setup_image (mqs_image *image, const mqs_image_callbacks *icb) int mqs_image_has_queues (mqs_image *image, char **message) { mpi_image_info * i_info = (mpi_image_info *)mqs_get_image_info (image); - char* missing_in_action; + + i_info->extra = NULL; /* Default failure message ! */ *message = "The symbols and types in the Open MPI library used by TotalView\n" @@ -465,239 +319,23 @@ int mqs_image_has_queues (mqs_image *image, char **message) "No message queue display is possible.\n" "This is probably an Open MPI version or configuration problem."; - /* Force in the file containing our breakpoint function, to ensure that - * types have been read from there before we try to look them up. + /* Force in the file containing our breakpoint function, to ensure + * that types have been read from there before we try to look them + * up. */ mqs_find_function (image, "MPIR_Breakpoint", mqs_lang_c, NULL); - /* Are we supposed to ignore this ? (e.g. it's really an HPF runtime using the - * Open MPI process acquisition, but not wanting queue display) + /* Are we supposed to ignore this ? (e.g. it's really an HPF + * runtime using the Open MPI process acquisition, but not wanting + * queue display) */ if (mqs_find_symbol (image, "MPIR_Ignore_queues", NULL) == mqs_ok) { *message = NULL; /* Fail silently */ return err_silent_failure; } - /** - * Open MPI use a bunch of lists in order to keep track of the internal - * objects. We have to make sure we're able to find all of them in the image - * and compute their ofset in order to be able to parse them later. - * We need to find the opal_list_item_t, the opal_list_t, the ompi_free_list_item_t, - * and the ompi_free_list_t. - * - * Once we have these offsets, we should make sure that we have access to all - * requests lists and types. We're looking here only at the basic type for the - * requests as they hold all the information we need to export to the debugger. - */ - { - mqs_type* qh_type = mqs_find_type( image, "opal_list_item_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "opal_list_item_t"; - goto type_missing; - } - i_info->opal_list_item_t.size = mqs_sizeof(qh_type); - i_info->opal_list_item_t.offset.opal_list_next = mqs_field_offset(qh_type, "opal_list_next"); - } - { - mqs_type* qh_type = mqs_find_type( image, "opal_list_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "opal_list_t"; - goto type_missing; - } - i_info->opal_list_t.size = mqs_sizeof(qh_type); - i_info->opal_list_t.offset.opal_list_sentinel = mqs_field_offset(qh_type, "opal_list_sentinel"); - } - { - mqs_type* qh_type = mqs_find_type( image, "ompi_free_list_item_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_free_list_item_t"; - goto type_missing; - } - /* This is just an overloaded opal_list_item_t */ - i_info->ompi_free_list_item_t.size = mqs_sizeof(qh_type); - } - { - mqs_type* qh_type = mqs_find_type( image, "ompi_free_list_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_free_list_t"; - goto type_missing; - } - i_info->ompi_free_list_t.size = mqs_sizeof(qh_type); - i_info->ompi_free_list_t.offset.fl_elem_class = mqs_field_offset(qh_type, "fl_elem_class"); - i_info->ompi_free_list_t.offset.fl_mpool = mqs_field_offset(qh_type, "fl_mpool"); - i_info->ompi_free_list_t.offset.fl_elem_size = mqs_field_offset(qh_type, "fl_elem_size"); - i_info->ompi_free_list_t.offset.fl_alignment = mqs_field_offset(qh_type, "fl_alignment"); - i_info->ompi_free_list_t.offset.fl_allocations = mqs_field_offset(qh_type, "fl_allocations"); - i_info->ompi_free_list_t.offset.fl_max_to_alloc = mqs_field_offset(qh_type, "fl_max_to_alloc"); - i_info->ompi_free_list_t.offset.fl_num_per_alloc = mqs_field_offset(qh_type, "fl_num_per_alloc"); - i_info->ompi_free_list_t.offset.fl_num_allocated = mqs_field_offset(qh_type, "fl_num_allocated"); - } - /** - * Now let's look for all types required for reading the requests. - */ - { - mqs_type* qh_type = mqs_find_type( image, "ompi_request_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_request_t"; - goto type_missing; - } - i_info->ompi_request_t.size = mqs_sizeof(qh_type); - i_info->ompi_request_t.offset.req_type = mqs_field_offset(qh_type, "req_type"); - i_info->ompi_request_t.offset.req_status = mqs_field_offset(qh_type, "req_status"); - i_info->ompi_request_t.offset.req_complete = mqs_field_offset(qh_type, "req_complete"); - i_info->ompi_request_t.offset.req_state = mqs_field_offset(qh_type, "req_state"); - i_info->ompi_request_t.offset.req_f_to_c_index = mqs_field_offset(qh_type, "req_f_to_c_index"); - } - { - mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_request_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "mca_pml_base_request_t"; - goto type_missing; - } - i_info->mca_pml_base_request_t.size = mqs_sizeof(qh_type); - i_info->mca_pml_base_request_t.offset.req_addr = mqs_field_offset(qh_type, "req_addr"); - i_info->mca_pml_base_request_t.offset.req_count = mqs_field_offset(qh_type, "req_count"); - i_info->mca_pml_base_request_t.offset.req_peer = mqs_field_offset(qh_type, "req_peer"); - i_info->mca_pml_base_request_t.offset.req_tag = mqs_field_offset(qh_type, "req_tag"); - i_info->mca_pml_base_request_t.offset.req_comm = mqs_field_offset(qh_type, "req_comm"); - i_info->mca_pml_base_request_t.offset.req_datatype = mqs_field_offset(qh_type, "req_datatype"); - i_info->mca_pml_base_request_t.offset.req_proc = mqs_field_offset(qh_type, "req_proc"); - i_info->mca_pml_base_request_t.offset.req_sequence = mqs_field_offset(qh_type, "req_sequence"); - i_info->mca_pml_base_request_t.offset.req_type = mqs_field_offset(qh_type, "req_type"); - i_info->mca_pml_base_request_t.offset.req_pml_complete = mqs_field_offset(qh_type, "req_pml_complete"); - } - { - mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_send_request_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "mca_pml_base_send_request_t"; - goto type_missing; - } - i_info->mca_pml_base_send_request_t.size = mqs_sizeof(qh_type); - i_info->mca_pml_base_send_request_t.offset.req_addr = mqs_field_offset(qh_type, "req_addr"); - i_info->mca_pml_base_send_request_t.offset.req_bytes_packed = mqs_field_offset(qh_type, "req_bytes_packed"); - i_info->mca_pml_base_send_request_t.offset.req_send_mode = mqs_field_offset(qh_type, "req_send_mode"); - } - { - mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_recv_request_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "mca_pml_base_recv_request_t"; - goto type_missing; - } - i_info->mca_pml_base_recv_request_t.size = mqs_sizeof(qh_type); - i_info->mca_pml_base_recv_request_t.offset.req_bytes_packed = mqs_field_offset(qh_type, "req_bytes_packed"); - } - /** - * Gather information about the received fragments and theirs headers. - */ -#if 0 /* Disabled until I find a better way */ - { - mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_common_hdr_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "mca_pml_ob1_common_hdr_t"; - goto type_missing; - } - i_info->mca_pml_ob1_common_hdr_t.size = mqs_sizeof(qh_type); - i_info->mca_pml_ob1_common_hdr_t.offset.hdr_type = mqs_field_offset(qh_type, "hdr_type"); - i_info->mca_pml_ob1_common_hdr_t.offset.hdr_flags = mqs_field_offset(qh_type, "hdr_flags"); - } - { - mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_match_hdr_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "mca_pml_ob1_match_hdr_t"; - goto type_missing; - } - i_info->mca_pml_ob1_match_hdr_t.size = mqs_sizeof(qh_type); - i_info->mca_pml_ob1_match_hdr_t.offset.hdr_common = mqs_field_offset(qh_type, "hdr_common"); - i_info->mca_pml_ob1_match_hdr_t.offset.hdr_ctx = mqs_field_offset(qh_type, "hdr_ctx"); - i_info->mca_pml_ob1_match_hdr_t.offset.hdr_src = mqs_field_offset(qh_type, "hdr_src"); - i_info->mca_pml_ob1_match_hdr_t.offset.hdr_tag = mqs_field_offset(qh_type, "hdr_tag"); - i_info->mca_pml_ob1_match_hdr_t.offset.hdr_seq = mqs_field_offset(qh_type, "hdr_seq"); - } - { - mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_recv_frag_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "mca_pml_ob1_recv_frag_t"; - goto type_missing; - } - i_info->mca_pml_ob1_recv_frag_t.size = mqs_sizeof(qh_type); - i_info->mca_pml_ob1_recv_frag_t.offset.hdr = mqs_field_offset(qh_type, "hdr"); - i_info->mca_pml_ob1_recv_frag_t.offset.request = mqs_field_offset(qh_type, "request"); - } -#endif - /** - * And now let's look at the communicator and group structures. - */ - { - mqs_type* qh_type = mqs_find_type( image, "opal_pointer_array_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "opal_pointer_array_t"; - goto type_missing; - } - i_info->opal_pointer_array_t.size = mqs_sizeof(qh_type); - i_info->opal_pointer_array_t.offset.lowest_free = mqs_field_offset(qh_type, "lowest_free"); - i_info->opal_pointer_array_t.offset.number_free = mqs_field_offset(qh_type, "number_free"); - i_info->opal_pointer_array_t.offset.size = mqs_field_offset(qh_type, "size"); - i_info->opal_pointer_array_t.offset.addr = mqs_field_offset(qh_type, "addr"); - } - { - mqs_type* qh_type = mqs_find_type( image, "ompi_communicator_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_communicator_t"; - goto type_missing; - } - i_info->ompi_communicator_t.size = mqs_sizeof(qh_type); - i_info->ompi_communicator_t.offset.c_name = mqs_field_offset(qh_type, "c_name"); - i_info->ompi_communicator_t.offset.c_contextid = mqs_field_offset(qh_type, "c_contextid"); - i_info->ompi_communicator_t.offset.c_my_rank = mqs_field_offset(qh_type, "c_my_rank" ); - i_info->ompi_communicator_t.offset.c_local_group = mqs_field_offset(qh_type, "c_local_group" ); - } - { - mqs_type* qh_type = mqs_find_type( image, "ompi_group_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_group_t"; - goto type_missing; - } - i_info->ompi_group_t.size = mqs_sizeof(qh_type); - i_info->ompi_group_t.offset.grp_proc_count = mqs_field_offset(qh_type, "grp_proc_count"); - i_info->ompi_group_t.offset.grp_my_rank = mqs_field_offset(qh_type, "grp_my_rank"); - i_info->ompi_group_t.offset.grp_flags = mqs_field_offset(qh_type, "grp_flags" ); - } - { - mqs_type* qh_type = mqs_find_type( image, "ompi_status_public_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_status_public_t"; - goto type_missing; - } - i_info->ompi_status_public_t.size = mqs_sizeof(qh_type); - i_info->ompi_status_public_t.offset.MPI_SOURCE = mqs_field_offset(qh_type, "MPI_SOURCE"); - i_info->ompi_status_public_t.offset.MPI_TAG = mqs_field_offset(qh_type, "MPI_TAG"); - i_info->ompi_status_public_t.offset.MPI_ERROR = mqs_field_offset(qh_type, "MPI_ERROR" ); - i_info->ompi_status_public_t.offset._count = mqs_field_offset(qh_type, "_count" ); - i_info->ompi_status_public_t.offset._cancelled = mqs_field_offset(qh_type, "_cancelled" ); - } - { - mqs_type* qh_type = mqs_find_type( image, "ompi_datatype_t", mqs_lang_c ); - if( !qh_type ) { - missing_in_action = "ompi_datatype_t"; - goto type_missing; - } - i_info->ompi_datatype_t.size = mqs_sizeof(qh_type); - i_info->ompi_datatype_t.offset.size = mqs_field_offset(qh_type, "size"); - i_info->ompi_datatype_t.offset.name = mqs_field_offset(qh_type, "name"); - } - - /* All the types are here. Let's succesfully return. */ - return mqs_ok; - - type_missing: - /** - * One of the required types is missing in the image. We are unable to extract - * the information we need from the pointers. We did our best but here - * we're at our limit. Give up! - */ - *message = missing_in_action; - printf( "The following type is missing %s\n", missing_in_action ); - return err_missing_type; + /* Fill in the type information */ + return ompi_fill_in_type_info(image, message); } /* mqs_image_has_queues */ /*********************************************************************** @@ -714,62 +352,67 @@ int mqs_setup_process (mqs_process *process, const mqs_process_callbacks *pcb) if (p_info) { mqs_image *image; mpi_image_info *i_info; + mpi_process_info_extra *extra; p_info->process_callbacks = pcb; + p_info->extra = mqs_malloc(sizeof(mpi_process_info_extra)); + extra = (mpi_process_info_extra*) p_info->extra; + /* Now we can get the rest of the info ! */ image = mqs_get_image (process); i_info = (mpi_image_info *)mqs_get_image_info (image); /* We have no communicators yet */ - p_info->communicator_list = NULL; + extra->communicator_list = NULL; /* Enforce the generation of the communicators list */ - p_info->comm_lowest_free = 0; - p_info->comm_number_free = 0; + extra->comm_lowest_free = 0; + extra->comm_number_free = 0; /* By default we don't show our internal requests*/ - p_info->show_internal_requests = 0; + extra->show_internal_requests = 0; - p_info->world_proc_array_entries = 0; - p_info->world_proc_array = NULL; + extra->world_proc_array_entries = 0; + extra->world_proc_array = NULL; mqs_get_type_sizes (process, &p_info->sizes); - /** - * Before going any further make sure we know exactly how the Open MPI - * library was compiled. This means we know the size of each of the basic - * types as stored in the MPIR_debug_typedefs_sizeof array. + /* + * Before going any further make sure we know exactly how the + * Open MPI library was compiled. This means we know the size + * of each of the basic types as stored in the + * MPIR_debug_typedefs_sizeof array. */ { mqs_taddr_t typedefs_sizeof; if(mqs_find_symbol (image, "MPIR_debug_typedefs_sizeof", &typedefs_sizeof) != mqs_ok) return err_no_store; - p_info->sizes.short_size = fetch_int( process, /* sizeof (short) */ - typedefs_sizeof, - p_info ); + p_info->sizes.short_size = ompi_fetch_int( process, /* sizeof (short) */ + typedefs_sizeof, + p_info ); typedefs_sizeof += p_info->sizes.int_size; - p_info->sizes.int_size = fetch_int( process, /* sizeof (int) */ - typedefs_sizeof, - p_info ); + p_info->sizes.int_size = ompi_fetch_int( process, /* sizeof (int) */ + typedefs_sizeof, + p_info ); typedefs_sizeof += p_info->sizes.int_size; - p_info->sizes.long_size = fetch_int( process, /* sizeof (long) */ - typedefs_sizeof, - p_info ); + p_info->sizes.long_size = ompi_fetch_int( process, /* sizeof (long) */ + typedefs_sizeof, + p_info ); typedefs_sizeof += p_info->sizes.int_size; - p_info->sizes.long_long_size = fetch_int( process, /* sizeof (long long) */ - typedefs_sizeof, - p_info ); + p_info->sizes.long_long_size = ompi_fetch_int( process, /* sizeof (long long) */ + typedefs_sizeof, + p_info ); typedefs_sizeof += p_info->sizes.int_size; - p_info->sizes.pointer_size = fetch_int( process, /* sizeof (void *) */ - typedefs_sizeof, - p_info ); + p_info->sizes.pointer_size = ompi_fetch_int( process, /* sizeof (void *) */ + typedefs_sizeof, + p_info ); typedefs_sizeof += p_info->sizes.int_size; - p_info->sizes.bool_size = fetch_int( process, /* sizeof (bool) */ - typedefs_sizeof, - p_info ); + p_info->sizes.bool_size = ompi_fetch_int( process, /* sizeof (bool) */ + typedefs_sizeof, + p_info ); typedefs_sizeof += p_info->sizes.int_size; - p_info->sizes.size_t_size = fetch_int( process, /* sizeof (size_t) */ - typedefs_sizeof, - p_info ); + p_info->sizes.size_t_size = ompi_fetch_int( process, /* sizeof (size_t) */ + typedefs_sizeof, + p_info ); DEBUG( VERBOSE_GENERAL, ("sizes short = %d int = %d long = %d long long = %d " "void* = %d bool = %d size_t = %d\n", @@ -792,19 +435,20 @@ int mqs_setup_process (mqs_process *process, const mqs_process_callbacks *pcb) int mqs_process_has_queues (mqs_process *proc, char **msg) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; mqs_image * image = mqs_get_image (proc); mpi_image_info *i_info = (mpi_image_info *)mqs_get_image_info (image); /* Don't bother with a pop up here, it's unlikely to be helpful */ *msg = 0; DEBUG(VERBOSE_GENERAL,("checking the status of the OMPI dll\n")); - if (mqs_find_symbol (image, "ompi_mpi_communicators", &p_info->commlist_base) != mqs_ok) + if (mqs_find_symbol (image, "ompi_mpi_communicators", &extra->commlist_base) != mqs_ok) return err_all_communicators; - if (mqs_find_symbol (image, "mca_pml_base_send_requests", &p_info->send_queue_base) != mqs_ok) + if (mqs_find_symbol (image, "mca_pml_base_send_requests", &extra->send_queue_base) != mqs_ok) return err_mpid_sends; - if (mqs_find_symbol (image, "mca_pml_base_recv_requests", &p_info->recv_queue_base) != mqs_ok) + if (mqs_find_symbol (image, "mca_pml_base_recv_requests", &extra->recv_queue_base) != mqs_ok) return err_mpid_recvs; DEBUG(VERBOSE_GENERAL,("process_has_queues returned success\n")); return mqs_ok; @@ -817,25 +461,26 @@ int mqs_process_has_queues (mqs_process *proc, char **msg) static int communicators_changed (mqs_process *proc) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; mqs_image * image = mqs_get_image (proc); mpi_image_info *i_info = (mpi_image_info *)mqs_get_image_info (image); mqs_tword_t number_free; /* the number of available positions in * the communicator array. */ mqs_tword_t lowest_free; /* the lowest free communicator */ - lowest_free = fetch_int( proc, - p_info->commlist_base + i_info->opal_pointer_array_t.offset.lowest_free, - p_info ); - number_free = fetch_int( proc, - p_info->commlist_base + i_info->opal_pointer_array_t.offset.number_free, - p_info ); - if( (lowest_free != p_info->comm_lowest_free) || - (number_free != p_info->comm_number_free) ) { + lowest_free = ompi_fetch_int( proc, + extra->commlist_base + i_info->opal_pointer_array_t.offset.lowest_free, + p_info ); + number_free = ompi_fetch_int( proc, + extra->commlist_base + i_info->opal_pointer_array_t.offset.number_free, + p_info ); + if( (lowest_free != extra->comm_lowest_free) || + (number_free != extra->comm_number_free) ) { DEBUG(VERBOSE_COMM, ("Recreate the communicator list\n" " lowest_free [current] %d != [stored] %d\n" " number_free [current] %d != [stored] %d\n", - (int)lowest_free, (int)p_info->comm_lowest_free, - (int)number_free, (int)p_info->comm_number_free) ); + (int)lowest_free, (int)extra->comm_lowest_free, + (int)number_free, (int)extra->comm_number_free) ); return 1; } DEBUG(VERBOSE_COMM, ("Communicator list not modified\n") ); @@ -851,7 +496,8 @@ static int communicators_changed (mqs_process *proc) static communicator_t * find_communicator( mpi_process_info *p_info, int recv_ctx ) { - communicator_t * comm = p_info->communicator_list; + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; + communicator_t * comm = extra->communicator_list; for( ; comm; comm = comm->next ) { if( comm->comm_info.unique_id == (mqs_taddr_t)recv_ctx ) @@ -878,6 +524,7 @@ static int compare_comms (const void *a, const void *b) static int rebuild_communicator_list (mqs_process *proc) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; mqs_image * image = mqs_get_image (proc); mpi_image_info *i_info = (mpi_image_info *)mqs_get_image_info (image); communicator_t **commp, *old; @@ -895,17 +542,17 @@ static int rebuild_communicator_list (mqs_process *proc) * Start by getting the number of registered communicators in the * global communicator array. */ - comm_size = fetch_int( proc, - p_info->commlist_base + i_info->opal_pointer_array_t.offset.size, - p_info ); - lowest_free = fetch_int( proc, - p_info->commlist_base + i_info->opal_pointer_array_t.offset.lowest_free, - p_info ); - number_free = fetch_int( proc, - p_info->commlist_base + i_info->opal_pointer_array_t.offset.number_free, - p_info ); - p_info->comm_lowest_free = lowest_free; - p_info->comm_number_free = number_free; + comm_size = ompi_fetch_int( proc, + extra->commlist_base + i_info->opal_pointer_array_t.offset.size, + p_info ); + lowest_free = ompi_fetch_int( proc, + extra->commlist_base + i_info->opal_pointer_array_t.offset.lowest_free, + p_info ); + number_free = ompi_fetch_int( proc, + extra->commlist_base + i_info->opal_pointer_array_t.offset.number_free, + p_info ); + extra->comm_lowest_free = lowest_free; + extra->comm_number_free = number_free; DEBUG(VERBOSE_COMM,("Number of coms %d lowest_free %d number_free %d\n", (int)comm_size, (int)lowest_free, (int)number_free)); @@ -916,23 +563,23 @@ static int rebuild_communicator_list (mqs_process *proc) * We can use the fact that MPI_COMM_WORLD is at index 0 to force the * creation of the world_proc_array. */ - p_info->world_proc_array_entries = 0; - mqs_free( p_info->world_proc_array ); - p_info->world_proc_array = NULL; + extra->world_proc_array_entries = 0; + mqs_free( extra->world_proc_array ); + extra->world_proc_array = NULL; /* Now get the pointer to the array of pointers to communicators */ comm_addr_base = - fetch_pointer( proc, - p_info->commlist_base + i_info->opal_pointer_array_t.offset.addr, - p_info ); + ompi_fetch_pointer( proc, + extra->commlist_base + i_info->opal_pointer_array_t.offset.addr, + p_info ); DEBUG(VERBOSE_COMM,("Array of communicators starting at 0x%llx (sizeof(mqs_taddr_t*) = %d)\n", (long long)comm_addr_base, (int)sizeof(mqs_taddr_t))); for( i = 0; (commcount < (comm_size - number_free)) && (i < comm_size); i++ ) { /* Get the communicator pointer */ comm_ptr = - fetch_pointer( proc, - comm_addr_base + i * p_info->sizes.pointer_size, - p_info ); + ompi_fetch_pointer( proc, + comm_addr_base + i * p_info->sizes.pointer_size, + p_info ); DEBUG(VERBOSE_GENERAL,("Fetch communicator pointer 0x%llx\n", (long long)comm_ptr)); if( 0 == comm_ptr ) continue; commcount++; @@ -940,12 +587,12 @@ static int rebuild_communicator_list (mqs_process *proc) DEBUG(VERBOSE_GENERAL, ("Retrieve context_id from 0x%llx and local_rank from 0x%llx\n", (long long)(comm_ptr + i_info->ompi_communicator_t.offset.c_contextid), (long long)(comm_ptr + i_info->ompi_communicator_t.offset.c_my_rank))); - context_id = fetch_int( proc, - comm_ptr + i_info->ompi_communicator_t.offset.c_contextid, - p_info ); - local_rank = fetch_int( proc, - comm_ptr + i_info->ompi_communicator_t.offset.c_my_rank, - p_info ); + context_id = ompi_fetch_int( proc, + comm_ptr + i_info->ompi_communicator_t.offset.c_contextid, + p_info ); + local_rank = ompi_fetch_int( proc, + comm_ptr + i_info->ompi_communicator_t.offset.c_my_rank, + p_info ); /* Do we already have this communicator ? */ old = find_communicator(p_info, context_id); @@ -954,8 +601,8 @@ static int rebuild_communicator_list (mqs_process *proc) old = (communicator_t *)mqs_malloc (sizeof (communicator_t)); /* Save the results */ - old->next = p_info->communicator_list; - p_info->communicator_list = old; + old->next = extra->communicator_list; + extra->communicator_list = old; old->comm_ptr = comm_ptr; old->comm_info.unique_id = context_id; old->comm_info.local_rank = local_rank; @@ -964,8 +611,8 @@ static int rebuild_communicator_list (mqs_process *proc) (long)old, context_id, local_rank)); /* Now get the information about the group */ group_base = - fetch_pointer( proc, comm_ptr + i_info->ompi_communicator_t.offset.c_local_group, - p_info ); + ompi_fetch_pointer( proc, comm_ptr + i_info->ompi_communicator_t.offset.c_local_group, + p_info ); old->group = find_or_create_group( proc, group_base ); } mqs_fetch_data( proc, comm_ptr + i_info->ompi_communicator_t.offset.c_name, @@ -984,7 +631,7 @@ static int rebuild_communicator_list (mqs_process *proc) /* Now iterate over the list tidying up any communicators which * no longer exist, and cleaning the flags on any which do. */ - commp = &p_info->communicator_list; + commp = &extra->communicator_list; commcount = 0; for (; *commp; ) { communicator_t *comm = *commp; @@ -1008,7 +655,7 @@ static int rebuild_communicator_list (mqs_process *proc) /* Sort the list so that it is displayed in some semi-sane order. */ communicator_t ** comm_array = (communicator_t **) mqs_malloc(commcount * sizeof (communicator_t *)); - communicator_t *comm = p_info->communicator_list; + communicator_t *comm = extra->communicator_list; for (i=0; inext) comm_array [i] = comm; @@ -1017,11 +664,11 @@ static int rebuild_communicator_list (mqs_process *proc) qsort (comm_array, commcount, sizeof (communicator_t *), compare_comms); /* Rebuild the list */ - p_info->communicator_list = NULL; + extra->communicator_list = NULL; for (i=0; inext = p_info->communicator_list; - p_info->communicator_list = comm; + comm->next = extra->communicator_list; + extra->communicator_list = comm; } mqs_free (comm_array); @@ -1048,16 +695,17 @@ int mqs_update_communicator_list (mqs_process *proc) int mqs_setup_communicator_iterator (mqs_process *proc) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; /* Start at the front of the list again */ - p_info->current_communicator = p_info->communicator_list; + extra->current_communicator = extra->communicator_list; /* Reset the operation iterator too */ - p_info->next_msg.free_list = 0; - p_info->next_msg.current_item = 0; - p_info->next_msg.opal_list_t_pos.list = 0; + extra->next_msg.free_list = 0; + extra->next_msg.current_item = 0; + extra->next_msg.opal_list_t_pos.list = 0; DEBUG(VERBOSE_COMM,("mqs_setup_communicator_iterator called\n")); - return p_info->current_communicator == NULL ? mqs_end_of_list : mqs_ok; + return extra->current_communicator == NULL ? mqs_end_of_list : mqs_ok; } /* mqs_setup_communicator_iterator */ /*********************************************************************** @@ -1066,9 +714,10 @@ int mqs_setup_communicator_iterator (mqs_process *proc) int mqs_get_communicator (mqs_process *proc, mqs_communicator *comm) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; - if (p_info->current_communicator) { - *comm = p_info->current_communicator->comm_info; + if (extra->current_communicator) { + *comm = extra->current_communicator->comm_info; DEBUG(VERBOSE_COMM,("mqs_get_communicator %d local_rank %d name %s\n", comm->unique_id, (int)comm->local_rank, comm->name)); @@ -1084,7 +733,8 @@ int mqs_get_communicator (mqs_process *proc, mqs_communicator *comm) int mqs_get_comm_group (mqs_process *proc, int *group_members) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); - communicator_t *comm = p_info->current_communicator; + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; + communicator_t *comm = extra->current_communicator; if (comm && comm->group) { group_t * g = comm->group; @@ -1104,9 +754,10 @@ int mqs_get_comm_group (mqs_process *proc, int *group_members) int mqs_next_communicator (mqs_process *proc) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; - p_info->current_communicator = p_info->current_communicator->next; - return (p_info->current_communicator != NULL) ? mqs_ok : mqs_end_of_list; + extra->current_communicator = extra->current_communicator->next; + return (extra->current_communicator != NULL) ? mqs_ok : mqs_end_of_list; } /* mqs_next_communicator */ /** @@ -1121,8 +772,8 @@ static int opal_list_t_init_parser( mqs_process *proc, mpi_process_info *p_info, position->list = list; position->sentinel = position->list + i_info->opal_list_t.offset.opal_list_sentinel; position->current_item = - fetch_pointer( proc, position->sentinel + i_info->opal_list_item_t.offset.opal_list_next, - p_info ); + ompi_fetch_pointer( proc, position->sentinel + i_info->opal_list_item_t.offset.opal_list_next, + p_info ); if( position->current_item == position->sentinel ) position->current_item = 0; DEBUG(VERBOSE_LISTS,("opal_list_t_init_parser list = 0x%llx, sentinel = 0x%llx, " @@ -1142,9 +793,9 @@ static int next_item_opal_list_t( mqs_process *proc, mpi_process_info *p_info, return mqs_end_of_list; position->current_item = - fetch_pointer( proc, - position->current_item + i_info->opal_list_item_t.offset.opal_list_next, - p_info ); + ompi_fetch_pointer( proc, + position->current_item + i_info->opal_list_item_t.offset.opal_list_next, + p_info ); if( position->current_item == position->sentinel ) position->current_item = 0; return mqs_ok; @@ -1183,23 +834,23 @@ static int ompi_free_list_t_init_parser( mqs_process *proc, mpi_process_info *p_ position->free_list = free_list; position->fl_elem_size = - fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_elem_size, - p_info ); + ompi_fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_elem_size, + p_info ); position->fl_alignment = - fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_alignment, - p_info ); + ompi_fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_alignment, + p_info ); position->fl_elem_class = - fetch_pointer( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_elem_class, - p_info ); + ompi_fetch_pointer( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_elem_class, + p_info ); position->fl_mpool = - fetch_pointer( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_mpool, - p_info ); + ompi_fetch_pointer( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_mpool, + p_info ); position->fl_num_per_alloc = - fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_num_per_alloc, - p_info ); + ompi_fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_num_per_alloc, + p_info ); position->fl_num_allocated = - fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_num_allocated, - p_info ); + ompi_fetch_size_t( proc, position->free_list + i_info->ompi_free_list_t.offset.fl_num_allocated, + p_info ); if( 0 == position->fl_mpool ) { position->header_space = position->fl_elem_size; @@ -1366,21 +1017,22 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, mqs_taddr_t current_item; mqs_tword_t req_complete, req_pml_complete, req_valid, req_type; mqs_taddr_t req_buffer, req_comm; + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; /* If we get a PML request with an internal tag we will jump back here */ rescan_requests: while( 1 ) { ompi_free_list_t_next_item( proc, p_info, - &p_info->next_msg, ¤t_item ); + &extra->next_msg, ¤t_item ); if( 0 == current_item ) { DEBUG(VERBOSE_REQ,("no more items in the %s request queue\n", look_for_user_buffer ? "receive" : "send" )); return mqs_end_of_list; } - req_valid = fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_state, p_info ); + req_valid = ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_state, p_info ); if( OMPI_REQUEST_INVALID == req_valid ) continue; - req_comm = fetch_pointer( proc, current_item + i_info->mca_pml_base_request_t.offset.req_comm, p_info ); - if( p_info->current_communicator->comm_ptr == req_comm ) break; + req_comm = ompi_fetch_pointer( proc, current_item + i_info->mca_pml_base_request_t.offset.req_comm, p_info ); + if( extra->current_communicator->comm_ptr == req_comm ) break; DEBUG(VERBOSE_REQ,("unmatched request (0x%llx) req_comm = %llx current_com = %llx\n", (long long)current_item, (long long)req_comm, (long long)p_info->current_communicator->comm_ptr)); @@ -1389,7 +1041,7 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, res->extra_text[0][0] = 0; res->extra_text[1][0] = 0; res->extra_text[2][0] = 0; res->extra_text[3][0] = 0; res->extra_text[4][0] = 0; - req_type = fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_type, p_info ); + req_type = ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_type, p_info ); if( OMPI_REQUEST_PML == req_type ) { mqs_taddr_t ompi_datatype; char data_name[64]; @@ -1399,47 +1051,47 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, * request the internal requests information then move along. */ res->desired_tag = - fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_tag, p_info ); + ompi_fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_tag, p_info ); if( MPI_ANY_TAG == (int)res->desired_tag ) { res->tag_wild = TRUE; } else { /* Don't allow negative tags to show up */ - if( ((int)res->desired_tag < 0) && (0 == p_info->show_internal_requests) ) + if( ((int)res->desired_tag < 0) && (0 == extra->show_internal_requests) ) goto rescan_requests; res->tag_wild = FALSE; } req_type = - fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_type, - p_info); + ompi_fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_type, + p_info); req_complete = - fetch_bool( proc, - current_item + i_info->ompi_request_t.offset.req_complete, - p_info ); + ompi_fetch_bool( proc, + current_item + i_info->ompi_request_t.offset.req_complete, + p_info ); req_pml_complete = - fetch_bool( proc, - current_item + i_info->mca_pml_base_request_t.offset.req_pml_complete, - p_info ); + ompi_fetch_bool( proc, + current_item + i_info->mca_pml_base_request_t.offset.req_pml_complete, + p_info ); res->status = (0 == req_complete ? mqs_st_pending : mqs_st_complete); - res->desired_local_rank = fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_peer, p_info ); - res->desired_global_rank = translate( p_info->current_communicator->group, + res->desired_local_rank = ompi_fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_peer, p_info ); + res->desired_global_rank = translate( extra->current_communicator->group, res->desired_local_rank ); - res->buffer = fetch_pointer( proc, current_item + i_info->mca_pml_base_request_t.offset.req_addr, + res->buffer = ompi_fetch_pointer( proc, current_item + i_info->mca_pml_base_request_t.offset.req_addr, p_info ); /* Set this to true if it's a buffered request */ res->system_buffer = FALSE; /* The pointer to the request datatype */ ompi_datatype = - fetch_pointer( proc, - current_item + i_info->mca_pml_base_request_t.offset.req_datatype, p_info ); + ompi_fetch_pointer( proc, + current_item + i_info->mca_pml_base_request_t.offset.req_datatype, p_info ); /* Retrieve the count as specified by the user */ res->desired_length = - fetch_size_t( proc, - ompi_datatype + i_info->ompi_datatype_t.offset.size, - p_info ); + ompi_fetch_size_t( proc, + ompi_datatype + i_info->ompi_datatype_t.offset.size, + p_info ); /* Be user friendly, show the datatype name */ mqs_fetch_data( proc, ompi_datatype + i_info->ompi_datatype_t.offset.name, 64, data_name ); @@ -1449,20 +1101,20 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, } /* And now compute the real length as specified by the user */ res->desired_length *= - fetch_size_t( proc, - current_item + i_info->mca_pml_base_request_t.offset.req_count, - p_info ); + ompi_fetch_size_t( proc, + current_item + i_info->mca_pml_base_request_t.offset.req_count, + p_info ); if( MCA_PML_REQUEST_SEND == req_type ) { snprintf( (char *)res->extra_text[0], 64, "Send: 0x%llx", (long long)current_item ); req_buffer = - fetch_pointer( proc, - current_item + i_info->mca_pml_base_send_request_t.offset.req_addr, - p_info ); + ompi_fetch_pointer( proc, + current_item + i_info->mca_pml_base_send_request_t.offset.req_addr, + p_info ); res->system_buffer = ( req_buffer == res->buffer ? FALSE : TRUE ); res->actual_length = - fetch_size_t( proc, - current_item + i_info->mca_pml_base_send_request_t.offset.req_bytes_packed, p_info ); + ompi_fetch_size_t( proc, + current_item + i_info->mca_pml_base_send_request_t.offset.req_bytes_packed, p_info ); res->actual_tag = res->desired_tag; res->actual_local_rank = res->desired_local_rank; res->actual_global_rank = res->actual_local_rank; @@ -1474,18 +1126,18 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, * is matched. */ res->actual_tag = - fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + - i_info->ompi_status_public_t.offset.MPI_TAG, p_info ); + ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + + i_info->ompi_status_public_t.offset.MPI_TAG, p_info ); if( MPI_ANY_TAG != (int)res->actual_tag ) { res->status = mqs_st_matched; res->desired_length = - fetch_size_t( proc, - current_item + i_info->mca_pml_base_recv_request_t.offset.req_bytes_packed, - p_info ); + ompi_fetch_size_t( proc, + current_item + i_info->mca_pml_base_recv_request_t.offset.req_bytes_packed, + p_info ); res->actual_local_rank = - fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + - i_info->ompi_status_public_t.offset.MPI_SOURCE, p_info ); - res->actual_global_rank = translate( p_info->current_communicator->group, + ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + + i_info->ompi_status_public_t.offset.MPI_SOURCE, p_info ); + res->actual_global_rank = translate( extra->current_communicator->group, res->actual_local_rank ); } } else { @@ -1497,19 +1149,19 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, /* If the length we're looking for is the count ... */ /*res->desired_length = - fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_count, p_info );*/ + ompi_fetch_int( proc, current_item + i_info->mca_pml_base_request_t.offset.req_count, p_info );*/ if( (mqs_st_pending < res->status) && (MCA_PML_REQUEST_SEND != req_type) ) { /* The real data from the status */ res->actual_length = - fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + - i_info->ompi_status_public_t.offset._count, p_info ); + ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + + i_info->ompi_status_public_t.offset._count, p_info ); res->actual_tag = - fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + - i_info->ompi_status_public_t.offset.MPI_TAG, p_info ); + ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + + i_info->ompi_status_public_t.offset.MPI_TAG, p_info ); res->actual_local_rank = - fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + - i_info->ompi_status_public_t.offset.MPI_SOURCE, p_info ); - res->actual_global_rank = translate( p_info->current_communicator->group, + ompi_fetch_int( proc, current_item + i_info->ompi_request_t.offset.req_status + + i_info->ompi_status_public_t.offset.MPI_SOURCE, p_info ); + res->actual_global_rank = translate( extra->current_communicator->group, res->actual_local_rank ); } dump_request( current_item, res ); @@ -1523,18 +1175,19 @@ static int fetch_request( mqs_process *proc, mpi_process_info *p_info, int mqs_setup_operation_iterator (mqs_process *proc, int op) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; - p_info->what = (mqs_op_class)op; + extra->what = (mqs_op_class)op; switch (op) { case mqs_pending_sends: DEBUG(VERBOSE_REQ,("setup the send queue iterator\n")); - ompi_free_list_t_init_parser( proc, p_info, &p_info->next_msg, p_info->send_queue_base ); + ompi_free_list_t_init_parser( proc, p_info, &extra->next_msg, extra->send_queue_base ); return mqs_ok; case mqs_pending_receives: DEBUG(VERBOSE_REQ,("setup the receive queue iterator\n")); - ompi_free_list_t_init_parser( proc, p_info, &p_info->next_msg, p_info->recv_queue_base ); + ompi_free_list_t_init_parser( proc, p_info, &extra->next_msg, extra->recv_queue_base ); return mqs_ok; case mqs_unexpected_messages: /* TODO */ @@ -1554,8 +1207,9 @@ int mqs_setup_operation_iterator (mqs_process *proc, int op) int mqs_next_operation (mqs_process *proc, mqs_pending_operation *op) { mpi_process_info *p_info = (mpi_process_info *)mqs_get_process_info (proc); + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; - switch (p_info->what) { + switch (extra->what) { case mqs_pending_receives: DEBUG(VERBOSE_REQ,("digging for the receive queue\n")); return fetch_request( proc, p_info, op, TRUE ); @@ -1575,8 +1229,9 @@ int mqs_next_operation (mqs_process *proc, mqs_pending_operation *op) void mqs_destroy_process_info (mqs_process_info *mp_info) { mpi_process_info *p_info = (mpi_process_info *)mp_info; + mpi_process_info_extra *extra = (mpi_process_info_extra*) p_info->extra; /* Need to handle the communicators and groups too */ - communicator_t *comm = p_info->communicator_list; + communicator_t *comm = extra->communicator_list; while (comm) { communicator_t *next = comm->next; @@ -1587,6 +1242,9 @@ void mqs_destroy_process_info (mqs_process_info *mp_info) comm = next; } + if (NULL != extra) { + mqs_free(extra); + } mqs_free (p_info); } /* mqs_destroy_process_info */ diff --git a/ompi/debuggers/ompi_dll_defs.h b/ompi/debuggers/ompi_msgq_dll_defs.h similarity index 52% rename from ompi/debuggers/ompi_dll_defs.h rename to ompi/debuggers/ompi_msgq_dll_defs.h index 59249a1d6c..bbef17e106 100644 --- a/ompi/debuggers/ompi_dll_defs.h +++ b/ompi/debuggers/ompi_msgq_dll_defs.h @@ -1,3 +1,15 @@ +/* + * Copyright (c) 2007 Cisco, Inc. All rights resereved. + * Copyright (c) 2004-2007 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + /********************************************************************** * Copyright (C) 2000-2004 by Etnus, LLC. * Copyright (C) 1999 by Etnus, Inc. @@ -28,153 +40,10 @@ * info required by the DLL for dumping message queues. */ -/*********************************************************************** - * Information associated with a specific executable image - */ -typedef struct -{ - const struct mqs_image_callbacks * image_callbacks; /* Functions needed here */ - /* basic structures */ - struct { - int size; - struct { - int opal_list_next; - } offset; - } opal_list_item_t; - struct { - int size; - struct { - int opal_list_sentinel; - } offset; - } opal_list_t; - struct { - int size; - } ompi_free_list_item_t; - struct { - int size; - struct { - int fl_elem_class; /* opal_class_t* */ - int fl_mpool; /* struct mca_mpool_base_module_t* */ - int fl_elem_size; /* size_t */ - int fl_alignment; /* size_t */ - int fl_allocations; /* opal_list_t */ - int fl_max_to_alloc; /* size_t */ - int fl_num_per_alloc; /* size_t */ - int fl_num_allocated; /* size_t */ - } offset; - } ompi_free_list_t; - /* requests structures */ - struct { - int size; - struct { - int req_type; - int req_status; - int req_complete; - int req_state; - int req_f_to_c_index; - } offset; - } ompi_request_t; - struct { - int size; - struct { - int req_addr; - int req_count; - int req_peer; - int req_tag; - int req_comm; - int req_datatype; - int req_proc; - int req_sequence; - int req_type; - int req_pml_complete; - } offset; - } mca_pml_base_request_t; - struct { - int size; - struct { - int req_addr; - int req_bytes_packed; - int req_send_mode; - } offset; - } mca_pml_base_send_request_t; - struct { - int size; - struct { - int req_bytes_packed; - } offset; - } mca_pml_base_recv_request_t; -#if 0 - /* fragments for unexpected messages (as well as theirs headers) */ - struct { - int size; - struct { - int hdr; - int request; - } offset; - } mca_pml_ob1_recv_frag_t; - struct { - int size; - struct { - int hdr_type; - int hdr_flags; - } offset; - } mca_pml_ob1_common_hdr_t; - struct { - int size; - struct { - int hdr_common; - int hdr_ctx; - int hdr_src; - int hdr_tag; - int hdr_seq; - } offset; - } mca_pml_ob1_match_hdr_t; -#endif - /* communicator structures */ - struct { - int size; - struct { - int lowest_free; - int number_free; - int size; - int addr; - } offset; - } opal_pointer_array_t; - struct { - int size; - struct { - int grp_proc_count; - int grp_my_rank; - int grp_flags; - } offset; - } ompi_group_t; - struct { - int size; - struct { - int c_name; - int c_contextid; - int c_my_rank; - int c_local_group; - } offset; - } ompi_communicator_t; - struct { - int size; - struct { - int MPI_SOURCE; - int MPI_TAG; - int MPI_ERROR; - int _count; - int _cancelled; - } offset; - } ompi_status_public_t; - struct { - int size; - struct { - int size; - int name; - } offset; - } ompi_datatype_t; -} mpi_image_info; +#ifndef OMPI_MSGQ_DLL_DEFS_H +#define OMPI_MSGQ_DLL_DEFS_H + +#include "ompi_common_dll_defs.h" /*********************************************************************** * Information associated with a specific process @@ -225,10 +94,7 @@ typedef struct { */ typedef struct { - const struct mqs_process_callbacks * process_callbacks; /* Functions needed here */ - struct communicator_t *communicator_list; /* List of communicators in the process */ - mqs_target_type_sizes sizes; /* Process architecture information */ /* Addresses in the target process */ mqs_taddr_t send_queue_base; /* Where to find the send message queues */ @@ -248,9 +114,6 @@ typedef struct mqs_ompi_free_list_t_pos next_msg; /* And state for the message iterator */ mqs_op_class what; /* What queue are we looking on */ -} mpi_process_info; - - - - +} mpi_process_info_extra; +#endif diff --git a/ompi/mca/topo/base/topo_base_cart_coords.c b/ompi/mca/topo/base/topo_base_cart_coords.c index 2f13a66de0..725a40ad4e 100644 --- a/ompi/mca/topo/base/topo_base_cart_coords.c +++ b/ompi/mca/topo/base/topo_base_cart_coords.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -57,8 +58,7 @@ int mca_topo_base_cart_coords (MPI_Comm comm, for (i = 0; (i < comm->c_topo_comm->mtc_ndims_or_nnodes) && (i < maxdims); ++i, ++d) { - - dim = (*d > 0) ? *d : -(*d); + dim = *d; remprocs /= dim; *coords++ = rank / remprocs; rank %= remprocs; diff --git a/ompi/mca/topo/base/topo_base_cart_create.c b/ompi/mca/topo/base/topo_base_cart_create.c index 5bc5a11688..31c89791ba 100644 --- a/ompi/mca/topo/base/topo_base_cart_create.c +++ b/ompi/mca/topo/base/topo_base_cart_create.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -85,12 +86,6 @@ int mca_topo_base_cart_create (mca_topo_base_comm_t *topo_data, return MPI_SUCCESS; } - for (i = 0, p = topo_data->mtc_dims_or_index; i < ndims; ++i, ++p) { - *p = (*periods) ? -(*dims) : *dims; - ++dims; - ++periods; - } - /* Have to replace this with the actual function body itself */ p = topo_data->mtc_dims_or_index; coords = topo_data->mtc_coords; @@ -99,7 +94,7 @@ int mca_topo_base_cart_create (mca_topo_base_comm_t *topo_data, for (i=0; (i < topo_data->mtc_ndims_or_nnodes && i < ndims); ++i, ++p) { - dim = (*p > 0) ? *p : -(*p); + dim = *p; nprocs /= dim; *coords++ = dummy_rank / nprocs; dummy_rank %= nprocs; diff --git a/ompi/mca/topo/base/topo_base_cart_get.c b/ompi/mca/topo/base/topo_base_cart_get.c index ccf908cfe1..fde5fa58a4 100644 --- a/ompi/mca/topo/base/topo_base_cart_get.c +++ b/ompi/mca/topo/base/topo_base_cart_get.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -17,6 +18,11 @@ */ #include "ompi_config.h" + +#ifdef HAVE_STRING_H +#include +#endif + #include "ompi/mca/topo/base/base.h" #include "ompi/communicator/communicator.h" #include "ompi/mca/topo/topo.h" @@ -40,25 +46,14 @@ int mca_topo_base_cart_get (MPI_Comm comm, int maxdims, int *dims, int *periods, - int *coords){ - int i; - int *d; - int *c; + int *coords) +{ + int m = (maxdims <= comm->c_topo_comm->mtc_ndims_or_nnodes) ? + maxdims : comm->c_topo_comm->mtc_ndims_or_nnodes; - d = comm->c_topo_comm->mtc_dims_or_index; - c = comm->c_topo_comm->mtc_coords; - - for (i = 0; (i < comm->c_topo_comm->mtc_ndims_or_nnodes) && (i < maxdims); ++i) { - - if (*d > 0) { - *dims++ = *d++; - *periods++ = 0; - } else { - *dims++ = -(*d++); - *periods++ = 1; - } - *coords++ = *c++; - } + memcpy(dims, comm->c_topo_comm->mtc_dims_or_index, m * sizeof(int)); + memcpy(periods, comm->c_topo_comm->mtc_periods_or_edges, m * sizeof(int)); + memcpy(coords, comm->c_topo_comm->mtc_coords, m * sizeof(int)); return MPI_SUCCESS; } diff --git a/ompi/mca/topo/base/topo_base_cart_rank.c b/ompi/mca/topo/base/topo_base_cart_rank.c index 2fbad1f32e..5934960f27 100644 --- a/ompi/mca/topo/base/topo_base_cart_rank.c +++ b/ompi/mca/topo/base/topo_base_cart_rank.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -46,6 +47,7 @@ int mca_topo_base_cart_rank (MPI_Comm comm, int i; int *d; int *c; + int *p; /* * Loop over coordinates computing the rank. @@ -55,13 +57,14 @@ int mca_topo_base_cart_rank (MPI_Comm comm, i = comm->c_topo_comm->mtc_ndims_or_nnodes - 1; d = comm->c_topo_comm->mtc_dims_or_index + i; + p = comm->c_topo_comm->mtc_periods_or_edges + i; c = coords + i; - for (; i >= 0; --i, --c, --d) { - dim = (*d > 0) ? *d : -(*d); + for (; i >= 0; --i, --c, --d, --p) { + dim = *d; ord = *c; if ((ord < 0) || (ord >= dim)) { - if (*d > 0) { + if (*p) { return MPI_ERR_ARG; } ord %= dim; diff --git a/ompi/mca/topo/base/topo_base_cart_shift.c b/ompi/mca/topo/base/topo_base_cart_shift.c index 17ef22976c..31c927fd35 100644 --- a/ompi/mca/topo/base/topo_base_cart_shift.c +++ b/ompi/mca/topo/base/topo_base_cart_shift.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -52,7 +53,7 @@ int mca_topo_base_cart_shift (MPI_Comm comm, int srcord; int destord; int i; - int *p; + int *d, *q; /* * Handle the trivial case. @@ -67,14 +68,11 @@ int mca_topo_base_cart_shift (MPI_Comm comm, * Compute the rank factor and ordinate. */ factor = ompi_comm_size(comm); - p = comm->c_topo_comm->mtc_dims_or_index; - for (i = 0; (i < comm->c_topo_comm->mtc_ndims_or_nnodes) && (i <= direction); ++i, ++p) { - if ((thisdirection = *p) > 0) { - thisperiod = 0; - } else { - thisperiod = 1; - thisdirection = -thisdirection; - } + d = comm->c_topo_comm->mtc_dims_or_index; + q = comm->c_topo_comm->mtc_periods_or_edges; + for (i = 0; (i < comm->c_topo_comm->mtc_ndims_or_nnodes) && (i <= direction); ++i, ++d, ++q) { + thisdirection = *d; + thisperiod = *q; ord %= factor; factor /= thisdirection; diff --git a/ompi/mca/topo/base/topo_base_cart_sub.c b/ompi/mca/topo/base/topo_base_cart_sub.c index 2a64e06ad3..bd5ea3f0c1 100644 --- a/ompi/mca/topo/base/topo_base_cart_sub.c +++ b/ompi/mca/topo/base/topo_base_cart_sub.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -72,7 +73,7 @@ int mca_topo_base_cart_sub (MPI_Comm comm, r = remain_dims + i; for (; i >= 0; --i, --d, --c, --r) { - dim = (*d > 0) ? *d : -(*d); + dim = *d; if (*r == 0) { colour += colfactor * (*c); colfactor *= dim; diff --git a/ompi/mca/topo/unity/topo_unity.c b/ompi/mca/topo/unity/topo_unity.c index 1dfd53d5c7..43eac12b89 100644 --- a/ompi/mca/topo/unity/topo_unity.c +++ b/ompi/mca/topo/unity/topo_unity.c @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2008 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -93,36 +94,17 @@ int mca_topo_unity_component_comm_unquery (struct ompi_communicator_t *comm) int mca_topo_unity_module_init (struct ompi_communicator_t *comm) { - /* This function is used to initialize the module on the communicator. We - * need to hang the data off of the communicator. For this we still use the - * same data structure which was defined in topo.h, mca_topo_comm_1_0_0_t. - * There are no additional things which we need. If some other module needs - * to hang additional data, then it has to have this structure as the first - * member and then extend. This is a must rule */ + /* Nothing to do -- the setup is done in communicator/comm.c + (setup the comm->c_topo_comm data) */ - struct mca_topo_base_comm_1_0_0_t *topo_data; - - /* allocate the data */ - - comm->c_topo_comm = NULL; - topo_data = (mca_topo_base_comm_1_0_0_t*)malloc(sizeof(struct mca_topo_base_comm_1_0_0_t)); - if (NULL == topo_data) { - return OMPI_ERROR; - } - - comm->c_topo_comm = topo_data; - return OMPI_SUCCESS; + return OMPI_SUCCESS; } int mca_topo_unity_module_finalize (struct ompi_communicator_t *comm) { - /* All we need to do for now is to remove the allocated data */ - - if (NULL != comm->c_topo_comm) { - free (comm->c_topo_comm); - comm->c_topo = NULL; - } + /* Nothing to do -- the teardown is done in + communicator/comm_init.c (free the comm->c_topo_comm data) */ return OMPI_SUCCESS; } diff --git a/ompi/runtime/mpiruntime.h b/ompi/runtime/mpiruntime.h index fcfbcb8db8..6fa5c457b2 100644 --- a/ompi/runtime/mpiruntime.h +++ b/ompi/runtime/mpiruntime.h @@ -102,11 +102,6 @@ int ompi_mpi_finalize(void); int ompi_mpi_abort(struct ompi_communicator_t* comm, int errcode, bool kill_remote_of_intercomm); -/** - * Wait for a TotalView-like debugger if asked. - */ -void ompi_mpi_wait_for_totalview(void); - /** * Do a preconnect of MPI connections (i.e., force connections to * be made if they will be made). diff --git a/ompi/runtime/ompi_mpi_init.c b/ompi/runtime/ompi_mpi_init.c index 12a2be7f62..bbc3b28628 100644 --- a/ompi/runtime/ompi_mpi_init.c +++ b/ompi/runtime/ompi_mpi_init.c @@ -752,8 +752,8 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided) ORTE_NAME_PRINT(ORTE_PROC_MY_NAME)); } - /* Do we need to wait for a TotalView-like debugger? */ - ompi_wait_for_totalview(); + /* Do we need to wait for a debugger? */ + ompi_wait_for_debugger(); /* check for timing request - get stop time and report elapsed time if so */ if (timing) {