Add volatile to asm statement in intr_get_level(),
[pintos-anon] / solutions / p1-2.patch
1 diff -X pat -urpN pintos.orig/src/threads/synch.c pintos/src/threads/synch.c
2 --- pintos.orig/src/threads/synch.c     2004-09-19 21:29:53.000000000 -0700
3 +++ pintos/src/threads/synch.c  2004-09-27 16:50:14.000000000 -0700
4 @@ -330,3 +330,35 @@ cond_name (const struct condition *cond)
5  
6    return cond->name;
7  }
8 +\f
9 +void
10 +latch_init (struct latch *latch, const char *name) 
11 +{
12 +  latch->released = false;
13 +  lock_init (&latch->monitor_lock, name);
14 +  cond_init (&latch->rel_cond, name);
15 +}
16 +
17 +void
18 +latch_acquire (struct latch *latch) 
19 +{
20 +  lock_acquire (&latch->monitor_lock);
21 +  if (!latch->released) 
22 +    {
23 +      cond_wait (&latch->rel_cond, &latch->monitor_lock);
24 +      ASSERT (latch->released); 
25 +    }
26 +  lock_release (&latch->monitor_lock);
27 +}
28 +
29 +void
30 +latch_release (struct latch *latch) 
31 +{
32 +  lock_acquire (&latch->monitor_lock);
33 +  if (!latch->released)
34 +    {
35 +      latch->released = true;
36 +      cond_signal (&latch->rel_cond, &latch->monitor_lock);
37 +    }
38 +  lock_release (&latch->monitor_lock);
39 +}
40 diff -X pat -urpN pintos.orig/src/threads/synch.h pintos/src/threads/synch.h
41 --- pintos.orig/src/threads/synch.h     2004-09-19 21:29:53.000000000 -0700
42 +++ pintos/src/threads/synch.h  2004-09-27 16:50:14.000000000 -0700
43 @@ -44,4 +44,16 @@ void cond_signal (struct condition *, st
44  void cond_broadcast (struct condition *, struct lock *);
45  const char *cond_name (const struct condition *);
46  
47 +/* Latch. */
48 +struct latch 
49 +  {
50 +    bool released;              /* Released yet? */
51 +    struct lock monitor_lock;   /* Monitor lock. */
52 +    struct condition rel_cond;  /* Signaled when released. */
53 +  };
54 +
55 +void latch_init (struct latch *, const char *);
56 +void latch_acquire (struct latch *);
57 +void latch_release (struct latch *);
58 +
59  #endif /* threads/synch.h */
60 diff -X pat -urpN pintos.orig/src/threads/thread.c pintos/src/threads/thread.c
61 --- pintos.orig/src/threads/thread.c    2004-09-26 14:15:17.000000000 -0700
62 +++ pintos/src/threads/thread.c 2004-09-27 16:51:03.000000000 -0700
63 @@ -80,6 +80,7 @@ thread_init (void) 
64    init_thread (initial_thread, "main", PRI_DEFAULT);
65    initial_thread->status = THREAD_RUNNING;
66    initial_thread->tid = allocate_tid ();
67 +  sema_up (&initial_thread->can_die);
68  }
69  
70  /* Starts preemptive thread scheduling by enabling interrupts.
71 @@ -148,6 +149,7 @@ thread_create (const char *name, int pri
72    /* Initialize thread. */
73    init_thread (t, name, priority);
74    tid = t->tid = allocate_tid ();
75 +  list_push_back (&thread_current ()->children, &t->children_elem);
76  
77    /* Stack frame for kernel_thread(). */
78    kf = alloc_frame (t, sizeof *kf);
79 @@ -224,16 +226,33 @@ thread_tid (void) 
80  void
81  thread_exit (void) 
82  {
83 +  struct thread *t = thread_current ();
84 +  list_elem *e;
85 +
86    ASSERT (!intr_context ());
87  
88  #ifdef USERPROG
89    process_exit ();
90  #endif
91  
92 +  /* Notify our parent that we're dying. */
93 +  latch_release (&t->ready_to_die);
94 +
95 +  /* Notify our children that they can die. */
96 +  for (e = list_begin (&t->children); e != list_end (&t->children);
97 +       e = list_next (e)) 
98 +    {
99 +      struct thread *child = list_entry (e, struct thread, children_elem);
100 +      sema_up (&child->can_die); 
101 +    }
102 +
103 +  /* Wait until our parent is ready for us to die. */
104 +  sema_down (&t->can_die);
105 +
106    /* Just set our status to dying and schedule another process.
107       We will be destroyed during the call to schedule_tail(). */
108    intr_disable ();
109 -  thread_current ()->status = THREAD_DYING;
110 +  t->status = THREAD_DYING;
111    schedule ();
112    NOT_REACHED ();
113  }
114 @@ -270,6 +290,22 @@ thread_block (void) 
115    thread_current ()->status = THREAD_BLOCKED;
116    schedule ();
117  }
118 +
119 +/* Waits for thread with tid CHILD_TID to die. */
120 +void
121 +thread_join (tid_t child_tid) 
122 +{
123 +  struct thread *cur = thread_current ();
124 +  list_elem *e;
125 +
126 +  for (e = list_begin (&cur->children); e != list_end (&cur->children); ) 
127 +    {
128 +      struct thread *child = list_entry (e, struct thread, children_elem);
129 +      e = list_next (e);
130 +      if (child->tid == child_tid) 
131 +        latch_acquire (&child->ready_to_die);
132 +    }
133 +}
134  \f
135  /* Idle thread.  Executes when no other thread is ready to run. */
136  static void
137 @@ -335,6 +371,9 @@ init_thread (struct thread *t, const cha
138    strlcpy (t->name, name, sizeof t->name);
139    t->stack = (uint8_t *) t + PGSIZE;
140    t->priority = priority;
141 +  latch_init (&t->ready_to_die, "ready-to-die");
142 +  sema_init (&t->can_die, 0, "can-die");
143 +  list_init (&t->children);
144    t->magic = THREAD_MAGIC;
145  }
146  
147 diff -X pat -urpN pintos.orig/src/threads/thread.h pintos/src/threads/thread.h
148 --- pintos.orig/src/threads/thread.h    2004-09-26 14:15:17.000000000 -0700
149 +++ pintos/src/threads/thread.h 2004-09-27 16:50:14.000000000 -0700
150 @@ -4,6 +4,7 @@
151  #include <debug.h>
152  #include <list.h>
153  #include <stdint.h>
154 +#include "threads/synch.h"
155  
156  /* States in a thread's life cycle. */
157  enum thread_status
158 @@ -89,6 +90,12 @@ struct thread
159      uint8_t *stack;                     /* Saved stack pointer. */
160      int priority;                       /* Priority. */
161  
162 +    /* Members for implementing thread_join(). */
163 +    struct latch ready_to_die;          /* Release when thread about to die. */
164 +    struct semaphore can_die;           /* Up when thread allowed to die. */
165 +    struct list children;               /* List of child threads. */
166 +    list_elem children_elem;            /* Element of `children' list. */
167 +
168      /* Shared between thread.c and synch.c. */
169      list_elem elem;                     /* List element. */
170