# Process Synchronization

(1)

(2)

## Process Synchronization

###  A Consumer-Producer Example

 Consumer:

while (1) {

while (counter == 0)

;

nextc = buffer[out];

out = (out +1) % BUFFER_SIZE;

counter--;

consume an item in nextc;

}

 Producer

while (1) {

while (counter == BUFFER_SIZE)

;

produce an item in nextp;

….

buffer[in] = nextp;

in = (in+1) % BUFFER_SIZE;

counter++;

}

## Process Synchronization

###  counter++ vs counter—

r1 = counter r2 = counter r1 = r1 + 1 r2 = r2 - 1 counter = r1 counter = r2

###  Initially, let counter = 5.

1. P: r1 = counter 2. P: r1 = r1 + 1 3. C: r2 = counter 4. C: r2 = r2 – 1 5. P: counter = r1 6. C: counter = r2

A Race Condition!

(3)

## Process Synchronization

###  Design a protocol that processes can use to cooperate.

 Each process has a segment of code, called a critical section, whose

execution must be mutually exclusive.

## Process Synchronization

###  A General Structure for the Critical- Section Problem

permission request

entry section;

critical section;

exit section;

remainder section;

} while (1);

do {

(4)

### 2. Progress

a. Only processes not in their remainder section can decide which will enter its critical section.

b. The selection cannot be postponed indefinitely.

###  Notation

 Processes Pi and Pj, where j=1-i;

###  Assumption

 Every basic machine-language instruction is atomic.

 Algorithm 1

 Idea: Remember which process is allowed to enter its critical section, That is, process i can enter its critical section if turn = i.

### The Critical-Section Problem – Peterson’s Solution

while (turn != i) ; critical section turn=j;

remainder section } while (1);

do {

(5)

### Time

suspend or quit!

turn=0 exit turn=1

exit

turn=0 blocked on P1’s entry section

### The Critical-Section Problem – Peterson’s Solution

flag[i]=true;

while (flag[j]) ; critical section flag[i]=false;

remainder section } while (1);

do {

Initially, flag[0]=flag[1]=false

* The switching of “flag[i]=true” and “while (flag[j]);”.

(6)

### The Critical-Section Problem – Peterson’s Solution

flag[i]=true;

turn=j;

while (flag[j] && turn==j) ; critical section

flag[i]=false;

remainder section } while (1);

do {

###  Mutual Exclusion

 The eventual value of turn determines which process enters the critical section.

###  Progress

 A process can only be stuck in the while loop, and the process which can keep it waiting must be in its critical sections.

###  Bounded Waiting

 Each process wait at most one entry by the other process.

(7)

### The Critical-Section Problem – A Multiple-Process Solution

• An observation: If Pi is in its critical section, and Pk (k != i) has already chosen its number[k], then (number[i],i) < (number[k],k).

choosing[i]=true;

number[i]=max(number[0], …number[n-1])+1;

choosing[i]=false;

for (j=0; j < n; j++) while choosing[j] ;

while (number[j] != 0 && (number[j],j)<(number[i],i)) ; critical section

number[i]=0;

remainder section } while (1);

do {

(8)

## Synchronization Hardware

###  Disable Interrupt Æ No Preemption

 Infeasible in multiprocessor environment where message passing is used.

 Potential impacts on interrupt-driven system clocks.

###  Atomic Hardware Instructions

 Test-and-set, Swap, etc.

boolean TestAndSet(boolean &target) { boolean rv = target;

target=true;

return rv;

}

while (TestAndSet(lock)) ; critical section

lock=false;

remainder section } while (1);

do {

## Synchronization Hardware

(9)

void Swap(boolean &a, boolean &b) { boolean temp = a;

a=b;

b=temp;

}

key=true;

while (key == true) Swap(lock, key);

critical section lock=false;

remainder section } while (1);

