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