| Index: gdb/testsuite/gdb.threads/siginfo-threads.c
|
| diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.c b/gdb/testsuite/gdb.threads/siginfo-threads.c
|
| similarity index 67%
|
| copy from gdb/testsuite/gdb.threads/watchthreads-reorder.c
|
| copy to gdb/testsuite/gdb.threads/siginfo-threads.c
|
| index ccded9920dd65607268e91cbf328ed7c50ef6db2..58590888ade00e88652d2ffb9c32cf6f8f6ee975 100644
|
| --- a/gdb/testsuite/gdb.threads/watchthreads-reorder.c
|
| +++ b/gdb/testsuite/gdb.threads/siginfo-threads.c
|
| @@ -1,6 +1,6 @@
|
| /* This testcase is part of GDB, the GNU debugger.
|
|
|
| - Copyright 2009-2012 Free Software Foundation, Inc.
|
| + Copyright 2010-2012 Free Software Foundation, Inc.
|
|
|
| This program is free software; you can redistribute it and/or modify
|
| it under the terms of the GNU General Public License as published by
|
| @@ -29,34 +29,37 @@
|
| #include <asm/unistd.h>
|
|
|
| #define gettid() syscall (__NR_gettid)
|
| +#define tgkill(tgid, tid, sig) syscall (__NR_tgkill, tgid, tid, sig)
|
|
|
| -/* Terminate always in the main task, it can lock up with SIGSTOPped GDB
|
| - otherwise. */
|
| +/* Terminate always in the main task. It can lock up with SIGSTOPped
|
| + GDB otherwise. */
|
| #define TIMEOUT (gettid () == getpid() ? 10 : 15)
|
|
|
| static pid_t thread1_tid;
|
| -static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER;
|
| -static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
| +static pthread_cond_t thread1_tid_cond
|
| + = PTHREAD_COND_INITIALIZER;
|
| +static pthread_mutex_t thread1_tid_mutex
|
| + = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
| +static int thread1_sigusr1_hit;
|
| +static int thread1_sigusr2_hit;
|
|
|
| static pid_t thread2_tid;
|
| -static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER;
|
| -static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
| +static pthread_cond_t thread2_tid_cond
|
| + = PTHREAD_COND_INITIALIZER;
|
| +static pthread_mutex_t thread2_tid_mutex
|
| + = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
| +static int thread2_sigusr1_hit;
|
| +static int thread2_sigusr2_hit;
|
|
|
| -static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
| +static pthread_mutex_t terminate_mutex
|
| + = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
|
|
| -/* These variables must have lower in-memory addresses than thread1_rwatch and
|
| - thread2_rwatch so that they take their watchpoint slots. */
|
| +/* Do not use alarm as it would create a ptrace event which would hang
|
| + us up if we are being traced by GDB, which we stopped
|
| + ourselves. */
|
|
|
| -static int unused1_rwatch;
|
| -static int unused2_rwatch;
|
| -
|
| -static volatile int thread1_rwatch;
|
| -static volatile int thread2_rwatch;
|
| -
|
| -/* Do not use alarm as it would create a ptrace event which would hang up us if
|
| - we are being traced by GDB which we stopped ourselves. */
|
| -
|
| -static void timed_mutex_lock (pthread_mutex_t *mutex)
|
| +static void
|
| +timed_mutex_lock (pthread_mutex_t *mutex)
|
| {
|
| int i;
|
| struct timespec start, now;
|
| @@ -81,15 +84,53 @@ static void timed_mutex_lock (pthread_mutex_t *mutex)
|
| exit (EXIT_FAILURE);
|
| }
|
|
|
| +static void
|
| +handler (int signo, siginfo_t *siginfo, void *exception)
|
| +{
|
| + int *varp;
|
| +
|
| + assert (siginfo->si_signo == signo);
|
| + assert (siginfo->si_code == SI_TKILL);
|
| + assert (siginfo->si_pid == getpid ());
|
| +
|
| + if (gettid () == thread1_tid)
|
| + {
|
| + if (signo == SIGUSR1)
|
| + varp = &thread1_sigusr1_hit;
|
| + else if (signo == SIGUSR2)
|
| + varp = &thread1_sigusr2_hit;
|
| + else
|
| + assert (0);
|
| + }
|
| + else if (gettid () == thread2_tid)
|
| + {
|
| + if (signo == SIGUSR1)
|
| + varp = &thread2_sigusr1_hit;
|
| + else if (signo == SIGUSR2)
|
| + varp = &thread2_sigusr2_hit;
|
| + else
|
| + assert (0);
|
| + }
|
| + else
|
| + assert (0);
|
| +
|
| + if (*varp)
|
| + {
|
| + fprintf (stderr, "Signal %d for TID %lu has been already hit!\n", signo,
|
| + (unsigned long) gettid ());
|
| + exit (EXIT_FAILURE);
|
| + }
|
| + *varp = 1;
|
| +}
|
| +
|
| static void *
|
| thread1_func (void *unused)
|
| {
|
| int i;
|
| - volatile int rwatch_store;
|
|
|
| timed_mutex_lock (&thread1_tid_mutex);
|
|
|
| - /* THREAD1_TID_MUTEX must be already locked to avoid race. */
|
| + /* THREAD1_TID_MUTEX must be already locked to avoid a race. */
|
| thread1_tid = gettid ();
|
|
|
| i = pthread_cond_signal (&thread1_tid_cond);
|
| @@ -97,13 +138,23 @@ thread1_func (void *unused)
|
| i = pthread_mutex_unlock (&thread1_tid_mutex);
|
| assert (i == 0);
|
|
|
| - rwatch_store = thread1_rwatch;
|
| -
|
| - /* Be sure the "t (tracing stop)" test can proceed for both threads. */
|
| + /* Be sure the "t (tracing stop)" test can proceed for both
|
| + threads. */
|
| timed_mutex_lock (&terminate_mutex);
|
| i = pthread_mutex_unlock (&terminate_mutex);
|
| assert (i == 0);
|
|
|
| + if (!thread1_sigusr1_hit)
|
| + {
|
| + fprintf (stderr, "Thread 1 signal SIGUSR1 not hit!\n");
|
| + exit (EXIT_FAILURE);
|
| + }
|
| + if (!thread1_sigusr2_hit)
|
| + {
|
| + fprintf (stderr, "Thread 1 signal SIGUSR2 not hit!\n");
|
| + exit (EXIT_FAILURE);
|
| + }
|
| +
|
| return NULL;
|
| }
|
|
|
| @@ -111,11 +162,10 @@ static void *
|
| thread2_func (void *unused)
|
| {
|
| int i;
|
| - volatile int rwatch_store;
|
|
|
| timed_mutex_lock (&thread2_tid_mutex);
|
|
|
| - /* THREAD2_TID_MUTEX must be already locked to avoid race. */
|
| + /* THREAD2_TID_MUTEX must be already locked to avoid a race. */
|
| thread2_tid = gettid ();
|
|
|
| i = pthread_cond_signal (&thread2_tid_cond);
|
| @@ -123,13 +173,23 @@ thread2_func (void *unused)
|
| i = pthread_mutex_unlock (&thread2_tid_mutex);
|
| assert (i == 0);
|
|
|
| - rwatch_store = thread2_rwatch;
|
| -
|
| - /* Be sure the "t (tracing stop)" test can proceed for both threads. */
|
| + /* Be sure the "t (tracing stop)" test can proceed for both
|
| + threads. */
|
| timed_mutex_lock (&terminate_mutex);
|
| i = pthread_mutex_unlock (&terminate_mutex);
|
| assert (i == 0);
|
|
|
| + if (!thread2_sigusr1_hit)
|
| + {
|
| + fprintf (stderr, "Thread 2 signal SIGUSR1 not hit!\n");
|
| + exit (EXIT_FAILURE);
|
| + }
|
| + if (!thread2_sigusr2_hit)
|
| + {
|
| + fprintf (stderr, "Thread 2 signal SIGUSR2 not hit!\n");
|
| + exit (EXIT_FAILURE);
|
| + }
|
| +
|
| return NULL;
|
| }
|
|
|
| @@ -266,6 +326,7 @@ main (int argc, char **argv)
|
| {
|
| int i;
|
| int standalone = 0;
|
| + struct sigaction act;
|
|
|
| if (argc == 2 && strcmp (argv[1], "-s") == 0)
|
| standalone = 1;
|
| @@ -279,6 +340,20 @@ main (int argc, char **argv)
|
|
|
| timed_mutex_lock (&terminate_mutex);
|
|
|
| + errno = 0;
|
| + memset (&act, 0, sizeof (act));
|
| + act.sa_sigaction = handler;
|
| + act.sa_flags = SA_RESTART | SA_SIGINFO;
|
| + i = sigemptyset (&act.sa_mask);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| + i = sigaction (SIGUSR1, &act, NULL);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| + i = sigaction (SIGUSR2, &act, NULL);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| +
|
| i = pthread_create (&thread1, NULL, thread1_func, NULL);
|
| assert (i == 0);
|
|
|
| @@ -314,10 +389,11 @@ main (int argc, char **argv)
|
| state_wait (tracer, "T (stopped)");
|
| }
|
|
|
| - /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so
|
| - they could not trigger the watchpoints before GDB gets unstopped later.
|
| - Threads get resumed at pthread_cond_wait below. Use `while' loops for
|
| - protection against spurious pthread_cond_wait wakeups. */
|
| + /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex)
|
| + and so they could not trigger the signals before GDB is unstopped
|
| + later. Threads get resumed by the pthread_cond_wait below. Use
|
| + `while' loops for protection against spurious pthread_cond_wait
|
| + wakeups. */
|
|
|
| printf ("Waiting till the threads initialize their TIDs.\n");
|
|
|
| @@ -337,7 +413,21 @@ main (int argc, char **argv)
|
| (unsigned long) thread1_tid, (unsigned long) thread2_tid,
|
| (unsigned long) getpid ());
|
|
|
| - printf ("Waiting till the threads get trapped by the watchpoints.\n");
|
| + errno = 0;
|
| + i = tgkill (getpid (), thread1_tid, SIGUSR1);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| + i = tgkill (getpid (), thread1_tid, SIGUSR2);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| + i = tgkill (getpid (), thread2_tid, SIGUSR1);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| + i = tgkill (getpid (), thread2_tid, SIGUSR2);
|
| + assert_perror (errno);
|
| + assert (i == 0);
|
| +
|
| + printf ("Waiting till the threads are trapped by the signals.\n");
|
|
|
| if (tracer)
|
| {
|
| @@ -363,9 +453,5 @@ main (int argc, char **argv)
|
|
|
| printf ("Exiting.\n"); /* break-at-exit */
|
|
|
| - /* Just prevent compiler `warning: unusedX_rwatch defined but not used'. */
|
| - unused1_rwatch = 1;
|
| - unused2_rwatch = 2;
|
| -
|
| return EXIT_SUCCESS;
|
| }
|
|
|