-/* Copyright (C) 1992-2019 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbthread.h"
#include "progspace.h"
#include "objfiles.h"
+#include "cli/cli-style.h"
static int ada_build_task_list ();
/* 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;
+ int initialized_p = 0;
/* The ATCB record type. */
- struct type *atcb_type;
+ struct type *atcb_type = nullptr;
/* The ATCB "Common" component type. */
- struct type *atcb_common_type;
+ struct type *atcb_common_type = nullptr;
/* The type of the "ll" field, from the atcb_common_type. */
- struct type *atcb_ll_type;
+ struct type *atcb_ll_type = nullptr;
/* The type of the "call" field, from the atcb_common_type. */
- struct type *atcb_call_type;
+ struct type *atcb_call_type = nullptr;
/* The index of various fields in the ATCB record and sub-records. */
- struct atcb_fieldnos atcb_fieldno;
+ struct atcb_fieldnos atcb_fieldno {};
};
/* Key to our per-program-space data. */
-static const struct program_space_data *ada_tasks_pspace_data_handle;
-
-/* A cleanup routine for our per-program-space data. */
-static void
-ada_tasks_pspace_data_cleanup (struct program_space *pspace, void *arg)
-{
- struct ada_tasks_pspace_data *data
- = (struct ada_tasks_pspace_data *) arg;
- xfree (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. */
};
/* Key to our per-inferior data. */
-static const struct inferior_data *ada_tasks_inferior_data_handle;
+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.
{
struct ada_tasks_pspace_data *data;
- data = ((struct ada_tasks_pspace_data *)
- program_space_data (pspace, ada_tasks_pspace_data_handle));
+ data = ada_tasks_pspace_data_handle.get (pspace);
if (data == NULL)
- {
- data = XCNEW (struct ada_tasks_pspace_data);
- set_program_space_data (pspace, ada_tasks_pspace_data_handle, data);
- }
+ data = ada_tasks_pspace_data_handle.emplace (pspace);
return data;
}
{
struct ada_tasks_inferior_data *data;
- data = ((struct ada_tasks_inferior_data *)
- inferior_data (inf, ada_tasks_inferior_data_handle));
+ data = ada_tasks_inferior_data_handle.get (inf);
if (data == NULL)
- {
- data = new ada_tasks_inferior_data;
- set_inferior_data (inf, ada_tasks_inferior_data_handle, data);
- }
+ data = ada_tasks_inferior_data_handle.emplace (inf);
return data;
}
-/* A cleanup routine for our per-inferior data. */
-static void
-ada_tasks_inferior_data_cleanup (struct inferior *inf, void *arg)
-{
- struct ada_tasks_inferior_data *data
- = (struct ada_tasks_inferior_data *) arg;
- delete data;
-}
-
/* Return the task number of the task whose thread is THREAD, or zero
if the task could not be found. */
task state. */
static int
-ada_task_is_alive (struct ada_task_info *task_info)
+ada_task_is_alive (const struct ada_task_info *task_info)
{
return (task_info->state != Terminated);
}
}
/* Read the ATCB data of a given task given its TASK_ID (which is in practice
- the address of its assocated ATCB record), and store the result inside
+ the address of its associated ATCB record), and store the result inside
TASK_INFO. */
static void
msym = lookup_minimal_symbol_by_pc (task_id);
if (msym.minsym)
{
- const char *full_name = MSYMBOL_LINKAGE_NAME (msym.minsym);
+ const char *full_name = msym.minsym->linkage_name ();
const char *task_name = full_name;
const char *p;
called_task_fieldno));
}
- /* If the ATCB cotnains some information about RV callers, then
+ /* If the ATCB contains some information about RV callers, then
compute the "caller_task". Otherwise, leave it as zero. */
if (pspace_data->atcb_fieldno.call >= 0)
void
print_ada_task_info (struct ui_out *uiout,
- char *arg_str,
+ const char *arg_str,
struct inferior *inf)
{
struct ada_tasks_inferior_data *data;
ui_out_emit_table table_emitter (uiout, nb_columns, nb_tasks, "tasks");
uiout->table_header (1, ui_left, "current", "");
uiout->table_header (3, ui_right, "id", "ID");
- uiout->table_header (9, ui_right, "task-id", "TID");
+ {
+ size_t tid_width = 9;
+ /* Grown below in case the largest entry is bigger. */
+
+ if (!uiout->is_mi_like_p ())
+ {
+ for (taskno = 1; taskno <= data->task_list.size (); taskno++)
+ {
+ const struct ada_task_info *const task_info
+ = &data->task_list[taskno - 1];
+
+ gdb_assert (task_info != NULL);
+
+ tid_width = std::max (tid_width,
+ 1 + strlen (phex_nz (task_info->task_id,
+ sizeof (CORE_ADDR))));
+ }
+ }
+ uiout->table_header (tid_width, ui_right, "task-id", "TID");
+ }
/* The following column is provided in GDB/MI mode only because
it is only really useful in that mode, and also because it
allows us to keep the CLI output shorter and more compact. */
uiout->field_skip ("current");
/* Print the task number. */
- uiout->field_int ("id", taskno);
+ uiout->field_signed ("id", taskno);
/* Print the Task ID. */
- uiout->field_fmt ("task-id", "%9lx", (long) task_info->task_id);
+ uiout->field_string ("task-id", phex_nz (task_info->task_id,
+ sizeof (CORE_ADDR)));
/* Print the associated Thread ID. */
if (uiout->is_mi_like_p ())
{
- thread_info *thread = find_thread_ptid (task_info->ptid);
+ thread_info *thread = (ada_task_is_alive (task_info)
+ ? find_thread_ptid (task_info->ptid)
+ : nullptr);
if (thread != NULL)
- uiout->field_int ("thread-id", thread->global_num);
+ uiout->field_signed ("thread-id", thread->global_num);
else
- /* This should never happen unless there is a bug somewhere,
- but be resilient when that happens. */
- uiout->field_skip ("thread-id");
+ {
+ /* This can happen if the thread is no longer alive. */
+ uiout->field_skip ("thread-id");
+ }
}
/* Print the ID of the parent task. */
parent_id = get_task_number_from_id (task_info->parent, inf);
if (parent_id)
- uiout->field_int ("parent-id", parent_id);
+ uiout->field_signed ("parent-id", parent_id);
else
uiout->field_skip ("parent-id");
/* Print the base priority of the task. */
- uiout->field_int ("priority", task_info->priority);
+ uiout->field_signed ("priority", task_info->priority);
/* Print the task current state. */
if (task_info->caller_task)
else
uiout->field_string ("state", task_states[task_info->state]);
- /* Finally, print the task name. */
+ /* Finally, print the task name, without quotes around it, as mi like
+ is not expecting quotes, and in non mi-like no need for quotes
+ as there is a specific column for the name. */
uiout->field_fmt ("name",
+ (task_info->name[0] != '\0'
+ ? ui_file_style ()
+ : metadata_style.style ()),
"%s",
- task_info->name[0] != '\0' ? task_info->name
- : _("<no name>"));
+ (task_info->name[0] != '\0'
+ ? task_info->name
+ : _("<no name>")));
uiout->text ("\n");
}
if (task_info->name[0] != '\0')
printf_filtered (_("Name: %s\n"), task_info->name);
else
- printf_filtered (_("<no name>\n"));
+ fprintf_styled (gdb_stdout, metadata_style.style (), _("<no name>\n"));
/* Print the TID and LWP. */
printf_filtered (_("Thread: %#lx\n"), task_info->ptid.tid ());
if (current_task == 0)
printf_filtered (_("[Current task is unknown]\n"));
else
- printf_filtered (_("[Current task is %d]\n"), current_task);
+ {
+ struct ada_tasks_inferior_data *data
+ = get_ada_tasks_inferior_data (current_inferior ());
+ struct ada_task_info *task_info = &data->task_list[current_task - 1];
+
+ printf_filtered (_("[Current task is %s]\n"),
+ task_to_str (current_task, task_info).c_str ());
+ }
}
/* Parse and evaluate TIDSTR into a task id, and try to switch to
task_info = &data->task_list[taskno - 1];
if (!ada_task_is_alive (task_info))
- error (_("Cannot switch to task %d: Task is no longer running"), taskno);
+ error (_("Cannot switch to task %s: Task is no longer running"),
+ task_to_str (taskno, task_info).c_str ());
/* On some platforms, the thread list is not updated until the user
performs a thread-related operation (by using the "info threads"
it's nicer for the user to just refuse to perform the task switch. */
thread_info *tp = find_thread_ptid (task_info->ptid);
if (tp == NULL)
- error (_("Unable to compute thread ID for task %d.\n"
+ error (_("Unable to compute thread ID for task %s.\n"
"Cannot switch to this task."),
- taskno);
+ task_to_str (taskno, task_info).c_str ());
switch_to_thread (tp);
ada_find_printable_frame (get_selected_frame (NULL));
- printf_filtered (_("[Switching to task %d]\n"), taskno);
+ printf_filtered (_("[Switching to task %s]\n"),
+ task_to_str (taskno, task_info).c_str ());
print_stack_frame (get_selected_frame (NULL),
frame_relative_level (get_selected_frame (NULL)),
SRC_AND_LOC, 1);
void
_initialize_tasks (void)
{
- ada_tasks_pspace_data_handle
- = register_program_space_data_with_cleanup (NULL,
- ada_tasks_pspace_data_cleanup);
- ada_tasks_inferior_data_handle
- = register_inferior_data_with_cleanup (NULL,
- ada_tasks_inferior_data_cleanup);
-
/* Attach various observers. */
gdb::observers::normal_stop.attach (ada_tasks_normal_stop_observer);
gdb::observers::new_objfile.attach (ada_tasks_new_objfile_observer);
/* Some new commands provided by this module. */
add_info ("tasks", info_tasks_command,
- _("Provide information about all known Ada tasks"));
+ _("Provide information about all known Ada tasks."));
add_cmd ("task", class_run, task_command,
_("Use this command to switch between Ada tasks.\n\
-Without argument, this command simply prints the current task ID"),
+Without argument, this command simply prints the current task ID."),
&cmdlist);
}