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 13 static void* thread_func(void*); 14 15 16 /* Local variables. */ 17 18 /* s_sem protects s_d3. */ 19 static sem_t s_sem; 20 21 static double s_d1; /* accessed before thread creation and in the created */ 22 /* thread (not a race). */ 23 static double s_d2; /* accessed in the created thread and after the join */ 24 /* (not a race). */ 25 static double s_d3; /* accessed simultaneously from both threads (race). */ 26 static int s_debug = 0; 27 static int s_do_printf = 0; 28 static int s_do_mutual_exclusion = 0; 29 30 31 /* Function definitions. */ 32 33 int 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 92 static 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