---- cs140/pintos/src/threads/thread.c 2004-09-17 23:16:15.000000000 -0700
-+++ cs140/ref/pintos/src/threads/thread.c 2004-09-17 23:19:03.000000000 -0700
-@@ -75,6 +75,7 @@
+diff -X pat -urpN pintos.orig/src/threads/synch.c pintos/src/threads/synch.c
+--- pintos.orig/src/threads/synch.c 2004-09-19 21:29:53.000000000 -0700
++++ pintos/src/threads/synch.c 2004-09-27 16:50:14.000000000 -0700
+@@ -330,3 +330,35 @@ cond_name (const struct condition *cond)
+
+ return cond->name;
+ }
++\f
++void
++latch_init (struct latch *latch, const char *name)
++{
++ latch->released = false;
++ lock_init (&latch->monitor_lock, name);
++ cond_init (&latch->rel_cond, name);
++}
++
++void
++latch_acquire (struct latch *latch)
++{
++ lock_acquire (&latch->monitor_lock);
++ if (!latch->released)
++ {
++ cond_wait (&latch->rel_cond, &latch->monitor_lock);
++ ASSERT (latch->released);
++ }
++ lock_release (&latch->monitor_lock);
++}
++
++void
++latch_release (struct latch *latch)
++{
++ lock_acquire (&latch->monitor_lock);
++ if (!latch->released)
++ {
++ latch->released = true;
++ cond_signal (&latch->rel_cond, &latch->monitor_lock);
++ }
++ lock_release (&latch->monitor_lock);
++}
+diff -X pat -urpN pintos.orig/src/threads/synch.h pintos/src/threads/synch.h
+--- pintos.orig/src/threads/synch.h 2004-09-19 21:29:53.000000000 -0700
++++ pintos/src/threads/synch.h 2004-09-27 16:50:14.000000000 -0700
+@@ -44,4 +44,16 @@ void cond_signal (struct condition *, st
+ void cond_broadcast (struct condition *, struct lock *);
+ const char *cond_name (const struct condition *);
+
++/* Latch. */
++struct latch
++ {
++ bool released; /* Released yet? */
++ struct lock monitor_lock; /* Monitor lock. */
++ struct condition rel_cond; /* Signaled when released. */
++ };
++
++void latch_init (struct latch *, const char *);
++void latch_acquire (struct latch *);
++void latch_release (struct latch *);
++
+ #endif /* threads/synch.h */
+diff -X pat -urpN pintos.orig/src/threads/thread.c pintos/src/threads/thread.c
+--- pintos.orig/src/threads/thread.c 2004-09-26 14:15:17.000000000 -0700
++++ pintos/src/threads/thread.c 2004-09-27 16:51:03.000000000 -0700
+@@ -80,6 +80,7 @@ thread_init (void)
init_thread (initial_thread, "main", PRI_DEFAULT);
initial_thread->status = THREAD_RUNNING;
initial_thread->tid = allocate_tid ();
+ sema_up (&initial_thread->can_die);
+ }
+
+ /* Starts preemptive thread scheduling by enabling interrupts.
+@@ -148,6 +149,7 @@ thread_create (const char *name, int pri
+ /* Initialize thread. */
+ init_thread (t, name, priority);
+ tid = t->tid = allocate_tid ();
++ list_push_back (&thread_current ()->children, &t->children_elem);
- /* Initialize run queue. */
- list_init (&ready_list);
-@@ -244,12 +245,29 @@
+ /* Stack frame for kernel_thread(). */
+ kf = alloc_frame (t, sizeof *kf);
+@@ -224,16 +226,34 @@ thread_tid (void)
void
thread_exit (void)
{
+ struct thread *t = thread_current ();
-+ list_elem *e;
++ list_elem *e, *next;
+
ASSERT (!intr_context ());
+ #ifdef USERPROG
+ process_exit ();
+ #endif
+
+ /* Notify our parent that we're dying. */
-+ sema_up (&t->ready_to_die);
++ latch_release (&t->ready_to_die);
+
+ /* Notify our children that they can die. */
-+ for (e = list_begin (&t->children); e != list_end (&t->children);
-+ e = list_next (e))
++ for (e = list_begin (&t->children); e != list_end (&t->children); e = next)
+ {
+ struct thread *child = list_entry (e, struct thread, children_elem);
++ next = list_next (e);
++ list_remove (e);
+ sema_up (&child->can_die);
+ }
+
schedule ();
NOT_REACHED ();
}
-@@ -286,6 +304,31 @@
+@@ -270,6 +290,22 @@ thread_block (void)
thread_current ()->status = THREAD_BLOCKED;
schedule ();
}
+ struct thread *child = list_entry (e, struct thread, children_elem);
+ e = list_next (e);
+ if (child->tid == child_tid)
-+ {
-+ /* Wait until child is ready to die. */
-+ sema_down (&child->ready_to_die);
-+
-+ /* Remove from list of children. */
-+ list_remove (&child->children_elem);
-+
-+ /* Notify child that it can finish dying. */
-+ sema_up (&child->can_die);
-+ }
++ latch_acquire (&child->ready_to_die);
+ }
+}
\f
/* Idle thread. Executes when no other thread is ready to run. */
static void
-@@ -348,12 +391,13 @@
- {
- init_thread (t, name, priority);
- t->tid = allocate_tid ();
-+ list_push_back (&thread_current ()->children, &t->children_elem);
- }
-
- return t;
- }
-
--/* Does basic initialization of T as a blocked thread named
-+/* Does basic initialization of T as a new, blocked thread named
- NAME. */
- static void
- init_thread (struct thread *t, const char *name, int priority)
-@@ -367,6 +411,9 @@
+@@ -335,6 +371,9 @@ init_thread (struct thread *t, const cha
strlcpy (t->name, name, sizeof t->name);
t->stack = (uint8_t *) t + PGSIZE;
t->priority = priority;
-+ sema_init (&t->ready_to_die, 0, "ready-to-die");
++ latch_init (&t->ready_to_die, "ready-to-die");
+ sema_init (&t->can_die, 0, "can-die");
+ list_init (&t->children);
t->magic = THREAD_MAGIC;
}
---- cs140/pintos/src/threads/thread.h 2004-09-16 21:42:35.000000000 -0700
-+++ cs140/ref/pintos/src/threads/thread.h 2004-09-17 23:21:14.000000000 -0700
+diff -X pat -urpN pintos.orig/src/threads/thread.h pintos/src/threads/thread.h
+--- pintos.orig/src/threads/thread.h 2004-09-26 14:15:17.000000000 -0700
++++ pintos/src/threads/thread.h 2004-09-27 16:50:14.000000000 -0700
@@ -4,6 +4,7 @@
#include <debug.h>
#include <list.h>
#include <stdint.h>
+#include "threads/synch.h"
- #ifdef USERPROG
- #include "userprog/addrspace.h"
-@@ -93,6 +94,12 @@
+ /* States in a thread's life cycle. */
+ enum thread_status
+@@ -89,6 +90,12 @@ struct thread
uint8_t *stack; /* Saved stack pointer. */
int priority; /* Priority. */
+ /* Members for implementing thread_join(). */
-+ struct semaphore ready_to_die; /* Up when thread about to die. */
++ struct latch ready_to_die; /* Release when thread about to die. */
+ struct semaphore can_die; /* Up when thread allowed to die. */
+ struct list children; /* List of child threads. */
+ list_elem children_elem; /* Element of `children' list. */