1/**
2 * @file  annotate_sem.c
3 *
4 * @brief Multithreaded test program that triggers various access patterns
5 *        without triggering any race conditions using a binary semaphore
6 *        implemented via busy-waiting. Annotations are used to tell DRD
7 *        which higher-level semaphore operations are being performed.
8 */
9
10#include <assert.h>
11#include <pthread.h>
12#include <stdio.h>
13#include "../../config.h"
14#include "../../drd/drd.h"
15
16#define THREADS 10
17#define ITERATIONS 1000
18
19typedef struct {
20  volatile unsigned value;
21} sem_t;
22
23static sem_t s_sem;
24static unsigned int s_counter;
25
26static void sem_init(sem_t *p, unsigned value)
27{
28  DRD_IGNORE_VAR(*p);
29  p->value = value;
30  ANNOTATE_SEM_INIT_PRE(p, value);
31}
32
33static void sem_destroy(sem_t *p)
34{
35  ANNOTATE_SEM_DESTROY_POST(p);
36}
37
38static void sem_wait(sem_t *p)
39{
40  unsigned old, new;
41  struct timespec ts = { 0, 0 };
42
43  ANNOTATE_SEM_WAIT_PRE(p);
44  do {
45    old = p->value;
46    new = old - 1;
47    nanosleep(&ts, NULL);
48    ts.tv_nsec = 1;
49  } while (!old || !__sync_bool_compare_and_swap(&p->value, old, new));
50  ANNOTATE_SEM_WAIT_POST(p);
51}
52
53static void sem_post(sem_t *p)
54{
55  ANNOTATE_SEM_POST_PRE(p);
56  __sync_fetch_and_add(&p->value, 1);
57}
58
59static void *thread_func(void *arg)
60{
61  unsigned int i;
62  unsigned int sum = 0;
63
64  for (i = 0; i < ITERATIONS; i++) {
65    sem_wait(&s_sem);
66    sum += s_counter;
67    sem_post(&s_sem);
68
69    sem_wait(&s_sem);
70    s_counter++;
71    sem_post(&s_sem);
72  }
73
74  return 0;
75}
76
77int main(int argc, const char *argv[])
78{
79  pthread_t tid[THREADS];
80  unsigned int i;
81
82  sem_init(&s_sem, 1);
83  for (i = 0; i < THREADS; i++)
84    pthread_create(&tid[i], 0, thread_func, 0);
85
86  for (i = 0; i < THREADS; i++)
87    pthread_join(tid[i], 0);
88
89  assert(s_counter == THREADS * ITERATIONS);
90  assert(s_sem.value == 1);
91  sem_destroy(&s_sem);
92
93  fprintf(stderr, "Finished.\n");
94
95  return 0;
96}
97