1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Unit test for drd that triggers a race on the use of a POSIX condition
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   variable. By Bart Van Assche.
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>      // printf()
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h>
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>    // usleep()
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Local functions declarations.
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func(void* thread_arg);
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Local variables.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_mutex_t s_mutex;
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_cond_t  s_cond;
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int             s_use_mutex = 0;
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Function definitions.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char** argv)
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int optchar;
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_t threadid;
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while ((optchar = getopt(argc, argv, "m")) != EOF)
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch (optchar)
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'm':
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s_use_mutex = 1;
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert(0);
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_init(&s_cond, 0);
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_init(&s_mutex, 0);
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_lock(&s_mutex);
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_create(&threadid, 0, thread_func, 0);
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_wait(&s_cond, &s_mutex);
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_unlock(&s_mutex);
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_join(threadid, 0);
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_destroy(&s_mutex);
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_destroy(&s_cond);
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0;
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func(void* thread_arg)
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Wait until the main thread has entered pthread_cond_wait().
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_lock(&s_mutex);
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_unlock(&s_mutex);
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Signal the condition variable.
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (s_use_mutex) pthread_mutex_lock(&s_mutex);
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_signal(&s_cond);
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
72