You are on page 1of 68

Concurrency issues

CMPS282 — Fall 2023

Mageda Sharafeddin
mageda.sharafeddin@pu.edu.lb

Computer Science Departmemt


Concurrency P/C Regions Philosophers Transactions

Outline

Overview
Concurrency issues
Producer consumer problem
Producer/Consumer
Critical regions
Mutual exclusion
Peterson
Atomic operations
Dining philosophers
Condition variables
Monitor construct
Transactional memory
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Concurrency

▶ Some segments of code execute simultaneously


▶ Examples: multi-processing, multi-threading
▶ Single processor machines emulate concurrency by iterating
amongst processes and threads
▶ Machines with multiprocessors are really concurrent

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Concurrency in the news

New York Times, 25 April 1989, in an article on new operating


systems for the IBM PC: Real concurrency–in which one program
actually continues to function while you call up and use another–is
more amazing but of small use to the average person. How many
programs do you have that take more than a few seconds to
perform any task?

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Race Conditions

▶ Two processes access shared memory simultaneously


▶ This may result in unexpected results
▶ To avoid race conditions is to prevent trouble in situations
involving shared memory, shared files. Find some way to
prohibit more than one process from reading and writing the
shared data at the same time.
▶ Put in other words, what we need is mutual exclusion.
▶ The part of the program where the shared memory is accessed
is called the critical region or critical section.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Concurrency issues

▶ Deadlocks
▶ Process P0 has resource A and waits for B
▶ Process P1 has resource B and waits for A
▶ Livelocks
▶ Adnan meets Ammar in a narrow corridor
▶ Adnan and Ammar both politely back up
▶ Both move forward thinking the other opened the way
▶ May occur when we try to avoid a deadlock

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

In Order for Concurrent Processes To


Cooperate

▶ No two processes may be simultaneously inside their critical


regions.
▶ No assumptions may be made about speeds or the number of
CPUs.
▶ No process running outside its critical region may block any
process.
▶ No process should have to wait forever to enter its critical
region.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Lock Variables

▶ Consider having a single, shared (lock) variable, initially 0.


When a process wants to enter its critical region, it first tests
the lock. If the lock is 0, the process sets it to 1 and enters
the critical region. If the lock is already 1, the process just
waits until it becomes 0. Thus, a 0 means that no process is
in its critical region, and a 1 means that some process is in its
critical region.
▶ Problem: Suppose that one process reads the lock and sees
that it is 0. Before it can set the lock to 1, another process is
scheduled, runs, and sets the lock to 1. When the first process
runs again, it will also set the lock to 1, and two processes will
be in their critical regions at the same time.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Producer-consumer – 1
Race condition

(a) Producer (b) Consumer


#define N 100
int count = 0;
void producer() { void consumer(){
ItemPtr item; ItemPtr item;
while(true) { while(true) {
item = produce();
if (count == N) sleep(); if (count == 0) sleep();
buffer.insert(item); item = buffer.remove();
count++; count--;
if (count == 1) if (count == N -1)
wakeup(consumer); wakeup(producer);
} } consumeItem(item);
} }

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Producer-consumer - also called the


bounded-buffer problem
Summary of Algorithm

1. The two share a common fixed size buffer


2. The producer keeps producing items until buffer is full
▶ When producer wants to put an item but there is none,
Solution is producer goes to sleep
3. The consumer keeps consuming until buffer is empty
▶ The problem is when the consumer wants to remove an item
but the buffer is empty, Solution is consumer goes to sleep

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Producer-consumer
Summary of Algorithm

4. The producer code will first test to see if count is N. If it is,


the producer will go to sleep; if it is not, the producer will add
an item and increment count.
5. The consumer code is similar: first test count to see if it is 0.
If it is, go to sleep; if it is nonzero, remove an item and
decrement the counter.
6. Each of the processes also tests to see if the other should be
awakened, and if so, wakes it up.
7. Leads to race conditions

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Producer-consumer
Sleep/wakeup problem

1. The consumer finds an empty buffer


2. Before the consumer sleeps, the scheduler decides to stop
running the consumer temporarily and starts the producer
which produces one item, increments count and wakes up the
consumer because the producer already saw the count = 0
value.
▶ The consumer is already awake, so that has no effect. The
wakeup signal is now lost
3. The consumer now sleeps
4. The producer keeps producing until buffer is full, then sleeps
5. End state, both processes are asleep, forever
6. The essence of the problem here is that a wakeup sent to a
process that is not (yet) sleeping is lost.
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Producer-consumer
Solution!!

