Transcript
Page 1: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

Chapter 6.3: Process SynchronizationChapter 6.3: Process SynchronizationPart 3Part 3

Page 2: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.2 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Module 6: Process SynchronizationModule 6: Process Synchronization

Lecture 6.1 Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware

Lecture 6.2: Semaphores

Lecture 6.3 Classic Problems of Synchronization Monitors Synchronization Examples Atomic Transactions

Page 3: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.3 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Classical Problems of SynchronizationClassical Problems of Synchronization

We will discuss all three of these very important topics.

Bounded-Buffer Problem

Readers and Writers Problem

Dining-Philosophers Problem

Page 4: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.4 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Bounded-Buffer ProblemBounded-Buffer Problem

Idea here is to control access to shared resources via a buffer pool.

Each element in the buffer contains a single item.

And, the buffer is of fixed size.

We need to coordinate access to this shared resource and, if it is not busy, then we need exclusive control when we access it.

We need a mutex semaphore (initialized to 1 – for mutual exclusion) and two additional semaphores empty and full, where empty is initially set to the maximum items available in pool, n, and full is set to 0.

These semaphores are best used in a producer-consumer relationship where access to a number of resources and controlled in a buffer.

Code is straightforward. The producer moves an item into a buffer

The consumer removes an item from the buffer.

We will show the concept here.

Page 5: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.5 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Bounded Buffer Problem (Cont.) - ProducerBounded Buffer Problem (Cont.) - Producer

The structure of the producer process

do {

// produce an item to be placed into a buffer

wait (empty); // can see process may have to wait if empty is true.

wait (mutex); // After wait(), however, we must ensure mutual exclusion// to access the buffer.

// code to add item to the buffer

signal (mutex); // releases the lock

signal (full); // what do you think this will do?

} while (true);

Page 6: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.6 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Bounded Buffer Problem (Cont.) - ConsumerBounded Buffer Problem (Cont.) - Consumer

The structure of the consumer process

do {

wait (full); // may have to wait if full is zero (no room in the buffer)

wait (mutex); // provides for mutual exclusion; gain exclusive access.

// remove an item from buffer

signal (mutex); // releases its hold on mutual exclusivity

signal (empty); // what do you think this does? (reduces number of items

// in buffer by one?

// Other processes may now access shared buffer.

// consume the removed item

} while (true);

Page 7: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.7 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Readers-Writers ProblemReaders-Writers Problem

This is a very common problem and generally refers to sharing issues centering on a data set to be shared among concurrent processes Readers – only read the data set; they do not perform any updates Writers – can both read an write.

Clearly, we don’t want a process to be reading data while another process is in the middle of updating data!!

Two problems: 1. The ‘first’ readers-writers problem: No reader is to be kept waiting unless a

writer has obtained permission to use the object that is shared. Equivalently, no reader should wait for other readers to finish simply because a writer

is waiting.

2. The ‘second’ readers-writers problem says that once a writer is ready to write, this write performs as soon as possible; that is, if a writer is waiting to access an object, then no new readers should be given permission to read.

Page 8: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.8 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Readers-Writers Problem – more 1Readers-Writers Problem – more 1Problem is that solutions to the Readers-Writers issue may result in Problem is that solutions to the Readers-Writers issue may result in starvationstarvation..

We will present a We will present a solutionsolution to the to the firstfirst readers-writers problem: readers-writers problem:

Supporting data structure:Supporting data structure:

semaphore mutex, wrt; semaphore mutex, wrt; // two semaphores// two semaphores

int readcount;int readcount; // simple integer variable// simple integer variable

(mutex and wrt are set to 1; readcount set to 0)(mutex and wrt are set to 1; readcount set to 0)

For the For the readersreaders: :

‘‘readcount’readcount’ is a count of the number of processes currently reading the object. is a count of the number of processes currently reading the object. ‘‘Mutex’Mutex’ is used to control is used to control accessaccess to the readcount integer. to the readcount integer.

