Tải bản đầy đủ (.pdf) (15 trang)

Advanced Operating Systems: Lecture 11 - Mr. Farhan Zaidi

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (277.72 KB, 15 trang )

CS703 ­ Advanced 
Operating Systems
By Mr. Farhan Zaidi

 

 


Lecture No. 
11


Overview of today’s lecture









Producer consumer problem with a bounded buffer
Solving producer consumer problem using locks and
semaphores
Semaphores used for two purposes
Condition variables and monitors—introduction
Condition variables—definition
Hoare and Mesa style monitors
Recap of lecture




Producer­consumer with a bounded buffer



Problem definition
Producer puts things into a shared buffer, consumer takes them out. Need
synchronization for coordinating producer and consumer.



Multimedia processing:Producer creates MPEG video frames, consumer
renders the frames



Event-driven graphical user interface: Producer detects mouse clicks, mouse
movements, and keyboard hits and inserts corresponding events in buffer.
Consumer retrieves events from buffer and paints the display.



Don't want producer and consumer to have to operate in lockstep, so put a
fixed-size buffer between them; need to synchronize access to this buffer.
Producer needs to wait if buffer is full; consumer needs to wait if buffer is empty.



Solution uses semaphores for both mutex and scheduling.



Correctness constraints for solution
1) Consumer must wait for producer to fill buffers, if none full
(scheduling constraint)
2) Producer must wait for consumer to empty buffers, if all full
(scheduling constraint)
3) Only one thread can manipulate buffer queue at a time
(mutual exclusion)
Use a separate semaphore for each constraint;
Note semaphores being used in multiple ways.
Semaphore fullBuffers;
// if 0, no item in buffer
Semaphore emptyBuffers;
// if 0, nowhere to put more item
Semaphore mutex; // mutual exclusion


Semaphore solution





















Semaphore fullBuffers = 0 // initially, no item!
Semaphore emptyBuffers = numBuffers;
// initially, number of empty slots
// semaphore used to count how many
// resources there are!
Semaphore mutex = 1; // no one using the buffer
Producer() {
emptyBuffers.P();
mutex.P(); // make sure no one else is accessing the buffer
put 1 item in buffer
mutex.V(); // ok for others to use buffer
fullBuffers.V();
}
Consumer() {
fullBuffers.P();
mutex.P(); // make sure no one else is accessing the buffer
take 1 item out;
mutex.V(); // next person's turn
emptyBuffers.V();



Questions


Why does producer does P & V operations on different semaphores
than the consumer?



Is order of P's important?
Is order of V's important?





What if we have 2 producers or 2 consumers? Do we need to
change anything?


Two uses of semaphores















Mutual exclusion
When semaphores are used for mutual exclusion, the semaphore
has an initial value of 1, and P() is called before the critical section,
and V() is called after the critical section.
semaphore->P();
// critical section goes here
semaphore->V();
Scheduling constraints
Semaphores can also be used to express generalized scheduling
constraints -- in other words, semaphores provide a way for a
thread to wait for something. Usually, in this case, the initial value of
the semaphore is 0, but not always!
For example, you can implement Thread’s join (reaping) using
semaphores:
Initial value of semaphore = 0
ThreadJoin calls P
ThreadFinish calls V


Monitor Definition

Monitor: a lock and zero or more condition variables for
managing concurrent access to shared data
Note: Tanenbaum and Silberschatz both describe monitors as a
programming language construct, where the monitor lock is
acquired automatically on calling any procedure in a C++ class,

for example.
No widely-used language actually does this, however! So in many reallife operating systems, such as Windows, Linux, or Solaris, monitors
are used with explicit calls to locks and condition variables.


Condition variables
A simple example:














AddToQueue() {
lock.Acquire(); // lock before using shared data
put item on queue; // ok to access shared data
lock.Release(); // unlock after done with shared
// data
}
RemoveFromQueue() {
lock.Acquire(); // lock before using shared data
if something on queue // ok to access shared data

remove it;
lock.Release(); // unlock after done with shared data
return item;
}


Condition variables (2)


How do we change RemoveFromQueue to wait until something
is on the queue? Logically, want to go to sleep inside of critical
section, but if we hold lock when going to sleep, other threads
won't be able to get in to add things to the queue, to wake up the
sleeping thread. Key idea with condition variables: make it
possible to go to sleep inside critical section, by atomically
releasing lock at same time we go to sleep



Condition variable: a queue of threads waiting for something
inside a critical section.


Condition variables(3)


Condition variables support three operations:




Wait() -- release lock, go to sleep, re-acquire lock
Note: Releasing lock and going to sleep is atomic



Signal() -- wake up a waiter, if any



Broadcast() -- wake up all waiters



Rule: must hold lock when doing condition variable operations.


A synchronized queue, using condition 
variables:
AddToQueue() {
lock.Acquire();
put item on queue;
condition.signal();
lock.Release();
}
RemoveFromQueue() {
lock.Acquire();
while nothing on queue
condition.wait(&lock);// release lock; go to sleep; re-acquire lock
remove item from queue;
lock.Release();

return item;
}


Mesa vs. Hoare monitors


Need to be careful about the precise definition of signal and wait.



Mesa-style: (most real operating systems) Signaller keeps lock and processor.
Waiter simply put on ready queue, with no special priority. (in other words,
waiter may have to wait for lock)



Hoare-style: (most textbooks)
Signaller gives up lock, CPU to waiter; waiter runs immediately Waiter gives lock
and processor back to signaller when it exits critical section or if it waits again.




Readers/Writers
Motivation
Shared database (for example, bank balances, or airline seats)
Two classes of users:
Readers -- never modify database
Writers -- read and modify database

Using a single lock on the database would be overly restrictive.
Want:
many readers at same time
only one writer at same time




×