From b4fa80ad676217ab28bd1da20d25542cc9089957 Mon Sep 17 00:00:00 2001 From: "Remzi H. Arpaci-Dusseau" Date: Mon, 22 Apr 2019 13:14:08 -0500 Subject: [PATCH] reader writer lock + small cleanups --- threads-sema/Makefile | 1 + threads-sema/README.md | 8 ++ threads-sema/dining_philosophers_deadlock.c | 5 +- .../dining_philosophers_no_deadlock.c | 5 +- threads-sema/rwlock.c | 94 +++++++++++++++++++ 5 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 threads-sema/rwlock.c diff --git a/threads-sema/Makefile b/threads-sema/Makefile index 32c63fa..0d7aba7 100644 --- a/threads-sema/Makefile +++ b/threads-sema/Makefile @@ -8,6 +8,7 @@ SRCS := dining_philosophers_deadlock.c \ join.c \ binary.c \ producer_consumer_works.c \ + rwlock.c \ zemaphore.c OBJS := ${SRCS:c=o} diff --git a/threads-sema/README.md b/threads-sema/README.md index 9683b9c..652e1e5 100644 --- a/threads-sema/README.md +++ b/threads-sema/README.md @@ -43,6 +43,9 @@ prompt> ./producer_consumer 1 1000 1 The output should print each produced item once, and show which consumer consumed each produced item. +# Reader/Writer Locks + +Code in `rwlock.c`. Build via `make`, run via `rwlock`. # Dining Philosophers @@ -55,3 +58,8 @@ different forms: Run `make` to build all of them with the highly primitive `Makefile`. + +# Zemaphores + +Code in `zemaphore.c`. We bet you can figure out the rest. This is just +a small test of the Zemaphore with the fork/join problem. diff --git a/threads-sema/dining_philosophers_deadlock.c b/threads-sema/dining_philosophers_deadlock.c index 28c3170..84db8d6 100644 --- a/threads-sema/dining_philosophers_deadlock.c +++ b/threads-sema/dining_philosophers_deadlock.c @@ -40,13 +40,14 @@ void eat() { void *philosopher(void *arg) { arg_t *args = (arg_t *) arg; + int p = args->thread_id; int i; for (i = 0; i < args->num_loops; i++) { think(); - get_forks(args->thread_id); + get_forks(p); eat(); - put_forks(args->thread_id); + put_forks(p); } return NULL; } diff --git a/threads-sema/dining_philosophers_no_deadlock.c b/threads-sema/dining_philosophers_no_deadlock.c index c9d409f..6840410 100644 --- a/threads-sema/dining_philosophers_no_deadlock.c +++ b/threads-sema/dining_philosophers_no_deadlock.c @@ -45,13 +45,14 @@ void eat() { void *philosopher(void *arg) { arg_t *args = (arg_t *) arg; + int p = args->thread_id; int i; for (i = 0; i < args->num_loops; i++) { think(); - get_forks(args->thread_id); + get_forks(p); eat(); - put_forks(args->thread_id); + put_forks(p); } return NULL; } diff --git a/threads-sema/rwlock.c b/threads-sema/rwlock.c new file mode 100644 index 0000000..6b2bc10 --- /dev/null +++ b/threads-sema/rwlock.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include + +#include "common.h" +#include "common_threads.h" + +typedef struct _rwlock_t { + sem_t writelock; + sem_t lock; + int readers; +} rwlock_t; + +void rwlock_init(rwlock_t *lock) { + lock->readers = 0; + Sem_init(&lock->lock, 1); + Sem_init(&lock->writelock, 1); +} + +void rwlock_acquire_readlock(rwlock_t *lock) { + Sem_wait(&lock->lock); + lock->readers++; + if (lock->readers == 1) + Sem_wait(&lock->writelock); + Sem_post(&lock->lock); +} + +void rwlock_release_readlock(rwlock_t *lock) { + Sem_wait(&lock->lock); + lock->readers--; + if (lock->readers == 0) + Sem_post(&lock->writelock); + Sem_post(&lock->lock); +} + +void rwlock_acquire_writelock(rwlock_t *lock) { + Sem_wait(&lock->writelock); +} + +void rwlock_release_writelock(rwlock_t *lock) { + Sem_post(&lock->writelock); +} + +int read_loops; +int write_loops; +int counter = 0; + +rwlock_t mutex; + +void *reader(void *arg) { + int i; + int local = 0; + for (i = 0; i < read_loops; i++) { + rwlock_acquire_readlock(&mutex); + local = counter; + rwlock_release_readlock(&mutex); + printf("read %d\n", local); + } + printf("read done: %d\n", local); + return NULL; +} + +void *writer(void *arg) { + int i; + for (i = 0; i < write_loops; i++) { + rwlock_acquire_writelock(&mutex); + counter++; + rwlock_release_writelock(&mutex); + } + printf("write done\n"); + return NULL; +} + +int main(int argc, char *argv[]) { + if (argc != 3) { + fprintf(stderr, "usage: rwlock readloops writeloops\n"); + exit(1); + } + read_loops = atoi(argv[1]); + write_loops = atoi(argv[2]); + + rwlock_init(&mutex); + pthread_t c1, c2; + Pthread_create(&c1, NULL, reader, NULL); + Pthread_create(&c2, NULL, writer, NULL); + Pthread_join(c1, NULL); + Pthread_join(c2, NULL); + printf("all done\n"); + return 0; +} + +