Presentation is loading. Please wait.

Presentation is loading. Please wait.

Silberschatz, Galvin and Gagne ©2009 Edited by Khoury, 2015 Operating System Concepts – 9 th Edition, Chapter 5: Process Synchronization.

Similar presentations


Presentation on theme: "Silberschatz, Galvin and Gagne ©2009 Edited by Khoury, 2015 Operating System Concepts – 9 th Edition, Chapter 5: Process Synchronization."— Presentation transcript:

1 Silberschatz, Galvin and Gagne ©2009 Edited by Khoury, 2015 Operating System Concepts – 9 th Edition, Chapter 5: Process Synchronization

2 5.2 Module 5: Process Synchronization Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores Classic Problems of Synchronization Synchronization Examples

3 5.3 Objectives To introduce the critical-section problem, whose solutions can be used to ensure the consistency of shared data To present both software and hardware solutions of the critical-section problem

4 5.4 Background Multitasking: multiple cooperating processes running concurrently Need to access shared data can lead to data inconsistency OS needs to maintain data consistency Requires mechanisms to ensure the orderly execution of cooperating processes We saw one in Chapter 3: the producer-consumer bounded buffer We’ll modify it to keep track of the count of items produced #define BUFFER_SIZE 10 typedef struct {... } item; item buffer[BUFFER_SIZE]; int in = 0; int out = 0; int counter = 0;

