IPDL/Proposal:Shmem access control
Optional fine-grained access change for Shmem
New syntax
['[' access '|' access ']'] Shmem
|access| can be one of
. +r -r +w -w +r+w +r-w -r+w -r-w
The first |access| specifier refers to my side's shmem access after sending the Shmem in a message. So |+r-w| would mean my side retains read privileges and gives up write priveleges.
The second |access| specifier refers to the other side's shmem access after receiving the Shmem in a message. So |+w| would mean that the other side is granted write privileges.
Fine-grained access change is optional. If no access change is specified, then it defaults to |[-r-w|+r+w]|, which is what is currently implemented.
An actor may take away particular access from itself without granting it to the other actor. This could be called a "reserved" right. The actor may later grant it to the other actor, or grant it to itself. For example
[-w|+r] Shmem // reserve write access for myself, but only grant read access to the other actor
The access change must adhere to the rules
- An actor may not grant access that it doesn't have itself
- Actors may only voluntarily surrender access rights; an actor may not take away access rights from its partner
- No write/write hazards: only one actor may have write access (or have reserved it).
- No read/write hazards: one actor cannot have +r while the other has +w
- Shmem "chmod" messages may not race. (It's rather difficult, but possible, to guarantee that access bits stay consistent and hazard free. Deferring.)
The IPDL compiler can only sanity check transfers; it can't do full checking statically, since it doesn't know about "particular" shmem instances. The dynamic check is basically free, though.
drawWindow Example
Protocol
sync protocol PDrawWindow { child: Init([-w |+r ] Shmem[] front, [-r-w|+r+w] Shmem[] back); parent: sync Drew([-r |. ] Shmem[] dirtyFronts, [-r-w|+r+w] Shmem[] dirtyBacks, DirtyRects[] damage, ...) returns ([-r-w|+r+w] Shmem[] newBacks, [-w |+r ] Shmem[] newFronts, ...); state START: send Init goto DRAWING; state DRAWING: recv Drew goto DRAWING; };
Timeline in C++
chrome content ----------------------------------------- --------------------------- // --- Init sequence --- front = AllocShmem() [recv ShmemCreated()] // front: rw rights // front: no rights back = AllocShmem() [recv ShmemCreated()] // back: rw rights // back: no rights // draw default background into |front| SendInit(front, back) recv Init(front, back) // front: r, w reserved // front: r // back: no rights // back: rw
// --- Steady state ---- // draw stuff SentDrew(front, back, &back, &front, dirtyRects) // front: no rights // back: no rights recv SendDrew(front, back, ...) // front: r, w reserved // back: rw swap(front, back) reply Drew(back, front) // front: r, w reserved // back: no rights recv ReplyDrew(back, front) // render |front| to screen // back: rw // front: r // blit |front| changes into |back| using dirtyRects
// draw stuff, repeat