linuxthreads package heavily relies on wait() synchronization to keep
them correct. */
+#include "defs.h"
#include <sys/types.h> /* for pid_t */
#include <sys/ptrace.h> /* for PT_* flags */
-#include <sys/wait.h> /* for WUNTRACED and __WCLONE flags */
+#include "gdb_wait.h" /* for WUNTRACED and __WCLONE flags */
#include <signal.h> /* for struct sigaction and NSIG */
#include <sys/utsname.h>
-#include "defs.h"
#include "target.h"
#include "inferior.h"
#include "gdbcore.h"
#include "gdbthread.h"
-#include "wait.h"
#include "gdbcmd.h"
#include "breakpoint.h"
#endif
/* Check to see if the given thread is alive. */
static int
-linuxthreads_thread_alive (pid)
- int pid;
+linuxthreads_thread_alive (int pid)
{
errno = 0;
return ptrace (PT_READ_U, pid, (PTRACE_ARG3_TYPE)0, 0) >= 0 || errno == 0;
our efforts to debug it, accept them with wait, but don't pass them
through to PID. Do pass all other signals through. */
static int
-linuxthreads_find_trap (pid, stop)
- int pid;
- int stop;
+linuxthreads_find_trap (int pid, int stop)
{
int i;
int rpid;
/* Cleanup stub for save_inferior_pid. */
static void
-restore_inferior_pid (arg)
- void *arg;
+restore_inferior_pid (void *arg)
{
-#if TARGET_PTR_BIT > TARGET_INT_BIT
- inferior_pid = (int) ((long) arg);
-#else
- inferior_pid = (int) arg;
-#endif
+ int *saved_pid_ptr = arg;
+ inferior_pid = *saved_pid_ptr;
+ free (arg);
}
/* Register a cleanup to restore the value of inferior_pid. */
static struct cleanup *
-save_inferior_pid ()
+save_inferior_pid (void)
{
-#if TARGET_PTR_BIT > TARGET_INT_BIT
- return make_cleanup (restore_inferior_pid, (void *) ((long) inferior_pid));
-#else
- return make_cleanup (restore_inferior_pid, (void *) inferior_pid);
-#endif
+ int *saved_pid_ptr;
+
+ saved_pid_ptr = xmalloc (sizeof (int));
+ *saved_pid_ptr = inferior_pid;
+ return make_cleanup (restore_inferior_pid, saved_pid_ptr);
}
static void
-sigchld_handler (signo)
- int signo;
+sigchld_handler (int signo)
{
/* This handler is used to get an EINTR while doing waitpid()
when an event is received */
/* Have we already collected a wait status for PID in the
linuxthreads_wait bag? */
static int
-linuxthreads_pending_status (pid)
- int pid;
+linuxthreads_pending_status (int pid)
{
int i;
for (i = linuxthreads_wait_last; i >= 0; i--)
in OBJFILE, so we complain if it's required, but not there.
Return true iff things are okay. */
static int
-find_signal_var (sig, objfile)
- struct linuxthreads_signal *sig;
- struct objfile *objfile;
+find_signal_var (struct linuxthreads_signal *sig, struct objfile *objfile)
{
struct minimal_symbol *ms = lookup_minimal_symbol (sig->var, NULL, objfile);
}
static int
-find_all_signal_vars (objfile)
- struct objfile *objfile;
+find_all_signal_vars (struct objfile *objfile)
{
return ( find_signal_var (&linuxthreads_sig_restart, objfile)
&& find_signal_var (&linuxthreads_sig_cancel, objfile)
been initialized yet. If it has, tell GDB to pass that signal
through to the inferior silently. */
static void
-check_signal_number (sig)
- struct linuxthreads_signal *sig;
+check_signal_number (struct linuxthreads_signal *sig)
{
int num;
}
void
-check_all_signal_numbers ()
+check_all_signal_numbers (void)
{
/* If this isn't a LinuxThreads program, quit early. */
if (! linuxthreads_max)
talking to an executable that uses LinuxThreads, so we clear the
signal number and variable address too. */
static void
-restore_signal (sig)
- struct linuxthreads_signal *sig;
+restore_signal (struct linuxthreads_signal *sig)
{
if (! sig->signal)
return;
talking to an executable that uses LinuxThreads, so we clear the
signal number and variable address too. */
static void
-restore_all_signals ()
+restore_all_signals (void)
{
restore_signal (&linuxthreads_sig_restart);
restore_signal (&linuxthreads_sig_cancel);
If ALL is non-zero, process all threads.
If ALL is zero, skip threads with pending status. */
static void
-iterate_active_threads (func, all)
- void (*func)(int);
- int all;
+iterate_active_threads (void (*func) (int), int all)
{
CORE_ADDR descr;
int pid;
This is the worker function for linuxthreads_insert_breakpoint,
which passes it to iterate_active_threads. */
static void
-insert_breakpoint (pid)
- int pid;
+insert_breakpoint (int pid)
{
int j;
breakpoint if the thread's PC is pointing at the breakpoint being
removed. */
static void
-remove_breakpoint (pid)
- int pid;
+remove_breakpoint (int pid)
{
int j;
/* Kill a thread */
static void
-kill_thread (pid)
- int pid;
+kill_thread (int pid)
{
if (in_thread_list (pid))
{
/* Resume a thread */
static void
-resume_thread (pid)
- int pid;
+resume_thread (int pid)
{
if (pid != inferior_pid
&& in_thread_list (pid)
/* Detach a thread */
static void
-detach_thread (pid)
- int pid;
+detach_thread (int pid)
{
if (in_thread_list (pid) && linuxthreads_thread_alive (pid))
{
/* Attach a thread */
void
-attach_thread (pid)
- int pid;
+attach_thread (int pid)
{
if (ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0) != 0)
perror_with_name ("attach_thread");
/* Stop a thread */
static void
-stop_thread (pid)
- int pid;
+stop_thread (int pid)
{
if (pid != inferior_pid)
{
/* Wait for a thread */
static void
-wait_thread (pid)
- int pid;
+wait_thread (int pid)
{
int status;
int rpid;
/* Walk through the linuxthreads handles in order to detect all
threads and stop them */
static void
-update_stop_threads (test_pid)
- int test_pid;
+update_stop_threads (int test_pid)
{
struct cleanup *old_chain = NULL;
*/
/* Saved pointer to previous owner of the new_objfile event. */
-static void (*target_new_objfile_chain) PARAMS ((struct objfile *));
+static void (*target_new_objfile_chain) (struct objfile *);
void
-linuxthreads_new_objfile (objfile)
- struct objfile *objfile;
+linuxthreads_new_objfile (struct objfile *objfile)
{
struct minimal_symbol *ms;
return 1 otherwise 0. */
int
-linuxthreads_prepare_to_proceed (step)
- int step;
+linuxthreads_prepare_to_proceed (int step)
{
if (!linuxthreads_max
|| !linuxthreads_manager_pid
/* Convert a pid to printable form. */
char *
-linuxthreads_pid_to_str (pid)
- int pid;
+linuxthreads_pid_to_str (int pid)
{
static char buf[100];
and wait for the trace-trap that results from attaching. */
static void
-linuxthreads_attach (args, from_tty)
- char *args;
- int from_tty;
+linuxthreads_attach (char *args, int from_tty)
{
if (!args)
error_no_arg ("process-id to attach");
linuxthreads_breakpoints_inserted = 1;
linuxthreads_breakpoint_last = -1;
linuxthreads_wait_last = -1;
- linuxthreads_exit_status = __W_STOPCODE(0);
+ WSETSTOP (linuxthreads_exit_status, 0);
child_ops.to_attach (args, from_tty);
started via the normal ptrace (PTRACE_TRACEME). */
static void
-linuxthreads_detach (args, from_tty)
- char *args;
- int from_tty;
+linuxthreads_detach (char *args, int from_tty)
{
if (linuxthreads_max)
{
linuxthreads_find_trap (inferior_pid, 1);
linuxthreads_wait_last = -1;
- linuxthreads_exit_status = __W_STOPCODE(0);
+ WSETSTOP (linuxthreads_exit_status, 0);
}
linuxthreads_inferior_pid = 0;
signal activated. */
static void
-linuxthreads_resume (pid, step, signo)
- int pid;
- int step;
- enum target_signal signo;
+linuxthreads_resume (int pid, int step, enum target_signal signo)
{
if (!linuxthreads_max || stop_soon_quietly || linuxthreads_manager_pid == 0)
{
/* Abstract out the child_wait functionality. */
int
-linux_child_wait (pid, rpid, status)
- int pid;
- int *rpid;
- int *status;
+linux_child_wait (int pid, int *rpid, int *status)
{
int save_errno;
to a LWP id, and vice versa on the way out. */
static int
-linuxthreads_wait (pid, ourstatus)
- int pid;
- struct target_waitstatus *ourstatus;
+linuxthreads_wait (int pid, struct target_waitstatus *ourstatus)
{
int status;
int rpid;
/* Fork an inferior process, and start debugging it with ptrace. */
static void
-linuxthreads_create_inferior (exec_file, allargs, env)
- char *exec_file;
- char *allargs;
- char **env;
+linuxthreads_create_inferior (char *exec_file, char *allargs, char **env)
{
if (!exec_file && !exec_bfd)
{
linuxthreads_breakpoints_inserted = 1;
linuxthreads_breakpoint_last = -1;
linuxthreads_wait_last = -1;
- linuxthreads_exit_status = __W_STOPCODE(0);
+ WSETSTOP (linuxthreads_exit_status, 0);
if (linuxthreads_max)
linuxthreads_attach_pending = 1;
}
void
-linuxthreads_discard_global_state ()
+linuxthreads_discard_global_state (void)
{
linuxthreads_inferior_pid = 0;
linuxthreads_breakpoint_pid = 0;
/* Clean up after the inferior dies. */
static void
-linuxthreads_mourn_inferior ()
+linuxthreads_mourn_inferior (void)
{
if (linuxthreads_max)
{
/* Kill the inferior process */
static void
-linuxthreads_kill ()
+linuxthreads_kill (void)
{
int rpid;
int status;
/* Insert a breakpoint */
static int
-linuxthreads_insert_breakpoint (addr, contents_cache)
- CORE_ADDR addr;
- char *contents_cache;
+linuxthreads_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
{
if (linuxthreads_max && linuxthreads_manager_pid != 0)
{
/* Remove a breakpoint */
static int
-linuxthreads_remove_breakpoint (addr, contents_cache)
- CORE_ADDR addr;
- char *contents_cache;
+linuxthreads_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
{
if (linuxthreads_max && linuxthreads_manager_pid != 0)
{
/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
static int
-linuxthreads_can_run ()
+linuxthreads_can_run (void)
{
return child_suppress_run;
}
\f
static void
-init_linuxthreads_ops ()
+init_linuxthreads_ops (void)
{
linuxthreads_ops.to_shortname = "linuxthreads";
linuxthreads_ops.to_longname = "LINUX threads and pthread.";
}
void
-_initialize_linuxthreads ()
+_initialize_linuxthreads (void)
{
struct sigaction sact;
sigset_t linuxthreads_wait_mask; /* sigset with SIGCHLD */
sigprocmask(SIG_BLOCK,
&linuxthreads_wait_mask,
&linuxthreads_block_mask);
+ /* Make sure that linuxthreads_block_mask is not blocking SIGCHLD */
+ sigdelset (&linuxthreads_block_mask, SIGCHLD);
}