Download presentation
Presentation is loading. Please wait.
1
CS703 - Advanced Operating Systems
By Mr. Farhan Zaidi
2
Lecture No. 12
3
Overview of today’s lecture
Readers/writers problem Solving readers/writers problem using condition variables Pros and cons of the solution Duality of synchronization primitives Implementing condition variables using semaphores as building blocks Thread safety and reentrant functions Ways to solve thread un-safety problem of library functions Thread un-safe functions in C library Recap of lecture
4
Readers/Writers (2) Constraints
1. Readers can access database when no writers (Condition okToRead) 2. Writers can access database when no readers or writers (Condition okToWrite) 3. Only one thread manipulates state variables at a time.
5
Readers/Writers(3) State variables: Condition okToRead = NIL
Basic structure of solution Reader wait until no writers access database check out -- wake up waiting writer Writer wait until no readers or writers check out -- wake up waiting readers or writer State variables: # of active readers -- AR = 0 # of active writers -- AW = 0 # of waiting readers -- WR = 0 # of waiting writers -- WW = 0 Condition okToRead = NIL Condition okToWrite = NIL Lock lock = FREE
6
Readers/Writers (4) Code: Reader() { lock.Acquire();
while ((AW + WW) > 0) { // check if safe to read // if any writers, wait WR++; okToRead.Wait(&lock); WR--; } AR++; lock.Release(); Access DB AR--; If (AR == 0 && WW > 0)//if no other readers still // active, wake up writer okToWrite.Signal(&lock);
7
Readers/Writers (5) Writer() { // symmetrical lock.Acquire();
while ((AW + AR) > 0) { // check if safe to write // if any readers or writers, wait WW++; okToWrite->Wait(&lock); WW--; } AW++; lock.Release(); Access DB // check out AW--; if (WW > 0) // give priority to other writers okToWrite->Signal(&lock); else if (WR > 0) okToRead->Broadcast(&lock);
8
Questions 1. Can readers or writers starve? Who and Why?
2. Why does checkRead need a while?
9
semaphores and monitors
Illustrate the differences by considering: can we build monitors out of semaphores? After all, semaphores provide atomic operations and queueing. Does this work? Wait() { semaphore - > P(); } Signal() { semaphore - > V(); } Condition variables only work inside of a lock.. Does this work? Wait(Lock *lock) { lock->Release(); Semaphore - > P(); Lock - > Acquire(); } Signal() { Semaphore - > V();
10
semaphores and monitors(2)
What if thread signals and no one is waiting? No op. What if thread later waits? Thread waits. What if thread V's and no one is waiting? Increment. What if thread later does P? Decrement and continue. In other words, P + V are commutative -- result is the same no matter what order they occur. Condition variables are NOT commutative. That's why they must be in a critical section --need to access state variables to do their job. Does this fix the problem? Signal() { if semaphore queue is not empty semaphore->V(); } For one, not legal to look at contents of semaphore queue. But also: race condition -- signaller can slip in after lock is released, and before wait. Then waiter never wakes up! Need to release lock and go to sleep atomically. Is it possible to implement condition variables using semaphores? Yes!!!
11
Semaphore mutex = 1; // This lock is outside of the condition object
{ Semaphore lock = 1; Seamphore waitSem = 0; Int numWaiters = 0; } wait(cond, mutex) signal (cond, mutex) { { P(cond.lock); P(cond.lock); cond.numWaiters++; if (cond.numWaiters > 0) V(cond.lock); { V(mutex); V(cond. waitSem); P(cond.waitSem); P(cond.lock); } cond.numWaiters - -; V(cond.lock); V(cond.lock); P(mutex); }
12
Thread Safety Class 1: Failing to protect shared variables.
Functions called from a thread must be thread-safe. We identify four (non-disjoint) classes of thread-unsafe functions: Class 1: Failing to protect shared variables. Class 2: Relying on persistent state across invocations. Class 3: Returning a pointer to a static variable. Class 4: Calling thread-unsafe functions.
13
Thread-Unsafe Functions
Class 1: Failing to protect shared variables. Fix: Use P and V semaphore operations. Issue: Synchronization operations will slow down code.
14
Thread-Unsafe Functions (cont)
Class 3: Returning a ptr to a static variable. Fixes: 1. Rewrite code so caller passes pointer to struct. Issue: Requires changes in caller and callee. 2. Lock-and-copy Issue: Requires only simple changes in caller (and none in callee) However, caller must free memory. struct hostent *gethostbyname(char name) { static struct hostent h; <contact DNS and fill in h> return &h; } hostp = Malloc(...)); gethostbyname_r(name, hostp); struct hostent *gethostbyname_ts(char *p) { struct hostent *q = Malloc(...); P(&mutex); /* lock */ p = gethostbyname(name); *q = *p; /* copy */ V(&mutex); return q; }
15
Thread-Unsafe Functions
Class 4: Calling thread-unsafe functions. Calling one thread-unsafe function makes an entire function thread-unsafe. Fix: Modify the function so it calls only thread-safe functions
16
Reentrant Functions A function is reentrant iff it accesses NO shared variables when called from multiple threads. Reentrant functions are a proper subset of the set of thread-safe functions. Thread-safe functions Thread-unsafe functions Reentrant functions
17
Thread-Safe Library Functions
All functions in the Standard C Library are thread-safe. Examples: malloc, free, printf, scanf Most Unix system calls are thread-safe, with a few exceptions: Thread-unsafe function Class Reentrant version asctime 3 asctime_r ctime 3 ctime_r gethostbyaddr 3 gethostbyaddr_r gethostbyname 3 gethostbyname_r inet_ntoa 3 (none) localtime 3 localtime_r rand 2 rand_r
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.