OS Chapter 5 Process Synchronization

Ace your homework & exams now with Quizwiz!

Solution to Dining Philosophers

Each philosopher i invokes the operations pickup() and putdown() in the following sequence: 1. DiningPhilosophers.pickup(i); 2. EAT 3. DiningPhilosophers.putdown(i); ◆ No deadlock, but starvation is possible

Critical Section

Each process has critical section segment of code. Process may be changing common variables, updating table. If one process is in critical section, no other may be in its critical section

Solving critical section problem

Each process must ask permission to enter critical section in entry section, may follow critical section with exit section

Locking Protocol

Ensure serializability by associating lock with each data item ◆ Follow locking protocol for access control ❖ Locks ◆ Shared - Ti has shared-mode lock (S) on item Q, Ti can read Q but not write Q ◆ Exclusive - Ti has exclusive-mode lock (X) on Q, Ti can read and write Q ❖ Require every transaction on item Q acquire appropriate lock ❖ If lock already held, new request may have to wait ◆ Similar to readers-writers algorithm

Two-phase Locking Protocol

Generally ensures conflict serializability ❖ Each transaction issues lock and unlock requests in two phases ◆ Growing - obtaining locks ◆ Shrinking - releasing locks ❖ Does not prevent deadlock

Progress

If no process is executing in its critical section, some other process wants to enter its critical section, then selection of processes that will enter the critical section next cannot be postponed indefinitely.

Mutual Exclusion

If process Pi is executing in its critical section, then no other processes can be executing in their critical sections

Concurrent Transactions

Must be equivalent to serial execution - serializability ❖ Could perform all transactions in critical section ◆ Inefficient, too restrictive ❖ Concurrency-control algorithms provide serializability

Semaphore Implementation

Must guarantee that no two processes can execute wait() and signal() on the same semaphore at the same time. ◆ Thus, implementation becomes the critical section problem where the wait and signal code are placed in the critical section. ◆ Could now have busy waiting in critical section implementation ■ But implementation code is short ■ Little busy waiting if critical section rarely occupied. ◆ Note that applications may spend lots of time in critical sections and therefore this is not a good solution.

Solution to Critical Section problem

Mutual Exclusion Progress Bounded Waiting

Peterson's Solution

Two process solution Two processes share two variables; int turn ,boolean flag Variable turn indicates whose turn it is to enter the critical section flag array is used to indicate if a process is ready to enter the critical section

Types of Storage Media

Volatile storage - information stored here does not survive system crashes ◆ Example: main memory, cache ❖ Nonvolatile storage - Information usually survives crashes ◆ Example: disk and tape ❖ Stable storage - Information never lost ◆ Not actually possible, so approximated via replication or RAID to devices with independent failure modes

Semaphores with no Busy waiting

With each semaphore there is an associated waiting queue: ◆ Each entry in a waiting queue has two data items: ■ value (of type integer) ■ pointer to next record in the list ◆ Two operations: ■ block - place the process invoking the operation on the appropriate waiting queue. ■ wakeup - remove one of processes in the waiting queue and place it in the ready queue.

acquire() and release()

acquire() { while (!available) ; /* busy wait */ available = false;; } release() { available = true; } do { acquire lock /* critical section */ release lock /* remainder section */ } while (true);

Bounded Waiting

A bound must exist on the number of times that other processes are allowed to enter their critical sections after a process has made a request to enter its critical section and before that request is granted.

Readers-Writers Problem

A data set is shared among a number of concurrent processes ◆ Readers - only read the data set; they do not perform any updates ◆ Writers - can both read and write ❖ Problem - allow multiple readers to read at the same time ◆ Only one single writer can access the shared data at the same time

Monitors

A high-level abstraction that provides a convenient and effective mechanism for process synchronization ❖ Abstract data type, internal variables only accessible by code within the procedure ❖ Only one process may be active within the monitor at a time ❖ But not powerful enough to model some synchronization schemes

System Model

