2002-08-16 Andrew Cagney <ac131313@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
17#include <ctype.h>
18#include "defs.h"
19#include "command.h"
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"
33#endif
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)
74extern void *GET_CURRENT_THREAD();
75
76#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
77extern void *GET_CURRENT_THREAD();
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
93extern struct value* find_function_in_inferior (char *);
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
113char *ada_task_states[] =
114{
115 "Unactivated",
116 "Runnable",
117 "Terminated",
118 "Child Activation Wait",
119 "Accept Statement",
120 "Waiting on entry call",
121 "Async Select Wait",
122 "Delay Sleep",
123 "Child Termination Wait",
124 "Wait Child in Term Alt",
125 "",
126 "",
127 "",
128 "",
129 "Asynchronous Hold"
130};
131
132/* Global internal types */
133
134static char *ada_long_task_states[] =
135{
136 "Unactivated",
137 "Runnable",
138 "Terminated",
139 "Waiting for child activation",
140 "Blocked in accept statement",
141 "Waiting on entry call",
142 "Asynchronous Selective Wait",
143 "Delay Sleep",
144 "Waiting for children termination",
145 "Waiting for children in terminate alternative",
146 "",
147 "",
148 "",
149 "",
150 "Asynchronous Hold"
151};
152
153/* Global internal variables */
154
155static int highest_task_num = 0;
156int thread_support = 0; /* 1 if the thread library in use is supported */
157static int gdbtk_task_initialization = 0;
158
80ae6ee2
AS
159static int
160add_task_entry (void *p_task_id, int index)
14f9c5c9
AS
161{
162 struct task_entry *new_task_entry = NULL;
163 struct task_entry *pt;
164
165 highest_task_num++;
aacb1f0a 166 new_task_entry = xmalloc (sizeof (struct task_entry));
14f9c5c9
AS
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;
171 pt = task_list;
172 if (pt)
173 {
174 while (pt->next_task)
175 pt = pt->next_task;
176 pt->next_task = new_task_entry;
177 pt->stack_per = 0;
178 }
179 else task_list = new_task_entry;
180 return new_task_entry->task_num;
181}
182
183int
80ae6ee2 184get_entry_number (void *p_task_id)
14f9c5c9
AS
185{
186 struct task_entry *pt;
187
188 pt = task_list;
189 while (pt != NULL)
190 {
191 if (pt->task_id == p_task_id)
192 return pt->task_num;
193 pt = pt->next_task;
194 }
195 return 0;
196}
197
80ae6ee2
AS
198static struct task_entry *
199get_thread_entry_vptr (void *thread)
14f9c5c9
AS
200{
201 struct task_entry *pt;
202
203 pt = task_list;
204 while (pt != NULL)
205 {
206 if (pt->thread == thread)
207 return pt;
208 pt = pt->next_task;
209 }
210 return 0;
211}
212
80ae6ee2
AS
213static struct task_entry *
214get_entry_vptr (int p_task_num)
14f9c5c9
AS
215{
216 struct task_entry *pt;
217
218 pt = task_list;
219 while (pt)
220 {
221 if (pt->task_num == p_task_num)
222 return pt;
223 pt = pt->next_task;
224 }
225 return NULL;
226}
227
80ae6ee2
AS
228void
229init_task_list (void)
14f9c5c9
AS
230{
231 struct task_entry *pt, *old_pt;
232
233 pt = task_list;
234 while (pt)
235 {
236 old_pt = pt;
237 pt = pt->next_task;
aacb1f0a 238 xfree (old_pt);
14f9c5c9
AS
239 };
240 task_list = NULL;
241 highest_task_num = 0;
242}
243
80ae6ee2
AS
244int
245valid_task_id (int task)
14f9c5c9
AS
246{
247 return get_entry_vptr (task) != NULL;
248}
249
80ae6ee2
AS
250void *
251get_self_id (void)
14f9c5c9
AS
252{
253 struct value* val;
254 void *self_id;
255 int result;
256 struct task_entry *ent;
257 extern int do_not_insert_breakpoints;
258
259#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
260 if (thread_support)
261#endif
262 {
263 ent = get_thread_entry_vptr (GET_CURRENT_THREAD ());
264 return ent ? ent->task_id : 0;
265 }
266
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
269 task */
270 return NULL;
271}
272
273int get_current_task ()
274{
275 int result;
276
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;
296 int bounds [2];
297 char image [256];
298 int num;
299
300 /* FIXME: language_ada should be defined in defs.h */
301 /* if (current_language->la_language != language_ada)
302 {
303 printf_filtered ("The current language does not support tasks.\n");
304 return;
305 }
306 */
307 pt = get_entry_vptr (atoi (arg));
308 if (pt == NULL)
309 {
310 printf_filtered ("Task %s not found.\n", arg);
311 return;
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 */
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);
329 }
330 else printf_filtered ("<no name>\n");
331
332 /* print the thread id */
333
334 if ((long) pt->thread < 65536)
335 printf_filtered ("Thread: %ld\n", (long int) pt->thread);
336 else
337 printf_filtered ("Thread: %p\n", pt->thread);
338
339 if ((long) pt->lwp != 0)
340 {
341 if ((long) pt->lwp < 65536)
342 printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
343 else
344 printf_filtered ("LWP: %p\n", pt->lwp);
345 }
346
347 /* print the parent gdb task id */
348 num = get_entry_number (EXTRACT_ADDRESS (atcb.parent));
349 if (num != 0)
350 {
351 printf_filtered ("Parent: %d", num);
352 pt2 = get_entry_vptr (num);
353 READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
354
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),
358 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);
363 }
364 else
365 printf_filtered ("\n");
366 }
367 else
368 printf_filtered ("No parent\n");
369
370 /* print the base priority of the task */
371 printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority));
372
373 /* print the current state of the task */
374
375 /* check if this task is accepting a rendezvous */
376 if (atcb.call == NULL)
377 caller = NULL;
378 else {
379 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
380 caller = EXTRACT_ADDRESS (call.self);
381 }
382
383 if (caller != NULL)
384 {
385 num = get_entry_number (caller);
386 printf_filtered ("Accepting rendezvous with %d", num);
387
388 if (num != 0)
389 {
390 pt2 = get_entry_vptr (num);
391 READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
392
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),
396 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);
401 }
402 else
403 printf_filtered ("\n");
404 }
405 else
406 printf_filtered ("\n");
407 }
408 else
409 printf_filtered ("State: %s\n", ada_long_task_states [atcb.state]);
410}
411
412#if 0
413
414/* A useful function that shows the alignment of all the fields in the
415 tasks_fields structure
416 */
417
80ae6ee2 418print_align (void)
14f9c5c9
AS
419{
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");
443}
444#endif
445
446/* Print information about currently known tasks */
447
448static void
80ae6ee2 449info_tasks (char *arg, int from_tty)
14f9c5c9
AS
450{
451 struct value* val;
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;
458 int bounds [2];
459 char image [256];
460 int size;
461 char car;
462
463#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
464 pthreadTeb_t thr;
465 gdb_gregset_t regs;
466#endif
467
468 static struct symbol *sym;
469 static struct minimal_symbol *msym;
470 static void *known_tasks_addr = NULL;
471
472 int init_only = gdbtk_task_initialization;
473 gdbtk_task_initialization = 0;
474
475 task_number = 0;
476
477 if (PIDGET(inferior_ptid) == 0)
478 {
479 printf_filtered ("The program is not being run under gdb. ");
480 printf_filtered ("Use 'run' or 'attach' first.\n");
481 return;
482 }
483
484 if (ada__tasks_check_symbol_table)
485 {
486 thread_support = 0;
487#if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
488 defined (_AIX)
489 thread_support = 1;
490#endif
491
492 msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
493 if (msym != NULL)
494 known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym);
495 else
496#ifndef VXWORKS_TARGET
497 return;
498#else
499 {
500 if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
501 return;
502 }
503#endif
504
505 ada__tasks_check_symbol_table = 0;
506 }
507
508 if (known_tasks_addr == NULL)
509 return;
510
511#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
512 if (thread_support)
513#endif
514 thread_id = GET_CURRENT_THREAD ();
515
516 /* then we get a list of tasks created */
517
518 init_task_list ();
519
520 READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks);
521
522 for (i=0; i<MAX_NUMBER_OF_KNOWN_TASKS; i++)
523 {
524 temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
525
526 if (temp_task != NULL)
527 {
528 task_number = get_entry_number (temp_task);
529 if (task_number == 0)
530 task_number = add_task_entry (temp_task, i);
531 }
532 }
533
534 /* Return without printing anything if this function was called in
535 order to init GDBTK tasking. */
536
537 if (init_only) return;
538
539 /* print the header */
540
541#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
542 printf_filtered
543 (" ID TID P-ID Pri Stack %% State Name\n");
544#else
545 printf_filtered (" ID TID P-ID Pri State Name\n");
546#endif
547
548 /* Now that we have a list of task id's, we can print them */
549 pt = task_list;
550 while (pt)
551 {
552 temp_task = pt->task_id;
553
554 /* read the atcb in the inferior */
555 READ_MEMORY ((CORE_ADDR) temp_task, atcb);
556
557 /* store the thread id for future use */
558 pt->thread = EXTRACT_ADDRESS (atcb.thread);
559
560#if defined (linux)
561 pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0);
562#else
563 pt->lwp = EXTRACT_ADDRESS (atcb.lwp);
564#endif
565
566 /* print a star if this task is the current one */
567 if (thread_id)
568#if defined (__WIN32__) || defined (SGI) || defined (hpux)
569 printf_filtered (pt->lwp == thread_id ? "*" : " ");
570#else
571 printf_filtered (pt->thread == thread_id ? "*" : " ");
572#endif
573
574 /* print the gdb task id */
575 printf_filtered ("%3d", pt->task_num);
576
577 /* print the Ada task id */
578#ifndef VXWORKS_TARGET
579 printf_filtered (" %9lx", (long) temp_task);
580#else
581#ifdef TARGET_64
582 printf_filtered (" %#9lx", (unsigned long)pt->thread & 0x3ffffffffff);
583#else
584 printf_filtered (" %#9lx", (long)pt->thread);
585#endif
586#endif
587
588 /* print the parent gdb task id */
589 printf_filtered
590 (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
591
592 /* print the base priority of the task */
593 printf_filtered (" %3d", EXTRACT_INT (atcb.priority));
594
595#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
596 if (pt->task_num == 1 || atcb.state == Terminated)
597 {
598 printf_filtered (" Unknown");
599 goto next;
600 }
601
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 (&regs, 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;
611 }
612
613 /* print information about stack space used in the thread */
614 if (thr.__stack_size < 1024*1024)
615 {
616 size = thr.__stack_size / 1024;
617 car = 'K';
618 }
619 else if (thr.__stack_size < 1024*1024*1024)
620 {
621 size = thr.__stack_size / 1024 / 1024;
622 car = 'M';
623 }
624 else /* Who knows... */
625 {
626 size = thr.__stack_size / 1024 / 1024 / 1024;
627 car = 'G';
628 }
629 printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
630next:
631#endif
632
633 /* print the current state of the task */
634
635 /* check if this task is accepting a rendezvous */
636 if (atcb.call == NULL)
637 caller = NULL;
638 else {
639 READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
640 caller = EXTRACT_ADDRESS (call.self);
641 }
642
643 if (caller != NULL)
644 printf_filtered (" Accepting RV with %-4d", get_entry_number (caller));
645 else
646 {
647 state = atcb.state;
648#if defined (__WIN32__) || defined (SGI) || defined (hpux)
649 if (state == Runnable && (thread_id && pt->lwp == thread_id))
650#else
651 if (state == Runnable && (thread_id && pt->thread == thread_id))
652#endif
653 /* Replace "Runnable" by "Running" if this is the current task */
654 printf_filtered (" %-22s", "Running");
655 else
656 printf_filtered (" %-22s", ada_task_states [state]);
657 }
658
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);
666 }
667 else printf_filtered (" <no name>\n");
668
669 pt = pt->next_task;
670 }
671}
672
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. */
676
677int
80ae6ee2 678gdbtk_tcl_tasks_initialize (void)
14f9c5c9
AS
679{
680 gdbtk_task_initialization = 1;
681 info_tasks ("", gdb_stdout);
682
683 return (task_list != NULL);
684}
685
686static void
80ae6ee2 687info_tasks_command (char *arg, int from_tty)
14f9c5c9
AS
688{
689 if (arg == NULL || *arg == '\000')
690 info_tasks (arg, from_tty);
691 else
692 info_task (arg, from_tty);
693}
694
695/* Switch from one thread to another. */
696
697static void
698switch_to_thread (ptid_t ptid)
14f9c5c9
AS
699{
700 if (ptid_equal (ptid, inferior_ptid))
701 return;
702
703 inferior_ptid = ptid;
704 flush_cached_frames ();
705 registers_changed ();
706 stop_pc = read_pc ();
707 select_frame (get_current_frame ());
708}
709
710/* Switch to a specified task. */
711
80ae6ee2
AS
712static int
713task_switch (void *tid, void *lwpid)
14f9c5c9
AS
714{
715 int res = 0, pid;
716
717 if (thread_support)
718 {
719 flush_cached_frames ();
720
721 if (current_task != current_task_id)
722 {
723 res = THREAD_FETCH_REGISTERS ();
724 }
725 else
726 {
727#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
728 supply_gregset (&gregset_saved);
729 supply_fpregset (&fpregset_saved);
730#endif
731 }
732
733 if (res == 0) stop_pc = read_pc();
734 select_frame (get_current_frame ());
735 return res;
736 }
737
738 return -1;
739}
740
80ae6ee2
AS
741static void
742task_command (char *tidstr, int from_tty)
14f9c5c9
AS
743{
744 int num;
745 struct task_entry *e;
746
747 if (!tidstr)
748 error ("Please specify a task ID. Use the \"info tasks\" command to\n"
749 "see the IDs of currently known tasks.");
750
751 num = atoi (tidstr);
752 e = get_entry_vptr (num);
753
754 if (e == NULL)
755 error ("Task ID %d not known. Use the \"info tasks\" command to\n"
756 "see the IDs of currently known tasks.", num);
757
758 if (current_task_id == -1)
759 {
760#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
761 fill_gregset (&gregset_saved, -1);
762 fill_fpregset (&fpregset_saved, -1);
763#endif
764 current_task_id = get_current_task ();
765 }
766
767 current_task = num;
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)
772 {
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);
778 }
779 else
780 printf_filtered ("Unable to switch to task %d\n", num);
781}
782
783void
80ae6ee2 784_initialize_tasks (void)
14f9c5c9
AS
785{
786 static struct cmd_list_element *task_cmd_list = NULL;
787 extern struct cmd_list_element *cmdlist;
788
789 add_info (
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");
793
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,
797 &cmdlist);
798}
This page took 0.065855 seconds and 4 git commands to generate.