Claiming the ability to deploy across multiple platforms is one thing, implementing it is
another. MASCOT approaches this problem by defining the concept of the MASCOT
Machine which virtualizes synchtonization primitives so that they are neither operating
system or language dependent. MASCOT Machines may be either bare (in the form of a
kernel executive) or hosted (implemented on some other OS or platform), static (fixed
structure) or dynamic (capable of loading and running new MASCOT systems), and can
implement various commands to control a system while it is running. In all cases a
MASCOT Machine will implement Control Queues which are its sole synchronization
structure. MASCOT Machines provide mechanisms for creating and maintaining a pool of
Control Queues and implement four primitive (relative to the Machine itself) operations on
these structures:
•Join()
Become the owner of a Control Queue. There are 2 forms of the operation,
blocking and non-blocking. In the case of a blocking call the calling thread will
suspend until it becomes owner of the Control Queue.
•Leave()
Relinquish ownership of a Control Queue. It is an error for a thread to attempt to
Leave() a Control Queue it does not own.
•Wait()
The calling thread is suspended until the Control Queue receives a Stim(). It is
an error for a thread to attempt to wait on a Control Queue it does not own.
•Stim()
If a thread is waiting, release it to run. Stims are sticky; an unused Stim() will
remain until the next Wait() regardless of whether the Control Queue changes
owners. Stims are also boolean; once a Stim() is posted on a Control Queue
further stims have no effect until a wait is processed.
The implementations of MASCOT entities are, by definition, constrained to use only
Control Queues and their associated primitives for synchronization. In particular, IDAs
use these calls; the following inset shows a pseudo-code implementation of a simple FIFO
channel:
ControlQueue reader;
ControlQueue writer;
ConttolQueue lock;
int readCount = 0;
int writeCount = 0;
<some array of Element values>
Element read(){
Join( reader );
if( readCount>=writeCount ){
Wait( reader );
}
readCount++;
Leave(reader);
Join( lock );
<retrieve an Element>
Leave( lock );
return Element;
}
write( Element ){
Join( lock );
<add Element to the channel>
Leave( lock );
Join( writer );
writeCount++;
Leave( writer );
Stim( reader );
}