Assures that operations happen as a single logical unit of work, in its entirety, or not at all ❖ Related to field of database systems ❖ Challenge is assuring atomicity despite computer system failures ❖ Transaction - collection of instructions or operations that performs single logical function ◆ Here we are concerned with changes to stable storage - disk ◆ Transaction is series of read and write operations ◆ Terminated by commit (transaction successful) or abort (transaction failed) operation ◆ Aborted transaction must be rolled back to undo any

Classical Problems of Synchronization

Bounded-Buffer Problem ◆ Readers and Writers Problem ◆ Dining-Philosophers Problem

Serializability

Consider two data items A and B ❖ Consider Transactions T0 and T1 ❖ Execute T0, T1 atomically ❖ Execution sequence called schedule ❖ Atomically executed transaction order called serial schedule ❖ For N transactions, there are N! valid serial schedules

Semaphore usage

Counting semaphore ◆ integer value can range over an unrestricted domain ❖ Binary semaphore ◆ integer value can range only between 0 and 1 ◆ Essentially a mutex lock.

Timestamp-based Protocol Implementation

Data item Q gets two timestamps ◆ W-timestamp(Q) - largest timestamp of any transaction that executed write(Q) successfully ◆ R-timestamp(Q) - largest timestamp of successful read(Q) ◆ Updated whenever read(Q) or write(Q) executed ❖ Timestamp-ordering protocol assures any conflicting read and write executed in timestamp order ❖ Suppose Ti executes read(Q) ◆ If TS(Ti) < W-timestamp(Q), Ti needs to read value of Q that was already overwritten ■ read operation rejected and Ti rolled back ◆ If TS(Ti) ≥ W-timestamp(Q) ■ read executed, R-timestamp(Q) set to max(R-timestamp(Q), TS(Ti))

Deadlock and starvation

Deadlock - two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes ❖ Let S and Q be two semaphores initialized to 1. P0 P1 wait(S); wait(Q); wait(Q); wait(S); . . . . . . signal(S); signal(Q); signal(Q); signal(S);

Nonserial Schedule

Nonserial schedule allows overlapped execute ◆ Resulting execution not necessarily incorrect ❖ Consider schedule S, operations Oi, Oj ◆ Conflict if access same data item, with at least one write ❖ If Oi, Oj consecutive and operations of different transactions & Oi and Oj don't conflict ◆ Then S' with swapped order Oj Oi equivalent to S ❖ If S can become S' via swapping nonconflicting operations ◆ S is conflict serializable

Dining-Philosophers Problem

Philosophers spend their lives thinking and eating ❖ Don't interact with their neighbors, occasionally try to pick up 2 chopsticks (one at a time) to eat from bowl ◆ Need both to eat, then release both when done ❖ In the case of 5 philosophers ◆ Shared data ■ Bowl of rice (data set) ■ Semaphore chopstick [5] initialized to 1

Solution to Critical Section Problem-Two approaches depending on kernel

Preemptive Non-Preemptive

Mutex Locks

Product critical regions by first acquire() a lock then release() it ◆ Boolean variable indicating if lock is available or not. ◆ Calls to acquire() and release() must be atomic. ■ Usually implemented via hardware atomic instructions ◆ But this solution requires busy waiting ■ This lock is therefore called a spinlock.

Pthreads Syncronization

Pthreads API is OS-independent ❖ It provides: ◆ mutex locks ◆ condition variables ❖ Non-portable extensions include: ◆ read-write locks ◆ spinlocks

Log-Based Recovery

Record to stable storage information about all modifications by a transaction ❖ Most common is write-ahead logging ◆ Log on stable storage, each log record describes single transaction write operation, including ■ Transaction name ■ Data item name ■ Old value ■ New value ◆ <Ti starts> written to log when transaction Ti starts ◆ <Ti commits> written when Ti commits ❖ Log entry must reach stable storage before operation on data occurs

Timestamp-based Protocols

Select order among transactions in advance - timestamp-ordering ❖ Transaction Ti associated with timestamp TS(Ti) before Ti starts ◆ TS(Ti) < TS(Tj) if Ti entered system before Tj ◆ TS can be generated from system clock or as logical counter incremented at each entry of transaction ❖ Timestamps determine serializability order ◆ If TS(Ti) < TS(Tj), system must ensure produced schedule equivalent to serial schedule where Ti appears before Tj

