diff --git a/kern/conf/DUMBVM b/kern/conf/DUMBVM index 7862c64..6cabdba 100644 --- a/kern/conf/DUMBVM +++ b/kern/conf/DUMBVM @@ -30,3 +30,6 @@ options sfs # Always use the file system #options netfs # You might write this as a project. options dumbvm # Chewing gum and baling wire. + +#options semlock #locks with semaphores +options wchanlock #locks with wchans diff --git a/kern/conf/conf.kern b/kern/conf/conf.kern index 1e57da3..b5d5821 100644 --- a/kern/conf/conf.kern +++ b/kern/conf/conf.kern @@ -444,6 +444,9 @@ optfile net test/nettest.c defoption hello optfile hello main/hello.c +defoption semlock +defoption wchanlock + # LAB2 file syscall/file_syscalls.c file syscall/proc_syscalls.c diff --git a/kern/include/synch.h b/kern/include/synch.h index fee3b07..c80c62d 100644 --- a/kern/include/synch.h +++ b/kern/include/synch.h @@ -37,6 +37,9 @@ #include +#include "opt-semlock.h" +#include "opt-wchanlock.h" + /* * Dijkstra-style semaphore. * @@ -72,10 +75,19 @@ void V(struct semaphore *); * The name field is for easier debugging. A copy of the name is * (should be) made internally. */ + struct lock { char *lk_name; + volatile struct thread *owner; +#if OPT_SEMLOCK + struct semaphore *sem; +#elif OPT_WCHANLOCK + struct spinlock slk; + struct wchan *wchan; +#else // add what you need here // (don't forget to mark things volatile as needed) +#endif }; struct lock *lock_create(const char *name); diff --git a/kern/thread/synch.c b/kern/thread/synch.c index d083f4b..bc64eac 100644 --- a/kern/thread/synch.c +++ b/kern/thread/synch.c @@ -156,6 +156,24 @@ lock_create(const char *name) // add stuff here as needed +#if OPT_SEMLOCK + lock->sem = sem_create(name, 1); + if (lock->sem == NULL) { + kfree(lock->lk_name); + kfree(lock); + return NULL; + } +#elif OPT_WCHANLOCK + lock->wchan = wchan_create(lock->lk_name); + if (lock->wchan == NULL) { + kfree(lock->lk_name); + kfree(lock); + return NULL; + } + spinlock_init(&lock->slk); +#endif + + lock->owner = NULL; return lock; } @@ -167,6 +185,12 @@ lock_destroy(struct lock *lock) // add stuff here as needed kfree(lock->lk_name); +#if OPT_SEMLOCK + sem_destroy(lock->sem); +#elif OPT_WCHANLOCK + wchan_destroy(lock->wchan); + spinlock_cleanup(&lock->slk); +#endif kfree(lock); } @@ -175,7 +199,19 @@ lock_acquire(struct lock *lock) { // Write this - (void)lock; // suppress warning until code gets written +#if OPT_SEMLOCK + P(lock->sem); + lock->owner = curthread; +#elif OPT_WCHANLOCK + spinlock_acquire(&lock->slk); + while (lock->owner != NULL) { + wchan_sleep(lock->wchan, &lock->slk); + } + lock->owner = curthread; + spinlock_release(&lock->slk); +#else + lock->owner = curthread; +#endif } void @@ -183,17 +219,36 @@ lock_release(struct lock *lock) { // Write this - (void)lock; // suppress warning until code gets written + KASSERT(lock != NULL); + KASSERT(lock_do_i_hold(lock)); +#if OPT_SEMLOCK + lock->owner = NULL; + V(lock->sem); +#elif OPT_WCHANLOCK + spinlock_acquire(&lock->slk); + lock->owner = NULL; + wchan_wakeall(lock->wchan, &lock->slk); + spinlock_release(&lock->slk); +#else + lock->owner = NULL; +#endif } bool lock_do_i_hold(struct lock *lock) { // Write this + KASSERT(lock != NULL); +#if OPT_WCHANLOCK + bool ret = true; + spinlock_acquire(&lock->slk); + ret = lock->owner == curthread; + spinlock_release(&lock->slk); + return ret; // dummy until code gets written +#else + return lock->owner == curthread; +#endif - (void)lock; // suppress warning until code gets written - - return true; // dummy until code gets written } ////////////////////////////////////////////////////////////