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.
27 #if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks))
28 #include <sys/procfs.h>
31 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
37 /* FIXME: move all this conditional compilation in description
38 files or in configure.in */
40 #if defined (VXWORKS_TARGET)
41 #define THREAD_TO_PID(tid,lwpid) (tid)
44 #define THREAD_TO_PID(tid,lwpid) (0)
46 #elif (defined (sun) && defined (__SVR4))
47 #define THREAD_TO_PID thread_to_pid
49 #elif defined (sgi) || defined (__WIN32__) || defined (hpux)
50 #define THREAD_TO_PID(tid,lwpid) ((int)lwpid)
53 #define THREAD_TO_PID(tid,lwpid) (0)
56 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
57 #define THREAD_FETCH_REGISTERS dec_thread_fetch_registers
58 #define GET_CURRENT_THREAD dec_thread_get_current_thread
59 extern int dec_thread_get_registers (gdb_gregset_t
*, gdb_fpregset_t
*);
63 #define THREAD_FETCH_REGISTERS aix_thread_fetch_registers
64 #define GET_CURRENT_THREAD aix_thread_get_current_thread
67 #if defined(VXWORKS_TARGET)
68 #define GET_CURRENT_THREAD() ((void*)inferior_pid)
69 #define THREAD_FETCH_REGISTERS() (-1)
71 #elif defined (sun) && defined (__SVR4)
72 #define GET_CURRENT_THREAD solaris_thread_get_current_thread
73 #define THREAD_FETCH_REGISTERS() (-1)
74 extern void *GET_CURRENT_THREAD();
76 #elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
77 extern void *GET_CURRENT_THREAD();
79 #elif defined (__WIN32__) || defined (hpux)
80 #define GET_CURRENT_THREAD() (inferior_pid)
81 #define THREAD_FETCH_REGISTERS() (-1)
84 #define GET_CURRENT_THREAD() (NULL)
85 #define THREAD_FETCH_REGISTERS() (-1)
88 #define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
90 #define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var))
91 /* external declarations */
93 extern struct value
* find_function_in_inferior (char *);
95 /* Global visible variables */
97 struct task_entry
*task_list
= NULL
;
98 int ada__tasks_check_symbol_table
= 1;
99 void *pthread_kern_addr
= NULL
;
101 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
102 gdb_gregset_t gregset_saved
;
103 gdb_fpregset_t fpregset_saved
;
106 /* The maximum number of tasks known to the Ada runtime */
107 const int MAX_NUMBER_OF_KNOWN_TASKS
= 1000;
109 /* the current task */
110 int current_task
= -1, current_task_id
= -1, current_task_index
;
111 void *current_thread
, *current_lwp
;
113 char *ada_task_states
[] =
118 "Child Activation Wait",
120 "Waiting on entry call",
123 "Child Termination Wait",
124 "Wait Child in Term Alt",
132 /* Global internal types */
134 static char *ada_long_task_states
[] =
139 "Waiting for child activation",
140 "Blocked in accept statement",
141 "Waiting on entry call",
142 "Asynchronous Selective Wait",
144 "Waiting for children termination",
145 "Waiting for children in terminate alternative",
153 /* Global internal variables */
155 static int highest_task_num
= 0;
156 int thread_support
= 0; /* 1 if the thread library in use is supported */
157 static int gdbtk_task_initialization
= 0;
160 add_task_entry (void *p_task_id
, int index
)
162 struct task_entry
*new_task_entry
= NULL
;
163 struct task_entry
*pt
;
166 new_task_entry
= xmalloc (sizeof (struct task_entry
));
167 new_task_entry
->task_num
= highest_task_num
;
168 new_task_entry
->task_id
= p_task_id
;
169 new_task_entry
->known_tasks_index
= index
;
170 new_task_entry
->next_task
= NULL
;
174 while (pt
->next_task
)
176 pt
->next_task
= new_task_entry
;
179 else task_list
= new_task_entry
;
180 return new_task_entry
->task_num
;
184 get_entry_number (void *p_task_id
)
186 struct task_entry
*pt
;
191 if (pt
->task_id
== p_task_id
)
198 static struct task_entry
*
199 get_thread_entry_vptr (void *thread
)
201 struct task_entry
*pt
;
206 if (pt
->thread
== thread
)
213 static struct task_entry
*
214 get_entry_vptr (int p_task_num
)
216 struct task_entry
*pt
;
221 if (pt
->task_num
== p_task_num
)
229 init_task_list (void)
231 struct task_entry
*pt
, *old_pt
;
241 highest_task_num
= 0;
245 valid_task_id (int task
)
247 return get_entry_vptr (task
) != NULL
;
256 struct task_entry
*ent
;
257 extern int do_not_insert_breakpoints
;
259 #if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
263 ent
= get_thread_entry_vptr (GET_CURRENT_THREAD ());
264 return ent
? ent
->task_id
: 0;
267 /* FIXME: calling a function in the inferior with a multithreaded application
268 is not reliable, so return NULL if there is no safe way to get the current
273 int get_current_task ()
277 /* FIXME: language_ada should be defined in defs.h */
278 /* if (current_language->la_language != language_ada) return -1; */
280 result
= get_entry_number (get_self_id ());
282 /* return -1 if not found */
283 return result
== 0 ? -1 : result
;
286 /* Print detailed information about specified task */
289 info_task (char *arg
, int from_tty
)
292 struct task_entry
*pt
, *pt2
;
293 void *self_id
, *caller
;
294 struct task_fields atcb
, atcb2
;
295 struct entry_call call
;
300 /* FIXME: language_ada should be defined in defs.h */
301 /* if (current_language->la_language != language_ada)
303 printf_filtered ("The current language does not support tasks.\n");
307 pt
= get_entry_vptr (atoi (arg
));
310 printf_filtered ("Task %s not found.\n", arg
);
314 temp_task
= pt
->task_id
;
316 /* read the atcb in the inferior */
317 READ_MEMORY ((CORE_ADDR
) temp_task
, atcb
);
319 /* print the Ada task id */
320 printf_filtered ("Ada Task: %p\n", temp_task
);
322 /* print the name of the task */
323 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
);
330 else printf_filtered ("<no name>\n");
332 /* print the thread id */
334 if ((long) pt
->thread
< 65536)
335 printf_filtered ("Thread: %ld\n", (long int) pt
->thread
);
337 printf_filtered ("Thread: %p\n", pt
->thread
);
339 if ((long) pt
->lwp
!= 0)
341 if ((long) pt
->lwp
< 65536)
342 printf_filtered ("LWP: %ld\n", (long int) pt
->lwp
);
344 printf_filtered ("LWP: %p\n", pt
->lwp
);
347 /* print the parent gdb task id */
348 num
= get_entry_number (EXTRACT_ADDRESS (atcb
.parent
));
351 printf_filtered ("Parent: %d", num
);
352 pt2
= get_entry_vptr (num
);
353 READ_MEMORY ((CORE_ADDR
) pt2
->task_id
, atcb2
);
355 /* print the name of the task */
356 if (atcb2
.image
.P_ARRAY
!= NULL
) {
357 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_BOUNDS
),
359 bounds
[1] = EXTRACT_INT (bounds
[1]);
360 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_ARRAY
),
361 (char*) &image
, bounds
[1]);
362 printf_filtered (" (%.*s)\n", bounds
[1], image
);
365 printf_filtered ("\n");
368 printf_filtered ("No parent\n");
370 /* print the base priority of the task */
371 printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb
.priority
));
373 /* print the current state of the task */
375 /* check if this task is accepting a rendezvous */
376 if (atcb
.call
== NULL
)
379 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.call
), call
);
380 caller
= EXTRACT_ADDRESS (call
.self
);
385 num
= get_entry_number (caller
);
386 printf_filtered ("Accepting rendezvous with %d", num
);
390 pt2
= get_entry_vptr (num
);
391 READ_MEMORY ((CORE_ADDR
) pt2
->task_id
, atcb2
);
393 /* print the name of the task */
394 if (atcb2
.image
.P_ARRAY
!= NULL
) {
395 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_BOUNDS
),
397 bounds
[1] = EXTRACT_INT (bounds
[1]);
398 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb2
.image
.P_ARRAY
),
399 (char*) &image
, bounds
[1]);
400 printf_filtered (" (%.*s)\n", bounds
[1], image
);
403 printf_filtered ("\n");
406 printf_filtered ("\n");
409 printf_filtered ("State: %s\n", ada_long_task_states
[atcb
.state
]);
414 /* A useful function that shows the alignment of all the fields in the
415 tasks_fields structure
420 struct task_fields tf
;
421 void *tf_base
= &(tf
);
422 void *tf_state
= &(tf
.state
);
423 void *tf_entry_num
= &(tf
.entry_num
);
424 void *tf_parent
= &(tf
.parent
);
425 void *tf_priority
= &(tf
.priority
);
426 void *tf_current_priority
= &(tf
.current_priority
);
427 void *tf_image
= &(tf
.image
);
428 void *tf_call
= &(tf
.call
);
429 void *tf_thread
= &(tf
.thread
);
430 void *tf_lwp
= &(tf
.lwp
);
431 printf_filtered ("\n");
432 printf_filtered ("(tf_base = 0x%x)\n", tf_base
);
433 printf_filtered ("task_fields.entry_num at %3d (0x%x)\n", tf_entry_num
- tf_base
, tf_entry_num
);
434 printf_filtered ("task_fields.state at %3d (0x%x)\n", tf_state
- tf_base
, tf_state
);
435 printf_filtered ("task_fields.parent at %3d (0x%x)\n", tf_parent
- tf_base
, tf_parent
);
436 printf_filtered ("task_fields.priority at %3d (0x%x)\n", tf_priority
- tf_base
, tf_priority
);
437 printf_filtered ("task_fields.current_priority at %3d (0x%x)\n", tf_current_priority
- tf_base
, tf_current_priority
);
438 printf_filtered ("task_fields.image at %3d (0x%x)\n", tf_image
- tf_base
, tf_image
);
439 printf_filtered ("task_fields.call at %3d (0x%x)\n", tf_call
- tf_base
, tf_call
);
440 printf_filtered ("task_fields.thread at %3d (0x%x)\n", tf_thread
- tf_base
, tf_thread
);
441 printf_filtered ("task_fields.lwp at %3d (0x%x)\n", tf_lwp
- tf_base
, tf_lwp
);
442 printf_filtered ("\n");
446 /* Print information about currently known tasks */
449 info_tasks (char *arg
, int from_tty
)
452 int i
, task_number
, state
;
453 void *temp_task
, *temp_tasks
[MAX_NUMBER_OF_KNOWN_TASKS
];
454 struct task_entry
*pt
;
455 void *self_id
, *caller
, *thread_id
=NULL
;
456 struct task_fields atcb
;
457 struct entry_call call
;
463 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
468 static struct symbol
*sym
;
469 static struct minimal_symbol
*msym
;
470 static void *known_tasks_addr
= NULL
;
472 int init_only
= gdbtk_task_initialization
;
473 gdbtk_task_initialization
= 0;
477 if (PIDGET(inferior_ptid
) == 0)
479 printf_filtered ("The program is not being run under gdb. ");
480 printf_filtered ("Use 'run' or 'attach' first.\n");
484 if (ada__tasks_check_symbol_table
)
487 #if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
492 msym
= lookup_minimal_symbol (KNOWN_TASKS_NAME
, NULL
, NULL
);
494 known_tasks_addr
= (void *) SYMBOL_VALUE_ADDRESS (msym
);
496 #ifndef VXWORKS_TARGET
500 if (target_lookup_symbol (KNOWN_TASKS_NAME
, &known_tasks_addr
) != 0)
505 ada__tasks_check_symbol_table
= 0;
508 if (known_tasks_addr
== NULL
)
511 #if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
514 thread_id
= GET_CURRENT_THREAD ();
516 /* then we get a list of tasks created */
520 READ_MEMORY ((CORE_ADDR
) known_tasks_addr
, temp_tasks
);
522 for (i
=0; i
<MAX_NUMBER_OF_KNOWN_TASKS
; i
++)
524 temp_task
= EXTRACT_ADDRESS (temp_tasks
[i
]);
526 if (temp_task
!= NULL
)
528 task_number
= get_entry_number (temp_task
);
529 if (task_number
== 0)
530 task_number
= add_task_entry (temp_task
, i
);
534 /* Return without printing anything if this function was called in
535 order to init GDBTK tasking. */
537 if (init_only
) return;
539 /* print the header */
541 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
543 (" ID TID P-ID Pri Stack %% State Name\n");
545 printf_filtered (" ID TID P-ID Pri State Name\n");
548 /* Now that we have a list of task id's, we can print them */
552 temp_task
= pt
->task_id
;
554 /* read the atcb in the inferior */
555 READ_MEMORY ((CORE_ADDR
) temp_task
, atcb
);
557 /* store the thread id for future use */
558 pt
->thread
= EXTRACT_ADDRESS (atcb
.thread
);
561 pt
->lwp
= (void *) THREAD_TO_PID (atcb
.thread
, 0);
563 pt
->lwp
= EXTRACT_ADDRESS (atcb
.lwp
);
566 /* print a star if this task is the current one */
568 #if defined (__WIN32__) || defined (SGI) || defined (hpux)
569 printf_filtered (pt
->lwp
== thread_id
? "*" : " ");
571 printf_filtered (pt
->thread
== thread_id
? "*" : " ");
574 /* print the gdb task id */
575 printf_filtered ("%3d", pt
->task_num
);
577 /* print the Ada task id */
578 #ifndef VXWORKS_TARGET
579 printf_filtered (" %9lx", (long) temp_task
);
582 printf_filtered (" %#9lx", (unsigned long)pt
->thread
& 0x3ffffffffff);
584 printf_filtered (" %#9lx", (long)pt
->thread
);
588 /* print the parent gdb task id */
590 (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb
.parent
)));
592 /* print the base priority of the task */
593 printf_filtered (" %3d", EXTRACT_INT (atcb
.priority
));
595 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
596 if (pt
->task_num
== 1 || atcb
.state
== Terminated
)
598 printf_filtered (" Unknown");
602 read_memory ((CORE_ADDR
)atcb
.thread
, &thr
, sizeof (thr
));
603 current_thread
= atcb
.thread
;
604 regs
.regs
[SP_REGNUM
] = 0;
605 if (dec_thread_get_registers (®s
, NULL
) == 0) {
606 pt
->stack_per
= (100 * ((long)thr
.__stack_base
-
607 regs
.regs
[SP_REGNUM
])) / thr
.__stack_size
;
608 /* if the thread is terminated but still there, the
609 stack_base/size values are erroneous. Try to patch it */
610 if (pt
->stack_per
< 0 || pt
->stack_per
> 100) pt
->stack_per
= 0;
613 /* print information about stack space used in the thread */
614 if (thr
.__stack_size
< 1024*1024)
616 size
= thr
.__stack_size
/ 1024;
619 else if (thr
.__stack_size
< 1024*1024*1024)
621 size
= thr
.__stack_size
/ 1024 / 1024;
624 else /* Who knows... */
626 size
= thr
.__stack_size
/ 1024 / 1024 / 1024;
629 printf_filtered (" %4d%c %2d", size
, car
, pt
->stack_per
);
633 /* print the current state of the task */
635 /* check if this task is accepting a rendezvous */
636 if (atcb
.call
== NULL
)
639 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.call
), call
);
640 caller
= EXTRACT_ADDRESS (call
.self
);
644 printf_filtered (" Accepting RV with %-4d", get_entry_number (caller
));
648 #if defined (__WIN32__) || defined (SGI) || defined (hpux)
649 if (state
== Runnable
&& (thread_id
&& pt
->lwp
== thread_id
))
651 if (state
== Runnable
&& (thread_id
&& pt
->thread
== thread_id
))
653 /* Replace "Runnable" by "Running" if this is the current task */
654 printf_filtered (" %-22s", "Running");
656 printf_filtered (" %-22s", ada_task_states
[state
]);
659 /* finally, print the name of the task */
660 if (atcb
.image
.P_ARRAY
!= NULL
) {
661 READ_MEMORY ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.image
.P_BOUNDS
), bounds
);
662 bounds
[1] = EXTRACT_INT (bounds
[1]);
663 read_memory ((CORE_ADDR
) EXTRACT_ADDRESS (atcb
.image
.P_ARRAY
),
664 (char*)&image
, bounds
[1]);
665 printf_filtered (" %.*s\n", bounds
[1], image
);
667 else printf_filtered (" <no name>\n");
673 /* Task list initialization for GDB-Tk. We basically use info_tasks()
674 to initialize our variables, but abort that function before we
675 actually print anything. */
678 gdbtk_tcl_tasks_initialize (void)
680 gdbtk_task_initialization
= 1;
681 info_tasks ("", gdb_stdout
);
683 return (task_list
!= NULL
);
687 info_tasks_command (char *arg
, int from_tty
)
689 if (arg
== NULL
|| *arg
== '\000')
690 info_tasks (arg
, from_tty
);
692 info_task (arg
, from_tty
);
695 /* Switch from one thread to another. */
698 switch_to_thread (ptid_t ptid
)
700 if (ptid_equal (ptid
, inferior_ptid
))
703 inferior_ptid
= ptid
;
704 flush_cached_frames ();
705 registers_changed ();
706 stop_pc
= read_pc ();
707 select_frame (get_current_frame ());
710 /* Switch to a specified task. */
713 task_switch (void *tid
, void *lwpid
)
719 flush_cached_frames ();
721 if (current_task
!= current_task_id
)
723 res
= THREAD_FETCH_REGISTERS ();
727 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
728 supply_gregset (&gregset_saved
);
729 supply_fpregset (&fpregset_saved
);
733 if (res
== 0) stop_pc
= read_pc();
734 select_frame (get_current_frame ());
742 task_command (char *tidstr
, int from_tty
)
745 struct task_entry
*e
;
748 error ("Please specify a task ID. Use the \"info tasks\" command to\n"
749 "see the IDs of currently known tasks.");
752 e
= get_entry_vptr (num
);
755 error ("Task ID %d not known. Use the \"info tasks\" command to\n"
756 "see the IDs of currently known tasks.", num
);
758 if (current_task_id
== -1)
760 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
761 fill_gregset (&gregset_saved
, -1);
762 fill_fpregset (&fpregset_saved
, -1);
764 current_task_id
= get_current_task ();
768 current_task_index
= e
->known_tasks_index
;
769 current_thread
= e
->thread
;
770 current_lwp
= e
->lwp
;
771 if (task_switch (e
->thread
, e
->lwp
) == 0)
773 /* FIXME: find_printable_frame should be defined in frame.h, and
774 implemented in ada-lang.c */
775 /* find_printable_frame (selected_frame, frame_relative_level (selected_frame));*/
776 printf_filtered ("[Switching to task %d]\n", num
);
777 print_stack_frame (selected_frame
, frame_relative_level (selected_frame
), 1);
780 printf_filtered ("Unable to switch to task %d\n", num
);
784 _initialize_tasks (void)
786 static struct cmd_list_element
*task_cmd_list
= NULL
;
787 extern struct cmd_list_element
*cmdlist
;
790 "tasks", info_tasks_command
,
791 "Without argument: list all known Ada tasks, with status information.\n"
792 "info tasks n: print detailed information of task n.\n");
794 add_prefix_cmd ("task", class_run
, task_command
,
795 "Use this command to switch between tasks.\n\
796 The new task ID must be currently known.", &task_cmd_list
, "task ", 1,