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