OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [ada-tasks.c] - Blame information for rev 294

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005,
2
   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3
 
4
   This file is part of GDB.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
 
19
#include "defs.h"
20
#include "observer.h"
21
#include "gdbcmd.h"
22
#include "target.h"
23
#include "ada-lang.h"
24
#include "gdbcore.h"
25
#include "inferior.h"
26
#include "gdbthread.h"
27
 
28
/* The name of the array in the GNAT runtime where the Ada Task Control
29
   Block of each task is stored.  */
30
#define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
31
 
32
/* The maximum number of tasks known to the Ada runtime */
33
static const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
34
 
35
enum task_states
36
{
37
  Unactivated,
38
  Runnable,
39
  Terminated,
40
  Activator_Sleep,
41
  Acceptor_Sleep,
42
  Entry_Caller_Sleep,
43
  Async_Select_Sleep,
44
  Delay_Sleep,
45
  Master_Completion_Sleep,
46
  Master_Phase_2_Sleep,
47
  Interrupt_Server_Idle_Sleep,
48
  Interrupt_Server_Blocked_Interrupt_Sleep,
49
  Timer_Server_Sleep,
50
  AST_Server_Sleep,
51
  Asynchronous_Hold,
52
  Interrupt_Server_Blocked_On_Event_Flag,
53
  Activating,
54
  Acceptor_Delay_Sleep
55
};
56
 
57
/* A short description corresponding to each possible task state.  */
58
static const char *task_states[] = {
59
  N_("Unactivated"),
60
  N_("Runnable"),
61
  N_("Terminated"),
62
  N_("Child Activation Wait"),
63
  N_("Accept or Select Term"),
64
  N_("Waiting on entry call"),
65
  N_("Async Select Wait"),
66
  N_("Delay Sleep"),
67
  N_("Child Termination Wait"),
68
  N_("Wait Child in Term Alt"),
69
  "",
70
  "",
71
  "",
72
  "",
73
  N_("Asynchronous Hold"),
74
  "",
75
  N_("Activating"),
76
  N_("Selective Wait")
77
};
78
 
79
/* A longer description corresponding to each possible task state.  */
80
static const char *long_task_states[] = {
81
  N_("Unactivated"),
82
  N_("Runnable"),
83
  N_("Terminated"),
84
  N_("Waiting for child activation"),
85
  N_("Blocked in accept or select with terminate"),
86
  N_("Waiting on entry call"),
87
  N_("Asynchronous Selective Wait"),
88
  N_("Delay Sleep"),
89
  N_("Waiting for children termination"),
90
  N_("Waiting for children in terminate alternative"),
91
  "",
92
  "",
93
  "",
94
  "",
95
  N_("Asynchronous Hold"),
96
  "",
97
  N_("Activating"),
98
  N_("Blocked in selective wait statement")
99
};
100
 
101
/* The index of certain important fields in the Ada Task Control Block
102
   record and sub-records.  */
103
 
104
struct tcb_fieldnos
105
{
106
  /* Fields in record Ada_Task_Control_Block.  */
107
  int common;
108
  int entry_calls;
109
  int atc_nesting_level;
110
 
111
  /* Fields in record Common_ATCB.  */
112
  int state;
113
  int parent;
114
  int priority;
115
  int image;
116
  int image_len;     /* This field may be missing.  */
117
  int call;
118
  int ll;
119
 
120
  /* Fields in Task_Primitives.Private_Data.  */
121
  int ll_thread;
122
  int ll_lwp;        /* This field may be missing.  */
123
 
124
  /* Fields in Common_ATCB.Call.all.  */
125
  int call_self;
126
};
127
 
128
/* The type description for the ATCB record and subrecords, and
129
   the associated tcb_fieldnos. For efficiency reasons, these are made
130
   static globals so that we can compute them only once the first time
131
   and reuse them later.  Set to NULL if the types haven't been computed
132
   yet, or if they may be obsolete (for instance after having loaded
133
   a new binary).  */
134
 
135
static struct type *atcb_type = NULL;
136
static struct type *atcb_common_type = NULL;
137
static struct type *atcb_ll_type = NULL;
138
static struct type *atcb_call_type = NULL;
139
static struct tcb_fieldnos fieldno;
140
 
141
/* Set to 1 when the cached address of System.Tasking.Debug.Known_Tasks
142
   might be stale and so needs to be recomputed.  */
143
static int ada_tasks_check_symbol_table = 1;
144
 
145
/* The list of Ada tasks.
146
 
147
   Note: To each task we associate a number that the user can use to
148
   reference it - this number is printed beside each task in the tasks
149
   info listing displayed by "info tasks".  This number is equal to
150
   its index in the vector + 1.  Reciprocally, to compute the index
151
   of a task in the vector, we need to substract 1 from its number.  */
