Lecture_4
Lecture_4
Prof. Khaled F.
Hussain
Reference
• Silberschatz, Abraham, Peter B. Galvin, and Greg
Gagne. Operating system concepts. John Wiley & Sons.
Process Synchronization
• A situation where several processes access and manipulate the same data concurrently
and the outcome of the execution depends on the particular order in which the access
takes place, is called a race condition.
• counter++
register1 = counter
register1 = register1 + 1
counter = register1
• counter—
register2 = counter
register2 = register2 − 1
counter = register2
Race condition
• T0: producer execute register1 = counter {register1 = 5}
• T1: producer execute register1 = register1 + 1 {register1 = 6}
• T2: consumer execute register2 = counter {register2 = 5}
• T3: consumer execute register2 = register2 − 1 {register2 = 4}
• T4: producer execute counter = register1 {counter = 6}
• T5: consumer execute counter = register2 {counter = 4}
do {
critical section
turn = j;
remainder section
} while (true);
Peterson’s Solution
Peterson’s Solution (Cont.)
• To prove that this solution is correct. We need to show that:
• Mutual exclusion is preserved.
• The progress requirement is satisfied.
• The bounded-waiting requirement is met.
Synchronizati
on Hardware
• The critical-section problem could
be solved simply in a single-
processor environment if we could
prevent interrupts from occurring
while a shared variable was being
modified.
• In this way, we could be sure that
the current sequence of instructions
would be allowed to execute in
order without preemption.
• No other instructions would be run,
so no unexpected modifications
could be made to the shared
variable.
• This is often the approach taken by
nonpreemptive kernels.
Synchronization Hardware (Cont.)
Mutex Locks
• The previous hardware-based solutions to the critical-section problem are
complicated as well as generally inaccessible to application programmers.
• Operating-systems designers build software tools to solve the critical-section problem. The
simplest of these tools is the mutex lock. (In fact, the term mutex is short for mutual
exclusion.)
• We use the mutex lock to protect critical regions and thus prevent race conditions.
• That is, a process must acquire the lock before entering a critical section; it releases the lock
when it exits the critical section.
• The acquire()function acquires the lock, and the release() function releases the lock
acquire() {
while (!available); /* busy wait */
available = false; }
signal(S) { S++;}
Semaphore Usage
• Operating systems often distinguish between counting and binary semaphores.
• The value of a counting semaphore can range over an unrestricted domain.
• The value of a binary semaphore can range only between 0 and 1. Thus, binary
semaphores behave similarly to mutex locks. In fact, on systems that do not provide
mutex locks, binary semaphores can be used instead for providing mutual exclusion.
Semaphore Implementation
• To implement semaphores, we define a semaphore as follows:
typedef struct {
int value;
struct process *list;
} semaphore;
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
}
Semaphore Implementation (Cont.)
signal(semaphore *S) { S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
Deadlocks
and
Starvation
• The implementation of a
semaphore with a waiting queue
may result in a situation where
two or more processes are
waiting indefinitely for an event
that can be caused only by one
of the waiting processes. When
such a state is reached, these
processes are said to be
deadlocked.
• To illustrate this, consider a
system consisting of two
processes, P0 and P1, each
accessing two semaphores, S and
Q, set to the value 1:
Priority Inversion
• A scheduling challenge arises when a higher-priority process needs to read or modify
kernel data that are currently being accessed by a lower-priority process—or a chain of
lower-priority processes. Since kernel data are typically protected with a lock, the
higher-priority process will have to wait for a lower-priority one to finish with the
resource.
Classic Problems of Synchronization
• The Bounded-Buffer Problem
• The Readers–Writers Problem
• The Dining-Philosophers Problem
The Bounded-Buffer Problem
int n;
semaphore mutex = 1;
semaphore empty = n;
semaphore full = 0