+/* Per-inferior data key. */
+static const struct inferior_data *i386_inferior_data;
+
+/* Per-inferior data. */
+struct i386_inferior_data
+{
+ /* Copy of i386 hardware debug registers for performance reasons. */
+ struct i386_debug_reg_state state;
+};
+
+/* Per-inferior hook for register_inferior_data_with_cleanup. */
+
+static void
+i386_inferior_data_cleanup (struct inferior *inf, void *arg)
+{
+ struct i386_inferior_data *inf_data = arg;
+
+ xfree (inf_data);
+}
+
+/* Get data specific for INFERIOR_PTID LWP. Return special data area
+ for processes being detached. */
+
+static struct i386_inferior_data *
+i386_inferior_data_get (void)
+{
+ struct inferior *inf = current_inferior ();
+ struct i386_inferior_data *inf_data;
+
+ inf_data = inferior_data (inf, i386_inferior_data);
+ if (inf_data == NULL)
+ {
+ inf_data = xzalloc (sizeof (*inf_data));
+ set_inferior_data (current_inferior (), i386_inferior_data, inf_data);
+ }
+
+ if (inf->pid != ptid_get_pid (inferior_ptid))
+ {
+ /* INFERIOR_PTID is being detached from the inferior INF.
+ Provide local cache specific for the detached LWP. */
+
+ static struct i386_inferior_data detached_inf_data_local;
+ static int detached_inf_pid = -1;
+
+ if (detached_inf_pid != ptid_get_pid (inferior_ptid))
+ {
+ /* Reinitialize the local cache if INFERIOR_PTID is
+ different from the LWP last detached.
+
+ Linux kernel before 2.6.33 commit
+ 72f674d203cd230426437cdcf7dd6f681dad8b0d
+ will inherit hardware debug registers from parent
+ on fork/vfork/clone. Newer Linux kernels create such tasks with
+ zeroed debug registers.
+
+ GDB will remove all breakpoints (and watchpoints) from the forked
+ off process. We also need to reset the debug registers in that
+ process to be compatible with the older Linux kernels.
+
+ Copy the debug registers mirrors into the new process so that all
+ breakpoints and watchpoints can be removed together. The debug
+ registers mirror will become zeroed in the end before detaching
+ the forked off process. */
+
+ detached_inf_pid = ptid_get_pid (inferior_ptid);
+ detached_inf_data_local = *inf_data;
+ }
+
+ return &detached_inf_data_local;
+ }
+
+ return inf_data;
+}
+
+/* Get debug registers state for INFERIOR_PTID, see
+ i386_inferior_data_get. */
+
+struct i386_debug_reg_state *
+i386_debug_reg_state (void)
+{
+ return &i386_inferior_data_get ()->state;
+}