1. Modify the rules to add a wakeup waiting bit


2. When a wakeup is sent to a process that is still awake, this bit
is set. Later, when the process tries to go to sleep, if the
wakeup waiting bit is on, it will be turned off, but the process
will stay awake.
3. The wakeup waiting bit is a piggy bank for storing wakeup
signals.
4. The consumer clears the wakeup waiting bit in every iteration
of the loop.
5. What if we had three or more processes? One wakeup waiting
bit is insufficient, you might need 8, 32,.. in principle the
problem is still there!
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Critical regions
Mutual exclusion

▶ A critical region is a guarded segment of code


▶ Four conditions are necessary to provide mutual exclusion
1. Safe: Only one process/thread execute critical region code at
a given time
2. Life: The execution of code outside a critical region can not
block another execution
3. Bound: No process/thread should wait forever to enter critical
region
4. No assumptions on speed of execution or CPU count

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Concurrency real life atomic operations


Siblings in a house

▶ Hassan ▶ Zeinab
▶ Checks for bread ▶ -
▶ Goes to market ▶ -
▶ Buys bread ▶ Checks for bread
▶ Happy fridge ▶ Goes to marker
▶ Buys bread
▶ Lots of bread

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Solutions to concurrency issues


Turns

▶ They have to stay alive (Liveness property)


▶ Someone has to buy bread if out of bread
▶ They do not waste money (Safety property)
▶ At most one person buys bread
▶ Zeinab and Hassan decided to take turns
▶ At most one person buys bread

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Solutions to concurrency issues


Turns

▶ They have to stay alive (Liveness property)


▶ Someone has to buy bread if out of bread
▶ They do not waste money (Safety property)
▶ At most one person buys bread
▶ Zeinab and Hassan decided to take turns
▶ At most one person buys bread
▶ Is switching turns enough?
▶ What if Zeinab ran out of money

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Solutions to concurrency issues


Turns

▶ They have to stay alive (Liveness property)


▶ Someone has to buy bread if out of bread
▶ They do not waste money (Safety property)
▶ At most one person buys bread
▶ Zeinab and Hassan decided to take turns
▶ At most one person buys bread
▶ Is switching turns enough?
▶ What if Zeinab ran out of money
▶ What if they leave a note on the fridge
▶ What if both left a note at the same time

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Peterson’s algorithm
Take a turn and leave a note

Process 0 Process 1
flag[0] = 1; flag[1] = 1;
turn = 1;//Hassan turn = 0;//Zeinab
while( flag[1] && while( flag[0] &&
turn == 1 ); turn == 0 );
criticalBuyBread(); criticalBuyBread();
flag[0] = 0; flag[1] = 0;
nonCritical(); nonCritical();

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Full version of Peterson’s algorithm

Process Process Continued


#define FALSE 0 void leave_region(int process)
#define TRUE 1 {
#define N 2 interested[process] = FALSE;
int turn; }
int interested[N]; nonCritical();
void enter_region(int process)
{
int other;
other = 1 - process;
interested[process] = TRUE;
turn =process;
while (turn == process &&
interested[other] == TRUE);
}

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Explanation of Peterson’s Solution

▶ The process that enters the critical region is the one that:
▶ Calls the enter_region with its own process number.
▶ This might cause it to wait if needed.
▶ After finishing with the shared variable, it calls the
leaves_region to allow the other process to enter.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Explanation of Peterson’s Solution

▶ Assume process 0 calls enter region. It indicates its interest by


setting its array element and sets turn to 0. Since process 1 is
not interested, enter region returns immediately. If process 1
now makes a call to enter region, it will hang there until
interested[0] goes to FALSE, an event that happens only when
process 0 calls leave region to exit the critical region.
▶ Now consider the case that both processes call enter region
almost simultaneously. Both will store their process number in
turn. Whichever store is done last is the one that counts; the
first one is overwritten and lost. Suppose that process 1 stores
last, so turn is 1. When both processes come to the while
statement, process 0 executes it zero times and enters its
critical region. Process 1 loops and does not enter its critical
region until process 0 exits its critical region.
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Peterson’s algorithm

▶ Peterson’s works for only two processes


▶ Consumes CPU while waiting
▶ This algorithm is live, safe and deadlock free

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Busy Waiting Disadvantage

▶ Wasting CPU time.


▶ Also called spin lock
▶ Another problem is when one of the processes is much slower
than the other one as shown in next slide.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

What is wrong?

(a) Process 0 (b) Process 1


