of 42/42
Chapter 6.3: Process Chapter 6.3: Process Synchronization Synchronization Part 3 Part 3

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

  • View
    221

  • Download
    1

Embed Size (px)

Text of Chapter 6.3: Process Synchronization Part 3. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating...

  • Slide 1
  • Chapter 6.3: Process Synchronization Part 3
  • Slide 2
  • 6.2 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Module 6: Process Synchronization Lecture 6.1 Background The Critical-Section Problem Petersons Solution Synchronization Hardware Lecture 6.2: Semaphores Lecture 6.3 Classic Problems of Synchronization Monitors Synchronization Examples Atomic Transactions
  • Slide 3
  • 6.3 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Classical Problems of Synchronization We will discuss all three of these very important topics. Bounded-Buffer Problem Readers and Writers Problem Dining-Philosophers Problem
  • Slide 4
  • 6.4 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Bounded-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.
  • Slide 5
  • 6.5 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Bounded 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);
  • Slide 6
  • 6.6 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Bounded 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);
  • Slide 7
  • 6.7 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Readers-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 dont 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.
  • Slide 8
  • 6.8 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Readers-Writers Problem more 1 Problem is that solutions to the Readers-Writers issue may result in starvation. We will present a solution to the first readers-writers problem: Supporting data structure: semaphore mutex, wrt; // two semaphores int readcount;// 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 readers: readcount is a count of the number of processes currently reading the object. Mutex is used to control access to the readcount integer. For the writers: wrt serves as a mutual-exclusion semaphore for the writers. Do we need this for Readers??? wrt is also used by the first or last reader that enters / exits the critical section. Recall: we are not concerned (nor do other readers matter) by readers who enter /exit while at least one other reader is in its/their critical section. Lets look at the code.
  • Slide 9
  • 6.9 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Readers-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)
  • Slide 10
  • 6.10 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Readers-Writers Problem A Reader Process do { wait (mutex) ; // needed to control access to readcount. // Clearly, we wont 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) ; // heres 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);
  • Slide 11
  • 6.11 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Dining-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.
  • Slide 12
  • 6.12 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Dining-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) ;
  • Slide 13
  • 6.13 Silberschatz, Galvin and Gagne 2005 Operating System Concepts 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
  • Slide 14
  • 6.14 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Problems 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
  • Slide 15
  • 6.15 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Monitors 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, doesnt it.
  • Slide 16
  • 6.16 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 17
  • 6.17 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Schematic view of a Monitor Queue of clients for the monitor There can be a number of operations in a monitor
  • Slide 18
  • 6.18 Silberschatz, Galvin and Gagne 2005 Operating 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 doesnt come with them. From Stallings 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..
  • Slide 19
  • 6.19 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 20
  • 6.20 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Monitor with Condition Variables Monitor with Condition Variables Can see graphically the additional synchronization mechanisms programmer-defined. This will be come clear ahead Queue of entering processes
  • Slide 21
  • 6.21 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 22
  • 6.22 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Good Example of Monitor w/Conditions Lets consider the bounded buffer producer-consumer problem. And lets 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. 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. Lets look at the code..l.
  • Slide 23
  • 6.23 Silberschatz, Galvin and Gagne 2005 Operating 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 buffer nextin = (nextin + 1) % N; // adjust location for next append mod buffer size count++;// one more item in buffer csignal (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 buffer csignal (notfull);// signal if any process waiting until buffer is not full. } {// monitor body nextin = 0; nextout = 0; count = 0 // buffer is initially empty. }
  • Slide 24
  • 6.24 Silberschatz, Galvin and Gagne 2005 Operating 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); }
  • Slide 25
  • 6.25 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 26
  • 6.26 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Revisit Dining Philosophers with Monitors The classic problem has deadlock built in. Lets 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, lets look at more code
  • Slide 27
  • 6.27 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 28
  • 6.28 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Solution to Dining Philosophers monitor 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! Heres the initialization.Then note the instance variables at the top and the condition variables.
  • Slide 29
  • 6.29 Silberschatz, Galvin and Gagne 2005 Operating 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 weve 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.
  • Slide 30
  • 6.30 Silberschatz, Galvin and Gagne 2005 Operating System Concepts Synchronization Examples We will look at: Linux We will look at synchronization in the kernel...
  • Slide 31
  • 6.31 Silberschatz, Galvin and Gagne 2005 Operating 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().
  • Slide 32
  • 6.32 Silberschatz, Galvin and Gagne 2005 Operating 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().
  • Slide 33
  • 6.33 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 34
  • 6.34 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 35
  • 6.35 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 36
  • 6.36 Silberschatz, Galvin and Gagne 2005 Operating 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)
  • Slide 37
  • 6.37 Silberschatz, Galvin and Gagne 2005 Operating 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).
  • Slide 38
  • 6.38 Silberschatz, Galvin and Gagne 2005 Operating 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 onto stable storage.
  • Slide 39
  • 6.39 Silberschatz, Galvin and Gagne 2005 Operating 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 record and then finding the that follows it. So the redo and undo only need to be accommodated on this transaction and any others that started after.
  • Slide 40
  • 6.40 Silberschatz, Galvin and Gagne 2005 Operating 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 After every write a new record is written. Upon completion, a is written to the log.
  • Slide 41
  • 6.41 Silberschatz, Galvin and Gagne 2005 Operating 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.
  • Slide 42
  • End of Chapter 6 Part 3