1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
typedef struct
{
unsigned int count;
unsigned long waiters_count;
pthread_mutex_t lock;
pthread_cond_t count_nonzero;
} my_sem_t;
int my_sem_init(my_sem_t *s, int shared, unsigned int initial_count) {
int rc;
rc = pthread_mutex_init(&s->lock, NULL);
if (rc != 0) return rc;
rc = pthread_cond_init(&s->count_nonzero, NULL);
if (rc != 0) return rc;
s->count = initial_count;
s->waiters_count = 0;
return 0;
}
int my_sem_wait(my_sem_t *s) {
// Acquire mutex to enter critical section.
pthread_mutex_lock(&s->lock);
// Keep track of the number of waiters so that <sem_post> works correctly.
s->waiters_count++;
// Wait until the semaphore count is > 0, then atomically release
// <lock> and wait for <count_nonzero> to be signaled.
while (s->count == 0)
pthread_cond_wait(&s->count_nonzero, &s->lock);
// <s->lock> is now held.
// Decrement the waiters count.
s->waiters_count--;
// Decrement the semaphore's count.
s->count--;
// Release mutex to leave critical section.
pthread_mutex_unlock(&s->lock);
return 0;
}
int my_sem_post(my_sem_t *s) {
pthread_mutex_lock(&s->lock);
// Always allow one thread to continue if it is waiting.
if (s->waiters_count > 0)
pthread_cond_signal(&s->count_nonzero);
// Increment the semaphore's count.
s->count++;
pthread_mutex_unlock(&s->lock);
return 0;
}
int my_sem_destroy(my_sem_t *s) {
int rc;
rc = pthread_mutex_destroy(&s->lock);
if (rc != 0) return rc;
rc = pthread_cond_destroy(&s->count_nonzero);
if (rc != 0) return rc;
return 0;
}
|