MODIFICATIONS.
*/
-#include "synch.h"
-#include "interrupt.h"
-#include "lib.h"
-#include "thread.h"
+#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
- integer along with two atomic operators for manipulating it:
+/* Initializes semaphore SEMA to VALUE. A semaphore is a
+ nonnegative integer along with two atomic operators for
+ manipulating it:
- down or "P": wait for the value to become positive, then
decrement it.
- up or "V": increment the value (and wake up one waiting
thread, if any). */
void
-sema_init (struct semaphore *sema, unsigned value, const char *name)
+sema_init (struct semaphore *sema, unsigned value)
{
ASSERT (sema != NULL);
- ASSERT (name != NULL);
- strlcpy (sema->name, name, sizeof sema->name);
sema->value = value;
list_init (&sema->waiters);
}
This function may sleep, so it must not be called within an
interrupt handler. This function may be called with
- interrupts disabled, but interrupts will be turned back on if
- we need to sleep. */
+ interrupts disabled, but if it sleeps then the next scheduled
+ thread will probably turn interrupts back on. */
void
sema_down (struct semaphore *sema)
{
intr_set_level (old_level);
}
+/* Down or "P" operation on a semaphore, but only if the
+ semaphore is not already 0. Returns true if the semaphore is
+ decremented, false otherwise.
+
+ This function may be called from an interrupt handler. */
+bool
+sema_try_down (struct semaphore *sema)
+{
+ enum intr_level old_level;
+ bool success;
+
+ ASSERT (sema != NULL);
+
+ old_level = intr_disable ();
+ if (sema->value > 0)
+ {
+ sema->value--;
+ success = true;
+ }
+ else
+ success = false;
+ intr_set_level (old_level);
+
+ return success;
+}
+
/* Up or "V" operation on a semaphore. Increments SEMA's value
and wakes up one thread of those waiting for SEMA, if any.
intr_set_level (old_level);
}
-/* Return SEMA's name (for debugging purposes). */
-const char *
-sema_name (const struct semaphore *sema)
-{
- return sema->name;
-}
-
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;
- printk ("Testing semaphores...");
- sema_init (&sema[0], 0, "ping");
- sema_init (&sema[1], 0, "pong");
- thread = thread_create ("sema-test", sema_test_helper, &sema);
+ printf ("Testing semaphores...");
+ sema_init (&sema[0], 0);
+ sema_init (&sema[1], 0);
+ thread_create ("sema-test", PRI_DEFAULT, sema_test_helper, &sema);
for (i = 0; i < 10; i++)
{
sema_up (&sema[0]);
sema_down (&sema[1]);
}
- printk ("done.\n");
+ printf ("done.\n");
}
/* Thread function used by sema_self_test(). */
}
}
\f
-/* Initializes LOCK and names it NAME (for debugging purposes).
- A lock can be held by at most a single thread at any given
- time. Our locks are not "recursive", that is, it is an error
- for the thread currently holding a lock to try to acquire that
- lock.
+/* Initializes LOCK. A lock can be held by at most a single
+ thread at any given time. Our locks are not "recursive", that
+ is, it is an error for the thread currently holding a lock to
+ try to acquire that lock.
A lock is a specialization of a semaphore with an initial
value of 1. The difference between a lock and such a
onerous, it's a good sign that a semaphore should be used,
instead of a lock. */
void
-lock_init (struct lock *lock, const char *name)
+lock_init (struct lock *lock)
{
ASSERT (lock != NULL);
- ASSERT (name != NULL);
- strlcpy (lock->name, name, sizeof lock->name);
lock->holder = NULL;
- sema_init (&lock->semaphore, 1, name);
+ sema_init (&lock->semaphore, 1);
}
/* Acquires LOCK, sleeping until it becomes available if
void
lock_acquire (struct lock *lock)
{
- enum intr_level old_level;
-
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (!lock_held_by_current_thread (lock));
- old_level = intr_disable ();
sema_down (&lock->semaphore);
lock->holder = thread_current ();
- intr_set_level (old_level);
+}
+
+/* Tries to acquires LOCK and returns true if successful or false
+ on failure. The lock must not already be held by the current
+ thread.
+
+ This function will not sleep, so it may be called within an
+ interrupt handler. */
+bool
+lock_try_acquire (struct lock *lock)
+{
+ bool success;
+
+ ASSERT (lock != NULL);
+ ASSERT (!lock_held_by_current_thread (lock));
+
+ success = sema_try_down (&lock->semaphore);
+ if (success)
+ lock->holder = thread_current ();
+ return success;
}
/* 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)
{
- enum intr_level old_level;
-
ASSERT (lock != NULL);
ASSERT (lock_held_by_current_thread (lock));
- old_level = intr_disable ();
lock->holder = NULL;
sema_up (&lock->semaphore);
- intr_set_level (old_level);
}
/* Returns true if the current thread holds LOCK, false
return lock->holder == thread_current ();
}
-
-/* Returns the name of LOCK (for debugging purposes). */
-const char *
-lock_name (const struct lock *lock)
-{
- ASSERT (lock != NULL);
-
- return lock->name;
-}
\f
/* One semaphore in a list. */
struct semaphore_elem
{
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
struct semaphore semaphore; /* This semaphore. */
};
-/* Initializes condition variable COND and names it NAME. A
- condition variable allows one piece of code to signal a
- condition and cooperating code to receive the signal and act
- upon it. */
+/* Initializes condition variable COND. A condition variable
+ allows one piece of code to signal a condition and cooperating
+ code to receive the signal and act upon it. */
void
-cond_init (struct condition *cond, const char *name)
+cond_init (struct condition *cond)
{
ASSERT (cond != NULL);
- ASSERT (name != NULL);
- strlcpy (cond->name, name, sizeof cond->name);
list_init (&cond->waiters);
}
/* 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.
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.
ASSERT (!intr_context ());
ASSERT (lock_held_by_current_thread (lock));
- sema_init (&waiter.semaphore, 0, "condition");
+ sema_init (&waiter.semaphore, 0);
list_push_back (&cond->waiters, &waiter.elem);
lock_release (lock);
sema_down (&waiter.semaphore);
make sense to try to signal a condition variable within an
interrupt handler. */
void
-cond_signal (struct condition *cond, struct lock *lock)
+cond_signal (struct condition *cond, struct lock *lock UNUSED)
{
ASSERT (cond != NULL);
ASSERT (lock != NULL);
while (!list_empty (&cond->waiters))
cond_signal (cond, lock);
}
-
-/* Returns COND's name (for debugging purposes). */
-const char *
-cond_name (const struct condition *cond)
-{
- ASSERT (cond != NULL);
-
- return cond->name;
-}