For the For the writerswriters: :

‘‘wrt’ serves as a mutual-exclusion wrt’ serves as a mutual-exclusion semaphoresemaphore for the writers. for the writers.

Do we need this for Readers???Do we need this for Readers???

‘‘wrt’ is also used by the wrt’ is also used by the firstfirst or or lastlast readerreader that enters / exits the critical section. that enters / exits the critical section. Recall: we are not concerned (nor do other readers matter) by readers who Recall: we are not concerned (nor do other readers matter) by readers who enter /exit enter /exit whilewhile at least one other reader is in its/their critical section. at least one other reader is in its/their critical section.

Let’s look at the code….Let’s look at the code….

Page 9: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.9 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Readers-Writers Problem – A Writer ProcessReaders-Writers Problem – A Writer Process

The structure of a writer process

do {

wait (wrt) ; // writer may have to wait on ‘wrt.’

// wrt serves as mutual exclusion semaphore for writers.

// So when a process ‘gets’ wrt, no other process may

// be reading.

// writing is performed (critical section)

signal (wrt) ; // releases the semaphore

} while (true)

Page 10: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.10 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Readers-Writers Problem – A Reader ProcessReaders-Writers Problem – A Reader Process

do {

wait (mutex) ; // needed to control access to readcount.

// Clearly, we won’t want > one process having access to readcount at the // same time.

readcount ++ ; // important: if a writer is in critical section and n readers are

// waiting, one reader is queued on wrt; other readers on mutex. if (readercount == 1) wait (wrt) ;

// here’s the queue on first reader on wrt semaphore. - recall readcount // was set to 0. Since this is a first reader, it must ensure that no other

// process is writing to the shared resource. Hence, it may have to wait // on the wrt semaphore.

// Of course, once the Reader gets ‘through’ the wrt, it may continue…

signal (mutex) // Now, the Reader releases lock on mutex, which releases its ‘hold’ on // readcount.

// In first readers-writers problem, when code gets to this point// whether or not it has waited on wrt, reading can now be

performed!

wait (mutex) ; // now we need to adjust readcount; so we need to guarantee mutual // exclusion; Hence- may need to wait if another process

is accessing // readcount.

readcount - - ; // Once this process gets ‘through’ the wait in order to access readcount, , it // decrements and tests readcount.

if (readcount == 0) signal (wrt) ; // This means there were no processes waiting to read or ‘reading.’

signal (mutex) ; // signal mutex; this ‘releases’ readcount.

} while (true);

Page 11: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.11 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Dining-Philosophers ProblemDining-Philosophers Problem

Five philosophers: eat, think. Once in a while, they get hungry.

To eat, a philosopher needs two chopsticks – the ones on either side of him/her.

Philosopher can only pick up one at a time, and it must be available.

Once a philosopher has both chopsticks, she eats; when finished, she gives up both chopsticks and then again resumes ‘thinking.’

Shared data – two items.

Bowl of rice (you may liken this to a data set) Semaphore chopstick [5] initialized to 1 (an array of integers)

The solution (next slide) guarantees no two neighbors are eating at the same time, but deadlock will be clearly apparent.

Page 12: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.12 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Dining-Philosophers Problem – the StructureDining-Philosophers Problem – the Structure The structure of Philosopher i:

// Go through code on your own…

do {

wait ( chopstick[i] ); // waiting on chopstick to the ‘right.’

wait ( chopStick[ (i + 1) % 5] ); // waiting on other chopstick

// can see we are waiting on chopsticks on either side of her.

// eating takes place…..

signal ( chopstick[i] ); // releases one chopstick

signal (chopstick[ (i + 1) % 5] ); // releases other chopstick.

// here, philosopher attempts to give up both chopsticks.

// philosopher resumes thinking…

} while (true) ;

Page 13: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.13 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Dining-Philosophers Problem (Cont.)Dining-Philosophers Problem (Cont.)

