| OLD | NEW |
| 1 /* This testcase is part of GDB, the GNU debugger. | 1 /* This testcase is part of GDB, the GNU debugger. |
| 2 | 2 |
| 3 Copyright 2009-2012 Free Software Foundation, Inc. | 3 Copyright 2010-2012 Free Software Foundation, Inc. |
| 4 | 4 |
| 5 This program is free software; you can redistribute it and/or modify | 5 This program is free software; you can redistribute it and/or modify |
| 6 it under the terms of the GNU General Public License as published by | 6 it under the terms of the GNU General Public License as published by |
| 7 the Free Software Foundation; either version 3 of the License, or | 7 the Free Software Foundation; either version 3 of the License, or |
| 8 (at your option) any later version. | 8 (at your option) any later version. |
| 9 | 9 |
| 10 This program is distributed in the hope that it will be useful, | 10 This program is distributed in the hope that it will be useful, |
| 11 but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 GNU General Public License for more details. | 13 GNU General Public License for more details. |
| 14 | 14 |
| 15 You should have received a copy of the GNU General Public License | 15 You should have received a copy of the GNU General Public License |
| 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 17 | 17 |
| 18 #define _GNU_SOURCE | 18 #define _GNU_SOURCE |
| 19 #include <pthread.h> | 19 #include <pthread.h> |
| 20 #include <stdio.h> | 20 #include <stdio.h> |
| 21 #include <limits.h> | 21 #include <limits.h> |
| 22 #include <errno.h> | 22 #include <errno.h> |
| 23 #include <stdlib.h> | 23 #include <stdlib.h> |
| 24 #include <string.h> | 24 #include <string.h> |
| 25 #include <assert.h> | 25 #include <assert.h> |
| 26 #include <sys/types.h> | 26 #include <sys/types.h> |
| 27 #include <signal.h> | 27 #include <signal.h> |
| 28 #include <unistd.h> | 28 #include <unistd.h> |
| 29 #include <asm/unistd.h> | 29 #include <asm/unistd.h> |
| 30 | 30 |
| 31 #define gettid() syscall (__NR_gettid) | 31 #define gettid() syscall (__NR_gettid) |
| 32 #define tgkill(tgid, tid, sig) syscall (__NR_tgkill, tgid, tid, sig) |
| 32 | 33 |
| 33 /* Terminate always in the main task, it can lock up with SIGSTOPped GDB | 34 /* Terminate always in the main task. It can lock up with SIGSTOPped |
| 34 otherwise. */ | 35 GDB otherwise. */ |
| 35 #define TIMEOUT (gettid () == getpid() ? 10 : 15) | 36 #define TIMEOUT (gettid () == getpid() ? 10 : 15) |
| 36 | 37 |
| 37 static pid_t thread1_tid; | 38 static pid_t thread1_tid; |
| 38 static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER; | 39 static pthread_cond_t thread1_tid_cond |
| 39 static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_
NP; | 40 = PTHREAD_COND_INITIALIZER; |
| 41 static pthread_mutex_t thread1_tid_mutex |
| 42 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
| 43 static int thread1_sigusr1_hit; |
| 44 static int thread1_sigusr2_hit; |
| 40 | 45 |
| 41 static pid_t thread2_tid; | 46 static pid_t thread2_tid; |
| 42 static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER; | 47 static pthread_cond_t thread2_tid_cond |
| 43 static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_
NP; | 48 = PTHREAD_COND_INITIALIZER; |
| 49 static pthread_mutex_t thread2_tid_mutex |
| 50 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
| 51 static int thread2_sigusr1_hit; |
| 52 static int thread2_sigusr2_hit; |
| 44 | 53 |
| 45 static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
; | 54 static pthread_mutex_t terminate_mutex |
| 55 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
| 46 | 56 |
| 47 /* These variables must have lower in-memory addresses than thread1_rwatch and | 57 /* Do not use alarm as it would create a ptrace event which would hang |
| 48 thread2_rwatch so that they take their watchpoint slots. */ | 58 us up if we are being traced by GDB, which we stopped |
| 59 ourselves. */ |
| 49 | 60 |
| 50 static int unused1_rwatch; | 61 static void |
| 51 static int unused2_rwatch; | 62 timed_mutex_lock (pthread_mutex_t *mutex) |
| 52 | |
| 53 static volatile int thread1_rwatch; | |
| 54 static volatile int thread2_rwatch; | |
| 55 | |
| 56 /* Do not use alarm as it would create a ptrace event which would hang up us if | |
| 57 we are being traced by GDB which we stopped ourselves. */ | |
| 58 | |
| 59 static void timed_mutex_lock (pthread_mutex_t *mutex) | |
| 60 { | 63 { |
| 61 int i; | 64 int i; |
| 62 struct timespec start, now; | 65 struct timespec start, now; |
| 63 | 66 |
| 64 i = clock_gettime (CLOCK_MONOTONIC, &start); | 67 i = clock_gettime (CLOCK_MONOTONIC, &start); |
| 65 assert (i == 0); | 68 assert (i == 0); |
| 66 | 69 |
| 67 do | 70 do |
| 68 { | 71 { |
| 69 i = pthread_mutex_trylock (mutex); | 72 i = pthread_mutex_trylock (mutex); |
| 70 if (i == 0) | 73 if (i == 0) |
| 71 return; | 74 return; |
| 72 assert (i == EBUSY); | 75 assert (i == EBUSY); |
| 73 | 76 |
| 74 i = clock_gettime (CLOCK_MONOTONIC, &now); | 77 i = clock_gettime (CLOCK_MONOTONIC, &now); |
| 75 assert (i == 0); | 78 assert (i == 0); |
| 76 assert (now.tv_sec >= start.tv_sec); | 79 assert (now.tv_sec >= start.tv_sec); |
| 77 } | 80 } |
| 78 while (now.tv_sec - start.tv_sec < TIMEOUT); | 81 while (now.tv_sec - start.tv_sec < TIMEOUT); |
| 79 | 82 |
| 80 fprintf (stderr, "Timed out waiting for internal lock!\n"); | 83 fprintf (stderr, "Timed out waiting for internal lock!\n"); |
| 81 exit (EXIT_FAILURE); | 84 exit (EXIT_FAILURE); |
| 82 } | 85 } |
| 83 | 86 |
| 87 static void |
| 88 handler (int signo, siginfo_t *siginfo, void *exception) |
| 89 { |
| 90 int *varp; |
| 91 |
| 92 assert (siginfo->si_signo == signo); |
| 93 assert (siginfo->si_code == SI_TKILL); |
| 94 assert (siginfo->si_pid == getpid ()); |
| 95 |
| 96 if (gettid () == thread1_tid) |
| 97 { |
| 98 if (signo == SIGUSR1) |
| 99 varp = &thread1_sigusr1_hit; |
| 100 else if (signo == SIGUSR2) |
| 101 varp = &thread1_sigusr2_hit; |
| 102 else |
| 103 assert (0); |
| 104 } |
| 105 else if (gettid () == thread2_tid) |
| 106 { |
| 107 if (signo == SIGUSR1) |
| 108 varp = &thread2_sigusr1_hit; |
| 109 else if (signo == SIGUSR2) |
| 110 varp = &thread2_sigusr2_hit; |
| 111 else |
| 112 assert (0); |
| 113 } |
| 114 else |
| 115 assert (0); |
| 116 |
| 117 if (*varp) |
| 118 { |
| 119 fprintf (stderr, "Signal %d for TID %lu has been already hit!\n", signo, |
| 120 (unsigned long) gettid ()); |
| 121 exit (EXIT_FAILURE); |
| 122 } |
| 123 *varp = 1; |
| 124 } |
| 125 |
| 84 static void * | 126 static void * |
| 85 thread1_func (void *unused) | 127 thread1_func (void *unused) |
| 86 { | 128 { |
| 87 int i; | 129 int i; |
| 88 volatile int rwatch_store; | |
| 89 | 130 |
| 90 timed_mutex_lock (&thread1_tid_mutex); | 131 timed_mutex_lock (&thread1_tid_mutex); |
| 91 | 132 |
| 92 /* THREAD1_TID_MUTEX must be already locked to avoid race. */ | 133 /* THREAD1_TID_MUTEX must be already locked to avoid a race. */ |
| 93 thread1_tid = gettid (); | 134 thread1_tid = gettid (); |
| 94 | 135 |
| 95 i = pthread_cond_signal (&thread1_tid_cond); | 136 i = pthread_cond_signal (&thread1_tid_cond); |
| 96 assert (i == 0); | 137 assert (i == 0); |
| 97 i = pthread_mutex_unlock (&thread1_tid_mutex); | 138 i = pthread_mutex_unlock (&thread1_tid_mutex); |
| 98 assert (i == 0); | 139 assert (i == 0); |
| 99 | 140 |
| 100 rwatch_store = thread1_rwatch; | 141 /* Be sure the "t (tracing stop)" test can proceed for both |
| 101 | 142 threads. */ |
| 102 /* Be sure the "t (tracing stop)" test can proceed for both threads. */ | |
| 103 timed_mutex_lock (&terminate_mutex); | 143 timed_mutex_lock (&terminate_mutex); |
| 104 i = pthread_mutex_unlock (&terminate_mutex); | 144 i = pthread_mutex_unlock (&terminate_mutex); |
| 105 assert (i == 0); | 145 assert (i == 0); |
| 106 | 146 |
| 147 if (!thread1_sigusr1_hit) |
| 148 { |
| 149 fprintf (stderr, "Thread 1 signal SIGUSR1 not hit!\n"); |
| 150 exit (EXIT_FAILURE); |
| 151 } |
| 152 if (!thread1_sigusr2_hit) |
| 153 { |
| 154 fprintf (stderr, "Thread 1 signal SIGUSR2 not hit!\n"); |
| 155 exit (EXIT_FAILURE); |
| 156 } |
| 157 |
| 107 return NULL; | 158 return NULL; |
| 108 } | 159 } |
| 109 | 160 |
| 110 static void * | 161 static void * |
| 111 thread2_func (void *unused) | 162 thread2_func (void *unused) |
| 112 { | 163 { |
| 113 int i; | 164 int i; |
| 114 volatile int rwatch_store; | |
| 115 | 165 |
| 116 timed_mutex_lock (&thread2_tid_mutex); | 166 timed_mutex_lock (&thread2_tid_mutex); |
| 117 | 167 |
| 118 /* THREAD2_TID_MUTEX must be already locked to avoid race. */ | 168 /* THREAD2_TID_MUTEX must be already locked to avoid a race. */ |
| 119 thread2_tid = gettid (); | 169 thread2_tid = gettid (); |
| 120 | 170 |
| 121 i = pthread_cond_signal (&thread2_tid_cond); | 171 i = pthread_cond_signal (&thread2_tid_cond); |
| 122 assert (i == 0); | 172 assert (i == 0); |
| 123 i = pthread_mutex_unlock (&thread2_tid_mutex); | 173 i = pthread_mutex_unlock (&thread2_tid_mutex); |
| 124 assert (i == 0); | 174 assert (i == 0); |
| 125 | 175 |
| 126 rwatch_store = thread2_rwatch; | 176 /* Be sure the "t (tracing stop)" test can proceed for both |
| 127 | 177 threads. */ |
| 128 /* Be sure the "t (tracing stop)" test can proceed for both threads. */ | |
| 129 timed_mutex_lock (&terminate_mutex); | 178 timed_mutex_lock (&terminate_mutex); |
| 130 i = pthread_mutex_unlock (&terminate_mutex); | 179 i = pthread_mutex_unlock (&terminate_mutex); |
| 131 assert (i == 0); | 180 assert (i == 0); |
| 132 | 181 |
| 182 if (!thread2_sigusr1_hit) |
| 183 { |
| 184 fprintf (stderr, "Thread 2 signal SIGUSR1 not hit!\n"); |
| 185 exit (EXIT_FAILURE); |
| 186 } |
| 187 if (!thread2_sigusr2_hit) |
| 188 { |
| 189 fprintf (stderr, "Thread 2 signal SIGUSR2 not hit!\n"); |
| 190 exit (EXIT_FAILURE); |
| 191 } |
| 192 |
| 133 return NULL; | 193 return NULL; |
| 134 } | 194 } |
| 135 | 195 |
| 136 static const char * | 196 static const char * |
| 137 proc_string (const char *filename, const char *line) | 197 proc_string (const char *filename, const char *line) |
| 138 { | 198 { |
| 139 FILE *f; | 199 FILE *f; |
| 140 static char buf[LINE_MAX]; | 200 static char buf[LINE_MAX]; |
| 141 size_t line_len = strlen (line); | 201 size_t line_len = strlen (line); |
| 142 | 202 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 i = kill (tracer_save, SIGCONT); | 319 i = kill (tracer_save, SIGCONT); |
| 260 assert (i == 0); | 320 assert (i == 0); |
| 261 } | 321 } |
| 262 } | 322 } |
| 263 | 323 |
| 264 int | 324 int |
| 265 main (int argc, char **argv) | 325 main (int argc, char **argv) |
| 266 { | 326 { |
| 267 int i; | 327 int i; |
| 268 int standalone = 0; | 328 int standalone = 0; |
| 329 struct sigaction act; |
| 269 | 330 |
| 270 if (argc == 2 && strcmp (argv[1], "-s") == 0) | 331 if (argc == 2 && strcmp (argv[1], "-s") == 0) |
| 271 standalone = 1; | 332 standalone = 1; |
| 272 else | 333 else |
| 273 assert (argc == 1); | 334 assert (argc == 1); |
| 274 | 335 |
| 275 setbuf (stdout, NULL); | 336 setbuf (stdout, NULL); |
| 276 | 337 |
| 277 timed_mutex_lock (&thread1_tid_mutex); | 338 timed_mutex_lock (&thread1_tid_mutex); |
| 278 timed_mutex_lock (&thread2_tid_mutex); | 339 timed_mutex_lock (&thread2_tid_mutex); |
| 279 | 340 |
| 280 timed_mutex_lock (&terminate_mutex); | 341 timed_mutex_lock (&terminate_mutex); |
| 281 | 342 |
| 343 errno = 0; |
| 344 memset (&act, 0, sizeof (act)); |
| 345 act.sa_sigaction = handler; |
| 346 act.sa_flags = SA_RESTART | SA_SIGINFO; |
| 347 i = sigemptyset (&act.sa_mask); |
| 348 assert_perror (errno); |
| 349 assert (i == 0); |
| 350 i = sigaction (SIGUSR1, &act, NULL); |
| 351 assert_perror (errno); |
| 352 assert (i == 0); |
| 353 i = sigaction (SIGUSR2, &act, NULL); |
| 354 assert_perror (errno); |
| 355 assert (i == 0); |
| 356 |
| 282 i = pthread_create (&thread1, NULL, thread1_func, NULL); | 357 i = pthread_create (&thread1, NULL, thread1_func, NULL); |
| 283 assert (i == 0); | 358 assert (i == 0); |
| 284 | 359 |
| 285 i = pthread_create (&thread2, NULL, thread2_func, NULL); | 360 i = pthread_create (&thread2, NULL, thread2_func, NULL); |
| 286 assert (i == 0); | 361 assert (i == 0); |
| 287 | 362 |
| 288 if (!standalone) | 363 if (!standalone) |
| 289 { | 364 { |
| 290 tracer = proc_ulong ("/proc/self/status", "TracerPid:\t"); | 365 tracer = proc_ulong ("/proc/self/status", "TracerPid:\t"); |
| 291 if (tracer == 0) | 366 if (tracer == 0) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 307 | 382 |
| 308 printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); | 383 printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); |
| 309 | 384 |
| 310 if (tracer) | 385 if (tracer) |
| 311 { | 386 { |
| 312 i = kill (tracer, SIGSTOP); | 387 i = kill (tracer, SIGSTOP); |
| 313 assert (i == 0); | 388 assert (i == 0); |
| 314 state_wait (tracer, "T (stopped)"); | 389 state_wait (tracer, "T (stopped)"); |
| 315 } | 390 } |
| 316 | 391 |
| 317 /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so | 392 /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) |
| 318 they could not trigger the watchpoints before GDB gets unstopped later. | 393 and so they could not trigger the signals before GDB is unstopped |
| 319 Threads get resumed at pthread_cond_wait below. Use `while' loops for | 394 later. Threads get resumed by the pthread_cond_wait below. Use |
| 320 protection against spurious pthread_cond_wait wakeups. */ | 395 `while' loops for protection against spurious pthread_cond_wait |
| 396 wakeups. */ |
| 321 | 397 |
| 322 printf ("Waiting till the threads initialize their TIDs.\n"); | 398 printf ("Waiting till the threads initialize their TIDs.\n"); |
| 323 | 399 |
| 324 while (thread1_tid == 0) | 400 while (thread1_tid == 0) |
| 325 { | 401 { |
| 326 i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex); | 402 i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex); |
| 327 assert (i == 0); | 403 assert (i == 0); |
| 328 } | 404 } |
| 329 | 405 |
| 330 while (thread2_tid == 0) | 406 while (thread2_tid == 0) |
| 331 { | 407 { |
| 332 i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex); | 408 i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex); |
| 333 assert (i == 0); | 409 assert (i == 0); |
| 334 } | 410 } |
| 335 | 411 |
| 336 printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n", | 412 printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n", |
| 337 (unsigned long) thread1_tid, (unsigned long) thread2_tid, | 413 (unsigned long) thread1_tid, (unsigned long) thread2_tid, |
| 338 (unsigned long) getpid ()); | 414 (unsigned long) getpid ()); |
| 339 | 415 |
| 340 printf ("Waiting till the threads get trapped by the watchpoints.\n"); | 416 errno = 0; |
| 417 i = tgkill (getpid (), thread1_tid, SIGUSR1); |
| 418 assert_perror (errno); |
| 419 assert (i == 0); |
| 420 i = tgkill (getpid (), thread1_tid, SIGUSR2); |
| 421 assert_perror (errno); |
| 422 assert (i == 0); |
| 423 i = tgkill (getpid (), thread2_tid, SIGUSR1); |
| 424 assert_perror (errno); |
| 425 assert (i == 0); |
| 426 i = tgkill (getpid (), thread2_tid, SIGUSR2); |
| 427 assert_perror (errno); |
| 428 assert (i == 0); |
| 429 |
| 430 printf ("Waiting till the threads are trapped by the signals.\n"); |
| 341 | 431 |
| 342 if (tracer) | 432 if (tracer) |
| 343 { | 433 { |
| 344 /* s390x-unknown-linux-gnu will fail with "R (running)". */ | 434 /* s390x-unknown-linux-gnu will fail with "R (running)". */ |
| 345 | 435 |
| 346 state_wait (thread1_tid, "t (tracing stop)"); | 436 state_wait (thread1_tid, "t (tracing stop)"); |
| 347 | 437 |
| 348 state_wait (thread2_tid, "t (tracing stop)"); | 438 state_wait (thread2_tid, "t (tracing stop)"); |
| 349 } | 439 } |
| 350 | 440 |
| 351 cleanup (); | 441 cleanup (); |
| 352 | 442 |
| 353 printf ("Joining the threads.\n"); | 443 printf ("Joining the threads.\n"); |
| 354 | 444 |
| 355 i = pthread_mutex_unlock (&terminate_mutex); | 445 i = pthread_mutex_unlock (&terminate_mutex); |
| 356 assert (i == 0); | 446 assert (i == 0); |
| 357 | 447 |
| 358 i = pthread_join (thread1, NULL); | 448 i = pthread_join (thread1, NULL); |
| 359 assert (i == 0); | 449 assert (i == 0); |
| 360 | 450 |
| 361 i = pthread_join (thread2, NULL); | 451 i = pthread_join (thread2, NULL); |
| 362 assert (i == 0); | 452 assert (i == 0); |
| 363 | 453 |
| 364 printf ("Exiting.\n"); /* break-at-exit */ | 454 printf ("Exiting.\n"); /* break-at-exit */ |
| 365 | 455 |
| 366 /* Just prevent compiler `warning: unusedX_rwatch defined but not used'. */ | |
| 367 unused1_rwatch = 1; | |
| 368 unused2_rwatch = 2; | |
| 369 | |
| 370 return EXIT_SUCCESS; | 456 return EXIT_SUCCESS; |
| 371 } | 457 } |
| OLD | NEW |