diff --git a/kern/include/synch.h b/kern/include/synch.h index c80c62d..ac5f730 100644 --- a/kern/include/synch.h +++ b/kern/include/synch.h @@ -127,6 +127,8 @@ struct cv { char *cv_name; // add what you need here // (don't forget to mark things volatile as needed) + struct wchan *wchan; + struct spinlock slk; }; struct cv *cv_create(const char *name); diff --git a/kern/thread/synch.c b/kern/thread/synch.c index bc64eac..d5d4e3d 100644 --- a/kern/thread/synch.c +++ b/kern/thread/synch.c @@ -227,7 +227,7 @@ lock_release(struct lock *lock) #elif OPT_WCHANLOCK spinlock_acquire(&lock->slk); lock->owner = NULL; - wchan_wakeall(lock->wchan, &lock->slk); + wchan_wakeone(lock->wchan, &lock->slk); spinlock_release(&lock->slk); #else lock->owner = NULL; @@ -272,8 +272,15 @@ cv_create(const char *name) return NULL; } - // add stuff here as needed - +#if OPT_WCHANLOCK + cv->wchan = wchan_create(name); + if (cv->wchan == NULL) { + kfree(cv->cv_name); + kfree(cv); + return NULL; + } + spinlock_init(&cv->slk); +#endif return cv; } @@ -282,8 +289,10 @@ cv_destroy(struct cv *cv) { KASSERT(cv != NULL); - // add stuff here as needed - +#if OPT_WCHANLOCK + spinlock_cleanup(&cv->slk); + wchan_destroy(cv->wchan); +#endif kfree(cv->cv_name); kfree(cv); } @@ -291,23 +300,50 @@ cv_destroy(struct cv *cv) void cv_wait(struct cv *cv, struct lock *lock) { - // Write this +#if OPT_WCHANLOCK + KASSERT(cv != NULL); + KASSERT(lock_do_i_hold(lock)); + + spinlock_acquire(&cv->slk); + + lock_release(lock); + wchan_sleep(cv->wchan,&cv->slk); + spinlock_release(&cv->slk); + lock_acquire(lock); +#else (void)cv; // suppress warning until code gets written (void)lock; // suppress warning until code gets written +#endif } void cv_signal(struct cv *cv, struct lock *lock) { - // Write this +#if OPT_WCHANLOCK + KASSERT(cv != NULL); + KASSERT(lock_do_i_hold(lock)); + + spinlock_acquire(&cv->slk); + wchan_wakeone(cv->wchan, &cv->slk); + spinlock_release(&cv->slk); +#else (void)cv; // suppress warning until code gets written (void)lock; // suppress warning until code gets written +#endif } void cv_broadcast(struct cv *cv, struct lock *lock) { - // Write this +#if OPT_WCHANLOCK + KASSERT(cv != NULL); + KASSERT(lock_do_i_hold(lock)); + + spinlock_acquire(&cv->slk); + wchan_wakeall(cv->wchan, &cv->slk); + spinlock_release(&cv->slk); +#else (void)cv; // suppress warning until code gets written (void)lock; // suppress warning until code gets written +#endif }