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