25
1 Outline Processes Threads Inter-process communication (IPC) Classical IPC problems Scheduling

1 Outline Processes Threads Inter-process communication (IPC) Classical IPC problems Scheduling

  • View
    228

  • Download
    2

Embed Size (px)

Citation preview

1

Outline

Processes Threads Inter-process communication (IPC) Classical IPC problems Scheduling

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?)

25

Problems with Mutual Exclusion

Diskette and CD-Rom protected by mutexes Process A: got diskette, waiting CD-

Rom Process B: got CD-Rom, waiting

diskette A deadlock! Blocked forever

Programming with semaphores or mutexes is tricky