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.
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[] = {
117 "Child Activation Wait",
119 "Waiting on entry call",
122 "Child Termination Wait",
123 "Wait Child in Term Alt",
131 /* Global internal types */
133 static char *ada_long_task_states[] = {
137 "Waiting for child activation",
138 "Blocked in accept statement",
139 "Waiting on entry call",
140 "Asynchronous Selective Wait",
142 "Waiting for children termination",
143 "Waiting for children in terminate alternative",
151 /* Global internal variables */
153 static int highest_task_num = 0;
154 int thread_support = 0; /* 1 if the thread library in use is supported */
155 static int gdbtk_task_initialization = 0;
158 add_task_entry (void *p_task_id, int index)
160 struct task_entry *new_task_entry = NULL;
161 struct task_entry *pt;
164 new_task_entry = xmalloc (sizeof (struct task_entry));
165 new_task_entry->task_num = highest_task_num;
166 new_task_entry->task_id = p_task_id;
167 new_task_entry->known_tasks_index = index;
168 new_task_entry->next_task = NULL;
172 while (pt->next_task)
174 pt->next_task = new_task_entry;
178 task_list = new_task_entry;
179 return new_task_entry->task_num;
183 get_entry_number (void *p_task_id)
185 struct task_entry *pt;
190 if (pt->task_id == p_task_id)
197 static struct task_entry *
198 get_thread_entry_vptr (void *thread)
200 struct task_entry *pt;
205 if (pt->thread == thread)
212 static struct task_entry *
213 get_entry_vptr (int p_task_num)
215 struct task_entry *pt;
220 if (pt->task_num == p_task_num)
228 init_task_list (void)
230 struct task_entry *pt, *old_pt;
240 highest_task_num = 0;
244 valid_task_id (int task)
246 return get_entry_vptr (task) != NULL;
255 struct task_entry *ent;
256 extern int do_not_insert_breakpoints;
258 #if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
262 ent = get_thread_entry_vptr (GET_CURRENT_THREAD ());
263 return ent ? ent->task_id : 0;
266 /* FIXME: calling a function in the inferior with a multithreaded application
267 is not reliable, so return NULL if there is no safe way to get the current
273 get_current_task (void)
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)
325 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds);
326 bounds[1] = EXTRACT_INT (bounds[1]);
327 read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
328 (char *) &image, bounds[1]);
329 printf_filtered ("Name: %.*s\n", bounds[1], image);
332 printf_filtered ("<no name>\n");
334 /* print the thread id */
336 if ((long) pt->thread < 65536)
337 printf_filtered ("Thread: %ld\n", (long int) pt->thread);
339 printf_filtered ("Thread: %p\n", pt->thread);
341 if ((long) pt->lwp != 0)
343 if ((long) pt->lwp < 65536)
344 printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
346 printf_filtered ("LWP: %p\n", pt->lwp);
349 /* print the parent gdb task id */
350 num = get_entry_number (EXTRACT_ADDRESS (atcb.parent));
353 printf_filtered ("Parent: %d", num);
354 pt2 = get_entry_vptr (num);
355 READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
357 /* print the name of the task */
358 if (atcb2.image.P_ARRAY != NULL)
360 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
362 bounds[1] = EXTRACT_INT (bounds[1]);
363 read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
364 (char *) &image, bounds[1]);
365 printf_filtered (" (%.*s)\n", bounds[1], image);
368 printf_filtered ("\n");
371 printf_filtered ("No parent\n");
373 /* print the base priority of the task */
374 printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority));
376 /* print the current state of the task */
378 /* check if this task is accepting a rendezvous */
379 if (atcb.call == NULL)
383 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
384 caller = EXTRACT_ADDRESS (call.self);
389 num = get_entry_number (caller);
390 printf_filtered ("Accepting rendezvous with %d", num);
394 pt2 = get_entry_vptr (num);
395 READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
397 /* print the name of the task */
398 if (atcb2.image.P_ARRAY != NULL)
400 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
402 bounds[1] = EXTRACT_INT (bounds[1]);
403 read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
404 (char *) &image, bounds[1]);
405 printf_filtered (" (%.*s)\n", bounds[1], image);
408 printf_filtered ("\n");
411 printf_filtered ("\n");
414 printf_filtered ("State: %s\n", ada_long_task_states[atcb.state]);
419 /* A useful function that shows the alignment of all the fields in the
420 tasks_fields structure
425 struct task_fields tf;
426 void *tf_base = &(tf);
427 void *tf_state = &(tf.state);
428 void *tf_entry_num = &(tf.entry_num);
429 void *tf_parent = &(tf.parent);
430 void *tf_priority = &(tf.priority);
431 void *tf_current_priority = &(tf.current_priority);
432 void *tf_image = &(tf.image);
433 void *tf_call = &(tf.call);
434 void *tf_thread = &(tf.thread);
435 void *tf_lwp = &(tf.lwp);
436 printf_filtered ("\n");
437 printf_filtered ("(tf_base = 0x%x)\n", tf_base);
438 printf_filtered ("task_fields.entry_num at %3d (0x%x)\n",
439 tf_entry_num - tf_base, tf_entry_num);
440 printf_filtered ("task_fields.state at %3d (0x%x)\n",
441 tf_state - tf_base, tf_state);
442 printf_filtered ("task_fields.parent at %3d (0x%x)\n",
443 tf_parent - tf_base, tf_parent);
444 printf_filtered ("task_fields.priority at %3d (0x%x)\n",
445 tf_priority - tf_base, tf_priority);
446 printf_filtered ("task_fields.current_priority at %3d (0x%x)\n",
447 tf_current_priority - tf_base, tf_current_priority);
448 printf_filtered ("task_fields.image at %3d (0x%x)\n",
449 tf_image - tf_base, tf_image);
450 printf_filtered ("task_fields.call at %3d (0x%x)\n",
451 tf_call - tf_base, tf_call);
452 printf_filtered ("task_fields.thread at %3d (0x%x)\n",
453 tf_thread - tf_base, tf_thread);
454 printf_filtered ("task_fields.lwp at %3d (0x%x)\n",
455 tf_lwp - tf_base, tf_lwp);
456 printf_filtered ("\n");
460 /* Print information about currently known tasks */
463 info_tasks (char *arg, int from_tty)
466 int i, task_number, state;
467 void *temp_task, *temp_tasks[MAX_NUMBER_OF_KNOWN_TASKS];
468 struct task_entry *pt;
469 void *self_id, *caller, *thread_id = NULL;
470 struct task_fields atcb;
471 struct entry_call call;
477 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
482 static struct symbol *sym;
483 static struct minimal_symbol *msym;
484 static void *known_tasks_addr = NULL;
486 int init_only = gdbtk_task_initialization;
487 gdbtk_task_initialization = 0;
491 if (PIDGET (inferior_ptid) == 0)
493 printf_filtered ("The program is not being run under gdb. ");
494 printf_filtered ("Use 'run' or 'attach' first.\n");
498 if (ada__tasks_check_symbol_table)
501 #if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
506 msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
508 known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym);
510 #ifndef VXWORKS_TARGET
514 if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
519 ada__tasks_check_symbol_table = 0;
522 if (known_tasks_addr == NULL)
525 #if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
528 thread_id = GET_CURRENT_THREAD ();
530 /* then we get a list of tasks created */
534 READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks);
536 for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
538 temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
540 if (temp_task != NULL)
542 task_number = get_entry_number (temp_task);
543 if (task_number == 0)
544 task_number = add_task_entry (temp_task, i);
548 /* Return without printing anything if this function was called in
549 order to init GDBTK tasking. */
554 /* print the header */
556 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
558 (" ID TID P-ID Pri Stack %% State Name\n");
560 printf_filtered (" ID TID P-ID Pri State Name\n");
563 /* Now that we have a list of task id's, we can print them */
567 temp_task = pt->task_id;
569 /* read the atcb in the inferior */
570 READ_MEMORY ((CORE_ADDR) temp_task, atcb);
572 /* store the thread id for future use */
573 pt->thread = EXTRACT_ADDRESS (atcb.thread);
576 pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0);
578 pt->lwp = EXTRACT_ADDRESS (atcb.lwp);
581 /* print a star if this task is the current one */
583 #if defined (__WIN32__) || defined (SGI) || defined (hpux)
584 printf_filtered (pt->lwp == thread_id ? "*" : " ");
586 printf_filtered (pt->thread == thread_id ? "*" : " ");
589 /* print the gdb task id */
590 printf_filtered ("%3d", pt->task_num);
592 /* print the Ada task id */
593 #ifndef VXWORKS_TARGET
594 printf_filtered (" %9lx", (long) temp_task);
597 printf_filtered (" %#9lx", (unsigned long) pt->thread & 0x3ffffffffff);
599 printf_filtered (" %#9lx", (long) pt->thread);
603 /* print the parent gdb task id */
605 (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
607 /* print the base priority of the task */
608 printf_filtered (" %3d", EXTRACT_INT (atcb.priority));
610 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
611 if (pt->task_num == 1 || atcb.state == Terminated)
613 printf_filtered (" Unknown");
617 read_memory ((CORE_ADDR) atcb.thread, &thr, sizeof (thr));
618 current_thread = atcb.thread;
619 regs.regs[SP_REGNUM] = 0;
620 if (dec_thread_get_registers (®s, NULL) == 0)
622 pt->stack_per = (100 * ((long) thr.__stack_base -
623 regs.regs[SP_REGNUM])) / thr.__stack_size;
624 /* if the thread is terminated but still there, the
625 stack_base/size values are erroneous. Try to patch it */
626 if (pt->stack_per < 0 || pt->stack_per > 100)
630 /* print information about stack space used in the thread */
631 if (thr.__stack_size < 1024 * 1024)
633 size = thr.__stack_size / 1024;
636 else if (thr.__stack_size < 1024 * 1024 * 1024)
638 size = thr.__stack_size / 1024 / 1024;
641 else /* Who knows... */
643 size = thr.__stack_size / 1024 / 1024 / 1024;
646 printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
650 /* print the current state of the task */
652 /* check if this task is accepting a rendezvous */
653 if (atcb.call == NULL)
657 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
658 caller = EXTRACT_ADDRESS (call.self);
662 printf_filtered (" Accepting RV with %-4d",
663 get_entry_number (caller));
667 #if defined (__WIN32__) || defined (SGI) || defined (hpux)
668 if (state == Runnable && (thread_id && pt->lwp == thread_id))
670 if (state == Runnable && (thread_id && pt->thread == thread_id))
672 /* Replace "Runnable" by "Running" if this is the current task */
673 printf_filtered (" %-22s", "Running");
675 printf_filtered (" %-22s", ada_task_states[state]);
678 /* finally, print the name of the task */
679 if (atcb.image.P_ARRAY != NULL)
681 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS),
683 bounds[1] = EXTRACT_INT (bounds[1]);
684 read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
685 (char *) &image, bounds[1]);
686 printf_filtered (" %.*s\n", bounds[1], image);
689 printf_filtered (" <no name>\n");
695 /* Task list initialization for GDB-Tk. We basically use info_tasks()
696 to initialize our variables, but abort that function before we
697 actually print anything. */
700 gdbtk_tcl_tasks_initialize (void)
702 gdbtk_task_initialization = 1;
703 info_tasks ("", gdb_stdout);
705 return (task_list != NULL);
709 info_tasks_command (char *arg, int from_tty)
711 if (arg == NULL || *arg == '\000')
712 info_tasks (arg, from_tty);
714 info_task (arg, from_tty);
717 /* Switch from one thread to another. */
720 switch_to_thread (ptid_t ptid)
722 if (ptid_equal (ptid, inferior_ptid))
725 inferior_ptid = ptid;
726 flush_cached_frames ();
727 registers_changed ();
728 stop_pc = read_pc ();
729 select_frame (get_current_frame ());
732 /* Switch to a specified task. */
735 task_switch (void *tid, void *lwpid)
741 flush_cached_frames ();
743 if (current_task != current_task_id)
745 res = THREAD_FETCH_REGISTERS ();
749 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
750 supply_gregset (&gregset_saved);
751 supply_fpregset (&fpregset_saved);
756 stop_pc = read_pc ();
757 select_frame (get_current_frame ());
765 task_command (char *tidstr, int from_tty)
768 struct task_entry *e;
771 error ("Please specify a task ID. Use the \"info tasks\" command to\n"
772 "see the IDs of currently known tasks.");
775 e = get_entry_vptr (num);
778 error ("Task ID %d not known. Use the \"info tasks\" command to\n"
779 "see the IDs of currently known tasks.", num);
781 if (current_task_id == -1)
783 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
784 fill_gregset (&gregset_saved, -1);
785 fill_fpregset (&fpregset_saved, -1);
787 current_task_id = get_current_task ();
791 current_task_index = e->known_tasks_index;
792 current_thread = e->thread;
793 current_lwp = e->lwp;
794 if (task_switch (e->thread, e->lwp) == 0)
796 /* FIXME: find_printable_frame should be defined in frame.h, and
797 implemented in ada-lang.c */
798 /* find_printable_frame (deprecated_selected_frame, frame_relative_level (deprecated_selected_frame)); */
799 printf_filtered ("[Switching to task %d]\n", num);
800 print_stack_frame (deprecated_selected_frame,
801 frame_relative_level (deprecated_selected_frame), 1);
804 printf_filtered ("Unable to switch to task %d\n", num);
808 _initialize_tasks (void)
810 static struct cmd_list_element *task_cmd_list = NULL;
811 extern struct cmd_list_element *cmdlist;
813 add_info ("tasks", info_tasks_command,
814 "Without argument: list all known Ada tasks, with status information.\n"
815 "info tasks n: print detailed information of task n.\n");
817 add_prefix_cmd ("task", class_run, task_command,
818 "Use this command to switch between tasks.\n\
819 The new task ID must be currently known.", &task_cmd_list, "task ", 1, &cmdlist);