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