152
typedef struct ada_task_info ada_task_info_s;
153
DEF_VEC_O(ada_task_info_s);
154
static VEC(ada_task_info_s) *task_list = NULL;
155
 
156
/* When non-zero, this flag indicates that the current task_list
157
   is obsolete, and should be recomputed before it is accessed.  */
158
static int stale_task_list_p = 1;
159
 
160
/* Return the task number of the task whose ptid is PTID, or zero
161
   if the task could not be found.  */
162
 
163
int
164
ada_get_task_number (ptid_t ptid)
165
{
166
  int i;
167
 
168
  for (i=0; i < VEC_length (ada_task_info_s, task_list); i++)
169
    if (ptid_equal (VEC_index (ada_task_info_s, task_list, i)->ptid, ptid))
170
      return i + 1;
171
 
172
  return 0;  /* No matching task found.  */
173
}
174
 
175
/* Return the task number of the task that matches TASK_ID, or zero
176
   if the task could not be found.  */
177
 
178
static int
179
get_task_number_from_id (CORE_ADDR task_id)
180
{
181
  int i;
182
 
183
  for (i = 0; i < VEC_length (ada_task_info_s, task_list); i++)
184
    {
185
      struct ada_task_info *task_info =
186
        VEC_index (ada_task_info_s, task_list, i);
187
 
188
      if (task_info->task_id == task_id)
189
        return i + 1;
190
    }
191
 
192
  /* Task not found.  Return 0.  */
193
  return 0;
194
}
195
 
196
/* Return non-zero if TASK_NUM is a valid task number.  */
197
 
198
int
199
valid_task_id (int task_num)
200
{
201
  ada_build_task_list (0);
202
  return (task_num > 0
203
          && task_num <= VEC_length (ada_task_info_s, task_list));
204
}
205
 
206
/* Return non-zero iff the task STATE corresponds to a non-terminated
207
   task state.  */
208
 
209
static int
210
ada_task_is_alive (struct ada_task_info *task_info)
211
{
212
  return (task_info->state != Terminated);
213
}
214
 
215
/* Extract the contents of the value as a string whose length is LENGTH,
216
   and store the result in DEST.  */
217
 
218
static void
219
value_as_string (char *dest, struct value *val, int length)
220
{
221
  memcpy (dest, value_contents (val), length);
222
  dest[length] = '\0';
223
}
224
 
225
/* Extract the string image from the fat string corresponding to VAL,
226
   and store it in DEST.  If the string length is greater than MAX_LEN,
227
   then truncate the result to the first MAX_LEN characters of the fat
228
   string.  */
229
 
230
static void
231
read_fat_string_value (char *dest, struct value *val, int max_len)
232
{
233
  struct value *array_val;
234
  struct value *bounds_val;
235
  int len;
236
 
237
  /* The following variables are made static to avoid recomputing them
238
     each time this function is called.  */
239
  static int initialize_fieldnos = 1;
240
  static int array_fieldno;
241
  static int bounds_fieldno;
242
  static int upper_bound_fieldno;
243
 
244
  /* Get the index of the fields that we will need to read in order
245
     to extract the string from the fat string.  */
246
  if (initialize_fieldnos)
247
    {
248
      struct type *type = value_type (val);
249
      struct type *bounds_type;
250
 
251
      array_fieldno = ada_get_field_index (type, "P_ARRAY", 0);
252
      bounds_fieldno = ada_get_field_index (type, "P_BOUNDS", 0);
253
 
254
      bounds_type = TYPE_FIELD_TYPE (type, bounds_fieldno);
255
      if (TYPE_CODE (bounds_type) == TYPE_CODE_PTR)
256
        bounds_type = TYPE_TARGET_TYPE (bounds_type);
257
      if (TYPE_CODE (bounds_type) != TYPE_CODE_STRUCT)
258
        error (_("Unknown task name format. Aborting"));
259
      upper_bound_fieldno = ada_get_field_index (bounds_type, "UB0", 0);
260
 
261
      initialize_fieldnos = 0;
262
    }
263
 
264
  /* Get the size of the task image by checking the value of the bounds.
265
     The lower bound is always 1, so we only need to read the upper bound.  */
266
  bounds_val = value_ind (value_field (val, bounds_fieldno));
267
  len = value_as_long (value_field (bounds_val, upper_bound_fieldno));
268
 
269
  /* Make sure that we do not read more than max_len characters...  */
270
  if (len > max_len)
271
    len = max_len;
272
 
273
  /* Extract LEN characters from the fat string.  */
274
  array_val = value_ind (value_field (val, array_fieldno));
275
  read_memory (value_address (array_val), dest, len);
276
 
277
  /* Add the NUL character to close the string.  */
278
  dest[len] = '\0';
279
}
280
 