Remedies – (from your book) – that ensure deadlock will not occur 1. Allow at most four philosophers to be sitting simultaneously at table. 2. Allow a philosopher to pick up her chopsticks only if both chopsticks

are available (to do this she must pick them up in a critical section) 3. Use an asymmetric solution; that is, an odd philosopher picks up

first her left chopstick and then her right chopstick, whereas an even philosopher picks up her right chopstick and then her left chopstick.

Unfortunately even though these approaches produce a deadlock free solution, this does not preclude starvation!

Incidentally, we will return to the dining philosophers problem a few slides ahead…

Page 14: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.14 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Problems with SemaphoresProblems with Semaphores Correct use of semaphore operations requires careful attention:

Remember, these are usually written by programmers such as you and me…

Lots of possibilities for programming errors when programmers use semaphores to solve critical section problems.

While some of the possibilities are unlikely to occur, they can occur and results can be disastrous.

Getting the sequence wrong, repeating the same system call, omitting a call: : signal (mutex) …. wait (mutex) // sequence wrong wait (mutex) … wait (mutex) // two waits; no signal? wait (mutex) or signal (mutex) (but not both) // forgetting one….

A single process error can really wreak havoc Semaphores are powerful and flexible for enforcing mutual exclusion and for

coordinating processes. It is often difficult to produce a correct program using semaphores. The difficulty centers around the wait() and signal() operations that may be scattered

throughout a program. Not easy to see the overall effect of these operations on the semaphores they affect. Remember: semaphores themselves are not atomic, but include critical sections

which are atomic by using techniques such as test and set… Semaphores are operating system features available to programmers…

Enter the monitor type structure…

Page 15: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.15 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

MonitorsMonitors A Monitor is a high-level abstraction that provides a convenient and effective mechanism for

process synchronization. A monitor provides equivalent functionality to that of semaphores and is easier to control. Monitors have been implemented in a number of programming languages including Java. Using a monitor, a programmer may put monitor locks on any object, like a linked list. Can have a lock on a group of linked lists (single lock) or have a lock for each linked list, …

Lots of flexibility here. A monitor is first of all an abstract data type (ADT) – with restrictions Only one process may be active within the monitor at a time Note: in its implementation, this data type has both private data and public methods. This data type provides a set of programmer-defined operations providing for mutual exclusion . Recognize (again) that only one process may be active in the monitor at any given time. Also contains shared variables which establish the state of the instance at that time.

monitor monitor-name{

// shared variable declarations // kind of like ‘instance variables.’

procedure P1 (…) { …. }…

procedure Pn (…) {……}

Initialization code ( ….) { … }…

}}

Looks kind of like a standard class definition, doesn’t it….

Page 16: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.16 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Monitors

Since this is an object, only public methods can access the instance variables (in the monitor object),

its formal parameters for a specific method, and

