109 lines
1.9 KiB
Markdown
109 lines
1.9 KiB
Markdown
|
|
### Hardware primitives
|
|
Atomic R/W registers provide quite a basic computational model.
|
|
|
|
We can strenghten the model by adding specialized HW primitives, that essentially perform in an atomic way the combination of some atomic instructions.
|
|
Usually, every operating system provides at least one specilized HW primitive.
|
|
|
|
##### Most common ones:
|
|
- **Test&set:** atomic read+write of a boolean register
|
|
- **Swap:** atomic read+write of a general register (generalization of the above)
|
|
- **Fetch&add:** atomic read+increase of an integer register
|
|
- **Compare&swap:** tests the value of a general register, returns a boolean (result of the comparison, true if it is the same).
|
|
|
|
#### Test&Set
|
|
```
|
|
Let X be a boolean register
|
|
|
|
X.test&set() :=
|
|
tmp <- X
|
|
X <- 1
|
|
return tmp
|
|
|
|
(the function is implemented in an atomic way by the hardware by suspending the interruptions!)
|
|
```
|
|
|
|
###### How do we use it for MUTEX?
|
|
```
|
|
lock() :=
|
|
wait X.test&set() = 0
|
|
return
|
|
|
|
|
|
unlock() :=
|
|
X <- 0
|
|
return
|
|
```
|
|
|
|
|
|
#### Swap
|
|
```
|
|
X general register
|
|
|
|
X.swap(v) :=
|
|
tmp <- X
|
|
X <- v
|
|
return tmp
|
|
```
|
|
|
|
###### How do we use it for MUTEX?
|
|
```
|
|
lock() :=
|
|
wait X.swap(1) = 0
|
|
return
|
|
|
|
unlock() :=
|
|
X <- 0
|
|
return
|
|
```
|
|
|
|
#### Compare&swap
|
|
```
|
|
X boolean register
|
|
|
|
X.compare&swap(old, new) :=
|
|
if X = old then
|
|
X <- new
|
|
return true
|
|
return false
|
|
```
|
|
###### How do we use it for MUTEX?
|
|
```
|
|
Initialize X at 0
|
|
|
|
lock() :=
|
|
wait X.compare&swap(0, 1) = true
|
|
return
|
|
|
|
unlock() :=
|
|
X <- 0
|
|
return
|
|
```
|
|
|
|
#### Fetch&add
|
|
Up to now, all solutions enjoy deadlock freedom, but allow for starvation. So let's use Round Robin to promote the liveness property!
|
|
|
|
Let X be an integer register; the Fetch&add primitive is implemented as follows:
|
|
```
|
|
X.fetch&add(v) :=
|
|
tmp <- X
|
|
X <- X+v
|
|
return tmp
|
|
```
|
|
|
|
###### How do we use it for MUTEX?
|
|
```
|
|
Initialize TICKET and NEXT at 0
|
|
|
|
lock() :=
|
|
my_ticket <- TICKET.fetch&add(1)
|
|
wait my_ticket = NEXT
|
|
return
|
|
|
|
unlock() :=
|
|
NEXT <- NEXT + 1
|
|
return
|
|
```
|
|
|
|
>[!info} It is bounded bypass with bound n-1
|
|
|