
#
# pseudocode for Lock implementation
#
class Lock:
  def __init__(self):
    self.spinlock = False
    self.is_held  = False # protected by spinlock
    self.queue    = []    # protected by spinlock

  def acquire(self):
    # grab spin lock
    while test_and_set(self.spinlock):
      scheduler_yield()

    if self.is_held:
      # lock is held; deschedule
      self.queue.enqueue(scheduler_current_thread_TCB())
      self.spinlock = False
      scheduler_deschedule_current_thread()

      # NOTE: there is a race condition if you context switch between the above
      # two lines.  You really need a atomic deschedule and release operation

    else:
      # lock is free, grab it
      self.is_held  = True
      self.spinlock = False

  def release(self):
    # acquire spin lock
    while test_and_set(self.spinlock):
      scheduler_yield()

    if is_empty(self.queue):
      self.is_held = False
    else:
      # pass lock to next waiting thread
      thread = self.queue.dequeue()
      scheduler_make_ready(thread)

    self.spinlock = False

#
# pseudocode for condition variable implementation
#

class Condition:
  def __init__(self, monitor_lock):
    self.monitor_lock = monitor_lock

    # protected by monitor_lock
    self.queue = []

  def wait(self):
    # put this thread on queue and stop
    self.queue.enqueue(scheduler_current_thread_TCB())
    self.monitor_lock.release()
    scheduler_deschedule_current_thread()
    # NOTE: there is a race condition if you context switch between the above
    # two lines.  You really need a atomic deschedule and release operation

  def notifyAll(self):
    # move all threads from this queue to monitor lock's queue
    self.monitor_lock.queue.appendAll(self.queue)
    self.queue = []

