+ const target_info &info () const override
+ { return ravenscar_target_info; }
+
+ strata stratum () const override { return thread_stratum; }
+
+ ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+ void resume (ptid_t, int, enum gdb_signal) override;
+
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ void prepare_to_store (struct regcache *) override;
+
+ bool stopped_by_sw_breakpoint () override;
+
+ bool stopped_by_hw_breakpoint () override;
+
+ bool stopped_by_watchpoint () override;
+
+ bool stopped_data_address (CORE_ADDR *) override;
+
+ bool thread_alive (ptid_t ptid) override;
+
+ int core_of_thread (ptid_t ptid) override;
+
+ void update_thread_list () override;
+
+ const char *extra_thread_info (struct thread_info *) override;
+
+ std::string pid_to_str (ptid_t) override;
+
+ ptid_t get_ada_task_ptid (long lwp, long thread) override;
+
+ void mourn_inferior () override;
+
+ void close () override
+ {
+ delete this;
+ }
+
+private:
+
+ /* PTID of the last thread that received an event.
+ This can be useful to determine the associated task that received
+ the event, to make it the current task. */
+ ptid_t m_base_ptid = null_ptid;
+
+ void update_inferior_ptid ();
+ ptid_t active_task (int cpu);
+ bool task_is_currently_active (ptid_t ptid);
+ bool runtime_initialized ();
+};
+
+/* Return true iff PTID corresponds to a ravenscar task. */
+
+static bool
+is_ravenscar_task (ptid_t ptid)
+{
+ /* By construction, ravenscar tasks have their LWP set to zero.
+ Also make sure that the TID is nonzero, as some remotes, when
+ asked for the list of threads, will return the first thread
+ as having its TID set to zero. For instance, TSIM version
+ 2.0.48 for LEON3 sends 'm0' as a reply to the 'qfThreadInfo'
+ query, which the remote protocol layer then treats as a thread
+ whose TID is 0. This is obviously not a ravenscar task. */
+ return ptid.lwp () == 0 && ptid.tid () != 0;
+}
+
+/* Given PTID, which can be either a ravenscar task or a CPU thread,
+ return which CPU that ptid is running on.
+
+ This assume that PTID is a valid ptid_t. Otherwise, a gdb_assert
+ will be triggered. */
+
+static int
+ravenscar_get_thread_base_cpu (ptid_t ptid)
+{
+ int base_cpu;
+
+ if (is_ravenscar_task (ptid))
+ {
+ struct ada_task_info *task_info = ada_get_task_info_from_ptid (ptid);
+
+ gdb_assert (task_info != NULL);
+ base_cpu = task_info->base_cpu;
+ }
+ else
+ {
+ /* We assume that the LWP of the PTID is equal to the CPU number. */
+ base_cpu = ptid.lwp ();
+ }
+
+ return base_cpu;
+}
+
+/* Given a ravenscar task (identified by its ptid_t PTID), return true
+ if this task is the currently active task on the cpu that task is
+ running on.
+
+ In other words, this function determine which CPU this task is
+ currently running on, and then return nonzero if the CPU in question
+ is executing the code for that task. If that's the case, then
+ that task's registers are in the CPU bank. Otherwise, the task
+ is currently suspended, and its registers have been saved in memory. */
+
+bool
+ravenscar_thread_target::task_is_currently_active (ptid_t ptid)
+{
+ ptid_t active_task_ptid
+ = active_task (ravenscar_get_thread_base_cpu (ptid));
+
+ return ptid == active_task_ptid;
+}