Move problem 1-2 (join) into project 2 as the "wait" system call.
[pintos-anon] / src / threads / synch.c
index ea38068ad017f58888cdf34c9d9f5ce652d4449e..1504d98859f8b54cc6c6688f5ed1de3227cd97f8 100644 (file)
@@ -1,14 +1,36 @@
-#include "synch.h"
-#include "interrupt.h"
-#include "lib.h"
-#include "thread.h"
-
-/* One thread in a list. */
-struct thread_elem
-  {
-    list_elem elem;
-    struct thread *thread;      
-  };
+/* This file is derived from source code for the Nachos
+   instructional operating system.  The Nachos copyright notice
+   is reproduced in full below. */
+
+/* Copyright (c) 1992-1996 The Regents of the University of California.
+   All rights reserved.
+
+   Permission to use, copy, modify, and distribute this software
+   and its documentation for any purpose, without fee, and
+   without written agreement is hereby granted, provided that the
+   above copyright notice and the following two paragraphs appear
+   in all copies of this software.
+
+   IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO
+   ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
+   CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE
+   AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
+   HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
+   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+   PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+   BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+   PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+   MODIFICATIONS.
+*/
+
+#include "threads/synch.h"
+#include <stdio.h>
+#include <string.h>
+#include "threads/interrupt.h"
+#include "threads/thread.h"
 
 /* Initializes semaphore SEMA to VALUE and names it NAME (for
    debugging purposes only).  A semaphore is a nonnegative
@@ -30,8 +52,8 @@ sema_init (struct semaphore *sema, unsigned value, const char *name)
   list_init (&sema->waiters);
 }
 
-/* Waits for SEMA's value to become positive and then
-   atomically decrements it.
+/* Down or "P" operation on a semaphore.  Waits for SEMA's value
+   to become positive and then atomically decrements it.
 
    This function may sleep, so it must not be called within an
    interrupt handler.  This function may be called with
@@ -48,17 +70,15 @@ sema_down (struct semaphore *sema)
   old_level = intr_disable ();
   while (sema->value == 0) 
     {
-      struct thread_elem te;
-      te.thread = thread_current ();
-      list_push_back (&sema->waiters, &te.elem);
-      thread_sleep ();
+      list_push_back (&sema->waiters, &thread_current ()->elem);
+      thread_block ();
     }
   sema->value--;
   intr_set_level (old_level);
 }
 
-/* Increments SEMA's value.  Wakes up one thread of those waiting
-   for SEMA, if any. 
+/* Up or "V" operation on a semaphore.  Increments SEMA's value
+   and wakes up one thread of those waiting for SEMA, if any.
 
    This function may be called from an interrupt handler. */
 void
@@ -70,8 +90,8 @@ sema_up (struct semaphore *sema)
 
   old_level = intr_disable ();
   if (!list_empty (&sema->waiters)) 
-    thread_wake (list_entry (list_pop_front (&sema->waiters),
-                             struct thread_elem, elem)->thread);
+    thread_unblock (list_entry (list_pop_front (&sema->waiters),
+                                struct thread, elem));
   sema->value++;
   intr_set_level (old_level);
 }
@@ -83,37 +103,41 @@ sema_name (const struct semaphore *sema)
   return sema->name;
 }
 
-static void
-sema_test_helper (void *sema_) 
-{
-  struct semaphore *sema = sema_;
-  int i;
-
-  for (i = 0; i < 10; i++) 
-    {
-      sema_down (&sema[0]);
-      sema_up (&sema[1]);
-    }
-}
+static void sema_test_helper (void *sema_);
 
 /* Self-test for semaphores that makes control "ping-pong"
-   between a pair of threads.  Insert calls to printk() to see
+   between a pair of threads.  Insert calls to printf() to see
    what's going on. */
 void
 sema_self_test (void) 
 {
-  struct thread *thread;
   struct semaphore sema[2];
   int i;
 
+  printf ("Testing semaphores...");
   sema_init (&sema[0], 0, "ping");
   sema_init (&sema[1], 0, "pong");
-  thread = thread_create ("sema-test", sema_test_helper, &sema);
+  thread_create ("sema-test", PRI_DEFAULT, sema_test_helper, &sema);
   for (i = 0; i < 10; i++) 
     {
       sema_up (&sema[0]);
       sema_down (&sema[1]);
     }
+  printf ("done.\n");
+}
+
+/* Thread function used by sema_self_test(). */
+static void
+sema_test_helper (void *sema_) 
+{
+  struct semaphore *sema = sema_;
+  int i;
+
+  for (i = 0; i < 10; i++) 
+    {
+      sema_down (&sema[0]);
+      sema_up (&sema[1]);
+    }
 }
 \f
 /* Initializes LOCK and names it NAME (for debugging purposes).
@@ -138,7 +162,6 @@ lock_init (struct lock *lock, const char *name)
   ASSERT (lock != NULL);
   ASSERT (name != NULL);
 
-  strlcpy (lock->name, name, sizeof lock->name);
   lock->holder = NULL;
   sema_init (&lock->semaphore, 1, name);
 }
@@ -169,8 +192,8 @@ lock_acquire (struct lock *lock)
 /* Releases LOCK, which must be owned by the current thread.
 
    An interrupt handler cannot acquire a lock, so it does not
-   make sense to try to signal a condition variable within an
-   interrupt handler. */
+   make sense to try to release a lock within an interrupt
+   handler. */
 void
 lock_release (struct lock *lock) 
 {
@@ -202,14 +225,14 @@ lock_name (const struct lock *lock)
 {
   ASSERT (lock != NULL);
 
-  return lock->name;
+  return sema_name (&lock->semaphore);
 }
 \f
 /* One semaphore in a list. */
 struct semaphore_elem 
   {
-    list_elem elem;
-    struct semaphore semaphore;
+    struct list_elem elem;              /* List element. */
+    struct semaphore semaphore;         /* This semaphore. */
   };
 
 /* Initializes condition variable COND and names it NAME.  A
@@ -227,18 +250,18 @@ cond_init (struct condition *cond, const char *name)
 }
 
 /* Atomically releases LOCK and waits for COND to be signaled by
-   some other piece of code.  After COND is signalled, LOCK is
+   some other piece of code.  After COND is signaled, LOCK is
    reacquired before returning.  LOCK must be held before calling
    this function.
 
    The monitor implemented by this function is "Mesa" style, not
-   "Hoare" style.  That is, sending a signal is not atomic with
-   delivering it.  Thus, typically the caller must recheck the
-   condition after the wait completes and, if necessary, wait
+   "Hoare" style, that is, sending and receiving a signal are not
+   an atomic operation.  Thus, typically the caller must recheck
+   the condition after the wait completes and, if necessary, wait
    again.
 
    A given condition variable is associated with only a single
-   lock, but one lock may be be associated with any number of
+   lock, but one lock may be associated with any number of
    condition variables.  That is, there is a one-to-many mapping
    from locks to condition variables.