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 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 33 static void sem_destroy(sem_t *p) 34 { 35 ANNOTATE_SEM_DESTROY_POST(p); 36 } 37 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 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 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 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