1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2022-2024 Free Software Foundation, Inc.
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.
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.
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/>. */
23 #include <semaphore.h>
27 /* Semaphores, used to track when threads have started, and to control
28 when the threads finish. */
29 sem_t startup_semaphore
;
30 sem_t finish_semaphore
;
31 sem_t thread_1_semaphore
;
32 sem_t thread_2_semaphore
;
34 /* Mutex to control when the first worker thread hit a breakpoint
36 pthread_mutex_t mutex
= PTHREAD_MUTEX_INITIALIZER
;
38 /* Global variable to poke, just so threads have something to do. */
39 volatile int global_var
= 0;
44 /* Let thread 2 run. */
45 if (sem_post (&thread_2_semaphore
) != 0)
48 /* Wait for thread 2 to complete its actions. */
49 if (sem_wait (&thread_1_semaphore
) != 0)
59 *p
= 0; /* Segfault here. */
63 worker_func (void *arg
)
65 int tid
= *((int *) arg
);
67 /* Let the main thread know that this worker has started. */
68 if (sem_post (&startup_semaphore
) != 0)
74 /* Wait for MUTEX to become available, then pass through the
75 conditional breakpoint location. */
76 if (pthread_mutex_lock (&mutex
) != 0)
78 global_var
= 99; /* Conditional breakpoint here. */
79 if (pthread_mutex_unlock (&mutex
) != 0)
84 if (sem_wait (&thread_2_semaphore
) != 0)
87 if (sem_post (&thread_1_semaphore
) != 0)
92 /* Wait until we are allowed to finish. */
93 if (sem_wait (&finish_semaphore
) != 0)
102 global_var
= 99; /* Stop marker. */
105 /* The main program entry point. */
110 pthread_t threads
[NUM_THREADS
];
111 int args
[NUM_THREADS
];
114 /* An alarm, just in case the thread deadlocks. */
117 /* Semaphore initialization. */
118 if (sem_init (&startup_semaphore
, 0, 0) != 0)
120 if (sem_init (&finish_semaphore
, 0, 0) != 0)
122 if (sem_init (&thread_1_semaphore
, 0, 0) != 0)
124 if (sem_init (&thread_2_semaphore
, 0, 0) != 0)
127 /* Lock MUTEX, this prevents the first worker thread from rushing ahead. */
128 if (pthread_mutex_lock (&mutex
) != 0)
131 /* Worker thread creation. */
132 for (int i
= 0; i
< NUM_THREADS
; i
++)
135 pthread_create (&threads
[i
], NULL
, worker_func
, &args
[i
]);
138 /* Wait for every thread to start. */
139 for (int i
= 0; i
< NUM_THREADS
; i
++)
141 if (sem_wait (&startup_semaphore
) != 0)
145 /* Unlock the first thread so it can proceed. */
146 if (pthread_mutex_unlock (&mutex
) != 0)
149 /* Wait for the first thread only. */
150 pthread_join (threads
[0], &retval
);
152 /* Now post FINISH_SEMAPHORE to allow all the other threads to finish. */
153 for (int i
= 1; i
< NUM_THREADS
; i
++)
154 sem_post (&finish_semaphore
);
156 /* Now wait for the remaining threads to complete. */
157 for (int i
= 1; i
< NUM_THREADS
; i
++)
158 pthread_join (threads
[i
], &retval
);
160 /* Semaphore cleanup. */
161 sem_destroy (&finish_semaphore
);
162 sem_destroy (&startup_semaphore
);
163 sem_destroy (&thread_1_semaphore
);
164 sem_destroy (&thread_2_semaphore
);