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