1 /* Use a semaphore to implement mutual exclusion. */ 2 3 #include <assert.h> 4 #include <fcntl.h> /* O_CREAT */ 5 #include <pthread.h> 6 #include <semaphore.h> 7 #include <stdio.h> /* printf() */ 8 #include <stdlib.h> /* exit() */ 9 #include <unistd.h> /* sleep() */ 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 char semaphore_name[32]; 38 39 while ((optchar = getopt(argc, argv, "dmp")) != EOF) 40 { 41 switch (optchar) 42 { 43 case 'd': 44 s_debug = 1; 45 break; 46 case 'm': 47 s_do_mutual_exclusion = 1; 48 break; 49 case 'p': 50 s_do_printf = 1; 51 break; 52 default: 53 assert(0); 54 } 55 } 56 57 /* 58 * Use the ipcs and ipcrm commands to clean up named semaphores left by 59 * aborted instances of this process. 60 */ 61 snprintf(semaphore_name, sizeof(semaphore_name), "drd-sem-open-test"); 62 s_sem = sem_open(semaphore_name, O_CREAT, 0600, 1); 63 if (s_sem == SEM_FAILED) 64 { 65 fprintf(stderr, "Failed to create a semaphore with name %s\n", 66 semaphore_name); 67 exit(1); 68 } 69 70 /* 71 * Switch to line-buffered mode, such that timing information can be 72 * obtained for each printf() call with strace. 73 */ 74 setlinebuf(stdout); 75 76 if (s_debug) 77 { 78 printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3); 79 } 80 81 s_d1 = 1; 82 s_d3 = 3; 83 84 pthread_create(&threadid, 0, thread_func, 0); 85 86 sleep(1); /* Wait until thread_func() finished. */ 87 88 { 89 if (s_do_mutual_exclusion) sem_wait(s_sem); 90 s_d3++; 91 if (s_do_mutual_exclusion) sem_post(s_sem); 92 } 93 94 /* Wait until the thread finished. */ 95 pthread_join(threadid, 0); 96 if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2); 97 if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3); 98 99 sem_close(s_sem); 100 sem_unlink(semaphore_name); 101 102 return 0; 103 } 104 105 static void* thread_func(void* thread_arg) 106 { 107 if (s_do_printf) 108 { 109 printf("s_d1 = %g (should be 1)\n", s_d1); 110 } 111 s_d2 = 2; 112 { 113 if (s_do_mutual_exclusion) sem_wait(s_sem); 114 s_d3++; 115 if (s_do_mutual_exclusion) sem_post(s_sem); 116 } 117 return 0; 118 } 119