+ /* Simulator descriptor for this inferior. */
+ SIM_DESC gdbsim_desc;
+
+ /* This is the ptid we use for this particular simulator instance. Its
+ value is somewhat arbitrary, as the simulator target don't have a
+ notion of tasks or threads, but we need something non-null to place
+ in inferior_ptid. For simulators which permit multiple instances,
+ we also need a unique identifier to use for each inferior. */
+ ptid_t remote_sim_ptid;
+
+ /* Signal with which to resume. */
+ enum target_signal resume_siggnal;
+
+ /* Flag which indicates whether resume should step or not. */
+ int resume_step;
+};
+
+/* Flag indicating the "open" status of this module. It's set to 1
+ in gdbsim_open() and 0 in gdbsim_close(). */
+static int gdbsim_is_open = 0;
+
+/* Value of the next pid to allocate for an inferior. As indicated
+ elsewhere, its initial value is somewhat arbitrary; it's critical
+ though that it's not zero or negative. */
+static int next_pid;
+#define INITIAL_PID 42000
+
+/* Argument list to pass to sim_open(). It is allocated in gdbsim_open()
+ and deallocated in gdbsim_close(). The lifetime needs to extend beyond
+ the call to gdbsim_open() due to the fact that other sim instances other
+ than the first will be allocated after the gdbsim_open() call. */
+static char **sim_argv = NULL;
+
+/* OS-level callback functions for write, flush, etc. */
+static host_callback gdb_callback;
+static int callbacks_initialized = 0;
+
+/* Callback for iterate_over_inferiors. It checks to see if the sim
+ descriptor passed via ARG is the same as that for the inferior
+ designated by INF. Return true if so; false otherwise. */
+
+static int
+check_for_duplicate_sim_descriptor (struct inferior *inf, void *arg)
+{
+ struct sim_inferior_data *sim_data;
+ SIM_DESC new_sim_desc = arg;
+
+ sim_data = inferior_data (inf, sim_inferior_data_key);
+
+ return (sim_data != NULL && sim_data->gdbsim_desc == new_sim_desc);
+}
+
+/* Flags indicating whether or not a sim instance is needed. One of these
+ flags should be passed to get_sim_inferior_data(). */
+
+enum {SIM_INSTANCE_NOT_NEEDED = 0, SIM_INSTANCE_NEEDED = 1};
+
+/* Obtain pointer to per-inferior simulator data, allocating it if necessary.
+ Attempt to open the sim if SIM_INSTANCE_NEEDED is true. */
+
+static struct sim_inferior_data *
+get_sim_inferior_data (struct inferior *inf, int sim_instance_needed)
+{
+ SIM_DESC sim_desc = NULL;
+ struct sim_inferior_data *sim_data
+ = inferior_data (inf, sim_inferior_data_key);
+
+ /* Try to allocate a new sim instance, if needed. We do this ahead of
+ a potential allocation of a sim_inferior_data struct in order to
+ avoid needlessly allocating that struct in the event that the sim
+ instance allocation fails. */
+ if (sim_instance_needed == SIM_INSTANCE_NEEDED
+ && (sim_data == NULL || sim_data->gdbsim_desc == NULL))
+ {
+ struct inferior *idup;
+ sim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv);
+ if (sim_desc == NULL)
+ error (_("Unable to create simulator instance for inferior %d."),
+ inf->num);
+
+ idup = iterate_over_inferiors (check_for_duplicate_sim_descriptor,
+ sim_desc);
+ if (idup != NULL)
+ {
+ /* We don't close the descriptor due to the fact that it's
+ shared with some other inferior. If we were to close it,
+ that might needlessly muck up the other inferior. Of
+ course, it's possible that the damage has already been
+ done... Note that it *will* ultimately be closed during
+ cleanup of the other inferior. */
+ sim_desc = NULL;
+ error (
+ _("Inferior %d and inferior %d would have identical simulator state.\n"
+ "(This simulator does not support the running of more than one inferior.)"),
+ inf->num, idup->num);
+ }
+ }
+
+ if (sim_data == NULL)
+ {
+ sim_data = XZALLOC(struct sim_inferior_data);
+ set_inferior_data (inf, sim_inferior_data_key, sim_data);
+
+ /* Allocate a ptid for this inferior. */
+ sim_data->remote_sim_ptid = ptid_build (next_pid, 0, next_pid);
+ next_pid++;
+
+ /* Initialize the other instance variables. */
+ sim_data->program_loaded = 0;
+ sim_data->gdbsim_desc = sim_desc;
+ sim_data->resume_siggnal = TARGET_SIGNAL_0;
+ sim_data->resume_step = 0;
+ }
+ else if (sim_desc)
+ {
+ /* This handles the case where sim_data was allocated prior to
+ needing a sim instance. */
+ sim_data->gdbsim_desc = sim_desc;
+ }
+
+
+ return sim_data;
+}
+
+/* Return pointer to per-inferior simulator data using PTID to find the
+ inferior in question. Return NULL when no inferior is found or
+ when ptid has a zero or negative pid component. */
+
+static struct sim_inferior_data *
+get_sim_inferior_data_by_ptid (ptid_t ptid, int sim_instance_needed)
+{
+ struct inferior *inf;
+ int pid = ptid_get_pid (ptid);
+
+ if (pid <= 0)
+ return NULL;
+
+ inf = find_inferior_pid (pid);
+
+ if (inf)
+ return get_sim_inferior_data (inf, sim_instance_needed);
+ else
+ return NULL;
+}
+
+/* Free the per-inferior simulator data. */
+
+static void
+sim_inferior_data_cleanup (struct inferior *inf, void *data)
+{
+ struct sim_inferior_data *sim_data = data;
+
+ if (sim_data != NULL)
+ {
+ if (sim_data->gdbsim_desc)
+ {
+ sim_close (sim_data->gdbsim_desc, 0);
+ sim_data->gdbsim_desc = NULL;
+ }
+ xfree (sim_data);
+ }
+}