1c50c785cSJohn Marino /* Ada Ravenscar thread support.
2c50c785cSJohn Marino 
3*ef5ccd6cSJohn Marino    Copyright (C) 2004-2013 Free Software Foundation, Inc.
4c50c785cSJohn Marino 
5c50c785cSJohn Marino    This file is part of GDB.
6c50c785cSJohn Marino 
7c50c785cSJohn Marino    This program is free software; you can redistribute it and/or modify
8c50c785cSJohn Marino    it under the terms of the GNU General Public License as published by
9c50c785cSJohn Marino    the Free Software Foundation; either version 3 of the License, or
10c50c785cSJohn Marino    (at your option) any later version.
11c50c785cSJohn Marino 
12c50c785cSJohn Marino    This program is distributed in the hope that it will be useful,
13c50c785cSJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
14c50c785cSJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c50c785cSJohn Marino    GNU General Public License for more details.
16c50c785cSJohn Marino 
17c50c785cSJohn Marino    You should have received a copy of the GNU General Public License
18c50c785cSJohn Marino    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19c50c785cSJohn Marino 
20c50c785cSJohn Marino #include "defs.h"
21c50c785cSJohn Marino #include "gdbcore.h"
22c50c785cSJohn Marino #include "gdbthread.h"
23c50c785cSJohn Marino #include "ada-lang.h"
24c50c785cSJohn Marino #include "target.h"
25c50c785cSJohn Marino #include "inferior.h"
26c50c785cSJohn Marino #include "command.h"
27c50c785cSJohn Marino #include "ravenscar-thread.h"
28c50c785cSJohn Marino #include "observer.h"
29c50c785cSJohn Marino #include "gdb_string.h"
30c50c785cSJohn Marino #include "gdbcmd.h"
31c50c785cSJohn Marino #include "top.h"
32c50c785cSJohn Marino #include "regcache.h"
33c50c785cSJohn Marino 
34c50c785cSJohn Marino /* If non-null, ravenscar task support is enabled.  */
35c50c785cSJohn Marino static int ravenscar_task_support = 1;
36c50c785cSJohn Marino 
37c50c785cSJohn Marino /* This module's target-specific operations.  */
38c50c785cSJohn Marino static struct target_ops ravenscar_ops;
39c50c785cSJohn Marino 
40c50c785cSJohn Marino /* Some base target uses a special value for the null PID (exempli gratia
41c50c785cSJohn Marino    remote).  */
42c50c785cSJohn Marino static ptid_t base_magic_null_ptid;
43c50c785cSJohn Marino 
44c50c785cSJohn Marino /* Ptid of the inferior as seen by the process stratum.  */
45c50c785cSJohn Marino static ptid_t base_ptid;
46c50c785cSJohn Marino 
47c50c785cSJohn Marino static const char running_thread_name[] = "__gnat_running_thread_table";
48c50c785cSJohn Marino 
49c50c785cSJohn Marino static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
50a45ae5f8SJohn Marino static const char first_task_name[] = "system__tasking__debug__first_task";
51c50c785cSJohn Marino 
52c50c785cSJohn Marino static const char ravenscar_runtime_initializer[] =
53c50c785cSJohn Marino   "system__bb__threads__initialize";
54c50c785cSJohn Marino 
55c50c785cSJohn Marino static struct observer *update_target_observer = NULL;
56c50c785cSJohn Marino 
57c50c785cSJohn Marino static void ravenscar_find_new_threads (struct target_ops *ops);
58c50c785cSJohn Marino static ptid_t ravenscar_running_thread (void);
59c50c785cSJohn Marino static char *ravenscar_extra_thread_info (struct thread_info *tp);
60c50c785cSJohn Marino static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
61c50c785cSJohn Marino static void ravenscar_fetch_registers (struct target_ops *ops,
62c50c785cSJohn Marino                                        struct regcache *regcache, int regnum);
63c50c785cSJohn Marino static void ravenscar_store_registers (struct target_ops *ops,
64c50c785cSJohn Marino                                        struct regcache *regcache, int regnum);
65c50c785cSJohn Marino static void ravenscar_prepare_to_store (struct regcache *regcache);
66c50c785cSJohn Marino static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
67*ef5ccd6cSJohn Marino 			      enum gdb_signal siggnal);
68c50c785cSJohn Marino static void ravenscar_mourn_inferior (struct target_ops *ops);
69c50c785cSJohn Marino static void ravenscar_update_inferior_ptid (void);
70c50c785cSJohn Marino static int has_ravenscar_runtime (void);
71c50c785cSJohn Marino static int ravenscar_runtime_initialized (void);
72c50c785cSJohn Marino static void ravenscar_inferior_created (struct target_ops *target,
73c50c785cSJohn Marino 					int from_tty);
74c50c785cSJohn Marino 
75c50c785cSJohn Marino /* Fetch the ravenscar running thread from target memory and
76c50c785cSJohn Marino    update inferior_ptid accordingly.  */
77c50c785cSJohn Marino 
78c50c785cSJohn Marino static void
ravenscar_update_inferior_ptid(void)79c50c785cSJohn Marino ravenscar_update_inferior_ptid (void)
80c50c785cSJohn Marino {
81c50c785cSJohn Marino   base_ptid = inferior_ptid;
82c50c785cSJohn Marino 
83c50c785cSJohn Marino   /* If the runtime has not been initialized yet, the inferior_ptid is
84c50c785cSJohn Marino      the only ptid that there is.  */
85c50c785cSJohn Marino   if (!ravenscar_runtime_initialized ())
86c50c785cSJohn Marino     return;
87c50c785cSJohn Marino 
88c50c785cSJohn Marino   /* Make sure we set base_ptid before calling ravenscar_running_thread
89c50c785cSJohn Marino      as the latter relies on it.  */
90c50c785cSJohn Marino   inferior_ptid = ravenscar_running_thread ();
91c50c785cSJohn Marino   gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
92c50c785cSJohn Marino 
93c50c785cSJohn Marino   /* The running thread may not have been added to
94c50c785cSJohn Marino      system.tasking.debug's list yet; so ravenscar_find_new_threads
95c50c785cSJohn Marino      may not always add it to the thread list.  Add it here.  */
96c50c785cSJohn Marino   if (!find_thread_ptid (inferior_ptid))
97c50c785cSJohn Marino     add_thread (inferior_ptid);
98c50c785cSJohn Marino }
99c50c785cSJohn Marino 
100c50c785cSJohn Marino /* The Ravenscar Runtime exports a symbol which contains the ID of
101c50c785cSJohn Marino    the thread that is currently running.  Try to locate that symbol
102c50c785cSJohn Marino    and return its associated minimal symbol.
103c50c785cSJohn Marino    Return NULL if not found.  */
104c50c785cSJohn Marino 
105c50c785cSJohn Marino static struct minimal_symbol *
get_running_thread_msymbol(void)106c50c785cSJohn Marino get_running_thread_msymbol (void)
107c50c785cSJohn Marino {
108c50c785cSJohn Marino   struct minimal_symbol *msym;
109c50c785cSJohn Marino 
110c50c785cSJohn Marino   msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
111c50c785cSJohn Marino   if (!msym)
112c50c785cSJohn Marino     /* Older versions of the GNAT runtime were using a different
113c50c785cSJohn Marino        (less ideal) name for the symbol where the active thread ID
114c50c785cSJohn Marino        is stored.  If we couldn't find the symbol using the latest
115c50c785cSJohn Marino        name, then try the old one.  */
116c50c785cSJohn Marino     msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
117c50c785cSJohn Marino 
118c50c785cSJohn Marino   return msym;
119c50c785cSJohn Marino }
120c50c785cSJohn Marino 
121c50c785cSJohn Marino /* Return True if the Ada Ravenscar run-time can be found in the
122c50c785cSJohn Marino    application.  */
123c50c785cSJohn Marino 
124c50c785cSJohn Marino static int
has_ravenscar_runtime(void)125c50c785cSJohn Marino has_ravenscar_runtime (void)
126c50c785cSJohn Marino {
127c50c785cSJohn Marino   struct minimal_symbol *msym_ravenscar_runtime_initializer =
128c50c785cSJohn Marino     lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
129c50c785cSJohn Marino   struct minimal_symbol *msym_known_tasks =
130c50c785cSJohn Marino     lookup_minimal_symbol (known_tasks_name, NULL, NULL);
131a45ae5f8SJohn Marino   struct minimal_symbol *msym_first_task =
132a45ae5f8SJohn Marino     lookup_minimal_symbol (first_task_name, NULL, NULL);
133c50c785cSJohn Marino   struct minimal_symbol *msym_running_thread = get_running_thread_msymbol ();
134c50c785cSJohn Marino 
135c50c785cSJohn Marino   return (msym_ravenscar_runtime_initializer
136a45ae5f8SJohn Marino 	  && (msym_known_tasks || msym_first_task)
137c50c785cSJohn Marino 	  && msym_running_thread);
138c50c785cSJohn Marino }
139c50c785cSJohn Marino 
140c50c785cSJohn Marino /* Return True if the Ada Ravenscar run-time can be found in the
141c50c785cSJohn Marino    application, and if it has been initialized on target.  */
142c50c785cSJohn Marino 
143c50c785cSJohn Marino static int
ravenscar_runtime_initialized(void)144c50c785cSJohn Marino ravenscar_runtime_initialized (void)
145c50c785cSJohn Marino {
146c50c785cSJohn Marino   return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
147c50c785cSJohn Marino }
148c50c785cSJohn Marino 
149c50c785cSJohn Marino /* Return the ID of the thread that is currently running.
150c50c785cSJohn Marino    Return 0 if the ID could not be determined.  */
151c50c785cSJohn Marino 
152c50c785cSJohn Marino static CORE_ADDR
get_running_thread_id(void)153c50c785cSJohn Marino get_running_thread_id (void)
154c50c785cSJohn Marino {
155c50c785cSJohn Marino   const struct minimal_symbol *object_msym = get_running_thread_msymbol ();
156c50c785cSJohn Marino   int object_size;
157c50c785cSJohn Marino   int buf_size;
158c50c785cSJohn Marino   char *buf;
159c50c785cSJohn Marino   CORE_ADDR object_addr;
160c50c785cSJohn Marino   struct type *builtin_type_void_data_ptr =
161*ef5ccd6cSJohn Marino     builtin_type (target_gdbarch ())->builtin_data_ptr;
162c50c785cSJohn Marino 
163c50c785cSJohn Marino   if (!object_msym)
164c50c785cSJohn Marino     return 0;
165c50c785cSJohn Marino 
166c50c785cSJohn Marino   object_addr = SYMBOL_VALUE_ADDRESS (object_msym);
167c50c785cSJohn Marino   object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
168c50c785cSJohn Marino   buf_size = object_size;
169c50c785cSJohn Marino   buf = alloca (buf_size);
170c50c785cSJohn Marino   read_memory (object_addr, buf, buf_size);
171c50c785cSJohn Marino   return extract_typed_address (buf, builtin_type_void_data_ptr);
172c50c785cSJohn Marino }
173c50c785cSJohn Marino 
174c50c785cSJohn Marino static void
ravenscar_resume(struct target_ops * ops,ptid_t ptid,int step,enum gdb_signal siggnal)175c50c785cSJohn Marino ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
176*ef5ccd6cSJohn Marino 		  enum gdb_signal siggnal)
177c50c785cSJohn Marino {
178c50c785cSJohn Marino   struct target_ops *beneath = find_target_beneath (ops);
179c50c785cSJohn Marino 
180c50c785cSJohn Marino   inferior_ptid = base_ptid;
181c50c785cSJohn Marino   beneath->to_resume (beneath, base_ptid, step, siggnal);
182c50c785cSJohn Marino }
183c50c785cSJohn Marino 
184c50c785cSJohn Marino static ptid_t
ravenscar_wait(struct target_ops * ops,ptid_t ptid,struct target_waitstatus * status,int options)185c50c785cSJohn Marino ravenscar_wait (struct target_ops *ops, ptid_t ptid,
186c50c785cSJohn Marino                 struct target_waitstatus *status,
187c50c785cSJohn Marino                 int options)
188c50c785cSJohn Marino {
189c50c785cSJohn Marino   struct target_ops *beneath = find_target_beneath (ops);
190c50c785cSJohn Marino 
191c50c785cSJohn Marino   inferior_ptid = base_ptid;
192c50c785cSJohn Marino   beneath->to_wait (beneath, base_ptid, status, 0);
193*ef5ccd6cSJohn Marino   /* Find any new threads that might have been created, and update
194*ef5ccd6cSJohn Marino      inferior_ptid to the active thread.
195*ef5ccd6cSJohn Marino 
196*ef5ccd6cSJohn Marino      Only do it if the program is still alive, though.  Otherwise,
197*ef5ccd6cSJohn Marino      this causes problems when debugging through the remote protocol,
198*ef5ccd6cSJohn Marino      because we might try switching threads (and thus sending packets)
199*ef5ccd6cSJohn Marino      after the remote has disconnected.  */
200*ef5ccd6cSJohn Marino   if (status->kind != TARGET_WAITKIND_EXITED
201*ef5ccd6cSJohn Marino       && status->kind != TARGET_WAITKIND_SIGNALLED)
202*ef5ccd6cSJohn Marino     {
203c50c785cSJohn Marino       ravenscar_find_new_threads (ops);
204c50c785cSJohn Marino       ravenscar_update_inferior_ptid ();
205*ef5ccd6cSJohn Marino     }
206c50c785cSJohn Marino   return inferior_ptid;
207c50c785cSJohn Marino }
208c50c785cSJohn Marino 
209c50c785cSJohn Marino /* Add the thread associated to the given TASK to the thread list
210c50c785cSJohn Marino    (if the thread has already been added, this is a no-op).  */
211c50c785cSJohn Marino 
212c50c785cSJohn Marino static void
ravenscar_add_thread(struct ada_task_info * task)213c50c785cSJohn Marino ravenscar_add_thread (struct ada_task_info *task)
214c50c785cSJohn Marino {
215c50c785cSJohn Marino   if (find_thread_ptid (task->ptid) == NULL)
216c50c785cSJohn Marino     add_thread (task->ptid);
217c50c785cSJohn Marino }
218c50c785cSJohn Marino 
219c50c785cSJohn Marino static void
ravenscar_find_new_threads(struct target_ops * ops)220c50c785cSJohn Marino ravenscar_find_new_threads (struct target_ops *ops)
221c50c785cSJohn Marino {
222a45ae5f8SJohn Marino   ada_build_task_list ();
223c50c785cSJohn Marino 
224c50c785cSJohn Marino   /* Do not clear the thread list before adding the Ada task, to keep
225c50c785cSJohn Marino      the thread that the process stratum has included into it
226c50c785cSJohn Marino      (base_ptid) and the running thread, that may not have been included
227c50c785cSJohn Marino      to system.tasking.debug's list yet.  */
228c50c785cSJohn Marino 
229c50c785cSJohn Marino   iterate_over_live_ada_tasks (ravenscar_add_thread);
230c50c785cSJohn Marino }
231c50c785cSJohn Marino 
232c50c785cSJohn Marino static ptid_t
ravenscar_running_thread(void)233c50c785cSJohn Marino ravenscar_running_thread (void)
234c50c785cSJohn Marino {
235c50c785cSJohn Marino   CORE_ADDR tid = get_running_thread_id ();
236c50c785cSJohn Marino 
237c50c785cSJohn Marino   if (tid == 0)
238c50c785cSJohn Marino     return null_ptid;
239c50c785cSJohn Marino   else
240c50c785cSJohn Marino     return ptid_build (ptid_get_pid (base_ptid), 0, tid);
241c50c785cSJohn Marino }
242c50c785cSJohn Marino 
243c50c785cSJohn Marino static char *
ravenscar_extra_thread_info(struct thread_info * tp)244c50c785cSJohn Marino ravenscar_extra_thread_info (struct thread_info *tp)
245c50c785cSJohn Marino {
246c50c785cSJohn Marino   return "Ravenscar task";
247c50c785cSJohn Marino }
248c50c785cSJohn Marino 
249c50c785cSJohn Marino static int
ravenscar_thread_alive(struct target_ops * ops,ptid_t ptid)250c50c785cSJohn Marino ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
251c50c785cSJohn Marino {
252c50c785cSJohn Marino   /* Ravenscar tasks are non-terminating.  */
253c50c785cSJohn Marino   return 1;
254c50c785cSJohn Marino }
255c50c785cSJohn Marino 
256c50c785cSJohn Marino static char *
ravenscar_pid_to_str(struct target_ops * ops,ptid_t ptid)257c50c785cSJohn Marino ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
258c50c785cSJohn Marino {
259c50c785cSJohn Marino   static char buf[30];
260c50c785cSJohn Marino 
261c50c785cSJohn Marino   snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
262c50c785cSJohn Marino   return buf;
263c50c785cSJohn Marino }
264c50c785cSJohn Marino 
265c50c785cSJohn Marino static void
ravenscar_fetch_registers(struct target_ops * ops,struct regcache * regcache,int regnum)266c50c785cSJohn Marino ravenscar_fetch_registers (struct target_ops *ops,
267c50c785cSJohn Marino                            struct regcache *regcache, int regnum)
268c50c785cSJohn Marino {
269c50c785cSJohn Marino   struct target_ops *beneath = find_target_beneath (ops);
270c50c785cSJohn Marino 
271c50c785cSJohn Marino   if (!ravenscar_runtime_initialized ()
272c50c785cSJohn Marino       || ptid_equal (inferior_ptid, base_magic_null_ptid)
273c50c785cSJohn Marino       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
274c50c785cSJohn Marino     beneath->to_fetch_registers (beneath, regcache, regnum);
275c50c785cSJohn Marino   else
276*ef5ccd6cSJohn Marino     {
277*ef5ccd6cSJohn Marino       struct gdbarch *gdbarch = get_regcache_arch (regcache);
278*ef5ccd6cSJohn Marino       struct ravenscar_arch_ops *arch_ops
279*ef5ccd6cSJohn Marino 	= gdbarch_ravenscar_ops (gdbarch);
280*ef5ccd6cSJohn Marino 
281*ef5ccd6cSJohn Marino       arch_ops->to_fetch_registers (regcache, regnum);
282*ef5ccd6cSJohn Marino     }
283c50c785cSJohn Marino }
284c50c785cSJohn Marino 
285c50c785cSJohn Marino static void
ravenscar_store_registers(struct target_ops * ops,struct regcache * regcache,int regnum)286c50c785cSJohn Marino ravenscar_store_registers (struct target_ops *ops,
287c50c785cSJohn Marino                            struct regcache *regcache, int regnum)
288c50c785cSJohn Marino {
289c50c785cSJohn Marino   struct target_ops *beneath = find_target_beneath (ops);
290c50c785cSJohn Marino 
291c50c785cSJohn Marino   if (!ravenscar_runtime_initialized ()
292c50c785cSJohn Marino       || ptid_equal (inferior_ptid, base_magic_null_ptid)
293c50c785cSJohn Marino       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
294c50c785cSJohn Marino     beneath->to_store_registers (beneath, regcache, regnum);
295c50c785cSJohn Marino   else
296*ef5ccd6cSJohn Marino     {
297*ef5ccd6cSJohn Marino       struct gdbarch *gdbarch = get_regcache_arch (regcache);
298*ef5ccd6cSJohn Marino       struct ravenscar_arch_ops *arch_ops
299*ef5ccd6cSJohn Marino 	= gdbarch_ravenscar_ops (gdbarch);
300*ef5ccd6cSJohn Marino 
301*ef5ccd6cSJohn Marino       arch_ops->to_store_registers (regcache, regnum);
302*ef5ccd6cSJohn Marino     }
303c50c785cSJohn Marino }
304c50c785cSJohn Marino 
305c50c785cSJohn Marino static void
ravenscar_prepare_to_store(struct regcache * regcache)306c50c785cSJohn Marino ravenscar_prepare_to_store (struct regcache *regcache)
307c50c785cSJohn Marino {
308c50c785cSJohn Marino   struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
309c50c785cSJohn Marino 
310c50c785cSJohn Marino   if (!ravenscar_runtime_initialized ()
311c50c785cSJohn Marino       || ptid_equal (inferior_ptid, base_magic_null_ptid)
312c50c785cSJohn Marino       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
313c50c785cSJohn Marino     beneath->to_prepare_to_store (regcache);
314c50c785cSJohn Marino   else
315*ef5ccd6cSJohn Marino     {
316*ef5ccd6cSJohn Marino       struct gdbarch *gdbarch = get_regcache_arch (regcache);
317*ef5ccd6cSJohn Marino       struct ravenscar_arch_ops *arch_ops
318*ef5ccd6cSJohn Marino 	= gdbarch_ravenscar_ops (gdbarch);
319*ef5ccd6cSJohn Marino 
320*ef5ccd6cSJohn Marino       arch_ops->to_prepare_to_store (regcache);
321*ef5ccd6cSJohn Marino     }
322c50c785cSJohn Marino }
323c50c785cSJohn Marino 
324c50c785cSJohn Marino static void
ravenscar_mourn_inferior(struct target_ops * ops)325c50c785cSJohn Marino ravenscar_mourn_inferior (struct target_ops *ops)
326c50c785cSJohn Marino {
327c50c785cSJohn Marino   struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
328c50c785cSJohn Marino 
329c50c785cSJohn Marino   base_ptid = null_ptid;
330c50c785cSJohn Marino   beneath->to_mourn_inferior (beneath);
331c50c785cSJohn Marino   unpush_target (&ravenscar_ops);
332c50c785cSJohn Marino }
333c50c785cSJohn Marino 
334c50c785cSJohn Marino /* Observer on inferior_created: push ravenscar thread stratum if needed.  */
335c50c785cSJohn Marino 
336c50c785cSJohn Marino static void
ravenscar_inferior_created(struct target_ops * target,int from_tty)337c50c785cSJohn Marino ravenscar_inferior_created (struct target_ops *target, int from_tty)
338c50c785cSJohn Marino {
339*ef5ccd6cSJohn Marino   struct ravenscar_arch_ops *ops;
340c50c785cSJohn Marino 
341*ef5ccd6cSJohn Marino   if (!ravenscar_task_support
342*ef5ccd6cSJohn Marino       || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
343*ef5ccd6cSJohn Marino       || !has_ravenscar_runtime ())
344c50c785cSJohn Marino     return;
345c50c785cSJohn Marino 
346c50c785cSJohn Marino   base_magic_null_ptid = inferior_ptid;
347c50c785cSJohn Marino   ravenscar_update_inferior_ptid ();
348c50c785cSJohn Marino   push_target (&ravenscar_ops);
349c50c785cSJohn Marino }
350c50c785cSJohn Marino 
351c50c785cSJohn Marino static ptid_t
ravenscar_get_ada_task_ptid(long lwp,long thread)352c50c785cSJohn Marino ravenscar_get_ada_task_ptid (long lwp, long thread)
353c50c785cSJohn Marino {
354c50c785cSJohn Marino   return ptid_build (ptid_get_pid (base_ptid), 0, thread);
355c50c785cSJohn Marino }
356c50c785cSJohn Marino 
357c50c785cSJohn Marino static void
init_ravenscar_thread_ops(void)358c50c785cSJohn Marino init_ravenscar_thread_ops (void)
359c50c785cSJohn Marino {
360c50c785cSJohn Marino   ravenscar_ops.to_shortname = "ravenscar";
361c50c785cSJohn Marino   ravenscar_ops.to_longname = "Ravenscar tasks.";
362c50c785cSJohn Marino   ravenscar_ops.to_doc = "Ravenscar tasks support.";
363c50c785cSJohn Marino   ravenscar_ops.to_resume = ravenscar_resume;
364c50c785cSJohn Marino   ravenscar_ops.to_wait = ravenscar_wait;
365c50c785cSJohn Marino   ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
366c50c785cSJohn Marino   ravenscar_ops.to_store_registers = ravenscar_store_registers;
367c50c785cSJohn Marino   ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
368c50c785cSJohn Marino   ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
369c50c785cSJohn Marino   ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
370c50c785cSJohn Marino   ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
371c50c785cSJohn Marino   ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
372c50c785cSJohn Marino   ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
373c50c785cSJohn Marino   ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
374c50c785cSJohn Marino   ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
375c50c785cSJohn Marino   ravenscar_ops.to_has_memory = default_child_has_memory;
376c50c785cSJohn Marino   ravenscar_ops.to_has_stack = default_child_has_stack;
377c50c785cSJohn Marino   ravenscar_ops.to_has_registers = default_child_has_registers;
378c50c785cSJohn Marino   ravenscar_ops.to_has_execution = default_child_has_execution;
379c50c785cSJohn Marino   ravenscar_ops.to_stratum = thread_stratum;
380c50c785cSJohn Marino   ravenscar_ops.to_magic = OPS_MAGIC;
381c50c785cSJohn Marino }
382c50c785cSJohn Marino 
383c50c785cSJohn Marino /* Command-list for the "set/show ravenscar" prefix command.  */
384c50c785cSJohn Marino static struct cmd_list_element *set_ravenscar_list;
385c50c785cSJohn Marino static struct cmd_list_element *show_ravenscar_list;
386c50c785cSJohn Marino 
387c50c785cSJohn Marino /* Implement the "set ravenscar" prefix command.  */
388c50c785cSJohn Marino 
389c50c785cSJohn Marino static void
set_ravenscar_command(char * arg,int from_tty)390c50c785cSJohn Marino set_ravenscar_command (char *arg, int from_tty)
391c50c785cSJohn Marino {
392c50c785cSJohn Marino   printf_unfiltered (_(\
393c50c785cSJohn Marino "\"set ravenscar\" must be followed by the name of a setting.\n"));
394c50c785cSJohn Marino   help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
395c50c785cSJohn Marino }
396c50c785cSJohn Marino 
397c50c785cSJohn Marino /* Implement the "show ravenscar" prefix command.  */
398c50c785cSJohn Marino 
399c50c785cSJohn Marino static void
show_ravenscar_command(char * args,int from_tty)400c50c785cSJohn Marino show_ravenscar_command (char *args, int from_tty)
401c50c785cSJohn Marino {
402c50c785cSJohn Marino   cmd_show_list (show_ravenscar_list, from_tty, "");
403c50c785cSJohn Marino }
404c50c785cSJohn Marino 
405c50c785cSJohn Marino /* Implement the "show ravenscar task-switching" command.  */
406c50c785cSJohn Marino 
407c50c785cSJohn Marino static void
show_ravenscar_task_switching_command(struct ui_file * file,int from_tty,struct cmd_list_element * c,const char * value)408c50c785cSJohn Marino show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
409c50c785cSJohn Marino 				       struct cmd_list_element *c,
410c50c785cSJohn Marino 				       const char *value)
411c50c785cSJohn Marino {
412c50c785cSJohn Marino   if (ravenscar_task_support)
413c50c785cSJohn Marino     fprintf_filtered (file, _("\
414c50c785cSJohn Marino Support for Ravenscar task/thread switching is enabled\n"));
415c50c785cSJohn Marino   else
416c50c785cSJohn Marino     fprintf_filtered (file, _("\
417c50c785cSJohn Marino Support for Ravenscar task/thread switching is disabled\n"));
418c50c785cSJohn Marino }
419c50c785cSJohn Marino 
420*ef5ccd6cSJohn Marino /* Provide a prototype to silence -Wmissing-prototypes.  */
421*ef5ccd6cSJohn Marino extern void _initialize_ravenscar (void);
422*ef5ccd6cSJohn Marino 
423c50c785cSJohn Marino /* Module startup initialization function, automagically called by
424c50c785cSJohn Marino    init.c.  */
425c50c785cSJohn Marino 
426c50c785cSJohn Marino void
_initialize_ravenscar(void)427c50c785cSJohn Marino _initialize_ravenscar (void)
428c50c785cSJohn Marino {
429c50c785cSJohn Marino   init_ravenscar_thread_ops ();
430c50c785cSJohn Marino   base_ptid = null_ptid;
431c50c785cSJohn Marino 
432c50c785cSJohn Marino   /* Notice when the inferior is created in order to push the
433c50c785cSJohn Marino      ravenscar ops if needed.  */
434c50c785cSJohn Marino   observer_attach_inferior_created (ravenscar_inferior_created);
435c50c785cSJohn Marino 
436c50c785cSJohn Marino   add_target (&ravenscar_ops);
437c50c785cSJohn Marino 
438c50c785cSJohn Marino   add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
439c50c785cSJohn Marino                   _("Prefix command for changing Ravenscar-specific settings"),
440c50c785cSJohn Marino                   &set_ravenscar_list, "set ravenscar ", 0, &setlist);
441c50c785cSJohn Marino 
442c50c785cSJohn Marino   add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
443c50c785cSJohn Marino                   _("Prefix command for showing Ravenscar-specific settings"),
444c50c785cSJohn Marino                   &show_ravenscar_list, "show ravenscar ", 0, &showlist);
445c50c785cSJohn Marino 
446c50c785cSJohn Marino   add_setshow_boolean_cmd ("task-switching", class_obscure,
447c50c785cSJohn Marino                            &ravenscar_task_support, _("\
448c50c785cSJohn Marino Enable or disable support for GNAT Ravenscar tasks"), _("\
449c50c785cSJohn Marino Show whether support for GNAT Ravenscar tasks is enabled"),
450c50c785cSJohn Marino                            _("\
451c50c785cSJohn Marino Enable or disable support for task/thread switching with the GNAT\n\
452c50c785cSJohn Marino Ravenscar run-time library for bareboard configuration."),
453c50c785cSJohn Marino 			   NULL, show_ravenscar_task_switching_command,
454c50c785cSJohn Marino 			   &set_ravenscar_list, &show_ravenscar_list);
455c50c785cSJohn Marino }
456