1/* Use a semaphore to implement mutual exclusion. */
2
3
4#include <assert.h>
5#include <stdio.h>     /* printf() */
6#include <pthread.h>
7#include <semaphore.h>
8#include <unistd.h>    /* sleep() */
9
10
11/* Local functions declarations. */
12
13static void* thread_func(void*);
14
15
16/* Local variables. */
17
18/* s_sem protects s_d3. */
19static sem_t s_sem;
20
21static double s_d1; /* accessed before thread creation and in the created */
22                    /* thread (not a race). */
23static double s_d2; /* accessed in the created thread and after the join */
24                    /* (not a race). */
25static double s_d3; /* accessed simultaneously from both threads (race). */
26static int    s_debug     = 0;
27static int    s_do_printf = 0;
28static int    s_do_mutual_exclusion = 0;
29
30
31/* Function definitions. */
32
33int main(int argc, char** argv)
34{
35  int optchar;
36  pthread_t threadid;
37
38  while ((optchar = getopt(argc, argv, "dmp")) != EOF)
39  {
40    switch (optchar)
41    {
42    case 'd':
43      s_debug = 1;
44      break;
45    case 'm':
46      s_do_mutual_exclusion = 1;
47      break;
48    case 'p':
49      s_do_printf = 1;
50      break;
51    default:
52      assert(0);
53    }
54  }
55
56  sem_init(&s_sem, 0, 1);
57
58  /*
59   * Switch to line-buffered mode, such that timing information can be
60   * obtained for each printf() call with strace.
61   */
62  setlinebuf(stdout);
63
64  if (s_debug)
65  {
66    printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3);
67  }
68
69  s_d1 = 1;
70  s_d3 = 3;
71
72  pthread_create(&threadid, 0, thread_func, 0);
73
74  sleep(1); /* Wait until thread_func() finished. */
75
76  {
77    if (s_do_mutual_exclusion) sem_wait(&s_sem);
78    s_d3++;
79    if (s_do_mutual_exclusion) sem_post(&s_sem);
80  }
81
82  /* Wait until the thread finished. */
83  pthread_join(threadid, 0);
84  if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2);
85  if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3);
86
87  sem_destroy(&s_sem);
88
89  return 0;
90}
91
92static void* thread_func(void* thread_arg)
93{
94  if (s_do_printf)
95  {
96    printf("s_d1 = %g (should be 1)\n", s_d1);
97  }
98  s_d2 = 2;
99  {
100    if (s_do_mutual_exclusion) sem_wait(&s_sem);
101    s_d3++;
102    if (s_do_mutual_exclusion) sem_post(&s_sem);
103  }
104  return 0;
105}
106