turn true turn false
critical_region noncritical_region
turn false turn true
noncritical_region but still in
need turn ---> waiting noncritical_region
waiting because
waiting it just happens
waiting to be long

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Busy Waiting Not Suitable for Concurrency

▶ Busy waiting violates the third condition of concurrency which


is: No process running outside its critical region may block
any process.
▶ Note that sleep and wakeup used by the producer-consumer
solution cause a process to be suspended until it is awakened
(so it is blocked and not using CPU). Recall that the problem
was the race condition.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Critical regions
Execution

Mutual exclusion execution using critical regions

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

TSL Instruction
Help from hardware: TSL

▶ Test and Set Lock:


▶ It reads the contents of the memory word lock into register RX
and then stores a nonzero value at the memory address lock.
▶ The operations of reading the word and storing into it are
guaranteed to be indivisible - no other processor can access
the memory word until the instruction is finished.
▶ The CPU executing the TSL instruction locks the memory bus
to prohibit other CPUs from accessing memory until it is done.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

TSL Instruction
How it works

▶ It is important to note that locking the memory bus is very


different from disabling interrupts. Disabling interrupts then
performing a read on a memory word followed by a write does
not prevent a second processor on the bus from accessing the
word between the read and the write. The only way to keep
processor 2 out of the memory until processor 1 is finished is
to lock the bus, which requires a special hardware facility.
▶ To use the TSL instruction, we will use a shared variable, lock,
to coordinate access to shared memory. When lock is 0, any
process may set it to 1 using the TSL instruction and then
read or write the shared memory. When it is done, the process
sets lock back to 0 using an ordinary move instruction.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Critical regions
Implementation with the Test and set lock (TSL) instruction

enter_region:
TSL REGISTER,LOCK | copy lock to register and set lock to 1
CMP REGISTER,#0 | was lock zero?
JNE enter_region | if it was not zero, lock was set, so loop
RET |return to caller; critical region entered

leave_region:
MOVE LOCK,#0 | store a 0 in lock
RET |return to caller

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Critical regions
Implementation with the XCHG instruction

enter_region:
MOVE REGISTER,#1 | put a 1 in the register
XCHG REGISTER,LOCK | swap the contents of the register and lock variable
CMP REGISTER,#0 | was lock zero?
JNE enter_region | if it was non zero, lock was set, so loop
RET | return to caller; critical region entered

leave_region:
MOVE LOCK,#0 | store a 0 in lock
RET | return to caller

▶ Both TSL and XCHG suffer from busy waiting discussed


before.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Atomic operations

Definition
Either all effects of an atomic operation happen, or none happen.

Definition
An atomic operation is an isolated operation that is not affected by
concurrent operations.

▶ Operations on an ATM machines should not interleave


▶ Deposit $500 into an account with $200
▶ Withdraw $500 and no overdraft is allowed

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Atomicity and isolation

▶ Atomicity is difficult to implement


▶ Programs make small changes and even x++; is not atomic
▶ Effects of a failed AO should be invisible
▶ System needs to restore state at the start of the AO
▶ What if we fired a missile? Deposited money into ATM?
▶ Isolation is difficult to implement
▶ System must prevent interleaving of a certain permutation of
events

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Semaphores
An invention by Dijkstra

▶ A semaphore is a guarded Boolean or non-negative integer


variable
▶ The semantics of the value is the number of free resources
▶ Semaphores can be accessed with the following operations
▶ Acquire (P:proberen): down(s) {block or sleep until s>
0; s=s-1;}
▶ Release (V:verhogen): up or wakup(s){s=s+1;}
▶ Initialize:init(s,v){s=v;}
▶ s=s-1, s=v, and s=s+1 must be atomic
▶ If s goes up from 0 to 1 and several processes are sleeping, the
system chooses one at random to complete, the rest continue
their sleep and the queue has one less block process.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Semaphores

▶ The OS briefly disables all interrupts while it is testing the


semaphore, updating it, and putting the process to sleep, if
necessary. As all of these actions take only a few instructions.
▶ If multiple CPUs are being used, each semaphore should be
protected by a lock variable, with the TSL or XCHG
instructions used to make sure that only one CPU at a time
examines the semaphore (this is different from the busy
waiting behavior discussed earlier).

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

More on Semaphore

▶ A system hides interrupts using a semaphore, initially set to 0,