281
/* Return the address of the Known_Tasks array maintained in
282
   the Ada Runtime.  Return NULL if the array could not be found,
283
   meaning that the inferior program probably does not use tasking.
284
 
285
   In order to provide a fast response time, this function caches
286
   the Known_Tasks array address after the lookup during the first
287
   call. Subsequent calls will simply return this cached address.  */
288
 
289
static CORE_ADDR
290
get_known_tasks_addr (void)
291
{
292
  static CORE_ADDR known_tasks_addr = 0;
293
 
294
  if (ada_tasks_check_symbol_table)
295
    {
296
      struct symbol *sym;
297
      struct minimal_symbol *msym;
298
 
299
      msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
300
      if (msym != NULL)
301
        known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
302
      else
303
        {
304
          if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
305
            return 0;
306
        }
307
 
308
      /* FIXME: brobecker 2003-03-05: Here would be a much better place
309
         to attach the ada-tasks observers, instead of doing this
310
         unconditionaly in _initialize_tasks. This would avoid an
311
         unecessary notification when the inferior does not use tasking
312
         or as long as the user does not use the ada-tasks commands.
313
         Unfortunately, this is not possible for the moment: the current
314
         code resets ada__tasks_check_symbol_table back to 1 whenever
315
         symbols for a new program are being loaded. If we place the
316
         observers intialization here, we will end up adding new observers
317
         everytime we do the check for Ada tasking-related symbols
318
         above. This would currently have benign effects, but is still
319
         undesirable. The cleanest approach is probably to create a new
320
         observer to notify us when the user is debugging a new program.
321
         We would then reset ada__tasks_check_symbol_table back to 1
322
         during the notification, but also detach all observers.
323
         BTW: observers are probably not reentrant, so detaching during
324
         a notification may not be the safest thing to do... Sigh...
325
         But creating the new observer would be a good idea in any case,
326
         since this allow us to make ada__tasks_check_symbol_table
327
         static, which is a good bonus.  */
328
      ada_tasks_check_symbol_table = 0;
329
    }
330
 
331
  return known_tasks_addr;
332
}
333
 
334
/* Get from the debugging information the type description of all types
335
   related to the Ada Task Control Block that will be needed in order to
336
   read the list of known tasks in the Ada runtime.  Also return the
337
   associated ATCB_FIELDNOS.
338
 
339
   Error handling:  Any data missing from the debugging info will cause
340
   an error to be raised, and none of the return values to be set.
341
   Users of this function can depend on the fact that all or none of the
342
   return values will be set.  */
343
 
344
static void
345
get_tcb_types_info (struct type **atcb_type,
346
                    struct type **atcb_common_type,
347
                    struct type **atcb_ll_type,
348
                    struct type **atcb_call_type,
349
                    struct tcb_fieldnos *atcb_fieldnos)
