Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Chapter 5: Process Synchronization (Part - 1) Operating System Concepts – 9th Edition Modified by Dr. Neerja Mhaskar for CS 3SH3 Silberschatz, Galvin and Gagne ©2013 Background Processes (and threads) can execute concurrently Concurrent access to shared data may result in data inconsistency Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes Illustration of the problem: Suppose that we wanted to provide a solution to the consumer-producer problem (Figure next slide) that fills all the buffers. We can do so by having an integer counter that keeps track of the number of full buffers. Initially, counter is set to 0. It is incremented by the producer after it produces a new buffer item and is decremented by the consumer after it consumes a buffer. Operating System Concepts – 9th Edition 5.2 Silberschatz, Galvin and Gagne ©2013 Producer Consumer Problem Buffer Producer Operating System Concepts – 9th Edition Consumer 5.3 Silberschatz, Galvin and Gagne ©2013 Producer while (true) { /* produce an item in next produced */ while (counter == BUFFER_SIZE) ; /* do nothing */ buffer[in] = next_produced; in = (in + 1) % BUFFER_SIZE; counter++; } buffer = Shared buffer, circular array BUFFER_SIZE = max. size of the buffer. counter that keeps track of the number of full buffers Operating System Concepts – 9th Edition 5.4 Silberschatz, Galvin and Gagne ©2013 Consumer while (true) { while (counter == 0) ; /* do nothing */ next_consumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; counter--; /* consume the item in next consumed */ } Operating System Concepts – 9th Edition 5.5 Silberschatz, Galvin and Gagne ©2013 Race Condition counter++ could be implemented as register1 = counter register1 = register1 + 1 counter = register1 counter-- could be implemented as register2 = counter register2 = register2 - 1 counter = register2 Consider this execution interleaving with “counter = 5” initially: S0: producer execute register1 = counter S1: producer execute register1 = register1 + 1 S2: consumer execute register2 = counter S3: consumer execute register2 = register2 – 1 S4: producer execute counter = register1 S5: consumer execute counter = register2 Operating System Concepts – 9th Edition 5.6 {register1 = 5} {register1 = 6} {register2 = 5} {register2 = 4} {counter = 6 } {counter = 4} Silberschatz, Galvin and Gagne ©2013 Critical Section Problem Consider system of n processes {p0, p1, … pn-1} Each process has critical section segment of code Process may be changing common variables, updating table, writing file, etc Goal: When one process is in its critical section, no other process may be in its critical section and each process gets a turn (in bounded time) to execute its critical section Critical section problem is to design protocol to achieve this goal. Each process must ask permission to enter critical section in entry section, may follow critical section with exit section, then remainder section We will use Critical Section and CS interchangeably Operating System Concepts – 9th Edition 5.7 Silberschatz, Galvin and Gagne ©2013 Critical Section General structure of process Pi Operating System Concepts – 9th Edition 5.8 Silberschatz, Galvin and Gagne ©2013 Solution requirement to CS Problem 1. Mutual Exclusion - If process Pi is executing in its critical section, then no other processes can be executing in their critical sections 2. Progress - If no process is executing in its critical section and some processes wish to enter their critical sections, then 1. 2. Only those processes not executing in their remainder section can participate in deciding which will enter its CS next This selection cannot be postponed indefinitely 3. Bounded Waiting - A bound must exist on the number of times that other processes are allowed to enter their critical sections after a process has made a request to enter its critical section and before that request is granted Assume that each process executes at a nonzero speed No assumption concerning relative speed of the n processes Operating System Concepts – 9th Edition 5.9 Silberschatz, Galvin and Gagne ©2013 Critical-Section Handling in OS Preemption: The operating system removes the process running on the CPU after it has executed for the specified period of time, and brings another program in to run on the CPU. This act is called preemption. Two approaches taken by the kernel to handle CS: Preemptive – allows preemption of process when running in kernel mode Non-preemptive – runs until exits kernel mode, blocks, or voluntarily yields CPU Essentially free of race conditions in kernel mode Why would you prefer a Preemptive kernel? Operating System Concepts – 9th Edition 5.10 Silberschatz, Galvin and Gagne ©2013 Peterson’s Solution Good algorithmic description of solving the problem Two concurrent process solution (P0 and P1) Assume that the load and store machine-language instructions are atomic; that is, cannot be interrupted The two processes share two variables: int turn; Boolean flag[2] The variable turn indicates whose turn it is to enter the critical section The flag array is used to indicate if a process is ready to enter the critical section. flag[i] = true implies that process Pi is ready! Values of flag initialized to False. Operating System Concepts – 9th Edition 5.11 Silberschatz, Galvin and Gagne ©2013 Algorithm for Process Pi do { flag[i] = true; turn = j; while (flag[j] && turn = = j); Entry Section critical section Exit Section flag[i] = false; remainder section } while (true); Processes can execute this code arbitrarily many times. If i=0 then j=1 and visa versa. While loop in the entry section functions like a filter/trap. Operating System Concepts – 9th Edition 5.12 Silberschatz, Galvin and Gagne ©2013 Correctness of Peterson’s Solution All three CS requirements are met. Mutual exclusion is preserved If both P0 and P1 want to enter their CS this will result in both flag[0] = T and flag[1] = T But turn = 0 or turn = 1. Since turn can be either 0 or 1 at any given time only one process can enter and thus execute in its CS. Operating System Concepts – 9th Edition 5.13 Silberschatz, Galvin and Gagne ©2013 Correctness of Peterson’s Solution Progress is satisfied: At any given time if both P0 and P1 want to enter the CS the decision which process enters its CS happens in finite time. If both P0 and P1 want to enter this will result in both flag[0] = T and flag[1] = T But turn = 0 or turn = 1. The value of turn depends on the order of execution of the statement turn = j; in both processes P0 and P1 The value of turn will determine which process gets to enter its CS first. This decision is made in finite time. Additionally if process P0 (or P1 ) is executing in its remainder CS, it does not affect the other process from entering its CS. Therefore progress is satisfied. Operating System Concepts – 9th Edition 5.14 Silberschatz, Galvin and Gagne ©2013 Correctness of Peterson’s Solution Bounded waiting is satisfied: Consider, P0 and P1 both want to enter their CS. From Progress we know that one will enter its CS (lets say P0 gets its turn) When P0 is in CS then flag[0]=T and flag[1] = T and turn = 0 When P0 exists CS then flag[0]=F, flag[1] = T and turn = 0 Thus, P1 is the process that gets to enter its CS next. Therefore, bounded waiting is satisfied, and a process will enter its critical section after at most one entry by the other process (bounded waiting). Operating System Concepts – 9th Edition 5.15 Silberschatz, Galvin and Gagne ©2013 Some pointers to check correctness of CS solution The trickiest requirement to prove is progress If it is possible for ALL processes to be stuck at the while loop statement (remember processes can be preempted any time and any no. of times). Check if a process can enter its CS arbitrarily many times if the other processes do not wish to enter their CS. If this is not possible, then Progress requirement (condition 2) is violated. Progress requirement (condition 1) is violated. If strict order exists in which processes access their CS, then again Progress requirement (condition 1) is violated. To check if bounded waiting is achieved Check if it is possible for a process to enter its CS infinitely many times without giving other processes that wish to enter their CS a turn. Operating System Concepts – 9th Edition 5.16 Silberschatz, Galvin and Gagne ©2013 Synchronization Hardware Peterson’s Algorithm drawbacks: works for only two processes and relies atomic load and store machine instructions. Systems with single processors – could disable interrupts Currently running code would execute without preemption Generally too inefficient on a multiprocessor systems Disabling interrupts on a multiprocessor can be time consuming and system efficiency is decreased. All solutions hereafter based on idea of locking Protecting critical regions via locks Modern machines provide special atomic hardware instructions Test_and_Set() Compare_and_swap() Operating System Concepts – 9th Edition 5.17 Silberschatz, Galvin and Gagne ©2013 Solution to Critical-section Problem For Multiple Processes: Using Locks do { acquire lock critical section release lock remainder section } while (TRUE); Operating System Concepts – 9th Edition 5.18 Silberschatz, Galvin and Gagne ©2013 test_and_set Instruction Definition: boolean test_and_set (boolean *target) { boolean rv = *target; *target = TRUE; return rv: } 1. Executed atomically 2. Returns the original value of passed parameter 3. Set the new value of passed parameter to “TRUE”. Operating System Concepts – 9th Edition 5.19 Silberschatz, Galvin and Gagne ©2013 Solution using test_and_set() Shared Boolean variable lock. Initially lock=FALSE (lock is available) Suppose a process Pi wants to enter its CS do { while (test_and_set(&lock)); /* do nothing */ Sets lock=True and returns False /* critical section */ lock = false; /* remainder section */ } while (true); Operating System Concepts – 9th Edition 5.20 Silberschatz, Galvin and Gagne ©2013 Solution using test_and_set() Mutual Exclusion Suppose process Pj wants to enter its CS, while Pi is executing in its CS. It sees lock=True. do { Returns True, and also, lock=True, so waits. while (test_and_set(&lock)) ; /* do nothing */ /* critical section */ lock = false; /* remainder section */ } while (true); Process waits to get the lock at the while loop. Therefore when any process Pi is executing in its CS, another process cannot enter its CS and mutual exclusion is achieved. Operating System Concepts – 9th Edition 5.21 Silberschatz, Galvin and Gagne ©2013 Solution using test_and_set() Progress and Bounded waiting Initially lock=FALSE, multiple processes try to enter If multiple processes want to enter CS, only one of them gets to execute test and set (also in finite time) A process executing in its remainder section does not get to block another process from entering the CS, since it has already released the lock. However the same process can enter CS repeatedly, without giving a turn to other processes. Hence, bounded wait is not achieved. Operating System Concepts – 9th Edition 5.22 Silberschatz, Galvin and Gagne ©2013 compare_and_swap Instruction Definition: int compare _and_swap(int *value, int expected, int new_value) { int temp = *value; if (*value == expected) *value = new_value; return temp; } 1. Executed atomically 2. Returns the original value of passed parameter “value” 3. Compares the integer stored in “value” to the integer value stored in expected. If they are equal then stores the integer value of “new_value” in “value”. Operating System Concepts – 9th Edition 5.23 Silberschatz, Galvin and Gagne ©2013 Solution using compare_and_swap Shared integer “lock” initialized to 0; (lock is available) Expected value = 0 (lock is available) New value = 1 (lock is unavailable) Solution: do { while (compare_and_swap(&lock, 0, 1) != 0) ; /* do nothing */ /* critical section */ lock = 0; /* remainder section */ } while (true); Operating System Concepts – 9th Edition 5.24 Silberschatz, Galvin and Gagne ©2013 Solution using compare_and_swap() Shared int variable lock. Initially lock=0 (lock is available) Suppose a process Pi wants to enter its CS do { while (compare_and_swap(&lock, 0, 1) != 0) ; /* do nothing */ Checks if lock=0, in this case it is, therefore resets lock = 1 and returns 0 /* critical section */ lock = 0; /* remainder section */ } while (true); Operating System Concepts – 9th Edition 5.25 Silberschatz, Galvin and Gagne ©2013 Solution using compare_and_swap() Mutual Exclusion Cont. Shared int variable lock. Initially lock=0 Process Pj wants to enter CS, while Pi is executing in its CS. it sees lock=1. do { while (compare_and_swap(&lock, 0, 1) != 0) ; /* do nothing */ /* critical section */ Checks if lock=0, in this case it is not, therefore does not reset it and simply returns 1. lock = 0; /* remainder section */ } while (true); Process waits to get the lock at the while loop. Therefore when any process Pi is executing in its CS, another process cannot enter its CS and mutual exclusion is achieved. Operating System Concepts – 9th Edition 5.26 Silberschatz, Galvin and Gagne ©2013 Solution using compare_and_swap() Progress and bounded wait Initially lock=0 (open), multiple processes try to enter If multiple processes want to enter CS, only one of them gets to execute compare_and_swap() (also in finite time) A process executing in its remainder section does not get to block another process from entering the CS, since it has already released the lock. However the same process can enter CS repeatedly, without giving a turn to other processes. Hence, bounded wait is not achieved. Operating System Concepts – 9th Edition 5.27 Silberschatz, Galvin and Gagne ©2013 Mutex Locks Previous solutions are complicated and generally inaccessible to application programmers OS designers build software tools to solve critical section problem Simplest is mutex lock Protect a critical section by first acquire() a lock then release() the lock Boolean variable indicating if lock is available or not Calls to acquire() and release() must be atomic Usually implemented via hardware atomic instructions Operating System Concepts – 9th Edition 5.28 Silberschatz, Galvin and Gagne ©2013 acquire() and release() Shared Boolean available. Available = True -> lock is available and Avaiable = False -> lock is unavailable. Acquire Operation: acquire() { while (!available) ; /* busy wait */ available = false; } Release Operation: release() { available = true; } Operating System Concepts – 9th Edition 5.29 Silberschatz, Galvin and Gagne ©2013 Solution using Mutex lock do { acquire(); /*acquire lock*/ critical section release(); /*release lock*/ remainder section } while (true); Operating System Concepts – 9th Edition 5.30 Silberschatz, Galvin and Gagne ©2013 Issues with Hardware Instructions and Mutex Locks The issue with the previous lock based solutions (hardware instructions and mutex ) busy waiting Busy waiting consumes CPU cycles without doing any useful work. This type of lock is known as a spinlock, because the lock just sits there and spins while it waits. Although busy waiting wastes CPU cycles, it saves time by not invoking context switches Therefore, useful in multi-processing systems when the wait time is expected to be short - One thread spins on one processor while another completes their critical section on another processor. Operating System Concepts – 9th Edition 5.31 Silberschatz, Galvin and Gagne ©2013 Pthreads Synchronization Pthreads API is available for programmers at the user level and is not part of any particular kernel. Provides mutex locks, condition variables, and read–write locks for thread synchronization. Mutex locks are the fundamental synchronization technique used. pthread_mutex_t data type for mutex locks. mutex created with pthread_mutex_init()function. pthread_mutex_lock(); pthread_mutex_unlock(); Operating System Concepts – 9th Edition 5.32 Silberschatz, Galvin and Gagne ©2013 Pthread Mutex Example /*Declaring mutex*/ pthread_mutex_t mutex; /*Initialize mutex, it returns 0 Null indicates default mutex attributes passed. if mutex initialized with no errors.*/ if (pthread_mutex_init(&mutex, NULL) !=0){ printf("Error in initializing mutex \n"); } Returns 0 when mutex created with no errors, otherwise returns non zero value. /*Acquire mutex lock*/ pthread_mutex_lock(&mutex); /*Critical Section*/ /*Release mutex locks*/ pthread_mutex_unlock(&mutex); Operating System Concepts – 9th Edition 5.33 Silberschatz, Galvin and Gagne ©2013 End of Chapter 5 Operating System Concepts – 9th Edition Silberschatz, Galvin and Gagne ©2013