associated with each I/O device. Down for a process to an
I/O device thus blocking rest immediately. The interrupt
handler does Up to let a relevant process ready to run again.
▶ Mutual exclusion (mutex variable): It is designed to guarantee
that only one process at a time will be reading or writing the
buffer and the associated variables. This mutual exclusion is
required to prevent chaos.
▶ Synchronization: guarantee that certain event sequences do or
do not occur. In this case, they ensure that the producer
stops running when the buffer is full (variable), and that the
consumer stops running when it is empty (variable).

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Semaphores versus busy-waiting

▶ The processes spin using CPU cycles while waiting for the
lock
▶ Busy waiting is also known as spinlock
▶ With a semaphore the process can block itself
▶ Waits in a semaphore queue to be called when the semaphore
is available

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Semaphores and producer-consumer

(a) Producer (b) Consumer


#define N 100
semaphore mutex=1;
semaphore empty=N;
semaphore full=0;

void producer() { void consumer(){


ItemPtr item; ItemPtr item;
while(true) { while(true) {
item = produce(); down(&full);
down(&empty); down(&mutex);
down(&mutex); item = buffer.remove();
buffer.insert(item); up(&mutex);
up(&mutex); up(&empty);
up(&full); consumeItem(item);
} } } }
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Explanation of Producer-Consumer

▶ This solution uses three semaphores: one called full for


counting the number of slots that are full, one called empty
for counting the number of slots that are empty, and one
called mutex to make sure the producer and consumer do not
access the buffer at the same time.
▶ Full is initially 0, empty is initially equal to the number of
slots in the buffer, and mutex is initially 1. Semaphores that
are initialized to 1 and used by two or more processes to
ensure that only one of them can enter its critical region at
the same time are called binary semaphores.
▶ If each process does a down just before entering its critical
region and an up just after leaving it, mutual exclusion is
guaranteed.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Producer-consumer ??

(a) Producer (b) Consumer


#define N 100
semaphore mutex=1;
semaphore empty=N;
semaphore full=0;

void producer() { void consumer(){


ItemPtr item; ItemPtr item;
while(true) { while(true) {
item = produce(); down(&full);
down(&mutex); down(&mutex);
down(&empty); item = buffer.remove();
buffer.insert(item); up(&mutex);
up(&mutex); up(&empty);
up(&full); consumeItem(item);
} } } }
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Dining philosophers: models access to IO


devices

Philosopher
semaphore chopstick[5]=
{1,1,1,1,1}; // pseudo

do {
down(chopstick[i]);
down(chopstick([i+1) % 5]);
eat();
up(chopstick[i]);
up(chopstick[(i+1) % 5]);
think();
} while(true);
▶ Do you anticipate any problems?

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Mutexes: Simplified Semaphore

▶ When count is not needed, a mutex is used.


▶ Mutexes manages mutual exclusion per code/variable.
▶ A mutex is a shared variable that can be in one of two states:
unlocked or locked.
▶ When a thread (or process) needs access to a critical region, it
calls mutex lock. If the mutex is currently unlocked (meaning
that the critical region is available), the call succeeds and the
calling thread is free to enter the critical region.
▶ The mutex unlock call releases the mutex. If multiple threads
are blocked on the mutex, one of them is chosen at random
and allowed to acquire the lock.
▶ Because mutexes are so simple, they can easily be
implemented in user space provided that a TSL or XCHG
instruction is available.
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Mutexes in use
Implementation with the Test and set lock (TSL) instruction

mutex_lock:
TSL REGISTER,MUTEX | copy mutex to register and set mutex to 1
CMP REGISTER,#0 | was mutex zero?
JZE ok | if it was zero, mutex was unlocked, so return
CALL thread_yield | mutex is busy; schedule another thread
JMP mutex_lock | try again
ok: RET | return to caller; critical region entered

mutex_unlock:
MOVE MUTEX,#0 | store a 0 in mutex
RET

▶ Different from busy waiting with TSL in that the call to


thread_yield which will block the process. The next time the
process is scheduled, it will check the lock again.
▶ Neither mutex_lock nor mutex_unlock requires any kernel
calls. Using them require only a handful of instructions.
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

More on Mutexes

What if the variables are not in shared address space


(multiprocessor system):
▶ First: shared data structures (semaphores) can be stored in
the kernel and accessed only by means of system calls.
▶ Second: OS offers a way for processes to share some portion
of their address space with other processes.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Condition variables

▶ They provide support for conditional synchronization


