2002-08-14 Michael Snyder <msnyder@redhat.com>
[deliverable/binutils-gdb.git] / gdb / ada-tasks.c
CommitLineData
14f9c5c9
AS
1/* file ada-tasks.c: Ada tasking control for GDB
2 Copyright 1997 Free Software Foundation, Inc.
3 Contributed by Ada Core Technologies, Inc
4.
5 This file is part of GDB.
6
7 [$Id$]
8 Authors: Roch-Alexandre Nomine Beguin, Arnaud Charlet <charlet@gnat.com>
9
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.
14
15*/
16
d2e4a39e
AS
17#include <ctype.h>
18#include "defs.h"
19#include "command.h"
14f9c5c9
AS
20#include "value.h"
21#include "language.h"
22#include "inferior.h"
23#include "symtab.h"
24#include "target.h"
25#include "gdbcore.h"
26
27#if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks))
28#include <sys/procfs.h>
29#endif
30
31#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
32#include "gregset.h"
d2e4a39e 33#endif
14f9c5c9
AS
34
35#include "ada-lang.h"
36
37/* FIXME: move all this conditional compilation in description
38 files or in configure.in */
39
40#if defined (VXWORKS_TARGET)
41#define THREAD_TO_PID(tid,lwpid) (tid)
42
43#elif defined (linux)
44#define THREAD_TO_PID(tid,lwpid) (0)
45
46#elif (defined (sun) && defined (__SVR4))
47#define THREAD_TO_PID thread_to_pid
48
49#elif defined (sgi) || defined (__WIN32__) || defined (hpux)
50#define THREAD_TO_PID(tid,lwpid) ((int)lwpid)
51
52#else
53#define THREAD_TO_PID(tid,lwpid) (0)
54#endif
55
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
59extern int dec_thread_get_registers (gdb_gregset_t *, gdb_fpregset_t *);
60#endif
61
62#if defined (_AIX)
63#define THREAD_FETCH_REGISTERS aix_thread_fetch_registers
64#define GET_CURRENT_THREAD aix_thread_get_current_thread
65#endif
66
67#if defined(VXWORKS_TARGET)
68#define GET_CURRENT_THREAD() ((void*)inferior_pid)
69#define THREAD_FETCH_REGISTERS() (-1)
70
71#elif defined (sun) && defined (__SVR4)
72#define GET_CURRENT_THREAD solaris_thread_get_current_thread
73#define THREAD_FETCH_REGISTERS() (-1)
d2e4a39e 74extern void *GET_CURRENT_THREAD ();
14f9c5c9
AS
75
76#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
d2e4a39e 77extern void *GET_CURRENT_THREAD ();
14f9c5c9
AS
78
79#elif defined (__WIN32__) || defined (hpux)
80#define GET_CURRENT_THREAD() (inferior_pid)
81#define THREAD_FETCH_REGISTERS() (-1)
82
83#else
84#define GET_CURRENT_THREAD() (NULL)
85#define THREAD_FETCH_REGISTERS() (-1)
86#endif
87
88#define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
89
90#define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var))
91/* external declarations */
92
d2e4a39e 93extern struct value *find_function_in_inferior (char *);
14f9c5c9
AS
94
95/* Global visible variables */
96
97struct task_entry *task_list = NULL;
98int ada__tasks_check_symbol_table = 1;
99void *pthread_kern_addr = NULL;
100
101#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
102gdb_gregset_t gregset_saved;
103gdb_fpregset_t fpregset_saved;
104#endif
105
106/* The maximum number of tasks known to the Ada runtime */
107const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
108
109/* the current task */
110int current_task = -1, current_task_id = -1, current_task_index;
111void *current_thread, *current_lwp;
112
d2e4a39e 113char *ada_task_states[] = {
14f9c5c9
AS
114 "Unactivated",
115 "Runnable",
116 "Terminated",
117 "Child Activation Wait",
118 "Accept Statement",
119 "Waiting on entry call",
120 "Async Select Wait",
121 "Delay Sleep",
122 "Child Termination Wait",
123 "Wait Child in Term Alt",
124 "",
125 "",
126 "",
127 "",
128 "Asynchronous Hold"
129};
130
131/* Global internal types */
132
d2e4a39e 133static char *ada_long_task_states[] = {
14f9c5c9
AS
134 "Unactivated",
135 "Runnable",
136 "Terminated",
137 "Waiting for child activation",
138 "Blocked in accept statement",
139 "Waiting on entry call",
140 "Asynchronous Selective Wait",
141 "Delay Sleep",
142 "Waiting for children termination",
143 "Waiting for children in terminate alternative",
144 "",
145 "",
146 "",
147 "",
148 "Asynchronous Hold"
149};
150
151/* Global internal variables */
152
153static int highest_task_num = 0;
d2e4a39e 154int thread_support = 0; /* 1 if the thread library in use is supported */
14f9c5c9
AS
155static int gdbtk_task_initialization = 0;
156
d2e4a39e 157static int
80ae6ee2 158add_task_entry (void *p_task_id, int index)
14f9c5c9
AS
159{
160 struct task_entry *new_task_entry = NULL;
161 struct task_entry *pt;
162
163 highest_task_num++;
aacb1f0a 164 new_task_entry = xmalloc (sizeof (struct task_entry));
14f9c5c9
AS
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;
169 pt = task_list;
170 if (pt)
171 {
172 while (pt->next_task)
173 pt = pt->next_task;
174 pt->next_task = new_task_entry;
175 pt->stack_per = 0;
176 }
d2e4a39e
AS
177 else
178 task_list = new_task_entry;
14f9c5c9
AS
179 return new_task_entry->task_num;
180}
181
d2e4a39e 182int
80ae6ee2 183get_entry_number (void *p_task_id)
14f9c5c9
AS
184{
185 struct task_entry *pt;
186
187 pt = task_list;
188 while (pt != NULL)
189 {
190 if (pt->task_id == p_task_id)
191 return pt->task_num;
192 pt = pt->next_task;
193 }
194 return 0;
195}
196
80ae6ee2
AS
197static struct task_entry *
198get_thread_entry_vptr (void *thread)
14f9c5c9
AS
199{
200 struct task_entry *pt;
201
202 pt = task_list;
203 while (pt != NULL)
204 {
205 if (pt->thread == thread)
d2e4a39e 206 return pt;
14f9c5c9
AS
207 pt = pt->next_task;
208 }
209 return 0;
210}
211
80ae6ee2
AS
212static struct task_entry *
213get_entry_vptr (int p_task_num)
14f9c5c9
AS
214{
215 struct task_entry *pt;
216
217 pt = task_list;
218 while (pt)
219 {
220 if (pt->task_num == p_task_num)
221 return pt;
222 pt = pt->next_task;
223 }
224 return NULL;
225}
226
80ae6ee2
AS
227void
228init_task_list (void)
14f9c5c9
AS
229{
230 struct task_entry *pt, *old_pt;
231
232 pt = task_list;
233 while (pt)
234 {
235 old_pt = pt;
236 pt = pt->next_task;
aacb1f0a 237 xfree (old_pt);
14f9c5c9
AS
238 };
239 task_list = NULL;
240 highest_task_num = 0;
241}
242
80ae6ee2
AS
243int
244valid_task_id (int task)
14f9c5c9
AS
245{
246 return get_entry_vptr (task) != NULL;
247}
248
80ae6ee2
AS
249void *
250get_self_id (void)
14f9c5c9 251{
d2e4a39e 252 struct value *val;
14f9c5c9
AS
253 void *self_id;
254 int result;
255 struct task_entry *ent;
256 extern int do_not_insert_breakpoints;
257
258#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
259 if (thread_support)
260#endif
261 {
262 ent = get_thread_entry_vptr (GET_CURRENT_THREAD ());
263 return ent ? ent->task_id : 0;
264 }
265
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
268 task */
269 return NULL;
270}
271
d2e4a39e
AS
272int
273get_current_task ()
14f9c5c9
AS
274{
275 int result;
d2e4a39e 276
14f9c5c9
AS
277 /* FIXME: language_ada should be defined in defs.h */
278 /* if (current_language->la_language != language_ada) return -1; */
279
280 result = get_entry_number (get_self_id ());
281
282 /* return -1 if not found */
283 return result == 0 ? -1 : result;
284}
285
286/* Print detailed information about specified task */
287
288static void
80ae6ee2 289info_task (char *arg, int from_tty)
14f9c5c9
AS
290{
291 void *temp_task;
292 struct task_entry *pt, *pt2;
293 void *self_id, *caller;
294 struct task_fields atcb, atcb2;
295 struct entry_call call;
d2e4a39e
AS
296 int bounds[2];
297 char image[256];
14f9c5c9
AS
298 int num;
299
300 /* FIXME: language_ada should be defined in defs.h */
301 /* if (current_language->la_language != language_ada)
d2e4a39e
AS
302 {
303 printf_filtered ("The current language does not support tasks.\n");
304 return;
305 }
306 */
14f9c5c9
AS
307 pt = get_entry_vptr (atoi (arg));
308 if (pt == NULL)
309 {
d2e4a39e
AS
310 printf_filtered ("Task %s not found.\n", arg);
311 return;
14f9c5c9
AS
312 }
313
314 temp_task = pt->task_id;
315
316 /* read the atcb in the inferior */
317 READ_MEMORY ((CORE_ADDR) temp_task, atcb);
318
319 /* print the Ada task id */
320 printf_filtered ("Ada Task: %p\n", temp_task);
321
322 /* print the name of the task */
d2e4a39e
AS
323 if (atcb.image.P_ARRAY != NULL)
324 {
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);
330 }
331 else
332 printf_filtered ("<no name>\n");
14f9c5c9
AS
333
334 /* print the thread id */
335
336 if ((long) pt->thread < 65536)
337 printf_filtered ("Thread: %ld\n", (long int) pt->thread);
338 else
339 printf_filtered ("Thread: %p\n", pt->thread);
340
341 if ((long) pt->lwp != 0)
342 {
343 if ((long) pt->lwp < 65536)
d2e4a39e 344 printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
14f9c5c9 345 else
d2e4a39e 346 printf_filtered ("LWP: %p\n", pt->lwp);
14f9c5c9
AS
347 }
348
349 /* print the parent gdb task id */
350 num = get_entry_number (EXTRACT_ADDRESS (atcb.parent));
351 if (num != 0)
352 {
353 printf_filtered ("Parent: %d", num);
354 pt2 = get_entry_vptr (num);
355 READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
356
357 /* print the name of the task */
d2e4a39e
AS
358 if (atcb2.image.P_ARRAY != NULL)
359 {
360 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
361 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);
366 }
14f9c5c9 367 else
d2e4a39e 368 printf_filtered ("\n");
14f9c5c9
AS
369 }
370 else
371 printf_filtered ("No parent\n");
372
373 /* print the base priority of the task */
374 printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority));
375
376 /* print the current state of the task */
377
378 /* check if this task is accepting a rendezvous */
379 if (atcb.call == NULL)
380 caller = NULL;
d2e4a39e
AS
381 else
382 {
383 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
384 caller = EXTRACT_ADDRESS (call.self);
385 }
386
14f9c5c9
AS
387 if (caller != NULL)
388 {
389 num = get_entry_number (caller);
390 printf_filtered ("Accepting rendezvous with %d", num);
391
392 if (num != 0)
393 {
394 pt2 = get_entry_vptr (num);
395 READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
396
397 /* print the name of the task */
d2e4a39e
AS
398 if (atcb2.image.P_ARRAY != NULL)
399 {
400 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
401 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);
406 }
14f9c5c9
AS
407 else
408 printf_filtered ("\n");
409 }
410 else
411 printf_filtered ("\n");
412 }
413 else
d2e4a39e 414 printf_filtered ("State: %s\n", ada_long_task_states[atcb.state]);
14f9c5c9
AS
415}
416
417#if 0
418
419/* A useful function that shows the alignment of all the fields in the
420 tasks_fields structure
421 */
422
80ae6ee2 423print_align (void)
14f9c5c9
AS
424{
425 struct task_fields tf;
d2e4a39e
AS
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);
14f9c5c9 431 void *tf_current_priority = &(tf.current_priority);
d2e4a39e
AS
432 void *tf_image = &(tf.image);
433 void *tf_call = &(tf.call);
434 void *tf_thread = &(tf.thread);
435 void *tf_lwp = &(tf.lwp);
14f9c5c9
AS
436 printf_filtered ("\n");
437 printf_filtered ("(tf_base = 0x%x)\n", tf_base);
d2e4a39e
AS
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");
14f9c5c9
AS
457}
458#endif
459
460/* Print information about currently known tasks */
461
462static void
80ae6ee2 463info_tasks (char *arg, int from_tty)
14f9c5c9 464{
d2e4a39e 465 struct value *val;
14f9c5c9 466 int i, task_number, state;
d2e4a39e 467 void *temp_task, *temp_tasks[MAX_NUMBER_OF_KNOWN_TASKS];
14f9c5c9 468 struct task_entry *pt;
d2e4a39e 469 void *self_id, *caller, *thread_id = NULL;
14f9c5c9
AS
470 struct task_fields atcb;
471 struct entry_call call;
d2e4a39e
AS
472 int bounds[2];
473 char image[256];
14f9c5c9
AS
474 int size;
475 char car;
476
477#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
478 pthreadTeb_t thr;
479 gdb_gregset_t regs;
480#endif
481
482 static struct symbol *sym;
483 static struct minimal_symbol *msym;
484 static void *known_tasks_addr = NULL;
485
486 int init_only = gdbtk_task_initialization;
487 gdbtk_task_initialization = 0;
488
489 task_number = 0;
490
d2e4a39e 491 if (PIDGET (inferior_ptid) == 0)
14f9c5c9
AS
492 {
493 printf_filtered ("The program is not being run under gdb. ");
494 printf_filtered ("Use 'run' or 'attach' first.\n");
495 return;
496 }
497
498 if (ada__tasks_check_symbol_table)
499 {
500 thread_support = 0;
501#if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
502 defined (_AIX)
503 thread_support = 1;
504#endif
505
506 msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
507 if (msym != NULL)
508 known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym);
509 else
510#ifndef VXWORKS_TARGET
d2e4a39e 511 return;
14f9c5c9
AS
512#else
513 {
514 if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
515 return;
516 }
517#endif
518
519 ada__tasks_check_symbol_table = 0;
520 }
521
522 if (known_tasks_addr == NULL)
523 return;
524
525#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
526 if (thread_support)
527#endif
528 thread_id = GET_CURRENT_THREAD ();
529
530 /* then we get a list of tasks created */
531
532 init_task_list ();
533
534 READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks);
535
d2e4a39e 536 for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
14f9c5c9
AS
537 {
538 temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
539
540 if (temp_task != NULL)
d2e4a39e
AS
541 {
542 task_number = get_entry_number (temp_task);
543 if (task_number == 0)
14f9c5c9 544 task_number = add_task_entry (temp_task, i);
d2e4a39e
AS
545 }
546 }
14f9c5c9
AS
547
548 /* Return without printing anything if this function was called in
549 order to init GDBTK tasking. */
550
d2e4a39e
AS
551 if (init_only)
552 return;
14f9c5c9
AS
553
554 /* print the header */
555
556#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
557 printf_filtered
d2e4a39e 558 (" ID TID P-ID Pri Stack %% State Name\n");
14f9c5c9
AS
559#else
560 printf_filtered (" ID TID P-ID Pri State Name\n");
561#endif
562
563 /* Now that we have a list of task id's, we can print them */
564 pt = task_list;
565 while (pt)
566 {
567 temp_task = pt->task_id;
568
569 /* read the atcb in the inferior */
570 READ_MEMORY ((CORE_ADDR) temp_task, atcb);
571
572 /* store the thread id for future use */
573 pt->thread = EXTRACT_ADDRESS (atcb.thread);
574
575#if defined (linux)
576 pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0);
577#else
578 pt->lwp = EXTRACT_ADDRESS (atcb.lwp);
579#endif
580
581 /* print a star if this task is the current one */
582 if (thread_id)
583#if defined (__WIN32__) || defined (SGI) || defined (hpux)
584 printf_filtered (pt->lwp == thread_id ? "*" : " ");
585#else
586 printf_filtered (pt->thread == thread_id ? "*" : " ");
587#endif
588
589 /* print the gdb task id */
590 printf_filtered ("%3d", pt->task_num);
591
592 /* print the Ada task id */
593#ifndef VXWORKS_TARGET
594 printf_filtered (" %9lx", (long) temp_task);
595#else
596#ifdef TARGET_64
d2e4a39e 597 printf_filtered (" %#9lx", (unsigned long) pt->thread & 0x3ffffffffff);
14f9c5c9 598#else
d2e4a39e 599 printf_filtered (" %#9lx", (long) pt->thread);
14f9c5c9
AS
600#endif
601#endif
602
603 /* print the parent gdb task id */
604 printf_filtered
d2e4a39e 605 (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
14f9c5c9
AS
606
607 /* print the base priority of the task */
608 printf_filtered (" %3d", EXTRACT_INT (atcb.priority));
609
610#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
611 if (pt->task_num == 1 || atcb.state == Terminated)
612 {
d2e4a39e 613 printf_filtered (" Unknown");
14f9c5c9
AS
614 goto next;
615 }
616
d2e4a39e 617 read_memory ((CORE_ADDR) atcb.thread, &thr, sizeof (thr));
14f9c5c9 618 current_thread = atcb.thread;
d2e4a39e
AS
619 regs.regs[SP_REGNUM] = 0;
620 if (dec_thread_get_registers (&regs, NULL) == 0)
621 {
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)
627 pt->stack_per = 0;
628 }
14f9c5c9
AS
629
630 /* print information about stack space used in the thread */
d2e4a39e 631 if (thr.__stack_size < 1024 * 1024)
14f9c5c9
AS
632 {
633 size = thr.__stack_size / 1024;
634 car = 'K';
635 }
d2e4a39e 636 else if (thr.__stack_size < 1024 * 1024 * 1024)
14f9c5c9
AS
637 {
638 size = thr.__stack_size / 1024 / 1024;
639 car = 'M';
640 }
d2e4a39e 641 else /* Who knows... */
14f9c5c9
AS
642 {
643 size = thr.__stack_size / 1024 / 1024 / 1024;
644 car = 'G';
645 }
646 printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
d2e4a39e 647 next:
14f9c5c9
AS
648#endif
649
650 /* print the current state of the task */
651
652 /* check if this task is accepting a rendezvous */
653 if (atcb.call == NULL)
654 caller = NULL;
d2e4a39e
AS
655 else
656 {
657 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
658 caller = EXTRACT_ADDRESS (call.self);
659 }
660
14f9c5c9 661 if (caller != NULL)
d2e4a39e
AS
662 printf_filtered (" Accepting RV with %-4d",
663 get_entry_number (caller));
14f9c5c9
AS
664 else
665 {
666 state = atcb.state;
667#if defined (__WIN32__) || defined (SGI) || defined (hpux)
668 if (state == Runnable && (thread_id && pt->lwp == thread_id))
669#else
670 if (state == Runnable && (thread_id && pt->thread == thread_id))
671#endif
672 /* Replace "Runnable" by "Running" if this is the current task */
673 printf_filtered (" %-22s", "Running");
674 else
d2e4a39e 675 printf_filtered (" %-22s", ada_task_states[state]);
14f9c5c9
AS
676 }
677
678 /* finally, print the name of the task */
d2e4a39e
AS
679 if (atcb.image.P_ARRAY != NULL)
680 {
681 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS),
682 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);
687 }
688 else
689 printf_filtered (" <no name>\n");
14f9c5c9
AS
690
691 pt = pt->next_task;
692 }
693}
694
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. */
698
699int
80ae6ee2 700gdbtk_tcl_tasks_initialize (void)
14f9c5c9
AS
701{
702 gdbtk_task_initialization = 1;
703 info_tasks ("", gdb_stdout);
704
705 return (task_list != NULL);
706}
707
708static void
80ae6ee2 709info_tasks_command (char *arg, int from_tty)
14f9c5c9 710{
d2e4a39e
AS
711 if (arg == NULL || *arg == '\000')
712 info_tasks (arg, from_tty);
713 else
714 info_task (arg, from_tty);
14f9c5c9
AS
715}
716
717/* Switch from one thread to another. */
718
719static void
720switch_to_thread (ptid_t ptid)
14f9c5c9
AS
721{
722 if (ptid_equal (ptid, inferior_ptid))
723 return;
724
725 inferior_ptid = ptid;
726 flush_cached_frames ();
727 registers_changed ();
728 stop_pc = read_pc ();
729 select_frame (get_current_frame ());
730}
731
732/* Switch to a specified task. */
733
80ae6ee2
AS
734static int
735task_switch (void *tid, void *lwpid)
14f9c5c9
AS
736{
737 int res = 0, pid;
738
739 if (thread_support)
740 {
741 flush_cached_frames ();
742
743 if (current_task != current_task_id)
744 {
745 res = THREAD_FETCH_REGISTERS ();
746 }
747 else
748 {
749#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
750 supply_gregset (&gregset_saved);
751 supply_fpregset (&fpregset_saved);
752#endif
753 }
754
d2e4a39e
AS
755 if (res == 0)
756 stop_pc = read_pc ();
14f9c5c9
AS
757 select_frame (get_current_frame ());
758 return res;
759 }
760
761 return -1;
762}
763
80ae6ee2
AS
764static void
765task_command (char *tidstr, int from_tty)
14f9c5c9
AS
766{
767 int num;
768 struct task_entry *e;
769
770 if (!tidstr)
771 error ("Please specify a task ID. Use the \"info tasks\" command to\n"
d2e4a39e 772 "see the IDs of currently known tasks.");
14f9c5c9
AS
773
774 num = atoi (tidstr);
775 e = get_entry_vptr (num);
776
777 if (e == NULL)
778 error ("Task ID %d not known. Use the \"info tasks\" command to\n"
d2e4a39e 779 "see the IDs of currently known tasks.", num);
14f9c5c9
AS
780
781 if (current_task_id == -1)
782 {
783#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
784 fill_gregset (&gregset_saved, -1);
785 fill_fpregset (&fpregset_saved, -1);
786#endif
787 current_task_id = get_current_task ();
788 }
789
790 current_task = num;
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)
795 {
796 /* FIXME: find_printable_frame should be defined in frame.h, and
d2e4a39e
AS
797 implemented in ada-lang.c */
798 /* find_printable_frame (selected_frame, frame_relative_level (selected_frame)); */
14f9c5c9 799 printf_filtered ("[Switching to task %d]\n", num);
d2e4a39e
AS
800 print_stack_frame (selected_frame,
801 frame_relative_level (selected_frame), 1);
14f9c5c9
AS
802 }
803 else
804 printf_filtered ("Unable to switch to task %d\n", num);
805}
806
807void
80ae6ee2 808_initialize_tasks (void)
14f9c5c9
AS
809{
810 static struct cmd_list_element *task_cmd_list = NULL;
811 extern struct cmd_list_element *cmdlist;
812
d2e4a39e
AS
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");
14f9c5c9
AS
816
817 add_prefix_cmd ("task", class_run, task_command,
d2e4a39e
AS
818 "Use this command to switch between tasks.\n\
819 The new task ID must be currently known.", &task_cmd_list, "task ", 1, &cmdlist);
14f9c5c9 820}
This page took 0.073113 seconds and 4 git commands to generate.