Operating Systems Lecture Notes

2014 October 9 • Concurrency Managers


Outline

Where are We?

What’s Wrong?

What’s Next?

Stones and Bowls

Modern Stones and Bowls

test-and-set

Test-and-Set Critical Sections

Binary Semaphores

Binary Semaphore Example

widget q[N]
q-size = 0
head = tail = 0
BinarySemaphore bowl(true)

p()
  loop
    w = f()
    while q-size ≡ N {}
    q[tail++] = w
    bowl.take()
      ++q-size
    bowl.put()

c()
  loop
    while q-size ≡ 0 {}
    w = q[head++]
    bowl.take()
      --q-size
    bowl.put()
    g(w)

Tucking in the Loose Bits

Hummmm...

Counting Semaphores

class CountingSemaphore

  private unsigned bowl
  private BinarySemaphore mutex(true)

  CountingSemaphore(unsigned c) 
    bowl = c

  void put()
    mutex.take()
      ++bowl
    mutex.put()

  unsigned count()
    return bowl

  void take()
    bool done = false
    while !done
      mutex.take()
        if bowl > 0
          --bowl
	  done = true
      mutex.put()

Counting Semaphore Example

widget q[N]
head = tail = 0
CountingSemaphore bowl(0)

p()
loop
  while bowl.count()N {}
  q[tail] = f()
  bowl.put();
  tail = (tail + 1) mod N

c()
loop
  bowl.take()
  w = q[head]
  head = (head + 1) mod N
  g(w)

Waiting, Not Spinning

Blocking Semaphores

class BinarySemaphore

  BinarySemaphore(boolean b) 
    bowl = b

  void take()
    while true
      if bowl
	bowl = false ; break
      else
	pre-empt caller to waiters

  void put()
    bowl = true
    if !waiters.empty()
      schedule a waiter

  private boolean bowl
  private queue waiters

Are We Done?

Improvements

For Example

Hiding Shared State

Mutually Exclusive ADTs

ADT

  Shared private state
  private BinarySemaphore mutex(true)

\(\vdots\)

  operi(...)
    mutex.put()
      cs
    mutex.take()

\(\vdots\)

Queue Example

ADT queue<T>

  T q[N]
  head = tail = 0
  q-size = 0

  void add(T e)
    q[tail] = e
    tail = tail+1 mod N
    ++q-size

  T remove()
    T e = q[head]
    head = head+1 mod N
    --q-size
    return T

Strategic Waiting

ADT queue<T>

  T q[N] ; head = tail = 0 ; q-size = 0
  BinarySemaphore non-empty(false), non-full(true)

  void add(T e)
    non-full.take()
    q[tail] = e
    tail = tail+1 mod N
    ++q-size
    non-empty.put()

  T remove()
    non-empty.take()
    T e = q[head]
    head = head+1 mod N
    --q-size
    non-full.put()
    return T

Deadlock!

Condition Variables

Monitors

Queue Monitor

monitor queue<T>

  T q[N]
  head = tail = 0
  q-size = 0
  condition qUnfull(true), qUnempty(false)

  void put(T e)
    if q-size ≡ N
      qUnfull.wait()
    q[tail] = e
    tail = tail+1 mod N
    ++q-size
    qUnempty.signal()

  T get()
    qUnempty.wait()
    T e = q[head]
    head = head+1 mod N
    --q-size
    qUnfull.signal()
    return T

Summary

References

Credits


This page last modified on 2014 October 9.

Creative
    Commons License