1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Test program that triggers a race between pthread_barrier_wait() and
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * pthread_barrier_destroy(): proper synchronization is missing between
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the pthread_barrier_wait() and the pthread_barrier_destroy() calls. This
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * test program is based on the example that was posted on February 5, 2009 by
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Christoph Bartoschek on the valgrind-users mailing list. Redistribution of
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the source code below is permitted under the GPLv2 license.
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * See also http://article.gmane.org/gmane.comp.debugging.valgrind/8945/match=pthread_barrier_wait
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h>
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_barrier_t* barrier;
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread(void* arg)
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_barrier_wait(barrier);
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return NULL;
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main()
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_t tid;
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier = (pthread_barrier_t *) malloc(sizeof(*barrier));
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_barrier_init(barrier, NULL, 2);
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_create(&tid, NULL, thread, NULL);
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_barrier_wait(barrier);
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /*
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * The sleep() call below ensures that the pthread_barrier_destroy() call
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * happens after the created thread has returned from pthread_barrier_wait().
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sleep(1);
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_barrier_destroy(barrier);
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(barrier);
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_join(tid, NULL);
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0;
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
49