COMP 3511: Lecture 16
Date: 2024-10-29 15:02:18
Reviewed:
Topic / Chapter:
summary
βQuestions
- β if we can analyze deadlock given RAG?
- π¨βπ« yes, given particular RAG: we can identify the deadlock
- then, is it possible to check all possible states of a program
- π¨βπ« theoretically, yet not feasible
- β in EVM / distributed system, how can we apply similar tactics?
- e.g. smart contracts also apply similar idea (e.g. mutex) to prevent reentrancy
- how can we coordinate it across multiple computers? Do we consider each computer as a core?
- π¨βπ« we still consider each computer core as individual cores
- π¨βπ« we can't even work it out for a single computer, how can we do so for entire network?
- overhead will be too much: 10 ~ 20 times slower
- we usually do something similar to deadlock detection
- β Rust utilizes advanced compiler to ensure that there is no memory leak, runtime error, etc.
- can we do similar to programs, so that there won't be issues?
- π¨βπ« too complex, it won't be feasible
- π¨βπ it would be to compress all as a docker-like gigantic and atomic multi-core process
- can we really call that as a single process at this point?
- β Is deadlock detection somewhat similar to garbage collector?
- in that they check problem regularly
- π¨βπ« yes
Notes
Deadlocks
-
Deadlock in multi-threaded application
- order of threads running: depending on CPU scheduler
- identifying testing deadlocks: hard
- as they may occur only under certain scheduling circumstances
- example code
code
- deadlock with lock ordering
void transaction(Account from, Account to, double amount) { mutex lock1, lock2; lock1 = get_lock(from); lock2 = get_lock(to); acquire(lock1); acquire(lock2); withdraw(from, amount); deposit(to, amount); release(lock2); release(lock1); }
- transactions: execute concurrently
- 1 transferring 25 from A to B, 2 transferring 50 from B to A
- π¨βπ« we can have deadlock among any no. of processes (not just 2)
- order of threads running: depending on CPU scheduler
-
System model
- system:consist of resources
- resource types:
- : no. of types of resources
- not no. of resources
- e.g. CPU cycles, memory spaces, files, IO devices, semaphores...
- : no. of types of resources
- each resource type : w/ instances
- each process : utilizes a resource as follows
- request
- use
- release
-
Deadlock characterization
- deadlock involving multiple processes: arise if following 4 conditions hold simultaneously
- necessary to not sufficient conditions
- π¨βπ« sufficient condition not known
- mutual exclusion: only ne process at a time: can use a resource
- hold and wait: a process holding a resource, waiting to acquire additional resource (held by anther)
- no preemption: resource: can be released only voluntarily by process holding it
- circular wait: set of waiting process s.t.
- waiting for resource held by
- and for
- if there is dead lock -> conditions hold
- is any of the condition doesn't hold -> no dead lock
- deadlock involving multiple processes: arise if following 4 conditions hold simultaneously
-
Resource-allocation graph
- let graph
- : partitioned into two types
- bipartite!
- : set of all processes in system
- : set of all resource types in system
- request edge: directed edge
- π¨βπ please give me this resource!
- assignment edge: directed edge
- π¨βπ this resource belong to xxx!
- example
- 1 instance of
- 2 instances of
- 1 instance of
- 3 instance of
- : holds one and waiting for
- : holds one , one , waiting for
- : holding one
- π¨βπ« no circular wait: no deadlock (for this instance / snapshot)
- example, with deadlock
- cycles exist:
- processes : deadlocked
- graph with a cycle, yet no deadlock
- cycles exist, yet no deadlock
- basic facts
- if a graph has no cycle: no deadlock
- if a graph contains a cycle: system may / may not be in a deadlocked state
- if only one instance per resource type: then deadlock
- if several instances per resource type: possibility of deadlock
Deadlock handling
-
Methods for handling deadlocks
- ensure that: system will never enter a deadlock state
- deadlock prevention: ensure at least one of the necessary conditions cannot hold
- deadlock avoidance: requires additional information
- given in advance, concerning
- deadlock detection: allow system to enter a deadlock state
- periodically detect: if there is a deadlock & recover from it
- π¨βπ ~= garbage collector?
-
- ensure that: system will never enter a deadlock state
-
Deadlock prevention
- mutual exclusive: unavoidable
- some resources: cannot be shared!
- hold & wait: must guarantee: whenever a process request a resource, it doesn't hold any other resources
- require: each process to request and allocated all its resources before execution
- request resources only when process: has none
- disadvantages: low resource utilization, possible starvation
- require: each process to request and allocated all its resources before execution
- no preemption:
- preempt resource occupied by another resource
- preempted resource: added to waiting resource
- process: will be restarted only if all its old resources are regained
- only for resources w/ state being easily saved & restored
- e.g. registers, memory space, and DB transactions
- cannot be generally applied ro resource (e.g. locks, semaphore)
- preempt resource occupied by another resource
- circular wait: impose total ordering of all resource types
- require: each process requests resources in an increasing order of enumeration
- thus: must request before if
- can be proved by contradiction
- let: set of processes involved in circular wait:
- : awaiting for , held by process
- : waiting for held by
- implies:
- : impossible
- thus, there can be no circular wait
- π¨βπ« same problem as hold & wait: very slow
- problem: request resource much earlier than needed / expected
- require: each process requests resources in an increasing order of enumeration
- mutual exclusive: unavoidable
-
Circular wait example
- invalidating circular wait condition: most common
- assign each resource (i.e. mutex locks): unique number
- resources: must be acquired in order
- code
first_mutex = 1 second_mutex = 5
- invalidating circular wait condition: most common
-
Deadlock avoidance
- requires: system w/ additional a priori information available
- e.g. w/ knowledge of complete sqe. of request and release for each process
- system: can decide for each request whether process should wait to avoid a possible future deadlock
- simples & most useful model:
- requiring each process declaration on max no. of resources of each type
- that it might need (worst case)
- deadlock avoidance algorithm: dynamically examining resource-allocation state
- de ensure: circular-wait condition can never exist
- e.g. w/ knowledge of complete sqe. of request and release for each process
- resource allocation state: defined by
- available resources
- allocated resources
- max demand of processes
- requires: system w/ additional a priori information available
-
ββ Safe state
- when a process: request an available resource
- system: must decide whether allocation will leave system in safe state
- system: in safe state if there exists a safe sequence consisting all processes in systems
- s.t. for each , resource can still request:
- can be satisfied by currently available resources + resources held by all for
- i.e. can be freed by execution of
- π¨βπ« : not waiting for anybody
- can be satisfied by currently available resources + resources held by all for
- π¨βπ« procedure: find s.t. it can be executed w/o any need for waiting
- s.t. for each , resource can still request:
- i.e. if : resource needs not immediately available:
- : can wait until all have finished
- when finished: obtain needed resources, execute, return allocated resources & terminate
- when terminates, : obtain needed resources, and so on
- if no such seq. exist: system state is unsafe
- π¨βπ« not saying that there must be a deadlock
- i.e. no immediate solution found!
- β basic facts
- if system is in safe state: no deadlocks
- if a system is in unsafe state: possibility of deadlock
- when a process: request an available resource
Algorithms
-
Avoidance algorithms
- single instance of a resource type
- use resource allocation graph
- multiple instances of a resource type
- use Banker's algorithm
- single instance of a resource type
-
Resource-allocation graph scheme
- simply check: whether there exists a cycle
- π¨βπ« if so: deadlock!
- simply check: whether there exists a cycle
-
Banker's algorithm
- multiple instances
- each process: must declare priori maximum usage
- if resulting state is unsafe: don't allocate resource!
- when process requests a resource: wait
- check if: allocation result in a safe state / not
- when process
- similar to banking loan system
-
Data structure for Banker's algorithm
- : no. of processes, : no. of resources types
- available: vector of length
- if
available[j] = k
, then instances of type available
- if
- max: matrix
- if
Max[i,j] = k
, then may request at most instances of
- if
- allocation: matrix
- if
Allocation[i,j] = k
, currently allocated instance of
- if
- need: matrix
- if
Need[i,j] = k
, then may need more instances of tom complete tasks - ββ
Need[i,j] = Max[i, k] - Allocation[i, j]
- maximum s.t. process can request additionally
- ensure: the accumulated request doesn't exceed maximum
- i.e. check validity / legitimacy
- ensure: the accumulated request doesn't exceed maximum
- if
- π¨βπ« above properties: defines snapshot
-
Safety algorithm
- input: state
- let work & finish: vectors of length
- initialize:
Work = Available
Finish[i] = false
fori β [0, n-1]
- initialize:
- find s.t. both
Finish[i] = false
Need_i β€ Work
Work = Work + Allocation_i
Finish[i] = true
- go to step 2
- if
Finish[i] == true
for all : system is in a safe state- otherwise, unsafe
-
Resource-request algorithm for process
- input: request
- request: request vector for process