350
{
351
  struct type *type;
352
  struct type *common_type;
353
  struct type *ll_type;
354
  struct type *call_type;
355
  struct tcb_fieldnos fieldnos;
356
 
357
  const char *atcb_name = "system__tasking__ada_task_control_block___XVE";
358
  const char *atcb_name_fixed = "system__tasking__ada_task_control_block";
359
  const char *common_atcb_name = "system__tasking__common_atcb";
360
  const char *private_data_name = "system__task_primitives__private_data";
361
  const char *entry_call_record_name = "system__tasking__entry_call_record";
362
 
363
  struct symbol *atcb_sym =
364
    lookup_symbol (atcb_name, NULL, VAR_DOMAIN, NULL);
365
  const struct symbol *common_atcb_sym =
366
    lookup_symbol (common_atcb_name, NULL, VAR_DOMAIN, NULL);
367
  const struct symbol *private_data_sym =
368
    lookup_symbol (private_data_name, NULL, VAR_DOMAIN, NULL);
369
  const struct symbol *entry_call_record_sym =
370
    lookup_symbol (entry_call_record_name, NULL, VAR_DOMAIN, NULL);
371
 
372
  if (atcb_sym == NULL || atcb_sym->type == NULL)
373
    {
374
      /* In Ravenscar run-time libs, the  ATCB does not have a dynamic
375
         size, so the symbol name differs.  */
376
      atcb_sym = lookup_symbol (atcb_name_fixed, NULL, VAR_DOMAIN, NULL);
377
 
378
      if (atcb_sym == NULL || atcb_sym->type == NULL)
379
        error (_("Cannot find Ada_Task_Control_Block type. Aborting"));
380
 
381
      type = atcb_sym->type;
382
    }
383
  else
384
    {
385
      /* Get a static representation of the type record
386
         Ada_Task_Control_Block.  */
387
      type = atcb_sym->type;
388
      type = ada_template_to_fixed_record_type_1 (type, NULL, 0, NULL, 0);
389
    }
390
 
391
  if (common_atcb_sym == NULL || common_atcb_sym->type == NULL)
392
    error (_("Cannot find Common_ATCB type. Aborting"));
393
  if (private_data_sym == NULL || private_data_sym->type == NULL)
394
    error (_("Cannot find Private_Data type. Aborting"));
395
  if (entry_call_record_sym == NULL || entry_call_record_sym->type == NULL)
396
    error (_("Cannot find Entry_Call_Record type. Aborting"));
397
 
398
  /* Get the type for Ada_Task_Control_Block.Common.  */
399
  common_type = common_atcb_sym->type;
400
 
401
  /* Get the type for Ada_Task_Control_Bloc.Common.Call.LL.  */
402
  ll_type = private_data_sym->type;
403
 
404
  /* Get the type for Common_ATCB.Call.all.  */
405
  call_type = entry_call_record_sym->type;
406
 
407
  /* Get the field indices.  */
408
  fieldnos.common = ada_get_field_index (type, "common", 0);
409
  fieldnos.entry_calls = ada_get_field_index (type, "entry_calls", 1);
410
  fieldnos.atc_nesting_level =
411
    ada_get_field_index (type, "atc_nesting_level", 1);
412
  fieldnos.state = ada_get_field_index (common_type, "state", 0);
413
  fieldnos.parent = ada_get_field_index (common_type, "parent", 1);
414
  fieldnos.priority = ada_get_field_index (common_type, "base_priority", 0);
415
  fieldnos.image = ada_get_field_index (common_type, "task_image", 1);
416
  fieldnos.image_len = ada_get_field_index (common_type, "task_image_len", 1);
417
  fieldnos.call = ada_get_field_index (common_type, "call", 1);
418
  fieldnos.ll = ada_get_field_index (common_type, "ll", 0);
419
  fieldnos.ll_thread = ada_get_field_index (ll_type, "thread", 0);
420
  fieldnos.ll_lwp = ada_get_field_index (ll_type, "lwp", 1);
421
  fieldnos.call_self = ada_get_field_index (call_type, "self", 0);
422
 
423
  /* On certain platforms such as x86-windows, the "lwp" field has been
424
     named "thread_id".  This field will likely be renamed in the future,
425
     but we need to support both possibilities to avoid an unnecessary
426
     dependency on a recent compiler.  We therefore try locating the
427
     "thread_id" field in place of the "lwp" field if we did not find
428
     the latter.  */
429
  if (fieldnos.ll_lwp < 0)
430
    fieldnos.ll_lwp = ada_get_field_index (ll_type, "thread_id", 1);
431
 
432
  /* Set all the out parameters all at once, now that we are certain
433
     that there are no potential error() anymore.  */
434
  *atcb_type = type;
435
  *atcb_common_type = common_type;
436
  *atcb_ll_type = ll_type;
437
  *atcb_call_type = call_type;
438
  *atcb_fieldnos = fieldnos;
439
}
440
 
441
/* Build the PTID of the task from its COMMON_VALUE, which is the "Common"
442
   component of its ATCB record.  This PTID needs to match the PTID used
443
   by the thread layer.  */
444
 
445
static ptid_t
446
ptid_from_atcb_common (struct value *common_value)
447
{
448
  long thread = 0;
449
  CORE_ADDR lwp = 0;
450
  struct value *ll_value;
451
  ptid_t ptid;
452
 
453
  ll_value = value_field (common_value, fieldno.ll);
454
 
455
  if (fieldno.ll_lwp >= 0)
456
    lwp = value_as_address (value_field (ll_value, fieldno.ll_lwp));
457
  thread = value_as_long (value_field (ll_value, fieldno.ll_thread));
458
 
459
  ptid = target_get_ada_task_ptid (lwp, thread);
460
 
461
  return ptid;
462
}
463
 
464
/* Read the ATCB data of a given task given its TASK_ID (which is in practice
465
   the address of its assocated ATCB record), and store the result inside
466
   TASK_INFO.  */
467
 
