IPDL/Proposal:Shmem access control

From MozillaWiki
Jump to: navigation, search

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

  1. An actor may not grant access that it doesn't have itself
  2. Actors may only voluntarily surrender access rights; an actor may not take away access rights from its partner
  3. No write/write hazards: only one actor may have write access (or have reserved it).
  4. No read/write hazards: one actor cannot have +r while the other has +w
  5. 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