bc967ce51028a3da0a5514b6f3082ad1f777fc41
[external/binutils.git] / gdb / testsuite / gdb.threads / watchpoint-fork-mt.c
1 /* Test case for forgotten hw-watchpoints after fork()-off of a process.
2
3    Copyright 2012-2016 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "watchpoint-fork.h"
21
22 #include <assert.h>
23 #include <unistd.h>
24 #include <sys/wait.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <pthread.h>
28
29 #include <asm/unistd.h>
30 #include <unistd.h>
31 #define gettid() syscall (__NR_gettid)
32
33 /* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
34    variable.  Hit-comments need to be duplicated there to catch both at-stops
35    and behind-stops, depending on the target.  */
36
37 volatile int var;
38
39 void
40 marker (void)
41 {
42 }
43
44 static void
45 empty (void)
46 {
47 }
48
49 static void
50 mark_exit (void)
51 {
52 }
53
54 pthread_t thread;
55 volatile int step;
56
57 static void *
58 start (void *arg)
59 {
60   int i;
61
62   if (step >= 3)
63     goto step_3;
64
65   while (step != 1)
66     {
67       i = pthread_yield ();
68       assert (i == 0);
69     }
70
71   var++;        /* validity-thread-B */
72   empty ();     /* validity-thread-B */
73   step = 2;
74   while (step != 3)
75     {
76       if (step == 99)
77         goto step_99;
78
79       i = pthread_yield ();
80       assert (i == 0);
81     }
82
83 step_3:
84   if (step >= 5)
85     goto step_5;
86
87   var++;        /* after-fork1-B */
88   empty ();     /* after-fork1-B */
89   step = 4;
90   while (step != 5)
91     {
92       if (step == 99)
93         goto step_99;
94
95       i = pthread_yield ();
96       assert (i == 0);
97     }
98
99 step_5:
100   var++;        /* after-fork2-B */
101   empty ();     /* after-fork2-B */
102   return (void *) 5UL;
103
104 step_99:
105   /* We must not get caught here (against a forgotten breakpoint).  */
106   var++;
107   marker ();
108   return (void *) 99UL;
109 }
110
111 int
112 main (void)
113 {
114   int i;
115   void *thread_result;
116
117   setbuf (stdout, NULL);
118   printf ("main: %d\n", (int) gettid ());
119
120   /* General hardware breakpoints and watchpoints validity.  */
121   marker ();
122   var++;        /* validity-first */
123   empty ();     /* validity-first */
124
125   i = pthread_create (&thread, NULL, start, NULL);
126   assert (i == 0);
127
128   var++;        /* validity-thread-A */
129   empty ();     /* validity-thread-A */
130   step = 1;
131   while (step != 2)
132     {
133       i = pthread_yield ();
134       assert (i == 0);
135     }
136
137   /* Hardware watchpoints got disarmed here.  */
138   forkoff (1);
139
140   var++;        /* after-fork1-A */
141   empty ();     /* after-fork1-A */
142   step = 3;
143 #ifdef FOLLOW_CHILD
144   /* Spawn new thread as it was deleted in the child of FORK.  */
145   i = pthread_create (&thread, NULL, start, NULL);
146   assert (i == 0);
147 #endif
148   while (step != 4)
149     {
150       i = pthread_yield ();
151       assert (i == 0);
152     }
153
154   /* A sanity check for double hardware watchpoints removal.  */
155   forkoff (2);
156
157   var++;        /* after-fork2-A */
158   empty ();     /* after-fork2-A */
159   step = 5;
160 #ifdef FOLLOW_CHILD
161   /* Spawn new thread as it was deleted in the child of FORK.  */
162   i = pthread_create (&thread, NULL, start, NULL);
163   assert (i == 0);
164 #endif
165
166   i = pthread_join (thread, &thread_result);
167   assert (i == 0);
168   assert (thread_result == (void *) 5UL);
169
170   mark_exit ();
171   return 0;
172 }