+ /* The ATCB "Common" component type. */
+ struct type *atcb_common_type = nullptr;
+
+ /* The type of the "ll" field, from the atcb_common_type. */
+ struct type *atcb_ll_type = nullptr;
+
+ /* The type of the "call" field, from the atcb_common_type. */
+ struct type *atcb_call_type = nullptr;
+
+ /* 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_key<ada_tasks_pspace_data>
+ ada_tasks_pspace_data_handle;
+
+/* The kind of data structure used by the runtime to store the list
+ of Ada tasks. */
+
+enum ada_known_tasks_kind
+{
+ /* Use this value when we haven't determined which kind of structure
+ is being used, or when we need to recompute it.
+
+ We set the value of this enumerate to zero on purpose: This allows
+ us to use this enumerate in a structure where setting all fields
+ to zero will result in this kind being set to unknown. */
+ ADA_TASKS_UNKNOWN = 0,
+
+ /* This value means that we did not find any task list. Unless
+ there is a bug somewhere, this means that the inferior does not
+ use tasking. */
+ ADA_TASKS_NOT_FOUND,
+
+ /* This value means that the task list is stored as an array.
+ This is the usual method, as it causes very little overhead.
+ But this method is not always used, as it does use a certain
+ amount of memory, which might be scarse in certain environments. */
+ ADA_TASKS_ARRAY,
+
+ /* This value means that the task list is stored as a linked list.
+ This has more runtime overhead than the array approach, but
+ also require less memory when the number of tasks is small. */
+ ADA_TASKS_LIST,
+};
+
+/* This module's per-inferior data. */
+
+struct ada_tasks_inferior_data
+{
+ /* The type of data structure used by the runtime to store
+ the list of Ada tasks. The value of this field influences
+ the interpretation of the known_tasks_addr field below:
+ - ADA_TASKS_UNKNOWN: The value of known_tasks_addr hasn't
+ been determined yet;
+ - ADA_TASKS_NOT_FOUND: The program probably does not use tasking
+ and the known_tasks_addr is irrelevant;
+ - ADA_TASKS_ARRAY: The known_tasks is an array;
+ - ADA_TASKS_LIST: The known_tasks is a list. */
+ enum ada_known_tasks_kind known_tasks_kind = ADA_TASKS_UNKNOWN;
+
+ /* The address of the known_tasks structure. This is where
+ the runtime stores the information for all Ada tasks.
+ The interpretation of this field depends on KNOWN_TASKS_KIND
+ above. */
+ CORE_ADDR known_tasks_addr = 0;
+
+ /* Type of elements of the known task. Usually a pointer. */
+ struct type *known_tasks_element = nullptr;
+
+ /* Number of elements in the known tasks array. */
+ unsigned int known_tasks_length = 0;
+
+ /* When nonzero, this flag indicates that the task_list field
+ below is up to date. When set to zero, the list has either
+ not been initialized, or has potentially become stale. */
+ bool task_list_valid_p = false;
+
+ /* The list of Ada tasks.
+
+ Note: To each task we associate a number that the user can use to
+ reference it - this number is printed beside each task in the tasks
+ info listing displayed by "info tasks". This number is equal to
+ its index in the vector + 1. Reciprocally, to compute the index
+ of a task in the vector, we need to substract 1 from its number. */
+ std::vector<ada_task_info> task_list;
+};
+
+/* Key to our per-inferior data. */
+static const struct inferior_key<ada_tasks_inferior_data>
+ ada_tasks_inferior_data_handle;
+
+/* Return a string with TASKNO followed by the task name if TASK_INFO
+ contains a name. */
+
+static std::string
+task_to_str (int taskno, const ada_task_info *task_info)
+{
+ if (task_info->name[0] == '\0')
+ return string_printf ("%d", taskno);
+ else
+ return string_printf ("%d \"%s\"", taskno, task_info->name);
+}
+
+/* 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 = ada_tasks_pspace_data_handle.get (pspace);
+ if (data == NULL)
+ data = ada_tasks_pspace_data_handle.emplace (pspace);
+
+ return data;
+}
+
+/* Return the ada-tasks module's data for the given inferior (INF).
+ If none is found, add a zero'ed one now.
+
+ This function always returns a valid object.
+
+ Note that we could use an observer of the inferior-created event
+ to make sure that the ada-tasks per-inferior data always exists.
+ But we prefered this approach, as it avoids this entirely as long
+ as the user does not use any of the tasking features. This is
+ quite possible, particularly in the case where the inferior does
+ not use tasking. */
+
+static struct ada_tasks_inferior_data *
+get_ada_tasks_inferior_data (struct inferior *inf)
+{
+ struct ada_tasks_inferior_data *data;
+
+ data = ada_tasks_inferior_data_handle.get (inf);
+ if (data == NULL)
+ data = ada_tasks_inferior_data_handle.emplace (inf);
+
+ return data;
+}
+
+/* Return the task number of the task whose thread is THREAD, or zero