▶ Wait on a condition in a critical section
▶ Release lock at the same time
▶ Condition variables and mutexes are always used together.
▶ The pattern is for one thread to lock a mutex, then wait on a
conditional variable when it cannot get what it needs.
▶ Eventually another thread will signal it and it can continue.
▶ It is also worth noting that condition variables (unlike
semaphores) have no memory. If a signal is sent to a condition
variable on which no thread is waiting, the signal is lost.
Programmers have to be careful not to lose signals.
▶ Semaphores make sense to use for situation with some integer
number of available things.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Condition variables — operations

▶ Condition variables allow three operations


1. wait(lock)
▶ Release the lock
▶ Suspends calling thread
▶ Reacquire lock when back
2. signal()
▶ wakes up a suspended thread if any
3. broadcast()
▶ wakes up all suspended threads
▶ Requires a queue for each condition-variable to be
implemented

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Condition variables — example

Producer Consumer
Lock lock;
Condition notFull, notEmpty;

produce() { consume() {
lock.acquire(); lock.acquire();
while(count==N) while(count==0)
notFull.wait(&lock); notEmpty.wait(&lock);
ProduceItem(); ConsumeItem();
count++; count--;
notEmpty.signal(); notFull.signal();
lock.release(); } lock.release();}

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Condition variables
Comparison to semaphores

▶ Semaphores hold a count of available resources


▶ Semaphores can serve mutual exclusion and conditional
synchronization
▶ Harder to read/develop/comprehend
▶ Condition variables do not change state on signal

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Monitor: a high level synchronizer

monitor diningPhilosophers {
enum{think, hungry, eat} ▶ Only one executing function per
state[5] = think[5];
condition me[5]; monitor code
void test(i) { ▶ Wait for neighbors to eat
if (neighbors(i) != eat &&
state[i] == hungry) {
state[i] = eat;
▶ condition can wait and signal
me[i].signal(); ▶ signal different than up as it
} }
void vEat(int i) { does not change the state
state[i] = hungry;
test(i);
if (state[i] != eat)
▶ Problem: starvation
me[i].wait();
}
void vThink(int i) {
state[i] = think;
test(left(i));
test(right(i));
}
}

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Monitors

▶ Because the compiler, not the programmer, is arranging for


the mutual exclusion, it is much less likely that something will
go wrong.
▶ Programmer of the monitor structure does not have to be
aware of how the compiler arranges for mutual exclusion. It is
sufficient to know that by turning all the critical regions into
monitor procedures, no two processes will ever execute their
critical regions at the same time.
▶ A monitor is a composition of a lock and zero or more
condition variables
▶ Encapsulate shared data in an object
▶ Define methods that access data in a monitor
▶ Calling a method is a direct implication of acquiring the lock
▶ AKA synchronized methods in Java
OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Monitors: two possible semantics

▶ Hansen semantics
▶ Hoare semantics 1. Thread T1 waits on C
1. Thread T1 waits on C 2. Thread T2 in the monitor
2. Thread T2 in the monitor 3. T2 calls C.signal() and
3. T2 calls C.signal() wakes up T1
4. T2 gives up monitor and 4. T2 continues and finishes
blocks 5. T1 wakes up, takes over
5. T1 takes monitor, runs monitor
6. T1 gives up monitor 6. T1 runs, completes
7. T2 takes monitor, resumes

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Monitors: compare semantics

▶ Hansen semantics
▶ Hoare semantics ▶ Used in systems
▶ Textbookish, easily ▶ Signal is a hint that
provable condition may be true
▶ Clean ▶ Need to check condition
▶ Implementation is not before resuming
efficient ▶ May introduce buggy
▶ Not easy to get correctness synchronization
▶ Implementation is efficient
▶ Final note on condition variables within monitors: unlike sleep
and wakeup where wakeup could fail because while one
process was trying to go to sleep, the other one was trying to
wake it up. With monitors, that cannot happen.

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Summary

▶ Concurrency necessitates synchronization to coordinate


execution of processes and threads that share data structures
▶ Synchronization concepts
▶ Lock: mutual exclusion
▶ Conditional variable: conditional synchronization
▶ Semaphore: binary and counting semaphores
▶ Supports both mutual exclusion and conditional
synchronization
▶ Monitors: high level synchronization construct
▶ Separates mutual exclusion from conditional synchronization

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Transactional memory
Critical regions: atomicity and isolation

▶ Isolation
▶ Buffer changes to memory
▶ Hide buffers from other processes
▶ Atomicity
▶ On error, reset buffers to value in real memory
▶ On success, commit changes to real memory
▶ We need hardware or OS support for buffering and
committing values

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Operations of transactional memory

▶ xbegin, xend, xrestart


