Crash on thread id wrap around
[deliverable/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-2015 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
26 /* pthread_yield is a GNU extension. */
27 #define _GNU_SOURCE
28 #include <pthread.h>
29
30 #include <asm/unistd.h>
31 #include <unistd.h>
32 #define gettid() syscall (__NR_gettid)
33
34 #include "watchpoint-fork.h"
35
36 /* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
37 variable. Hit-comments need to be duplicated there to catch both at-stops
38 and behind-stops, depending on the target. */
39
40 volatile int var;
41
42 void
43 marker (void)
44 {
45 }
46
47 static void
48 empty (void)
49 {
50 }
51
52 static void
53 mark_exit (void)
54 {
55 }
56
57 pthread_t thread;
58 volatile int step;
59
60 static void *
61 start (void *arg)
62 {
63 int i;
64
65 if (step >= 3)
66 goto step_3;
67
68 while (step != 1)
69 {
70 i = pthread_yield ();
71 assert (i == 0);
72 }
73
74 var++; /* validity-thread-B */
75 empty (); /* validity-thread-B */
76 step = 2;
77 while (step != 3)
78 {
79 if (step == 99)
80 goto step_99;
81
82 i = pthread_yield ();
83 assert (i == 0);
84 }
85
86 step_3:
87 if (step >= 5)
88 goto step_5;
89
90 var++; /* after-fork1-B */
91 empty (); /* after-fork1-B */
92 step = 4;
93 while (step != 5)
94 {
95 if (step == 99)
96 goto step_99;
97
98 i = pthread_yield ();
99 assert (i == 0);
100 }
101
102 step_5:
103 var++; /* after-fork2-B */
104 empty (); /* after-fork2-B */
105 return (void *) 5UL;
106
107 step_99:
108 /* We must not get caught here (against a forgotten breakpoint). */
109 var++;
110 marker ();
111 return (void *) 99UL;
112 }
113
114 int
115 main (void)
116 {
117 int i;
118 void *thread_result;
119
120 setbuf (stdout, NULL);
121 printf ("main: %d\n", (int) gettid ());
122
123 /* General hardware breakpoints and watchpoints validity. */
124 marker ();
125 var++; /* validity-first */
126 empty (); /* validity-first */
127
128 i = pthread_create (&thread, NULL, start, NULL);
129 assert (i == 0);
130
131 var++; /* validity-thread-A */
132 empty (); /* validity-thread-A */
133 step = 1;
134 while (step != 2)
135 {
136 i = pthread_yield ();
137 assert (i == 0);
138 }
139
140 /* Hardware watchpoints got disarmed here. */
141 forkoff (1);
142
143 var++; /* after-fork1-A */
144 empty (); /* after-fork1-A */
145 step = 3;
146 #ifdef FOLLOW_CHILD
147 /* Spawn new thread as it was deleted in the child of FORK. */
148 i = pthread_create (&thread, NULL, start, NULL);
149 assert (i == 0);
150 #endif
151 while (step != 4)
152 {
153 i = pthread_yield ();
154 assert (i == 0);
155 }
156
157 /* A sanity check for double hardware watchpoints removal. */
158 forkoff (2);
159
160 var++; /* after-fork2-A */
161 empty (); /* after-fork2-A */
162 step = 5;
163 #ifdef FOLLOW_CHILD
164 /* Spawn new thread as it was deleted in the child of FORK. */
165 i = pthread_create (&thread, NULL, start, NULL);
166 assert (i == 0);
167 #endif
168
169 i = pthread_join (thread, &thread_result);
170 assert (i == 0);
171 assert (thread_result == (void *) 5UL);
172
173 mark_exit ();
174 return 0;
175 }
This page took 0.036946 seconds and 4 git commands to generate.