Implementing Mutual Exclusion - PowerPoint PPT Presentation

1 / 39
About This Presentation
Title:

Implementing Mutual Exclusion

Description:

Implementing Mutual Exclusion Sarah Diesburg Operating Systems COP 4610 Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock ... – PowerPoint PPT presentation

Number of Views:46
Avg rating:3.0/5.0
Slides: 40
Provided by: Sara262
Learn more at: http://ww2.cs.fsu.edu
Category:

less

Transcript and Presenter's Notes

Title: Implementing Mutual Exclusion


1
Implementing Mutual Exclusion
  • Sarah Diesburg
  • Operating Systems
  • COP 4610

2
From the Previous Lecture
  • The too much milk example shows that writing
    concurrent programs directly with load and store
    instructions (i.e., C assignment statements) is
    tricky
  • Programmers want to use higher-level operations,
    such as locks

3
Ways of Implementing Locks
  • All implementations require some level of
    hardware support

Locking primitives
High-level atomic operations Locks, semaphores, monitors, send and receive
Low-level atomic operations Load/store, interrupt disables, test_and_set
4
Atomic Memory Load and Store
  • C assignment statements
  • Examples too much milk solutions

5
Disable Interrupts (for Uniprocessors)
  • On a uniprocessor,
  • An operation is atomic as long as a context
    switch does not occur in the middle of an
    operation
  • Solution 1
  • LockAcquire()
  • // disable interrupts
  • LockRelease()
  • // enable interrupts

6
Problems with Solution 1
  • A user-level program may not re-enable interrupts
  • The kernel can no longer regain the control
  • No guarantees on the duration of interrupts bad
    for real-time systems
  • Solution 1 will not work for more complex
    scenarios (nested locks)

7
Solution 2
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • while (value ! FREE)
  • // enable interrupts
  • // disable interrupts
  • value BUSY
  • // enable interrupts
  • LockRelease()
  • // disable interrupts
  • value FREE
  • // enable interrupts

8
Solution 2
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • while (value ! FREE)
  • // enable interrupts
  • // disable interrupts
  • value BUSY
  • // enable interrupts
  • LockRelease()
  • // disable interrupts
  • value FREE
  • // enable interrupts

9
Solution 2
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • while (value ! FREE)
  • // enable interrupts
  • // disable interrupts
  • value BUSY
  • // enable interrupts
  • LockRelease()
  • // disable interrupts
  • value FREE
  • // enable interrupts

10
Solution 2
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • while (value ! FREE)
  • // enable interrupts
  • // disable interrupts
  • value BUSY
  • // enable interrupts
  • LockRelease()
  • // disable interrupts
  • value FREE
  • // enable interrupts

11
Solution 2
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • while (value ! FREE)
  • // enable interrupts
  • // disable interrupts
  • value BUSY
  • // enable interrupts
  • LockRelease()
  • // disable interrupts
  • value FREE
  • // enable interrupts

12
Solution 2
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • while (value ! FREE)
  • // enable interrupts
  • // disable interrupts
  • value BUSY
  • // enable interrupts
  • LockRelease()
  • // disable interrupts
  • value FREE
  • // enable interrupts

13
Problems with Solution 2
  • It works for a single processor
  • It does not work on a multi-processor machine
  • Other CPUs can still enter the critical section

14
The test_and_set Operation
  • test_and_set works on multiprocessors
  • Atomically reads a memory location
  • Sets it to 1
  • Returns the old value of memory location

15
The test_and_set Operation
  • value 0
  • LockAcquire()
  • // while the previous value is BUSY, loop
  • while (test_and_set(value) 1)
  • LockRelease()
  • value 0

16
Common Problems with Mentioned Approaches
  • Busy-waiting consumption of CPU cycles while a
    thread is waiting for a lock
  • Very inefficient
  • Can be avoided with a waiting queue

May as well sleep instead of busy-wait
17
A tail of two threads
  • Suppose both threads want the lock, but like to
    be lazy

Thread 1 Lazy
Thread 2 Lazier
18
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
19
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
20
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
21
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
22
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
23
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
24
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
25
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
26
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
zzzz
27
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
28
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
29
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
30
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
31
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
32
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
33
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
34
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
35
Locks Using Interrupt Disables, Without
Busy-Waiting
  • class Lock
  • int value FREE
  • LockAcquire()
  • // disable interrupts
  • if (value ! FREE)
  • // Queue the thread
  • // Go to sleep
  • else
  • value BUSY
  • // enable interrupts

LockRelease() // disable interrupts if
(someone is waiting) // wake a thread //
Put it on ready queue else value
FREE // enable interrupts
What happened?
36
So, Whats Going On?
  • Interrupt disable and enable operations occur
    across context switches (at the steady state)

37
So, Whats Going On?
  • Thread A
  • Thread B

Disable interrupts Sleep
Disable interrupts Sleep
38
Locks Using test_and_set, With Minimal
Busy-Waiting
  • Impossible to use test_and_set to avoid
    busy-waiting
  • However, waiting can be minimized with a waiting
    queue

39
Locks Using test_and_set, With Minimal
Busy-Waiting
  • class Lock
  • int value FREE
  • int guard 0
  • LockAcquire()
  • while (test_and_set(guard))
  • if (value ! FREE)
  • // queue the thread
  • // guard 0 and sleep
  • else
  • value BUSY
  • guard 0

LockRelease() while (test_and_set(guard)) i
f (anyone waiting) // wake up one thread //
put it on ready queue else value
FREE guard 0
Write a Comment
User Comments (0)
About PowerShow.com