mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-03 21:34:46 +08:00
* Makefile.in (i386-linux-nat.o): Update dependencies.
* config/i386/nm-linux.h (LINUX_CHILD_POST_STARTUP_INFERIOR): Define. * config/nm-linux.h (CHILD_POST_STARTUP_INFERIOR, CHILD_POST_ATTACH) (CHILD_FOLLOW_FORK, KILL_INFERIOR): Define. * i386-linux-nat.c: Include "linux-nat.h". (child_post_startup_inferior): New function. * i386-nat.c (child_post_startup_inferior): Wrap in #ifdef. * infptrace.c (kill_inferior): Wrap in #ifdef. * lin-lwp.c (lin_lwp_attach_lwp): Call child_post_attach after attaching to each LWP. (child_wait, lin_lwp_wait): Call linux_handle_extended_wait. (init_lin_lwp_ops): Fill in some more operations. * linux-nat.h (linux_enable_event_reporting) (linux_handle_extended_wait, linux_child_post_startup_inferior): New prototypes. * linux-nat.c (linux_enable_event_reporting): New function. (child_post_attach, linux_child_post_startup_inferior) (child_post_startup_inferior, child_follow_fork) (linux_handle_extended_wait, kill_inferior): New functions.
This commit is contained in:
@ -1,3 +1,25 @@
|
|||||||
|
2003-08-17 Daniel Jacobowitz <drow@mvista.com>
|
||||||
|
|
||||||
|
* Makefile.in (i386-linux-nat.o): Update dependencies.
|
||||||
|
* config/i386/nm-linux.h (LINUX_CHILD_POST_STARTUP_INFERIOR): Define.
|
||||||
|
* config/nm-linux.h (CHILD_POST_STARTUP_INFERIOR, CHILD_POST_ATTACH)
|
||||||
|
(CHILD_FOLLOW_FORK, KILL_INFERIOR): Define.
|
||||||
|
* i386-linux-nat.c: Include "linux-nat.h".
|
||||||
|
(child_post_startup_inferior): New function.
|
||||||
|
* i386-nat.c (child_post_startup_inferior): Wrap in #ifdef.
|
||||||
|
* infptrace.c (kill_inferior): Wrap in #ifdef.
|
||||||
|
* lin-lwp.c (lin_lwp_attach_lwp): Call child_post_attach after
|
||||||
|
attaching to each LWP.
|
||||||
|
(child_wait, lin_lwp_wait): Call linux_handle_extended_wait.
|
||||||
|
(init_lin_lwp_ops): Fill in some more operations.
|
||||||
|
* linux-nat.h (linux_enable_event_reporting)
|
||||||
|
(linux_handle_extended_wait, linux_child_post_startup_inferior): New
|
||||||
|
prototypes.
|
||||||
|
* linux-nat.c (linux_enable_event_reporting): New function.
|
||||||
|
(child_post_attach, linux_child_post_startup_inferior)
|
||||||
|
(child_post_startup_inferior, child_follow_fork)
|
||||||
|
(linux_handle_extended_wait, kill_inferior): New functions.
|
||||||
|
|
||||||
2003-08-16 Andrew Cagney <cagney@redhat.com>
|
2003-08-16 Andrew Cagney <cagney@redhat.com>
|
||||||
|
|
||||||
* gdbarch.sh: Delete all #if not GDB_MULTI_ARCH code.
|
* gdbarch.sh: Delete all #if not GDB_MULTI_ARCH code.
|
||||||
|
@ -1843,7 +1843,7 @@ i386-interix-tdep.o: i386-interix-tdep.c $(defs_h) $(arch_utils_h) \
|
|||||||
i386-linux-nat.o: i386-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
|
i386-linux-nat.o: i386-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
|
||||||
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(gregset_h) \
|
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(gregset_h) \
|
||||||
$(i387_tdep_h) $(i386_tdep_h) $(i386_linux_tdep_h) \
|
$(i387_tdep_h) $(i386_tdep_h) $(i386_linux_tdep_h) \
|
||||||
$(gdb_proc_service_h)
|
$(gdb_proc_service_h) $(linux_nat_h)
|
||||||
i386-linux-tdep.o: i386-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \
|
i386-linux-tdep.o: i386-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \
|
||||||
$(value_h) $(regcache_h) $(inferior_h) $(reggroups_h) $(symtab_h) \
|
$(value_h) $(regcache_h) $(inferior_h) $(reggroups_h) $(symtab_h) \
|
||||||
$(symfile_h) $(objfiles_h) $(solib_svr4_h) $(osabi_h) $(i386_tdep_h) \
|
$(symfile_h) $(objfiles_h) $(solib_svr4_h) $(osabi_h) $(i386_tdep_h) \
|
||||||
|
@ -82,4 +82,13 @@ extern int cannot_store_register (int regno);
|
|||||||
/* Override child_resume in `infptrace.c'. */
|
/* Override child_resume in `infptrace.c'. */
|
||||||
#define CHILD_RESUME
|
#define CHILD_RESUME
|
||||||
|
|
||||||
|
/* `linux-nat.c' and `i386-nat.c' have their own versions of
|
||||||
|
child_post_startup_inferior. Define this to use the copy in
|
||||||
|
`i386-linux-nat.c' instead, which calls both.
|
||||||
|
|
||||||
|
NOTE drow/2003-08-17: This is ugly beyond words, but properly
|
||||||
|
fixing it will require some serious surgery. Ideally the target
|
||||||
|
stack could be used for this. */
|
||||||
|
#define LINUX_CHILD_POST_STARTUP_INFERIOR
|
||||||
|
|
||||||
#endif /* nm-linux.h */
|
#endif /* nm-linux.h */
|
||||||
|
@ -73,3 +73,7 @@ extern void lin_thread_get_thread_signals (sigset_t *mask);
|
|||||||
#define CHILD_INSERT_FORK_CATCHPOINT
|
#define CHILD_INSERT_FORK_CATCHPOINT
|
||||||
#define CHILD_INSERT_VFORK_CATCHPOINT
|
#define CHILD_INSERT_VFORK_CATCHPOINT
|
||||||
#define CHILD_INSERT_EXEC_CATCHPOINT
|
#define CHILD_INSERT_EXEC_CATCHPOINT
|
||||||
|
#define CHILD_POST_STARTUP_INFERIOR
|
||||||
|
#define CHILD_POST_ATTACH
|
||||||
|
#define CHILD_FOLLOW_FORK
|
||||||
|
#define KILL_INFERIOR
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "inferior.h"
|
#include "inferior.h"
|
||||||
#include "gdbcore.h"
|
#include "gdbcore.h"
|
||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
|
#include "linux-nat.h"
|
||||||
|
|
||||||
#include "gdb_assert.h"
|
#include "gdb_assert.h"
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
@ -890,6 +891,13 @@ child_resume (ptid_t ptid, int step, enum target_signal signal)
|
|||||||
if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1)
|
if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1)
|
||||||
perror_with_name ("ptrace");
|
perror_with_name ("ptrace");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
child_post_startup_inferior (ptid_t ptid)
|
||||||
|
{
|
||||||
|
i386_cleanup_dregs ();
|
||||||
|
linux_child_post_startup_inferior (ptid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Register that we are able to handle GNU/Linux ELF core file
|
/* Register that we are able to handle GNU/Linux ELF core file
|
||||||
|
@ -230,6 +230,7 @@ i386_cleanup_dregs (void)
|
|||||||
dr_status_mirror = 0;
|
dr_status_mirror = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LINUX_CHILD_POST_STARTUP_INFERIOR
|
||||||
/* Reset all debug registers at each new startup
|
/* Reset all debug registers at each new startup
|
||||||
to avoid missing watchpoints after restart. */
|
to avoid missing watchpoints after restart. */
|
||||||
void
|
void
|
||||||
@ -237,6 +238,7 @@ child_post_startup_inferior (ptid_t ptid)
|
|||||||
{
|
{
|
||||||
i386_cleanup_dregs ();
|
i386_cleanup_dregs ();
|
||||||
}
|
}
|
||||||
|
#endif /* LINUX_CHILD_POST_STARTUP_INFERIOR */
|
||||||
|
|
||||||
/* Print the values of the mirrored debug registers.
|
/* Print the values of the mirrored debug registers.
|
||||||
This is called when maint_show_dr is non-zero. To set that
|
This is called when maint_show_dr is non-zero. To set that
|
||||||
|
@ -208,6 +208,7 @@ ptrace_wait (ptid_t ptid, int *status)
|
|||||||
return wstate;
|
return wstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef KILL_INFERIOR
|
||||||
void
|
void
|
||||||
kill_inferior (void)
|
kill_inferior (void)
|
||||||
{
|
{
|
||||||
@ -229,6 +230,7 @@ kill_inferior (void)
|
|||||||
ptrace_wait (null_ptid, &status);
|
ptrace_wait (null_ptid, &status);
|
||||||
target_mourn_inferior ();
|
target_mourn_inferior ();
|
||||||
}
|
}
|
||||||
|
#endif /* KILL_INFERIOR */
|
||||||
|
|
||||||
#ifndef CHILD_RESUME
|
#ifndef CHILD_RESUME
|
||||||
|
|
||||||
|
@ -324,6 +324,8 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose)
|
|||||||
gdb_assert (pid == GET_LWP (ptid)
|
gdb_assert (pid == GET_LWP (ptid)
|
||||||
&& WIFSTOPPED (status) && WSTOPSIG (status));
|
&& WIFSTOPPED (status) && WSTOPSIG (status));
|
||||||
|
|
||||||
|
child_post_attach (pid);
|
||||||
|
|
||||||
lp->stopped = 1;
|
lp->stopped = 1;
|
||||||
|
|
||||||
if (debug_lin_lwp)
|
if (debug_lin_lwp)
|
||||||
@ -1067,6 +1069,10 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
|||||||
return minus_one_ptid;
|
return minus_one_ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||||
|
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
|
||||||
|
return linux_handle_extended_wait (pid, status, ourstatus);
|
||||||
|
|
||||||
store_waitstatus (ourstatus, status);
|
store_waitstatus (ourstatus, status);
|
||||||
return pid_to_ptid (pid);
|
return pid_to_ptid (pid);
|
||||||
}
|
}
|
||||||
@ -1488,6 +1494,14 @@ retry:
|
|||||||
else
|
else
|
||||||
trap_ptid = null_ptid;
|
trap_ptid = null_ptid;
|
||||||
|
|
||||||
|
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||||
|
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
|
||||||
|
{
|
||||||
|
linux_handle_extended_wait (ptid_get_pid (trap_ptid),
|
||||||
|
status, ourstatus);
|
||||||
|
return trap_ptid;
|
||||||
|
}
|
||||||
|
|
||||||
store_waitstatus (ourstatus, status);
|
store_waitstatus (ourstatus, status);
|
||||||
return (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid)));
|
return (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid)));
|
||||||
}
|
}
|
||||||
@ -1657,6 +1671,12 @@ init_lin_lwp_ops (void)
|
|||||||
lin_lwp_ops.to_mourn_inferior = lin_lwp_mourn_inferior;
|
lin_lwp_ops.to_mourn_inferior = lin_lwp_mourn_inferior;
|
||||||
lin_lwp_ops.to_thread_alive = lin_lwp_thread_alive;
|
lin_lwp_ops.to_thread_alive = lin_lwp_thread_alive;
|
||||||
lin_lwp_ops.to_pid_to_str = lin_lwp_pid_to_str;
|
lin_lwp_ops.to_pid_to_str = lin_lwp_pid_to_str;
|
||||||
|
lin_lwp_ops.to_post_startup_inferior = child_post_startup_inferior;
|
||||||
|
lin_lwp_ops.to_post_attach = child_post_attach;
|
||||||
|
lin_lwp_ops.to_insert_fork_catchpoint = child_insert_fork_catchpoint;
|
||||||
|
lin_lwp_ops.to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
|
||||||
|
lin_lwp_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint;
|
||||||
|
|
||||||
lin_lwp_ops.to_stratum = thread_stratum;
|
lin_lwp_ops.to_stratum = thread_stratum;
|
||||||
lin_lwp_ops.to_has_thread_control = tc_schedlock;
|
lin_lwp_ops.to_has_thread_control = tc_schedlock;
|
||||||
lin_lwp_ops.to_magic = OPS_MAGIC;
|
lin_lwp_ops.to_magic = OPS_MAGIC;
|
||||||
|
181
gdb/linux-nat.c
181
gdb/linux-nat.c
@ -56,6 +56,8 @@
|
|||||||
#define __WALL 0x40000000 /* Wait for any child. */
|
#define __WALL 0x40000000 /* Wait for any child. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern struct target_ops child_ops;
|
||||||
|
|
||||||
struct simple_pid_list
|
struct simple_pid_list
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
@ -188,14 +190,148 @@ linux_supports_tracefork (void)
|
|||||||
return linux_supports_tracefork_flag;
|
return linux_supports_tracefork_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_enable_event_reporting (ptid_t ptid)
|
||||||
|
{
|
||||||
|
int pid = ptid_get_pid (ptid);
|
||||||
|
int options;
|
||||||
|
|
||||||
|
if (! linux_supports_tracefork ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
options = PTRACE_O_TRACEFORK;
|
||||||
|
|
||||||
|
ptrace (PTRACE_SETOPTIONS, pid, 0, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
child_post_attach (int pid)
|
||||||
|
{
|
||||||
|
linux_enable_event_reporting (pid_to_ptid (pid));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_child_post_startup_inferior (ptid_t ptid)
|
||||||
|
{
|
||||||
|
linux_enable_event_reporting (ptid);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef LINUX_CHILD_POST_STARTUP_INFERIOR
|
||||||
|
void
|
||||||
|
child_post_startup_inferior (ptid_t ptid)
|
||||||
|
{
|
||||||
|
linux_child_post_startup_inferior (ptid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
child_follow_fork (int follow_child)
|
||||||
|
{
|
||||||
|
ptid_t last_ptid;
|
||||||
|
struct target_waitstatus last_status;
|
||||||
|
int parent_pid, child_pid;
|
||||||
|
|
||||||
|
get_last_target_status (&last_ptid, &last_status);
|
||||||
|
parent_pid = ptid_get_pid (last_ptid);
|
||||||
|
child_pid = last_status.value.related_pid;
|
||||||
|
|
||||||
|
if (! follow_child)
|
||||||
|
{
|
||||||
|
/* We're already attached to the parent, by default. */
|
||||||
|
|
||||||
|
/* Before detaching from the child, remove all breakpoints from
|
||||||
|
it. (This won't actually modify the breakpoint list, but will
|
||||||
|
physically remove the breakpoints from the child.) */
|
||||||
|
detach_breakpoints (child_pid);
|
||||||
|
|
||||||
|
fprintf_filtered (gdb_stdout,
|
||||||
|
"Detaching after fork from child process %d.\n",
|
||||||
|
child_pid);
|
||||||
|
|
||||||
|
ptrace (PTRACE_DETACH, child_pid, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char child_pid_spelling[40];
|
||||||
|
|
||||||
|
/* Needed to keep the breakpoint lists in sync. */
|
||||||
|
detach_breakpoints (child_pid);
|
||||||
|
|
||||||
|
/* Before detaching from the parent, remove all breakpoints from it. */
|
||||||
|
remove_breakpoints ();
|
||||||
|
|
||||||
|
fprintf_filtered (gdb_stdout,
|
||||||
|
"Attaching after fork to child process %d.\n",
|
||||||
|
child_pid);
|
||||||
|
|
||||||
|
target_detach (NULL, 0);
|
||||||
|
|
||||||
|
inferior_ptid = pid_to_ptid (child_pid);
|
||||||
|
push_target (&child_ops);
|
||||||
|
|
||||||
|
/* Reset breakpoints in the child as appropriate. */
|
||||||
|
follow_inferior_reset_breakpoints ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptid_t
|
||||||
|
linux_handle_extended_wait (int pid, int status,
|
||||||
|
struct target_waitstatus *ourstatus)
|
||||||
|
{
|
||||||
|
int event = status >> 16;
|
||||||
|
|
||||||
|
if (event == PTRACE_EVENT_CLONE)
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
"unexpected clone event");
|
||||||
|
|
||||||
|
if (event == PTRACE_EVENT_FORK)
|
||||||
|
{
|
||||||
|
unsigned long new_pid;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ptrace (PTRACE_GETEVENTMSG, pid, 0, &new_pid);
|
||||||
|
|
||||||
|
/* If we haven't already seen the new PID stop, wait for it now. */
|
||||||
|
if (! pull_pid_from_list (&stopped_pids, new_pid))
|
||||||
|
{
|
||||||
|
/* The new child has a pending SIGSTOP. We can't affect it until it
|
||||||
|
hits the SIGSTOP, but we're already attached.
|
||||||
|
|
||||||
|
It won't be a clone (we didn't ask for clones in the event mask)
|
||||||
|
so we can just call waitpid and wait for the SIGSTOP. */
|
||||||
|
do {
|
||||||
|
ret = waitpid (new_pid, &status, 0);
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
if (ret == -1)
|
||||||
|
perror_with_name ("waiting for new child");
|
||||||
|
else if (ret != new_pid)
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
"wait returned unexpected PID %d", ret);
|
||||||
|
else if (!WIFSTOPPED (status) || WSTOPSIG (status) != SIGSTOP)
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
"wait returned unexpected status 0x%x", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ourstatus->kind = TARGET_WAITKIND_FORKED;
|
||||||
|
ourstatus->value.related_pid = new_pid;
|
||||||
|
return inferior_ptid;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
"unknown ptrace event %d", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
child_insert_fork_catchpoint (int pid)
|
child_insert_fork_catchpoint (int pid)
|
||||||
{
|
{
|
||||||
if (linux_supports_tracefork ())
|
if (! linux_supports_tracefork ())
|
||||||
error ("Fork catchpoints have not been implemented yet.");
|
|
||||||
else
|
|
||||||
error ("Your system does not support fork catchpoints.");
|
error ("Your system does not support fork catchpoints.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -216,4 +352,43 @@ child_insert_exec_catchpoint (int pid)
|
|||||||
error ("Your system does not support exec catchpoints.");
|
error ("Your system does not support exec catchpoints.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kill_inferior (void)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
int pid = PIDGET (inferior_ptid);
|
||||||
|
struct target_waitstatus last;
|
||||||
|
ptid_t last_ptid;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If we're stopped while forking and we haven't followed yet, kill the
|
||||||
|
other task. We need to do this first because the parent will be
|
||||||
|
sleeping if this is a vfork. */
|
||||||
|
|
||||||
|
get_last_target_status (&last_ptid, &last);
|
||||||
|
|
||||||
|
if (last.kind == TARGET_WAITKIND_FORKED
|
||||||
|
|| last.kind == TARGET_WAITKIND_VFORKED)
|
||||||
|
{
|
||||||
|
ptrace (PT_KILL, last.value.related_pid);
|
||||||
|
ptrace_wait (null_ptid, &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kill the current process. */
|
||||||
|
ptrace (PT_KILL, pid, (PTRACE_ARG3_TYPE) 0, 0);
|
||||||
|
ret = ptrace_wait (null_ptid, &status);
|
||||||
|
|
||||||
|
/* We might get a SIGCHLD instead of an exit status. This is
|
||||||
|
aggravated by the first kill above - a child has just died. */
|
||||||
|
|
||||||
|
while (ret == pid && WIFSTOPPED (status))
|
||||||
|
{
|
||||||
|
ptrace (PT_KILL, pid, (PTRACE_ARG3_TYPE) 0, 0);
|
||||||
|
ret = ptrace_wait (null_ptid, &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_mourn_inferior ();
|
||||||
|
}
|
||||||
|
@ -65,7 +65,12 @@ extern int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len,
|
|||||||
int write, struct mem_attrib *attrib,
|
int write, struct mem_attrib *attrib,
|
||||||
struct target_ops *target);
|
struct target_ops *target);
|
||||||
|
|
||||||
|
/* linux-nat functions for handling fork events. */
|
||||||
extern void linux_record_stopped_pid (int pid);
|
extern void linux_record_stopped_pid (int pid);
|
||||||
|
extern void linux_enable_event_reporting (ptid_t ptid);
|
||||||
|
extern ptid_t linux_handle_extended_wait (int pid, int status,
|
||||||
|
struct target_waitstatus *ourstatus);
|
||||||
|
extern void linux_child_post_startup_inferior (ptid_t ptid);
|
||||||
|
|
||||||
/* Iterator function for lin-lwp's lwp list. */
|
/* Iterator function for lin-lwp's lwp list. */
|
||||||
struct lwp_info *iterate_over_lwps (int (*callback) (struct lwp_info *,
|
struct lwp_info *iterate_over_lwps (int (*callback) (struct lwp_info *,
|
||||||
|
Reference in New Issue
Block a user