468
static void
469
read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
470
{
471
  struct value *tcb_value;
472
  struct value *common_value;
473
  struct value *atc_nesting_level_value;
474
  struct value *entry_calls_value;
475
  struct value *entry_calls_value_element;
476
  int called_task_fieldno = -1;
477
  const char ravenscar_task_name[] = "Ravenscar task";
478
 
479
  if (atcb_type == NULL)
480
    get_tcb_types_info (&atcb_type, &atcb_common_type, &atcb_ll_type,
481
                        &atcb_call_type, &fieldno);
482
 
483
  tcb_value = value_from_contents_and_address (atcb_type, NULL, task_id);
484
  common_value = value_field (tcb_value, fieldno.common);
485
 
486
  /* Fill in the task_id.  */
487
 
488
  task_info->task_id = task_id;
489
 
490
  /* Compute the name of the task.
491
 
492
     Depending on the GNAT version used, the task image is either a fat
493
     string, or a thin array of characters.  Older versions of GNAT used
494
     to use fat strings, and therefore did not need an extra field in
495
     the ATCB to store the string length. For efficiency reasons, newer
496
     versions of GNAT replaced the fat string by a static buffer, but this
497
     also required the addition of a new field named "Image_Len" containing
498
     the length of the task name. The method used to extract the task name
499
     is selected depending on the existence of this field.
500
 
501
     In some run-time libs (e.g. Ravenscar), the name is not in the ATCB;
502
     we may want to get it from the first user frame of the stack. For now,
503
     we just give a dummy name.  */
504
 
505
  if (fieldno.image_len == -1)
506
    {
507
      if (fieldno.image >= 0)
508
        read_fat_string_value (task_info->name,
509
                               value_field (common_value, fieldno.image),
510
                               sizeof (task_info->name) - 1);
511
      else
512
        strcpy (task_info->name, ravenscar_task_name);
513
    }
514
  else
515
    {
516
      int len = value_as_long (value_field (common_value, fieldno.image_len));
517
 
518
      value_as_string (task_info->name,
519
                       value_field (common_value, fieldno.image), len);
520
    }
521
 
522
  /* Compute the task state and priority.  */
523
 
524
  task_info->state = value_as_long (value_field (common_value, fieldno.state));
525
  task_info->priority =
526
    value_as_long (value_field (common_value, fieldno.priority));
527
 
528
  /* If the ATCB contains some information about the parent task,
529
     then compute it as well.  Otherwise, zero.  */
530
 
531
  if (fieldno.parent >= 0)
532
    task_info->parent =
533
      value_as_address (value_field (common_value, fieldno.parent));
534
  else
535
    task_info->parent = 0;
536
 
537
 
538
  /* If the ATCB contains some information about entry calls, then
539
     compute the "called_task" as well.  Otherwise, zero.  */
540
 
541
  if (fieldno.atc_nesting_level > 0 && fieldno.entry_calls > 0)
542
    {
543
      /* Let My_ATCB be the Ada task control block of a task calling the
544
         entry of another task; then the Task_Id of the called task is
545
         in My_ATCB.Entry_Calls (My_ATCB.ATC_Nesting_Level).Called_Task.  */
546
      atc_nesting_level_value = value_field (tcb_value,
547
                                             fieldno.atc_nesting_level);
548
      entry_calls_value =
549
        ada_coerce_to_simple_array_ptr (value_field (tcb_value,
550
                                                     fieldno.entry_calls));
551
      entry_calls_value_element =
552
        value_subscript (entry_calls_value,
553
                         value_as_long (atc_nesting_level_value));
554
      called_task_fieldno =
555
        ada_get_field_index (value_type (entry_calls_value_element),
556
                             "called_task", 0);
557
      task_info->called_task =
558
        value_as_address (value_field (entry_calls_value_element,
559
                                       called_task_fieldno));
560
    }
561
  else
562
    {
563
      task_info->called_task = 0;
564
    }
565
 
566
  /* If the ATCB cotnains some information about RV callers,
567
     then compute the "caller_task".  Otherwise, zero.  */
568
 
569
  task_info->caller_task = 0;
570
  if (fieldno.call >= 0)
571
    {
572
      /* Get the ID of the caller task from Common_ATCB.Call.all.Self.
573
         If Common_ATCB.Call is null, then there is no caller.  */
574
      const CORE_ADDR call =
575
        value_as_address (value_field (common_value, fieldno.call));
576
      struct value *call_val;
577
 
578
      if (call != 0)
579
        {
580
          call_val =
581
            value_from_contents_and_address (atcb_call_type, NULL, call);
582
          task_info->caller_task =
583
            value_as_address (value_field (call_val, fieldno.call_self));
584
        }
585
    }
586
 
587
  /* And finally, compute the task ptid.  */
588
 
589
  if (ada_task_is_alive (task_info))
590
    task_info->ptid = ptid_from_atcb_common (common_value);
591
  else
592
    task_info->ptid = null_ptid;
593
}
594
 
595
/* Read the ATCB info of the given task (identified by TASK_ID), and
596
   add the result to the TASK_LIST.  */
