b28a0dea827caa4da8ceddbdb62362f466135f22
[platform/upstream/gdb.git] / gdb / testsuite / gdb.threads / watchthreads-reorder.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3    Copyright 2009-2015 Free Software Foundation, Inc.
4
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.
9
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.
14
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/>.  */
17
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>
30
31 #define gettid() syscall (__NR_gettid)
32
33 /* Terminate always in the main task, it can lock up with SIGSTOPped GDB
34    otherwise.  */
35 #define TIMEOUT (gettid () == getpid() ? 10 : 15)
36
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;
40
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;
44
45 static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
46
47 static pthread_barrier_t threads_started_barrier;
48
49 /* These variables must have lower in-memory addresses than thread1_rwatch and
50    thread2_rwatch so that they take their watchpoint slots.  */
51
52 static int unused1_rwatch;
53 static int unused2_rwatch;
54
55 static volatile int thread1_rwatch;
56 static volatile int thread2_rwatch;
57
58 /* Do not use alarm as it would create a ptrace event which would hang up us if
59    we are being traced by GDB which we stopped ourselves.  */
60
61 static void timed_mutex_lock (pthread_mutex_t *mutex)
62 {
63   int i;
64   struct timespec start, now;
65
66   i = clock_gettime (CLOCK_MONOTONIC, &start);
67   assert (i == 0);
68
69   do
70     {
71       i = pthread_mutex_trylock (mutex);
72       if (i == 0)
73         return;
74       assert (i == EBUSY);
75
76       i = clock_gettime (CLOCK_MONOTONIC, &now);
77       assert (i == 0);
78       assert (now.tv_sec >= start.tv_sec);
79     }
80   while (now.tv_sec - start.tv_sec < TIMEOUT);
81
82   fprintf (stderr, "Timed out waiting for internal lock!\n");
83   exit (EXIT_FAILURE);
84 }
85
86 static void *
87 thread1_func (void *unused)
88 {
89   int i;
90   volatile int rwatch_store;
91
92   pthread_barrier_wait (&threads_started_barrier);
93
94   timed_mutex_lock (&thread1_tid_mutex);
95
96   /* THREAD1_TID_MUTEX must be already locked to avoid race.  */
97   thread1_tid = gettid ();
98
99   i = pthread_cond_signal (&thread1_tid_cond);
100   assert (i == 0);
101   i = pthread_mutex_unlock (&thread1_tid_mutex);
102   assert (i == 0);
103
104   rwatch_store = thread1_rwatch;
105
106   /* Be sure the "t (tracing stop)" test can proceed for both threads.  */
107   timed_mutex_lock (&terminate_mutex);
108   i = pthread_mutex_unlock (&terminate_mutex);
109   assert (i == 0);
110
111   return NULL;
112 }
113
114 static void *
115 thread2_func (void *unused)
116 {
117   int i;
118   volatile int rwatch_store;
119
120   pthread_barrier_wait (&threads_started_barrier);
121
122   timed_mutex_lock (&thread2_tid_mutex);
123
124   /* THREAD2_TID_MUTEX must be already locked to avoid race.  */
125   thread2_tid = gettid ();
126
127   i = pthread_cond_signal (&thread2_tid_cond);
128   assert (i == 0);
129   i = pthread_mutex_unlock (&thread2_tid_mutex);
130   assert (i == 0);
131
132   rwatch_store = thread2_rwatch;
133
134   /* Be sure the "t (tracing stop)" test can proceed for both threads.  */
135   timed_mutex_lock (&terminate_mutex);
136   i = pthread_mutex_unlock (&terminate_mutex);
137   assert (i == 0);
138
139   return NULL;
140 }
141
142 static const char *
143 proc_string (const char *filename, const char *line)
144 {
145   FILE *f;
146   static char buf[LINE_MAX];
147   size_t line_len = strlen (line);
148
149   f = fopen (filename, "r");
150   if (f == NULL)
151     {
152       fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line,
153                strerror (errno));
154       exit (EXIT_FAILURE);
155     }
156   while (errno = 0, fgets (buf, sizeof (buf), f))
157     {
158       char *s;
159
160       s = strchr (buf, '\n');
161       assert (s != NULL);
162       *s = 0;
163
164       if (strncmp (buf, line, line_len) != 0)
165         continue;
166
167       if (fclose (f))
168         {
169           fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line,
170                    strerror (errno));
171           exit (EXIT_FAILURE);
172         }
173
174       return &buf[line_len];
175     }
176   if (errno != 0)
177     {
178       fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno));
179       exit (EXIT_FAILURE);
180     }
181   fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line);
182   exit (EXIT_FAILURE);
183 }
184
185 static unsigned long
186 proc_ulong (const char *filename, const char *line)
187 {
188   const char *s = proc_string (filename, line);
189   long retval;
190   char *end;
191
192   errno = 0;
193   retval = strtol (s, &end, 10);
194   if (retval < 0 || retval >= LONG_MAX || (end && *end))
195     {
196       fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval,
197                strerror (errno));
198       exit (EXIT_FAILURE);
199     }
200   return retval;
201 }
202
203 static void
204 state_wait (pid_t process, const char *wanted)
205 {
206   char *filename;
207   int i;
208   struct timespec start, now;
209   const char *state;
210
211   i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process);
212   assert (i > 0);
213
214   i = clock_gettime (CLOCK_MONOTONIC, &start);
215   assert (i == 0);
216
217   do
218     {
219       state = proc_string (filename, "State:\t");
220
221       /* torvalds/linux-2.6.git 464763cf1c6df632dccc8f2f4c7e50163154a2c0
222          has changed "T (tracing stop)" to "t (tracing stop)".  Make the GDB
223          testcase backward compatible with older Linux kernels.  */
224       if (strcmp (state, "T (tracing stop)") == 0)
225         state = "t (tracing stop)";
226
227       if (strcmp (state, wanted) == 0)
228         {
229           free (filename);
230           return;
231         }
232
233       if (sched_yield ())
234         {
235           perror ("sched_yield()");
236           exit (EXIT_FAILURE);
237         }
238
239       i = clock_gettime (CLOCK_MONOTONIC, &now);
240       assert (i == 0);
241       assert (now.tv_sec >= start.tv_sec);
242     }
243   while (now.tv_sec - start.tv_sec < TIMEOUT);
244
245   fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n",
246            (unsigned long) process, wanted, state);
247   exit (EXIT_FAILURE);
248 }
249
250 static volatile pid_t tracer = 0;
251 static pthread_t thread1, thread2;
252
253 static void
254 cleanup (void)
255 {
256   printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer);
257
258   if (tracer)
259     {
260       int i;
261       int tracer_save = tracer;
262
263       tracer = 0;
264
265       i = kill (tracer_save, SIGCONT);
266       assert (i == 0);
267     }
268 }
269
270 int
271 main (int argc, char **argv)
272 {
273   int i;
274   int standalone = 0;
275
276   if (argc == 2 && strcmp (argv[1], "-s") == 0)
277     standalone = 1;
278   else
279     assert (argc == 1);
280
281   setbuf (stdout, NULL);
282
283   timed_mutex_lock (&thread1_tid_mutex);
284   timed_mutex_lock (&thread2_tid_mutex);
285
286   timed_mutex_lock (&terminate_mutex);
287
288   pthread_barrier_init (&threads_started_barrier, NULL, 3);
289
290   i = pthread_create (&thread1, NULL, thread1_func, NULL);
291   assert (i == 0);
292
293   i = pthread_create (&thread2, NULL, thread2_func, NULL);
294   assert (i == 0);
295
296   if (!standalone)
297     {
298       tracer = proc_ulong ("/proc/self/status", "TracerPid:\t");
299       if (tracer == 0)
300         {
301           fprintf (stderr, "The testcase must be run by GDB!\n");
302           exit (EXIT_FAILURE);
303         }
304       if (tracer != getppid ())
305         {
306           fprintf (stderr, "The testcase parent must be our GDB tracer!\n");
307           exit (EXIT_FAILURE);
308         }
309     }
310
311   /* SIGCONT our debugger in the case of our crash as we would deadlock
312      otherwise.  */
313
314   atexit (cleanup);
315
316   /* Wait until all threads are seen running.  On Linux (at least),
317      new threads start stopped, and the debugger must resume them.
318      Need to wait for that before stopping GDB.  */
319   pthread_barrier_wait (&threads_started_barrier);
320
321   printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer);
322
323   if (tracer)
324     {
325       i = kill (tracer, SIGSTOP);
326       assert (i == 0);
327       state_wait (tracer, "T (stopped)");
328     }
329
330   /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so
331      they could not trigger the watchpoints before GDB gets unstopped later.
332      Threads get resumed at pthread_cond_wait below.  Use `while' loops for
333      protection against spurious pthread_cond_wait wakeups.  */
334
335   printf ("Waiting till the threads initialize their TIDs.\n");
336
337   while (thread1_tid == 0)
338     {
339       i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex);
340       assert (i == 0);
341     }
342
343   while (thread2_tid == 0)
344     {
345       i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex);
346       assert (i == 0);
347     }
348
349   printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
350           (unsigned long) thread1_tid, (unsigned long) thread2_tid,
351           (unsigned long) getpid ());
352
353   printf ("Waiting till the threads get trapped by the watchpoints.\n");
354
355   if (tracer)
356     {
357       /* s390x-unknown-linux-gnu will fail with "R (running)".  */
358
359       state_wait (thread1_tid, "t (tracing stop)");
360
361       state_wait (thread2_tid, "t (tracing stop)");
362     }
363
364   cleanup ();
365
366   printf ("Joining the threads.\n");
367
368   i = pthread_mutex_unlock (&terminate_mutex);
369   assert (i == 0);
370
371   i = pthread_join (thread1, NULL);
372   assert (i == 0);
373
374   i = pthread_join (thread2, NULL);
375   assert (i == 0);
376
377   printf ("Exiting.\n");        /* break-at-exit */
378
379   /* Just prevent compiler `warning: unusedX_rwatch defined but not used'.  */
380   unused1_rwatch = 1;
381   unused2_rwatch = 2;
382
383   return EXIT_SUCCESS;
384 }