Presentation is loading. Please wait.

Presentation is loading. Please wait.

Oregon Health and Science University

Similar presentations


Presentation on theme: "Oregon Health and Science University"— Presentation transcript:

1 Oregon Health and Science University
CSE 513 Introduction to Operating Systems Class 3 - Interprocesses Communication & Synchronization Jonathan Walpole Dept. of Comp. Sci. and Eng. Oregon Health and Science University

2 Race conditions What is a race condition?
two or more processes have an inconsistent view of a shared memory region (I.e., a variable) Why do race conditions occur? values of memory locations replicated in registers during execution context switches at arbitrary times during execution processes can see “stale” memory values in registers What solutions can we apply? prevent context switches by preventing interrupts? make processes coordinate with each other to ensure mutual exclusion in accessing “critical sections” of code

3 Counter increment race condition
Incrementing a counter (load, increment, store) Context switch can occur after load and before increment!

4 Mutual exclusion conditions
No two processes simultaneously in critical region No assumptions made about speeds or numbers of CPUs No process running outside its critical region may block another process No process must wait forever to enter its critical region

5 Critical regions with mutual exclusion
Mutual exclusion using critical regions

6 How can we implement mutual exclusion?
What about using a binary “lock” variable in memory and having processes check it and set it before entry to critical regions? Many computers have some limited hardware support for setting locks “Atomic” Test and Set Lock instruction “Atomic” compare and swap operation Solves the problem of Expressing intention to enter C.S. Actually setting a lock to prevent concurrent access

7 Test and Set Lock Test-and-set does two things atomically:
Test a lock (whose value is returned) Set the lock Lock obtained when the return value is FALSE If TRUE, someone already had the lock (and still has it) 1. extract value lock = {TRUE , FALSE} Test_var 2. Set TRUE

8 Test and Set Lock FALSE Lock

9 Test and Set Lock P1 FALSE Lock

10 Test and Set Lock FALSE = Lock Available!! P1 FALSE Lock

11 Test and Set Lock P1 FALSE TRUE Lock

12 Test and Set Lock P1 FALSE TRUE Lock

13 Test and Set Lock P1 P2 P3 TRUE TRUE TRUE TRUE TRUE P4 TRUE TRUE Lock

14 Test and Set Lock P1 P2 P3 TRUE TRUE TRUE TRUE TRUE P4 TRUE TRUE Lock

15 Test and Set Lock P1 P2 P3 TRUE TRUE TRUE TRUE TRUE P4 TRUE TRUE Lock

16 Test and Set Lock P1 P2 P3 TRUE TRUE TRUE TRUE TRUE P4 FALSE TRUE Lock

17 Test and Set Lock P1 P2 P3 FALSE TRUE P4 FALSE Lock

18 Test and Set Lock P1 P2 P3 FALSE TRUE P4 FALSE Lock

19 Test and Set Lock P1 P2 P3 TRUE TRUE TRUE P4 TRUE TRUE Lock

20 Critical section entry code with TSL
J 1 repeat 2 while(TSL(lock)) 3 no-op; 4 critical section 5 Lock = FALSE; 6 remainder section 7 until FALSE 1 repeat while(TSL(lock)) 3 no-op; 4 critical section 5 Lock = FALSE; 6 remainder section 7 until FALSE Guaranteed that only one process returns with FALSE when a lock is returned to the system and others are waiting to act on the lock

21 Generalized primitives for critical sections
Thus far, the solutions have used busy waiting a process consumes CPU resources to evaluate when a lock becomes free on a single CPU system busy waiting prevents the lock holder from running, completing the critical section and releasing the lock! it would be better to block instead of busy wait (on a single CPU system) Blocking synchronization primitives sleep – allows a process to sleep on a condition wakeup – allows a process to signal another process that a condition it was waiting on is true but how can these be implemented?

