Download presentation
Presentation is loading. Please wait.
Published byDorothy Johnston Modified over 9 years ago
1
Mutual Exclusion
2
Readings r Silbershatz: Chapter 6
3
Mars Pathfinder r Considered flawless in the days after its July 4 th, 1997 landing on the Martian surface r After a few days the system kept resetting causing losses of data r Press called it a “software glitch” r What was the problem? m Answer later on!
4
Note r The assembly code for x = x +1 may look something like this: ld r1,x add r1,1 st r1,x r An interrupt can occur between any of the assembly code language instructions
5
Race Condition r A race condition exists in a program when the result of program execution depends on the precise order of execution of the threads of the process or other processes r Since thread/process execution speed varies, data values produced can be inconsistent
6
Race Condition Example (1) r Printing a file requires that the file is copied to the spooler directory m In Windows the spooler directory is in %SystemRoot%\SYSTEM32\SPOOL\PRINTERS r Print spooler process takes files from a well-defined directory and sends them one- at-a-time to the printer.
7
Race Condition Example (1) r Assume a spooler directory array (in shared memory) has a large number of slots m Numbered 0, 1, 2 m Each slot has a file name r Two other variables: m In points to the first empty slot where a new filename can be entered. m Out points to the first non-empty slot, from where the spooler will read a filename and print the corresponding file.
8
Race Condition Example (1) r Slots 1,2,3 are empty indicating the files in those slots have printed r Each process has a local variable next_free_slot representing an empty slot r Assume both process A and B want to print files. m Each wants to enter the filename into the first empty slot in spooler directory Talk.exe Prog.c Prog.h 1 2 3 4 5 6 7 8 … Spooler Directory 4 4 OUT 7 7 IN Process A next_free_slot variable Process B next_free_slot variable
9
Race Condition Example (1) r Process A reads and stores the value 7 in its local variable, next_free_slot r Process A’s time quanta expires r Process B is picked as the next process to run Talk.exe Prog.c Prog.h 1 2 3 4 5 6 7 8 … Spooler Directory 4 4 OUT 7 7 IN Process A next_free_slot variable Process B next_free_slot variable
10
Race Condition Example (1) r Process B reads in and stores the value 7 in its local variable, next_free_slot r Process B writes a filename to slot 7 Talk.exe Prog.c Prog.h 1 2 3 4 5 6 7 8 … Spooler Directory 4 4 OUT 7 7 IN Process A next_free_slot variable Process B next_free_slot variable ProgB.c
11
Race Condition Example (1) r Process B then updates the In variable to 8 r Process A now gets control of the CPU Talk.exe Prog.c Prog.h 1 2 3 4 5 6 7 8 … Spooler Directory 4 4 OUT 8 8 IN Process A next_free_slot variable Process B next_free_slot variable ProgB.c
12
Race Condition Example (1) r Process A writes its filename to slot 7 which erases process B’s filename. r Process B does not get its file printed. Talk.exe Prog.c Prog.h ProgA.c 1 2 3 4 5 6 7 8 … Spooler Directory 4 4 OUT 8 8 IN Process A Process B
13
Race Condition (2) r It is not just the OS that has to deal with race conditions r So do application programmers
14
Race Condition (2) r Application: Withdraw money from a bank account r Two requests for withdrawal from the same account comes to a bank from two different ATM machines r A thread for each request is created r Assume a balance of $1000
15
Race Condition (2) int withdraw(account, amount) { balance = get_balance(account); balance = balance – amount; put_balance(account, balance) return balance } What happens if both requests request that $1000 be withdrawn and there Is only $1200 in the account
16
Race Condition 2 r Both threads will read a balance of $1000 r Both threads will allow for $1000 to be withdrawn balance = get_balance(account) balance = balance – amount; balance=get_balance(account); balance = balance – amount; put_balance(account,balance) put_balance(account,balance); Execution sequence ss seen by CPU Thread 1 Thread 2 Thread 1 Context switch
17
Critical Sections and Mutual Exclusion r A critical section is any piece of code that accesses shared data r Mutual exclusion ensures that only one thread/process accesses the shared data
18
Conditions for Mutual Exclusion r Mutual Exclusion: No two threads (processes) simultaneously in critical section r Progress: No thread running outside its critical section may block another thread r Bounded Waiting: No thread must wait forever to enter its critical section r No assumptions made about speeds or number of CPUs
19
Mutual Exclusion in Critical Sections
20
Peterson’s Solution r Solution developed in 1981 r Considered revolutionary at the time r Software based r Assumes that the LOAD and STORE instructions are atomic i.e., cannot be interrupted (although this is no longer true for modern processors)
21
Peterson’s Solution r Each process has its own copy of variables r Two variables are shared m int turn; m int flag[2] r The variable turn indicates whose turn it is to enter the critical section.
22
Peterson’s Solution r The flag array is used to indicate if a process is ready to enter the critical section. m flag[0] = true implies that process P 0 is ready! m flag[0] = false implies that process P 0 is not ready! m flag[1] = true implies that process P 1 is ready! m flag[1] = false implies that process P 1 is not ready! m All values initialized to false (0)
23
Peterson’s Solution do { flag[0] = TRUE; turn = 1; while ( flag[1] && turn == 1); CRITICAL SECTION flag[0] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 0 Only way P 0 enters critical section is when flag[1] == FALSE or turn == 0 What if P 0 and P 1 are in their critical sections at the same time This implies that flag[0] == flag[1] ==TRUE If turn = 0 then P 1 cannot break out of its while loop If turn = 1 then P 0 cannot break out of its while loop This implies that P 0 and P 1 could not be in their critical sections at the same time do { flag[1] = TRUE; turn = 0; while ( flag[0] && turn == 0); CRITICAL SECTION flag[1] = FALSE; REMAINDER SECTION } while (TRUE) Code for P 1
24
Peterson’s Solution do { flag[0] = TRUE; turn = 1; while ( flag[1] && turn == 1); CRITICAL SECTION flag[0] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 0 Can P 0 block P 1 even if P 0 is not in its critical section? No. When P 0 finishes with its critical section it sets flag[0] to FALSE flag[0] being FALSE allows P 1 to break out of its while loop do { flag[1] = TRUE; turn = 0; while ( flag[0] && turn == 0); CRITICAL SECTION flag[1] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 1
25
Peterson’s Solution do { flag[0] = TRUE; turn = 1; while ( flag[1] && turn == 1); CRITICAL SECTION flag[0] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 0 r Initially flag[0] = flag[1] = FALSE r Let’s say that P 0 wants to enter the critical section (CS) m Assignments: flag[0] = TRUE, turn = 1 m The condition flag[1] && turn == 1 is evaluated turn is 1 but flag[1] is FALSE; Thus the condition evaluates to false which allows P 0 to enter the critical section do { flag[1] = TRUE; turn = 0; while ( flag[0] && turn == 0); CRITICAL SECTION flag[1] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 1
26
Peterson’s Solution do { flag[0] = TRUE; turn = 1; while ( flag[1] && turn == 1); CRITICAL SECTION flag[0] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 0 r Let’s say that P 1 wants to enter the critical section while P 0 is in the critical section. m Assignments: flag[1] = TRUE, turn = 0 m The condition flag[0] && turn == 0 is evaluated turn is 0 but flag[0] is TRUE; Thus the condition evaluates to true; P 1 enters the while loop. It is not allowed in the critical section do { flag[1] = TRUE; turn = 0; while ( flag[0] && turn == 0); CRITICAL SECTION flag[1] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 1
27
Peterson’s Solution do { flag[0] = TRUE; turn = 1; while ( flag[1] && turn == 1); CRITICAL SECTION flag[0] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 0 r Let’s say that P 0 leaves the critical section m Sets flag[0] = FALSE r The next time P 1 evaluates flag[1] && turn == 0 m It finds that flag[0] is FALSE which means that the while loop’s condition is false m Now P 1 can enter the critical section do { flag[1] = TRUE; turn = 0; while ( flag[0] && turn == 0); CRITICAL SECTION flag[1] = FALSE; REMAINDER SECTION } while (TRUE); Code for P 1
28
Peterson’s Solution r Peterson’s solution is not guaranteed to work on modern computer architectures m Modern CPUs reorder accesses to improve execution efficiency r Why was it presented? m Illustrates the complexities in designing software that addresses the requirements of mutual exclusion
29
Synchronization Hardware r Any solution to the critical section problem requires a lock r Process must acquire a lock before entering a critical section r Process must release the lock when it exists the critical section. r We will present several hardware solutions for locks while (true) { acquire lock critical section release lock other }
30
30 Mutual Exclusion via Disabling Interrupts r Process disables all interrupts before entering its critical region r Enables all interrupts just before leaving its critical region r CPU is switched from one process to another only via clock or other interrupts r So disabling interrupts guarantees that there will be no process switch
31
31 Mutual Exclusion via Disabling Interrupts r Disadvantage: m Gives the power to control interrupts to user (what if a user turns off the interrupts and never turns them on again?) m Does not work in the case of multiple CPUs. Only the CPU that executes the disable instruction is effected.
32
Test and Lock Instruction (TSL) r Many computers have the following type of instruction: TSL REGISTER, LOCK m Reads LOCK into register REGISTER m Stores a nonzero value at the memory location LOCK m The operations of reading the word and storing it are guaranteed to be indivisible m The CPU executing the TSL instruction locks the memory bus to prohibit other CPUs from accessing memory until the TSL instruction is done
33
Using the TSL Instruction
34
Using the TSL Operation r Before entering its critical region, a process calls enter_region r What if LOCK is 1? m Busy wait until lock is 0 r When leaving the critical section, a process calls leave_region
35
Using the TSL Operation r Assume two processes: P 0 and P 1 r LOCK is initialized to zero r Assume that P 0 wants to enter the critical section r It executes the TSL instruction. m The register value is 0 which reflects the value of LOCK m LOCK is set to 1
36
Using the TSL Operation r Now P 1 wants to enter the critical section; It executes the TSL instruction m The register value is 1 which reflects the value of LOCK m P 1 cannot enter the critical section m It repeats the TSL instruction and comparison operation until it can get into the critical section r P 0 is done with the critical section m LOCK becomes 0 r The next time P 1 executes the TSL instruction and comparison operation it finds that the register value (which reflects LOCK) is zero. It can now enter the critical section.
37
Implementing TSL r Implementing atomic TSL instructions on multiprocessors is not trivial. r This is a subject for a computer architecture course
38
Questions r How are multiple processes prevented from being in the critical section ? r Why different than disabling interrupts? r Which is better in a multicore system? m Disabling interrupts or TSL test?
39
Question r Assume that instead of a TSL instruction there is an instruction to swap the contents of a register and memory word in a single indivisible action. m Can you write a enter_region routine based on this
40
Semaphores
41
Signals r A signal is used in UNIX systems to notify a process that a particular event has occurred m A signal is generated by the occurrence of a particular event m A generated signal is delivered to a process m Once delivered, the signal must be handled r A signal process is used to associate computation with a signal
42
Signals r Example m is entered m This causes an event to be generated to a running process that is in the foreground m When that process receives the event it executes a signal handler which terminates the process
43
Signals r Two possible handlers m Default signal handler: Provided by kernel m User-defined signal handler: Provided by user and overrides the default r What if a process has multiple threads? m How a signal is handled depends on the type of signal. Options Deliver the signal to the thread to which the signal applies Deliver the signal to every thread in the process Deliver the signal to certain threads in the process Assign a specific thread to receive all signals for the process r
44
Signals r Windows does not provide explicit support for signals m Emulated r We will now discuss how signals and TSL support a software abstraction called semaphore which is used by application programmers to address problems related to critical sections.
45
What is a semaphore? r A semaphore is an integer variable with the following three operations. 1. Initialize: You can initialize the semaphore to any non- negative value. 2. Decrement: A process can decrement the semaphore, if its value is positive. If value is 0, the process blocks (gets put into queue). It is said to be sleeping on the semaphore. This is the wait operation. 3. Increment: If value is 0 and some processes are sleeping on the semaphore, one is unblocked. Otherwise, value is incremented. This is the signal operation.
46
What is a Semaphore? r Use wait before entering a critical section r Use signal after finishing with a critical section i.e., r Example: Assume S is initialized to 1. ……… wait(S); //critical section signal(S);
47
Semaphore r Binary Semaphore: Value is either 0 or 1 m Often referred to as a mutex r Counting Semaphore: Value ranges from 0 to N where N can be any integer number r Note: m The terms wait() and signal() are often referred to as down() and up()
48
Semaphore r Assume two processes P0 and P1 execute the following when they want to use the critical section down(S); //critical section up(S);
49
Using Semaphores r Assume two processes: P 0 and P 1 r Initialize the semaphore variable, s, to 1 m Why not zero? r Now what would happen if P 0 executes the down operation? m The semaphore s is currently 1. m It becomes 0 and P 0 enters the critical section r Now what would happen if P 1 executes the down operation? m The semaphore s is currently 0 m P 1 blocks
50
Using Semaphores r Assume now that P 0 is done with the critical section r It calls the up function m P 1 is unblocked m If there was no process waiting to enter the critical section the value of s would become one.
51
Using Semaphores r What happens if there are three processes: P 0,P 1,P 2 r Assume P 0 enters its critical section r If P 1 and P 2 execute the down operation they will block r When P 0 leaves the critical section then P 1 is unblocked allowing P 1 to enter its critical section m P 2 is still blocked r What if P 0 wants to enter its critical section again when P 1 is in it?
52
Using Semaphores r What if we want to allow 10 processes to use a critical section? r How would we initialize a semaphore, s?
53
Implementation r With each semaphore there is an associated waiting queue. Each entry in a waiting queue has two data items: m value (of type integer) m pointer to next record in the list
54
Implementation r A semaphore can be defined as a C struct along these lines: typedef struct { int value; struct process *list; } semaphore
55
Implementation r down() operation can be defined as down(semaphore *S) { S->value--; if (S->value < 0) { add this process to S->list; block(); } r The block() operation suspends the process that invokes it.
56
Implementation r up() operation can be defined as up(semaphore *S) { S->value++; if (S->value <= 0) { remove process P from S->list; wakeup(P); } r The wakeup() operation sends a signal that represents an event that the invoking process is no longer in the critical section
57
Implementation r The up and down operations represent require access to a “critical section” (semaphore) r Use something like TSL. r The implementation described is how Linux implements semaphores
58
Deadlock r Deadlock – Two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes r Something to watch for
59
Deadlock r Example: Let S and Q be two semaphores initialized to one Process P0 Process P1 down(S); down(Q); down(Q); down(S); …… …. up(S); up(Q); up(Q); up(S);
60
Mars PathFinder r Priority Inversion: Scheduling problem when lower-priority process holds a lock needed by higher-priority process r Now back to the Mars Pathfinder problem m High priority task was taking longer than expected to complete its work m The task was forced to wait for a shared resource that was being held by a lower- priority process m Lower-priority process was being pre-empted by a medium priority process m Scheduler detected problem and would reset
61
Mars PathFinder r The fix m The OS had a global variable to enable priority inheritance on all semaphores m It was off m It was set to on and then everything worked
62
Summary r Defined race condition r Examined different solutions
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.