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: ada-tasks.c,v 1.7 2003/06/17 20:58:32 ciceron Exp $]
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 "regcache.h"
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"
34 #endif
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
60 extern 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)
75 extern void *GET_CURRENT_THREAD ();
76 
77 #elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
78 extern void *GET_CURRENT_THREAD ();
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 
94 /* Global visible variables */
95 
96 struct task_entry *task_list = NULL;
97 int ada__tasks_check_symbol_table = 1;
98 void *pthread_kern_addr = NULL;
99 
100 #if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
101 gdb_gregset_t gregset_saved;
102 gdb_fpregset_t fpregset_saved;
103 #endif
104 
105 /* The maximum number of tasks known to the Ada runtime */
106 const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
107 
108 /* the current task */
109 int current_task = -1, current_task_id = -1, current_task_index;
110 void *current_thread, *current_lwp;
111 
112 char *ada_task_states[] = {
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 
132 static char *ada_long_task_states[] = {
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 
152 static int highest_task_num = 0;
153 int thread_support = 0;		/* 1 if the thread library in use is supported */
154 static int gdbtk_task_initialization = 0;
155 
156 static int
add_task_entry(void * p_task_id,int index)157 add_task_entry (void *p_task_id, int index)
158 {
159   struct task_entry *new_task_entry = NULL;
160   struct task_entry *pt;
161 
162   highest_task_num++;
163   new_task_entry = xmalloc (sizeof (struct task_entry));
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     }
176   else
177     task_list = new_task_entry;
178   return new_task_entry->task_num;
179 }
180 
181 int
get_entry_number(void * p_task_id)182 get_entry_number (void *p_task_id)
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 
196 static struct task_entry *
get_thread_entry_vptr(void * thread)197 get_thread_entry_vptr (void *thread)
198 {
199   struct task_entry *pt;
200 
201   pt = task_list;
202   while (pt != NULL)
203     {
204       if (pt->thread == thread)
205 	return pt;
206       pt = pt->next_task;
207     }
208   return 0;
209 }
210 
211 static struct task_entry *
get_entry_vptr(int p_task_num)212 get_entry_vptr (int p_task_num)
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 
226 void
init_task_list(void)227 init_task_list (void)
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;
236       xfree (old_pt);
237     };
238   task_list = NULL;
239   highest_task_num = 0;
240 }
241 
242 int
valid_task_id(int task)243 valid_task_id (int task)
244 {
245   return get_entry_vptr (task) != NULL;
246 }
247 
248 void *
get_self_id(void)249 get_self_id (void)
250 {
251   struct value *val;
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 
271 int
get_current_task(void)272 get_current_task (void)
273 {
274   int result;
275 
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 
287 static void
info_task(char * arg,int from_tty)288 info_task (char *arg, int from_tty)
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;
295   int bounds[2];
296   char image[256];
297   int num;
298 
299   /* FIXME: language_ada should be defined in defs.h */
300   /*  if (current_language->la_language != language_ada)
301      {
302      printf_filtered ("The current language does not support tasks.\n");
303      return;
304      }
305    */
306   pt = get_entry_vptr (atoi (arg));
307   if (pt == NULL)
308     {
309       printf_filtered ("Task %s not found.\n", arg);
310       return;
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 */
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");
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)
343 	printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
344       else
345 	printf_filtered ("LWP: %p\n", pt->lwp);
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 */
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 	}
366       else
367 	printf_filtered ("\n");
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;
380   else
381     {
382       READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
383       caller = EXTRACT_ADDRESS (call.self);
384     }
385 
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 */
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 	    }
406 	  else
407 	    printf_filtered ("\n");
408 	}
409       else
410 	printf_filtered ("\n");
411     }
412   else
413     printf_filtered ("State: %s\n", ada_long_task_states[atcb.state]);
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 
422 print_align (void)
423 {
424   struct task_fields tf;
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);
430   void *tf_current_priority = &(tf.current_priority);
431   void *tf_image = &(tf.image);
432   void *tf_call = &(tf.call);
433   void *tf_thread = &(tf.thread);
434   void *tf_lwp = &(tf.lwp);
435   printf_filtered ("\n");
436   printf_filtered ("(tf_base = 0x%x)\n", tf_base);
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");
456 }
457 #endif
458 
459 /* Print information about currently known tasks */
460 
461 static void
info_tasks(char * arg,int from_tty)462 info_tasks (char *arg, int from_tty)
463 {
464   struct value *val;
465   int i, task_number, state;
466   void *temp_task, *temp_tasks[MAX_NUMBER_OF_KNOWN_TASKS];
467   struct task_entry *pt;
468   void *self_id, *caller, *thread_id = NULL;
469   struct task_fields atcb;
470   struct entry_call call;
471   int bounds[2];
472   char image[256];
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 
490   if (PIDGET (inferior_ptid) == 0)
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
510 	return;
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 
535   for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
536     {
537       temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
538 
539       if (temp_task != NULL)
540 	{
541 	  task_number = get_entry_number (temp_task);
542 	  if (task_number == 0)
543 	    task_number = add_task_entry (temp_task, i);
544 	}
545     }
546 
547   /* Return without printing anything if this function was called in
548      order to init GDBTK tasking. */
549 
550   if (init_only)
551     return;
552 
553   /* print the header */
554 
555 #if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
556   printf_filtered
557     ("  ID       TID P-ID Pri Stack  %% State                  Name\n");
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
596       printf_filtered (" %#9lx", (unsigned long) pt->thread & 0x3ffffffffff);
597 #else
598       printf_filtered (" %#9lx", (long) pt->thread);
599 #endif
600 #endif
601 
602       /* print the parent gdb task id */
603       printf_filtered
604 	(" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
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 	{
612 	  printf_filtered ("  Unknown");
613 	  goto next;
614 	}
615 
616       read_memory ((CORE_ADDR) atcb.thread, &thr, sizeof (thr));
617       current_thread = atcb.thread;
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 	}
628 
629       /* print information about stack space used in the thread */
630       if (thr.__stack_size < 1024 * 1024)
631 	{
632 	  size = thr.__stack_size / 1024;
633 	  car = 'K';
634 	}
635       else if (thr.__stack_size < 1024 * 1024 * 1024)
636 	{
637 	  size = thr.__stack_size / 1024 / 1024;
638 	  car = 'M';
639 	}
640       else			/* Who knows... */
641 	{
642 	  size = thr.__stack_size / 1024 / 1024 / 1024;
643 	  car = 'G';
644 	}
645       printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
646     next:
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;
654       else
655 	{
656 	  READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
657 	  caller = EXTRACT_ADDRESS (call.self);
658 	}
659 
660       if (caller != NULL)
661 	printf_filtered (" Accepting RV with %-4d",
662 			 get_entry_number (caller));
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
674 	    printf_filtered (" %-22s", ada_task_states[state]);
675 	}
676 
677       /* finally, print the name of the task */
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");
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 
698 int
gdbtk_tcl_tasks_initialize(void)699 gdbtk_tcl_tasks_initialize (void)
700 {
701   gdbtk_task_initialization = 1;
702   info_tasks ("", gdb_stdout);
703 
704   return (task_list != NULL);
705 }
706 
707 static void
info_tasks_command(char * arg,int from_tty)708 info_tasks_command (char *arg, int from_tty)
709 {
710   if (arg == NULL || *arg == '\000')
711     info_tasks (arg, from_tty);
712   else
713     info_task (arg, from_tty);
714 }
715 
716 /* Switch from one thread to another. */
717 
718 static void
switch_to_thread(ptid_t ptid)719 switch_to_thread (ptid_t ptid)
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 
733 static int
task_switch(void * tid,void * lwpid)734 task_switch (void *tid, void *lwpid)
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 
754       if (res == 0)
755 	stop_pc = read_pc ();
756       select_frame (get_current_frame ());
757       return res;
758     }
759 
760   return -1;
761 }
762 
763 static void
task_command(char * tidstr,int from_tty)764 task_command (char *tidstr, int from_tty)
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"
771 	   "see the IDs of currently known tasks.");
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"
778 	   "see the IDs of currently known tasks.", num);
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
796          implemented in ada-lang.c */
797       /*      find_printable_frame (deprecated_selected_frame, frame_relative_level (deprecated_selected_frame)); */
798       printf_filtered ("[Switching to task %d]\n", num);
799       print_stack_frame (deprecated_selected_frame,
800 			 frame_relative_level (deprecated_selected_frame), 1);
801     }
802   else
803     printf_filtered ("Unable to switch to task %d\n", num);
804 }
805 
806 void
_initialize_tasks(void)807 _initialize_tasks (void)
808 {
809   static struct cmd_list_element *task_cmd_list = NULL;
810   extern struct cmd_list_element *cmdlist;
811 
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");
815 
816   add_prefix_cmd ("task", class_run, task_command,
817 		  "Use this command to switch between tasks.\n\
818  The new task ID must be currently known.", &task_cmd_list, "task ", 1, &cmdlist);
819 }
820