diff --git a/kern/include/synch.h b/kern/include/synch.h
index ac3714b..461eedc 100644
--- a/kern/include/synch.h
+++ b/kern/include/synch.h
@@ -74,8 +74,12 @@ void V(struct semaphore *);
*/
struct lock {
char *lk_name;
- // add what you need here
- // (don't forget to mark things volatile as needed)
+
+ // BEGIN SOLUTION
+ struct wchan *lk_wchan;
+ struct spinlock lk_lock;
+ volatile struct thread *lk_holder;
+ // END SOLUTION
};
struct lock *lock_create(const char *name);
@@ -113,8 +117,10 @@ void lock_destroy(struct lock *);
struct cv {
char *cv_name;
- // add what you need here
- // (don't forget to mark things volatile as needed)
+
+ // BEGIN SOLUTION
+ struct wchan *cv_wchan;
+ // END SOLUTION
};
struct cv *cv_create(const char *name);
diff --git a/kern/include/version.h b/kern/include/version.h
index 9fec0e8..4734a98 100644
--- a/kern/include/version.h
+++ b/kern/include/version.h
@@ -35,6 +35,7 @@
* code we gave you.
*/
#define BASE_VERSION "1.99.05"
+#define ASST1SOL_VERSION "1.0"
/*
* Change this as you see fit in the course of hacking the system.
diff --git a/kern/startup/main.c b/kern/startup/main.c
index be4c4b8..535a864 100644
--- a/kern/startup/main.c
+++ b/kern/startup/main.c
@@ -96,7 +96,7 @@ boot(void)
*/
kprintf("\n");
- kprintf("OS/161 base system version %s\n", BASE_VERSION);
+ kprintf("OS/161 base version %s ASST1 solution version %s\n", BASE_VERSION, ASST1SOL_VERSION);
kprintf("%s", harvard_copyright);
kprintf("\n");
diff --git a/kern/thread/synch.c b/kern/thread/synch.c
index 9a7468c..fb983b4 100644
--- a/kern/thread/synch.c
+++ b/kern/thread/synch.c
@@ -163,7 +163,16 @@ lock_create(const char *name)
return NULL;
}
- // add stuff here as needed
+ // BEGIN SOLUTION
+ lock->lk_wchan = wchan_create(lock->lk_name);
+ if (lock->lk_wchan == NULL) {
+ kfree(lock->lk_name);
+ kfree(lock);
+ return NULL;
+ }
+ spinlock_init(&lock->lk_lock);
+ lock->lk_holder = NULL;
+ // END SOLUTION
return lock;
}
@@ -173,7 +182,11 @@ lock_destroy(struct lock *lock)
{
KASSERT(lock != NULL);
- // add stuff here as needed
+ // BEGIN SOLUTION
+ KASSERT(lock->lk_holder == NULL);
+ spinlock_cleanup(&lock->lk_lock);
+ wchan_destroy(lock->lk_wchan);
+ // END SOLUTION
kfree(lock->lk_name);
kfree(lock);
@@ -182,27 +195,52 @@ lock_destroy(struct lock *lock)
void
lock_acquire(struct lock *lock)
{
- // Write this
+ // BEGIN SOLUTION
+ DEBUGASSERT(lock != NULL);
+ KASSERT(curthread->t_in_interrupt == false);
+
+ spinlock_acquire(&lock->lk_lock);
+ while (lock->lk_holder != NULL) {
+ /* As in the semaphore. */
+ wchan_lock(lock->lk_wchan);
+ spinlock_release(&lock->lk_lock);
+ wchan_sleep(lock->lk_wchan);
+
+ spinlock_acquire(&lock->lk_lock);
+ }
- (void)lock; // suppress warning until code gets written
+ lock->lk_holder = curthread;
+ spinlock_release(&lock->lk_lock);
+ // END SOLUTION
}
void
lock_release(struct lock *lock)
{
- // Write this
-
- (void)lock; // suppress warning until code gets written
+ // BEGIN SOLUTION
+ DEBUGASSERT(lock != NULL);
+
+ spinlock_acquire(&lock->lk_lock);
+ lock->lk_holder = NULL;
+ wchan_wakeone(lock->lk_wchan);
+ spinlock_release(&lock->lk_lock);
+ // END SOLUTION
}
bool
lock_do_i_hold(struct lock *lock)
{
- // Write this
+ // BEGIN SOLUTION
+ bool ret;
- (void)lock; // suppress warning until code gets written
+ DEBUGASSERT(lock != NULL);
- return true; // dummy until code gets written
+ spinlock_acquire(&lock->lk_lock);
+ ret = (lock->lk_holder == curthread);
+ spinlock_release(&lock->lk_lock);
+
+ return ret;
+ // END SOLUTION
}
////////////////////////////////////////////////////////////
@@ -226,7 +264,14 @@ cv_create(const char *name)
return NULL;
}
- // add stuff here as needed
+ // BEGIN SOLUTION
+ cv->cv_wchan = wchan_create(cv->cv_name);
+ if (cv->cv_wchan == NULL) {
+ kfree(cv->cv_name);
+ kfree(cv);
+ return NULL;
+ }
+ // END SOLUTION
return cv;
}
@@ -236,7 +281,9 @@ cv_destroy(struct cv *cv)
{
KASSERT(cv != NULL);
- // add stuff here as needed
+ // BEGIN SOLUTION
+ wchan_destroy(cv->cv_wchan);
+ // END SOLUTION
kfree(cv->cv_name);
kfree(cv);
@@ -245,23 +292,28 @@ cv_destroy(struct cv *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
+ // BEGIN SOLUTION
+ wchan_lock(cv->cv_wchan);
+ lock_release(lock);
+ wchan_sleep(cv->cv_wchan);
+ lock_release(lock);
+ // END SOLUTION
}
-
+
void
cv_signal(struct cv *cv, struct lock *lock)
{
- // Write this
- (void)cv; // suppress warning until code gets written
- (void)lock; // suppress warning until code gets written
+ // BEGIN SOLUTION
+ (void)lock;
+ wchan_wakeone(cv->cv_wchan);
+ // END SOLUTION
}
-
+
void
cv_broadcast(struct cv *cv, struct lock *lock)
{
- // Write this
- (void)cv; // suppress warning until code gets written
- (void)lock; // suppress warning until code gets written
+ // BEGIN SOLUTION
+ (void)lock;
+ wchan_wakeall(cv->cv_wchan);
+ // END SOLUTION
}