125f9f5411f64046c2ffc0822f727aedc21f07720bart/* Use a semaphore to implement mutual exclusion. */ 225f9f5411f64046c2ffc0822f727aedc21f07720bart 325f9f5411f64046c2ffc0822f727aedc21f07720bart#include <assert.h> 425f9f5411f64046c2ffc0822f727aedc21f07720bart#include <fcntl.h> /* O_CREAT */ 525f9f5411f64046c2ffc0822f727aedc21f07720bart#include <pthread.h> 625f9f5411f64046c2ffc0822f727aedc21f07720bart#include <semaphore.h> 725f9f5411f64046c2ffc0822f727aedc21f07720bart#include <stdio.h> /* printf() */ 825f9f5411f64046c2ffc0822f727aedc21f07720bart#include <stdlib.h> /* exit() */ 925f9f5411f64046c2ffc0822f727aedc21f07720bart#include <unistd.h> /* sleep() */ 1025f9f5411f64046c2ffc0822f727aedc21f07720bart 1125f9f5411f64046c2ffc0822f727aedc21f07720bart/* Local functions declarations. */ 1225f9f5411f64046c2ffc0822f727aedc21f07720bart 1325f9f5411f64046c2ffc0822f727aedc21f07720bartstatic void* thread_func(void*); 1425f9f5411f64046c2ffc0822f727aedc21f07720bart 1525f9f5411f64046c2ffc0822f727aedc21f07720bart 1625f9f5411f64046c2ffc0822f727aedc21f07720bart/* Local variables. */ 1725f9f5411f64046c2ffc0822f727aedc21f07720bart 1825f9f5411f64046c2ffc0822f727aedc21f07720bart/* s_sem protects s_d3. */ 1925f9f5411f64046c2ffc0822f727aedc21f07720bartstatic sem_t* s_sem; 2025f9f5411f64046c2ffc0822f727aedc21f07720bart 2125f9f5411f64046c2ffc0822f727aedc21f07720bartstatic double s_d1; /* accessed before thread creation and in the created */ 2225f9f5411f64046c2ffc0822f727aedc21f07720bart /* thread (not a race). */ 2325f9f5411f64046c2ffc0822f727aedc21f07720bartstatic double s_d2; /* accessed in the created thread and after the join */ 2425f9f5411f64046c2ffc0822f727aedc21f07720bart /* (not a race). */ 2525f9f5411f64046c2ffc0822f727aedc21f07720bartstatic double s_d3; /* accessed simultaneously from both threads (race). */ 2625f9f5411f64046c2ffc0822f727aedc21f07720bartstatic int s_debug = 0; 2725f9f5411f64046c2ffc0822f727aedc21f07720bartstatic int s_do_printf = 0; 2825f9f5411f64046c2ffc0822f727aedc21f07720bartstatic int s_do_mutual_exclusion = 0; 2925f9f5411f64046c2ffc0822f727aedc21f07720bart 3025f9f5411f64046c2ffc0822f727aedc21f07720bart 3125f9f5411f64046c2ffc0822f727aedc21f07720bart/* Function definitions. */ 3225f9f5411f64046c2ffc0822f727aedc21f07720bart 3325f9f5411f64046c2ffc0822f727aedc21f07720bartint main(int argc, char** argv) 3425f9f5411f64046c2ffc0822f727aedc21f07720bart{ 3525f9f5411f64046c2ffc0822f727aedc21f07720bart int optchar; 3625f9f5411f64046c2ffc0822f727aedc21f07720bart pthread_t threadid; 3725f9f5411f64046c2ffc0822f727aedc21f07720bart char semaphore_name[32]; 3825f9f5411f64046c2ffc0822f727aedc21f07720bart 3925f9f5411f64046c2ffc0822f727aedc21f07720bart while ((optchar = getopt(argc, argv, "dmp")) != EOF) 4025f9f5411f64046c2ffc0822f727aedc21f07720bart { 4125f9f5411f64046c2ffc0822f727aedc21f07720bart switch (optchar) 4225f9f5411f64046c2ffc0822f727aedc21f07720bart { 4325f9f5411f64046c2ffc0822f727aedc21f07720bart case 'd': 4425f9f5411f64046c2ffc0822f727aedc21f07720bart s_debug = 1; 4525f9f5411f64046c2ffc0822f727aedc21f07720bart break; 4625f9f5411f64046c2ffc0822f727aedc21f07720bart case 'm': 4725f9f5411f64046c2ffc0822f727aedc21f07720bart s_do_mutual_exclusion = 1; 4825f9f5411f64046c2ffc0822f727aedc21f07720bart break; 4925f9f5411f64046c2ffc0822f727aedc21f07720bart case 'p': 5025f9f5411f64046c2ffc0822f727aedc21f07720bart s_do_printf = 1; 5125f9f5411f64046c2ffc0822f727aedc21f07720bart break; 5225f9f5411f64046c2ffc0822f727aedc21f07720bart default: 5325f9f5411f64046c2ffc0822f727aedc21f07720bart assert(0); 5425f9f5411f64046c2ffc0822f727aedc21f07720bart } 5525f9f5411f64046c2ffc0822f727aedc21f07720bart } 5625f9f5411f64046c2ffc0822f727aedc21f07720bart 5725f9f5411f64046c2ffc0822f727aedc21f07720bart /* 5825f9f5411f64046c2ffc0822f727aedc21f07720bart * Use the ipcs and ipcrm commands to clean up named semaphores left by 5925f9f5411f64046c2ffc0822f727aedc21f07720bart * aborted instances of this process. 6025f9f5411f64046c2ffc0822f727aedc21f07720bart */ 618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj snprintf(semaphore_name, sizeof(semaphore_name), "/drd-sem-open-test-%ld", 628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (long) getpid()); 638c7213fc97157614ca53f70353b9cd2d7a9326d9bart s_sem = sem_open(semaphore_name, O_CREAT | O_EXCL, 0600, 1); 6425f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_sem == SEM_FAILED) 6525f9f5411f64046c2ffc0822f727aedc21f07720bart { 6625f9f5411f64046c2ffc0822f727aedc21f07720bart fprintf(stderr, "Failed to create a semaphore with name %s\n", 6725f9f5411f64046c2ffc0822f727aedc21f07720bart semaphore_name); 6825f9f5411f64046c2ffc0822f727aedc21f07720bart exit(1); 6925f9f5411f64046c2ffc0822f727aedc21f07720bart } 7025f9f5411f64046c2ffc0822f727aedc21f07720bart 7125f9f5411f64046c2ffc0822f727aedc21f07720bart /* 7231b983d29affe6c30a2283be8824c6d75c74d848bart * Switch to line-buffered mode, such that timing information can be 7325f9f5411f64046c2ffc0822f727aedc21f07720bart * obtained for each printf() call with strace. 7425f9f5411f64046c2ffc0822f727aedc21f07720bart */ 7525f9f5411f64046c2ffc0822f727aedc21f07720bart setlinebuf(stdout); 7625f9f5411f64046c2ffc0822f727aedc21f07720bart 7725f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_debug) 7825f9f5411f64046c2ffc0822f727aedc21f07720bart { 7925f9f5411f64046c2ffc0822f727aedc21f07720bart printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3); 8025f9f5411f64046c2ffc0822f727aedc21f07720bart } 8125f9f5411f64046c2ffc0822f727aedc21f07720bart 8225f9f5411f64046c2ffc0822f727aedc21f07720bart s_d1 = 1; 8325f9f5411f64046c2ffc0822f727aedc21f07720bart s_d3 = 3; 8425f9f5411f64046c2ffc0822f727aedc21f07720bart 8525f9f5411f64046c2ffc0822f727aedc21f07720bart pthread_create(&threadid, 0, thread_func, 0); 8625f9f5411f64046c2ffc0822f727aedc21f07720bart 8725f9f5411f64046c2ffc0822f727aedc21f07720bart sleep(1); /* Wait until thread_func() finished. */ 8825f9f5411f64046c2ffc0822f727aedc21f07720bart 8925f9f5411f64046c2ffc0822f727aedc21f07720bart { 9025f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_mutual_exclusion) sem_wait(s_sem); 9125f9f5411f64046c2ffc0822f727aedc21f07720bart s_d3++; 9225f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_mutual_exclusion) sem_post(s_sem); 9325f9f5411f64046c2ffc0822f727aedc21f07720bart } 9425f9f5411f64046c2ffc0822f727aedc21f07720bart 9525f9f5411f64046c2ffc0822f727aedc21f07720bart /* Wait until the thread finished. */ 9625f9f5411f64046c2ffc0822f727aedc21f07720bart pthread_join(threadid, 0); 9725f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2); 9825f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3); 9925f9f5411f64046c2ffc0822f727aedc21f07720bart 10025f9f5411f64046c2ffc0822f727aedc21f07720bart sem_close(s_sem); 10125f9f5411f64046c2ffc0822f727aedc21f07720bart sem_unlink(semaphore_name); 10225f9f5411f64046c2ffc0822f727aedc21f07720bart 10325f9f5411f64046c2ffc0822f727aedc21f07720bart return 0; 10425f9f5411f64046c2ffc0822f727aedc21f07720bart} 10525f9f5411f64046c2ffc0822f727aedc21f07720bart 10625f9f5411f64046c2ffc0822f727aedc21f07720bartstatic void* thread_func(void* thread_arg) 10725f9f5411f64046c2ffc0822f727aedc21f07720bart{ 10825f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_printf) 10925f9f5411f64046c2ffc0822f727aedc21f07720bart { 11025f9f5411f64046c2ffc0822f727aedc21f07720bart printf("s_d1 = %g (should be 1)\n", s_d1); 11125f9f5411f64046c2ffc0822f727aedc21f07720bart } 11225f9f5411f64046c2ffc0822f727aedc21f07720bart s_d2 = 2; 11325f9f5411f64046c2ffc0822f727aedc21f07720bart { 11425f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_mutual_exclusion) sem_wait(s_sem); 11525f9f5411f64046c2ffc0822f727aedc21f07720bart s_d3++; 11625f9f5411f64046c2ffc0822f727aedc21f07720bart if (s_do_mutual_exclusion) sem_post(s_sem); 11725f9f5411f64046c2ffc0822f727aedc21f07720bart } 11825f9f5411f64046c2ffc0822f727aedc21f07720bart return 0; 11925f9f5411f64046c2ffc0822f727aedc21f07720bart} 120