597
 
598
static void
599
add_ada_task (CORE_ADDR task_id)
600
{
601
  struct ada_task_info task_info;
602
 
603
  read_atcb (task_id, &task_info);
604
  VEC_safe_push (ada_task_info_s, task_list, &task_info);
605
}
606
 
607
/* Read the Known_Tasks array from the inferior memory, and store
608
   it in TASK_LIST.  Return non-zero upon success.  */
609
 
610
static int
611
read_known_tasks_array (void)
612
{
613
  const int target_ptr_byte =
614
    gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT;
615
  const CORE_ADDR known_tasks_addr = get_known_tasks_addr ();
616
  const int known_tasks_size = target_ptr_byte * MAX_NUMBER_OF_KNOWN_TASKS;
617
  gdb_byte *known_tasks = alloca (known_tasks_size);
618
  int i;
619
 
620
  /* Step 1: Clear the current list, if necessary.  */
621
  VEC_truncate (ada_task_info_s, task_list, 0);
622
 
623
  /* If the application does not use task, then no more needs to be done.
624
     It is important to have the task list cleared (see above) before we
625
     return, as we don't want a stale task list to be used...  This can
626
     happen for instance when debugging a non-multitasking program after
627
     having debugged a multitasking one.  */
628
  if (known_tasks_addr == 0)
629
    return 0;
630
 
631
  /* Step 2: Build a new list by reading the ATCBs from the Known_Tasks
632
     array in the Ada runtime.  */
633
  read_memory (known_tasks_addr, known_tasks, known_tasks_size);
634
  for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
635
    {
636
      struct type *data_ptr_type =
637
        builtin_type (target_gdbarch)->builtin_data_ptr;
638
      CORE_ADDR task_id =
639
        extract_typed_address (known_tasks + i * target_ptr_byte,
640
                               data_ptr_type);
641
 
642
      if (task_id != 0)
643
        add_ada_task (task_id);
644
    }
645
 
646
  /* Step 3: Unset stale_task_list_p, to avoid re-reading the Known_Tasks
647
     array unless needed.  Then report a success.  */
648
  stale_task_list_p = 0;
649
 
650
  return 1;
651
}
652
 
653
/* Builds the task_list by reading the Known_Tasks array from
654
   the inferior.  Prints an appropriate message and returns non-zero
655
   if it failed to build this list.  */
656
 
657
int
658
ada_build_task_list (int warn_if_null)
659
{
660
  if (!target_has_stack)
661
    error (_("Cannot inspect Ada tasks when program is not running"));
662
 
663
  if (stale_task_list_p)
664
    read_known_tasks_array ();
665
 
666
  if (task_list == NULL)
667
    {
668
      if (warn_if_null)
669
        printf_filtered (_("Your application does not use any Ada tasks.\n"));
670
      return 0;
671
    }
672
 
673
  return 1;
674
}
675
 
676
/* Print a one-line description of the task whose number is TASKNO.
677
   The formatting should fit the "info tasks" array.  */
678
 
679
static void
680
short_task_info (int taskno)
681
{
682
  const struct ada_task_info *const task_info =
683
    VEC_index (ada_task_info_s, task_list, taskno - 1);
684
  int active_task_p;
685
 
686
  gdb_assert (task_info != NULL);
687
 
688
  /* Print a star if this task is the current task (or the task currently
689
     selected).  */
690
 
691
  active_task_p = ptid_equal (task_info->ptid, inferior_ptid);
692
  if (active_task_p)
693
    printf_filtered ("*");
694
  else
695
    printf_filtered (" ");
696
 
697
  /* Print the task number.  */
698
  printf_filtered ("%3d", taskno);
699
 
700
  /* Print the Task ID.  */
701
  printf_filtered (" %9lx", (long) task_info->task_id);
702
 
703
  /* Print the Task ID of the task parent.  */
704
  printf_filtered (" %4d", get_task_number_from_id (task_info->parent));
705
 
706
  /* Print the base priority of the task.  */
707
  printf_filtered (" %3d", task_info->priority);
708
 
709
  /* Print the task current state.  */
710
  if (task_info->caller_task)
711
    printf_filtered (_(" Accepting RV with %-4d"),
712
                     get_task_number_from_id (task_info->caller_task));
713
  else if (task_info->state == Entry_Caller_Sleep && task_info->called_task)
714
    printf_filtered (_(" Waiting on RV with %-3d"),
715
                     get_task_number_from_id (task_info->called_task));
716
  else
717
    printf_filtered (" %-22s", _(task_states[task_info->state]));
718
 
719
  /* Finally, print the task name.  */
720
  if (task_info->name[0] != '\0')
721
    printf_filtered (" %s\n", task_info->name);
722
  else
723
    printf_filtered (_(" <no name>\n"));
724
}
725
 
