Process P 0

advertisement
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.
2.
Initialize: You can initialize the semaphore to any
non-negative value.
Decrement: The down operation
•
•
3.
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..
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 Semaphores
Process P0
Process P1
………………..
down(S);
//critical section
up(S);
………………..
………………..
down(S);
//critical section
up(S);
………………..
Using Semaphores
Process P0
down(S);
critical section
up(S);
Process P1
down(S);
critical section
up(S);
 Initialize the semaphore variable, S, to 1
 Why not zero?
Using Semaphores
Process P0
down(S);
critical section
up(S);
Process P1
down(S);
critical section
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 Semaphores
Process P0
down(S);
critical section
up(S);
Process P1
down(S);
critical section
up(S);
 Now what would happen if P1 executes the down
operation?


The semaphore S is currently 0
P1 blocks
Using Semaphores
Process P0
down(S);
critical section
up(S);
Process P1
down(S);
critical section
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 one
Process P0
down(S);
down(Q);
……
up(S);
up(Q);
Process P1
down(Q);
down(S);
….
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 as
up(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
TSL
enter_region:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 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
TSL
enter_region:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 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:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 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
TSL
enter_region:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave region:
move Lock, #0
RET
 Return to caller only if Register value is 0
TSL
enter_region:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 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:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 Assume two processes: P0 and P1
 LOCK is initialized to zero
Using TSL
enter_region:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 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:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller
leave_region:
move Lock, #0
RET
 P0 is done with the critical section
 LOCK becomes 0
Using TSL
Enter_region:
TSL Register, Lock
CMP Register, #0
JNE enter_region
RET //to caller

leave_region:
move Lock, #0
RET
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
this
you write a enter_region routine based on
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 lowerpriority 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
Download