5 5.5 Background while (true) { while (counter == BUFFER SIZE) ; // do nothing -- no free buffers // Produce an item buffer[in] = item; in = (in + 1) % BUFFER SIZE; counter++; } while (true) { while (counter == 0) ; // do nothing -- nothing to consume // remove an item from the buffer item = buffer[out]; out = (out + 1) % BUFFER SIZE; counter--; return item; }

6 5.6 Background Producer’s counter++ could be implemented as MOV AX, [counter] INC AX MOV [counter], AX Consumer’s counter-- could be implemented as MOV AX, [counter] DEC AX MOV [counter], AX Concurrent execution, process preempted after 2 CPU commands, counter = 5 MOV AX, [counter] counter = 5 INC AX MOV AX, [counter] counter = 5 DEC AX MOV [counter], AX counter = 6 MOV [counter], AX counter = 4

7 5.7 Background Race condition: when several processes manipulate the same data, and the outcome depends on the particular (and often unpredictable) execution order Unavoidable consequence of multitasking and multithreading with shared data and resources Made worse by multicore systems, where several threads of a process are literally running at the same time using the same global data Solution: process synchronization, finding ways to coordinate multiple cooperating processes so that they do not interfere with each other

8 5.8 Critical Section A process’ critical section is the segment of code in which it modifies common variables Solving the race condition requires insuring that no two process can execute their critical section at once Designing a protocol to do this is the critical section problem Basic idea: Before running the critical section, request permission and wait for it in an entry section After finished running the critical section, release permission in an exit section Rest of the program after the exit section is the remainder section do{ entry section critical section exit section remainder section } while (true)

9 5.9 Critical Section Mutual Exclusion If a process is executing in its critical section, then no other processes can be executing in their critical sections Progress If no process is executing in its critical section and there exist some processes that wish to enter their critical section The selection of the next process to enter its critical section cannot be postponed indefinitely Bounded Waiting When a process requests to enter its critical section There is a bound on the number of times other processes are allowed to enter before it, before its request is granted

10 5.10 Peterson’s Solution Software solution Two processes, P 0 and P 1 If one is P i, the other is P j The two processes share two variables: l int turn;  Indicates whose turn it is to enter the critical section. l bool flag[2];  Indicates if a process is ready to enter the critical section  flag[i] = true means that process P i is ready do { flag[i] = TRUE; turn = j; while (flag[j] && turn == j) ; //critical section flag[i] = FALSE; //remainder section } while (TRUE);

11 5.11 Peterson’s Solution Mutual Exclusion The while condition guarantees that a process can only enter its critical section if the other’s flag is false or it is its turn If both processes are in their critical section, then both got out of the while and both flags are true, which means turn is both 0 and 1 at once Progress Bounded Waiting P i can only be prevented from entering its critical section by the while condition If P j is no ready to run its critical section, its flag is false and P i can enter If P j is already running its critical section, P i enters the while loop, until P j is done and sets its flag to false If P i and P j are simultaneously ready, P j might run first but P i will run as soon as P j is done (waiting bounded at 1)

12 5.12 Synchronization Hardware Many systems provide hardware support for critical section code Allow us to create hardware locks to protect critical sections Single processor – could disable interrupts cli and sti instructions Currently running code would execute without preemption Generally too inefficient on multiprocessor systems  Delays passing message around  Reduces scalability Modern machines provide special atomic (not interruptable) hardware instructions Test memory word and set value Swap contents of two memory words We will generalize them as two functions do { acquire lock critical section release lock remainder section } while (TRUE);

13 5.13 Synchronization Hardware Test memory word and set value Remember: this is an atomic hardware instruction Can implement lock as a shared memory word lock initialized to FALSE boolean TestAndSet (boolean *target) { boolean rv = *target; *target = TRUE; return rv: } do { while ( TestAndSet (&lock )) ; // do nothing //critical section lock = FALSE; //remainder section } while (TRUE);

14 5.14 Synchronization Hardware Swap contents of two memory words Remember: this is an atomic hardware instruction Can implement lock as shared boolean variable lock initialized to FALSE and swapped with each process’ local key void Swap (boolean *a, boolean *b) { boolean temp = *a; *a = *b; *b = temp: } do { key = TRUE; while (key == TRUE) Swap (&lock, &key ); //critical section lock = FALSE; //remainder section } while (TRUE);

15 5.15 Synchronization Hardware Both these algorithm respect mutual exclusion and progress, but not bounded waiting Assuming n processes We add a shared array of waiting processes Set to true at entry Set to false before running In exit section of P i, circular scan array and set next process to false Waiting bounded at n+1 If no waiting process, release lock (progress) do { waiting[i] = TRUE; key = TRUE; while (waiting[i] && key) key = TestAndSet(&lock); waiting[i] = FALSE; //critical section j = (i + 1) % n; while ((j != i) && !waiting[j]) j = (j + 1) % n; if (j == i) lock = FALSE; else waiting[j] = FALSE; //remainder section } while (TRUE);

16 5.16 Semaphores Semaphore S is an integer variable used for synchronization Can only be accessed via two indivisible (atomic) operations wait (S) { while S <= 0 ; // no-op S--; } signal (S) { S++; }

17 5.17 Semaphores are used to limit the number of objects accessing a resource For example, a critical section Counting semaphore can take any value Set to the maximum number of available resources Binary semaphore can only be 0 or 1 Also known as mutex locks Semaphores Semaphore mutex; // initialized to 1 do { wait (mutex); // Critical Section signal (mutex); // remainder section } while (TRUE);

18 5.18 Semaphore Implementation One problem of semaphores shown here (and of the other synchronization methods) is that they use busy waiting: a process has to loop endlessly while it waits Waste of CPU Also called spinlock, because process “spins” while waiting for a lock Alternative: use two process-handling system calls block() : places the invoking process in the waiting queue wakeup(P) : moves process P from the waiting queue to the ready queue.

19 5.19 Semaphore Implementation typedef struct{ int value; struct process *list; }semaphore wait(semaphore *S) { S->value--; if (S->value < 0) { //add process to S->list; block(); } signal(semaphore *S) { S->value++; if (S->value <= 0) { //get next process from S->list; wakeup(P); }

20 5.20 Semaphore Implementation Must guarantee that no two processes can execute wait() and signal() on the same semaphore at the same time Thus, implementation becomes the critical section problem where the wait and signal code are placed in the critical section. Could use busy waiting… which is what we wanted to eliminate! Moved busy waiting from process critical section to wait() & signal() critical section  Much shorter code, less likely to be occupied  Can be done in less than a second, while a process critical section can take minutes or more – Much less wasted CPU

21 5.21 Semaphore Problems With multiple semaphores, two or more processes can become deadlocked waiting for the other to release a semaphore they need Let S and Q be two binary semaphores P 0 P 1 wait (S);wait (Q); wait (Q);wait (S); //critical section //critical section signal (S); signal (Q); signal (Q); signal (S); If the selection of the next process in the list violates bounded waiting, then a process can suffer from starvation or indefinite blocking A high-priority process needing a lock held by a low-priority process will be forced it to wait. Worse, if a runnable medium-priority process preempts the low-priority one, the high-priority one is delayed longer; priority inversion Can be solved by priority inheritance

22 5.22 Classical Problems of Synchronization Three typical synchronization problems used as benchmarks and tests Bounded-Buffer Problem Readers and Writers Problem Dining-Philosophers Problem

23 5.23 Bounded-Buffer Problem N buffers, each can hold one item, initially empty Binary semaphore mutex, for access to the buffer, initialized to 1 Counting semaphore full, number of full buffers, initialized to 0 Counting semaphore empty, number of empty buffers, initialized to N do { // produce an item wait (empty); wait (mutex); // add item to the buffer signal (mutex); signal (full); } while (TRUE); do { wait (full); wait (mutex); // remove an item from buffer signal (mutex); signal (empty); // consume the item } while (TRUE);

24 5.24 Readers-Writers Problem Data is shared among a number of concurrent processes Readers that only read the data, but never write or update it Writers that both read and write the data Problem: multiple readers should be allowed simultaneously, but each writer should have exclusive access First variation: new readers can read while writer waits (writer might starve) Second variation: FCFS, new readers wait after writer (reader might starve) Solution for second one simple with a single semaphore Solution for first one: Binary semaphore mutex initialized to 1 Binary semaphore wrt initialized to 1 Integer readcount initialized to 0

25 5.25 Readers-Writers Problem Write process can only go through with wrt semaphore Read process waits/signals wrt if it is the first/last read process on the data Integer readcount keeps track of current number of readers Updating it is part of the critical section, therefore locked by mutex semaphore do { wait (wrt); // writing signal (wrt); } while (TRUE); do { wait (mutex); readcount++; if (readcount == 1) wait (wrt); signal (mutex) // reading is performed wait (mutex); readcount--; if (readcount == 0) signal (wrt); signal (mutex); } while (TRUE);

26 5.26 Dining-Philosophers Problem Simple representation of problem of allocating limited, shared resources between multiple processes without deadlocks or starvation Problem: Bowl of rice: critical data Chopsticks: Array of binary semaphores chopstick[5] initialized to 1 Philosophers: concurrent processes

27 5.27 Dining-Philosophers Problem Simple solutions Max four philosophers Only pick up chopsticks if both are available, without giving another a chance to pick them up (i.e. in a critical section) Asymmetry: odd-numbered philosophers pick up left chopstick first, even-numbered philosophers pick up right chopstick first do { wait( chopstick[i] ); wait( chopstick[(i+1)%5]); // eat signal( chopstick[i] ); signal(chopstick[(i+1)%5]); // think } while (TRUE);

28 5.28 Problems with Semaphores Incorrect use of semaphore operations: l signal(mutex) … wait(mutex) l wait(mutex) … wait(mutex) Omitting wait(mutex) or signal(mutex) (or both) Causes timing and synchronization errors that can be difficult to detect Errors in the entire system (no mutual exclusion, deadlocks) caused by only one poorly-programmed user process Might only occur given a specific execution sequence

29 5.29 Synchronization Examples Solaris Windows XP Linux Pthreads

30 5.30 Solaris Synchronization Implements a variety of locks to support multitasking, multithreading (including real-time threads), and multiprocessing Implements semaphores as we studied Adaptive mutexes used to protect short (<100 instructions) critical data in multi-CPU systems If process holding lock is currently running on another CPU, spinlock Otherwise, process holding lock is not currently running, so sleep Reader-writer locks used to protect long critical data that is often read (best for multithreading) Turnstiles used to order the list of threads waiting to acquire lock A thread needs to enter a turnstile for each object it is waiting for Implemented as one turnstile per kernel thread rather than per object  First thread to lock on an object becomes its turnstile  Since a thread can only be waiting after one object at a time, this is more efficient

31 5.31 Windows XP Synchronization Multithreaded kernel On single-processor system, simply masks all interrupts whose interrupt handlers can access the critical resource On multiprocessor systems, uses spinlocks and prevents preempting of the thread using the resource Outside the kernel, synchronization done with dispatcher objects Can make use of mutexes, semaphores, timers A dispatcher object can be signaled (available to be used by a thread) or nonsignaled (already used, the new thread must wait) When a dispatcher object moves to signaled state, kernel checks for waiting threads and moves a number of them (depending on the nature of the dispatcher object) to the ready queue

32 5.32 Linux Synchronization For short-term locks On single-processor systems: disable kernel preemption On multi-processor systems: spinlock For long-term locks: semaphores

33 5.33 Pthreads Synchronization Pthreads API is an IEEE standard, OS-independent Pthread standard includes: mutex locks reader-writer locks Certain non-standard extensions add: semaphores spinlocks

34 5.34 Review Any solution to the critical section problem has to respect three properties. What are they and why are they important? What is a spinlock, and why is it often used in multi-CPU systems but must be avoided in single-CPU systems? What is priority inheritance; what problem does it solve and how?

35 5.35 Exercises Read sections 5.1 to 5.7 and 5.9 If you have the “with Java” textbook, skip the Java sections and subtract 1 to the following section numbers 5.1 5.3 5.4 5.5 5.7 5.8 5.9 5.10 5.11 5.12 5.16 5.17 5.28

36 Silberschatz, Galvin and Gagne ©2009 Edited by Khoury, 2015 Operating System Concepts – 9 th Edition, End of Chapter 5


Download ppt "Silberschatz, Galvin and Gagne ©2009 Edited by Khoury, 2015 Operating System Concepts – 9 th Edition, Chapter 5: Process Synchronization."

Similar presentations


Ads by Google