View
228
Download
2
Embed Size (px)
Citation preview
2
Issues about IPC
Communication between processes is indispensable. Interrupt is not preferred. Why? How about pipe?
Basic issues How to pass information How to solve the competition for resources
(mutual exclusion) How to guarantee the dependency
(synchronization)
3
Sharing Resources
Var in A
Var in B
A: reads ininA inA=7
B: reads ininB inA=7 inB=7
B: Put file in slot 7Update in8
inA=7 inB=8
A: Put file in slot 7Update in8
inA=8 inB=8
A’s file overwrites B’s!!!
Spooler director
y...
4 abc
5 prog.c
6 prog.n
7...
Process A
Process B
out = 4
in = 7
The next file to print
The next free slot
4
Race Conditions
Two or more processes are reading or writing some shared data, the final result depends on who/when runs precisely Must be avoided
Solution: mutual exclusion Critical region/section: the part of program
where the shared resource is accessed No two processes in their critical regions at
the same time
5
Conditions for Sharing Resource
No two processes simultaneously inside their critical regions (mutual exclusion)
No assumption about speeds or number of CPUs
No process running outside its critical region may block other processes
No process waits forever to enter its critical region (no deadlock)
6
Mutual Exclusion Using Critical Regions
B attempts to enter critical region
B enters critical region
B leaves critical region
B blocked
Process A
Process B
A enters critical region
A leaves critical region
Time
T1
T2
T3
T4
7
Achieve Mutual Exclusion
Busy waiting Sleep and wakeup Semaphores Mutexes Monitors Message passing Barriers
8
Busy Waiting – Disabling Interrupts
Enter critical region disable interrupts … enable interrupts leave critical region Simplest, intuitive Why disable interrupt? No process
switching in critical region Problem: lose control of user
processes Not work in the case of multiple CPUs Good for kernel.
9
Busy Waiting – Lock Variables
Disable interrupt is not good. Any software solution?
Lock variable: single, shared variable Before entering critical region, test and set Race condition on the lock variable
After one process reads the lock but before it sets to 1, switching happens.
Problem: test and set lock variable must be inseparable, i.e., atomic Ask for help from hardware
10
TSL: Help from Hardware Problem of lock variables
Test, if 0, enter, else wait What if both process test 0 and enter?
TSL instruction: TSL RX, LOCK Read, update and write-back All three operations are indivisible
Enter_region: TSL REG, LOCK CMP REG, #0 JNE Enter_region RET
Leave_region: MOV LOCK, #0 RET
While (TRUE){ while (turn!=0); /*loop*/ critical_region(); turn=1; non_critical_region();}
While (TRUE){ while (turn!=1); /*loop*/ critical_region(); turn=0; non_critical_region();}
Busy Waiting: Strict Alternation
Process 0 Process 1
A process may be blocked by another one not in its critical region! It requires strictly alternate in using critical regions.
Process 0 and 1 use critical region alternatively in a strict order!
// Initially turn=0
12
Get Rid of Strict Alternation
Peterson’s solution: combine taking turns with the idea of lock variables
Two procedures enter_region and leave_region
For each process Call enter_region before entering its critical region Call leave_region after leaving its critical region
Process 0:……Enter_region(0);critical_part;Leave_region(0);…..
Process 1:……Enter_region(1);critical_part;Leave_region(1);…..
C Code of Peterson’s Solution
int turn; // shared variable. whose turn is it?int interested[2]; //shared variable. all values initially FALSEVoid enter_region(int process) //parameter: 0 or 1{ int other; //local variable. number of the other
process other=1-process; //the opposite of process interested[process]=TRUE; //show that you are interested turn=process; //set flag while (turn==process && interested[other]==TRUE);}
Void leave_region(int process) //process: who is leaving?{ interested[process]=FALSE //departure from critical region}
21
3
……. ……..
P0:1 interested[0]=TRUE
P1:1 interested[1]=TRUE
P0:2 turn=0
P1:2 turn=1
P0:3 While( turn==0 && interested[1]==TRUE) entering!
P1:3 While( turn==1 && interested[0]==TRUE) busy waiting!
void enter_region(int 0) //process=0
{
int other; //local variable
other=1-process=1;
interested[0]=TRUE;
turn=0;
while (turn==0 && interested[1]==TRUE);
}
void enter_region(int 1) //process=1
{
int other; //local variable
other=1-process=0;
interested[1]=TRUE;
turn=1;
while (turn==1 && interested[0]==TRUE);
}
23
23
1 1
15
Problems of Busy Waiting Waste CPU time Some processes may never get chance to
run Priority inversion problem E.g., L in critical region, while H is busy waiting
Solution: block instead of waiting sleep and wakeup operations sleep(): cause the caller to block, until another
process wakes it up wakeup(pid): wake up the process specified by
pid
16
Producer-Consumer Problem
Elements: producer, consumer, buffer
Producer: put items into buffer Consumer: take items out of buffer Buffer: fixed size holder of items
producer
consumer
bufferitems items
#define N 100 // number of slots in the bufferint count = 0; // number of items in the buffer
void producer(void){ int item;
while (TRUE){ // repeat forever item = produce_item(); // generate next item if (count == N) sleep(); // if buffer is full, go to sleep insert_item(item); // put item into buffer count = count+1; // increment count of items in buffer if (count == 1) wakeup(consumer); // was buffer empty? }}
void consumer(void){ int item;
while (TRUE){ // repeat forever if (count == 0) sleep(); // if buffer is empty, go to sleep item = remove_item(); // take item out of buffer count = count-1; // decrement count of items in buffer if (count == N – 1) wakeup(producer); // was buffer full? consume_item(item); // print item }}
Switch to producer. Lost-wakeup call!
18
Problem: Lost-Wakeup
Race condition on the shared variable: count Buffer is empty and consumer reads the counter
as value 0. But before consumer can make the sleep() call, CPU switches to producer. Producer inserts an item, sets counter to 1 and sends a wakeup call to consumer. However, consumer is not sleeping yet, the wakeup signal is lost!
Now CPU switches back to consumer and it finally makes the sleep() call- consumer is asleep now.
Producer will fill up the buffer sooner or later, and it goes to sleep as well.
Both are sleeping!
19
Semaphores Two atomic operations: down and
up Suppose s is a semaphore down(&s): s--; if s < 0 then sleep up(&s): s++; if s <= 0 then wake up
one of the processes blocked by down operation on s.
up operation never blocked! What’s the value of s now? Don’t know
Can only be accessed by the two operations after initialization.
20
Atomic Operations Both down and up are as a single,
indivisible atomic actions Value < 0 indicates some process
sleeping Solve the lost-wakeup problem
(why?) How to implement these atomic
operations? Disable all interrupts Use TSL instruction
21
Use of Semaphores Mutual exclusion
Semaphore s is initialized to 1. Call down(&s) before enter critical region Call up(&s) after leave critical region Can be used for buffer in Producer-
Consumer problem Synchronization
Guarantee certain event sequences do or do not occur
E.g., the Producer stops running when the buffer is full.
Producer-Consumer using Semaphores
#define N 100 // number of slots in the buffersemaphore mutual = 1; // controls access to critical regionsemaphore empty = N; // counts empty buffer slotssemaphore full = 0; // counts full buffer slots
void producer(void){ int item; while (TRUE){ item = produce_item(); // generate something to put in buffer down(&empty); // decrement empty count down(&mutual); // enter critical region insert_item(item); // put new item in buffer up(&mutual); // leave critical region up(&full); // increment count of full slots }}
void consumer(void){ int item; while (TRUE){ down(&full); // decrement full count down(&mutual); // enter critical region item = remove_item(); // take item from buffer up(&mutual); // leave critical region up(&empty); // increment count of empty slots }}
23
Mutexes: Binary Semaphores
Achieve mutual exclusion Two states: unlocked (0) / locked (1) Two operations: mutex_lock(&m) and
mutex_unlock(&m) For a process
Call mutex_lock before entering critical region Call mutex_unlock after leaving critical region
Can be implemented in user space with TSL instruction.
Implementation of Mutex
mutex_lock: TSL REGISTER, MUTEX | copy mutex to register and set mutex to 1 CMP REGISTER, #0 | was mutex zero? JZE ok | if it was zero, mutex was unlocked, so return CALL thread_yield | mutex is busy; schedule another thread JMP mutex_lock | try again latterok: RET | return to caller; critical region entered
mutex_unlock: MOV MUTEX, #0 | store a zero in mutex RET | return to caller
Notice: thread_yield is used. Busy waiting does not work here. (Why?)