Remove obsolete test from gdb.cp/var-tag.exp
[binutils-gdb.git] / gdb / testsuite / gdb.threads / ia64-sigill.c
blob183f376ce9bc69c752a915ed0589ba07d6db1a17
1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2010-2024 Free Software Foundation, Inc.
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
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
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/>. */
18 #define _GNU_SOURCE
19 #include <pthread.h>
20 #include <stdio.h>
21 #include <limits.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <sys/types.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <asm/unistd.h>
31 #define gettid() syscall (__NR_gettid)
33 /* Terminate always in the main task, it can lock up with SIGSTOPped GDB
34 otherwise. */
35 #define TIMEOUT (gettid () == getpid() ? 10 : 15)
37 static pid_t thread1_tid;
38 static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER;
39 static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
41 static pid_t thread2_tid;
42 static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER;
43 static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
45 static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
47 static pthread_barrier_t threads_started_barrier;
49 /* Do not use alarm as it would create a ptrace event which would hang up us if
50 we are being traced by GDB which we stopped ourselves. */
52 static void timed_mutex_lock (pthread_mutex_t *mutex)
54 int i;
55 struct timespec start, now;
57 i = clock_gettime (CLOCK_MONOTONIC, &start);
58 assert (i == 0);
62 i = pthread_mutex_trylock (mutex);
63 if (i == 0)
64 return;
65 assert (i == EBUSY);
67 i = clock_gettime (CLOCK_MONOTONIC, &now);
68 assert (i == 0);
69 assert (now.tv_sec >= start.tv_sec);
71 while (now.tv_sec - start.tv_sec < TIMEOUT);
73 fprintf (stderr, "Timed out waiting for internal lock!\n");
74 exit (EXIT_FAILURE);
77 static void *
78 thread_func (void *threadno_voidp)
80 int threadno = (intptr_t) threadno_voidp;
81 int i;
83 pthread_barrier_wait (&threads_started_barrier);
85 switch (threadno)
87 case 1:
88 timed_mutex_lock (&thread1_tid_mutex);
90 /* THREAD1_TID_MUTEX must be already locked to avoid race. */
91 thread1_tid = gettid ();
93 i = pthread_cond_signal (&thread1_tid_cond);
94 assert (i == 0);
95 i = pthread_mutex_unlock (&thread1_tid_mutex);
96 assert (i == 0);
98 break;
100 case 2:
101 timed_mutex_lock (&thread2_tid_mutex);
103 /* THREAD2_TID_MUTEX must be already locked to avoid race. */
104 thread2_tid = gettid ();
106 i = pthread_cond_signal (&thread2_tid_cond);
107 assert (i == 0);
108 i = pthread_mutex_unlock (&thread2_tid_mutex);
109 assert (i == 0);
111 break;
113 default:
114 assert (0);
117 #ifdef __ia64__
118 asm volatile ("label:\n"
119 "nop.m 0\n"
120 "nop.i 0\n"
121 "nop.b 0\n");
122 #endif
123 /* break-here */
125 /* Be sure the "t (tracing stop)" test can proceed for both threads. */
126 timed_mutex_lock (&terminate_mutex);
127 i = pthread_mutex_unlock (&terminate_mutex);
128 assert (i == 0);
130 return NULL;
133 static const char *
134 proc_string (const char *filename, const char *line)
136 FILE *f;
137 static char buf[LINE_MAX];
138 size_t line_len = strlen (line);
140 f = fopen (filename, "r");
141 if (f == NULL)
143 fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line,
144 strerror (errno));
145 exit (EXIT_FAILURE);
147 while (errno = 0, fgets (buf, sizeof (buf), f))
149 char *s;
151 s = strchr (buf, '\n');
152 assert (s != NULL);
153 *s = 0;
155 if (strncmp (buf, line, line_len) != 0)
156 continue;
158 if (fclose (f))
160 fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line,
161 strerror (errno));
162 exit (EXIT_FAILURE);
165 return &buf[line_len];
167 if (errno != 0)
169 fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno));
170 exit (EXIT_FAILURE);
172 fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line);
173 exit (EXIT_FAILURE);
176 static unsigned long
177 proc_ulong (const char *filename, const char *line)
179 const char *s = proc_string (filename, line);
180 long retval;
181 char *end;
183 errno = 0;
184 retval = strtol (s, &end, 10);
185 if (retval < 0 || retval >= LONG_MAX || (end && *end))
187 fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval,
188 strerror (errno));
189 exit (EXIT_FAILURE);
191 return retval;
194 static void
195 state_wait (pid_t process, const char *wanted)
197 char *filename;
198 int i;
199 struct timespec start, now;
200 const char *state;
202 i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process);
203 assert (i > 0);
205 i = clock_gettime (CLOCK_MONOTONIC, &start);
206 assert (i == 0);
210 state = proc_string (filename, "State:\t");
212 /* torvalds/linux-2.6.git 464763cf1c6df632dccc8f2f4c7e50163154a2c0
213 has changed "T (tracing stop)" to "t (tracing stop)". Make the GDB
214 testcase backward compatible with older Linux kernels. */
215 if (strcmp (state, "T (tracing stop)") == 0)
216 state = "t (tracing stop)";
218 if (strcmp (state, wanted) == 0)
220 free (filename);
221 return;
224 if (sched_yield ())
226 perror ("sched_yield()");
227 exit (EXIT_FAILURE);
230 i = clock_gettime (CLOCK_MONOTONIC, &now);
231 assert (i == 0);
232 assert (now.tv_sec >= start.tv_sec);
234 while (now.tv_sec - start.tv_sec < TIMEOUT);
236 fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n",
237 (unsigned long) process, wanted, state);
238 exit (EXIT_FAILURE);
241 static volatile pid_t tracer = 0;
242 static pthread_t thread1, thread2;
244 static void
245 cleanup (void)
247 printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer);
249 if (tracer)
251 int i;
252 int tracer_save = tracer;
254 tracer = 0;
256 i = kill (tracer_save, SIGCONT);
257 assert (i == 0);
262 main (int argc, char **argv)
264 int i;
265 int standalone = 0;
267 if (argc == 2 && strcmp (argv[1], "-s") == 0)
268 standalone = 1;
269 else
270 assert (argc == 1);
272 setbuf (stdout, NULL);
274 timed_mutex_lock (&thread1_tid_mutex);
275 timed_mutex_lock (&thread2_tid_mutex);
277 timed_mutex_lock (&terminate_mutex);
279 pthread_barrier_init (&threads_started_barrier, NULL, 3);
281 i = pthread_create (&thread1, NULL, thread_func, (void *) (intptr_t) 1);
282 assert (i == 0);
284 i = pthread_create (&thread2, NULL, thread_func, (void *) (intptr_t) 2);
285 assert (i == 0);
287 if (!standalone)
289 tracer = proc_ulong ("/proc/self/status", "TracerPid:\t");
290 if (tracer == 0)
292 fprintf (stderr, "The testcase must be run by GDB!\n");
293 exit (EXIT_FAILURE);
295 if (tracer != getppid ())
297 fprintf (stderr, "The testcase parent must be our GDB tracer!\n");
298 exit (EXIT_FAILURE);
302 /* SIGCONT our debugger in the case of our crash as we would deadlock
303 otherwise. */
305 atexit (cleanup);
307 /* Wait until all threads are seen running. On Linux (at least),
308 new threads start stopped, and the debugger must resume them.
309 Need to wait for that before stopping GDB. */
310 pthread_barrier_wait (&threads_started_barrier);
312 printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer);
314 if (tracer)
316 i = kill (tracer, SIGSTOP);
317 assert (i == 0);
318 state_wait (tracer, "T (stopped)");
321 /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so
322 they could not trigger the breakpoint before GDB gets unstopped later.
323 Threads get resumed at pthread_cond_wait below. Use `while' loops for
324 protection against spurious pthread_cond_wait wakeups. */
326 printf ("Waiting till the threads initialize their TIDs.\n");
328 while (thread1_tid == 0)
330 i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex);
331 assert (i == 0);
334 while (thread2_tid == 0)
336 i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex);
337 assert (i == 0);
340 printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
341 (unsigned long) thread1_tid, (unsigned long) thread2_tid,
342 (unsigned long) getpid ());
344 printf ("Waiting till the threads get trapped by the breakpoint.\n");
346 if (tracer)
348 /* s390x-unknown-linux-gnu will fail with "R (running)". */
350 state_wait (thread1_tid, "t (tracing stop)");
352 state_wait (thread2_tid, "t (tracing stop)");
355 cleanup ();
357 printf ("Joining the threads.\n");
359 i = pthread_mutex_unlock (&terminate_mutex);
360 assert (i == 0);
362 i = pthread_join (thread1, NULL);
363 assert (i == 0);
365 i = pthread_join (thread2, NULL);
366 assert (i == 0);
368 printf ("Exiting.\n"); /* break-at-exit */
370 return EXIT_SUCCESS;