any local variables declared within the methods (only accessible by code in ‘this’ method.

Again, only one process at a time can be active within the monitor.

This is important.

Thus the programmer does not have to worry about this kind of synchronization issues revolving around sharing the monitor.

Page 17: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.17 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Schematic view of a MonitorSchematic view of a Monitor

Queue of clients for the monitor

There can be a number of operations in a monitor

Page 18: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.18 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

More on the Monitor and its Operations But unfortunately, this ADT is not powerful enough for modeling some synchronization

schemes. And, in fact, programmers can and do add some of their own synchronization mechanisms – the monitor doesn’t come with them….

From Stalling’s book: As it turns out, in order for a monitor to be useful for concurrent processing, a monitor must include synchronization tools.

For example: suppose a process invokes a monitor and, while in the monitor, this process must be blocked until some condition is satisfied; that is, it cannot continue until something becomes true, false, available, etc….. So:.

A facility is needed through which the process is not only blocked while using the monitor, but releases the monitor so that some other process may have access to the monitor and enter it. Remember, there is only one instance of the monitor.

Later, when this ‘condition’ is satisfied and the monitor is again available, the process can be resumed and allowed to reenter the monitor at the point of its suspension.

Monitors support synchronization by using condition constructs or condition variables. These are contained within the monitor and accessible only within the monitor. These guys are special data types in monitors that are operated on by two functions: (ahead) First, the variables look like: condition x, y; They are operated upon by: wait() and signal(), as in x.wait or x.signal.

x.wait () – this suspends the execution of the calling process on condition c. Monitor is now available to other processes. :

x.signal () – is a system call to resume execution of a blocked process after a wait() on the same condition. If there are several processes blocked on this condition, OS will select one of them; if there are none, do nothing. .

Page 19: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.19 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Condition Variables – Synchronization Mechanizations for use in Monitors

It is important to note that the wait() and signal() operations are different than those for the semaphore.

If a process in a monitor signals() and no task is waiting on the condition variable, the signal is lost.

We like to think (not exactly true the monitor has only a single entry point that is guarded so that only one process may be in the monitor at a time.

Other processes that attempt to enter the monitor join a queue of processes blocked waiting for monitor availability. (see two slides back)

Once a process is ‘in’ the monitor, it can temporarily block itself on condition x by issuing x.wait. It will then be placed in a queue of processes waiting to reenter the monitor when the condition changes and resume execution at the point in its program following the wait().

If a process that is executing in a monitor detects a change in condition variable x, it issues a x.signal operation that alerts the corresponding condition queue that the condition had changed.

Page 20: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.20 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Monitor with Condition VariablesMonitor with Condition Variables

Can see graphically the additional synchronization mechanisms – programmer-defined.This will be come clear ahead…

Queue of entering processes

Page 21: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.21 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Discussion on signal() and wait() So, again, x.wait() process invoking this operation is suspended until

another process invokes x.signal();

x.signal() resumes exactly one suspended process, if in fact there is a process suspended; otherwise, there is no net effect, as we have said.

Even with these additional synch mechanisms, nothing is free.

If signal() is invoked by P and another process, Q, is suspended (associated with the condition x), then Q can resume, and P must wait. Recall: We cannot have two processes with simultaneous access.

But there are two possibilities and both are reasonable:

Signal and Wait. P either waits until Q leaves the monitor or waits for another logical condition to be okay.

Signal and Continue. Here, Q either waits until P leaves the monitor or waits for another condition to be okay.

Here, P is already executing, so let it continue, but if so when Q resumes, the logical condition for which Q was waiting might not be true.

In Concurrent Pascal (no longer taught), when P executes the signal operation, it immediately leaves the monitor and Q is resumed immediately.

Page 22: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.22 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Good Example of Monitor w/Conditions Let’s consider the bounded buffer producer-consumer problem. And let’s look at the

code on the next page… The monitor module, boundedbuffer, controls the buffer used to store and retrieve

characters. The monitor includes two condition variables (declared with the construct cond: notfull

is true when there is room to add at least one character to the buffer, and notempty is true when there is at least one character in the buffer.

<take a brief look at the declarations in the monitor – next slide > We can see that there are two methods in this monitor: append() and take()… A producer can add characters to the buffer only by means of the procedure append

inside the monitor; the producer itself does not have direct access to buffer. The procedure first checks the condition notfull to determine if there is space available

in the buffer. If not, the process executing the monitor is blocked on that condition. Some other process (producer or consumer) may now enter the monitor. Later, when the buffer is no longer full, the blocked process may be removed from the

queue, reactivated , and resume processing. After placing a character in the buffer, the process signals the notempty condition. A similar description can be made of the consumer function. Let’s look at the code..l.

Page 23: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.23 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

// program producerconsumer monitor boundedbuffer; char buffer [N]; // N is the buffer size int nextin, nextout, count; // these variables are ‘obvious’ I hope. cond notfull, notempty; // condition variables for synchronization void append (char x) { // executed by the producer…

if (count == N)cwait (notfull); // buffer is full; avoid overflow; wait on notfull!

buffer [nextin] = x; // otherwise, move x into buffernextin = (nextin + 1) % N; // adjust location for next append mod buffer sizecount++; // one more item in buffercsignal (notempty); // resume any ‘waiting’ consumer

} void take (char x) { if (count == 0)

cwait (notempty);// buffer empty; avoid underflow; wait until notempty.x = buffer [nextout]; // otherwise, assign next char in buffer to x nextout = (nextout + 1) % N; // adjust location of next item for consumption…count --; // one fewer item in buffercsignal (notfull); // signal if any process waiting until buffer is not full.

}

{ // monitor bodynextin = 0; nextout = 0; count = 0 // buffer is initially empty.

}

Page 24: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.24 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

and,

void producer() char x; {

while (true){

produce (x);append (x);

} }

void consumer () {

char x;while (true){

take(x);consume (x);

} } void main() {

parbegin (producer, consumer); }

Page 25: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.25 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Explanation of Preceding Code

This example points out the division of responsibility with monitors as compared to semaphores.

In the case of monitors, the monitor construct itself enforces mutual exclusion: it is not possible for both producer and consumer to simultaneously access buffer.

However, the programmer must place the appropriate wait and signal primitives inside the monitor to prevent processes from depositing items in a full buffer or removing them from an empty one. (see two slides back: used cwait and csignal)

In the case of semaphores, both mutual exclusion and synchronization are the responsibility of the programmer.

And we could go on in this area….

These last few slides came from Stallings – to supplement our book.

Page 26: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.26 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Revisit Dining Philosophers with Monitors

The classic problem has deadlock built in. Let’s take a look using Monitors! Here, we impose the constraint that a philosopher may pick up her

chopsticks only if both are available. (one of the ‘solutions’ cited earlier… The algorithm needs to capture the ‘states’ a philosopher may be in: The

states are: thinking, hungry, and eating. Note: enum {thinking, hungry, eating} state[5]; This means we have an array of enum data types and each element of

state has a value of one of the three enumerated data types. We also add conditions to assist in additional synchronization:

condition self[5]

which is used for philosopher I to delay him/herself when hungry, but when s/he is

unable to obtain both chopsticks.

Self[ ] is the synchronization primitives needed for synchronization.

Recall: the monitor itself provides for mutual exclusion; but synchronization is the responsibility of the programmer and this code must be included….

Given this backdrop, let’s look at more code…

Page 27: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.27 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

We have a monitor, dp (for dining philosophers) and the definition is provided in the next slide.

Initialization has every philosopher ‘Thinking.‘

At the top of the monitor, the enum data type is declared.

The condition array, ‘self’, is declared as the constraint on synchronization.

Page 28: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.28 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Solution to Dining PhilosophersSolution to Dining Philosophersmonitor DP

{

enum { THINKING; HUNGRY, EATING) state [5] ;

condition self [5];

void pickup (int i) {

state[i] = HUNGRY; test(i); if (state[i] != EATING) self [i].wait;}

void putdown (int i) { state[i] = THINKING;

// test left and right neighbors test((i + 4) % 5); test((i + 1) % 5);

} void test (int i) {

if ( (state[(i + 4) % 5] != EATING) && (state[i] == HUNGRY) && (state[(i + 1) % 5] != EATING) ) { state[i] = EATING ;

self[i].signal () ; } }

initialization_code() { for (int i = 0; i < 5; i++) state[i] = THINKING;}

}

Each philosopher starts by executing the pickup method, which sets him/her to Hungry and invokes test().Note: This may result in the suspension of process.Note the code for the wait()…Consider for philosopher 0:Set state[0] to Hungry; invoke test(). In test(): ‘If statement’ (state[4] not Eating, && state[0] is Hungry and state[1] is not Eating (both neighbors), so set state[0] to EATING; set self[0].signal(). Philosopher may now eat. (kind of like ‘consume’)Then, philosopher executes putdown(). Here, this state is reset to Thinking (eating is done…) and then tests the two neighbors. These will be False, since both (originally) are Thinking. Then Philosopher 0 invokes the condition self[0].signal() citing s/he is done. Note this signal is a programmer responsibility for synchronization.Of course, this is not perfect, and a philosopher may, in fact, still starve to death!

Here’s the initialization….Then note the ‘instance variables’ at the top and the condition variables.

Page 29: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.29 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Enough

Book contains more materials on implementing a monitor using semaphores and resuming processes within a monitor.

I recommend that you read these.

But we’ve accomplished our objective – a reasonably thorough introduction to semaphores and monitors.

You should know the characteristics of each: the advantages and the disadvantages…

Advanced operating systems courses and advanced OS programming would continue with these last two topics dealing with monitors.

Page 30: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.30 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Synchronization ExamplesSynchronization Examples

We will look at: Linux

We will look at synchronization in the kernel...

Page 31: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.31 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Synchronization in Linux

We recall that prior to version 2.6, Linux was a non-preemptive kernel.

Newer versions of the Linux kernel are preemptive. This means a task can be preempted when running in

kernel mode. Now, we know that the Linux kernel uses spinlocks and

semaphores for locking in the kernel. Recall:

Spinlocks – a type of semaphore that causes continual looping executing a busy waiting execution.

It may be costly because the CPU could be busy doing other tasks. Might be okay, however, in that there is no context switching involved

and when the locks are expected to be held for only a very short time, spinlocks may be the way to go.

Often employed on multiprocessor systems because one thread can wait (spin) on one processor while another process executes its critical section on another processor.

Semaphores – merely an integer variable itself (usually an integer) that can be accessed controlled only via two atomic operations: wait() and signal().

Page 32: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.32 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Synchronization in Linux – more

As we are aware, in symmetric multiprocessors (SMP), spinlocks will work well if critical section execution is quick.

For single processor machines, the mechanism used is to simply enable / disable kernel pre-emption.

In summary: in single processors, we disable / enable preemption, while in multiple processor machines, we use spinlocks (acquire and release the spin lock).

Now, how does Linux implement the preemption process?

Linux employs two system calls: preempt_disable() and preempt_enable().

Page 33: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.33 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Synchronization in Linux – more Pre-empting the kernel is not always a simple task; at times it may not be safe. There may be a process executing in kernel mode currently holding lock(s). So, do we really want to preempt such processes???

To address this, each task in the system has what is called a ‘thread-info’ structure that contains an integer counter, preempt_count.

This counter indicates the number of locks held by the task.

Any time a kernel mode task is holding one or more locks, (lock > 0), then preempting cannot be done..

So only when this count becomes zero (that is, the executing task releases all locks), then a kernel process can be interrupted via the system calls.

As we recall, spinlocks and kernel preemption/non-preemption are acceptable approaches when a lock is held for a short time.

If a lock must be held for longer periods, a semaphore is used and typically a process blocks.

Page 34: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.34 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

6.9 Atomic Transactions

Goal is to ensure critical sections are executed atomically by using mutual exclusion mechanisms.

Motivation: execute critical section totally or not at all.

Long time focus in data base systems where one is not allowed to read, say, financial data, when the file / database is undergoing updating by another process. Much research has taken place in the database arena. Thinking: apply this research to operating systems too.

These are the ideas behind atomic transactions. The transaction must execution to completion.

Page 35: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.35 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

6.9.1 The System Model

Transaction – a series of instructions that must run from beginning to end (atomic execution) – considered a ‘single logical function.’

Here, we are reading and writing – terminated by ‘commit’ or ‘abort.’

Commit implies that transaction has completed a successful execution.

Abort implies that the transaction terminated due to logical error or system failure.

Now, an aborted transaction may have updated data and this data might not be in the correct ‘state’ when the transaction terminated abnormally.

Thus, we must undertake some kind of roll back or restore to get the data back to its previous stable / reliable state.

Page 36: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.36 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

The System Model – more; Devices

So we must talk about device properties used to store data that might be involved in some kind of rollback. Volatile Storage – usually does not survive a system

crash (central memory and cache)

Nonvolatile Storage – data usually survives crashes (disks, magnetic tapes, …)

Stable Storage - Information never lost. Here we replicate information in ‘non-volatile storage caches’

(generally disk) with independent failure models and to

update the information in a controlled manner. (later chapters)

Page 37: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.37 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

6.9.1 The System Model – more; the Log

We also have a Log. Before a write() is ultimately executed, all ‘log’ info must be written to

stable storage. Clearly, this incurs a very serious performance penalty!!

Additional ‘Writes’ plus additional storage are needed for the log, etc. But where vitally important, such as in secure environments, financial

environments, and more, this performance penalty is worth the price. In general terms, by using the log, the system is able to recover from

a failure and recover from a partial update.

Two algorithms are needed: An undo() – restores values of data prior to Transaction A redo() – sets values of data to new values. Both old values and new values must have been loaded into the log

for these two algorithms to be successful. Naturally, failure can occur during recovery. So this process must

be idempotent (yield same results if executed repeatedly).

Page 38: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.38 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

6.9.2 Checkpoints in Logs Here again, consider what we have: we have a log and the log is used

to determine which transactions need to be undone and/or redone. It would first appear that we might conceivably have to go through the

entire log to determine a set of transactions that need reconsideration. Major Disadvantages:

Search process takes time. Recovery takes lots of time

We can save time by undertaking ‘checkpoints.’ Essentially, in addition to the write-ahead logging, the system

performs periodic checkpoints. Process is:

Output all log records currently residing in volatile storage (PM) onto stable memory

Output all modified data residing in volatile storage to the stable storage Output a log record <checkpoint> onto stable storage.

Page 39: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.39 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

6.9.2 Checkpoints

The process of establishing checkpoints in the log helps to shorten the recovery time, and it makes sense If transaction T1 is committed prior to the checkpoint, T1 commit

record is in log. Here, any modifications made by T1 must have already been written to

stable storage either prior to the checkpoint or as part of the checkpoint itself.

In recovery, then, there is no need for a redo on the transaction.

So, a recovery routine now only examines the log to determine the most recent transaction that started into execution before the most recent checkpoint took place.

Does so by searching log backward to find first <checkpoint> record and then finding the <T-start> that follows it.

So the redo and undo only need to be accommodated on this transaction and any others that started after <T- Start>.

Page 40: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.40 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

6.9.2 Log-Based Recovery To enable atomicity:

Record on stable storage information describing all modifications made by transaction to data it has accessed.

This method is referred to as write-ahead logging. (this is not new) System maintains a data structure called a log.

Log itself consists of records describing transaction particulars: Transaction name – unique name of trans that performed the write operation Data item name – unique name of the data item written Old value: value prior to the write New value: value that data item should have after the write.

Process: Prior to transaction execution, original record written to log <T-starts> After every ‘write’ a new record is written. Upon completion, a <T- commits> is written to the log.

Page 41: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

6.41 Silberschatz, Galvin and Gagne ©2005Operating System Concepts

Summarizing This chapter was all about working with sequential processes that must

share data. Of course, mutual exclusion and synchronization must be ensured. Critical Sections can be accessed by only one process at a time. Different approaches were presented to deal with this phenomenon. Main disadvantage of user-coded solutions is they usually require busy

waiting. Semaphores overcome this and can be used with various schemes

especially if there is hardware support for atomic instructions. Classic Problems: There is a large class of concurrency-related problems

addressed by the classic bounded-buffer problem, the readers-writers problem, and the dining-philosopher problem.

Monitors provide a synchronization mechanism by using an abstract data type (ADT).

Condition variables provide a method by which a monitor procedure can provide additional constraints and block a process’ execution until the process is signaled to continue.

We looked at Linux and discussed logs with checkpoints for recovery.

Page 42: Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Module 6: Process Synchronization Lecture

End of Chapter 6End of Chapter 6Part 3Part 3


Recommended