Unit OS3: Concurrency Unit OS3: Concurrency
3.1. Concurrency, Critical Sections, Semaphores 3.1. Concurrency, Critical Sections, Semaphores
Copyright Notice Copyright Notice
© 2000-2005 David A. Solomon and Mark Russinovich
© 2000-2005 David A. Solomon and Mark Russinovich
These materials are part of the
These materials are part of the Windows Operating Windows Operating System Internals Curriculum Development Kit,
System Internals Curriculum Development Kit, developed by David A. Solomon and Mark E.
developed by David A. Solomon and Mark E.
Russinovich with Andreas Polze Russinovich with Andreas Polze
Microsoft has licensed these materials from David Microsoft has licensed these materials from David Solomon Expert Seminars, Inc. for distribution to Solomon Expert Seminars, Inc. for distribution to academic organizations solely for use in academic academic organizations solely for use in academic environments (and not for commercial use)
environments (and not for commercial use)
Roadmap for Section 3.1.
Roadmap for Section 3.1.
The Critical-Section Problem The Critical-Section Problem
Software Solutions Software Solutions
Synchronization Hardware Synchronization Hardware
Semaphores Semaphores
Synchronization in Windows & Linux
Synchronization in Windows & Linux
The Critical-Section Problem The Critical-Section Problem
nn threads all competing to use a shared threads all competing to use a shared resource (i.e.; shared data)
resource (i.e.; shared data)
Each thread has a code segment, called
Each thread has a code segment, called critical critical section
section, in which the shared data is accessed, in which the shared data is accessed Problem:
Problem:
Ensure that when one thread is executing in its Ensure that when one thread is executing in its critical section, no other thread is allowed to critical section, no other thread is allowed to execute in its critical section
execute in its critical section
Solution to Critical-Section Problem Solution to Critical-Section Problem
1.1. Mutual Exclusion Mutual Exclusion
Only one thread at a time is allowed into its critical section, among all Only one thread at a time is allowed into its critical section, among all threads that have critical sections for the same resource or shared threads that have critical sections for the same resource or shared data.
data.
A thread halted in its non-critical section must not interfere with other A thread halted in its non-critical section must not interfere with other threads.
threads.
2.2. Progress Progress
A thread remains inside its critical section for a finite time only.
A thread remains inside its critical section for a finite time only.
No assumptions concerning relative speed of the threads.
No assumptions concerning relative speed of the threads.
3.3. Bounded WaitingBounded Waiting
It must no be possible for a thread requiring access to a critical section It must no be possible for a thread requiring access to a critical section to be delayed indefinitely.
to be delayed indefinitely.
When no thread is in a critical section, any thread that requests entry When no thread is in a critical section, any thread that requests entry must be permitted to enter without delay.
must be permitted to enter without delay.
Initial Attempts to Solve Problem Initial Attempts to Solve Problem
Only 2 threads,
Only 2 threads, TT00 and T and T11 General structure of thread
General structure of thread TTii (other thread (other thread TTjj)) do {do {
enter section enter section
critical section critical section
exit section exit section
reminder section reminder section
} while (1);
} while (1);
Threads may share some common variables to Threads may share some common variables to
synchronize their actions.
synchronize their actions.
First Attempt: Algorithm 1 First Attempt: Algorithm 1
Shared variables - initialization Shared variables - initialization
int turn = 0;
int turn = 0;
turn == i
turn == i TTii can enter its critical section can enter its critical section Thread
Thread TTii
do {do {
while (turn != i) ; while (turn != i) ;
critical section critical section turn = j;
turn = j;
reminder section reminder section } while (1);
} while (1);
Satisfies mutual exclusion, but not progress Satisfies mutual exclusion, but not progress
Second Attempt: Algorithm 2 Second Attempt: Algorithm 2
Shared variables - initialization Shared variables - initialization
int flag[2]; flag[0] = flag[1] = 0;
int flag[2]; flag[0] = flag[1] = 0;
flag[i] == 1
flag[i] == 1 T Tii can enter its critical section can enter its critical section Thread T
Thread Tii
do {do {
flag[i] = 1;
flag[i] = 1;
while (flag[j] == 1) ;
while (flag[j] == 1) ; critical sectioncritical section flag[i] = 0;
flag[i] = 0;
remainder section remainder section
} while(1);
} while(1);
Satisfies mutual exclusion, but not progress requirement.
Satisfies mutual exclusion, but not progress requirement.
Third Attempt: Algorithm 3 Third Attempt: Algorithm 3
(Peterson’s Algorithm - 1981) (Peterson’s Algorithm - 1981)
Shared variables of algorithms 1 and 2 - initialization:
Shared variables of algorithms 1 and 2 - initialization:
int flag[2]; flag[0] = flag[1] = 0;
int flag[2]; flag[0] = flag[1] = 0;
int turn = 0;
int turn = 0;
Thread T Thread Tii
do {do {
flag[i] = 1;
flag[i] = 1;
turn = j;
turn = j;
while ((flag[j] == 1) && turn == j) ; while ((flag[j] == 1) && turn == j) ;
critical section critical section flag[i] = 0;
flag[i] = 0;
remainder section remainder section } while (1);
} while (1);
Solves the critical-section problem for two threads.
Solves the critical-section problem for two threads.
Dekker’s Algorithm (1965) Dekker’s Algorithm (1965)
This is the first correct solution proposed for the This is the first correct solution proposed for the
two-thread (two-process) case.
two-thread (two-process) case.
Originally developed by Dekker in a different Originally developed by Dekker in a different
context, it was applied to the critical section context, it was applied to the critical section
problem by Dijkstra.
problem by Dijkstra.
Dekker adds the idea of a favored thread and allows Dekker adds the idea of a favored thread and allows
access to either thread when the request is access to either thread when the request is
uncontested.
uncontested.
When there is a conflict, one thread is favored, and When there is a conflict, one thread is favored, and
the priority reverses after successful execution of the priority reverses after successful execution of
the critical section.
the critical section.
Dekker’s Algorithm (contd.) Dekker’s Algorithm (contd.)
Shared variables - initialization:
Shared variables - initialization:
int flag[2]; flag[0] = flag[1] = 0;
int flag[2]; flag[0] = flag[1] = 0;
int turn = 0;
int turn = 0;
Thread T Thread Tii
do {do {
flag[i] = 1;
flag[i] = 1;
while (flag[j] ) while (flag[j] ) if (turn == j) { if (turn == j) { flag[i] = 0;
flag[i] = 0;
while (turn == j);
while (turn == j);
flag[i] = 1;
flag[i] = 1;
}}
critical section critical section
turn = j;
turn = j;
flag[I] = 0;;
flag[I] = 0;;
remainder section remainder section
} while (1);
} while (1);
Bakery Algorithm Bakery Algorithm
(Lamport 1979) (Lamport 1979)
A Solution to the Critical Section problem for n threads A Solution to the Critical Section problem for n threads
Before entering its critical section, a thread receives a Before entering its critical section, a thread receives a
number. Holder of the smallest number enters the critical number. Holder of the smallest number enters the critical section.
section.
If threads T
If threads Tii and T and Tjj receive the same number, receive the same number, if i < j, then T
if i < j, then Tii is served first; else T is served first; else Tjj is served first. is served first.
The numbering scheme generates numbers in The numbering scheme generates numbers in monotonically non-decreasing order;
monotonically non-decreasing order;
i.e., 1,1,1,2,3,3,3,4,4,5...
i.e., 1,1,1,2,3,3,3,4,4,5...
Bakery Algorithm Bakery Algorithm
Notation “<“ establishes lexicographical order Notation “<“ establishes lexicographical order
among 2-tuples (ticket #, thread id #) among 2-tuples (ticket #, thread id #)
((a,ba,b) < (c,d) < (c,d) if ) if aa < < cc or if or if a == a == cc and and b b < < dd max (
max (aa00,…, ,…, aan-1n-1) = { k | ) = { k | kk a aii for for ii = 0,…, = 0,…, nn – 1 } – 1 }
Share S d data d data
int choosing[n];
int choosing[n];
int number[n];
int number[n]; - the ticket- the ticket
Data structures are initialized to 0 Data structures are initialized to 0
Bakery Algorithm Bakery Algorithm
do { do {
choosing[i] = 1;
choosing[i] = 1;
number[i] = max(number[0],number[1] ...,number[n-1]) + 1;
number[i] = max(number[0],number[1] ...,number[n-1]) + 1;
choosing[i] = 0;
choosing[i] = 0;
for (j = 0; j < n; j++) { for (j = 0; j < n; j++) {
while (choosing[j] == 1) ; while (choosing[j] == 1) ; while ((number[j] != 0) &&
while ((number[j] != 0) &&
((number[j],j) ‘’<‘’ (number[i],i)));
((number[j],j) ‘’<‘’ (number[i],i)));
}}
critical section critical section number[i] = 0;
number[i] = 0;
remainder section remainder section } while (1);
} while (1);
Mutual Exclusion -
Mutual Exclusion - Hardware Support Hardware Support
Interrupt Disabling Interrupt Disabling
Concurrent threads cannot overlap on a uniprocessor Concurrent threads cannot overlap on a uniprocessor
Thread will run until performing a system call or interrupt Thread will run until performing a system call or interrupt
happens happens
Special Atomic Machine Instructions Special Atomic Machine Instructions
Test and Set Instruction - read & write a memory location Test and Set Instruction - read & write a memory location
Exchange Instruction - swap register and memory location Exchange Instruction - swap register and memory location
Problems with Machine-Instruction Approach Problems with Machine-Instruction Approach
Busy waiting Busy waiting
Starvation is possible Starvation is possible Deadlock is possible Deadlock is possible
Synchronization Hardware Synchronization Hardware
Test and modify the content of a word atomically Test and modify the content of a word atomically
boolean TestAndSet(boolean &target) { boolean TestAndSet(boolean &target) {
boolean rv = target;
boolean rv = target;
target = true;
target = true;
return rv;
return rv;
}}
Mutual Exclusion with Test-and-Set Mutual Exclusion with Test-and-Set
Shared data:
Shared data:
boolean lock = false;
boolean lock = false;
Thread T Thread Tii
do {do {
while (TestAndSet(lock)) ; while (TestAndSet(lock)) ;
critical section critical section lock = false;
lock = false;
remainder section remainder section }}
Synchronization Hardware Synchronization Hardware
Atomically swap two variables.
Atomically swap two variables.
void Swap(boolean &a, boolean &b) { void Swap(boolean &a, boolean &b) {
boolean temp = a;
boolean temp = a;
a = b;
a = b;
b = temp;
b = temp;
}}
Mutual Exclusion with Swap Mutual Exclusion with Swap
Shared data (initialized to Shared data (initialized to 00):):
int lock = 0;
int lock = 0;
Thread Thread TTii
int key;
int key;
do {do {
key = 1;
key = 1;
while (key == 1) Swap(lock,key);
while (key == 1) Swap(lock,key);
critical section critical section lock = 0;
lock = 0;
remainder section remainder section }}
Semaphores Semaphores
Semaphore
Semaphore S S – integer variable – integer variable
can only be accessed via two atomic operations can only be accessed via two atomic operations
waitwait ( (SS): ):
while (
while (S <=S <= 0); 0);
SS--;--;
signal
signal ( (SS): ):
S++;S++;
Critical Section of n Threads Critical Section of n Threads
Shared data:
Shared data:
semaphore mutex; //initially mutex = 1semaphore mutex; //initially mutex = 1
Thread T Thread T
ii: :
do {do {
wait(mutex);wait(mutex);
critical sectioncritical section signal(mutex);signal(mutex);
remainder sectionremainder section } while (1);
} while (1);
Semaphore Implementation Semaphore Implementation
Semaphores may suspend/resume threads Semaphores may suspend/resume threads
Avoid busy waiting Avoid busy waiting
Define a semaphore as a record Define a semaphore as a record
typedef struct { typedef struct { int value;int value;
struct thread *L;
struct thread *L;
} semaphore;
} semaphore;
Assume two simple operations:
Assume two simple operations:
suspend()
suspend() suspends the thread that invokes it. suspends the thread that invokes it.
resume(
resume(TT)) resumes the execution of a blocked thread resumes the execution of a blocked thread TT..
Implementation Implementation
Semaphore operations now defined as Semaphore operations now defined as wait(wait(S):S):
S.value--;
S.value--;
if (S.value < 0) { if (S.value < 0) {
add this thread to S.L;
add this thread to S.L;
suspend();
suspend();
}}
signal
signal((SS): ):
S.value++;
S.value++;
if (S.value <= 0) { if (S.value <= 0) {
remove a thread T from S.L;
remove a thread T from S.L;
resume(T);
resume(T);
}}
Semaphore as a General Semaphore as a General
Synchronization Tool Synchronization Tool
Execute
Execute B B in in T T
jjonly after only after A A executed in executed in T T
iiUse semaphore
Use semaphore flag flag initialized to 0 initialized to 0 Code:
Code:
T T
iiT T
jj… … … …
A A wait wait ( ( flag flag ) ) signal
signal ( ( flag flag ) ) B B
Two Types of Semaphores Two Types of Semaphores
Counting
Counting semaphore semaphore
integer value can range over an unrestricted integer value can range over an unrestricted
domain.
domain.
Binary
Binary semaphore semaphore
integer value can range only between 0 and 1;
integer value can range only between 0 and 1;
can be simpler to implement.
can be simpler to implement.
Counting semaphore
Counting semaphore S can be implemented S can be implemented as a binary semaphore.
as a binary semaphore.
Deadlock and Starvation Deadlock and Starvation
Deadlock
Deadlock – two or more threads are waiting indefinitely for an event – two or more threads are waiting indefinitely for an event that can be caused by only one of the waiting threads.
that can be caused by only one of the waiting threads.
Let Let SS and and QQ be two semaphores initialized to 1 be two semaphores initialized to 1 TT00 TT11
wait(wait(S);S); waitwait((QQ););
waitwait((QQ);); waitwait((SS););
…… … …
signal
signal((SS);); signal(signal(QQ););
signal
signal((QQ)) signalsignal((SS););
Starvation
Starvation – indefinite blocking. A thread may never be removed – indefinite blocking. A thread may never be removed from the semaphore queue in which it is suspended.
from the semaphore queue in which it is suspended.
Solution - all code should acquire/release semaphores in same order Solution - all code should acquire/release semaphores in same order
Windows Synchronization Windows Synchronization
Uses interrupt masks to protect access to global Uses interrupt masks to protect access to global resources on uniprocessor systems.
resources on uniprocessor systems.
Uses
Uses spinlocksspinlocks on multiprocessor systems. on multiprocessor systems.
Provides
Provides dispatcher objectsdispatcher objects which may act as mutexes which may act as mutexes and semaphores.
and semaphores.
Dispatcher objects may also provide
Dispatcher objects may also provide eventsevents. An event . An event acts much like a condition variable.
acts much like a condition variable.
Linux Synchronization Linux Synchronization
Kernel
Kernel disables interruptsdisables interrupts for synchronizing access to for synchronizing access to global data on uniprocessor systems.
global data on uniprocessor systems.
Uses
Uses spinlocksspinlocks for multiprocessor synchronization. for multiprocessor synchronization.
Uses
Uses semaphoressemaphores and and readers-writersreaders-writers locks when longer locks when longer sections of code need access to data.
sections of code need access to data.
Implements POSIX synchronization primitives to support Implements POSIX synchronization primitives to support multitasking, multithreading (including real-time threads), multitasking, multithreading (including real-time threads), and multiprocessing.
and multiprocessing.
Further Reading Further Reading
Ben-Ari, M., Principles of Concurrent Programming, Ben-Ari, M., Principles of Concurrent Programming, Prentice Hall, 1982
Prentice Hall, 1982
Lamport, L., The Mutual Exclusion Problem, Journal of Lamport, L., The Mutual Exclusion Problem, Journal of the ACM, April 1986
the ACM, April 1986
Abraham Silberschatz, Peter B. Galvin, Operating Abraham Silberschatz, Peter B. Galvin, Operating System Concepts, John Wiley & Sons, 6th Ed., 2003;
System Concepts, John Wiley & Sons, 6th Ed., 2003;
Chapter 7 - Process Synchronization Chapter 7 - Process Synchronization
Chapter 8 - Deadlocks Chapter 8 - Deadlocks