* symfile.h (quick_symbol_functions): Clarify usage of
[deliverable/binutils-gdb.git] / gdb / ada-tasks.c
index 17671b30185278d306fb08cccf33f19a92608328..90502e8c80b8fba537fa94fa404a2e48f3b73014 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004,
-   2005, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005,
+   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -49,47 +49,53 @@ enum task_states
   Timer_Server_Sleep,
   AST_Server_Sleep,
   Asynchronous_Hold,
-  Interrupt_Server_Blocked_On_Event_Flag
+  Interrupt_Server_Blocked_On_Event_Flag,
+  Activating,
+  Acceptor_Delay_Sleep
 };
 
 /* A short description corresponding to each possible task state.  */
-static char *task_states[] = {
-  _("Unactivated"),
-  _("Runnable"),
-  _("Terminated"),
-  _("Child Activation Wait"),
-  _("Accept Statement"),
-  _("Waiting on entry call"),
-  _("Async Select Wait"),
-  _("Delay Sleep"),
-  _("Child Termination Wait"),
-  _("Wait Child in Term Alt"),
+static const char *task_states[] = {
+  N_("Unactivated"),
+  N_("Runnable"),
+  N_("Terminated"),
+  N_("Child Activation Wait"),
+  N_("Accept or Select Term"),
+  N_("Waiting on entry call"),
+  N_("Async Select Wait"),
+  N_("Delay Sleep"),
+  N_("Child Termination Wait"),
+  N_("Wait Child in Term Alt"),
   "",
   "",
   "",
   "",
-  _("Asynchronous Hold"),
-  ""
+  N_("Asynchronous Hold"),
+  "",
+  N_("Activating"),
+  N_("Selective Wait")
 };
 
 /* A longer description corresponding to each possible task state.  */
-static char *long_task_states[] = {
-  _("Unactivated"),
-  _("Runnable"),
-  _("Terminated"),
-  _("Waiting for child activation"),
-  _("Blocked in accept statement"),
-  _("Waiting on entry call"),
-  _("Asynchronous Selective Wait"),
-  _("Delay Sleep"),
-  _("Waiting for children termination"),
-  _("Waiting for children in terminate alternative"),
+static const char *long_task_states[] = {
+  N_("Unactivated"),
+  N_("Runnable"),
+  N_("Terminated"),
+  N_("Waiting for child activation"),
+  N_("Blocked in accept or select with terminate"),
+  N_("Waiting on entry call"),
+  N_("Asynchronous Selective Wait"),
+  N_("Delay Sleep"),
+  N_("Waiting for children termination"),
+  N_("Waiting for children in terminate alternative"),
+  "",
   "",
   "",
   "",
+  N_("Asynchronous Hold"),
   "",
-  _("Asynchronous Hold"),
-  ""
+  N_("Activating"),
+  N_("Blocked in selective wait statement")
 };
 
 /* The index of certain important fields in the Ada Task Control Block
@@ -192,24 +198,18 @@ get_task_number_from_id (CORE_ADDR task_id)
 int
 valid_task_id (int task_num)
 {
+  ada_build_task_list (0);
   return (task_num > 0
           && task_num <= VEC_length (ada_task_info_s, task_list));
 }
 
-/* Return the task info associated to the Environment Task.
-   This function assumes that the inferior does in fact use tasking.  */
+/* Return non-zero iff the task STATE corresponds to a non-terminated
+   task state.  */
 
-struct ada_task_info *
-ada_get_environment_task (void)
+static int
+ada_task_is_alive (struct ada_task_info *task_info)
 {
-  ada_build_task_list (0);
-  gdb_assert (VEC_length (ada_task_info_s, task_list) > 0);
-
-  /* We use a little bit of insider knowledge to determine which task
-     is the Environment Task:  We know that this task is created first,
-     and thus should always be task #1, which is at index 0 of the
-     TASK_LIST.  */
-  return (VEC_index (ada_task_info_s, task_list, 0));
+  return (task_info->state != Terminated);
 }
 
 /* Call the ITERATOR function once for each Ada task that hasn't been
@@ -293,7 +293,7 @@ read_fat_string_value (char *dest, struct value *val, int max_len)
 
   /* Extract LEN characters from the fat string.  */
   array_val = value_ind (value_field (val, array_fieldno));
-  read_memory (VALUE_ADDRESS (array_val), dest, len);
+  read_memory (value_address (array_val), dest, len);
 
   /* Add the NUL character to close the string.  */
   dest[len] = '\0';
@@ -314,7 +314,6 @@ get_known_tasks_addr (void)
 
   if (ada_tasks_check_symbol_table)
     {
-      struct symbol *sym;
       struct minimal_symbol *msym;
 
       msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
@@ -381,20 +380,29 @@ get_tcb_types_info (struct type **atcb_type,
   const char *private_data_name = "system__task_primitives__private_data";
   const char *entry_call_record_name = "system__tasking__entry_call_record";
 
+  /* ATCB symbols may be found in several compilation units. As we
+     are only interested in one instance, use standard (literal,
+     C-like) lookups to get the first match.  */
+
   struct symbol *atcb_sym =
-    lookup_symbol (atcb_name, NULL, VAR_DOMAIN, NULL);
+    lookup_symbol_in_language (atcb_name, NULL, VAR_DOMAIN,
+                              language_c, NULL);
   const struct symbol *common_atcb_sym =
-    lookup_symbol (common_atcb_name, NULL, VAR_DOMAIN, NULL);
+    lookup_symbol_in_language (common_atcb_name, NULL, VAR_DOMAIN,
+                              language_c, NULL);
   const struct symbol *private_data_sym =
-    lookup_symbol (private_data_name, NULL, VAR_DOMAIN, NULL);
+    lookup_symbol_in_language (private_data_name, NULL, VAR_DOMAIN,
+                              language_c, NULL);
   const struct symbol *entry_call_record_sym =
-    lookup_symbol (entry_call_record_name, NULL, VAR_DOMAIN, NULL);
+    lookup_symbol_in_language (entry_call_record_name, NULL, VAR_DOMAIN,
+                              language_c, NULL);
 
   if (atcb_sym == NULL || atcb_sym->type == NULL)
     {
       /* In Ravenscar run-time libs, the  ATCB does not have a dynamic
          size, so the symbol name differs.  */
-      atcb_sym = lookup_symbol (atcb_name_fixed, NULL, VAR_DOMAIN, NULL);
+      atcb_sym = lookup_symbol_in_language (atcb_name_fixed, NULL, VAR_DOMAIN,
+                                           language_c, NULL);
 
       if (atcb_sym == NULL || atcb_sym->type == NULL)
         error (_("Cannot find Ada_Task_Control_Block type. Aborting"));
@@ -570,7 +578,8 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
         ada_coerce_to_simple_array_ptr (value_field (tcb_value,
                                                      fieldno.entry_calls));
       entry_calls_value_element =
-        value_subscript (entry_calls_value, atc_nesting_level_value);
+        value_subscript (entry_calls_value,
+                        value_as_long (atc_nesting_level_value));
       called_task_fieldno =
         ada_get_field_index (value_type (entry_calls_value_element),
                              "called_task", 0);
@@ -604,9 +613,18 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
         }
     }
 
-  /* And finally, compute the task ptid.  */
-
-  if (ada_task_is_alive (task_info))
+  /* And finally, compute the task ptid.  Note that there are situations
+     where this cannot be determined:
+       - The task is no longer alive - the ptid is irrelevant;
+       - We are debugging a core file - the thread is not always
+         completely preserved for us to link back a task to its
+         underlying thread.  Since we do not support task switching
+         when debugging core files anyway, we don't need to compute
+         that task ptid.
+     In either case, we don't need that ptid, and it is just good enough
+     to set it to null_ptid.  */
+
+  if (target_has_execution && ada_task_is_alive (task_info))
     task_info->ptid = ptid_from_atcb_common (common_value);
   else
     task_info->ptid = null_ptid;
@@ -631,7 +649,7 @@ static int
 read_known_tasks_array (void)
 {
   const int target_ptr_byte =
-    gdbarch_ptr_bit (current_gdbarch) / TARGET_CHAR_BIT;
+    gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT;
   const CORE_ADDR known_tasks_addr = get_known_tasks_addr ();
   const int known_tasks_size = target_ptr_byte * MAX_NUMBER_OF_KNOWN_TASKS;
   gdb_byte *known_tasks = alloca (known_tasks_size);
@@ -654,7 +672,7 @@ read_known_tasks_array (void)
   for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
     {
       struct type *data_ptr_type =
-        builtin_type (current_gdbarch)->builtin_data_ptr;
+        builtin_type (target_gdbarch)->builtin_data_ptr;
       CORE_ADDR task_id =
         extract_typed_address (known_tasks + i * target_ptr_byte,
                               data_ptr_type);
@@ -693,15 +711,6 @@ ada_build_task_list (int warn_if_null)
   return 1;
 }
 
-/* Return non-zero iff the task STATE corresponds to a non-terminated
-   task state.  */
-
-int
-ada_task_is_alive (struct ada_task_info *task_info)
-{
-  return (task_info->state != Terminated);
-}
-
 /* Print a one-line description of the task whose number is TASKNO.
    The formatting should fit the "info tasks" array.  */
 
@@ -742,11 +751,8 @@ short_task_info (int taskno)
   else if (task_info->state == Entry_Caller_Sleep && task_info->called_task)
     printf_filtered (_(" Waiting on RV with %-3d"),
                      get_task_number_from_id (task_info->called_task));
-  else if (task_info->state == Runnable && active_task_p)
-    /* Replace "Runnable" by "Running" since this is the active task.  */
-    printf_filtered (" %-22s", "Running");
   else
-    printf_filtered (" %-22s", task_states[task_info->state]);
+    printf_filtered (" %-22s", _(task_states[task_info->state]));
 
   /* Finally, print the task name.  */
   if (task_info->name[0] != '\0')
@@ -785,7 +791,8 @@ info_task (char *taskno_str, int from_tty)
   task_info = VEC_index (ada_task_info_s, task_list, taskno - 1);
 
   /* Print the Ada task ID.  */
-  printf_filtered (_("Ada Task: %s\n"), paddr_nz (task_info->task_id));
+  printf_filtered (_("Ada Task: %s\n"),
+                  paddress (target_gdbarch, task_info->task_id));
 
   /* Print the name of the task.  */
   if (task_info->name[0] != '\0')
@@ -833,7 +840,7 @@ info_task (char *taskno_str, int from_tty)
                          target_taskno);
       }
     else
-      printf_filtered ("State: %s", long_task_states[task_info->state]);
+      printf_filtered (_("State: %s"), _(long_task_states[task_info->state]));
 
     if (target_taskno)
       {
@@ -899,6 +906,28 @@ task_command_1 (char *taskno_str, int from_tty)
   if (!ada_task_is_alive (task_info))
     error (_("Cannot switch to task %d: Task is no longer running"), taskno);
    
+  /* On some platforms, the thread list is not updated until the user
+     performs a thread-related operation (by using the "info threads"
+     command, for instance).  So this thread list may not be up to date
+     when the user attempts this task switch.  Since we cannot switch
+     to the thread associated to our task if GDB does not know about
+     that thread, we need to make sure that any new threads gets added
+     to the thread list.  */
+  target_find_new_threads ();
+
+  /* Verify that the ptid of the task we want to switch to is valid
+     (in other words, a ptid that GDB knows about).  Otherwise, we will
+     cause an assertion failure later on, when we try to determine
+     the ptid associated thread_info data.  We should normally never
+     encounter such an error, but the wrong ptid can actually easily be
+     computed if target_get_ada_task_ptid has not been implemented for
+     our target (yet).  Rather than cause an assertion error in that case,
+     it's nicer for the user to just refuse to perform the task switch.  */
+  if (!find_thread_ptid (task_info->ptid))
+    error (_("Unable to compute thread ID for task %d.\n"
+             "Cannot switch to this task."),
+           taskno);
+
   switch_to_thread (task_info->ptid);
   ada_find_printable_frame (get_selected_frame (NULL));
   printf_filtered (_("[Switching to task %d]\n"), taskno);
@@ -942,7 +971,7 @@ Task switching not supported when debugging from core files\n\
 
 /* Indicate that the task list may have changed, so invalidate the cache.  */
 
-void
+static void
 ada_task_list_changed (void)
 {
   stale_task_list_p = 1;  
@@ -951,7 +980,7 @@ ada_task_list_changed (void)
 /* The 'normal_stop' observer notification callback.  */
 
 static void
-ada_normal_stop_observer (struct bpstats *unused_args)
+ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2)
 {
   /* The inferior has been resumed, and just stopped. This means that
      our task_list needs to be recomputed before it can be used again.  */
@@ -960,7 +989,7 @@ ada_normal_stop_observer (struct bpstats *unused_args)
 
 /* A routine to be called when the objfiles have changed.  */
 
-void
+static void
 ada_new_objfile_observer (struct objfile *objfile)
 {
   /* Invalidate all cached data that were extracted from an objfile.  */
@@ -973,6 +1002,9 @@ ada_new_objfile_observer (struct objfile *objfile)
   ada_tasks_check_symbol_table = 1;
 }
 
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_tasks;
+
 void
 _initialize_tasks (void)
 {
This page took 0.02841 seconds and 4 git commands to generate.