# Claims about Cached Opsem
## Background
Let us first define the following types
```
PermScore: [0,1]
Register: String
Address: Natural
Location -> Register | Address
M : Location -> Address, (Parent, PermScore)
```
Each Pointer (in a register or memory) has a `PermScore` between [0, 1].
- A score of 1 means sole access to the memory location it points to -- hence read-write access.
- A score of 0 implies that the pointer is dormant - it points to a memory location but cannot read or write.
- A score between 0 and 1 means that the pointer can read but not write memory.
Our first claim is:
**Claim 1** An allocated memory region has a total `PermScore` of 1.0 distributed between all pointers to the memory region.
Proof:
Assume `alloc` creates a pointer with `PermScore` 1.0 and `ps: Location -> [0,1]`.
```
{ps(p) == 0} ---- (0)
alloc(p, sz)
{ps(p) == 1}
```
Now if we can prove that all operations on pointers distribute `PermScore` between pointers to the same location then we can prove Claim 1. The different operations are:
1. `alloc`;
2. `brreg2reg`;
3. `brmem2reg`;
4. `brmem2reg_ro`;
5. `mvmem2reg`;
6. `mvreg2mem`;
7. `die`.
We write our goal as:
**Claim 1.1** All operations on pointers maintain Claim 1.
Proof:
Let us define the following invariants.
```
{ps(taker) == 0, ps(giver) = X, 0 <= X <= 1} ---- (1)
takePerm(giver, taker)
{ps(giver) == 0, taker == X}
{ps(giver) == X, ps(taker) = Y, 0 <= X + Y <= 1} ---- (2)
returnPerm(giver, taker)
{ps(giver) = 0, ps(taker) = X + Y}
{ps(giver) == X, ps(taker) = 0, 0 <= X <= 1} ---- (3)
splitPerm(giver, taker)
{ps(giver) = X/2, ps(taker) = X/2}
```
Let us now look at how each operation holds Claim 1. Once we show that all of them hold, then inductively the claim will hold in any valid program.
#### p1, q0 = brreg2reg p0
```
To prove:
{ps(p1) == 0, ps(q0) == 0, ps(p0) == 1 }
brreg2reg(p0, q0, p1)
{ps(p1) == 0, ps(q0) == 1, ps(p0) == 0 }
Operationally `brreg2reg` does the following
1. takePerm(p0, q0)
Solving for ?:
Thus {ps(p1) == 0, ps(q0) == 0, ps(p0) == 1 } takePerm(p0, q0) {?}
Using (1) we can rewrite as
{ps(p1) == 0, ps(q0) == 0, ps(p0) == 1 } takePerm(p0, q0) {ps(p1) == 0, ps(q0) == 1, ps(p0) == 0}
```
#### m1, q0 = brmem2reg pp0, m0
```
To prove:
{ps(m0[pp0]) == 1, ps(q0) == 0 }
brmem2reg(q0, pp0, m0) -> m1
{ps(m0[pp0]) == 0, ps(q0) == 1, ps(m1[pp0]) == 0 }
Operationally `brmem2reg` does the following
1. takePerm(m0[pp0], q0)
Solving for ?:
Thus {ps(m0[pp0]) == 1, ps(q0) == 0 } takePerm(m0[pp0], q0) {?}
Using (1) we can rewrite as
{ps(m0[pp0]) == 1, ps(q0) == 0 } takePerm(m0[pp0], q0) {ps(m0[pp0]) == 0, ps(q0) == 1, ps(m1[pp0]) == 0 }
```
#### m1, q0 = brmem2reg_ro pp0, m0
```
To prove:
{ps(m0[pp0]) == X, ps(q0) == 0, 0 <= X <= 1 }
brmem2reg_ro(q0, pp0, m0) -> m1
{ps(m0[pp0]) == 0, ps(q0) == X/2, ps(m1[pp0]) == X/2 }
Operationally `brmem2reg_ro` does the following
1. splitperm(m0[pp0], q0)
Solving for ?:
Thus {ps(m0[pp0]) == X, ps(q0) == 0, 0 <= X <= 1} splitPerm(m0[pp0], q0) {?}
Using (3) we can rewrite as
{ps(m0[pp0]) == X, ps(q0) == 0, 0 <= X <= 1} splitPerm(m0[pp0], q0) {ps(m0[pp0]) == 0, ps(q0) == X/2, ps(m1[pp0]) == X/2 }
```
#### m1 = mvreg2mem pp0, p0, m0
```
To prove:
{ps(m0[pp0]) == 0, ps(p0) == 1 }
mvreg2mem(p1, pp0, m0) -> m1
{ps(m0[pp0]) == 0, ps(p1) == 0, ps(m1[pp0]) == 1 }
Operationally `mvreg2mem` does the following
1. takePerm(p0, m[pp0])
Solving for ?:
Thus {ps(m0[pp0]) == 0, ps(p0) == 1} takePerm(p0, m[pp0]) {?}
Using (1) we can rewrite as
{ps(m0[pp0]) == 0, ps(p0) == 1} takePerm(m0[pp0], q0) {ps(m0[pp0]) == 0, ps(q0) ==0, ps(m1[pp0]) == 1 }
```
#### m1, p1 = mvmem2reg pp0, m0
```
To prove:
{ps(m0[pp0]) == 1, ps(p1) == 0 }
mvmem2reg(p1, pp0, m0) -> m1
{ps(m0[pp0]) == 0, ps(p1) == 1, ps(m1[pp0]) == 0 }
Operationally `mvmem2reg` does the following
1. takePerm(m[pp0], p1)
Solving for ?:
Thus {ps(m0[pp0]) == 1, ps(p1) == 0} takePerm(p0, m[pp0]) {?}
Using (1) we can rewrite as
{ps(m0[pp0]) == 1, ps(p1) == 0} takePerm(m0[pp0], q0) {ps(m0[pp0]) == 0, ps(p1) == 1, ps(m1[pp0]) == 0 }
```
#### die q0
`pr(p) gives the parent of pointer p or None`
```
To prove:
{ps(q0) = X, ps(pr(q0)) = Y, 0 <= X + Y <= 1 }
die (q0, m0) -> m1
{ps(q0) = 0, ps(pr(q0)) = X + Y }
Operationally `die` does the following
1. returnPerm(q0, ps(pr(q0)))
Solving for ?:
Thus {ps(q0) = X, ps(pr(q0)) = Y, 0 <= X + Y <= 1 } returnPerm(q0, ps(pr(q0))) {?}
Using (1) we can rewrite as
{ps(q0) = X, ps(pr(q0)) = Y, 0 <= X + Y <= 1 } returnPerm(q0, ps(pr(q0))) {ps(q0) = 0, ps(pr(q0)) = X + Y }
```
Here Claim 1.1 is proved and therefore Claim 1 is proved.
### More claims
**Claim 2** If a pointer to an allocated region has `PermScore` 1.0 then all other pointers (if any) have `PermScore` 0.
Proof:
By counter example: Let us say we have two pointers A and B where A has a `PermScore` 1.0 and B has `PermScore` > 0.0 then `ps(A) + ps(B) > 1` which violates Claim 1.
**Claim 3** If a pointer to an allocated region has 0.0 < `PermScore` < 1.0 then all other pointers must have 0 <= `PermScore` < 1.0 such that the cumulative `PermScore` is 1.0.
Proof:
By counter example
Let us say there are `n` pointers `p0, ..., pn-1` to a memory location. Let 0.0 < ps(p0) < 1.0 without loss of generality. Now assume there is another pointer pm (0 <= m <=n) such that ps(pm) = 1. Now `ps(p0) + ... + ps(pm) + ... + pn-1 > 1` which violates Claim 1.
**Claim 4** If a pointer to an allocated region has `PermScore` 0.0 then there must be at least one other pointer to the allocated region with `PermScore` > 0.0.
Proof:
We can prove by counterexample.
## Mapping distributed state to centralized state
> Note: This section has different nomenclature than above. It may be read independently modulo proofs for mentioned claims.
The procedure to map distributed state to centralized state follows:
1. The D machine has a single store M_D which maps `Location -> Address * Cache Value * (Parent, PermScore)`. Each Location is (Register | Address) i.e. a union of register file and main memory.
2. To map M_D to <R, M, S, O>, we go through all Locations in M_D. For each key l,
* we copy the corresponding address to either R or M in C.
* we copy the correct cache value to S. If multiple keys map to the same key in S then either the cache value must be the same (since no pointer has RW access as per Claim 3) or only one-of-N pointers is active and its value dominates (Claim 2) .
* similar to cache value, for each l we set the appropriate ownership state in O. That is, either the state is immutably borrowed or uniquely owned.
3. At the end of this construction, the distributed state of D is mapped to the centralized state of C.
## How does the distributed machine know what is the latest value in the centralized machine?
1. Given a pointer P, if ps(P) or ps(M_D[P]) is (0,1] then return cached value else goto step 2.
2. Go through all pointers in memory until another pointer to the same address is found. Goto step 1.
**Claim 5**
Since `PermScore` of all pointers to a memory location cannot be 0.0 as per Claim 4, the recursion will eventually terminate.