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 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) 75extern void *GET_CURRENT_THREAD (); 76 77#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__)) 78extern 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 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 112char *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 132static 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 152static int highest_task_num = 0; 153int thread_support = 0; /* 1 if the thread library in use is supported */ 154static int gdbtk_task_initialization = 0; 155 156static int 157add_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 181int 182get_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 196static struct task_entry * 197get_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 211static struct task_entry * 212get_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 226void 227init_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 242int 243valid_task_id (int task) 244{ 245 return get_entry_vptr (task) != NULL; 246} 247 248void * 249get_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 271int 272get_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 287static void 288info_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 422print_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 461static void 462info_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 (®s, 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 698int 699gdbtk_tcl_tasks_initialize (void) 700{ 701 gdbtk_task_initialization = 1; 702 info_tasks ("", gdb_stdout); 703 704 return (task_list != NULL); 705} 706 707static void 708info_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 718static void 719switch_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 733static int 734task_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 763static void 764task_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 806void 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