Solution using test and set

Shared boolean variable lock, initialized to FALSE ❖ Solution: do { while ( test_and_set(&lock) ) ; /* do nothing */ /* critical section */ lock = false; // Ponder: Why isn't this atomic? /* remainder section */ } while (true);

Solution using compare and swap

Solution: do { while ( compare_and_swap(&lock, 0, 1) != 0 ) ; /* do nothing - just wait */ /* critical section */ lock = 0; /* remainder section */ } while (true);

Timestamp-ordering Protocol

Suppose Ti executes write(Q) ◆ If TS(Ti) < R-timestamp(Q), value Q produced by Ti was needed previously and Ti assumed it would never be produced ■ Write operation rejected, Ti rolled back ◆ If TS(Ti) < W-timestamp(Q), Ti attempting to write obsolete value of Q ■ Write operation rejected and Ti rolled back ◆ Otherwise, write executed ❖ Any rolled back transaction Ti is assigned new timestamp and restarted ❖ Algorithm ensures conflict serializability and freedom from deadlock

Semaphore

Synchronization tool that does not require busy waiting. ◆ Semaphore S - integer variable ❖ Two standard operations modify S: ◆ wait() and signal() ■ Originally called P() and V() ◆ Less complicated ◆ Can only be accessed via two indivisible (atomic) operations

Atomic Transactions

System Model ❖ Log-based Recovery ❖ Checkpoints ❖ Concurrent Atomic Transactions

Preemptive

allows preemption of process when running in kernel mode

Atomic hardware instructions

atomic- non interruptive either test memory word and set value or swap contents of two memory words

Concurrent access to shared data may result in

data inconsistency

Critical Section code

do { [entry section] critical section [exit section] remainder section }while (true);

CSP using Locks

do { acquire lock // critical section goes here release lock //remainder section goes here }while(true);

Bounded-waiting Mutual Exclusion with test and set

do { waiting[i] = true; key = true; while (waiting[i] && key) key = test_and_set(&lock); waiting[i] = false; /* critical section */ j = (i + 1) % n; while ((j != i) && !waiting[j]) j = (j + 1) % n; if (j == i) lock = false; else waiting[j] = false; /* remainder

Starvation

indefinite blocking --a process may never be removed from the semaphore queue in which it is suspended

How to solve the consumer-producer problem?

make a integer counter that keeps track of the number of full buffers. Counter set to 0 initially and incremented by producer after it producers new buffer and is decremented by consumer after it consumes a buffer.

Bounded Buffer Problem

n buffers, each can hold one item ❖ Semaphore mutex initialized to the value 1 ❖ Semaphore full initialized to the value 0 ❖ Semaphore empty initialized to the value n

Locking

protecting critical regions via locks Synchronization Hardware(hardware support for critical section code)

Non-preemptive

runs until exits kernel mode,blocks,or voluntarily yields CPU -free of race conditions in kernel mode.

Priority Inversion

scheduling problem when lower priority process holds a lock needed by higher priority process

Solution to Dining Philosophers

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; } }

Producer

while (true) { /* produce an item in next produced */ while (counter == BUFFER_SIZE) ; /* do nothing */ buffer[in] = next_produced; in = (in + 1) % BUFFER_SIZE; counter++; }

Consumer

while (true) { while (counter == 0) ; /* do nothing */ next_consumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; counter--; /* consume the item in next consumed */ }

Can processes be executed Concurrently?

yes


Related study sets

Computer Science Fundamental Principles Vocabulary - Unit #8

View Set

Chemical and Physical Properties

View Set

Chapter 21 Active Reading Guide: The Evolution of Populations

View Set

Microbiology Chapter 8.4-8.5 Pre-Lecture Assignment

View Set

Week 2: Readings from Grammar Lab: Guide to Grammar Website: Subjects, Predicates, Objects, Complements, Noun Phrases, Prepositional Phrases, Appositive Phrases, Absolute Phrases, Gerund Phrases, Participial Phrases, and Infinitive Phrases

View Set

AWS Certified Solutions Architect Associate

View Set