]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.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-2013 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 <assert.h>
21 #include <unistd.h>
22 #include <sys/wait.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <pthread.h>
26
27 #include <asm/unistd.h>
28 #include <unistd.h>
29 #define gettid() syscall (__NR_gettid)
30
31 #include "watchpoint-fork.h"
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 }