do {

## Synchronization Hardware

waiting[i]=true;

key=true;

while (waiting[i] && key) key=TestAndSet(lock);

waiting[i]=false;

critical section;

j= (i+1) % n;

while(j != i) && (not waiting[j]) j= (j+1) % n;

If (j=i) lock=false;

else waiting[j]=false;

remainder section } while (1);

do {

## Synchronization Hardware

 Mutual Exclusion

 Pass if key == F or waiting[i] == F

 Progress

 Exit process

sends a process in.

Bounded Waiting

 Wait at most n-1 times

Atomic TestAndSet is hard to implement in a multiprocessor

environment.

(10)

## Semaphores

###  A variable S only accessible by two atomic operations:

signal(S) { /* V */

S++;

} wait(S) { /* P */

while (S <= 0) ; S—;

}

•Indivisibility for “(S<=0)”, “S—”, and “S++”

## Semaphores – Usages

###  Critical Sections

do {

wait(mutex);

critical section signal(mutex);

remainder section } while (1);

P1:

S1;

signal(synch);

P2:

wait(synch);

S2;

(11)

## Semaphores

###  Spinlock – A Busy-Waiting Semaphore

 “while (S <= 0)” causes the wasting of CPU cycles!

 When locks are held for a short time, spinlocks are useful since no context switching is involved.

###  Semaphores with Block-Waiting

 No busy waiting from the entry to the critical section!

## Semaphores

###  Semaphores with Block Waiting

typedef struct { int value;

struct process *L;

} semaphore ;

void signal(semaphore S);

S.value++;

if (S.value <= 0) {

remove a process P form S.L;

wakeup(P);

} }

void wait(semaphore S) { S.value--;

if (S.value < 0) {

block();

} }

* |S.value| = the # of waiting processes if S.value < 0.

(12)

## Semaphores

###  Mutual exclusion in wait() & signal()

 Uniprocessor Environments

 Interrupt Disabling

 TestAndSet, Swap

 Software Methods, e.g., the Bakery Algorithm, in Section 7.2

 Multiprocessor Environments

###  Remarks: Busy-waiting is limited to only the critical sections of the wait() & signal()!

 A set of processes is in a deadlock state when every process in the set is waiting for an event that can be caused only by another process in the set.

###  Starvation (or Indefinite Blocking)

 E.g., a LIFO queue

P0: wait(S); P1: wait(Q);

wait(Q); wait(S);

… …

signal(S); signal(Q);

signal(Q); signal(S);

(13)

## Binary Semaphore

###  The value ranges from 0 to 1Æ easy implementation!

wait(S)

wait(S1); /* protect C */

C--;

if (C < 0) { signal(S1);

wait(S2);

}

signal(S1);

signal(S)

wait(S1);

C++;

if (C <= 0)

signal (S2); /* wakeup */

else

signal (S1);

* S1 & S2: binary semaphores

## Problems – The Bounded Buffer

### Producer:

do {

produce an item in nextp;

…….

wait(empty); /* control buffer availability */

wait(mutex); /* mutual exclusion */

……

signal(mutex);

signal(full); /* increase item counts */

} while (1);

Initialized to n Initialized to 1

Initialized to 0

(14)

## Problems – The Bounded Buffer

### Consumer:

do {

wait(full); /* control buffer availability */

wait(mutex); /* mutual exclusion */

…….

remove an item from buffer to nextp;

……

signal(mutex);

signal(empty); /* increase item counts */

consume nextp;

} while (1);

Initialized to n Initialized to 1 Initialized to 0

(15)

## Problems – Readers and Writers

semaphore wrt, mutex;

(initialized to 1);

Writer:

wait(wrt);

……

writing is performed

……

signal(wrt)

wait(mutex);

signal(mutex);

wait(mutex);

signal(mutex);

First R/W Solution

Queueing mechanism

Which is awaken?

thinking hungry

(16)

## Problems – Dining-Philosophers

 At most four philosophers appear.

 Pick up two chopsticks “simultaneously”.

 Order their behaviors, e.g., odds pick up their right one first, and evens pick up their left one first.

