diff --git a/kern/include/synch.h b/kern/include/synch.h index fee3b07..59058d0 100644 --- a/kern/include/synch.h +++ b/kern/include/synch.h @@ -44,10 +44,10 @@ * internally. */ struct semaphore { - char *sem_name; + char *sem_name; struct wchan *sem_wchan; struct spinlock sem_lock; - volatile unsigned sem_count; + volatile unsigned sem_count; }; struct semaphore *sem_create(const char *name, unsigned initial_count); @@ -137,5 +137,40 @@ void cv_wait(struct cv *cv, struct lock *lock); void cv_signal(struct cv *cv, struct lock *lock); void cv_broadcast(struct cv *cv, struct lock *lock); +/* + * Reader-writer locks. + * + * When the lock is created, no thread should be holding it. Likewise, + * when the lock is destroyed, no thread should be holding it. + * + * The name field is for easier debugging. A copy of the name is + * (should be) made internally. + */ + +struct rwlock { + char *rwlock_name; + // add what you need here + // (don't forget to mark things volatile as needed) +}; + +struct rwlock * rwlock_create(const char *); +void rwlock_destroy(struct rwlock *); + +/* + * Operations: + * rwlock_acquire_read - Get the lock for reading. Multiple threads can + * hold the lock for reading at the same time. + * rwlock_release_read - Free the lock. + * rwlock_acquire_write - Get the lock for writing. Only one thread can + * hold the write lock at one time. + * rwlock_release_write - Free the write lock. + * + * These operations must be atomic. You get to write them. + */ + +void rwlock_acquire_read(struct rwlock *); +void rwlock_release_read(struct rwlock *); +void rwlock_acquire_write(struct rwlock *); +void rwlock_release_write(struct rwlock *); #endif /* _SYNCH_H_ */ diff --git a/kern/thread/synch.c b/kern/thread/synch.c index d083f4b..b7a08d9 100644 --- a/kern/thread/synch.c +++ b/kern/thread/synch.c @@ -47,18 +47,18 @@ struct semaphore * sem_create(const char *name, unsigned initial_count) { - struct semaphore *sem; + struct semaphore *sem; - sem = kmalloc(sizeof(*sem)); - if (sem == NULL) { - return NULL; - } + sem = kmalloc(sizeof(*sem)); + if (sem == NULL) { + return NULL; + } - sem->sem_name = kstrdup(name); - if (sem->sem_name == NULL) { - kfree(sem); - return NULL; - } + sem->sem_name = kstrdup(name); + if (sem->sem_name == NULL) { + kfree(sem); + return NULL; + } sem->sem_wchan = wchan_create(sem->sem_name); if (sem->sem_wchan == NULL) { @@ -68,39 +68,39 @@ sem_create(const char *name, unsigned initial_count) } spinlock_init(&sem->sem_lock); - sem->sem_count = initial_count; + sem->sem_count = initial_count; - return sem; + return sem; } void sem_destroy(struct semaphore *sem) { - KASSERT(sem != NULL); + KASSERT(sem != NULL); /* wchan_cleanup will assert if anyone's waiting on it */ spinlock_cleanup(&sem->sem_lock); wchan_destroy(sem->sem_wchan); - kfree(sem->sem_name); - kfree(sem); + kfree(sem->sem_name); + kfree(sem); } void P(struct semaphore *sem) { - KASSERT(sem != NULL); + KASSERT(sem != NULL); - /* - * May not block in an interrupt handler. - * - * For robustness, always check, even if we can actually - * complete the P without blocking. - */ - KASSERT(curthread->t_in_interrupt == false); + /* + * May not block in an interrupt handler. + * + * For robustness, always check, even if we can actually + * complete the P without blocking. + */ + KASSERT(curthread->t_in_interrupt == false); /* Use the semaphore spinlock to protect the wchan as well. */ spinlock_acquire(&sem->sem_lock); - while (sem->sem_count == 0) { + while (sem->sem_count == 0) { /* * * Note that we don't maintain strict FIFO ordering of @@ -114,21 +114,21 @@ P(struct semaphore *sem) * ordering? */ wchan_sleep(sem->sem_wchan, &sem->sem_lock); - } - KASSERT(sem->sem_count > 0); - sem->sem_count--; + } + KASSERT(sem->sem_count > 0); + sem->sem_count--; spinlock_release(&sem->sem_lock); } void V(struct semaphore *sem) { - KASSERT(sem != NULL); + KASSERT(sem != NULL); spinlock_acquire(&sem->sem_lock); - sem->sem_count++; - KASSERT(sem->sem_count > 0); + sem->sem_count++; + KASSERT(sem->sem_count > 0); wchan_wakeone(sem->sem_wchan, &sem->sem_lock); spinlock_release(&sem->sem_lock); @@ -141,59 +141,59 @@ V(struct semaphore *sem) struct lock * lock_create(const char *name) { - struct lock *lock; + struct lock *lock; - lock = kmalloc(sizeof(*lock)); - if (lock == NULL) { - return NULL; - } + lock = kmalloc(sizeof(*lock)); + if (lock == NULL) { + return NULL; + } - lock->lk_name = kstrdup(name); - if (lock->lk_name == NULL) { - kfree(lock); - return NULL; - } + lock->lk_name = kstrdup(name); + if (lock->lk_name == NULL) { + kfree(lock); + return NULL; + } - // add stuff here as needed + // add stuff here as needed - return lock; + return lock; } void lock_destroy(struct lock *lock) { - KASSERT(lock != NULL); + KASSERT(lock != NULL); - // add stuff here as needed + // add stuff here as needed - kfree(lock->lk_name); - kfree(lock); + kfree(lock->lk_name); + kfree(lock); } void lock_acquire(struct lock *lock) { - // Write this + // Write this - (void)lock; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written } void lock_release(struct lock *lock) { - // Write this + // Write this - (void)lock; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written } bool lock_do_i_hold(struct lock *lock) { - // Write this + // Write this - (void)lock; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written - return true; // dummy until code gets written + return true; // dummy until code gets written } //////////////////////////////////////////////////////////// @@ -204,47 +204,47 @@ lock_do_i_hold(struct lock *lock) struct cv * cv_create(const char *name) { - struct cv *cv; + struct cv *cv; - cv = kmalloc(sizeof(*cv)); - if (cv == NULL) { - return NULL; - } + cv = kmalloc(sizeof(*cv)); + if (cv == NULL) { + return NULL; + } - cv->cv_name = kstrdup(name); - if (cv->cv_name==NULL) { - kfree(cv); - return NULL; - } + cv->cv_name = kstrdup(name); + if (cv->cv_name==NULL) { + kfree(cv); + return NULL; + } - // add stuff here as needed + // add stuff here as needed - return cv; + return cv; } void cv_destroy(struct cv *cv) { - KASSERT(cv != NULL); + KASSERT(cv != NULL); - // add stuff here as needed + // add stuff here as needed - kfree(cv->cv_name); - kfree(cv); + kfree(cv->cv_name); + kfree(cv); } void cv_wait(struct cv *cv, struct lock *lock) { - // Write this - (void)cv; // suppress warning until code gets written - (void)lock; // suppress warning until code gets written + // Write this + (void)cv; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written } void cv_signal(struct cv *cv, struct lock *lock) { - // Write this + // Write this (void)cv; // suppress warning until code gets written (void)lock; // suppress warning until code gets written }