Non-Deadlock Bugs
Atomicity violation
- Desired serializability among multiple memory accesses is violated
- Two different threads access the field
proc_info

- Solution
Order violation
- Desired order between two memory accesses is flipped
- A should be executed before B, but the order is not enforced during execution
- Thread2 assumes that the variable
mThread has already been intialized

- Solution
- Enforce ordering using condition variables
Deadlock
Deadlock
Conditions for deadlock
- Mutual exclusion
- Only one process can hold resources
- Hold and wait
- A process holding a resource can block, waiting for another resource
- No preemption
- One process cannot force another to give up a resource
- Circular wait
- Given conditions 1~3, if there is a circular wait, then there is potential for deadlock
- Buggy programming
- Programmer forgets to release resource
Circular Waiting
- Thread 1 holds lock a, waits on lock b
- Thread 2 holds lock b, waits on lock a

Methods for Handling Deadlocks
- Ensure that the system will never enter a deadlock state
- Deadlock prevention
- Deadlock avoidance
- Allow the system to enter a deadlock state and then recover
- Ignore the problem and pretend that deadlocks never occur
- Handling the deadlocks has large overhead
so that ignore the problem
Deadlock Prevention
Idea: If one condition is not met, deadlock does not occur
- Mutual Exclusion
- Not required for sharable resources (read-only files)
- Hold and Wait
- Must guarantee that whenever a process requests a resource,
it does not hold any other resources
- Require process to request and be allocated all its resources before it begins execution,
or allow process to request only when the process has none allocated to it
- Low resource utilization, starvation possible
- Do not request during execution
Allocate all resources before execution
- No Preemption
- If a process that is holding some resources requests resources that can not be immediately allocated,
then all resources currently being held are released
- Preempted resources are added to the list of resources for which the process is waiting
- Process will be restarted only when it can regain its old resources
- Circular Wait
Lock Ranking
To prevent circular wait
- Locate all locks in the program
- Number the locks in the order that they should be acquired
- Add assertions
- No automated way of doing
- Requires careful programming by the developers
Example
- Rank the locks
- Enforce rank ordering
- Before lock B, check islocked(A)
- Thread 2 assertion will fail

When Ranking doesn't work
- In some cases, impossible to rank order locks
- Eliminate no preemption condition using
trylock()
- if
trylock() succeed, break the while loop
- if
trylock() fail, unlock and loop the while

Deadlock Avoidance
Assumption
- Each process declare the maximum number of resources
- Examine the resource allocation state to ensure that there can never be a circular-wait condition
- Resource aloocation state is defined by the number of available and allocated resources, and the maximum demands of the processes
Safe State
- System is in safe state
if there exists a sequence of all the process in the systems
that can be excuted without blocking
- Behavior
- If Pi's resource needs are not immediately available, Pi wait
- When other process is finished, Pi can obtain needed resources, execute
- When Pi terminates, Pi+1 can obatin its needed resources, execute
- Basic
- If a system is in safe state => no deadlocks
- If a system is in unsafe state => possibility of deadlock
- Avoidance => ensure that a system will never enter an unsafe state
Avoidance Algorithms
Resource allocation graph
Single instance of a resource
- Claim edge Pi→Rj: process Pi may request resource Rj
- Claim edge converts to request edge when a process requests a resource
- Request edge converts to assignment edge when the resource is allocated
- When a resource is released, assignment edge reconverts to a claim edge
Safe state
- P1 gets R2, execute, terminate
- P2 gets R1,R2, execute, terminate

Unsafe state
- In this case, avoidance indicates that make P1 can not request R2
- If requested, deadlock occurs

Banker's algorithm
Multiple instances of a resource
- Each process must a priori claim maximum use
- When a process gets all its resources, it must return them in a finite amount of time
Data structures for the Banker's algorithm
- Available
- Vector of length m
- If available [j]=k, there are k instances of resource Rj available
- Max
- n×m matrix,
- Max[i,j]=k, Pi may request at most k instances of resource Rj
- Allocation
- n×m matrix,
- Allocation[i,j]=k, Pi is currently allocated k instances of resource Rj
- Need
- n×m matrix,
- Need[i,j]=k, Pi may need k more instances of resource Rj to complete task
- Need = Max - Allocation
Behavior
- First, allocate resources and check whether it's safe state or unsafe state
- If safe => allocate resources
- If unsafe => old resource allocation state is restored
Example 1)
- System is in a safe state since the sequence <P1,P3,P4,P2,P0> satisfies safety criteria

Example 2)
- P1 request (1,0,2)
- (1,0,2)≤(3,3,2) => available
- the sequence <P1,P3,P4,P2,P0> satisfies safety criteria

Detection Algorithm
Allow system to enter deadlock state
Detection algorithm
- Resouce allocation graph
- Banker's algorithm
Recovery scheme
- Avoidance checks every requests -> overhead ↑
- Allow requests -> detect -> overhead ↓
Resource allocation graph and wait-for graph
Single instance of a resource
- Nodes are processes
- Pi→Pj if Pi is waiting for Pj
- Periodically invoke an algorithm that searches for a cycle in a graph
- If there is a cycle, there exists a deadlock
- O(n2) operations

Recovery from deadlock: Process termination
- Abort all deadlocked processes
- Abort one process at a time
Selecting a victim - minimize cost
Rollback - return to some safe state, restart process for that state
Starvation problem
- Same process may always be picked as victim, include number of rollback in cost factor