• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 typedef struct {
20   volatile unsigned value;
21 } sem_t;
22 
23 static sem_t s_sem;
24 static unsigned int s_counter;
25 
sem_init(sem_t * p,unsigned value)26 static 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 
sem_destroy(sem_t * p)33 static void sem_destroy(sem_t *p)
34 {
35   ANNOTATE_SEM_DESTROY_POST(p);
36 }
37 
sem_wait(sem_t * p)38 static 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 
sem_post(sem_t * p)53 static void sem_post(sem_t *p)
54 {
55   ANNOTATE_SEM_POST_PRE(p);
56   __sync_fetch_and_add(&p->value, 1);
57 }
58 
thread_func(void * arg)59 static 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 
main(int argc,const char * argv[])77 int 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