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-%ld", 62 (long) getpid()); 63 s_sem = sem_open(semaphore_name, O_CREAT | O_EXCL, 0600, 1); 64 if (s_sem == SEM_FAILED) 65 { 66 fprintf(stderr, "Failed to create a semaphore with name %s\n", 67 semaphore_name); 68 exit(1); 69 } 70 71 /* 72 * Switch to line-buffered mode, such that timing information can be 73 * obtained for each printf() call with strace. 74 */ 75 setlinebuf(stdout); 76 77 if (s_debug) 78 { 79 printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3); 80 } 81 82 s_d1 = 1; 83 s_d3 = 3; 84 85 pthread_create(&threadid, 0, thread_func, 0); 86 87 sleep(1); /* Wait until thread_func() finished. */ 88 89 { 90 if (s_do_mutual_exclusion) sem_wait(s_sem); 91 s_d3++; 92 if (s_do_mutual_exclusion) sem_post(s_sem); 93 } 94 95 /* Wait until the thread finished. */ 96 pthread_join(threadid, 0); 97 if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2); 98 if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3); 99 100 sem_close(s_sem); 101 sem_unlink(semaphore_name); 102 103 return 0; 104 } 105 106 static void* thread_func(void* thread_arg) 107 { 108 if (s_do_printf) 109 { 110 printf("s_d1 = %g (should be 1)\n", s_d1); 111 } 112 s_d2 = 2; 113 { 114 if (s_do_mutual_exclusion) sem_wait(s_sem); 115 s_d3++; 116 if (s_do_mutual_exclusion) sem_post(s_sem); 117 } 118 return 0; 119 } 120