reader writer lock + small cleanups

This commit is contained in:
Remzi H. Arpaci-Dusseau
2019-04-22 13:14:08 -05:00
parent d532b42eda
commit b4fa80ad67
5 changed files with 109 additions and 4 deletions

View File

@@ -8,6 +8,7 @@ SRCS := dining_philosophers_deadlock.c \
join.c \ join.c \
binary.c \ binary.c \
producer_consumer_works.c \ producer_consumer_works.c \
rwlock.c \
zemaphore.c zemaphore.c
OBJS := ${SRCS:c=o} OBJS := ${SRCS:c=o}

View File

@@ -43,6 +43,9 @@ prompt> ./producer_consumer 1 1000 1
The output should print each produced item once, and show which The output should print each produced item once, and show which
consumer consumed each produced item. consumer consumed each produced item.
# Reader/Writer Locks
Code in `rwlock.c`. Build via `make`, run via `rwlock`.
# Dining Philosophers # Dining Philosophers
@@ -55,3 +58,8 @@ different forms:
Run `make` to build all of them with the highly primitive `Makefile`. 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.

View File

@@ -40,13 +40,14 @@ void eat() {
void *philosopher(void *arg) { void *philosopher(void *arg) {
arg_t *args = (arg_t *) arg; arg_t *args = (arg_t *) arg;
int p = args->thread_id;
int i; int i;
for (i = 0; i < args->num_loops; i++) { for (i = 0; i < args->num_loops; i++) {
think(); think();
get_forks(args->thread_id); get_forks(p);
eat(); eat();
put_forks(args->thread_id); put_forks(p);
} }
return NULL; return NULL;
} }

View File

@@ -45,13 +45,14 @@ void eat() {
void *philosopher(void *arg) { void *philosopher(void *arg) {
arg_t *args = (arg_t *) arg; arg_t *args = (arg_t *) arg;
int p = args->thread_id;
int i; int i;
for (i = 0; i < args->num_loops; i++) { for (i = 0; i < args->num_loops; i++) {
think(); think();
get_forks(args->thread_id); get_forks(p);
eat(); eat();
put_forks(args->thread_id); put_forks(p);
} }
return NULL; return NULL;
} }

94
threads-sema/rwlock.c Normal file
View File

@@ -0,0 +1,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#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;
}