mutual exclusion -- addendum
DESCRIPTION
Mutual Exclusion -- Addendum. Mutual Exclusion in Critical Sections. RoadMap. Today there are libraries that provide application programmers with semaphores Semaphores are used by programmers to provide for critical sections - PowerPoint PPT PresentationTRANSCRIPT
Mutual Exclusion -- Addendum
Mutual Exclusion in Critical Sections
RoadMap Today there are libraries that provide
application programmers with semaphores
Semaphores are used by programmers to provide for critical sections
Let’s first talk about semaphores and then the OS support for them.
What is a semaphore?A semaphore is an integer variable with the
following three operations.1. Initialize: You can initialize the semaphore to
any non-negative value.2. Decrement: The down operation
• Semaphore value > 0: Decrement by 1. • Semaphore value == 0: If value is 0, the process blocks
(gets put into queue). It is said to be sleeping on the semaphore..
3. Increment: The up operation.• Semaphore value == 0 and some processes are
sleeping on the semaphore, one is unblocked. Otherwise, value is incremented.
What is a Semaphore? Use down before entering a critical
section Use up after finishing with a critical
section i.e., Example: Assume S is initialized to 1. ……… down(S); //critical section up(S);
Using SemaphoresProcess P0
………………..down(S); //critical sectionup(S);………………..
Process P1
………………..down(S); //critical sectionup(S);………………..
Using SemaphoresProcess P0 Process P1
down(S); down(S); critical section critical sectionup(S); up(S); Initialize the semaphore variable, S, to 1
Why not zero?
Using SemaphoresProcess P0 Process P1
down(S); down(S); critical section critical sectionup(S); up(S); Now what would happen if P0 executes the
down operation? The semaphore S is currently 1. It becomes 0 and P0 enters the critical section
Using SemaphoresProcess P0 Process P1
down(S); down(S); critical section critical sectionup(S); up(S); Now what would happen if P1 executes the
down operation? The semaphore S is currently 0 P1 blocks
Using SemaphoresProcess P0 Process P1
down(S); down(S); critical section critical sectionup(S); up(S); Assume now that P0 is done with the critical section
It calls the up function P1 is unblocked If there was no process waiting to enter the
critical section the value of s would become one
Using Semaphores What happens if there are three processes:
P0,P1,P2 Assume P0 enters its critical section If P1 and P2 execute the down operation they
will block When P0 leaves the critical section then P1 is
unblocked allowing P1 to enter its critical section P2 is still blocked
What if P0 wants to enter its critical section again when P1 is in it?
Using Semaphores What if we want to allow 10 processes
to use a critical section? How would we initialize a semaphore, s?
Semaphore Binary Semaphore: Value is either 0 or 1
Often referred to as a mutex Counting Semaphore: Value ranges from
0 to N where N can be any integer number
Deadlock Deadlock – Two or more processes are
waiting indefinitely for an event that can be caused by only one of the waiting processes
Something to watch for
Deadlock Example: Let S and Q be two
semaphores initialized to oneProcess P0 Process P1
down(S); down(Q); down(Q); down(S); …… …. up(S); up(Q); up(Q); up(S);
Implementation With each semaphore there is an
associated waiting queue. Each entry in a waiting queue has two data items: value (of type integer) pointer to next record in the list
Implementation A semaphore can be defined as a C
struct along these lines:
typedef struct { int value; struct process *list; } semaphore
Implementation down() operation can be defined as
down(semaphore *S) { S->value--; if (S->value < 0) {
add this process to S->list;
block(); }
} The block() operation suspends the
process that invokes it.
Implementation up() operation can be defined asup(semaphore *S) {
S->value++; if (S->value <= 0) {
remove process P from S->list;
wakeup(P); }
} The wakeup() operation sends a signal
that represents an event that the invoking process is no longer in the critical section
Implementation BTW, the implementation just described
is how Linux implements semaphores The up and down operations represent
require access to a critical section which is the semaphore variable
Need hardware/OS support e.g., Hardware support e.g., TSL. Signals
Synchronization Hardware Any solution to the
critical section problem requires a lock
Process must acquire a lock before entering a critical section
Process must release the lock when it exists the critical section.
We will present a hardware solution
while (true) { acquire lock critical section release lock other}
Test and Lock Instruction (TSL)
Many computers have the following type of instruction: TSL REGISTER, LOCK
One use of this instruction is to provide a lock for a critical region such code that operations on a semaphore variable
Using the TSL Instruction
TSLenter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller TSL Register, Lock
Reads LOCK into register REGISTER Stores a nonzero value at the memory
location LOCK The operations of reading the word and
storing it are guaranteed to be indivisible
TSLenter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller TSL Register, Lock
The CPU executing the TSL instruction locks the memory bus to prohibit other CPUs from accessing memory until the TSL instruction is done
TSL enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller CMP Register, #0
Compare register value with 0 JNE Enter_Region
If Register value is not 0 then go to the start of enter region
TSLenter_region: leave region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller Return to caller only if Register value is 0
TSL enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller Before entering its critical region, a process calls enter_region
What if LOCK is 1? Busy wait until lock is 0
When leaving the critical section, a process calls leave_region
Using TSL enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller Assume two processes: P0 and P1
LOCK is initialized to zero
Using TSL enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller Assume that P0 wants to enter the critical section
It executes the TSL instruction. The register value is 0 which reflects the
value of LOCK LOCK is set to 1
Using TSL enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller
Now P1 wants to enter the critical section; It executes the TSL instruction The register value is 1 which reflects the
value of LOCK P1 cannot enter the critical section It repeats the TSL instruction and
comparison operation until it can get into the critical section
Using TSL enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller P0 is done with the critical section
LOCK becomes 0
Using TSL Enter_region: leave_region: TSL Register, Lock move Lock, #0 CMP Register, #0 RET JNE enter_region RET //to caller The next time P1 executes the TSL instruction and comparison operation it finds that the register value (which reflects LOCK) is zero. It can now enter the critical section.
Implementing TSL Implementing atomic TSL instructions
on multiprocessors is not trivial. This is a subject for a computer
architecture course
Signals A signal is used in UNIX systems to
notify a process that a particular event has occurred A signal is generated by the occurrence of a
particular event A generated signal is delivered to a process Once delivered, the signal must be handled
A signal process is used to associate computation with a signal
Signals Example
<control> <C> is entered This causes an event to be generated to a
running process that is in the foreground When that process receives the event it
executes a signal handler which terminates the process
Signals Two possible handlers
Default signal handler: Provided by kernel User-defined signal handler: Provided by
user and overrides the default What if a process has multiple threads?
How a signal is handled depends on the type of signal. Options• Deliver the signal to the thread to which the signal
applies• Deliver the signal to every thread in the process• Deliver the signal to certain threads in the process• Assign a specific threa to receive all signals for the
process
Semaphore Implementation When the up is executed a blocked
process is woken up. This is done using signals
Semaphore operations are critical sections – use TSL.
Questions How are multiple processes prevented
from being in the critical section ?
Why different than disabling interrupts?
Which is better in a multicore system? Disabling interrupts or TSL test?
Question Assume that instead of a TSL instruction
there is an instruction to swap the contents of a register and memory word in a single indivisible action. Can you write a enter_region routine based
on this
Mars PathFinder Priority Inversion: Scheduling problem
when lower-priority process holds a lock needed by higher-priority process
Now back to the Mars Pathfinder problem High priority task was taking longer than
expected to complete its work The task was forced to wait for a shared
resource that was being held by a lower-priority process
Lower-priority process was being pre-empted by a medium priority process
Scheduler detected problem and would reset
Mars PathFinder The fix
The OS had a global variable to enable priority inheritance on all semaphores
It was off It was set to on and then everything worked
Summary Defined race condition Examined different solutions