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