22 Blocking synchronization primitives
Sleep and wakeup are system calls OS can implement them by managing a data structure that records who is blocked and on what condition but how can the OS access these data structures atomically? Concurrency in the OS: context switches and interrupts the OS can arrange not to perform a context switch while manipulating its data structures for sleep and wakeup but what about interrupts? what if interrupt handlers manipulate the sleep and wakeup data structures? What if they need synchronization? how can the OS synchronize access to its own critical sections?

23 Disabling interrupts Disabling interrupts in the OS vs disabling interrupts in user processes why not allow user processes to disable interrupts? is it ok to disable interrupts in the OS? what precautions should you take?

24 Generic synchronization problems

25 Producer/Consumer with busy waiting
process producer{ while(1){ //produce char c while (count==n) no_op; buf[InP] = c; InP = InP + 1 mod n count++; } process consumer{ while(1){ while (count==0) no_op; c = buf[OutP]; OutP = OutP + 1 mod n count--; //consume char } n-1 Global variables: char buf[n] int InP, OutP; // [0-n-1] int count 2 3

26 Problems with busy waiting solution
Producer and consumer can’t run at the same time Count variable can be corrupted if context switch occurs at the wrong time Bugs difficult to track down

27 Producer/Consumer with blocking
process producer{ while(1){ //produce char c if (count==n) sleep(full); buf[InP] = c; InP = InP + 1 mod n count++; if (count == 1) wakeup(empty); } process consumer{ while(1){ while (count==0) sleep(empty); c = buf[OutP]; OutP = OutP + 1 mod n count--; if (count == n-1) wakeup(full); //consume char } n-1 1 Global variables: char buf[n] int InP, OutP; // [0-n-1] int count 2 3

28 Problems with the blocking solution
Count variable can be corrupted Increments or decrements may be lost Both processes may sleep forever Buffer contents may be over-written Code that manipulates count must be made a critical section and protected using mutual exclusion Sleep and wakeup must be implemented as system calls OS must use synchronization mechanisms (TSL or interrupt disabling) in its implementation of sleep and wake-up … I.e., the critical sections of OS code that manipulate sleep/wakeup data structures must be protected using mutual exclusion

29 Semaphores An abstract data type that can be used for condition synchronization and mutual exclusion Integer variable with two operations: down (sema_var) decrement sema_var by 1, if possible if not possible, “wait” until possible up(sema_var) increment sema_var by 1 Both up() and down() are assumed to be atomic made to be atomic by OS implementation

30 Semaphores There are multiple names for semaphores
Down(S), wait(S), P(S) Up(S), signal(S), V(S) Semaphore implementations Binary semaphores (mutex) support mutual exclusion (lock either set or free) Counting semaphores support multiple values for more sophisticated coordination and controlled concurrent access among processes

31 Using Semaphores for Mutex
semaphore mutex = 1 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE

32 Using Semaphores for Mutex
semaphore mutex = 0 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE

33 Using Semaphores for Mutex
semaphore mutex = 0 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE

34 Using Semaphores for Mutex
semaphore mutex = 1 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE

35 Using Semaphores for Mutex
semaphore mutex = 1 Check again to see if it can be decremented 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE 1 repeat 2 down(mutex); 3 critical section 4 up(mutex); 5 remainder section 6 until FALSE

36 In class exercise… Implement producer consumer solution:

37 Counting semaphores in producer/consumer
Global variables semaphore full_buffs = 0; semaphore empty_buffs = n; char buff[n]; int InP, OutP; process producer{ while(1){ //produce char c down(empty_buffs); buf[InP] = c; InP = InP + 1 mod n up(full_buffs); } process consumer{ while(1){ down(full_buffs); c = buf[OutP]; OutP = OutP + 1 mod n up(empty_buffs); //consume char }

38 Implementing semaphores
Generally, the hardware has some simple mechanism to support semaphores Control over interrupts (almost all) Special atomic instructions in ISA test and set lock compare and swap Spin-Locks vs. Blocking Spin-locks (busy waiting) may waste a lot of cycles on uni-processors Blocking may waste a lot of cycles on multi-processors

39 Implementing semphores
Blocking struct semaphore{ int val; list L; } Down(semaphore sem) DISABLE_INTS sem.val--; if (sem.val < 0){ add proc to sem.L block(proc); } ENABLE_INTS Up(semaphore sem) DISABLE_INTS sem.val++; if (sem.val <= 0) { proc = remove next proc from sem.L wakeup(proc); } ENABLE_INTS

40 Semaphores in UNIX User-accessible semaphores in UNIX are somewhat complex each up and down operation is done atomically on an “array” of semaphores. *********WORDS OF WARNING ********* Semaphores are allocated by (and in) the operating system (number based on configuration parameters). Semaphores in UNIX ARE A SHARED RESOURCE AMONG EVERYONE (most implementations are). REMOVE your semaphores after you are done with them.

41 Typical usage main(){ int sem_id; sem_id = NewSemaphore(1); Down(sem_id); [CRITICAL SECTION] Up (sem_id); FreeSemaphore(sem_id); }

42 Managing your UNIX semaphores
Listing currently allocated ipc resources ipcs Removing semaphores ipcrm -s <sem number>

43 Classical IPC problems
There are a number of “classic” IPC problems including: Producer / Consumer synchronization The dining philosophers problem The sleeping barber problem The readers and writers problem Counting semaphores out of binary semaphores

44 Dining Philosophers Problem
Five philosophers sit at a table Between each philosopher there is one chopstick Philosophers: Why do they need to synchronize? How should they do it? while(!dead){ Think(hard); Grab first chopstick; Grab second chopstick; Eat; Put first chopstick back; Put second chopstick back; }

45 Dining philospher’s solution???
Why doesn’t this work? #define N 5 Philosopher() { while(!dead){ Think(hard); take_fork(i); take_fork((i+1)% N); Eat(alot); put_fork(i); put_fork((i+1)% N); }

46 Dining philospher’s solution (part 1)

47 Dining philospher’s solution (part 2)

48 Dining Philosophers Is this correct?
What does it mean for it to be correct? Is there an easier way?

49 Sleeping Barber Problem

50 Sleeping barber Barber
if there are people waiting for a hair cut bring them to the barber chair, and give them a haircut else go to sleep Customer: if the waiting chairs are all full, then leave store. if someone is getting a haircut, then wait for the barber to free up by sitting in a chair if the barber is sleeping, then wake him up and get a haircut

51 Solution to the sleeping barber problem

52 The readers and writers problem
Readers and writers want to access a database Multiple readers can proceed concurrently Writers must synchronize with readers and other writers Maximize concurrency Prevent starvation

53 One solution to readers and writers

54 Counting semaphores A binary semaphore can only take on the values of [0, 1]. Class exercise: create a counting semaphore (generalized semaphore that we discussed previously) using just a binary semaphore!!

55 Possible solution Semaphore S1, S2, S3; // BINARY!!
int C = N; // N is # locks down_c(sem){ downB(S3); downB(S1); C = C – 1; if (C<0) { upB(S1); downB(S2); } else { upB(S3); up_c(sem){ downB(S1); C = C + 1; if (C<=0) { upB(S2); } upB(S1);

56 Monitors It is difficult to produce correct programs using semaphores
correct ordering of up and down operations is tricky! Can we get the compiler to generate the correct semaphore code for us? what are suitable higher level abstractions for synchronization?

57 Monitors Collect related shared objects together in a monitor
Characteristics Local data variables are accessible only via the monitor’s procedures Processes enter the monitor by invoking one of its procedures Only one process may execute within the monitor at a given time Condition variables (cv) Wait(cv) – block on condition Signal(cv) – wake up process waiting on cv

58 Monitor structures shared data monitor entry queue condition queues x
initialization code monitor operations y x shared data condition queues monitor entry queue

59 Monitor example for mutual exclusion
process Producer begin loop <produce char “c”> BoundedBuffer.deposit(c) end loop end Producer monitor: BoundedBuffer var buffer : ...; nextIn, nextOut :... ; entry deposit(c: char) begin ... end entry remove(var c: char) end BoundedBuffer process Consumer begin loop BoundedBuffer.remove(c) <consume char “c”> end loop end Consumer

60 Condition variables Condition variables allow processes to synchronize based on some state of the monitor variables For example: Buffer_full in the producer/consumer Operations wait(cv) and signal(cv) allow synchronization within a monitor Only one processor active at one time what happens on a signal from A to B? A waits for B to leave monitor, or waits for another condition B waits for A to leave monitor, or waits for another condition … and what happens on wait?

61 Monitor example monitor : BoundedBuffer
var buffer : array[0..n-1] of char nextIn,nextOut : 0..n-1 := 0 fullCount : 0..n := 0 notEmpty, notFull : condition entry deposit(c:char) entry remove(var c: char) begin begin if (fullCount = n) then if (fullCount = n) then wait(notFull) wait(notEmpty) end if end if buffer[nextIn] := c c := buffer[nextOut] nextIn := nextIn+1 mod n nextOut := nextOut+1 mod n fullCount := fullCount fullCount := fullCount-1 signal(notEmpty) signal(notFull) end deposit end remove end BoundedBuffer

62 Condition synchronization semantics
Signaling and signaled processes can not both run What if signaling process continues to run and signals other condition variable? What if signaled process continues to run and signals other condition variables? What order should processes run? How do you avoid deadlock?

63 Condition synchronization semantics
Hoare Semantics On signal, allow signalled process to run; upon its exit from the monitor, signaller process continues Stonger guarantees Easier to prove correctness Mesa Semantics (Xerox PARC) Signal is merely a “hint” Requires process to check that condition is ok to continue upon receipt of signal

64 Producer consumer with message passing

65 Barriers Use of a barrier processes approaching a barrier
all processes but one blocked at barrier last process arrives, all are let through

66 Summary Process synchronization topics Reading Semaphores IPC problems
Monitors Reading

67 Solution to sleeping barber problem.
Spare slides Solution to sleeping barber problem.

68 Generalized Up in UNIX /****************************************************************/ /* Up */ /* Does a signal() on a semaphore “semaphore_id” */ /* Input: semaphore_id */ /* Returns: Increments the semaphore, and returns the value */ /* from the signal operation */ /* Example: rc = Up(my_mutex_semaphore) */ /****************************************************************/ int Up(semaphore_id) int semaphore_id; { struct sembuf sema; int rc; sema.sem_num=0; sema.sem_op = 1; sema.sem_flg=0; if ((rc=semop(semaphore_id,&sema,1))<0) perror(“V op”); return(rc); }

69 Generalized Down in UNIX
/****************************************************************/ /* Down */ /* Does a wait() on a semaphore “semaphore_id” */ /* Input: semaphore_id */ /* */ /* Returns: Decrements the semaphore, and returns the value */ /* from the down operation */ /* Example: rc = Down(my_mutex_semaphore) */ /****************************************************************/ int Down(semaphore_id) int semaphore_id; { struct sembuf sema; int rc; sema.sem_num=0; sema.sem_op = -1; sema.sem_flg=0; if ((rc=semop(semaphore_id,&sema,1))<0) perror(“down op”); return(rc); }

70 Initializing semaphores in UNIX
/*******************************************************************/ /* NewSemaphore */ /* **** YOU MUST CALL FreeSemaphore() to REMOVE SEMAPHORES!! *** */ /* Creates a new semaphore and initializes it to “initial_value” */ /* Input: initial_value of semaphore (Unsigned short) */ /* Returns: semaphore identifier */ /* Example: sem_id = NewSemaphore((ushort)1) */ /* creates a binary semaphore */ /*******************************************************************/ int NewSemaphore(initial_value) ushort initial_value; { int tmp_sem_id; if((tmp_sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600))<0) perror(“Creating sem”); if (semctl(tmp_sem_id,0,SETVAL,initial_value)<0) perror(“Sem control setting lock”); return(tmp_sem_id); }

71 Freeing semaphores in UNIX
/****************************************************************/ /* FreeSemaphore */ /* Deletes Semaphore “semaphore_id” from the system */ /* Input: semaphore_id ID of semaphore */ /****************************************************************/ int FreeSemaphore(semaphore_id) int semaphore_id; { int rc; if ((rc=semctl(semaphore_id,1,IPC_RMID))<0) perror(“Removing Semaphore”); return(rc); }

72 Mutual Exclusion with Busy Waiting (1)
Proposed solution to critical region problem (a) Process (b) Process 1.

73 Mutual Exclusion with Busy Waiting (2)
Peterson's solution for achieving mutual exclusion

74 Mutual Exclusion with Busy Waiting (3)
Entering and leaving a critical region using the TSL instruction

75 Producer-consumer problem with fatal race condition
Sleep and Wakeup Producer-consumer problem with fatal race condition

76 The producer-consumer problem using semaphores

77 Implementation of mutex_lock and mutex_unlock
Mutexes Implementation of mutex_lock and mutex_unlock

78 Monitors (1) Example of a monitor

79 Monitors (2) Outline of producer-consumer problem with monitors
only one monitor procedure active at one time buffer has N slots

80 Solution to producer-consumer problem in Java (part 1)
Monitors (3) Solution to producer-consumer problem in Java (part 1)

81 Solution to producer-consumer problem in Java (part 2)
Monitors (4) Solution to producer-consumer problem in Java (part 2)

82 Semantics of monitors What is the strongest statement we can make about the state of the monitor after a waiter wakes up? entry deposit(c:char) entry remove(var c: char) begin begin if (fullCount = n) then : : wait(notFull) c := buffer[nextOut] fullCount := fullCount-1 end if signal(notFull) end deposit end remove

83 Synchronization problems with Mesa
P P P3 /* fullCount=n */ if (fullCount==n) wait(notFull); remove() ... fullCount--; signal(notFull); /* exit monitor */ /* fullCount=n-1*/ deposit() fullCount++;

84 Mesa semantics monitor : BoundedBuffer
var buffer : array[0..n-1] of char nextIn,nextOut : 0..n-1 := 0 fullCount : 0..n := 0 notEmpty, notFull : condition entry deposit(c:char) entry remove(var c: char) begin begin while (fullCount = n) then while (fullCount = n) then wait(notFull) wait(notEmpty) end while end while buffer[nextIn] := c c := buffer[nextOut] nextIn := nextIn+1 mod n nextOut := nextOut+1 mod n fullCount := fullCount fullCount := fullCount-1 signal(notEmpty) signal(notFull) end deposit end remove end BoundedBuffer

85 System calls Three main parts
Providing hooks to “register” the system call Adding the actual system call code Compiling the kernel Making it available to programs

86 System calls: header files
/usr/src/linux/include/new_sys_call.h /usr/src/linux/include/asm-i386/unistd.h /usr/src/linux/include/arch/i386/kernel/entry.S #include <linux/linkage.h> #include <linux/unistd.h> _syscall0(int, new_sys_call); ... #define __NR_sys_new_sys_call ... .long SYMBOL_NAME(sys_new_sys_call)

87 System calls: adding code
/usr/src/linux/kernel/new_sys_call.c Modify Makefile to update with new files (if any). Compile and install the kernel #include <linux/new_sys_call.h> asmlinkage int sys_new_sys_call(void){ return(222); }

88 System calls: creating a program
The most important thing is to have the header file around (as well as the new kernel). #include <linux/new_sys_call.h> int main(){ printf(“return val %d\n”,new_sys_call()); }


Download ppt "Oregon Health and Science University"

Similar presentations


Ads by Google