1 /* file ada-tasks.c: Ada tasking control for GDB
2 Copyright 1997 Free Software Foundation, Inc.
3 Contributed by Ada Core Technologies, Inc
5 This file is part of GDB.
8 Authors: Roch-Alexandre Nomine Beguin, Arnaud Charlet <charlet@gnat.com>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
28 #if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks))
29 #include <sys/procfs.h>
32 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
38 /* FIXME: move all this conditional compilation in description
39 files or in configure.in */
41 #if defined (VXWORKS_TARGET)
42 #define THREAD_TO_PID(tid,lwpid) (tid)
45 #define THREAD_TO_PID(tid,lwpid) (0)
47 #elif (defined (sun) && defined (__SVR4))
48 #define THREAD_TO_PID thread_to_pid
50 #elif defined (sgi) || defined (__WIN32__) || defined (hpux)
51 #define THREAD_TO_PID(tid,lwpid) ((int)lwpid)
54 #define THREAD_TO_PID(tid,lwpid) (0)
57 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
58 #define THREAD_FETCH_REGISTERS dec_thread_fetch_registers
59 #define GET_CURRENT_THREAD dec_thread_get_current_thread
60 extern int dec_thread_get_registers (gdb_gregset_t
*, gdb_fpregset_t
*);
64 #define THREAD_FETCH_REGISTERS aix_thread_fetch_registers
65 #define GET_CURRENT_THREAD aix_thread_get_current_thread
68 #if defined(VXWORKS_TARGET)
69 #define GET_CURRENT_THREAD() ((void*)inferior_pid)
70 #define THREAD_FETCH_REGISTERS() (-1)
72 #elif defined (sun) && defined (__SVR4)
73 #define GET_CURRENT_THREAD solaris_thread_get_current_thread
74 #define THREAD_FETCH_REGISTERS() (-1)
75 extern void *GET_CURRENT_THREAD ();
77 #elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
78 extern void *GET_CURRENT_THREAD ();
80 #elif defined (__WIN32__) || defined (hpux)
81 #define GET_CURRENT_THREAD() (inferior_pid)
82 #define THREAD_FETCH_REGISTERS() (-1)
85 #define GET_CURRENT_THREAD() (NULL)
86 #define THREAD_FETCH_REGISTERS() (-1)
89 #define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
91 #define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var))
92 /* external declarations */
94 /* Global visible variables */
96 struct task_entry
*task_list
= NULL
;
97 int ada__tasks_check_symbol_table
= 1;
98 void *pthread_kern_addr
= NULL
;
100 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
101 gdb_gregset_t gregset_saved
;
102 gdb_fpregset_t fpregset_saved
;
105 /* The maximum number of tasks known to the Ada runtime */
106 const int MAX_NUMBER_OF_KNOWN_TASKS
= 1000;
108 /* the current task */
109 int current_task
= -1, current_task_id
= -1, current_task_index
;
110 void *current_thread
, *current_lwp
;
112 char *ada_task_states
[] = {
116 "Child Activation Wait",
118 "Waiting on entry call",
121 "Child Termination Wait",
122 "Wait Child in Term Alt",
130 /* Global internal types */
132 static char *ada_long_task_states
[] = {
136 "Waiting for child activation",
137 "Blocked in accept statement",
138 "Waiting on entry call",
139 "Asynchronous Selective Wait",
141 "Waiting for children termination",
142 "Waiting for children in terminate alternative",
150 /* Global internal variables */
152 static int highest_task_num
= 0;
153 int thread_support
= 0; /* 1 if the thread library in use is supported */
154 static int gdbtk_task_initialization
= 0;
157 add_task_entry (void *p_task_id
, int index
)
159 struct task_entry
*new_task_entry
= NULL
;
160 struct task_entry
*pt
;
163 new_task_entry
= xmalloc (sizeof (struct task_entry
));
164 new_task_entry
->task_num
= highest_task_num
;
165 new_task_entry
->task_id
= p_task_id
;
166 new_task_entry
->known_tasks_index
= index
;
167 new_task_entry
->next_task
= NULL
;
171 while (pt
->next_task
)
173 pt
->next_task
= new_task_entry
;
177 task_list
= new_task_entry
;
178 return new_task_entry
->task_num
;
182 get_entry_number (void *p_task_id
)
184 struct task_entry
*pt
;
189 if (pt
->task_id
== p_task_id
)
196 static struct task_entry
*
197 get_thread_entry_vptr (void *thread
)
199 struct task_entry
*pt
;
204 if (pt
->thread
== thread
)
211 static struct task_entry
*
212 get_entry_vptr (int p_task_num
)
214 struct task_entry
*pt
;
219 if (pt
->task_num
== p_task_num
)
227 init_task_list (void)
229 struct task_entry
*pt
, *old_pt
;
239 highest_task_num
= 0;
243 valid_task_id (int task
)
245 return get_entry_vptr (task
) != NULL
;
254 struct task_entry
*ent
;
255 extern int do_not_insert_breakpoints
;
257 #if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
261 ent
= get_thread_entry_vptr (GET_CURRENT_THREAD ());
262 return ent
? ent
->task_id
: 0;
265 /* FIXME: calling a function in the inferior with a multithreaded application
266 is not reliable, so return NULL if there is no safe way to get the current
272 get_current_task (void)
276 /* FIXME: language_ada should be defined in defs.h */
277 /* if (current_language->la_language != language_ada) return -1; */
279 result
= get_entry_number (get_self_id ());
281 /* return -1 if not found */
282 return result
== 0 ? -1 : result
;
285 /* Print detailed information about specified task */
288 info_task (char *arg
, int from_tty
)
291 struct task_entry
*pt
, *pt2
;
292 void *self_id
, *caller
;
293 struct task_fields atcb
, atcb2
;
294 struct entry_call call
;
299 /* FIXME: language_ada should be defined in defs.h */
300 /* if (current_language->la_language != language_ada)
302 printf_filtered ("The current language does not support tasks.\n");
306 pt
= get_entry_vptr (atoi (arg
));
309 printf_filtered ("Task %s not found.\n", arg
);
313 temp_task
= pt
->task_id
;
315 /* read the atcb in the inferior */
316 READ_MEMORY ((CORE_ADDR
) temp_task
, atcb
);
318 /* print the Ada task id */
319 printf_filtered ("Ada Task: %p\n", temp_task
);
321 /* print the name of the task */
322 if (atcb
.image
.P_ARRAY
!= NULL
)
324 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.image
.P_BOUNDS
), bounds
);
325 bounds
[1] = EXTRACT_INT (bounds
[1]);
326 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.image
.P_ARRAY
),
327 (char *) &image
, bounds
[1]);
328 printf_filtered ("Name: %.*s\n", bounds
[1], image
);
331 printf_filtered ("<no name>\n");
333 /* print the thread id */
335 if ((long) pt
->thread
< 65536)
336 printf_filtered ("Thread: %ld\n", (long int) pt
->thread
);
338 printf_filtered ("Thread: %p\n", pt
->thread
);
340 if ((long) pt
->lwp
!= 0)
342 if ((long) pt
->lwp
< 65536)
343 printf_filtered ("LWP: %ld\n", (long int) pt
->lwp
);
345 printf_filtered ("LWP: %p\n", pt
->lwp
);
348 /* print the parent gdb task id */
349 num
= get_entry_number (EXTRACT_ADDRESS (atcb
.parent
));
352 printf_filtered ("Parent: %d", num
);
353 pt2
= get_entry_vptr (num
);
354 READ_MEMORY ((CORE_ADDR
) pt2
->task_id
, atcb2
);
356 /* print the name of the task */
357 if (atcb2
.image
.P_ARRAY
!= NULL
)
359 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_BOUNDS
),
361 bounds
[1] = EXTRACT_INT (bounds
[1]);
362 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_ARRAY
),
363 (char *) &image
, bounds
[1]);
364 printf_filtered (" (%.*s)\n", bounds
[1], image
);
367 printf_filtered ("\n");
370 printf_filtered ("No parent\n");
372 /* print the base priority of the task */
373 printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb
.priority
));
375 /* print the current state of the task */
377 /* check if this task is accepting a rendezvous */
378 if (atcb
.call
== NULL
)
382 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.call
), call
);
383 caller
= EXTRACT_ADDRESS (call
.self
);
388 num
= get_entry_number (caller
);
389 printf_filtered ("Accepting rendezvous with %d", num
);
393 pt2
= get_entry_vptr (num
);
394 READ_MEMORY ((CORE_ADDR
) pt2
->task_id
, atcb2
);
396 /* print the name of the task */
397 if (atcb2
.image
.P_ARRAY
!= NULL
)
399 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_BOUNDS
),
401 bounds
[1] = EXTRACT_INT (bounds
[1]);
402 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_ARRAY
),
403 (char *) &image
, bounds
[1]);
404 printf_filtered (" (%.*s)\n", bounds
[1], image
);
407 printf_filtered ("\n");
410 printf_filtered ("\n");
413 printf_filtered ("State: %s\n", ada_long_task_states
[atcb
.state
]);
418 /* A useful function that shows the alignment of all the fields in the
419 tasks_fields structure
424 struct task_fields tf
;
425 void *tf_base
= &(tf
);
426 void *tf_state
= &(tf
.state
);
427 void *tf_entry_num
= &(tf
.entry_num
);
428 void *tf_parent
= &(tf
.parent
);
429 void *tf_priority
= &(tf
.priority
);
430 void *tf_current_priority
= &(tf
.current_priority
);
431 void *tf_image
= &(tf
.image
);
432 void *tf_call
= &(tf
.call
);
433 void *tf_thread
= &(tf
.thread
);
434 void *tf_lwp
= &(tf
.lwp
);
435 printf_filtered ("\n");
436 printf_filtered ("(tf_base = 0x%x)\n", tf_base
);
437 printf_filtered ("task_fields.entry_num at %3d (0x%x)\n",
438 tf_entry_num
- tf_base
, tf_entry_num
);
439 printf_filtered ("task_fields.state at %3d (0x%x)\n",
440 tf_state
- tf_base
, tf_state
);
441 printf_filtered ("task_fields.parent at %3d (0x%x)\n",
442 tf_parent
- tf_base
, tf_parent
);
443 printf_filtered ("task_fields.priority at %3d (0x%x)\n",
444 tf_priority
- tf_base
, tf_priority
);
445 printf_filtered ("task_fields.current_priority at %3d (0x%x)\n",
446 tf_current_priority
- tf_base
, tf_current_priority
);
447 printf_filtered ("task_fields.image at %3d (0x%x)\n",
448 tf_image
- tf_base
, tf_image
);
449 printf_filtered ("task_fields.call at %3d (0x%x)\n",
450 tf_call
- tf_base
, tf_call
);
451 printf_filtered ("task_fields.thread at %3d (0x%x)\n",
452 tf_thread
- tf_base
, tf_thread
);
453 printf_filtered ("task_fields.lwp at %3d (0x%x)\n",
454 tf_lwp
- tf_base
, tf_lwp
);
455 printf_filtered ("\n");
459 /* Print information about currently known tasks */
462 info_tasks (char *arg
, int from_tty
)
465 int i
, task_number
, state
;
466 void *temp_task
, *temp_tasks
[MAX_NUMBER_OF_KNOWN_TASKS
];
467 struct task_entry
*pt
;
468 void *self_id
, *caller
, *thread_id
= NULL
;
469 struct task_fields atcb
;
470 struct entry_call call
;
476 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
481 static struct symbol
*sym
;
482 static struct minimal_symbol
*msym
;
483 static void *known_tasks_addr
= NULL
;
485 int init_only
= gdbtk_task_initialization
;
486 gdbtk_task_initialization
= 0;
490 if (PIDGET (inferior_ptid
) == 0)
492 printf_filtered ("The program is not being run under gdb. ");
493 printf_filtered ("Use 'run' or 'attach' first.\n");
497 if (ada__tasks_check_symbol_table
)
500 #if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
505 msym
= lookup_minimal_symbol (KNOWN_TASKS_NAME
, NULL
, NULL
);
507 known_tasks_addr
= (void *) SYMBOL_VALUE_ADDRESS (msym
);
509 #ifndef VXWORKS_TARGET
513 if (target_lookup_symbol (KNOWN_TASKS_NAME
, &known_tasks_addr
) != 0)
518 ada__tasks_check_symbol_table
= 0;
521 if (known_tasks_addr
== NULL
)
524 #if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
527 thread_id
= GET_CURRENT_THREAD ();
529 /* then we get a list of tasks created */
533 READ_MEMORY ((CORE_ADDR
) known_tasks_addr
, temp_tasks
);
535 for (i
= 0; i
< MAX_NUMBER_OF_KNOWN_TASKS
; i
++)
537 temp_task
= EXTRACT_ADDRESS (temp_tasks
[i
]);
539 if (temp_task
!= NULL
)
541 task_number
= get_entry_number (temp_task
);
542 if (task_number
== 0)
543 task_number
= add_task_entry (temp_task
, i
);
547 /* Return without printing anything if this function was called in
548 order to init GDBTK tasking. */
553 /* print the header */
555 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
557 (" ID TID P-ID Pri Stack %% State Name\n");
559 printf_filtered (" ID TID P-ID Pri State Name\n");
562 /* Now that we have a list of task id's, we can print them */
566 temp_task
= pt
->task_id
;
568 /* read the atcb in the inferior */
569 READ_MEMORY ((CORE_ADDR
) temp_task
, atcb
);
571 /* store the thread id for future use */
572 pt
->thread
= EXTRACT_ADDRESS (atcb
.thread
);
575 pt
->lwp
= (void *) THREAD_TO_PID (atcb
.thread
, 0);
577 pt
->lwp
= EXTRACT_ADDRESS (atcb
.lwp
);
580 /* print a star if this task is the current one */
582 #if defined (__WIN32__) || defined (SGI) || defined (hpux)
583 printf_filtered (pt
->lwp
== thread_id
? "*" : " ");
585 printf_filtered (pt
->thread
== thread_id
? "*" : " ");
588 /* print the gdb task id */
589 printf_filtered ("%3d", pt
->task_num
);
591 /* print the Ada task id */
592 #ifndef VXWORKS_TARGET
593 printf_filtered (" %9lx", (long) temp_task
);
596 printf_filtered (" %#9lx", (unsigned long) pt
->thread
& 0x3ffffffffff);
598 printf_filtered (" %#9lx", (long) pt
->thread
);
602 /* print the parent gdb task id */
604 (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb
.parent
)));
606 /* print the base priority of the task */
607 printf_filtered (" %3d", EXTRACT_INT (atcb
.priority
));
609 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
610 if (pt
->task_num
== 1 || atcb
.state
== Terminated
)
612 printf_filtered (" Unknown");
616 read_memory ((CORE_ADDR
) atcb
.thread
, &thr
, sizeof (thr
));
617 current_thread
= atcb
.thread
;
618 regs
.regs
[SP_REGNUM
] = 0;
619 if (dec_thread_get_registers (®s
, NULL
) == 0)
621 pt
->stack_per
= (100 * ((long) thr
.__stack_base
-
622 regs
.regs
[SP_REGNUM
])) / thr
.__stack_size
;
623 /* if the thread is terminated but still there, the
624 stack_base/size values are erroneous. Try to patch it */
625 if (pt
->stack_per
< 0 || pt
->stack_per
> 100)
629 /* print information about stack space used in the thread */
630 if (thr
.__stack_size
< 1024 * 1024)
632 size
= thr
.__stack_size
/ 1024;
635 else if (thr
.__stack_size
< 1024 * 1024 * 1024)
637 size
= thr
.__stack_size
/ 1024 / 1024;
640 else /* Who knows... */
642 size
= thr
.__stack_size
/ 1024 / 1024 / 1024;
645 printf_filtered (" %4d%c %2d", size
, car
, pt
->stack_per
);
649 /* print the current state of the task */
651 /* check if this task is accepting a rendezvous */
652 if (atcb
.call
== NULL
)
656 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.call
), call
);
657 caller
= EXTRACT_ADDRESS (call
.self
);
661 printf_filtered (" Accepting RV with %-4d",
662 get_entry_number (caller
));
666 #if defined (__WIN32__) || defined (SGI) || defined (hpux)
667 if (state
== Runnable
&& (thread_id
&& pt
->lwp
== thread_id
))
669 if (state
== Runnable
&& (thread_id
&& pt
->thread
== thread_id
))
671 /* Replace "Runnable" by "Running" if this is the current task */
672 printf_filtered (" %-22s", "Running");
674 printf_filtered (" %-22s", ada_task_states
[state
]);
677 /* finally, print the name of the task */
678 if (atcb
.image
.P_ARRAY
!= NULL
)
680 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.image
.P_BOUNDS
),
682 bounds
[1] = EXTRACT_INT (bounds
[1]);
683 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.image
.P_ARRAY
),
684 (char *) &image
, bounds
[1]);
685 printf_filtered (" %.*s\n", bounds
[1], image
);
688 printf_filtered (" <no name>\n");
694 /* Task list initialization for GDB-Tk. We basically use info_tasks()
695 to initialize our variables, but abort that function before we
696 actually print anything. */
699 gdbtk_tcl_tasks_initialize (void)
701 gdbtk_task_initialization
= 1;
702 info_tasks ("", gdb_stdout
);
704 return (task_list
!= NULL
);
708 info_tasks_command (char *arg
, int from_tty
)
710 if (arg
== NULL
|| *arg
== '\000')
711 info_tasks (arg
, from_tty
);
713 info_task (arg
, from_tty
);
716 /* Switch from one thread to another. */
719 switch_to_thread (ptid_t ptid
)
721 if (ptid_equal (ptid
, inferior_ptid
))
724 inferior_ptid
= ptid
;
725 flush_cached_frames ();
726 registers_changed ();
727 stop_pc
= read_pc ();
728 select_frame (get_current_frame ());
731 /* Switch to a specified task. */
734 task_switch (void *tid
, void *lwpid
)
740 flush_cached_frames ();
742 if (current_task
!= current_task_id
)
744 res
= THREAD_FETCH_REGISTERS ();
748 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
749 supply_gregset (&gregset_saved
);
750 supply_fpregset (&fpregset_saved
);
755 stop_pc
= read_pc ();
756 select_frame (get_current_frame ());
764 task_command (char *tidstr
, int from_tty
)
767 struct task_entry
*e
;
770 error ("Please specify a task ID. Use the \"info tasks\" command to\n"
771 "see the IDs of currently known tasks.");
774 e
= get_entry_vptr (num
);
777 error ("Task ID %d not known. Use the \"info tasks\" command to\n"
778 "see the IDs of currently known tasks.", num
);
780 if (current_task_id
== -1)
782 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
783 fill_gregset (&gregset_saved
, -1);
784 fill_fpregset (&fpregset_saved
, -1);
786 current_task_id
= get_current_task ();
790 current_task_index
= e
->known_tasks_index
;
791 current_thread
= e
->thread
;
792 current_lwp
= e
->lwp
;
793 if (task_switch (e
->thread
, e
->lwp
) == 0)
795 /* FIXME: find_printable_frame should be defined in frame.h, and
796 implemented in ada-lang.c */
797 /* find_printable_frame (deprecated_selected_frame, frame_relative_level (deprecated_selected_frame)); */
798 printf_filtered ("[Switching to task %d]\n", num
);
799 print_stack_frame (deprecated_selected_frame
,
800 frame_relative_level (deprecated_selected_frame
), 1);
803 printf_filtered ("Unable to switch to task %d\n", num
);
807 _initialize_tasks (void)
809 static struct cmd_list_element
*task_cmd_list
= NULL
;
810 extern struct cmd_list_element
*cmdlist
;
812 add_info ("tasks", info_tasks_command
,
813 "Without argument: list all known Ada tasks, with status information.\n"
814 "info tasks n: print detailed information of task n.\n");
816 add_prefix_cmd ("task", class_run
, task_command
,
817 "Use this command to switch between tasks.\n\
818 The new task ID must be currently known.", &task_cmd_list
, "task ", 1, &cmdlist
);