###  Solutions to Starvation:

 No philosopher will starve to death.

(17)

## Critical Regions

###  Various programming errors in using low-level constructs,e.g., semaphores

 Interchange the order of wait and signal operations

 Miss some waits or signals

 Replace waits with signals

 etc

## Critical Regions

###  Variable v – shared among processes and only accessible in the region

struct buffer { item pool[n];

int count, in, out;

};

 count < 0

###  S – statements

Example: Mutual Exclusion region v when (true) S1;

region v when (true) S2;

(18)

## Critical Regions – Consumer-Producer

Producer:

region buffer when (count < n) {

pool[in] = nextp;

in = (in + 1) % n;

count++;

}

Consumer:

region buffer when (count > 0) {

nextc = pool[out];

out = (out + 1) % n;

count--;

} struct buffer {

item pool[n];

int count, in, out;

};

## Critical Regions –

### Implementation by Semaphores

Region x when BB do SS;

wait(mutex);

while (!BB) { /* fail B */

first-count++;

if (second-count > 0)

/* try other processes waiting on second-delay */

signal(second-delay);

else signal(mutex);

/* block itself on first-delay */

wait(first-delay);

/* to protect the region */

semaphore mutex;

/* to (re-)test B */

semaphore first-delay;

int first-count=0;

/* to retest B */

semaphore second-delay;

int second-count=0;

(19)

## Critical Regions –

### Implementation by Semaphores

first-count--;

second-count++;

if (first-count > 0) signal(first-delay);

else signal(second-delay);

/* block itself on first-delay */

wait(second-delay);

second-count--;

} S S;

if (first-count > 0)

signal(first-delay);

else if (second-count > 0) signal(second-delay);

else signal(mutex);

## Monitor

###  Procedures

 Only access local variables or formal parameters

###  Condition variables

 x.wait() or x.signal

monitor name {

variable declaration void proc1(…) { }

void procn(…) { }

}

………

procedures initialization

code shared data

x

entry queue queue for x

(20)

## Monitor

###  P x.signal() a suspended process Q

 P either waits until Q leaves the

monitor or waits for another condition

 Q either waits until P leaves the monitor, or waits for another condition.

## Monitor – Dining-Philosophers

monitor dp {

enum {thinking, hungry, eating} state[5];

condition self[5];

void pickup(int i) { stat[i]=hungry;

test(i);

if (stat[i] != eating) self[i].wait;

}

void putdown(int i) { stat[i] = thinking;

test((i+4) % 5);

test((i + 1) % 5);

} Pi:

dp.pickup(i);

… eat …

dp.putdown(i);

(21)

## Monitor – Dining-Philosophers

void test(int i) {

if (stat[(i+4) % 5]) != eating &&

stat[i] == hungry &&

state[(i+1) % 5] != eating) { stat[i] = eating;

self[i].signal();

} }

