1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3 * (C) 2005 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
5 */
6
7 /* Fixme: include the mpichconf.h file? */
8
9 /* Allow fprintf in debug statements */
10 /* style: allow:fprintf:5 sig:0 */
11
12 #include <stdlib.h>
13 #include <stdint.h>
14 #include <string.h>
15 #include "mpi.h"
16
17 /* #define DEBUG_MPIDBG_DLL 1 */
18
19 /* Define this to have the code print out details of its list traversal
20 action. This is primarily for use with dbgstub.c and the test programs
21 such as tvtest.c */
22 /* #define DEBUG_LIST_ITER */
23
24 /* Define this to have the code print out its operation to a file.
25 This may be used to help understand how the debugger is using this
26 interface */
27 /* #define DEBUG_MPIDBG_LOGGING */
28 #ifdef DEBUG_MPIDBG_LOGGING
29 #include <stdio.h>
30 FILE *debugfp = 0;
31
initLogFile(void)32 static void initLogFile(void)
33 {
34 if (!debugfp) {
35 debugfp = fopen( "mpich-dbg-interface-log.txt", "w" );
36 }
37 }
38 #else
39 /* no-op definition */
40 #define initLogFile()
41 #endif
42
43 /* MPIR_dll_name is defined in dbg_init.c; it must be part of the target image,
44 not the debugger interface */
45
46 /* mpi_interface.h defines the interface to the debugger. This interface
47 is the same for any MPI implementation, for a given debugger
48 (a more precise name might be mpi_tv_interface.h) */
49 #include "mpi_interface.h"
50 /* mpich2_dll_defs.h defines the structures for a particular MPI
51 implementation (MPICH2 in this case) */
52 #include "mpich2_dll_defs.h"
53
54 /* style: allow:strncpy:1 sig:0 */
55
56 /* ------------------------------------------------------------------------ */
57 /* Local variables for this package */
58
59 static const mqs_basic_callbacks *mqs_basic_entrypoints = 0;
60 static int host_is_big_endian = -1;
61
62 /* ------------------------------------------------------------------------ */
63 /* Error values. */
64 enum {
65 err_silent_failure = mqs_first_user_code,
66
67 err_no_current_communicator,
68 err_bad_request,
69 err_no_store,
70 err_all_communicators,
71 err_group_corrupt,
72
73 err_failed_qhdr,
74 err_unexpected,
75 err_posted,
76
77 err_failed_queue,
78 err_first,
79
80 };
81
82 /* Internal structure we hold for each communicator */
83 typedef struct communicator_t
84 {
85 struct communicator_t * next;
86 group_t * group; /* Translations */
87 int context_id; /* To catch changes */
88 int recvcontext_id; /* May also be needed for
89 matchine */
90 int present;
91 mqs_communicator comm_info; /* Info needed at the higher level */
92 } communicator_t;
93
94 /* Internal functions used only by routines in this package */
95 static void mqs_free_communicator_list( struct communicator_t *comm );
96
97 static int communicators_changed (mqs_process *proc);
98 static int rebuild_communicator_list (mqs_process *proc);
99 static int compare_comms (const void *a, const void *b);
100
101 static group_t * find_or_create_group (mqs_process *proc,
102 mqs_tword_t np,
103 mqs_taddr_t table);
104 static int translate (group_t *this, int idx);
105 #if 0
106 static int reverse_translate (group_t * this, int idx);
107 #endif
108 static void group_decref (group_t * group);
109 static communicator_t * find_communicator (mpich_process_info *p_info,
110 mqs_taddr_t comm_base, int recv_ctx);
111
112 /* ------------------------------------------------------------------------ */
113 /*
114 * Many of the services used by this file are performed by calling
115 * functions executed by the debugger. In other words, these are routines
116 * that the debugger must export to this package. To make it easy to
117 * identify these functions as well as to make their use simple,
118 * we use macros that start with dbgr_xxx (for debugger). These
119 * function pointers are set early in the initialization phase.
120 *
121 * Note: to avoid any changes to the mpi_interface.h file, the fields in
122 * the structures that contain the function pointers have not been
123 * renamed dbgr_xxx and continue to use their original mqs_ prefix.
124 * Using the dbgr_ prefix for the debugger-provided callbacks was done to
125 * make it more obvious whether the debugger or the MPI interface DLL is
126 * responsible for providing the function.
127 */
128 #define dbgr_malloc (mqs_basic_entrypoints->mqs_malloc_fp)
129 #define dbgr_free (mqs_basic_entrypoints->mqs_free_fp)
130 #define dbgr_prints (mqs_basic_entrypoints->mqs_eprints_fp)
131 #define dbgr_put_image_info (mqs_basic_entrypoints->mqs_put_image_info_fp)
132 #define dbgr_get_image_info (mqs_basic_entrypoints->mqs_get_image_info_fp)
133 #define dbgr_put_process_info (mqs_basic_entrypoints->mqs_put_process_info_fp)
134 #define dbgr_get_process_info (mqs_basic_entrypoints->mqs_get_process_info_fp)
135
136 /* These macros *RELY* on the function already having set up the conventional
137 * local variables i_info or p_info.
138 */
139 #define dbgr_find_type (i_info->image_callbacks->mqs_find_type_fp)
140 #define dbgr_field_offset (i_info->image_callbacks->mqs_field_offset_fp)
141 #define dbgr_get_type_sizes (i_info->image_callbacks->mqs_get_type_sizes_fp)
142 #define dbgr_find_function (i_info->image_callbacks->mqs_find_function_fp)
143 #define dbgr_find_symbol (i_info->image_callbacks->mqs_find_symbol_fp)
144
145 #define dbgr_get_image (p_info->process_callbacks->mqs_get_image_fp)
146 #define dbgr_get_global_rank (p_info->process_callbacks->mqs_get_global_rank_fp)
147 #define dbgr_fetch_data (p_info->process_callbacks->mqs_fetch_data_fp)
148 #define dbgr_target_to_host (p_info->process_callbacks->mqs_target_to_host_fp)
149
150 /* Routines to access data within the process */
151 static mqs_taddr_t fetch_pointer (mqs_process * proc, mqs_taddr_t addr,
152 mpich_process_info *p_info);
153 static mqs_tword_t fetch_int (mqs_process * proc, mqs_taddr_t addr,
154 mpich_process_info *p_info);
155 static mqs_tword_t fetch_int16 (mqs_process * proc, mqs_taddr_t addr,
156 mpich_process_info *p_info);
157
158 /* ------------------------------------------------------------------------ */
159 /* Startup calls
160 These three routines are the first ones invoked by the debugger; they
161 are used to ensure that the debug interface library is a known version.
162 */
mqs_version_compatibility(void)163 int mqs_version_compatibility ( void )
164 {
165 return MQS_INTERFACE_COMPATIBILITY;
166 }
167
mqs_version_string(void)168 char *mqs_version_string ( void )
169 {
170 return (char *)"MPICH message queue support for MPICH2 " MPICH2_VERSION " compiled on " __DATE__;
171 }
172
173 /* Allow the debugger to discover the size of an address type */
mqs_dll_taddr_width(void)174 int mqs_dll_taddr_width (void)
175 {
176 return sizeof (mqs_taddr_t);
177 }
178
179 /* ------------------------------------------------------------------------ */
180 /* Initialization
181
182 The function mqs_setup_basic_callbacks is used by the debugger to
183 inform the routines in this file of the addresses of functions that
184 it may call in the debugger.
185
186 The function mqs_setup_image creates the image structure (local to this
187 file) and tell the debugger about it
188
189 The function mqs_image_has_queues initializes the image structure.
190 Much of the information that is saved in the image structure is information
191 about the relative offset to data within an MPICH2 data structure.
192 These offsets allow the debugger to retrieve information about the
193 MPICH2 structures. The debugger routine dbgr_find_type is used to
194 find information on an named type, and dbgr_field_offset is used
195 to get the offset of a named field within a type.
196
197 The function mqs_setup_process(process, callbacks) creates a private
198 process information structure and stores a pointer to it in process
199 (using dbgr_put_process_info). The use of a routine to store this
200 value rather than passing an address to the process structure is
201 done to give the debugger control over any operation that might store
202 into the debuggers memory (instead, we'll use put_xxx_info).
203
204 The function mqs_process_has_queues ??
205 */
mqs_setup_basic_callbacks(const mqs_basic_callbacks * cb)206 void mqs_setup_basic_callbacks (const mqs_basic_callbacks * cb)
207 {
208 int t = 1;
209 initLogFile();
210 host_is_big_endian = (*(char *)&t) != 1;
211 mqs_basic_entrypoints = cb;
212 }
213
214 /*
215 Allocate and setup the basic image data structure. Also
216 save the callbacks provided by the debugger; these will be used
217 to access information about the image. This memory may be recovered
218 with mqs_destroy_image_info.
219 */
mqs_setup_image(mqs_image * image,const mqs_image_callbacks * icb)220 int mqs_setup_image (mqs_image *image, const mqs_image_callbacks *icb)
221 {
222 mpich_image_info *i_info =
223 (mpich_image_info *)dbgr_malloc (sizeof (mpich_image_info));
224
225 if (!i_info)
226 return err_no_store;
227
228 memset ((void *)i_info, 0, sizeof (mpich_image_info));
229 i_info->image_callbacks = icb; /* Before we do *ANYTHING* */
230
231 /* Tell the debugger to associate i_info with image */
232 dbgr_put_image_info (image, (mqs_image_info *)i_info);
233
234 return mqs_ok;
235 }
236
237 /*
238 * Setup information needed to access the queues. If successful, return
239 * mqs_ok. If not, return an erro rcode. Also set the message pointer
240 * with an explanatory message if there is a problem; otherwise, set it
241 * to NULL.
242 *
243 * This routine is where much of the information specific to an MPI
244 * implementation is used. In particular, the names of the structures
245 * internal to an implementation and their fields are used here.
246 *
247 * FIXME: some of this information is specific to particular devices.
248 * For example, the message queues are defined by the device. How do
249 * we export this information? Should the queue code itself be responsible
250 * for this (either by calling a routine in the image, using
251 * dbgr_find_function (?) or by having the queue implementation provide a
252 * separate file that can be included here to get the necessary information.
253 */
mqs_image_has_queues(mqs_image * image,char ** message)254 int mqs_image_has_queues (mqs_image *image, char **message)
255 {
256 mpich_image_info * i_info =
257 (mpich_image_info *)dbgr_get_image_info (image);
258 int have_co = 0, have_cl = 0, have_req = 0, have_dreq = 0;
259
260 /* Default failure message ! */
261 *message = (char *)"The symbols and types in the MPICH library used by TotalView\n"
262 "to extract the message queues are not as expected in\n"
263 "the image '%s'\n"
264 "No message queue display is possible.\n"
265 "This is probably an MPICH version or configuration problem.";
266
267 /* Force in the file containing our wait-for-debugger function, to ensure
268 * that types have been read from there before we try to look them up.
269 */
270 dbgr_find_function (image, (char *)"MPIR_WaitForDebugger", mqs_lang_c, NULL);
271
272 /* Find the various global variables and structure definitions
273 that describe the communicator and message queue structures for
274 the MPICH2 implementation */
275
276 /* First, the communicator information. This is in two parts:
277 MPIR_All_Communicators - a structure containing the head of the
278 list of all active communicators. The type is MPIR_Comm_list.
279 The communicators themselves are of type MPID_Comm.
280 */
281 {
282 mqs_type *cl_type = dbgr_find_type( image, (char *)"MPIR_Comm_list",
283 mqs_lang_c );
284 if (cl_type) {
285 have_cl = 1;
286 i_info->sequence_number_offs =
287 dbgr_field_offset( cl_type, (char *)"sequence_number" );
288 i_info->comm_head_offs = dbgr_field_offset( cl_type, (char *)"head" );
289 }
290 }
291 {
292 mqs_type *co_type = dbgr_find_type( image, (char *)"MPID_Comm", mqs_lang_c );
293 if (co_type) {
294 have_co = 1;
295 i_info->comm_name_offs = dbgr_field_offset( co_type, (char *)"name" );
296 i_info->comm_next_offs = dbgr_field_offset( co_type, (char *)"comm_next" );
297 i_info->comm_rsize_offs = dbgr_field_offset( co_type, (char *)"remote_size" );
298 i_info->comm_rank_offs = dbgr_field_offset( co_type, (char *)"rank" );
299 i_info->comm_context_id_offs = dbgr_field_offset( co_type, (char *)"context_id" );
300 i_info->comm_recvcontext_id_offs = dbgr_field_offset( co_type, (char *)"recvcontext_id" );
301 }
302 }
303
304 /* Now the receive queues. The receive queues contain MPID_Request
305 objects, and the various fields are within types in that object.
306 To simplify the eventual access, we compute all offsets relative to the
307 request. This means diving into the types that make of the
308 request definition */
309 {
310 mqs_type *req_type = dbgr_find_type( image, (char *)"MPID_Request", mqs_lang_c );
311 if (req_type) {
312 int dev_offs;
313 have_req = 1;
314 dev_offs = dbgr_field_offset( req_type, (char *)"dev" );
315 i_info->req_status_offs = dbgr_field_offset( req_type, (char *)"status" );
316 i_info->req_cc_offs = dbgr_field_offset( req_type, (char *)"cc" );
317 if (dev_offs >= 0) {
318 mqs_type *dreq_type = dbgr_find_type( image, (char *)"MPIDI_Request",
319 mqs_lang_c );
320 i_info->req_dev_offs = dev_offs;
321 if (dreq_type) {
322 int loff, match_offs;
323 have_dreq = 1;
324 loff = dbgr_field_offset( dreq_type, (char *)"next" );
325 i_info->req_next_offs = dev_offs + loff;
326 loff = dbgr_field_offset( dreq_type, (char *)"user_buf" );
327 i_info->req_user_buf_offs = dev_offs + loff;
328 loff = dbgr_field_offset( dreq_type, (char *)"user_count" );
329 i_info->req_user_count_offs = dev_offs + loff;
330 loff = dbgr_field_offset( dreq_type, (char *)"datatype" );
331 i_info->req_datatype_offs = dev_offs + loff;
332 match_offs = dbgr_field_offset( dreq_type, (char *)"match" );
333 /*
334 Current definition from the mpidpre.h file for ch3.
335
336 typedef struct MPIDI_Message_match_parts {
337 int32_t tag;
338 MPIR_Rank_t rank;
339 MPIR_Context_id_t context_id;
340 } MPIDI_Message_match_parts_t;
341 typedef union {
342 MPIDI_Message_match_parts_t parts;
343 MPIR_Upint whole;
344 } MPIDI_Message_match;
345 */
346 if (match_offs >= 0) {
347 mqs_type *match_type = dbgr_find_type( image, (char *)"MPIDI_Message_match", mqs_lang_c );
348 if (match_type) {
349 int parts_offs = dbgr_field_offset( match_type, (char *)"parts" );
350 if (parts_offs >= 0) {
351 mqs_type *parts_type = dbgr_find_type( image, (char *)"MPIDI_Message_match_parts_t", mqs_lang_c );
352 if (parts_type) {
353 int moff;
354 moff = dbgr_field_offset( parts_type, (char *)"tag" );
355 i_info->req_tag_offs = dev_offs + match_offs + moff;
356 moff = dbgr_field_offset( parts_type, (char *)"rank" );
357 i_info->req_rank_offs = dev_offs + match_offs + moff;
358 moff = dbgr_field_offset( parts_type, (char *)"context_id" );
359 i_info->req_context_id_offs = dev_offs + match_offs + moff;
360 }
361 }
362 }
363 }
364 }
365 }
366 }
367 }
368
369 /* Send queues use a separate system */
370 {
371 mqs_type *sreq_type = dbgr_find_type( image, (char *)"MPIR_Sendq", mqs_lang_c );
372 if (sreq_type) {
373 i_info->sendq_next_offs = dbgr_field_offset( sreq_type, (char *)"next" );
374 i_info->sendq_tag_offs = dbgr_field_offset( sreq_type, (char *)"tag" );
375 i_info->sendq_rank_offs = dbgr_field_offset( sreq_type, (char *)"rank" );
376 i_info->sendq_context_id_offs = dbgr_field_offset( sreq_type, (char *)"context_id" );
377 i_info->sendq_req_offs = dbgr_field_offset( sreq_type, (char *)"sreq" );
378 }
379 }
380
381 return mqs_ok;
382 }
383 /* mqs_setup_process initializes the process structure.
384 * The memory allocated by this routine (and routines that modify this
385 * structure) is freed with mqs_destroy_process_info
386 */
mqs_setup_process(mqs_process * process,const mqs_process_callbacks * pcb)387 int mqs_setup_process (mqs_process *process, const mqs_process_callbacks *pcb)
388 {
389 /* Extract the addresses of the global variables we need and save
390 them away */
391 mpich_process_info *p_info =
392 (mpich_process_info *)dbgr_malloc (sizeof (mpich_process_info));
393
394 if (p_info) {
395 mqs_image *image;
396 mpich_image_info *i_info;
397
398 p_info->process_callbacks = pcb;
399
400 /* Now we can get the rest of the info ! */
401 image = dbgr_get_image (process);
402 i_info = (mpich_image_info *)dbgr_get_image_info (image);
403
404 /* Library starts at zero, so this ensures we go look to start with */
405 p_info->communicator_sequence = -1;
406 /* We have no communicators yet */
407 p_info->communicator_list = NULL;
408 /* Ask the debugger to initialize the structure that contains
409 the sizes of basic items (short, int, long, long long, and
410 void *) */
411 dbgr_get_type_sizes (process, &p_info->sizes);
412
413 /* Tell the debugger to associate p_info with process */
414 dbgr_put_process_info (process, (mqs_process_info *)p_info);
415
416 return mqs_ok;
417 }
418 else
419 return err_no_store;
420 }
mqs_process_has_queues(mqs_process * proc,char ** msg)421 int mqs_process_has_queues (mqs_process *proc, char **msg)
422 {
423 mpich_process_info *p_info =
424 (mpich_process_info *)dbgr_get_process_info (proc);
425 mqs_image * image = dbgr_get_image (proc);
426 mpich_image_info *i_info =
427 (mpich_image_info *)dbgr_get_image_info (image);
428 mqs_taddr_t head_ptr;
429
430 /* Don't bother with a pop up here, it's unlikely to be helpful */
431 *msg = 0;
432
433 /* Check first for the communicator list */
434 if (dbgr_find_symbol (image, (char *)"MPIR_All_communicators", &p_info->commlist_base) != mqs_ok)
435 return err_all_communicators;
436
437 /* Check for the receive and send queues */
438 if (dbgr_find_symbol( image, (char *)"MPID_Recvq_posted_head_ptr", &head_ptr ) != mqs_ok)
439 return err_posted;
440 p_info->posted_base = fetch_pointer( proc, head_ptr, p_info );
441
442 if (dbgr_find_symbol( image, (char *)"MPID_Recvq_unexpected_head_ptr", &head_ptr ) != mqs_ok)
443 return err_unexpected;
444 p_info->unexpected_base = fetch_pointer( proc, head_ptr, p_info );
445
446 /* Send queues are optional */
447 if (dbgr_find_symbol( image, (char *)"MPIR_Sendq_head", &p_info->sendq_base) ==
448 mqs_ok) {
449 p_info->has_sendq = 1;
450 }
451 else {
452 p_info->has_sendq = 0;
453 }
454
455 return mqs_ok;
456 }
457
458 /* This routine is called by the debugger to map an error code into a
459 printable string */
mqs_dll_error_string(int errcode)460 char * mqs_dll_error_string (int errcode)
461 {
462 switch (errcode) {
463 case err_silent_failure:
464 return (char *)"";
465 case err_no_current_communicator:
466 return (char *)"No current communicator in the communicator iterator";
467 case err_bad_request:
468 return (char *)"Attempting to setup to iterate over an unknown queue of operations";
469 case err_no_store:
470 return (char *)"Unable to allocate store";
471 case err_group_corrupt:
472 return (char *)"Could not read a communicator's group from the process (probably a store corruption)";
473 case err_unexpected:
474 return (char *)"Failed to find symbol MPID_Recvq_unexpected_head_ptr";
475 case err_posted:
476 return (char *)"Failed to find symbol MPID_Recvq_posted_head_ptr";
477 }
478 return (char *)"Unknown error code";
479 }
480 /* ------------------------------------------------------------------------ */
481 /* Queue Display
482 *
483 */
484
485 /* Communicator list.
486 *
487 * To avoid problems that might be caused by having the list of communicators
488 * change in the process that is being debugged, the communicator access
489 * routines make an internal copy of the communicator list.
490 *
491 */
492 /* update_communicator_list makes a copy of the list of currently active
493 * communicators and stores it in the mqs_process structure.
494 */
mqs_update_communicator_list(mqs_process * proc)495 int mqs_update_communicator_list (mqs_process *proc)
496 {
497 if (communicators_changed (proc))
498 return rebuild_communicator_list (proc);
499 else
500 return mqs_ok;
501 }
502 /* These three routines (setup_communicator_iterator, get_communicator,
503 * and next_communicator) provide a way to access each communicator in the
504 * list that is initialized by update_communicator_list.
505 */
mqs_setup_communicator_iterator(mqs_process * proc)506 int mqs_setup_communicator_iterator (mqs_process *proc)
507 {
508 mpich_process_info *p_info =
509 (mpich_process_info *)dbgr_get_process_info (proc);
510
511 /* Start at the front of the list again */
512 p_info->current_communicator = p_info->communicator_list;
513 /* Reset the operation iterator too */
514 p_info->next_msg = 0;
515
516 return p_info->current_communicator == NULL ? mqs_end_of_list : mqs_ok;
517 }
mqs_get_communicator(mqs_process * proc,mqs_communicator * comm)518 int mqs_get_communicator (mqs_process *proc, mqs_communicator *comm)
519 {
520 mpich_process_info *p_info =
521 (mpich_process_info *)dbgr_get_process_info (proc);
522
523 if (p_info->current_communicator) {
524 *comm = p_info->current_communicator->comm_info;
525 return mqs_ok;
526 }
527 else
528 return err_no_current_communicator;
529 }
mqs_next_communicator(mqs_process * proc)530 int mqs_next_communicator (mqs_process *proc)
531 {
532 mpich_process_info *p_info =
533 (mpich_process_info *)dbgr_get_process_info (proc);
534
535 p_info->current_communicator = p_info->current_communicator->next;
536
537 return (p_info->current_communicator != NULL) ? mqs_ok : mqs_end_of_list;
538 }
539 /* ------------------------------------------------------------------------ */
540 /* Iterate over the queues attached to the current communicator. */
541
542 /* Forward references for routines used to implement the operations */
543 static int fetch_send (mqs_process *proc, mpich_process_info *p_info,
544 mqs_pending_operation *res);
545 static int fetch_receive (mqs_process *proc, mpich_process_info *p_info,
546 mqs_pending_operation *res, int look_for_user_buffer);
547
mqs_setup_operation_iterator(mqs_process * proc,int op)548 int mqs_setup_operation_iterator (mqs_process *proc, int op)
549 {
550 mpich_process_info *p_info =
551 (mpich_process_info *)dbgr_get_process_info (proc);
552 /* mqs_image * image = dbgr_get_image (proc); */
553 /* mpich_image_info *i_info =
554 (mpich_image_info *)dbgr_get_image_info (image); */
555
556 p_info->what = (mqs_op_class)op;
557
558 switch (op) {
559 case mqs_pending_sends:
560 if (!p_info->has_sendq)
561 return mqs_no_information;
562 else {
563 p_info->next_msg = p_info->sendq_base;
564 return mqs_ok;
565 }
566
567 /* The address on the receive queues is the address of a pointer to
568 the head of the list. */
569 case mqs_pending_receives:
570 p_info->next_msg = p_info->posted_base;
571 return mqs_ok;
572
573 case mqs_unexpected_messages:
574 p_info->next_msg = p_info->unexpected_base;
575 return mqs_ok;
576
577 default:
578 return err_bad_request;
579 }
580 }
581
582 /* Fetch the next operation on the current communicator, from the
583 selected queue. Since MPICH2 does not (normally) use separate queues
584 for each communicator, we must compare the queue items with the
585 current communicator.
586 */
mqs_next_operation(mqs_process * proc,mqs_pending_operation * op)587 int mqs_next_operation (mqs_process *proc, mqs_pending_operation *op)
588 {
589 mpich_process_info *p_info =
590 (mpich_process_info *)dbgr_get_process_info (proc);
591
592 switch (p_info->what) {
593 case mqs_pending_receives:
594 return fetch_receive (proc,p_info,op,1);
595 case mqs_unexpected_messages:
596 return fetch_receive (proc,p_info,op,0);
597 case mqs_pending_sends:
598 return fetch_send (proc,p_info,op);
599 default: return err_bad_request;
600 }
601 }
602 /* ------------------------------------------------------------------------ */
603 /* Clean up routines
604 * These routines free any memory allocated when the process or image
605 * structures were allocated.
606 */
mqs_destroy_process_info(mqs_process_info * mp_info)607 void mqs_destroy_process_info (mqs_process_info *mp_info)
608 {
609 mpich_process_info *p_info = (mpich_process_info *)mp_info;
610
611 /* Need to handle the communicators and groups too */
612 mqs_free_communicator_list( p_info->communicator_list );
613
614 dbgr_free (p_info);
615 }
616
mqs_destroy_image_info(mqs_image_info * info)617 void mqs_destroy_image_info (mqs_image_info *info)
618 {
619 dbgr_free (info);
620 }
621
622 /* ------------------------------------------------------------------------ */
623
624 /* ------------------------------------------------------------------------ */
625 /* Internal Routine
626 *
627 * These routine know about the internal structure of the MPI implementation.
628 */
629
630 /* Get the next entry in the current receive queue (posted or unexpected) */
631
fetch_receive(mqs_process * proc,mpich_process_info * p_info,mqs_pending_operation * res,int look_for_user_buffer)632 static int fetch_receive (mqs_process *proc, mpich_process_info *p_info,
633 mqs_pending_operation *res, int look_for_user_buffer)
634 {
635 mqs_image * image = dbgr_get_image (proc);
636 mpich_image_info *i_info = (mpich_image_info *)dbgr_get_image_info (image);
637 communicator_t *comm = p_info->current_communicator;
638 int16_t wanted_context = comm->recvcontext_id;
639 mqs_taddr_t base = fetch_pointer (proc, p_info->next_msg, p_info);
640
641 #ifdef DEBUG_LIST_ITER
642 initLogFile();
643 fprintf( debugfp, "fetch receive base = %x, comm= %x, context = %d\n",
644 base, comm, wanted_context );
645 #endif
646 while (base != 0) {
647 /* Check this entry to see if the context matches */
648 int16_t actual_context = fetch_int16( proc, base + i_info->req_context_id_offs, p_info );
649
650 #ifdef DEBUG_LIST_ITER
651 initLogFile();
652 fprintf( debugfp, "fetch receive msg context = %d\n", actual_context );
653 #endif
654 if (actual_context == wanted_context) {
655 /* Found a request for this communicator */
656 int tag = fetch_int( proc, base + i_info->req_tag_offs, p_info );
657 int rank = fetch_int16( proc, base + i_info->req_rank_offs, p_info );
658 int is_complete = fetch_int ( proc, base + i_info->req_cc_offs, p_info);
659 mqs_tword_t user_buffer = fetch_pointer( proc,base+i_info->req_user_buf_offs, p_info);
660 int user_count = fetch_int( proc,base + i_info->req_user_count_offs, p_info );
661
662 /* Return -1 for ANY_TAG or ANY_SOURCE */
663 res->desired_tag = (tag >= 0) ? tag : -1;
664 res->desired_local_rank = (rank >= 0) ? rank : -1;
665 res->desired_global_rank = -1; /* Convert to rank in comm world,
666 if valid (in mpi-2, may
667 not be available) */
668 res->desired_length = user_count; /* Count, not bytes */
669
670 res->tag_wild = (tag < 0);
671 res->buffer = user_buffer;
672 /* We don't know the rest of these */
673 res->system_buffer = 0;
674 res->actual_local_rank = rank;
675 res->actual_global_rank = -1;
676 res->actual_tag = tag;
677 res->actual_length = -1;
678 res->extra_text[0][0] = 0;
679
680 res->status = (is_complete != 0) ? mqs_st_pending : mqs_st_complete;
681
682 /* Don't forget to step the queue ! */
683 p_info->next_msg = base + i_info->req_next_offs;
684 return mqs_ok;
685 }
686 else {
687 /* Try the next one */
688 base = fetch_pointer (proc, base + i_info->req_next_offs, p_info);
689 }
690 }
691 #if 0
692 while (base != 0)
693 { /* Well, there's a queue, at least ! */
694 mqs_tword_t actual_context = fetch_int16(proc, base + i_info->context_id_offs, p_info);
695
696 if (actual_context == wanted_context)
697 { /* Found a good one */
698 mqs_tword_t tag = fetch_int (proc, base + i_info->tag_offs, p_info);
699 mqs_tword_t tagmask = fetch_int (proc, base + i_info->tagmask_offs, p_info);
700 mqs_tword_t lsrc = fetch_int (proc, base + i_info->lsrc_offs, p_info);
701 mqs_tword_t srcmask = fetch_int (proc, base + i_info->srcmask_offs, p_info);
702 mqs_taddr_t ptr = fetch_pointer (proc, base + i_info->ptr_offs, p_info);
703
704 /* Fetch the fields from the MPIR_RHANDLE */
705 int is_complete = fetch_int (proc, ptr + i_info->is_complete_offs, p_info);
706 mqs_taddr_t buf = fetch_pointer (proc, ptr + i_info->buf_offs, p_info);
707 mqs_tword_t len = fetch_int (proc, ptr + i_info->len_offs, p_info);
708 mqs_tword_t count = fetch_int (proc, ptr + i_info->count_offs, p_info);
709
710 /* If we don't have start, then use buf instead... */
711 mqs_taddr_t start;
712 if (i_info->start_offs < 0)
713 start = buf;
714 else
715 start = fetch_pointer (proc, ptr + i_info->start_offs, p_info);
716
717 /* Hurrah, we should now be able to fill in all the necessary fields in the
718 * result !
719 */
720 res->status = is_complete ? mqs_st_complete : mqs_st_pending; /* We can't discern matched */
721 if (srcmask == 0)
722 {
723 res->desired_local_rank = -1;
724 res->desired_global_rank = -1;
725 }
726 else
727 {
728 res->desired_local_rank = lsrc;
729 res->desired_global_rank = translate (comm->group, lsrc);
730
731 }
732 res->tag_wild = (tagmask == 0);
733 res->desired_tag = tag;
734
735 if (look_for_user_buffer)
736 {
737 res->system_buffer = 0;
738 res->buffer = buf;
739 res->desired_length = len;
740 }
741 else
742 {
743 res->system_buffer = 1;
744 /* Correct an oddity. If the buffer length is zero then no buffer
745 * is allocated, but the descriptor is left with random data.
746 */
747 if (count == 0)
748 start = 0;
749
750 res->buffer = start;
751 res->desired_length = count;
752 }
753
754 if (is_complete)
755 { /* Fill in the actual results, rather than what we were looking for */
756 mqs_tword_t mpi_source = fetch_int (proc, ptr + i_info->MPI_SOURCE_offs, p_info);
757 mqs_tword_t mpi_tag = fetch_int (proc, ptr + i_info->MPI_TAG_offs, p_info);
758
759 res->actual_length = count;
760 res->actual_tag = mpi_tag;
761 res->actual_local_rank = mpi_source;
762 res->actual_global_rank= translate (comm->group, mpi_source);
763 }
764
765 /* Don't forget to step the queue ! */
766 p_info->next_msg = base + i_info->next_offs;
767 return mqs_ok;
768 }
769 else
770 { /* Try the next one */
771 base = fetch_pointer (proc, base + i_info->next_offs, p_info);
772 }
773 }
774 #endif
775 p_info->next_msg = 0;
776 return mqs_end_of_list;
777 } /* fetch_receive */
778
779 /* Get the next entry in the send queue, if there is one. The assumption is
780 that the MPI implementation is quiescent while these queue probes are
781 taking place, so we can simply keep track of the location of the "next"
782 entry. (in the next_msg field) */
fetch_send(mqs_process * proc,mpich_process_info * p_info,mqs_pending_operation * res)783 static int fetch_send (mqs_process *proc, mpich_process_info *p_info,
784 mqs_pending_operation *res)
785 {
786 mqs_image * image = dbgr_get_image (proc);
787 mpich_image_info *i_info = (mpich_image_info *)dbgr_get_image_info (image);
788 communicator_t *comm = p_info->current_communicator;
789 int wanted_context = comm->context_id;
790 mqs_taddr_t base = fetch_pointer (proc, p_info->next_msg, p_info);
791
792 if (!p_info->has_sendq)
793 return mqs_no_information;
794
795 #ifdef DEBUG_LIST_ITER
796 if (base) {
797 initLogFile();
798 fprintf( debugf, "comm ptr = %p, comm context = %d\n",
799 comm, comm->context_id );
800 }
801 #endif
802 /* Say what operation it is. We can only see non blocking send operations
803 * in MPICH. Other MPI systems may be able to show more here.
804 */
805 /* FIXME: handle size properly (declared as 64 in mpi_interface.h) */
806 strncpy ((char *)res->extra_text[0],"Non-blocking send",20);
807 res->extra_text[1][0] = 0;
808
809 while (base != 0) {
810 /* Check this entry to see if the context matches */
811 int actual_context = fetch_int16( proc, base + i_info->sendq_context_id_offs, p_info );
812
813 if (actual_context == wanted_context) {
814 /* Fill in some of the fields */
815 mqs_tword_t target = fetch_int (proc, base+i_info->sendq_rank_offs, p_info);
816 mqs_tword_t tag = fetch_int (proc, base+i_info->sendq_tag_offs, p_info);
817 mqs_tword_t length = 0;
818 mqs_taddr_t data = 0;
819 mqs_taddr_t sreq = fetch_pointer(proc, base+i_info->sendq_req_offs, p_info );
820 mqs_tword_t is_complete = fetch_int( proc, sreq+i_info->req_cc_offs, p_info );
821 data = fetch_pointer( proc, sreq+i_info->req_user_buf_offs, p_info );
822 length = fetch_int( proc, sreq+i_info->req_user_count_offs, p_info );
823 /* mqs_tword_t complete=0; */
824
825 #ifdef DEBUG_LIST_ITER
826 initLogFile();
827 fprintf( debugpf, "sendq entry = %p, rank off = %d, tag off = %d, context = %d\n",
828 base, i_info->sendq_rank_offs, i_info->sendq_tag_offs, actual_context );
829 #endif
830
831 /* Ok, fill in the results */
832 res->status = (is_complete != 0) ? mqs_st_pending : mqs_st_complete;
833 res->actual_local_rank = res->desired_local_rank = target;
834 res->actual_global_rank= res->desired_global_rank= translate (comm->group, target);
835 res->tag_wild = 0;
836 res->actual_tag = res->desired_tag = tag;
837 res->desired_length = res->actual_length = length;
838 res->system_buffer = 0;
839 res->buffer = data;
840
841
842 /* Don't forget to step the queue ! */
843 p_info->next_msg = base + i_info->sendq_next_offs;
844 return mqs_ok;
845 }
846 else {
847 /* Try the next one */
848 base = fetch_pointer (proc, base + i_info->sendq_next_offs, p_info);
849 }
850 }
851 #if 0
852 while (base != 0)
853 { /* Well, there's a queue, at least ! */
854 /* Check if it's one we're interested in ? */
855 mqs_taddr_t commp = fetch_pointer (proc, base+i_info->db_comm_offs, p_info);
856 mqs_taddr_t next = base+i_info->db_next_offs;
857
858 if (commp == comm->comm_info.unique_id)
859 { /* Found one */
860 mqs_tword_t target = fetch_int (proc, base+i_info->db_target_offs, p_info);
861 mqs_tword_t tag = fetch_int (proc, base+i_info->db_tag_offs, p_info);
862 mqs_tword_t length = fetch_int (proc, base+i_info->db_byte_length_offs, p_info);
863 mqs_taddr_t data = fetch_pointer (proc, base+i_info->db_data_offs, p_info);
864 mqs_taddr_t shandle= fetch_pointer (proc, base+i_info->db_shandle_offs, p_info);
865 mqs_tword_t complete=fetch_int (proc, shandle+i_info->is_complete_offs, p_info);
866
867 /* Ok, fill in the results */
868 res->status = complete ? mqs_st_complete : mqs_st_pending; /* We can't discern matched */
869 res->actual_local_rank = res->desired_local_rank = target;
870 res->actual_global_rank= res->desired_global_rank= translate (comm->group, target);
871 res->tag_wild = 0;
872 res->actual_tag = res->desired_tag = tag;
873 res->desired_length = res->actual_length = length;
874 res->system_buffer = 0;
875 res->buffer = data;
876
877 p_info->next_msg = next;
878 return mqs_ok;
879 }
880
881 base = fetch_pointer (proc, next, p_info);
882 }
883
884 p_info->next_msg = 0;
885 #endif
886 return mqs_end_of_list;
887 } /* fetch_send */
888
889 /* ------------------------------------------------------------------------ */
890 /* Communicator */
communicators_changed(mqs_process * proc)891 static int communicators_changed (mqs_process *proc)
892 {
893 mpich_process_info *p_info =
894 (mpich_process_info *)dbgr_get_process_info (proc);
895 mqs_image * image = dbgr_get_image (proc);
896 mpich_image_info *i_info =
897 (mpich_image_info *)dbgr_get_image_info (image);
898 mqs_tword_t new_seq = fetch_int (proc,
899 p_info->commlist_base+i_info->sequence_number_offs,
900 p_info);
901 int res = (new_seq != p_info->communicator_sequence);
902
903 /* Save the sequence number for next time */
904 p_info->communicator_sequence = new_seq;
905
906 return res;
907 }
908
909 /***********************************************************************
910 * Find a matching communicator on our list. We check the recv context
911 * as well as the address since the communicator structures may be
912 * being re-allocated from a free list, in which case the same
913 * address will be re-used a lot, which could confuse us.
914 */
find_communicator(mpich_process_info * p_info,mqs_taddr_t comm_base,int recv_ctx)915 static communicator_t * find_communicator ( mpich_process_info *p_info,
916 mqs_taddr_t comm_base, int recv_ctx)
917 {
918 communicator_t * comm = p_info->communicator_list;
919
920 for (; comm; comm=comm->next)
921 {
922 if (comm->comm_info.unique_id == comm_base &&
923 comm->recvcontext_id == recv_ctx)
924 return comm;
925 }
926
927 return NULL;
928 } /* find_communicator */
929 /* This is the comparison function used in the qsort call in
930 rebuild_communicator_list */
compare_comms(const void * a,const void * b)931 static int compare_comms (const void *a, const void *b)
932 {
933 communicator_t * ca = *(communicator_t **)a;
934 communicator_t * cb = *(communicator_t **)b;
935
936 return cb->recvcontext_id - ca->recvcontext_id;
937 } /* compare_comms */
rebuild_communicator_list(mqs_process * proc)938 static int rebuild_communicator_list (mqs_process *proc)
939 {
940 mpich_process_info *p_info =
941 (mpich_process_info *)dbgr_get_process_info (proc);
942 mqs_image * image = dbgr_get_image (proc);
943 mpich_image_info *i_info =
944 (mpich_image_info *)dbgr_get_image_info (image);
945 mqs_taddr_t comm_base = fetch_pointer (proc,
946 p_info->commlist_base+i_info->comm_head_offs,
947 p_info);
948
949 communicator_t **commp;
950 int commcount = 0;
951
952 /* Iterate over the list in the process comparing with the list
953 * we already have saved. This is n**2, because we search for each
954 * communicator on the existing list. I don't think it matters, though
955 * because there aren't that many communicators to worry about, and
956 * we only ever do this if something changed.
957 */
958 while (comm_base) {
959 /* We do have one to look at, so extract the info */
960 int recv_ctx = fetch_int16 (proc, comm_base+i_info->comm_recvcontext_id_offs, p_info);
961 int send_ctx = fetch_int16 (proc, comm_base+i_info->comm_context_id_offs, p_info);
962 communicator_t *old = find_communicator (p_info, comm_base, recv_ctx);
963
964 char *name = (char *)"--unnamed--";
965 char namebuffer[64];
966 /* In MPICH2, the name is preallocated and of size MPI_MAX_OBJECT_NAME */
967 if (dbgr_fetch_data( proc, comm_base+i_info->comm_name_offs,64,
968 namebuffer) == mqs_ok && namebuffer[0] != 0) {
969 name = namebuffer;
970 }
971
972 if (old) {
973 old->present = 1; /* We do want this communicator */
974 strncpy (old->comm_info.name, name, sizeof(old->comm_info.name) ); /* Make sure the name is up to date,
975 * it might have changed and we can't tell.
976 */
977 }
978 else {
979 mqs_taddr_t group_base = fetch_pointer (proc, comm_base+i_info->lrank_to_grank_offs,
980 p_info);
981 int np = fetch_int (proc, comm_base+i_info->comm_rsize_offs,p_info);
982 group_t *g = find_or_create_group (proc, np, group_base);
983 communicator_t *nc;
984
985 #if 0
986 if (!g)
987 return err_group_corrupt;
988 #endif
989
990 nc = (communicator_t *)dbgr_malloc (sizeof (communicator_t));
991
992 /* Save the results */
993 nc->next = p_info->communicator_list;
994 p_info->communicator_list = nc;
995 nc->present = 1;
996 nc->group = g;
997 nc->context_id = send_ctx;
998 nc->recvcontext_id = recv_ctx;
999
1000 strncpy (nc->comm_info.name, name, sizeof( nc->comm_info.name ) );
1001 nc->comm_info.unique_id = comm_base;
1002 nc->comm_info.size = np;
1003 nc->comm_info.local_rank = fetch_int (proc, comm_base+i_info->comm_rank_offs,p_info);
1004 #ifdef DEBUG_LIST_ITER
1005 initLogFile();
1006 fprintf( debugfp, "Adding communicator %p, send context=%d, recv context=%d, size=%d, name=%s\n",
1007 comm_base, send_ctx, recv_ctx, np, name );
1008 #endif
1009 #if 0
1010 nc->comm_info.local_rank= reverse_translate (g, dbgr_get_global_rank (proc));
1011 #endif
1012 }
1013 /* Step to the next communicator on the list */
1014 comm_base = fetch_pointer (proc, comm_base+i_info->comm_next_offs, p_info);
1015 }
1016
1017 /* Now iterate over the list tidying up any communicators which
1018 * no longer exist, and cleaning the flags on any which do.
1019 */
1020 commp = &p_info->communicator_list;
1021
1022 for (; *commp; commp = &(*commp)->next) {
1023 communicator_t *comm = *commp;
1024
1025 if (comm->present) {
1026 comm->present = 0;
1027 commcount++;
1028 }
1029 else {
1030 /* It needs to be deleted */
1031 *commp = comm->next; /* Remove from the list */
1032 group_decref (comm->group); /* Group is no longer referenced from here */
1033 dbgr_free (comm);
1034 }
1035 }
1036
1037 if (commcount) {
1038 /* Sort the list so that it is displayed in some semi-sane order. */
1039 communicator_t ** comm_array = (communicator_t **) dbgr_malloc (
1040 commcount * sizeof (communicator_t *));
1041 communicator_t *comm = p_info->communicator_list;
1042 int i;
1043 for (i=0; i<commcount; i++, comm=comm->next)
1044 comm_array [i] = comm;
1045
1046 /* Do the sort */
1047 qsort (comm_array, commcount, sizeof (communicator_t *), compare_comms);
1048
1049 /* Re build the list */
1050 p_info->communicator_list = NULL;
1051 for (i=0; i<commcount; i++) {
1052 comm = comm_array[i];
1053 comm->next = p_info->communicator_list;
1054 p_info->communicator_list = comm;
1055 }
1056
1057 dbgr_free (comm_array);
1058 }
1059
1060 return mqs_ok;
1061 } /* rebuild_communicator_list */
1062
1063 /* Internal routine to free the communicator list */
mqs_free_communicator_list(struct communicator_t * comm)1064 static void mqs_free_communicator_list( struct communicator_t *comm )
1065 {
1066 while (comm) {
1067 communicator_t *next = comm->next;
1068
1069 /* Release the group data structures */
1070 /* group_decref (comm->group); */
1071 dbgr_free (comm);
1072
1073 comm = next;
1074 }
1075 }
1076
1077 /* ------------------------------------------------------------------------ */
1078 /* Internal routine to fetch data from the process */
fetch_pointer(mqs_process * proc,mqs_taddr_t addr,mpich_process_info * p_info)1079 static mqs_taddr_t fetch_pointer (mqs_process * proc, mqs_taddr_t addr,
1080 mpich_process_info *p_info)
1081 {
1082 int asize = p_info->sizes.pointer_size;
1083 char data [8]; /* ASSUME a pointer fits in 8 bytes */
1084 mqs_taddr_t res = 0;
1085
1086 if (mqs_ok == dbgr_fetch_data (proc, addr, asize, data))
1087 dbgr_target_to_host (proc, data,
1088 ((char *)&res) + (host_is_big_endian ? sizeof(mqs_taddr_t)-asize : 0),
1089 asize);
1090
1091 return res;
1092 }
fetch_int(mqs_process * proc,mqs_taddr_t addr,mpich_process_info * p_info)1093 static mqs_tword_t fetch_int (mqs_process * proc, mqs_taddr_t addr,
1094 mpich_process_info *p_info)
1095 {
1096 int isize = p_info->sizes.int_size;
1097 char buffer[8]; /* ASSUME an integer fits in 8 bytes */
1098 mqs_tword_t res = 0;
1099
1100 if (mqs_ok == dbgr_fetch_data (proc, addr, isize, buffer))
1101 dbgr_target_to_host (proc, buffer,
1102 ((char *)&res) + (host_is_big_endian ? sizeof(mqs_tword_t)-isize : 0),
1103 isize);
1104
1105 return res;
1106 }
fetch_int16(mqs_process * proc,mqs_taddr_t addr,mpich_process_info * p_info)1107 static mqs_tword_t fetch_int16 (mqs_process * proc, mqs_taddr_t addr,
1108 mpich_process_info *p_info)
1109 {
1110 char buffer[8]; /* ASSUME an integer fits in 8 bytes */
1111 int16_t res = 0;
1112
1113 if (mqs_ok == dbgr_fetch_data (proc, addr, 2, buffer))
1114 dbgr_target_to_host (proc, buffer,
1115 ((char *)&res) + (host_is_big_endian ? sizeof(mqs_tword_t)-2 : 0),
1116 2);
1117
1118 return res;
1119 }
1120
1121 /* ------------------------------------------------------------------------- */
1122 /* With each communicator we need to translate ranks to/from their
1123 MPI_COMM_WORLD equivalents. This code is not yet implemented
1124 */
1125 /* ------------------------------------------------------------------------- */
1126 /* idx is rank in group this; return rank in MPI_COMM_WORLD */
translate(group_t * this,int idx)1127 static int translate (group_t *this, int idx)
1128 {
1129 return -1;
1130 }
1131 #if 0
1132 /* idx is rank in MPI_COMM_WORLD, return rank in group this */
1133 static int reverse_translate (group_t * this, int idx)
1134 {
1135 return -1;
1136 }
1137 #endif
find_or_create_group(mqs_process * proc,mqs_tword_t np,mqs_taddr_t table)1138 static group_t * find_or_create_group (mqs_process *proc,
1139 mqs_tword_t np,
1140 mqs_taddr_t table)
1141 {
1142 return 0;
1143 }
group_decref(group_t * group)1144 static void group_decref (group_t * group)
1145 {
1146 if (--(group->ref_count) == 0) {
1147 dbgr_free (group->local_to_global);
1148 dbgr_free (group);
1149 }
1150 } /* group_decref */
1151