726
/* Print a list containing a short description of all Ada tasks.  */
727
/* FIXME: Shouldn't we be using ui_out??? */
728
 
729
static void
730
info_tasks (int from_tty)
731
{
732
  int taskno;
733
  const int nb_tasks = VEC_length (ada_task_info_s, task_list);
734
 
735
  printf_filtered (_("  ID       TID P-ID Pri State                  Name\n"));
736
 
737
  for (taskno = 1; taskno <= nb_tasks; taskno++)
738
    short_task_info (taskno);
739
}
740
 
741
/* Print a detailed description of the Ada task whose ID is TASKNO_STR.  */
742
 
743
static void
744
info_task (char *taskno_str, int from_tty)
745
{
746
  const int taskno = value_as_long (parse_and_eval (taskno_str));
747
  struct ada_task_info *task_info;
748
  int parent_taskno = 0;
749
 
750
  if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, task_list))
751
    error (_("Task ID %d not known.  Use the \"info tasks\" command to\n"
752
             "see the IDs of currently known tasks"), taskno);
753
  task_info = VEC_index (ada_task_info_s, task_list, taskno - 1);
754
 
755
  /* Print the Ada task ID.  */
756
  printf_filtered (_("Ada Task: %s\n"),
757
                   paddress (target_gdbarch, task_info->task_id));
758
 
759
  /* Print the name of the task.  */
760
  if (task_info->name[0] != '\0')
761
    printf_filtered (_("Name: %s\n"), task_info->name);
762
  else
763
    printf_filtered (_("<no name>\n"));
764
 
765
  /* Print the TID and LWP.  */
766
  printf_filtered (_("Thread: %#lx\n"), ptid_get_tid (task_info->ptid));
767
  printf_filtered (_("LWP: %#lx\n"), ptid_get_lwp (task_info->ptid));
768
 
769
  /* Print who is the parent (if any).  */
770
  if (task_info->parent != 0)
771
    parent_taskno = get_task_number_from_id (task_info->parent);
772
  if (parent_taskno)
773
    {
774
      struct ada_task_info *parent =
775
        VEC_index (ada_task_info_s, task_list, parent_taskno - 1);
776
 
777
      printf_filtered (_("Parent: %d"), parent_taskno);
778
      if (parent->name[0] != '\0')
779
        printf_filtered (" (%s)", parent->name);
780
      printf_filtered ("\n");
781
    }
782
  else
783
    printf_filtered (_("No parent\n"));
784
 
785
  /* Print the base priority.  */
786
  printf_filtered (_("Base Priority: %d\n"), task_info->priority);
787
 
788
  /* print the task current state.  */
789
  {
790
    int target_taskno = 0;
791
 
792
    if (task_info->caller_task)
793
      {
794
        target_taskno = get_task_number_from_id (task_info->caller_task);
795
        printf_filtered (_("State: Accepting rendezvous with %d"),
796
                         target_taskno);
797
      }
798
    else if (task_info->state == Entry_Caller_Sleep && task_info->called_task)
799
      {
800
        target_taskno = get_task_number_from_id (task_info->called_task);
801
        printf_filtered (_("State: Waiting on task %d's entry"),
802
                         target_taskno);
803
      }
804
    else
805
      printf_filtered (_("State: %s"), _(long_task_states[task_info->state]));
806
 
807
    if (target_taskno)
808
      {
809
        struct ada_task_info *target_task_info =
810
          VEC_index (ada_task_info_s, task_list, target_taskno - 1);
811
 
812
        if (target_task_info->name[0] != '\0')
813
          printf_filtered (" (%s)", target_task_info->name);
814
      }
815
 
816
    printf_filtered ("\n");
817
  }
818
}
819
 
820
/* If ARG is empty or null, then print a list of all Ada tasks.
821
   Otherwise, print detailed information about the task whose ID
822
   is ARG.
823
 
824
   Does nothing if the program doesn't use Ada tasking.  */
825
 
826
static void
827
info_tasks_command (char *arg, int from_tty)
828
{
829
  const int task_list_built = ada_build_task_list (1);
830
 
831
  if (!task_list_built)
832
    return;
833
 
834
  if (arg == NULL || *arg == '\0')
835
    info_tasks (from_tty);
836
  else
837
    info_task (arg, from_tty);
838
}
839
 
840
/* Print a message telling the user id of the current task.
841
   This function assumes that tasking is in use in the inferior.  */
842
 