▶ Implicit in atomic{acctA-=100;acctB+=100;}
▶ Safety rules
1. If TA writes data read by another transaction, then TA aborts
2. If TA read data from uncommitted transaction, then TA can
not commit

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Example for transactional memory

produce() { consume() {
atomic { atomic {
if (count == n) { if (count == 0) {
retry; } retry; }
produceItem(); consumeItem();
count++; count--;
} } } }
▶ {RP , WP , RC , WC } Divide address space into Read and
Write categories per transaction
▶ Safe when WP ∩ (RC ∪ WC ) is empty

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

What do we have in the kernel?

▶ An operation is atomic on single processor machines if no


context switch occurs
▶ Atomicity means preventing context switching
▶ Program: no system calls, no exceptions
▶ System: disable (more of delay) interrupts
▶ What if thread persists and does not stop?
▶ Starve other threads
▶ No guarantee on length of critical sections

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Disabling interrupts

▶ Assign levels to interrupts (reset:0, timer:1, network:2, disk:4,


software:7)
▶ Process can only disable iterrupts on its level or higher
▶ Process restores iterrupts of previous levels when done

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Linux entry points

▶ Instruction int 0x80 is the system call instruction


▶ Programmable iterrupt controller (PIC) receives a signal from
a device on an interrupt request (IRQ) line
▶ A process commits a page fault in kernel mode
▶ A process in kernel mode uses IPC
▶ After the interrupt is handled the process resumes

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Linux synchronization constructs

▶ All CPUs
▶ Atomic operations, spin-locks, semaphore, global interrupt
disable
▶ Local CPU
▶ Memory barrier, local interrupt disable, local softIRQ disable
▶ Atomic instructions are
▶ Instructions with no or only 1 aligned memory access (last 2
bits are 0 on a 32-bit address)
▶ Lock prefixed instructions with read, modify, and write access

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Rendezvous problem (Message passing and no


shared memory

Problem Hint
//guarantee that a1 happens before b2 semaphore aArrived(0);
// and b1 happens before a2 semaphore bArrived(0);
Thread A
statement a1

statement a2

Thread B
statement b1

statement b2

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Rendezvous solution

//guarantee that a1 happens semaphore aArrived(0);


// before b2 semaphore bArrived(0);
// and b1 happens before a2

Thread A
statement a1
aArrived.up();
bArrived.down();
statement a2

Thread B
statement b1
bArrived.up();
aArrived.down();
statement b2

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Barrier problem: relaxation problem in


physics

// rendezvous does not work Hint


// for more than 2
// // N is the number of threads
// all threads execute int count = 0;
// rendezvous and wait for semaphore mutex(1);
// each other before executing semaphore barrier(0);
// critical

Thread
rendezvous
critical section

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Barrier solution
AKA turnstile

Hint
Thread // N is the number of threads
rendezvous int count = 0;
mutex.down(); semaphore mutex(1);
count++; semaphore barrier(0);
if (count == n) barrier.up();
mutex.up();
barrier.down(); // is it ok to read count?
barrier.up();
critical section
mutex.down();
count--; // how many times do we signal?
if (count == 0) barrier.down();
// What if we want to reuse the
mutex.up();
// barrier?

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Dance floor problem


Leaders and followes

Leader Hint
wait for follower
dance(); leaderQ wait/signal;
followerQ wait/signal;

Follower
wait for leader
dance();

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Dance floor problem


Leaders and followers

Leader Follower
followerQ.signal(); leaderQ.signal();
leaderQ.wait(); followerQ.wait();
dance(); dance();

▶ In essence this is a Rendezvous solution

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Readers writers problem: models database


access

// Writer can not edit Hint


// if any other is in thread
int readers = 0;
// Reader can not read semaphore mutex(1);
// if a writer is in thread semaphore db(1);

OS Phoenicia University
Concurrency P/C Regions Philosophers Transactions

Readers writers solution

Writer Reader
semaphore mutex = 1; void reader(void)
semaphore db = 1; {
int rc = 0; while (TRUE) {
void writer(void) down(&mutex);/*protect rc*/
{ rc = rc+1;
while (TRUE) { if (rc == 1) /*first reader*/
no_critical_region( ); down(&db);
down(&db); up(&mutex);
write_database( ); read_database();
up(&db); down(&mutex);
} rc = rc-1;
} if (rc == 0) /*last reader*/
up(&db);/*all done,release*/
up(&mutex);
non_critical_region();
}
}
OS Phoenicia University

You might also like