aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2011-09-16 19:09:07 +0000
committerJoel Brobecker <brobecker@gnat.com>2011-09-16 19:09:07 +0000
commit6da9ca05ace2b56540db950aa5281e6ef76f76c3 (patch)
tree67c018a6143b834f915c35330d767006267318b9
parentdccd3cbdabe18b21f6085fcf60323cbc466d1161 (diff)
downloadgdb-6da9ca05ace2b56540db950aa5281e6ef76f76c3.zip
gdb-6da9ca05ace2b56540db950aa5281e6ef76f76c3.tar.gz
gdb-6da9ca05ace2b56540db950aa5281e6ef76f76c3.tar.bz2
[Ada] Make the ATCB type info program-space-specific
This module caches the type description of various elements of the Ada Task Control Block (ATCB). This cache was implemented as static globals, which is wrong in the case where we have multiple inferiors. This change cleans things up a bit by moving some of these static globals to a per-program-space area. gdb/ChangeLog: * ada-tasks.c: #include "progspace.h" and "objfiles.h". (atcb_type, atcb_common_type, atcb_ll_type, atcb_call_type) (atcb_fieldno): Delete these static globals. (struct ada_tasks_pspace_data): New struct. (ada_tasks_pspace_data_handle): New static global. (get_ada_tasks_pspace_data): New function. (ada_tasks_invalidate_pspace_data): New function. (get_tcb_types_info, ptid_from_atcb_common, read_atcb) (read_known_tasks_list, ada_new_objfile_observer): Adjust. (_initialize_tasks): Create this module's per-progspace data handle.
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/ada-tasks.c189
2 files changed, 150 insertions, 53 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 62a59b9..05e9505 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,19 @@
2011-09-16 Joel Brobecker <brobecker@adacore.com>
+ * ada-tasks.c: #include "progspace.h" and "objfiles.h".
+ (atcb_type, atcb_common_type, atcb_ll_type, atcb_call_type)
+ (atcb_fieldno): Delete these static globals.
+ (struct ada_tasks_pspace_data): New struct.
+ (ada_tasks_pspace_data_handle): New static global.
+ (get_ada_tasks_pspace_data): New function.
+ (ada_tasks_invalidate_pspace_data): New function.
+ (get_tcb_types_info, ptid_from_atcb_common, read_atcb)
+ (read_known_tasks_list, ada_new_objfile_observer): Adjust.
+ (_initialize_tasks): Create this module's per-progspace
+ data handle.
+
+2011-09-16 Joel Brobecker <brobecker@adacore.com>
+
* ada-tasks.c (struct atcb_fieldnos): Renames struct tcb_fieldnos.
2011-09-16 Tristan Gingold <gingold@adacore.com>
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index e49cf69..4e48d3c 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -24,6 +24,8 @@
#include "gdbcore.h"
#include "inferior.h"
#include "gdbthread.h"
+#include "progspace.h"
+#include "objfiles.h"
/* The name of the array in the GNAT runtime where the Ada Task Control
Block of each task is stored. */
@@ -131,18 +133,33 @@ struct atcb_fieldnos
int call_self;
};
-/* The type description for the ATCB record and subrecords, and
- the associated atcb_fieldnos. For efficiency reasons, these are made
- static globals so that we can compute them only once the first time
- and reuse them later. Set to NULL if the types haven't been computed
- yet, or if they may be obsolete (for instance after having loaded
- a new binary). */
+/* This module's per-program-space data. */
-static struct type *atcb_type = NULL;
-static struct type *atcb_common_type = NULL;
-static struct type *atcb_ll_type = NULL;
-static struct type *atcb_call_type = NULL;
-static struct atcb_fieldnos atcb_fieldno;
+struct ada_tasks_pspace_data
+{
+ /* Nonzero if the data has been initialized. If set to zero,
+ it means that the data has either not been initialized, or
+ has potentially become stale. */
+ int initialized_p;
+
+ /* The ATCB record type. */
+ struct type *atcb_type;
+
+ /* The ATCB "Common" component type. */
+ struct type *atcb_common_type;
+
+ /* The type of the "ll" field, from the atcb_common_type. */
+ struct type *atcb_ll_type;
+
+ /* The type of the "call" field, from the atcb_common_type. */
+ struct type *atcb_call_type;
+
+ /* The index of various fields in the ATCB record and sub-records. */
+ struct atcb_fieldnos atcb_fieldno;
+};
+
+/* Key to our per-program-space data. */
+static const struct program_space_data *ada_tasks_pspace_data_handle;
/* Set to 1 when the cached address of System.Tasking.Debug.Known_Tasks
might be stale and so needs to be recomputed. */
@@ -163,6 +180,26 @@ static VEC(ada_task_info_s) *task_list = NULL;
is obsolete, and should be recomputed before it is accessed. */
static int stale_task_list_p = 1;
+/* Return the ada-tasks module's data for the given program space (PSPACE).
+ If none is found, add a zero'ed one now.
+
+ This function always returns a valid object. */
+
+static struct ada_tasks_pspace_data *
+get_ada_tasks_pspace_data (struct program_space *pspace)
+{
+ struct ada_tasks_pspace_data *data;
+
+ data = program_space_data (pspace, ada_tasks_pspace_data_handle);
+ if (data == NULL)
+ {
+ data = XZALLOC (struct ada_tasks_pspace_data);
+ set_program_space_data (pspace, ada_tasks_pspace_data_handle, data);
+ }
+
+ return data;
+}
+
/* Return the task number of the task whose ptid is PTID, or zero
if the task could not be found. */
@@ -323,6 +360,7 @@ get_tcb_types_info (void)
struct type *ll_type;
struct type *call_type;
struct atcb_fieldnos fieldnos;
+ struct ada_tasks_pspace_data *pspace_data;
const char *atcb_name = "system__tasking__ada_task_control_block___XVE";
const char *atcb_name_fixed = "system__tasking__ada_task_control_block";
@@ -412,11 +450,13 @@ get_tcb_types_info (void)
/* Set all the out parameters all at once, now that we are certain
that there are no potential error() anymore. */
- atcb_type = type;
- atcb_common_type = common_type;
- atcb_ll_type = ll_type;
- atcb_call_type = call_type;
- atcb_fieldno = fieldnos;
+ pspace_data = get_ada_tasks_pspace_data (current_program_space);
+ pspace_data->initialized_p = 1;
+ pspace_data->atcb_type = type;
+ pspace_data->atcb_common_type = common_type;
+ pspace_data->atcb_ll_type = ll_type;
+ pspace_data->atcb_call_type = call_type;
+ pspace_data->atcb_fieldno = fieldnos;
}
/* Build the PTID of the task from its COMMON_VALUE, which is the "Common"
@@ -430,12 +470,16 @@ ptid_from_atcb_common (struct value *common_value)
CORE_ADDR lwp = 0;
struct value *ll_value;
ptid_t ptid;
+ const struct ada_tasks_pspace_data *pspace_data
+ = get_ada_tasks_pspace_data (current_program_space);
- ll_value = value_field (common_value, atcb_fieldno.ll);
+ ll_value = value_field (common_value, pspace_data->atcb_fieldno.ll);
- if (atcb_fieldno.ll_lwp >= 0)
- lwp = value_as_address (value_field (ll_value, atcb_fieldno.ll_lwp));
- thread = value_as_long (value_field (ll_value, atcb_fieldno.ll_thread));
+ if (pspace_data->atcb_fieldno.ll_lwp >= 0)
+ lwp = value_as_address (value_field (ll_value,
+ pspace_data->atcb_fieldno.ll_lwp));
+ thread = value_as_long (value_field (ll_value,
+ pspace_data->atcb_fieldno.ll_thread));
ptid = target_get_ada_task_ptid (lwp, thread);
@@ -456,12 +500,15 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
struct value *entry_calls_value_element;
int called_task_fieldno = -1;
const char ravenscar_task_name[] = "Ravenscar task";
+ const struct ada_tasks_pspace_data *pspace_data
+ = get_ada_tasks_pspace_data (current_program_space);
- if (atcb_type == NULL)
+ if (!pspace_data->initialized_p)
get_tcb_types_info ();
- tcb_value = value_from_contents_and_address (atcb_type, NULL, task_id);
- common_value = value_field (tcb_value, atcb_fieldno.common);
+ tcb_value = value_from_contents_and_address (pspace_data->atcb_type,
+ NULL, task_id);
+ common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common);
/* Fill in the task_id. */
@@ -482,37 +529,44 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
we may want to get it from the first user frame of the stack. For now,
we just give a dummy name. */
- if (atcb_fieldno.image_len == -1)
+ if (pspace_data->atcb_fieldno.image_len == -1)
{
- if (atcb_fieldno.image >= 0)
+ if (pspace_data->atcb_fieldno.image >= 0)
read_fat_string_value (task_info->name,
- value_field (common_value, atcb_fieldno.image),
+ value_field (common_value,
+ pspace_data->atcb_fieldno.image),
sizeof (task_info->name) - 1);
else
strcpy (task_info->name, ravenscar_task_name);
}
else
{
- int len = value_as_long (value_field (common_value,
- atcb_fieldno.image_len));
+ int len = value_as_long
+ (value_field (common_value,
+ pspace_data->atcb_fieldno.image_len));
value_as_string (task_info->name,
- value_field (common_value, atcb_fieldno.image), len);
+ value_field (common_value,
+ pspace_data->atcb_fieldno.image),
+ len);
}
/* Compute the task state and priority. */
task_info->state =
- value_as_long (value_field (common_value, atcb_fieldno.state));
+ value_as_long (value_field (common_value,
+ pspace_data->atcb_fieldno.state));
task_info->priority =
- value_as_long (value_field (common_value, atcb_fieldno.priority));
+ value_as_long (value_field (common_value,
+ pspace_data->atcb_fieldno.priority));
/* If the ATCB contains some information about the parent task,
then compute it as well. Otherwise, zero. */
- if (atcb_fieldno.parent >= 0)
+ if (pspace_data->atcb_fieldno.parent >= 0)
task_info->parent =
- value_as_address (value_field (common_value, atcb_fieldno.parent));
+ value_as_address (value_field (common_value,
+ pspace_data->atcb_fieldno.parent));
else
task_info->parent = 0;
@@ -520,16 +574,17 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
/* If the ATCB contains some information about entry calls, then
compute the "called_task" as well. Otherwise, zero. */
- if (atcb_fieldno.atc_nesting_level > 0 && atcb_fieldno.entry_calls > 0)
+ if (pspace_data->atcb_fieldno.atc_nesting_level > 0
+ && pspace_data->atcb_fieldno.entry_calls > 0)
{
/* Let My_ATCB be the Ada task control block of a task calling the
entry of another task; then the Task_Id of the called task is
in My_ATCB.Entry_Calls (My_ATCB.ATC_Nesting_Level).Called_Task. */
- atc_nesting_level_value = value_field (tcb_value,
- atcb_fieldno.atc_nesting_level);
+ atc_nesting_level_value =
+ value_field (tcb_value, pspace_data->atcb_fieldno.atc_nesting_level);
entry_calls_value =
- ada_coerce_to_simple_array_ptr (value_field (tcb_value,
- atcb_fieldno.entry_calls));
+ ada_coerce_to_simple_array_ptr
+ (value_field (tcb_value, pspace_data->atcb_fieldno.entry_calls));
entry_calls_value_element =
value_subscript (entry_calls_value,
value_as_long (atc_nesting_level_value));
@@ -549,20 +604,23 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
then compute the "caller_task". Otherwise, zero. */
task_info->caller_task = 0;
- if (atcb_fieldno.call >= 0)
+ if (pspace_data->atcb_fieldno.call >= 0)
{
/* Get the ID of the caller task from Common_ATCB.Call.all.Self.
If Common_ATCB.Call is null, then there is no caller. */
const CORE_ADDR call =
- value_as_address (value_field (common_value, atcb_fieldno.call));
+ value_as_address (value_field (common_value,
+ pspace_data->atcb_fieldno.call));
struct value *call_val;
if (call != 0)
{
call_val =
- value_from_contents_and_address (atcb_call_type, NULL, call);
+ value_from_contents_and_address (pspace_data->atcb_call_type,
+ NULL, call);
task_info->caller_task =
- value_as_address (value_field (call_val, atcb_fieldno.call_self));
+ value_as_address
+ (value_field (call_val, pspace_data->atcb_fieldno.call_self));
}
}
@@ -637,9 +695,11 @@ read_known_tasks_list (CORE_ADDR known_tasks_addr)
struct type *data_ptr_type =
builtin_type (target_gdbarch)->builtin_data_ptr;
CORE_ADDR task_id;
+ const struct ada_tasks_pspace_data *pspace_data
+ = get_ada_tasks_pspace_data (current_program_space);
/* Sanity check. */
- if (atcb_fieldno.activation_link < 0)
+ if (pspace_data->atcb_fieldno.activation_link < 0)
return 0;
/* Build a new list by reading the ATCBs. Read head of the list. */
@@ -653,10 +713,12 @@ read_known_tasks_list (CORE_ADDR known_tasks_addr)
add_ada_task (task_id);
/* Read the chain. */
- tcb_value = value_from_contents_and_address (atcb_type, NULL, task_id);
- common_value = value_field (tcb_value, atcb_fieldno.common);
- task_id = value_as_address (value_field (common_value,
- atcb_fieldno.activation_link));
+ tcb_value = value_from_contents_and_address (pspace_data->atcb_type,
+ NULL, task_id);
+ common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common);
+ task_id = value_as_address
+ (value_field (common_value,
+ pspace_data->atcb_fieldno.activation_link));
}
return 1;
@@ -1030,6 +1092,14 @@ ada_task_list_changed (void)
stale_task_list_p = 1;
}
+/* Invalidate the per-program-space data. */
+
+static void
+ada_tasks_invalidate_pspace_data (struct program_space *pspace)
+{
+ get_ada_tasks_pspace_data (pspace)->initialized_p = 0;
+}
+
/* The 'normal_stop' observer notification callback. */
static void
@@ -1045,14 +1115,25 @@ ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2)
static void
ada_new_objfile_observer (struct objfile *objfile)
{
- /* Invalidate all cached data that were extracted from an objfile. */
+ ada_tasks_check_symbol_table = 1;
- atcb_type = NULL;
- atcb_common_type = NULL;
- atcb_ll_type = NULL;
- atcb_call_type = NULL;
+ /* Invalidate the relevant data in our program-space data. */
- ada_tasks_check_symbol_table = 1;
+ if (objfile == NULL)
+ {
+ /* All objfiles are being cleared, so we should clear all
+ our caches for all program spaces. */
+ struct program_space *pspace;
+
+ for (pspace = program_spaces; pspace != NULL; pspace = pspace->next)
+ ada_tasks_invalidate_pspace_data (pspace);
+ }
+ else
+ {
+ /* The associated program-space data might have changed after
+ this objfile was added. Invalidate all cached data. */
+ ada_tasks_invalidate_pspace_data (objfile->pspace);
+ }
}
/* Provide a prototype to silence -Wmissing-prototypes. */
@@ -1061,6 +1142,8 @@ extern initialize_file_ftype _initialize_tasks;
void
_initialize_tasks (void)
{
+ ada_tasks_pspace_data_handle = register_program_space_data ();
+
/* Attach various observers. */
observer_attach_normal_stop (ada_normal_stop_observer);
observer_attach_new_objfile (ada_new_objfile_observer);