Blame src/mpi/debugger/dll_mpich.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2005 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/* Fixme: include the mpichconf.h file? */
Packit Service c5cf8c
Packit Service c5cf8c
/* Allow fprintf in debug statements */
Packit Service c5cf8c
/* style: allow:fprintf:5 sig:0 */
Packit Service c5cf8c
Packit Service c5cf8c
#include <stdlib.h>
Packit Service c5cf8c
#include <stdint.h>
Packit Service c5cf8c
#include <string.h>
Packit Service c5cf8c
#include "mpi.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* #define DEBUG_MPIDBG_DLL 1 */
Packit Service c5cf8c
Packit Service c5cf8c
/* Define this to have the code print out details of its list traversal
Packit Service c5cf8c
   action.  This is primarily for use with dbgstub.c and the test programs
Packit Service c5cf8c
   such as tvtest.c */
Packit Service c5cf8c
/* #define DEBUG_LIST_ITER */
Packit Service c5cf8c
Packit Service c5cf8c
/* Define this to have the code print out its operation to a file.
Packit Service c5cf8c
   This may be used to help understand how the debugger is using this
Packit Service c5cf8c
   interface */
Packit Service c5cf8c
/* #define DEBUG_MPIDBG_LOGGING */
Packit Service c5cf8c
#ifdef DEBUG_MPIDBG_LOGGING
Packit Service c5cf8c
#include <stdio.h>
Packit Service c5cf8c
FILE *debugfp = 0;
Packit Service c5cf8c
Packit Service c5cf8c
static void initLogFile(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    if (!debugfp) {
Packit Service c5cf8c
        debugfp = fopen("mpich-dbg-interface-log.txt", "w");
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
#else
Packit Service c5cf8c
/* no-op definition */
Packit Service c5cf8c
#define initLogFile()
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/* MPIR_dll_name is defined in dbg_init.c; it must be part of the target image,
Packit Service c5cf8c
   not the debugger interface */
Packit Service c5cf8c
Packit Service c5cf8c
/* mpi_interface.h defines the interface to the debugger.  This interface
Packit Service c5cf8c
   is the same for any MPI implementation, for a given debugger
Packit Service c5cf8c
   (a more precise name might be mpi_tv_interface.h) */
Packit Service c5cf8c
#include "mpi_interface.h"
Packit Service c5cf8c
/* mpich_dll_defs.h defines the structures for a particular MPI
Packit Service c5cf8c
   implementation (MPICH in this case) */
Packit Service c5cf8c
#include "mpich_dll_defs.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* style: allow:strncpy:1 sig:0 */
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Local variables for this package */
Packit Service c5cf8c
Packit Service c5cf8c
static const mqs_basic_callbacks *mqs_basic_entrypoints = 0;
Packit Service c5cf8c
static int host_is_big_endian = -1;
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Error values. */
Packit Service c5cf8c
enum {
Packit Service c5cf8c
    err_silent_failure = mqs_first_user_code,
Packit Service c5cf8c
Packit Service c5cf8c
    err_no_current_communicator,
Packit Service c5cf8c
    err_bad_request,
Packit Service c5cf8c
    err_no_store,
Packit Service c5cf8c
    err_all_communicators,
Packit Service c5cf8c
    err_group_corrupt,
Packit Service c5cf8c
Packit Service c5cf8c
    err_failed_qhdr,
Packit Service c5cf8c
    err_unexpected,
Packit Service c5cf8c
    err_posted,
Packit Service c5cf8c
Packit Service c5cf8c
    err_failed_queue,
Packit Service c5cf8c
    err_first,
Packit Service c5cf8c
Packit Service c5cf8c
};
Packit Service c5cf8c
Packit Service c5cf8c
/* Internal structure we hold for each communicator */
Packit Service c5cf8c
typedef struct communicator_t {
Packit Service c5cf8c
    struct communicator_t *next;
Packit Service c5cf8c
    group_t *group;             /* Translations */
Packit Service c5cf8c
    int context_id;             /* To catch changes */
Packit Service c5cf8c
    int recvcontext_id;         /* May also be needed for
Packit Service c5cf8c
                                 * matchine */
Packit Service c5cf8c
    int present;
Packit Service c5cf8c
    mqs_communicator comm_info; /* Info needed at the higher level */
Packit Service c5cf8c
} communicator_t;
Packit Service c5cf8c
Packit Service c5cf8c
/* Internal functions used only by routines in this package */
Packit Service c5cf8c
static void mqs_free_communicator_list(struct communicator_t *comm);
Packit Service c5cf8c
Packit Service c5cf8c
static int communicators_changed(mqs_process * proc);
Packit Service c5cf8c
static int rebuild_communicator_list(mqs_process * proc);
Packit Service c5cf8c
static int compare_comms(const void *a, const void *b);
Packit Service c5cf8c
Packit Service c5cf8c
static group_t *find_or_create_group(mqs_process * proc, mqs_tword_t np, mqs_taddr_t table);
Packit Service c5cf8c
static int translate(group_t * this, int idx);
Packit Service c5cf8c
#if 0
Packit Service c5cf8c
static int reverse_translate(group_t * this, int idx);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
static void group_decref(group_t * group);
Packit Service c5cf8c
static communicator_t *find_communicator(mpich_process_info * p_info,
Packit Service c5cf8c
                                         mqs_taddr_t comm_base, int recv_ctx);
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Many of the services used by this file are performed by calling
Packit Service c5cf8c
 * functions executed by the debugger.  In other words, these are routines
Packit Service c5cf8c
 * that the debugger must export to this package.  To make it easy to
Packit Service c5cf8c
 * identify these functions as well as to make their use simple,
Packit Service c5cf8c
 * we use macros that start with dbgr_xxx (for debugger).  These
Packit Service c5cf8c
 * function pointers are set early in the initialization phase.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Note: to avoid any changes to the mpi_interface.h file, the fields in
Packit Service c5cf8c
 * the structures that contain the function pointers have not been
Packit Service c5cf8c
 * renamed dbgr_xxx and continue to use their original mqs_ prefix.
Packit Service c5cf8c
 * Using the dbgr_ prefix for the debugger-provided callbacks was done to
Packit Service c5cf8c
 * make it more obvious whether the debugger or the MPI interface DLL is
Packit Service c5cf8c
 * responsible for providing the function.
Packit Service c5cf8c
 */
Packit Service c5cf8c
#define dbgr_malloc           (mqs_basic_entrypoints->mqs_malloc_fp)
Packit Service c5cf8c
#define dbgr_free             (mqs_basic_entrypoints->mqs_free_fp)
Packit Service c5cf8c
#define dbgr_prints           (mqs_basic_entrypoints->mqs_eprints_fp)
Packit Service c5cf8c
#define dbgr_put_image_info   (mqs_basic_entrypoints->mqs_put_image_info_fp)
Packit Service c5cf8c
#define dbgr_get_image_info   (mqs_basic_entrypoints->mqs_get_image_info_fp)
Packit Service c5cf8c
#define dbgr_put_process_info (mqs_basic_entrypoints->mqs_put_process_info_fp)
Packit Service c5cf8c
#define dbgr_get_process_info (mqs_basic_entrypoints->mqs_get_process_info_fp)
Packit Service c5cf8c
Packit Service c5cf8c
/* These macros *RELY* on the function already having set up the conventional
Packit Service c5cf8c
 * local variables i_info or p_info.
Packit Service c5cf8c
 */
Packit Service c5cf8c
#define dbgr_find_type        (i_info->image_callbacks->mqs_find_type_fp)
Packit Service c5cf8c
#define dbgr_field_offset     (i_info->image_callbacks->mqs_field_offset_fp)
Packit Service c5cf8c
#define dbgr_get_type_sizes   (i_info->image_callbacks->mqs_get_type_sizes_fp)
Packit Service c5cf8c
#define dbgr_find_function    (i_info->image_callbacks->mqs_find_function_fp)
Packit Service c5cf8c
#define dbgr_find_symbol      (i_info->image_callbacks->mqs_find_symbol_fp)
Packit Service c5cf8c
Packit Service c5cf8c
#define dbgr_get_image        (p_info->process_callbacks->mqs_get_image_fp)
Packit Service c5cf8c
#define dbgr_get_global_rank  (p_info->process_callbacks->mqs_get_global_rank_fp)
Packit Service c5cf8c
#define dbgr_fetch_data       (p_info->process_callbacks->mqs_fetch_data_fp)
Packit Service c5cf8c
#define dbgr_target_to_host   (p_info->process_callbacks->mqs_target_to_host_fp)
Packit Service c5cf8c
Packit Service c5cf8c
/* Routines to access data within the process */
Packit Service c5cf8c
static mqs_taddr_t fetch_pointer(mqs_process * proc, mqs_taddr_t addr, mpich_process_info * p_info);
Packit Service c5cf8c
static mqs_tword_t fetch_int(mqs_process * proc, mqs_taddr_t addr, mpich_process_info * p_info);
Packit Service c5cf8c
static mqs_tword_t fetch_int16(mqs_process * proc, mqs_taddr_t addr, mpich_process_info * p_info);
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Startup calls
Packit Service c5cf8c
   These three routines are the first ones invoked by the debugger; they
Packit Service c5cf8c
   are used to ensure that the debug interface library is a known version.
Packit Service c5cf8c
*/
Packit Service c5cf8c
int mqs_version_compatibility(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    return MQS_INTERFACE_COMPATIBILITY;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
const char *mqs_version_string(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    return "MPICH message queue support for MPICH " MPICH_VERSION " compiled on " __DATE__;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Allow the debugger to discover the size of an address type */
Packit Service c5cf8c
int mqs_dll_taddr_width(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    return sizeof(mqs_taddr_t);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Initialization
Packit Service c5cf8c
Packit Service c5cf8c
   The function mqs_setup_basic_callbacks is used by the debugger to
Packit Service c5cf8c
   inform the routines in this file of the addresses of functions that
Packit Service c5cf8c
   it may call in the debugger.
Packit Service c5cf8c
Packit Service c5cf8c
   The function mqs_setup_image creates the image structure (local to this
Packit Service c5cf8c
   file) and tell the debugger about it
Packit Service c5cf8c
Packit Service c5cf8c
   The function mqs_image_has_queues initializes the image structure.
Packit Service c5cf8c
   Much of the information that is saved in the image structure is information
Packit Service c5cf8c
   about the relative offset to data within an MPICH data structure.
Packit Service c5cf8c
   These offsets allow the debugger to retrieve information about the
Packit Service c5cf8c
   MPICH structures.  The debugger routine dbgr_find_type is used to
Packit Service c5cf8c
   find information on an named type, and dbgr_field_offset is used
Packit Service c5cf8c
   to get the offset of a named field within a type.
Packit Service c5cf8c
Packit Service c5cf8c
   The function mqs_setup_process(process, callbacks) creates a private
Packit Service c5cf8c
   process information structure and stores a pointer to it in process
Packit Service c5cf8c
   (using dbgr_put_process_info).  The use of a routine to store this
Packit Service c5cf8c
   value rather than passing an address to the process structure is
Packit Service c5cf8c
   done to give the debugger control over any operation that might store
Packit Service c5cf8c
   into the debuggers memory (instead, we'll use put_xxx_info).
Packit Service c5cf8c
Packit Service c5cf8c
   The function mqs_process_has_queues ??
Packit Service c5cf8c
 */
Packit Service c5cf8c
void mqs_setup_basic_callbacks(const mqs_basic_callbacks * cb)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int t = 1;
Packit Service c5cf8c
    initLogFile();
Packit Service c5cf8c
    host_is_big_endian = (*(char *) &t) != 1;
Packit Service c5cf8c
    mqs_basic_entrypoints = cb;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
   Allocate and setup the basic image data structure.  Also
Packit Service c5cf8c
   save the callbacks provided by the debugger; these will be used
Packit Service c5cf8c
   to access information about the image.  This memory may be recovered
Packit Service c5cf8c
   with mqs_destroy_image_info.
Packit Service c5cf8c
 */
Packit Service c5cf8c
int mqs_setup_image(mqs_image * image, const mqs_image_callbacks * icb)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_malloc(sizeof(mpich_image_info));
Packit Service c5cf8c
Packit Service c5cf8c
    if (!i_info)
Packit Service c5cf8c
        return err_no_store;
Packit Service c5cf8c
Packit Service c5cf8c
    memset((void *) i_info, 0, sizeof(mpich_image_info));
Packit Service c5cf8c
    i_info->image_callbacks = icb;      /* Before we do *ANYTHING* */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Tell the debugger to associate i_info with image */
Packit Service c5cf8c
    dbgr_put_image_info(image, (mqs_image_info *) i_info);
Packit Service c5cf8c
Packit Service c5cf8c
    return mqs_ok;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Setup information needed to access the queues.  If successful, return
Packit Service c5cf8c
 * mqs_ok.  If not, return an erro rcode.  Also set the message pointer
Packit Service c5cf8c
 * with an explanatory message if there is a problem; otherwise, set it
Packit Service c5cf8c
 * to NULL.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This routine is where much of the information specific to an MPI
Packit Service c5cf8c
 * implementation is used.  In particular, the names of the structures
Packit Service c5cf8c
 * internal to an implementation and their fields are used here.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * FIXME: some of this information is specific to particular devices.
Packit Service c5cf8c
 * For example, the message queues are defined by the device.  How do
Packit Service c5cf8c
 * we export this information?  Should the queue code itself be responsible
Packit Service c5cf8c
 * for this (either by calling a routine in the image, using
Packit Service c5cf8c
 * dbgr_find_function (?) or by having the queue implementation provide a
Packit Service c5cf8c
 * separate file that can be included here to get the necessary information.
Packit Service c5cf8c
 */
Packit Service c5cf8c
int mqs_image_has_queues(mqs_image * image, const char **message)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Default failure message ! */
Packit Service c5cf8c
    *message = "The symbols and types in the MPICH library used by TotalView\n"
Packit Service c5cf8c
        "to extract the message queues are not as expected in\n"
Packit Service c5cf8c
        "the image '%s'\n"
Packit Service c5cf8c
        "No message queue display is possible.\n"
Packit Service c5cf8c
        "This is probably an MPICH version or configuration problem.";
Packit Service c5cf8c
Packit Service c5cf8c
    /* Force in the file containing our wait-for-debugger function, to ensure
Packit Service c5cf8c
     * that types have been read from there before we try to look them up.
Packit Service c5cf8c
     */
Packit Service c5cf8c
    dbgr_find_function(image, (char *) "MPII_Wait_for_debugger", mqs_lang_c, NULL);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Find the various global variables and structure definitions
Packit Service c5cf8c
     * that describe the communicator and message queue structures for
Packit Service c5cf8c
     * the MPICH implementation */
Packit Service c5cf8c
Packit Service c5cf8c
    /* First, the communicator information.  This is in two parts:
Packit Service c5cf8c
     * MPIR_All_Communicators - a structure containing the head of the
Packit Service c5cf8c
     * list of all active communicators.  The type is MPIR_Comm_list.
Packit Service c5cf8c
     * The communicators themselves are of type MPIR_Comm.
Packit Service c5cf8c
     */
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mqs_type *cl_type = dbgr_find_type(image, (char *) "MPIR_Comm_list",
Packit Service c5cf8c
                                           mqs_lang_c);
Packit Service c5cf8c
        if (cl_type) {
Packit Service c5cf8c
            i_info->sequence_number_offs = dbgr_field_offset(cl_type, (char *) "sequence_number");
Packit Service c5cf8c
            i_info->comm_head_offs = dbgr_field_offset(cl_type, (char *) "head");
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mqs_type *co_type = dbgr_find_type(image, (char *) "MPIR_Comm", mqs_lang_c);
Packit Service c5cf8c
        if (co_type) {
Packit Service c5cf8c
            i_info->comm_name_offs = dbgr_field_offset(co_type, (char *) "name");
Packit Service c5cf8c
            i_info->comm_next_offs = dbgr_field_offset(co_type, (char *) "comm_next");
Packit Service c5cf8c
            i_info->comm_rsize_offs = dbgr_field_offset(co_type, (char *) "remote_size");
Packit Service c5cf8c
            i_info->comm_rank_offs = dbgr_field_offset(co_type, (char *) "rank");
Packit Service c5cf8c
            i_info->comm_context_id_offs = dbgr_field_offset(co_type, (char *) "context_id");
Packit Service c5cf8c
            i_info->comm_recvcontext_id_offs =
Packit Service c5cf8c
                dbgr_field_offset(co_type, (char *) "recvcontext_id");
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Now the receive queues.  The receive queues contain MPIR_Request
Packit Service c5cf8c
     * objects, and the various fields are within types in that object.
Packit Service c5cf8c
     * To simplify the eventual access, we compute all offsets relative to the
Packit Service c5cf8c
     * request.  This means diving into the types that make of the
Packit Service c5cf8c
     * request definition */
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mqs_type *req_type = dbgr_find_type(image, (char *) "MPIR_Request", mqs_lang_c);
Packit Service c5cf8c
        if (req_type) {
Packit Service c5cf8c
            int dev_offs;
Packit Service c5cf8c
            dev_offs = dbgr_field_offset(req_type, (char *) "dev");
Packit Service c5cf8c
            i_info->req_status_offs = dbgr_field_offset(req_type, (char *) "status");
Packit Service c5cf8c
            i_info->req_cc_offs = dbgr_field_offset(req_type, (char *) "cc");
Packit Service c5cf8c
            if (dev_offs >= 0) {
Packit Service c5cf8c
                mqs_type *dreq_type = dbgr_find_type(image, (char *) "MPIDI_Request",
Packit Service c5cf8c
                                                     mqs_lang_c);
Packit Service c5cf8c
                i_info->req_dev_offs = dev_offs;
Packit Service c5cf8c
                if (dreq_type) {
Packit Service c5cf8c
                    int loff, match_offs;
Packit Service c5cf8c
                    loff = dbgr_field_offset(dreq_type, (char *) "next");
Packit Service c5cf8c
                    i_info->req_next_offs = dev_offs + loff;
Packit Service c5cf8c
                    loff = dbgr_field_offset(dreq_type, (char *) "user_buf");
Packit Service c5cf8c
                    i_info->req_user_buf_offs = dev_offs + loff;
Packit Service c5cf8c
                    loff = dbgr_field_offset(dreq_type, (char *) "user_count");
Packit Service c5cf8c
                    i_info->req_user_count_offs = dev_offs + loff;
Packit Service c5cf8c
                    loff = dbgr_field_offset(dreq_type, (char *) "datatype");
Packit Service c5cf8c
                    i_info->req_datatype_offs = dev_offs + loff;
Packit Service c5cf8c
                    match_offs = dbgr_field_offset(dreq_type, (char *) "match");
Packit Service c5cf8c
                    if (match_offs >= 0) {
Packit Service c5cf8c
                        mqs_type *match_type =
Packit Service c5cf8c
                            dbgr_find_type(image, (char *) "MPIDI_Message_match", mqs_lang_c);
Packit Service c5cf8c
                        if (match_type) {
Packit Service c5cf8c
                            int parts_offs = dbgr_field_offset(match_type, (char *) "parts");
Packit Service c5cf8c
                            if (parts_offs >= 0) {
Packit Service c5cf8c
                                mqs_type *parts_type =
Packit Service c5cf8c
                                    dbgr_find_type(image, (char *) "MPIDI_Message_match_parts_t",
Packit Service c5cf8c
                                                   mqs_lang_c);
Packit Service c5cf8c
                                if (parts_type) {
Packit Service c5cf8c
                                    int moff;
Packit Service c5cf8c
                                    moff = dbgr_field_offset(parts_type, (char *) "tag");
Packit Service c5cf8c
                                    i_info->req_tag_offs = dev_offs + match_offs + moff;
Packit Service c5cf8c
                                    moff = dbgr_field_offset(parts_type, (char *) "rank");
Packit Service c5cf8c
                                    i_info->req_rank_offs = dev_offs + match_offs + moff;
Packit Service c5cf8c
                                    moff = dbgr_field_offset(parts_type, (char *) "context_id");
Packit Service c5cf8c
                                    i_info->req_context_id_offs = dev_offs + match_offs + moff;
Packit Service c5cf8c
                                }
Packit Service c5cf8c
                            }
Packit Service c5cf8c
                        }
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Send queues use a separate system */
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mqs_type *sreq_type = dbgr_find_type(image, (char *) "MPIR_Sendq", mqs_lang_c);
Packit Service c5cf8c
        if (sreq_type) {
Packit Service c5cf8c
            i_info->sendq_next_offs = dbgr_field_offset(sreq_type, (char *) "next");
Packit Service c5cf8c
            i_info->sendq_tag_offs = dbgr_field_offset(sreq_type, (char *) "tag");
Packit Service c5cf8c
            i_info->sendq_rank_offs = dbgr_field_offset(sreq_type, (char *) "rank");
Packit Service c5cf8c
            i_info->sendq_context_id_offs = dbgr_field_offset(sreq_type, (char *) "context_id");
Packit Service c5cf8c
            i_info->sendq_req_offs = dbgr_field_offset(sreq_type, (char *) "sreq");
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mqs_ok;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* mqs_setup_process initializes the process structure.
Packit Service c5cf8c
 * The memory allocated by this routine (and routines that modify this
Packit Service c5cf8c
 * structure) is freed with mqs_destroy_process_info
Packit Service c5cf8c
 */
Packit Service c5cf8c
int mqs_setup_process(mqs_process * process, const mqs_process_callbacks * pcb)
Packit Service c5cf8c
{
Packit Service c5cf8c
    /* Extract the addresses of the global variables we need and save
Packit Service c5cf8c
     * them away */
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_malloc(sizeof(mpich_process_info));
Packit Service c5cf8c
Packit Service c5cf8c
    if (p_info) {
Packit Service c5cf8c
        mqs_image *image;
Packit Service c5cf8c
        mpich_image_info *i_info;
Packit Service c5cf8c
Packit Service c5cf8c
        p_info->process_callbacks = pcb;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Now we can get the rest of the info ! */
Packit Service c5cf8c
        image = dbgr_get_image(process);
Packit Service c5cf8c
        i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
Packit Service c5cf8c
        /* Library starts at zero, so this ensures we go look to start with */
Packit Service c5cf8c
        p_info->communicator_sequence = -1;
Packit Service c5cf8c
        /* We have no communicators yet */
Packit Service c5cf8c
        p_info->communicator_list = NULL;
Packit Service c5cf8c
        /* Ask the debugger to initialize the structure that contains
Packit Service c5cf8c
         * the sizes of basic items (short, int, long, long long, and
Packit Service c5cf8c
         * void *) */
Packit Service c5cf8c
        dbgr_get_type_sizes(process, &p_info->sizes);
Packit Service c5cf8c
Packit Service c5cf8c
        /* Tell the debugger to associate p_info with process */
Packit Service c5cf8c
        dbgr_put_process_info(process, (mqs_process_info *) p_info);
Packit Service c5cf8c
Packit Service c5cf8c
        return mqs_ok;
Packit Service c5cf8c
    } else
Packit Service c5cf8c
        return err_no_store;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int mqs_process_has_queues(mqs_process * proc, char **msg)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
    mqs_image *image = dbgr_get_image(proc);
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
    mqs_taddr_t head_ptr;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Don't bother with a pop up here, it's unlikely to be helpful */
Packit Service c5cf8c
    *msg = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Check first for the communicator list */
Packit Service c5cf8c
    if (dbgr_find_symbol(image, (char *) "MPIR_All_communicators", &p_info->commlist_base) !=
Packit Service c5cf8c
        mqs_ok)
Packit Service c5cf8c
        return err_all_communicators;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Check for the receive and send queues */
Packit Service c5cf8c
    if (dbgr_find_symbol(image, (char *) "MPID_Recvq_posted_head_ptr", &head_ptr) != mqs_ok)
Packit Service c5cf8c
        return err_posted;
Packit Service c5cf8c
    p_info->posted_base = fetch_pointer(proc, head_ptr, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
    if (dbgr_find_symbol(image, (char *) "MPID_Recvq_unexpected_head_ptr", &head_ptr) != mqs_ok)
Packit Service c5cf8c
        return err_unexpected;
Packit Service c5cf8c
    p_info->unexpected_base = fetch_pointer(proc, head_ptr, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Send queues are optional */
Packit Service c5cf8c
    if (dbgr_find_symbol(image, (char *) "MPIR_Sendq_head", &p_info->sendq_base) == mqs_ok) {
Packit Service c5cf8c
        p_info->has_sendq = 1;
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        p_info->has_sendq = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mqs_ok;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* This routine is called by the debugger to map an error code into a
Packit Service c5cf8c
   printable string */
Packit Service c5cf8c
const char *mqs_dll_error_string(int errcode)
Packit Service c5cf8c
{
Packit Service c5cf8c
    switch (errcode) {
Packit Service c5cf8c
        case err_silent_failure:
Packit Service c5cf8c
            return "";
Packit Service c5cf8c
        case err_no_current_communicator:
Packit Service c5cf8c
            return "No current communicator in the communicator iterator";
Packit Service c5cf8c
        case err_bad_request:
Packit Service c5cf8c
            return "Attempting to setup to iterate over an unknown queue of operations";
Packit Service c5cf8c
        case err_no_store:
Packit Service c5cf8c
            return "Unable to allocate store";
Packit Service c5cf8c
        case err_group_corrupt:
Packit Service c5cf8c
            return
Packit Service c5cf8c
                "Could not read a communicator's group from the process (probably a store corruption)";
Packit Service c5cf8c
        case err_unexpected:
Packit Service c5cf8c
            return "Failed to find symbol MPID_Recvq_unexpected_head_ptr";
Packit Service c5cf8c
        case err_posted:
Packit Service c5cf8c
            return "Failed to find symbol MPID_Recvq_posted_head_ptr";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return "Unknown error code";
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Queue Display
Packit Service c5cf8c
 *
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/* Communicator list.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * To avoid problems that might be caused by having the list of communicators
Packit Service c5cf8c
 * change in the process that is being debugged, the communicator access
Packit Service c5cf8c
 * routines make an internal copy of the communicator list.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 */
Packit Service c5cf8c
/* update_communicator_list makes a copy of the list of currently active
Packit Service c5cf8c
 * communicators and stores it in the mqs_process structure.
Packit Service c5cf8c
 */
Packit Service c5cf8c
int mqs_update_communicator_list(mqs_process * proc)
Packit Service c5cf8c
{
Packit Service c5cf8c
    if (communicators_changed(proc))
Packit Service c5cf8c
        return rebuild_communicator_list(proc);
Packit Service c5cf8c
    else
Packit Service c5cf8c
        return mqs_ok;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* These three routines (setup_communicator_iterator, get_communicator,
Packit Service c5cf8c
 * and next_communicator) provide a way to access each communicator in the
Packit Service c5cf8c
 * list that is initialized by update_communicator_list.
Packit Service c5cf8c
 */
Packit Service c5cf8c
int mqs_setup_communicator_iterator(mqs_process * proc)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Start at the front of the list again */
Packit Service c5cf8c
    p_info->current_communicator = p_info->communicator_list;
Packit Service c5cf8c
    /* Reset the operation iterator too */
Packit Service c5cf8c
    p_info->next_msg = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    return p_info->current_communicator == NULL ? mqs_end_of_list : mqs_ok;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int mqs_get_communicator(mqs_process * proc, mqs_communicator * comm)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
Packit Service c5cf8c
    if (p_info->current_communicator) {
Packit Service c5cf8c
        *comm = p_info->current_communicator->comm_info;
Packit Service c5cf8c
        return mqs_ok;
Packit Service c5cf8c
    } else
Packit Service c5cf8c
        return err_no_current_communicator;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int mqs_next_communicator(mqs_process * proc)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
Packit Service c5cf8c
    p_info->current_communicator = p_info->current_communicator->next;
Packit Service c5cf8c
Packit Service c5cf8c
    return (p_info->current_communicator != NULL) ? mqs_ok : mqs_end_of_list;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Iterate over the queues attached to the current communicator. */
Packit Service c5cf8c
Packit Service c5cf8c
/* Forward references for routines used to implement the operations */
Packit Service c5cf8c
static int fetch_send(mqs_process * proc, mpich_process_info * p_info, mqs_pending_operation * res);
Packit Service c5cf8c
static int fetch_receive(mqs_process * proc, mpich_process_info * p_info,
Packit Service c5cf8c
                         mqs_pending_operation * res, int look_for_user_buffer);
Packit Service c5cf8c
Packit Service c5cf8c
int mqs_setup_operation_iterator(mqs_process * proc, int op)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
    /*    mqs_image * image          = dbgr_get_image (proc); */
Packit Service c5cf8c
/*    mpich_image_info *i_info   =
Packit Service c5cf8c
      (mpich_image_info *)dbgr_get_image_info (image); */
Packit Service c5cf8c
Packit Service c5cf8c
    p_info->what = (mqs_op_class) op;
Packit Service c5cf8c
Packit Service c5cf8c
    switch (op) {
Packit Service c5cf8c
        case mqs_pending_sends:
Packit Service c5cf8c
            if (!p_info->has_sendq)
Packit Service c5cf8c
                return mqs_no_information;
Packit Service c5cf8c
            else {
Packit Service c5cf8c
                p_info->next_msg = p_info->sendq_base;
Packit Service c5cf8c
                return mqs_ok;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* The address on the receive queues is the address of a pointer to
Packit Service c5cf8c
             * the head of the list.  */
Packit Service c5cf8c
        case mqs_pending_receives:
Packit Service c5cf8c
            p_info->next_msg = p_info->posted_base;
Packit Service c5cf8c
            return mqs_ok;
Packit Service c5cf8c
Packit Service c5cf8c
        case mqs_unexpected_messages:
Packit Service c5cf8c
            p_info->next_msg = p_info->unexpected_base;
Packit Service c5cf8c
            return mqs_ok;
Packit Service c5cf8c
Packit Service c5cf8c
        default:
Packit Service c5cf8c
            return err_bad_request;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Fetch the next operation on the current communicator, from the
Packit Service c5cf8c
   selected queue. Since MPICH does not (normally) use separate queues
Packit Service c5cf8c
   for each communicator, we must compare the queue items with the
Packit Service c5cf8c
   current communicator.
Packit Service c5cf8c
*/
Packit Service c5cf8c
int mqs_next_operation(mqs_process * proc, mqs_pending_operation * op)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
Packit Service c5cf8c
    switch (p_info->what) {
Packit Service c5cf8c
        case mqs_pending_receives:
Packit Service c5cf8c
            return fetch_receive(proc, p_info, op, 1);
Packit Service c5cf8c
        case mqs_unexpected_messages:
Packit Service c5cf8c
            return fetch_receive(proc, p_info, op, 0);
Packit Service c5cf8c
        case mqs_pending_sends:
Packit Service c5cf8c
            return fetch_send(proc, p_info, op);
Packit Service c5cf8c
        default:
Packit Service c5cf8c
            return err_bad_request;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Clean up routines
Packit Service c5cf8c
 * These routines free any memory allocated when the process or image
Packit Service c5cf8c
 * structures were allocated.
Packit Service c5cf8c
 */
Packit Service c5cf8c
void mqs_destroy_process_info(mqs_process_info * mp_info)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) mp_info;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Need to handle the communicators and groups too */
Packit Service c5cf8c
    mqs_free_communicator_list(p_info->communicator_list);
Packit Service c5cf8c
Packit Service c5cf8c
    dbgr_free(p_info);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void mqs_destroy_image_info(mqs_image_info * info)
Packit Service c5cf8c
{
Packit Service c5cf8c
    dbgr_free(info);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Internal Routine
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * These routine know about the internal structure of the MPI implementation.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/* Get the next entry in the current receive queue (posted or unexpected) */
Packit Service c5cf8c
Packit Service c5cf8c
static int fetch_receive(mqs_process * proc, mpich_process_info * p_info,
Packit Service c5cf8c
                         mqs_pending_operation * res, int look_for_user_buffer)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mqs_image *image = dbgr_get_image(proc);
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
    communicator_t *comm = p_info->current_communicator;
Packit Service c5cf8c
    int16_t wanted_context = comm->recvcontext_id;
Packit Service c5cf8c
    mqs_taddr_t base = fetch_pointer(proc, p_info->next_msg, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG_LIST_ITER
Packit Service c5cf8c
    initLogFile();
Packit Service c5cf8c
    fprintf(debugfp, "fetch receive base = %x, comm= %x, context = %d\n",
Packit Service c5cf8c
            base, comm, wanted_context);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    while (base != 0) {
Packit Service c5cf8c
        /* Check this entry to see if the context matches */
Packit Service c5cf8c
        int16_t actual_context = fetch_int16(proc, base + i_info->req_context_id_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG_LIST_ITER
Packit Service c5cf8c
        initLogFile();
Packit Service c5cf8c
        fprintf(debugfp, "fetch receive msg context = %d\n", actual_context);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
        if (actual_context == wanted_context) {
Packit Service c5cf8c
            /* Found a request for this communicator */
Packit Service c5cf8c
            int tag = fetch_int(proc, base + i_info->req_tag_offs, p_info);
Packit Service c5cf8c
            int rank = fetch_int16(proc, base + i_info->req_rank_offs, p_info);
Packit Service c5cf8c
            int is_complete = fetch_int(proc, base + i_info->req_cc_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t user_buffer = fetch_pointer(proc, base + i_info->req_user_buf_offs, p_info);
Packit Service c5cf8c
            int user_count = fetch_int(proc, base + i_info->req_user_count_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Return -1 for ANY_TAG or ANY_SOURCE */
Packit Service c5cf8c
            res->desired_tag = (tag >= 0) ? tag : -1;
Packit Service c5cf8c
            res->desired_local_rank = (rank >= 0) ? rank : -1;
Packit Service c5cf8c
            res->desired_global_rank = -1;      /* Convert to rank in comm world,
Packit Service c5cf8c
                                                 * if valid (in mpi-2, may
Packit Service c5cf8c
                                                 * not be available) */
Packit Service c5cf8c
            res->desired_length = user_count;   /* Count, not bytes */
Packit Service c5cf8c
Packit Service c5cf8c
            res->tag_wild = (tag < 0);
Packit Service c5cf8c
            res->buffer = user_buffer;
Packit Service c5cf8c
            /* We don't know the rest of these */
Packit Service c5cf8c
            res->system_buffer = 0;
Packit Service c5cf8c
            res->actual_local_rank = rank;
Packit Service c5cf8c
            res->actual_global_rank = -1;
Packit Service c5cf8c
            res->actual_tag = tag;
Packit Service c5cf8c
            res->actual_length = -1;
Packit Service c5cf8c
            res->extra_text[0][0] = 0;
Packit Service c5cf8c
Packit Service c5cf8c
            res->status = (is_complete != 0) ? mqs_st_pending : mqs_st_complete;
Packit Service c5cf8c
Packit Service c5cf8c
            /* Don't forget to step the queue ! */
Packit Service c5cf8c
            p_info->next_msg = base + i_info->req_next_offs;
Packit Service c5cf8c
            return mqs_ok;
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            /* Try the next one */
Packit Service c5cf8c
            base = fetch_pointer(proc, base + i_info->req_next_offs, p_info);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
#if 0
Packit Service c5cf8c
    while (base != 0) { /* Well, there's a queue, at least ! */
Packit Service c5cf8c
        mqs_tword_t actual_context = fetch_int16(proc, base + i_info->context_id_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
        if (actual_context == wanted_context) { /* Found a good one */
Packit Service c5cf8c
            mqs_tword_t tag = fetch_int(proc, base + i_info->tag_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t tagmask = fetch_int(proc, base + i_info->tagmask_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t lsrc = fetch_int(proc, base + i_info->lsrc_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t srcmask = fetch_int(proc, base + i_info->srcmask_offs, p_info);
Packit Service c5cf8c
            mqs_taddr_t ptr = fetch_pointer(proc, base + i_info->ptr_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Fetch the fields from the MPIR_RHANDLE */
Packit Service c5cf8c
            int is_complete = fetch_int(proc, ptr + i_info->is_complete_offs, p_info);
Packit Service c5cf8c
            mqs_taddr_t buf = fetch_pointer(proc, ptr + i_info->buf_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t len = fetch_int(proc, ptr + i_info->len_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t count = fetch_int(proc, ptr + i_info->count_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
            /* If we don't have start, then use buf instead... */
Packit Service c5cf8c
            mqs_taddr_t start;
Packit Service c5cf8c
            if (i_info->start_offs < 0)
Packit Service c5cf8c
                start = buf;
Packit Service c5cf8c
            else
Packit Service c5cf8c
                start = fetch_pointer(proc, ptr + i_info->start_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Hurrah, we should now be able to fill in all the necessary fields in the
Packit Service c5cf8c
             * result !
Packit Service c5cf8c
             */
Packit Service c5cf8c
            res->status = is_complete ? mqs_st_complete : mqs_st_pending;       /* We can't discern matched */
Packit Service c5cf8c
            if (srcmask == 0) {
Packit Service c5cf8c
                res->desired_local_rank = -1;
Packit Service c5cf8c
                res->desired_global_rank = -1;
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                res->desired_local_rank = lsrc;
Packit Service c5cf8c
                res->desired_global_rank = translate(comm->group, lsrc);
Packit Service c5cf8c
Packit Service c5cf8c
            }
Packit Service c5cf8c
            res->tag_wild = (tagmask == 0);
Packit Service c5cf8c
            res->desired_tag = tag;
Packit Service c5cf8c
Packit Service c5cf8c
            if (look_for_user_buffer) {
Packit Service c5cf8c
                res->system_buffer = 0;
Packit Service c5cf8c
                res->buffer = buf;
Packit Service c5cf8c
                res->desired_length = len;
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                res->system_buffer = 1;
Packit Service c5cf8c
                /* Correct an oddity. If the buffer length is zero then no buffer
Packit Service c5cf8c
                 * is allocated, but the descriptor is left with random data.
Packit Service c5cf8c
                 */
Packit Service c5cf8c
                if (count == 0)
Packit Service c5cf8c
                    start = 0;
Packit Service c5cf8c
Packit Service c5cf8c
                res->buffer = start;
Packit Service c5cf8c
                res->desired_length = count;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            if (is_complete) {  /* Fill in the actual results, rather than what we were looking for */
Packit Service c5cf8c
                mqs_tword_t mpi_source = fetch_int(proc, ptr + i_info->MPI_SOURCE_offs, p_info);
Packit Service c5cf8c
                mqs_tword_t mpi_tag = fetch_int(proc, ptr + i_info->MPI_TAG_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
                res->actual_length = count;
Packit Service c5cf8c
                res->actual_tag = mpi_tag;
Packit Service c5cf8c
                res->actual_local_rank = mpi_source;
Packit Service c5cf8c
                res->actual_global_rank = translate(comm->group, mpi_source);
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* Don't forget to step the queue ! */
Packit Service c5cf8c
            p_info->next_msg = base + i_info->next_offs;
Packit Service c5cf8c
            return mqs_ok;
Packit Service c5cf8c
        } else {        /* Try the next one */
Packit Service c5cf8c
            base = fetch_pointer(proc, base + i_info->next_offs, p_info);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    p_info->next_msg = 0;
Packit Service c5cf8c
    return mqs_end_of_list;
Packit Service c5cf8c
}       /* fetch_receive */
Packit Service c5cf8c
Packit Service c5cf8c
/* Get the next entry in the send queue, if there is one.  The assumption is
Packit Service c5cf8c
   that the MPI implementation is quiescent while these queue probes are
Packit Service c5cf8c
   taking place, so we can simply keep track of the location of the "next"
Packit Service c5cf8c
   entry. (in the next_msg field) */
Packit Service c5cf8c
static int fetch_send(mqs_process * proc, mpich_process_info * p_info, mqs_pending_operation * res)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mqs_image *image = dbgr_get_image(proc);
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
    communicator_t *comm = p_info->current_communicator;
Packit Service c5cf8c
    int wanted_context = comm->context_id;
Packit Service c5cf8c
    mqs_taddr_t base = fetch_pointer(proc, p_info->next_msg, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
    if (!p_info->has_sendq)
Packit Service c5cf8c
        return mqs_no_information;
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG_LIST_ITER
Packit Service c5cf8c
    if (base) {
Packit Service c5cf8c
        initLogFile();
Packit Service c5cf8c
        fprintf(debugf, "comm ptr = %p, comm context = %d\n", comm, comm->context_id);
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    /* Say what operation it is. We can only see non blocking send operations
Packit Service c5cf8c
     * in MPICH. Other MPI systems may be able to show more here.
Packit Service c5cf8c
     */
Packit Service c5cf8c
    /* FIXME: handle size properly (declared as 64 in mpi_interface.h) */
Packit Service c5cf8c
    strncpy((char *) res->extra_text[0], "Non-blocking send", 20);
Packit Service c5cf8c
    res->extra_text[1][0] = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    while (base != 0) {
Packit Service c5cf8c
        /* Check this entry to see if the context matches */
Packit Service c5cf8c
        int actual_context = fetch_int16(proc, base + i_info->sendq_context_id_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
        if (actual_context == wanted_context) {
Packit Service c5cf8c
            /* Fill in some of the fields */
Packit Service c5cf8c
            mqs_tword_t target = fetch_int(proc, base + i_info->sendq_rank_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t tag = fetch_int(proc, base + i_info->sendq_tag_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t length = 0;
Packit Service c5cf8c
            mqs_taddr_t data = 0;
Packit Service c5cf8c
            mqs_taddr_t sreq = fetch_pointer(proc, base + i_info->sendq_req_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t is_complete = fetch_int(proc, sreq + i_info->req_cc_offs, p_info);
Packit Service c5cf8c
            data = fetch_pointer(proc, sreq + i_info->req_user_buf_offs, p_info);
Packit Service c5cf8c
            length = fetch_int(proc, sreq + i_info->req_user_count_offs, p_info);
Packit Service c5cf8c
            /* mqs_tword_t complete=0; */
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG_LIST_ITER
Packit Service c5cf8c
            initLogFile();
Packit Service c5cf8c
            fprintf(debugpf, "sendq entry = %p, rank off = %d, tag off = %d, context = %d\n",
Packit Service c5cf8c
                    base, i_info->sendq_rank_offs, i_info->sendq_tag_offs, actual_context);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
            /* Ok, fill in the results */
Packit Service c5cf8c
            res->status = (is_complete != 0) ? mqs_st_pending : mqs_st_complete;
Packit Service c5cf8c
            res->actual_local_rank = res->desired_local_rank = target;
Packit Service c5cf8c
            res->actual_global_rank = res->desired_global_rank = translate(comm->group, target);
Packit Service c5cf8c
            res->tag_wild = 0;
Packit Service c5cf8c
            res->actual_tag = res->desired_tag = tag;
Packit Service c5cf8c
            res->desired_length = res->actual_length = length;
Packit Service c5cf8c
            res->system_buffer = 0;
Packit Service c5cf8c
            res->buffer = data;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
            /* Don't forget to step the queue ! */
Packit Service c5cf8c
            p_info->next_msg = base + i_info->sendq_next_offs;
Packit Service c5cf8c
            return mqs_ok;
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            /* Try the next one */
Packit Service c5cf8c
            base = fetch_pointer(proc, base + i_info->sendq_next_offs, p_info);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
#if 0
Packit Service c5cf8c
    while (base != 0) { /* Well, there's a queue, at least ! */
Packit Service c5cf8c
        /* Check if it's one we're interested in ? */
Packit Service c5cf8c
        mqs_taddr_t commp = fetch_pointer(proc, base + i_info->db_comm_offs, p_info);
Packit Service c5cf8c
        mqs_taddr_t next = base + i_info->db_next_offs;
Packit Service c5cf8c
Packit Service c5cf8c
        if (commp == comm->comm_info.unique_id) {       /* Found one */
Packit Service c5cf8c
            mqs_tword_t target = fetch_int(proc, base + i_info->db_target_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t tag = fetch_int(proc, base + i_info->db_tag_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t length = fetch_int(proc, base + i_info->db_byte_length_offs, p_info);
Packit Service c5cf8c
            mqs_taddr_t data = fetch_pointer(proc, base + i_info->db_data_offs, p_info);
Packit Service c5cf8c
            mqs_taddr_t shandle = fetch_pointer(proc, base + i_info->db_shandle_offs, p_info);
Packit Service c5cf8c
            mqs_tword_t complete = fetch_int(proc, shandle + i_info->is_complete_offs, p_info);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Ok, fill in the results */
Packit Service c5cf8c
            res->status = complete ? mqs_st_complete : mqs_st_pending;  /* We can't discern matched */
Packit Service c5cf8c
            res->actual_local_rank = res->desired_local_rank = target;
Packit Service c5cf8c
            res->actual_global_rank = res->desired_global_rank = translate(comm->group, target);
Packit Service c5cf8c
            res->tag_wild = 0;
Packit Service c5cf8c
            res->actual_tag = res->desired_tag = tag;
Packit Service c5cf8c
            res->desired_length = res->actual_length = length;
Packit Service c5cf8c
            res->system_buffer = 0;
Packit Service c5cf8c
            res->buffer = data;
Packit Service c5cf8c
Packit Service c5cf8c
            p_info->next_msg = next;
Packit Service c5cf8c
            return mqs_ok;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        base = fetch_pointer(proc, next, p_info);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    p_info->next_msg = 0;
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    return mqs_end_of_list;
Packit Service c5cf8c
}       /* fetch_send */
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Communicator */
Packit Service c5cf8c
static int communicators_changed(mqs_process * proc)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
    mqs_image *image = dbgr_get_image(proc);
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
    mqs_tword_t new_seq = fetch_int(proc,
Packit Service c5cf8c
                                    p_info->commlist_base + i_info->sequence_number_offs,
Packit Service c5cf8c
                                    p_info);
Packit Service c5cf8c
    int res = (new_seq != p_info->communicator_sequence);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Save the sequence number for next time */
Packit Service c5cf8c
    p_info->communicator_sequence = new_seq;
Packit Service c5cf8c
Packit Service c5cf8c
    return res;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/***********************************************************************
Packit Service c5cf8c
 * Find a matching communicator on our list. We check the recv context
Packit Service c5cf8c
 * as well as the address since the communicator structures may be
Packit Service c5cf8c
 * being re-allocated from a free list, in which case the same
Packit Service c5cf8c
 * address will be re-used a lot, which could confuse us.
Packit Service c5cf8c
 */
Packit Service c5cf8c
static communicator_t *find_communicator(mpich_process_info * p_info,
Packit Service c5cf8c
                                         mqs_taddr_t comm_base, int recv_ctx)
Packit Service c5cf8c
{
Packit Service c5cf8c
    communicator_t *comm = p_info->communicator_list;
Packit Service c5cf8c
Packit Service c5cf8c
    for (; comm; comm = comm->next) {
Packit Service c5cf8c
        if (comm->comm_info.unique_id == comm_base && comm->recvcontext_id == recv_ctx)
Packit Service c5cf8c
            return comm;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return NULL;
Packit Service c5cf8c
}       /* find_communicator */
Packit Service c5cf8c
Packit Service c5cf8c
/* This is the comparison function used in the qsort call in
Packit Service c5cf8c
   rebuild_communicator_list */
Packit Service c5cf8c
static int compare_comms(const void *a, const void *b)
Packit Service c5cf8c
{
Packit Service c5cf8c
    communicator_t *ca = *(communicator_t **) a;
Packit Service c5cf8c
    communicator_t *cb = *(communicator_t **) b;
Packit Service c5cf8c
Packit Service c5cf8c
    return cb->recvcontext_id - ca->recvcontext_id;
Packit Service c5cf8c
}       /* compare_comms */
Packit Service c5cf8c
Packit Service c5cf8c
static int rebuild_communicator_list(mqs_process * proc)
Packit Service c5cf8c
{
Packit Service c5cf8c
    mpich_process_info *p_info = (mpich_process_info *) dbgr_get_process_info(proc);
Packit Service c5cf8c
    mqs_image *image = dbgr_get_image(proc);
Packit Service c5cf8c
    mpich_image_info *i_info = (mpich_image_info *) dbgr_get_image_info(image);
Packit Service c5cf8c
    mqs_taddr_t comm_base = fetch_pointer(proc,
Packit Service c5cf8c
                                          p_info->commlist_base + i_info->comm_head_offs,
Packit Service c5cf8c
                                          p_info);
Packit Service c5cf8c
Packit Service c5cf8c
    communicator_t **commp;
Packit Service c5cf8c
    int commcount = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Iterate over the list in the process comparing with the list
Packit Service c5cf8c
     * we already have saved. This is n**2, because we search for each
Packit Service c5cf8c
     * communicator on the existing list. I don't think it matters, though
Packit Service c5cf8c
     * because there aren't that many communicators to worry about, and
Packit Service c5cf8c
     * we only ever do this if something changed.
Packit Service c5cf8c
     */
Packit Service c5cf8c
    while (comm_base) {
Packit Service c5cf8c
        /* We do have one to look at, so extract the info */
Packit Service c5cf8c
        int recv_ctx = fetch_int16(proc, comm_base + i_info->comm_recvcontext_id_offs, p_info);
Packit Service c5cf8c
        int send_ctx = fetch_int16(proc, comm_base + i_info->comm_context_id_offs, p_info);
Packit Service c5cf8c
        communicator_t *old = find_communicator(p_info, comm_base, recv_ctx);
Packit Service c5cf8c
Packit Service c5cf8c
        const char *name = "--unnamed--";
Packit Service c5cf8c
        char namebuffer[64];
Packit Service c5cf8c
        /* In MPICH, the name is preallocated and of size MPI_MAX_OBJECT_NAME */
Packit Service c5cf8c
        if (dbgr_fetch_data(proc, comm_base + i_info->comm_name_offs, 64,
Packit Service c5cf8c
                            namebuffer) == mqs_ok && namebuffer[0] != 0) {
Packit Service c5cf8c
            name = namebuffer;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        if (old) {
Packit Service c5cf8c
            old->present = 1;   /* We do want this communicator */
Packit Service c5cf8c
            strncpy(old->comm_info.name, name, sizeof(old->comm_info.name));    /* Make sure the name is up to date,
Packit Service c5cf8c
                                                                                 * it might have changed and we can't tell.
Packit Service c5cf8c
                                                                                 */
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            mqs_taddr_t group_base = fetch_pointer(proc, comm_base + i_info->lrank_to_grank_offs,
Packit Service c5cf8c
                                                   p_info);
Packit Service c5cf8c
            int np = fetch_int(proc, comm_base + i_info->comm_rsize_offs, p_info);
Packit Service c5cf8c
            group_t *g = find_or_create_group(proc, np, group_base);
Packit Service c5cf8c
            communicator_t *nc;
Packit Service c5cf8c
Packit Service c5cf8c
#if 0
Packit Service c5cf8c
            if (!g)
Packit Service c5cf8c
                return err_group_corrupt;
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
            nc = (communicator_t *) dbgr_malloc(sizeof(communicator_t));
Packit Service c5cf8c
Packit Service c5cf8c
            /* Save the results */
Packit Service c5cf8c
            nc->next = p_info->communicator_list;
Packit Service c5cf8c
            p_info->communicator_list = nc;
Packit Service c5cf8c
            nc->present = 1;
Packit Service c5cf8c
            nc->group = g;
Packit Service c5cf8c
            nc->context_id = send_ctx;
Packit Service c5cf8c
            nc->recvcontext_id = recv_ctx;
Packit Service c5cf8c
Packit Service c5cf8c
            strncpy(nc->comm_info.name, name, sizeof(nc->comm_info.name));
Packit Service c5cf8c
            nc->comm_info.unique_id = comm_base;
Packit Service c5cf8c
            nc->comm_info.size = np;
Packit Service c5cf8c
            nc->comm_info.local_rank = fetch_int(proc, comm_base + i_info->comm_rank_offs, p_info);
Packit Service c5cf8c
#ifdef DEBUG_LIST_ITER
Packit Service c5cf8c
            initLogFile();
Packit Service c5cf8c
            fprintf(debugfp,
Packit Service c5cf8c
                    "Adding communicator %p, send context=%d, recv context=%d, size=%d, name=%s\n",
Packit Service c5cf8c
                    comm_base, send_ctx, recv_ctx, np, name);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
#if 0
Packit Service c5cf8c
            nc->comm_info.local_rank = reverse_translate(g, dbgr_get_global_rank(proc));
Packit Service c5cf8c
#endif
Packit Service c5cf8c
        }
Packit Service c5cf8c
        /* Step to the next communicator on the list */
Packit Service c5cf8c
        comm_base = fetch_pointer(proc, comm_base + i_info->comm_next_offs, p_info);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Now iterate over the list tidying up any communicators which
Packit Service c5cf8c
     * no longer exist, and cleaning the flags on any which do.
Packit Service c5cf8c
     */
Packit Service c5cf8c
    commp = &p_info->communicator_list;
Packit Service c5cf8c
Packit Service c5cf8c
    for (; *commp; commp = &(*commp)->next) {
Packit Service c5cf8c
        communicator_t *comm = *commp;
Packit Service c5cf8c
Packit Service c5cf8c
        if (comm->present) {
Packit Service c5cf8c
            comm->present = 0;
Packit Service c5cf8c
            commcount++;
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            /* It needs to be deleted */
Packit Service c5cf8c
            *commp = comm->next;        /* Remove from the list */
Packit Service c5cf8c
            group_decref(comm->group);  /* Group is no longer referenced from here */
Packit Service c5cf8c
            dbgr_free(comm);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (commcount) {
Packit Service c5cf8c
        /* Sort the list so that it is displayed in some semi-sane order. */
Packit Service c5cf8c
        communicator_t **comm_array =
Packit Service c5cf8c
            (communicator_t **) dbgr_malloc(commcount * sizeof(communicator_t *));
Packit Service c5cf8c
        communicator_t *comm = p_info->communicator_list;
Packit Service c5cf8c
        int i;
Packit Service c5cf8c
        for (i = 0; i < commcount; i++, comm = comm->next)
Packit Service c5cf8c
            comm_array[i] = comm;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Do the sort */
Packit Service c5cf8c
        qsort(comm_array, commcount, sizeof(communicator_t *), compare_comms);
Packit Service c5cf8c
Packit Service c5cf8c
        /* Re build the list */
Packit Service c5cf8c
        p_info->communicator_list = NULL;
Packit Service c5cf8c
        for (i = 0; i < commcount; i++) {
Packit Service c5cf8c
            comm = comm_array[i];
Packit Service c5cf8c
            comm->next = p_info->communicator_list;
Packit Service c5cf8c
            p_info->communicator_list = comm;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        dbgr_free(comm_array);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mqs_ok;
Packit Service c5cf8c
}       /* rebuild_communicator_list */
Packit Service c5cf8c
Packit Service c5cf8c
/* Internal routine to free the communicator list */
Packit Service c5cf8c
static void mqs_free_communicator_list(struct communicator_t *comm)
Packit Service c5cf8c
{
Packit Service c5cf8c
    while (comm) {
Packit Service c5cf8c
        communicator_t *next = comm->next;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Release the group data structures */
Packit Service c5cf8c
        /* group_decref (comm->group);           */
Packit Service c5cf8c
        dbgr_free(comm);
Packit Service c5cf8c
Packit Service c5cf8c
        comm = next;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------ */
Packit Service c5cf8c
/* Internal routine to fetch data from the process */
Packit Service c5cf8c
static mqs_taddr_t fetch_pointer(mqs_process * proc, mqs_taddr_t addr, mpich_process_info * p_info)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int asize = p_info->sizes.pointer_size;
Packit Service c5cf8c
    char data[8];               /* ASSUME a pointer fits in 8 bytes */
Packit Service c5cf8c
    mqs_taddr_t res = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    if (mqs_ok == dbgr_fetch_data(proc, addr, asize, data))
Packit Service c5cf8c
        dbgr_target_to_host(proc, data,
Packit Service c5cf8c
                            ((char *) &res) + (host_is_big_endian ? sizeof(mqs_taddr_t) -
Packit Service c5cf8c
                                               asize : 0), asize);
Packit Service c5cf8c
Packit Service c5cf8c
    return res;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static mqs_tword_t fetch_int(mqs_process * proc, mqs_taddr_t addr, mpich_process_info * p_info)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int isize = p_info->sizes.int_size;
Packit Service c5cf8c
    char buffer[8];             /* ASSUME an integer fits in 8 bytes */
Packit Service c5cf8c
    mqs_tword_t res = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    if (mqs_ok == dbgr_fetch_data(proc, addr, isize, buffer))
Packit Service c5cf8c
        dbgr_target_to_host(proc, buffer,
Packit Service c5cf8c
                            ((char *) &res) + (host_is_big_endian ? sizeof(mqs_tword_t) -
Packit Service c5cf8c
                                               isize : 0), isize);
Packit Service c5cf8c
Packit Service c5cf8c
    return res;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static mqs_tword_t fetch_int16(mqs_process * proc, mqs_taddr_t addr, mpich_process_info * p_info)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char buffer[8];             /* ASSUME an integer fits in 8 bytes */
Packit Service c5cf8c
    int16_t res = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    if (mqs_ok == dbgr_fetch_data(proc, addr, 2, buffer))
Packit Service c5cf8c
        dbgr_target_to_host(proc, buffer,
Packit Service c5cf8c
                            ((char *) &res) + (host_is_big_endian ? sizeof(mqs_tword_t) - 2 : 0),
Packit Service c5cf8c
                            2);
Packit Service c5cf8c
Packit Service c5cf8c
    return res;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* ------------------------------------------------------------------------- */
Packit Service c5cf8c
/* With each communicator we need to translate ranks to/from their
Packit Service c5cf8c
   MPI_COMM_WORLD equivalents.  This code is not yet implemented
Packit Service c5cf8c
*/
Packit Service c5cf8c
/* ------------------------------------------------------------------------- */
Packit Service c5cf8c
/* idx is rank in group this; return rank in MPI_COMM_WORLD */
Packit Service c5cf8c
static int translate(group_t * this, int idx)
Packit Service c5cf8c
{
Packit Service c5cf8c
    return -1;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#if 0
Packit Service c5cf8c
/* idx is rank in MPI_COMM_WORLD, return rank in group this */
Packit Service c5cf8c
static int reverse_translate(group_t * this, int idx)
Packit Service c5cf8c
{
Packit Service c5cf8c
    return -1;
Packit Service c5cf8c
}
Packit Service c5cf8c
#endif
Packit Service c5cf8c
static group_t *find_or_create_group(mqs_process * proc, mqs_tword_t np, mqs_taddr_t table)
Packit Service c5cf8c
{
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static void group_decref(group_t * group)
Packit Service c5cf8c
{
Packit Service c5cf8c
    if (--(group->ref_count) == 0) {
Packit Service c5cf8c
        dbgr_free(group->local_to_global);
Packit Service c5cf8c
        dbgr_free(group);
Packit Service c5cf8c
    }
Packit Service c5cf8c
}       /* group_decref */