350 likes | 478 Views
Concurrency: Background and Implementation. Fred Kuhns (fredk@arl.wustl.edu, http://www.arl.wustl.edu/~fredk) Department of Computer Science and Engineering Washington University in St. Louis. Origins of Concurrency. Processes need to communicate, issues:
E N D
Concurrency: Background and Implementation Fred Kuhns (fredk@arl.wustl.edu, http://www.arl.wustl.edu/~fredk) Department of Computer Science and Engineering Washington University in St. Louis
Origins of Concurrency • Processes need to communicate, issues: • How is information exchanged between processes (shared memory or messages)? • How to prevent interference between cooperating processes (mutual exclusion)? • How to control the sequence of process execution (conditional synchronization)? • Execution of the kernel (interrupts, exception, traps) often results in the need for concurrent access to state and deferred processing pending an event. Cs422 – Operating Systems Organization
Problems – Shared Memory • Concurrent programs may exhibit a dependency on process/thread execution sequence or processor speed (neither are desirable!) • race condition – who’s first, and who goes next. affects program results. • There are two basic issues resulting from the need to support concurrency: • Mutual exclusion: ensure that processes/threads do not interfere with one another, i.e. there are no race conditions. In other words, program constraints (assumptions) are not violated. • Conditional synchronization. Processes/threads must be able to “wait” for the data to arrive or constraints (assertions) to be satisfied. Cs422 – Operating Systems Organization
Preliminaries • Consider a process as a sequence of statements which are implemented as one or more primitive atomic operations (hardware instructions) • Concurrent program results in the interleaving of statements from different processes • Program state is value of variables at a given point in time. Execution viewed as a sequence of states si,. Atomic actions transform states. • Program history is sequence of states: s0 -> s1 -> ... -> sN • Synchronization constrains the set of possible histories to only those that are desirable • Mutual Exclusion combines a sequence of actions into a critical section which appear to execute atomically. Cs422 – Operating Systems Organization
Race Conditions • If two or more process access and modify shared data concurrently, then the final value of the shared data may depend on the order in which it was accessed. • Race condition manifest themselves as intermittent problems and are generally difficult to debug. • To prevent race conditions, concurrent processes must synchronize their access to the shared memory locations: known as the critical section problem. Cs422 – Operating Systems Organization
Race Conditions - Example • There are 4 cases: • case 1: task A runs to completion first loading y=0, z=0. x = 0 + 0 = 0 • case 2: Task B runs and sets y to 1, then Task A runs loading y=1 and z=0. x = 1 + 0 = 1 • case 3: Task A runs loading y=0, then Task B runs to completion, then Task A runs loading z=2. x = 0 + 2 = 2 • case 4: Task B runs to completion, then Task A runs loading y=1, z=2,x = 1 + 2 = 3 Example 1 int y = 0, z = 0; Task A { x = y + z} Task B {y = 1; z = 2} Results: x = {0, 1, 2, 3} load y into R0 load z into R1 set R0 = R0 + R1 set R0 -> x Cs422 – Operating Systems Organization
Kernel File Table 0 myfile.c: attributes myfile.o: attributes 1 ... NULL 7 ... Race Condition: OS Example Task A: ... get KFT_NextFree (7) -- preempted –- KFT_NextFree += 1; update entry 7 Task B: ... get KFT_NextFree (7) KFT_NextFree += 1; update Entry 7 -- preempt KFT_NextFree = 7 • Final value of kernel table entry 7 is indeterminate. • Final value of KFT_NextFree is 9 • Kernel File Table entry 8 is not allocated Cs422 – Operating Systems Organization
Avoiding Race Conditions • Independent processes: Two processes are independent if the write set of each is disjoint from both the read and write sets of the other. • Critical reference: reference to variable changed by another process. • At-Most-Once property: If the assignment x = e statement satisfies (1) e contains at most one critical reference and x is not read by another process or (2) e contains no critical references, in which case x may be read by another process. • only one variable may be in the read and write set of two or more processes. • Four techniques: • 1 - Disjoint variables, 2 - Weakened assertions, 3 - Global invariants, 4 - Synchronization Cs422 – Operating Systems Organization
Critical Section Problem Entry/exit protocol satisfies: • Mutual Exclusion: At most one in CS • Absence of deadlock: 2 or more then at least one enters CS • Absence of Unnecessary delay: if attempting to enter CS and others not in CS (or exited) then process must enter • Eventual entry: can’t wait forever – no starvation. Task A { while (True) { entry protocol; critical section; exit protocol; non-critical section; } } Cs422 – Operating Systems Organization
Mutual Exclusion • First we look at mutual exclusion alone, also known as busy waiting • Simplest approach is to disable interrupts • why does this work? • traditionally kernel use this approach • less attractive for user process. why? • What about using a lock variable to indicate if another process is already in its critical section? Cs422 – Operating Systems Organization
Mutual Exclusion - Interrupt Disabling • Process runs until requests OS service or interrupted • Process disables interrupts for MUTEX • Processor has limited ability to interleave programs • Efficiency of execution may be degraded • Multiprocessing • disabling interrupts on one processor will not guarantee mutual exclusion Cs422 – Operating Systems Organization
Interrupt Disabling Entry/exit protocol satisfies (with assumptions): • Mutual Exclusion: Yes • Absence of deadlock: Yes • Absence of Unnecessary delay: Yes • Eventual entry: Yes Cs422 – Operating Systems Organization
Lock Variables Process A { while (True) { while (lock == 1) ; lock = 1; critical section; lock = 0; non-critical; } } int lock = 0; Process B { while (True) { while (lock == 1) ; lock = 1; critical section; lock = 0; non-critical; } } Cs422 – Operating Systems Organization
Lock Entry/exit protocol satisfies: • Mutual Exclusion: No • Absence of deadlock: Yes • Absence of Unnecessary delay: Yes • Eventual entry: No Cs422 – Operating Systems Organization
Taking Turns Task A { int myid = 0; while (True) { while (turn != 0) ; critical section; turn = 1; non-critical; } } int turn = 0; Task B { int myid = 1; while (True) { while (turn != 1) ; critical section; turn = 0; non-critical; } } Cs422 – Operating Systems Organization
Taking turns Entry/exit protocol satisfies: • Mutual Exclusion: Yes • Absence of deadlock: Yes • Absence of Unnecessary delay: No • Eventual entry: Yes Cs422 – Operating Systems Organization
Process A { int myid = 0; while (True) { enter(myid); critical section; leave(myid); } } Process B { int myid = 1; while (True) { enter(myid); critical section; leave(myid); } } Combined Approach aka Peterson’s Solution #define N 2 int turn = 0; int want[N]; void enter(int proc) { int other; other = 1 – proc; want[proc] = True; turn = proc; while (turn == proc && want[other] == True) ; } void leave(int proc) { want[proc] = False; } Cs422 – Operating Systems Organization
Peterson’s Solution Entry/exit protocol satisfies: • Mutual Exclusion: Yes • Absence of deadlock: Yes • Absence of Unnecessary delay: Yes • Eventual entry: Yes Cs422 – Operating Systems Organization
Consumer Producer Example #define BUFSZ 10 typedef struct { . . . } item; item buffer[BUFSZ]; int in = 0; int out = 0; int counter = 0; Producer item nextProduced; while (TRUE) { while (counter == BUFSZ) ; /* do nothing */ buffer[in] = nextProduced; in = (in + 1) % BUFSZ; counter++; } Consumer item nextConsumed; while (TRUE) { while (counter == 0); nextConsumed = buffer[out]; out = (out + 1) % BUFSZ; counter--; } Cs422 – Operating Systems Organization
Bounded Buffer • If both the producer and consumer attempt to update the buffer concurrently, the assembly language statements may get interleaved. • Interleaving depends upon how the producer and consumer processes are scheduled. Cs422 – Operating Systems Organization
Bounded Buffer • Assume counter is initially 5. One interleaving of statements is:producer: register1 = counter (register1 = 5)producer: register1 = register1 + 1 (register1 = 6)consumer: register2 = counter (register2 = 5)consumer: register2 = register2 – 1 (register2 = 4)producer: counter = register1 (counter = 6)consumer: counter = register2 (counter = 4) • The value of count may be either 4 or 6, where the correct result should be 5. Cs422 – Operating Systems Organization
Help from Hardware • Special Machine Instructions • Performed in a single instruction cycle • Not subject to interference from other instructions • Reading and writing • Reading and testing Cs422 – Operating Systems Organization
Test and Set Lock (TSL) (Return original value of lock) boolean TSL (boolean &lock) { boolean tmp = lock; lock = True; return tmp; } You have the lock iff False is returned. Why: • if lock == False before calling TSL(lock) • it is set to True and False is returned • if lock == True before calling TSL(lock) • it is set to True and True is returned Cs422 – Operating Systems Organization
Mutual Exclusion with TSL • Shared data: boolean lock = False; // initialize to false • Task Pi do { // Entry protocol while (TSL(lock) == True) ; // spin: wait for lock // execute critical section code -- critical section -- // Exit protocol lock = False; // Non-critical section code -- remainder section -- } while (1); Cs422 – Operating Systems Organization
Exchange Instruction • Atomically swap values, after calling swap, • a == original value of b • b = original value of a (Atomically swap two variables) void Swap(boolean &a, boolean &b) { int temp = a; a = b; b = temp; }; Cs422 – Operating Systems Organization
Mutual Exclusion with Swap • Shared data (initialized to False): boolean lock = False; boolean waiting[n]; • Process Pi do { // Entry protocol key = True; // when lock is false key becomes false while (key == True) Swap(lock, key); // Execute critical section code -- critical section -- // Exit protocol lock = false; // Non-critical section code -- remainder section -- } Cs422 – Operating Systems Organization
Machine Instructions • Advantages • Applicable multiple processes on single or multi-processor systems (using shared memory) • It is simple and therefore easy to verify • It can be used to support multiple critical sections • Disadvantages • Busy-waiting consumes processor time • Starvation possible when a process leaves a critical section and more than one process is waiting. • Who is next? • Deadlock - If a low priority process has the critical region (i.e. lock) but is preempted by a higher priority process spinning on lock then neither can advance. Cs422 – Operating Systems Organization
Busy Waiting • While busy waiting is useful in some situations it may also lead to other problems: inefficient use of CPU and deadlock resulting from a priority inversion • What we really want is a way to combine mutual exclusion schemes with conditional synchronization. • In other words, we want the option of blocking a process until it is able to acquire the mutual exclusion lock. • Simple solutikon is to add two new functions: • sleep() and wakeup() Cs422 – Operating Systems Organization
Adding Conditional Synchronization int N 10 int buf[N]; int in = 0, out = 0, cnt = 0; Task producer { int item; while (TRUE) { item = mkitem(); if (cnt == N) sleep(); buf[in] = item; in = (in + 1) % N; lock(lock);cnt++;unlock(0); if (cnt == 1) wakeup(consumer); } } Task consumer { item_t item; while (TRUE) { if (cnt == 0) sleep(); item = buf[out]; out = (out + 1) % N; lock(lock);cnt--;unlock(lock); if (cnt == N-1) wakeup(producer); consume(item); } } Cs422 – Operating Systems Organization
Lost wakeup problem • Assume that the lock() and unlock() functions implement a simple spin lock. • There is a race condition that results in a lost wakeup, do you see it? Cs422 – Operating Systems Organization
Intro to Semaphores • Synchronization mechanism: • No busy waiting and No lost wakeup problem. • Integer variable accessible via two indivisible (atomic) operations : • P(s) or wait(s): If s > 0 then decrement else block thread on semaphore queue • V(s) or signal(s): if s <= 0 then wake one sleeping thread, else increment s. • Each Semaphore has an associated queue. • Can define a non-blocking version of wait(s). Cs422 – Operating Systems Organization
Critical Section of n Tasks • Shared data: semaphore mutex; // initialize mutex = 1 • Process Ti: do {wait(mutex); -- critical section -- signal(mutex); -- remainder section – } while (1); Cs422 – Operating Systems Organization
Semaphore Implementation • Define a semaphore as a record typedef struct { int value; // value of semaphore queue_t sq; // task/thread queue } semaphore; • Assume two simple operations: • block suspends the task/thread that invokes it. • wakeup(T) resumes the execution of a blocked task/thread T. Cs422 – Operating Systems Organization
Implementation - Threads void signal(sem_t *S) { thread_t t; S->value++; if (S->value 0) { t = getthread(S->sq);wakeup(t); } return; } void wait(sem_t *S) { S->value--; while (S->value< 0) { addthread(S->sq); sleep(); } return; } Cs422 – Operating Systems Organization
Some Reference Background • Semaphores used in Initial MP implementations • Threads are woken up in FIFO order (convoys) • forcing a strictly fifo order may result in unnecessary blocking • Used to provide • Mutual exclusion (initialized to 1) • Event-waiting (initialized to 0) • Resource counting (initialized to number available) Cs422 – Operating Systems Organization