If two domains are collaborating and running concurrently there are likely to be times when one must wait until the other has come to some point in its work. I assume shared RAM here for that is often where much of their mutual state lives. One scheme is for each domain to own a cell in shared RAM where it can leave a note to the other when it is blocked. It thereupon becomes ready.
Each domain examines the other’s cell after it has taken any action that might unblock the other. When a domain sees that the other has left a note, it zaps the note and forks the other domain. To reveal bugs it is probably wise to note when the other domain is waiting before beginning to wait yourself. The following sequence in collaborating domains X and Y is to be avoided:
int CS(int v, b, int * lock){ // This block is magically atomic. if(v == *lock) {*lock = b; return -1;} return *lock;}
When X wants the lock it does:
z: if(CS(0, 1, &lock) != -1){ // conflict if(CS(2, 4, &lock) != -1) goto z; y: Wait on wait object. Set wait object’s time value to next year. if(lock == 4) {log("its probably been a year"); goto y;} go to z;}When X is done with the lock it does:
z: if(CS(1, 0, &lock) != -1){ // Y wants this lock. if(CS(4, 0, &lock) != -1) crash; Set wait object’s time value to 0 (long past). }Mutatis mutandis for Y. The somewhat costly invocation of the wait object happens only on lock conflict, not on typical lock usage. A correctness proof might note that