void init() {

for (int i=0; i < 5; i++) state[i] = thinking;

But starvation could occur!

### Monitor –Implementation by Semaphores

 Semaphores

 mutex – to protect the monitor

 next – being initialized to zero, on which processes may suspend themselves

 nextcount

 For each external function F

wait(mutex);

body of F;

if (next-count > 0) signal(next);

else signal(mutex);

(22)

###  For every condition x

 A semaphore x-sem

 An integer variable x-count

 Implementation of x.wait() and x.signal :

 x.wait()

x-count++;

if (next-count > 0) signal(next);

else signal(mutex);

wait(x-sem);

x-count--;

 x.signal

if (x-count > 0) {

next-count++;

signal(x-sem);

wait(next);

next-count--;

}

* x.wait() and x.signal() are invoked within a monitor.

## Monitor

### x.wait(c);

 where the expression c is evaluated to determine its process’s resumption order.

R.acquire(t);

access the resource;

R.release;

monitor ResAllc { boolean busy;

condition x;

void acquire(int time) { if (busy)

x.wait(time);

busy=true;

}

}

(23)

## Monitor

 Remark: Whether the monitor is correctly used?

=> Requirements for correct computations

 Processes always make their calls on the monitor in correct order.

 No uncooperative process can access resource directly without using the access protocols.

 Note: Scheduling behavior should consult the built-in monitor scheduling algorithm if resource access RPC are built inside the monitor.

(24)

(25)

## Synchronization – Linux

###  Interrupt disabling and enabling in a uniprocessor platform.

 preempt_disable() and preempt_enable()

 Preempt_count

(26)

## Atomic Transactions –System Model

### 1. Atomicity: All or Nothing

 An aborted transaction must be rolled back.

 The effect of a committed transaction must persist and be imposed as a logical unit of operations.

(27)

## Atomic Transactions –System Model

### 2. Serializability:

 The order of transaction executions must be equivalent to a serial

schedule.

T0 T1 R(A)

W(A)

R(A) W(A) R(B)

W(B)

R(B) W(B)

Two operations Oi & Oj conflict if 1. Access the same object

2. One of them is write

## Atomic Transactions –System Model

###  Conflict Serializable:

 S is conflict serializable if S can be transformed into a serial schedule by swapping nonconflicting operations.

T0 T1 R(A)

W(A)

R(A) W(A) R(B)

W(B)

R(B) W(B)

T0 T1 R(A)

W(A) R(B) W(B)

R(A) W(A) R(B) W(B)

(28)

## Atomic Transactions –Concurrency Control

###  Lock modes (A general approach!)

 2. Exclusive-Mode: “Reads” & “Writes“

###  General Rule

 A transaction must receive a lock of an appropriate mode of an object before it accesses the object. The lock may not be released until the last access of the object is done.

## Atomic Transactions –Concurrency Control

Lock

Request Locked?

Request

compatible with the current lock?

Lock is

granted WAIT

Yes

Yes No

No

(29)

## Atomic Transactions –Concurrency Control

###  How to improve 2PL?

 Semantics, Order of Data, Access Pattern, etc.

Growing Phase

Shrinking Phase

serializable schedules 2PL schedules R0(A) W0(A) R1(A) R1(B) R0(B) W0(B)

## Atomic Transactions –Concurrency Control

i

### )

 Determine transactions’ order in a schedule in advance!

###  A General Approach:

 TS(Ti) – System Clock or Logical Counter

 Unique?

 Scheduling Scheme – deadlock-free &

serializable





)) ( ( )

(Q MaxT W(Q) TS Ti timestamp

W − = i

)) ( ( )

(Q MaxT R(Q) TS Ti timestamp

R− = i

(30)

## Atomic Transactions –Concurrency Control

 R(Q) requested by Ti Æ check TS(Ti) !

 W(Q) requested by Ti Æ check TS(Ti) !

 Rejected transactions are rolled back and restated with a new time stamp.

Time W-timestamp(Q)

Rejected Granted

Time R-timestamp(Q)

Rejected Granted

Time W-timestamp(Q)

Rejected Granted

### FailureRecovery – A Way to Achieve Atomicity

 Failures of Volatile and Nonvolatile Storages!

 Volatile Storage: Memory and Cache

 Nonvolatile Storage: Disks, Magnetic Tape, etc.

 Stable Storage: Storage which never fail.

###  Log-Based Recovery

 Log Records

< Ti starts >

< Ti commits >

< Ti aborts >

< Ti, Data-Item-Name, Old-Value, New-Value>

(31)

Time

restart crash

## Failure Recovery

###  Why Checkpointing?

 The needs to scan and rerun all log entries to redo committed transactions.

###  CheckPoint

 Output all log records, Output DB, and Write

<check point> to stable storage!

 Commit: A Force Write Procedure

crash Time checkpoint

Updating...

## References

Related subjects :