implementing lock

Post on 25-Feb-2016

70 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Implementing Lock. 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. Ways of Implementing Locks. - PowerPoint PPT Presentation

TRANSCRIPT

Implementing LockImplementing Lock

From the Previous LectureFrom the Previous Lecture The “too much milk” example shows The “too much milk” example shows

that writing concurrent programs that writing concurrent programs directly with load and store directly with load and store instructions (i.e., C assignment instructions (i.e., C assignment statements) is trickystatements) is tricky

Programmers want to use higher-Programmers want to use higher-level operations, such as lockslevel operations, such as locks

Ways of Implementing LocksWays of Implementing Locks

Locking primitivesLocking primitivesHigh-level atomic High-level atomic operationsoperations

Locks, semaphores, Locks, semaphores, monitors, send and monitors, send and receivereceive

Low-level atomic Low-level atomic operationsoperations

Load/store, interrupt Load/store, interrupt disables, disables, test_and_settest_and_set

All implementations require some All implementations require some level of hardware supportlevel of hardware support

Atomic Memory Load and StoreAtomic Memory Load and Store C assignment statementsC assignment statements Examples: “too much milk” solutionsExamples: “too much milk” solutions

Disable Interrupts (for Disable Interrupts (for Uniprocessors)Uniprocessors)

On a uniprocessor,On a uniprocessor,– An operation is atomic as long as a An operation is atomic as long as a

context switch does not occur in the context switch does not occur in the middle of an operationmiddle of an operation

Solution 1Solution 1Lock::Acquire() {Lock::Acquire() {

// disable interrupts;// disable interrupts;}}Lock::Release() {Lock::Release() {

// enable interrupts;// enable interrupts; }}

An ExampleAn Example

locklockAcquire();Acquire();if (no milk) {if (no milk) {

// get milk// get milk}}locklockRelease();Release();

Problems with Solution 1Problems with Solution 1 A user-level program may not re-A user-level program may not re-

enable interruptsenable interrupts– The kernel can no longer regain the The kernel can no longer regain the

controlcontrol No guarantees on the duration of No guarantees on the duration of

interrupts; bad for real-time systemsinterrupts; bad for real-time systems Solution 1 will not work for more Solution 1 will not work for more

complex scenarios (nested locks)complex scenarios (nested locks)

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

The lock is initially FREE.

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (while (value != FREEvalue != FREE) {) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Check the lock value whileinterrupts are disabled.

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Re-enable interrupts inside theloop, so someone may have a chance to unlock.

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Disable the interrupts againbefore checking the lock.

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

If no one is holding the lock, grab the lock.

Problems with Solution 2Problems with Solution 2 It works for a single processorIt works for a single processor It does not work on a multi-processor It does not work on a multi-processor

machinemachine– Other CPUs can still enter the critical Other CPUs can still enter the critical

sectionsection

The The test_and_settest_and_set Operation Operation test_and_settest_and_set also works on also works on

multiprocessorsmultiprocessors– Atomically reads a memory locationAtomically reads a memory location– Sets it to 1Sets it to 1– Returns the old value of memory Returns the old value of memory

locationlocation

The The test_and_settest_and_set Operation Operationvalue = 0;value = 0;

Lock::Acquire() {Lock::Acquire() {// while the previous value is BUSY, loop// while the previous value is BUSY, loopwhile (test_and_set(value) == 1);while (test_and_set(value) == 1);

}}

Lock::Release() {Lock::Release() {value = 0;value = 0;

}}

Common Problems with Mentioned Common Problems with Mentioned ApproachesApproaches

Busy-waitingBusy-waiting: consumption of CPU : consumption of CPU cycles while a thread is waiting for a cycles while a thread is waiting for a locklock– Very inefficientVery inefficient– Can be avoided with a waiting queueCan be avoided with a waiting queue

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsif (value != FREE) {if (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 1 tries to grab the lock.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

No more busy waiting…

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Grab the lock.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 1 goes on computing.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 2 tries to grab the lock.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) {(value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

The lock is busy…

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Put the thread 2 on a waiting queue.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Go to sleep. Wait for the princesscharming…Context switch within the sleep.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Say thread 1 wants to release the lock.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Hello? Is someone waiting there? <echo> Is someone waiting there?Thread 2 is waiting.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Put thread 2 on ready queue; context switch.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 2: Who kissed me? I don’t do mornings…

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 2 is done with its computation.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Suppose no one else is waiting.

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Release the lock. (Thread 1 hasfinished its work, so it’s okay.)

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Warp 9, engage (let’s get out of here)…

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Eventually, the kernel will contextswitch back to thread 1…Thread 1: What happened?

So, What’s Going On?So, What’s Going On? Interrupt disable and enable Interrupt disable and enable

operations occur across context operations occur across context switches (at the steady state)switches (at the steady state)

So, What’s Going On?So, What’s Going On?

Thread AThread A Thread BThread BAcquire() { Disable interrupts Sleep

Release() { Disable interrupts Put A in ready queue enable interrupt}

Context switch

Return from sleepEnable interrupts}

Context switch

Enable interrupts……

Locks Using Locks Using test_and_settest_and_set, With , With Minimal Busy-WaitingMinimal Busy-Waiting

Impossible to use Impossible to use test_and_settest_and_set to to avoid busy-waitingavoid busy-waiting

However, waiting can be minimized However, waiting can be minimized with a waiting queuewith a waiting queue

Locks Using Locks Using test_and_settest_and_set, With , With Minimal Busy-WaitingMinimal Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {while (test_and_set(guard));while (test_and_set(guard));if (value != FREE) {if (value != FREE) {

// queue the thread// queue the thread// guard = 0 and // guard = 0 and

sleepsleep} else {} else {

value = BUSY;value = BUSY;}}guard = 0;guard = 0;

}}

Lock::Release() {Lock::Release() {while (test_and_set(guard));while (test_and_set(guard));if (anyone waiting) {if (anyone waiting) {

// wake up one thread// wake up one thread// put it on ready // put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}guard = 0;guard = 0;

}}

top related