843
static void
844
display_current_task_id (void)
845
{
846
  const int current_task = ada_get_task_number (inferior_ptid);
847
 
848
  if (current_task == 0)
849
    printf_filtered (_("[Current task is unknown]\n"));
850
  else
851
    printf_filtered (_("[Current task is %d]\n"), current_task);
852
}
853
 
854
/* Parse and evaluate TIDSTR into a task id, and try to switch to
855
   that task.  Print an error message if the task switch failed.  */
856
 
857
static void
858
task_command_1 (char *taskno_str, int from_tty)
859
{
860
  const int taskno = value_as_long (parse_and_eval (taskno_str));
861
  struct ada_task_info *task_info;
862
 
863
  if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, task_list))
864
    error (_("Task ID %d not known.  Use the \"info tasks\" command to\n"
865
             "see the IDs of currently known tasks"), taskno);
866
  task_info = VEC_index (ada_task_info_s, task_list, taskno - 1);
867
 
868
  if (!ada_task_is_alive (task_info))
869
    error (_("Cannot switch to task %d: Task is no longer running"), taskno);
870
 
871
  /* On some platforms, the thread list is not updated until the user
872
     performs a thread-related operation (by using the "info threads"
873
     command, for instance).  So this thread list may not be up to date
874
     when the user attempts this task switch.  Since we cannot switch
875
     to the thread associated to our task if GDB does not know about
876
     that thread, we need to make sure that any new threads gets added
877
     to the thread list.  */
878
  target_find_new_threads ();
879
 
880
  switch_to_thread (task_info->ptid);
881
  ada_find_printable_frame (get_selected_frame (NULL));
882
  printf_filtered (_("[Switching to task %d]\n"), taskno);
883
  print_stack_frame (get_selected_frame (NULL),
884
                     frame_relative_level (get_selected_frame (NULL)), 1);
885
}
886
 
887
 
888
/* Print the ID of the current task if TASKNO_STR is empty or NULL.
889
   Otherwise, switch to the task indicated by TASKNO_STR.  */
890
 
891
static void
892
task_command (char *taskno_str, int from_tty)
893
{
894
  const int task_list_built = ada_build_task_list (1);
895
 
896
  if (!task_list_built)
897
    return;
898
 
899
  if (taskno_str == NULL || taskno_str[0] == '\0')
900
    display_current_task_id ();
901
  else
902
    {
903
      /* Task switching in core files doesn't work, either because:
904
           1. Thread support is not implemented with core files
905
           2. Thread support is implemented, but the thread IDs created
906
              after having read the core file are not the same as the ones
907
              that were used during the program life, before the crash.
908
              As a consequence, there is no longer a way for the debugger
909
              to find the associated thead ID of any given Ada task.
910
         So, instead of attempting a task switch without giving the user
911
         any clue as to what might have happened, just error-out with
912
         a message explaining that this feature is not supported.  */
913
      if (!target_has_execution)
914
        error (_("\
915
Task switching not supported when debugging from core files\n\
916
(use thread support instead)"));
917
      task_command_1 (taskno_str, from_tty);
918
    }
919
}
920
 
921
/* Indicate that the task list may have changed, so invalidate the cache.  */
922
 
923
static void
924
ada_task_list_changed (void)
925
{
926
  stale_task_list_p = 1;
927
}
928
 
929
/* The 'normal_stop' observer notification callback.  */
930
 
931
static void
932
ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2)
933
{
934
  /* The inferior has been resumed, and just stopped. This means that
935
     our task_list needs to be recomputed before it can be used again.  */
936
  ada_task_list_changed ();
937
}
938
 
939
/* A routine to be called when the objfiles have changed.  */
940
 
941
static void
942
ada_new_objfile_observer (struct objfile *objfile)
943
{
944
  /* Invalidate all cached data that were extracted from an objfile.  */
945
 
946
  atcb_type = NULL;
947
  atcb_common_type = NULL;
948
  atcb_ll_type = NULL;
949
  atcb_call_type = NULL;
950
 
951
  ada_tasks_check_symbol_table = 1;
952
}
953
 
954
/* Provide a prototype to silence -Wmissing-prototypes.  */
955
extern initialize_file_ftype _initialize_tasks;
956
 
957
void
958
_initialize_tasks (void)
959
{
960
  /* Attach various observers.  */
961
  observer_attach_normal_stop (ada_normal_stop_observer);
962
  observer_attach_new_objfile (ada_new_objfile_observer);
963
 
964
  /* Some new commands provided by this module.  */
965
  add_info ("tasks", info_tasks_command,
966
            _("Provide information about all known Ada tasks"));
967
  add_cmd ("task", class_run, task_command,
968
           _("Use this command to switch between Ada tasks.\n\
969
Without argument, this command simply prints the current task ID"),
970
           &cmdlist);
971
}
972
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.