-- SakuraRTImpl.mesa
-- last edited by Suzuki: 19-Apr-82 10:06:27
DIRECTORY
MOSSIMFns USING [assignArg, initializationResult, readFileString,
setInputH, setInputL, setInputX, targc],
SakuraRT,
Process,
Rope,
RandomCard,
SimStep,
SimTsim USING [boolvalue, nptr, pchars, pnode, ufind],
stdio,
Storage,
TTY;
SakuraRTImpl: MONITOR
IMPORTS MOSSIMFns, RandomCard, SimStep, SimTsim, stdio, Storage, Process, TTY
EXPORTS SakuraRT = {
Node: PUBLIC TYPE = RECORD [
value: REF ANY,
cond: CONDITION,
waitingArrayLength: CARDINAL ← 0,
waiting: POINTER TO ARRAY OF LONG POINTER TO CONDITION ← NIL,
port: REF Port,
max: CARDINAL ← 0,
body: SEQUENCE size: [0..LAST[INTEGER]] OF RECORD [
choice: PrivateChoice,
response: CARDINAL,
direction: {Up, Down, Change}]
];
PrivateHandle: TYPE = REF Node;
Port: TYPE = RECORD [
body: SELECT size: {Single, Multiple} FROM
Single => [handle: SimTsim.nptr],
Multiple => [handle: REF PortSequence],
ENDCASE];
PortSequence: TYPE = RECORD[SEQUENCE size: [0..LAST[INTEGER]] OF SimTsim.nptr];
ChoiceNode: PUBLIC TYPE = RECORD [
response: CARDINAL,
cond: CONDITION];
PrivateChoice: TYPE = REF ChoiceNode;
TooManyWaiting: SIGNAL = CODE;
OutOfBounds: ERROR = CODE;
Assign: PUBLIC PROC [cond: LONG POINTER TO CONDITION, h:PrivateHandle]
RETURNS [CARDINAL] = {
IF h.waiting=NIL THEN {
h.waiting ← Storage.Node[20];
h.waitingArrayLength ← 10;
FOR i: NAT IN [0..10) DO
h.waiting[i] ← NIL ENDLOOP};
FOR i: NAT IN [0..10) DO
IF h.waiting[i]=NIL THEN {h.waiting[i] ← cond; RETURN[i]};
REPEAT
FINISHED => SIGNAL TooManyWaiting
ENDLOOP;
RETURN[0]};
CreateChoice: PUBLIC PROC RETURNS [PrivateChoice] = {
choice: PrivateChoice ← NEW[ChoiceNode];
Process.EnableAborts[@choice.cond];
Process.DisableTimeout[@choice.cond];
RETURN[choice]};
RegisterUp: PUBLIC PROC [choice: PrivateChoice, retValue: CARDINAL, port: PrivateHandle] = {
port.body[port.max] ← [choice, retValue, Up];
port.max ← port.max+1};
Remove: PUBLIC PROC [loc: CARDINAL, h: PrivateHandle] = {
IF loc>=h.waitingArrayLength THEN ERROR OutOfBounds;
h.waiting[loc] ← NIL};
GetChoice: PUBLIC PROC [choice: PrivateChoice] RETURNS [CARDINAL] = {
Wait[@choice.cond];
RETURN[choice.response]};
Create: PUBLIC PROC [size: CARDINAL] RETURNS [ret: PrivateHandle] = {
ret ← NEW[Node[size]];
Process.EnableAborts[@ret.cond];
Process.DisableTimeout[@ret.cond]};
Put: PUBLIC PROC [n: PrivateHandle, v: REF ANY] = {
-- WF.WF1["Put S:%u ", v];
CheckAbort[];
StuffIt[n, v];
WakeUp[n];
-- StandardDelay[];
Process.Yield[];
-- WF.WF0["Put F "]
};
Stuff: PROC [n: PrivateHandle, v: REF ANY] = {
-- WF.WF1[" Stuff S:%b ", v];
StuffIt[n, v];
WakeUp[n];
Process.Yield[];
-- WF.WF0[" Stuff F "]
};
StuffIt: ENTRY PROC [n: PrivateHandle, v: REF ANY] = {
ENABLE UNWIND => NULL;
n.value ← v};
Place: PUBLIC PROC [n: PrivateHandle, v: REF ANY] = {
CheckAbort[];
StuffIt[n, v];
};
Get: PUBLIC PROC [n: PrivateHandle] RETURNS [ret: REF ANY] = {
-- WF.WF0[" Get S "];
CheckAbort[];
ret ← GrabIt[n];
UNTIL ret#NIL DO
StandardDelay[];
ret ← GrabIt[n];
ENDLOOP;
Process.Yield[]
-- StandardDelay[];
-- WF.WF0[" Get F "]
};
GetCard: PUBLIC PROC [tree: PrivateHandle] RETURNS [CARDINAL] = {
RETURN[NARROW[Get[tree], REF CARDINAL]↑]};
GetBool: PUBLIC PROC [tree: PrivateHandle] RETURNS [BOOLEAN] = {
RETURN[NARROW[Get[tree], REF BOOLEAN]↑]};
Grab: PUBLIC ENTRY PROC [n: PrivateHandle] RETURNS [ret: REF ANY] = {
ENABLE UNWIND => NULL;
-- WF.WF0[" Grab S"];
CheckAbort[];
ret ← n.value;
-- WF.WF0[" Grab F "]
};
GrabIt: ENTRY PROC [n: PrivateHandle] RETURNS[ret: REF ANY] = {
ENABLE UNWIND => NULL;
ret ← n.value};
GetNew: PUBLIC PROC [n: PrivateHandle, v: BOOLEAN] = {
-- WF.WF1[" GetNew S:%b ", v];
CheckAbort[];
StandardDelay[];
GetNewBody[n, v];
-- WF.WF0[" GetNew F"]
};
GetNewChange: PUBLIC PROC [n: PrivateHandle] = {
CheckAbort[];
Wait[@n.cond]
};
GetNewBody: ENTRY PROC[n: PrivateHandle, v: BOOLEAN] = {
ENABLE UNWIND => NULL;
DO
WaitInternal[@n.cond];
IF v=NARROW[n.value, REF BOOLEAN]↑ THEN EXIT;
ENDLOOP;
};
WakeUp: ENTRY PROC [h: PrivateHandle] = {
ENABLE UNWIND => NULL;
BROADCAST h.cond;
FOR i: NAT IN [0..h.waitingArrayLength) DO
IF h.waiting[i]#NIL THEN BROADCAST h.waiting[i]↑;
ENDLOOP;
FOR i: NAT IN [0..h.max) DO
IF (SELECT h.body[i].direction FROM
Change => TRUE,
Up => NARROW[h.value, REF BOOLEAN]↑,
Down => NOT NARROW[h.value, REF BOOLEAN]↑,
ENDCASE => FALSE) THEN {
h.body[i].choice.response ← h.body[i].response;
BROADCAST h.body[i].choice.cond};
ENDLOOP;
};
SIMGet: PUBLIC PROC [node: PrivateHandle] = {
n: SimTsim.nptr;
CheckAbort[];
WITH s: node.port SELECT FROM
Single => {
n ← s.handle;
IF SimTsim.pchars[n.npot]='X THEN
PrintStringLine["Undefined value: ", SimTsim.pnode[n]]
ELSE {
val: REF BOOLEAN ← NEW[BOOLEAN ← SimTsim.boolvalue[n.npot]];
Stuff[node, val]}};
Multiple => IF s.handle.size<=16 THEN {
val: REF CARDINAL ← NEW[CARDINAL ← CARDPort[node]];
Stuff[node, val]}
ELSE IF s.handle.size<=32 THEN {
val: REF LONG CARDINAL ← NEW[LONG CARDINAL ← LongCARDPort[node]];
Stuff[node, val]}
ELSE PrintStringLine["Unimplemented port type for port: ",
SimTsim.pnode[s.handle[0]]];
ENDCASE
};
SIMSet: PUBLIC PROC [node: PrivateHandle] = {
-- Assigns value from Sakura to MOSSIM through input ports
CheckAbort[];
IF node.value=NIL THEN { -- make nodes undefined
WITH p: node.port SELECT FROM
Single => {
MOSSIMFns.assignArg[1, SimTsim.pnode[p.handle]];
MOSSIMFns.targc ← 2;
MOSSIMFns.setInputX[]};
Multiple => {
FOR i: NAT IN [0..p.handle.size) DO
MOSSIMFns.assignArg[i+1, SimTsim.pnode[p.handle[i]]];
ENDLOOP;
MOSSIMFns.targc ← p.handle.size+1;
MOSSIMFns.setInputX[]};
ENDCASE;
RETURN};
WITH node.value SELECT FROM
n: REF BOOLEAN =>
WITH p: node.port SELECT FROM
Single => {
MOSSIMFns.assignArg[1, SimTsim.pnode[p.handle]];
MOSSIMFns.targc ← 2;
IF n↑ THEN MOSSIMFns.setInputH[] ELSE MOSSIMFns.setInputL[]};
ENDCASE => ERROR;
n: REF CARDINAL =>
WITH p: node.port SELECT FROM
Multiple => IF p.handle.size<=16 THEN {
val: CARDINAL ← n↑;
FOR i: NAT IN [p.handle.size..16) DO val ← val*2 ENDLOOP;
FOR i: NAT IN [0..p.handle.size) DO
MOSSIMFns.assignArg[i+1, SimTsim.pnode[p.handle[i]]];
val ← val*2;
ENDLOOP;
MOSSIMFns.targc ← p.handle.size+1;
IF val>=100000B THEN MOSSIMFns.setInputH[]
ELSE MOSSIMFns.setInputL[]}
ELSE ERROR;
ENDCASE => ERROR;
n: REF LONG CARDINAL =>
WITH p: node.port SELECT FROM
Multiple => IF p.handle.size<=32 THEN {
val: LONG CARDINAL ← n↑;
FOR i: NAT IN [p.handle.size..32) DO val ← val*2 ENDLOOP;
FOR i: NAT IN [0..32) DO
MOSSIMFns.assignArg[i+1, SimTsim.pnode[p.handle[i]]];
val ← val*2;
ENDLOOP;
MOSSIMFns.targc ← 33;
IF val>=20000000000B THEN MOSSIMFns.setInputH[]
ELSE MOSSIMFns.setInputL[]}
ELSE ERROR;
ENDCASE => ERROR;
ENDCASE => ERROR};
SIMConnect: PUBLIC PROC [node: PrivateHandle, name: STRING] = {
n: SimTsim.nptr ← SimTsim.ufind[name];
CheckAbort[];
IF n=NIL THEN
PrintStringLine["Cannot find the name: ", name]
ELSE {
node.port ← NEW[Single Port];
node.port↑ ← [Single[n]]}};
SIMMultiConnectInit, CharMultiConnectInit: PUBLIC PROC [node: PrivateHandle, size: CARDINAL] = {
node.port ← NEW[Multiple Port];
node.port↑ ← AllocatePorts[size]};
AllocatePorts: PROC [size: CARDINAL]
RETURNS [h: Multiple Port] = {
h.handle ← NEW[PortSequence[size]]};
SIMMultiConnectAssign, CharMultiConnectAssign:
PUBLIC PROC [node: PrivateHandle, name: STRING,
loc: CARDINAL] = {
n: SimTsim.nptr ← SimTsim.ufind[name];
CheckAbort[];
IF n=NIL THEN
PrintStringLine["Cannot find the name: ", name]
ELSE WITH h: node.port SELECT FROM
Single => ERROR;
Multiple => h.handle[loc] ← n;
ENDCASE => ERROR};
CARDPort: PROC [node: PrivateHandle] RETURNS [ret: CARDINAL] = {
WITH n: node.port SELECT FROM
Single => ERROR;
Multiple =>
SELECT n.handle.size FROM
<= 16 => {
ret ← 0;
FOR i: CARDINAL IN [0..n.handle.size) DO
SELECT SimTsim.pchars[n.handle[i].npot] FROM
'1 => ret ← 2*ret+1;
'0 => ret ← 2*ret;
ENDCASE => PrintStringLine[
"This node returns undefined value: ",
SimTsim.pnode[n.handle[i]]];
ENDLOOP};
ENDCASE => ERROR;
ENDCASE};
LongCARDPort: PROC [node: PrivateHandle] RETURNS [ret: LONG CARDINAL] = {
WITH n: node.port SELECT FROM
Single => ERROR;
Multiple =>
SELECT n.handle.size FROM
<= 32 => {
ret ← 0;
FOR i: CARDINAL IN [0..n.handle.size) DO
SELECT SimTsim.pchars[n.handle[i].npot] FROM
'1 => ret ← 2*ret+1;
'0 => ret ← 2*ret;
ENDCASE => PrintStringLine[
"This node returns undefined value: ",
SimTsim.pnode[n.handle[i]]];
ENDLOOP};
ENDCASE => ERROR;
ENDCASE};
CharGet: PUBLIC PROC [node: PrivateHandle] = {
ArrayPort: TYPE = RECORD[SEQUENCE size: [0..LAST[INTEGER]] OF CHARACTER];
CharPorts: PROC [handle: REF PortSequence, size: CARDINAL]
RETURNS [val: REF ArrayPort] = {
val ← NEW [ArrayPort[size]];
FOR i: NAT IN [0..size) DO
val[i] ← SimTsim.pchars[handle[i].npot];
ENDLOOP;
}; -- CharPorts
CheckAbort[];
WITH s: node.port SELECT FROM
Single => {
val: REF CHARACTER ← NEW[CHARACTER ← SimTsim.pchars[s.handle.npot]];
Stuff[node, val]};
Multiple => IF s.handle.size=16 THEN Stuff[node, CharPorts[s.handle, 16]]
ELSE IF s.handle.size=32 THEN Stuff[node, CharPorts[s.handle, 32]]
ELSE PrintStringLine["Unimplemented port type for port: ",
SimTsim.pnode[s.handle[0]]];
ENDCASE
};
Notify: PUBLIC PROC [node: PrivateHandle] = {
val: REF BOOLEAN;
CheckAbort[];
IF node=NIL THEN ERROR;
val ← NARROW[GrabIt[node], REF BOOLEAN];
IF val=NIL THEN
val ← NEW[BOOLEAN]
ELSE IF val↑ THEN
{val↑ ← FALSE;
StuffIt[node, val]};
val↑ ← TRUE;
Put[node, val]};
-- Scheduler
currentProcessSize: CARDINAL;
Pool: TYPE = RECORD [
cond: CONDITION, free: POINTER TO Pool];
MaxCond: CARDINAL = 100;
ConditionPool: ARRAY [0..MaxCond) OF Pool;
FreePool: POINTER TO Pool;
UniversalTime: LONG CARDINAL;
TimeQueue: TYPE = RECORD [
next: REF TimeQueue,
time: LONG CARDINAL,
size: CARDINAL,
events: POINTER TO Pool];
AllTime: REF TimeQueue ← NIL;
Fork: PUBLIC PROC[newProcess: PROC] RETURNS[PROCESS] = {
p: PROCESS;
CheckAbort[];
IncCurrentEntry[];
p ← FORK newProcess[];
Process.Yield[];
RETURN[p]
};
Join: PUBLIC PROC[process: PROCESS] = {
[] ← JOIN process;
};
NotifyAll: PUBLIC PROC[p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
p14, p15: PrivateHandle] = {
NotifyInternal[p1];
NotifyInternal[p2];
NotifyInternal[p3];
NotifyInternal[p4];
NotifyInternal[p5];
NotifyInternal[p6];
NotifyInternal[p7];
NotifyInternal[p8];
NotifyInternal[p9];
NotifyInternal[p10];
NotifyInternal[p11];
NotifyInternal[p12];
NotifyInternal[p13];
NotifyInternal[p14];
NotifyInternal[p15]};
NotifyInternal: ENTRY PROC [p: PrivateHandle] = {
ENABLE UNWIND => NULL;
IF p=NIL THEN RETURN;
NOTIFY p.cond;
FOR i: NAT IN [0..p.waitingArrayLength) DO
IF p.waiting[i]#NIL THEN NOTIFY p.waiting[i]↑
ENDLOOP;
FOR i: NAT IN [0..p.size) DO
IF p.body[i].choice#NIL THEN NOTIFY p.body[i].choice.cond;
ENDLOOP};
ProcessEnd: PUBLIC ENTRY PROC = {
ENABLE UNWIND => NULL;
DecCurrentInternal[];
IF AllTime = NIL THEN RETURN;
IF ~CurrentMore[] THEN NotifyEarliest[];
};
Abort: PUBLIC PROC = {
};
ProcessHolder: TYPE = REF ProcessHolderRec;
ProcessHolderRec: TYPE = RECORD [
name: PROCESS,
next: ProcessHolder];
ProcessHolderList: ProcessHolder ← NIL;
CatalogProcId: PUBLIC ENTRY PROC [process: PROCESS] = {
ENABLE UNWIND => NULL;
processHolder: ProcessHolder ← NEW[ProcessHolderRec];
processHolder.name ← process;
processHolder.next ← ProcessHolderList;
ProcessHolderList ← processHolder};
AbortAll: PUBLIC ENTRY PROC = {
ENABLE UNWIND => NULL;
UNTIL ProcessHolderList=NIL DO
Process.Abort[ProcessHolderList.name];
ProcessHolderList ← ProcessHolderList.next;
ENDLOOP};
GetProcessSize: PUBLIC ENTRY PROC RETURNS[ret: CARDINAL] = {
ENABLE UNWIND => NULL;
ret ← currentProcessSize};
Delay: PUBLIC PROC [max: CARDINAL] = {
CheckAbort[];
DelayInternal[max];
Process.Yield[];
};
RandomDelay: PUBLIC PROC [min, max: CARDINAL] = {
CheckAbort[];
DelayInternal[RandomCard.Choose[min, max]]
};
DelayInternal: ENTRY PROC [max: CARDINAL] = {
ENABLE UNWIND => NULL;
index: CARDINAL;
startTime: LONG CARDINAL ← UniversalTime+max;
DecCurrentInternal[];
IF currentProcessSize#0 THEN {
PutThisProcess[startTime];
RETURN};
IF startTime<Earliest[] THEN {
currentProcessSize ← currentProcessSize+1;
UniversalTime ← startTime; RETURN};
IF startTime>Earliest[] THEN {
NotifyEarliest[];
PutThisProcess[startTime];
RETURN};
index ← RandomCard.Choose[0,EarliestSize[]];
IF index=0 THEN {
currentProcessSize ← currentProcessSize+1;
UniversalTime ← startTime; RETURN};
NotifyEarliestAt[index-1];
PutThisProcess[startTime];
};
StandardDelay: PUBLIC PROC = {
CheckAbort[];
DelayInternal[RandomCard.Choose[1, 2]];
Process.Yield[];
};
Wait: PUBLIC ENTRY PROC [c: LONG POINTER TO CONDITION] = {
ENABLE UNWIND => NULL;
CheckAbort[];
IF currentProcessSize = 0 THEN ERROR;
currentProcessSize ← currentProcessSize-1;
IF AllTime#NIL AND currentProcessSize = 0 THEN NotifyEarliest[];
WAIT c↑;
currentProcessSize ← currentProcessSize+1};
WaitInternal: INTERNAL PROC [c: LONG POINTER TO CONDITION] = {
currentProcessSize ← currentProcessSize-1;
IF AllTime#NIL AND currentProcessSize = 0 THEN NotifyEarliest[];
WAIT c↑;
currentProcessSize ← currentProcessSize+1};
IncCurrent: PUBLIC PROC = {
CheckAbort[];
IncCurrentEntry[];
Process.Yield[]};
DecCurrent: PUBLIC PROC = {
CheckAbort[];
DecCurrentEntry[];
Process.Yield[]};
-- Current process size manipulation
CurrentMore: INTERNAL PROC RETURNS[BOOLEAN] = {
RETURN[currentProcessSize#0]
};
DecCurrentInternal: INTERNAL PROC = {
IF currentProcessSize = 0 THEN ERROR;
currentProcessSize ← currentProcessSize-1;
};
IncCurrentEntry: ENTRY PROC = {
ENABLE UNWIND => NULL;
currentProcessSize ← currentProcessSize+1;
};
DecCurrentEntry: ENTRY PROC = {
ENABLE UNWIND => NULL;
IF currentProcessSize = 0 THEN ERROR;
currentProcessSize ← currentProcessSize-1;
IF AllTime#NIL AND currentProcessSize = 0 THEN NotifyEarliest[];
};
-- Time queue manipulation
Earliest: INTERNAL PROC RETURNS[LONG CARDINAL] = {
IF AllTime=NIL THEN RETURN[LAST[LONG CARDINAL]];
RETURN[AllTime.time]};
EarliestSize: INTERNAL PROC RETURNS[CARDINAL] = {
RETURN[AllTime.size]};
NotifyEarliest: INTERNAL PROC = {
index: CARDINAL ← RandomCard.Choose[0,AllTime.size-1];
NotifyEarliestAt[index]
};
NotifyEarliestAt: INTERNAL PROC [index: CARDINAL] = {
eventQueue: POINTER TO Pool ← AllTime.events;
back: POINTER TO Pool;
currentProcessSize ← currentProcessSize+1;
UniversalTime ← AllTime.time;
IF index=0 THEN {
AllTime.events ← eventQueue.free;
NOTIFY eventQueue.cond;
eventQueue.free ← FreePool;
FreePool ← eventQueue;
IF AllTime.size=1 THEN {
time: REF TimeQueue ← AllTime;
AllTime ← AllTime.next}
ELSE AllTime.size ← AllTime.size-1;
RETURN};
THROUGH [0..index-1) DO
eventQueue ← eventQueue.free;
ENDLOOP;
back ← eventQueue;
eventQueue ← eventQueue.free;
NOTIFY eventQueue.cond;
back.free ← eventQueue.free;
eventQueue.free ← FreePool;
FreePool ← eventQueue;
AllTime.size ← AllTime.size-1;
};
PutThisProcess: INTERNAL PROC[startTime: LONG CARDINAL] = {
timeQueue: REF TimeQueue;
{IF AllTime=NIL OR AllTime.time>startTime THEN GOTO PutFront;
timeQueue ← AllTime;
IF AllTime.time=startTime THEN GOTO PutHere;
FOR timeQueue← AllTime, timeQueue.next UNTIL timeQueue.next=NIL DO
IF timeQueue.time=startTime THEN GOTO PutHere;
IF timeQueue.next.time>startTime THEN GOTO PutAfter
REPEAT
FINISHED =>
IF timeQueue.time=startTime THEN GOTO PutHere
ELSE GOTO PutAfter
ENDLOOP;
EXITS
PutFront => {
time: REF TimeQueue ← NEW[TimeQueue];
event: POINTER TO Pool;
time.next ← AllTime;
AllTime ← time;
time.time ← startTime;
time.size ← 1;
time.events ← FreePool;
IF FreePool = NIL THEN ERROR;
FreePool ← FreePool.free;
time.events.free ← NIL;
event ← time.events;
WAIT event.cond};
PutHere => {
pool: POINTER TO Pool ← FreePool;
IF FreePool=NIL THEN ERROR;
FreePool ← FreePool.free;
pool.free ← timeQueue.events;
timeQueue.events ← pool;
timeQueue.size ← timeQueue.size+1;
WAIT pool.cond};
PutAfter => {
time: REF TimeQueue ← NEW[TimeQueue];
event: POINTER TO Pool;
time.next ← timeQueue.next;
timeQueue.next ← time;
time.time ← startTime;
time.size ← 1;
time.events ← FreePool;
IF FreePool = NIL THEN ERROR;
FreePool ← FreePool.free;
time.events.free ← NIL;
event ← time.events;
WAIT event.cond};
}};
-- Abort
CheckAbort: PROC = {
-- IF TTY.UserAbort[] THEN ERROR ABORTED
};
Unimplementd: SIGNAL = CODE;
Alarm: PROC = {
SIGNAL Unimplementd};
SIMRead: PUBLIC PROC [file: STRING] = {
PrintStringLine["File read started: ", file];
MOSSIMFns.assignArg[1, file];
MOSSIMFns.targc ← 2;
MOSSIMFns.readFileString[];
PrintStringLine["", "File read finished"];
PrintStringLine["Initialization started", ""];
UNTIL MOSSIMFns.initializationResult[]=0 DO ENDLOOP;
PrintStringLine["Initialization finished", ""]};
PrintStringLine: PROC [s1, s2: stdio.SimString] = {
stdio.foutstring[stdio.stdout, s1];
stdio.foutstring[stdio.stdout, s2];
stdio.putc[stdio.CR, stdio.stdout]};
SIMStep: PUBLIC PROC = {
[] ← SimStep.step[];
StandardDelay[]};
SakuraWatchProc: PROC = {
DO
Process.Pause[1];
IF TTY.UserAbort[] THEN {
AbortAll[];
EXIT}
ENDLOOP};
-- Main part
watch: PROCESS;
[] ← RandomCard.InitRandom[seed: -1];
FreePool ← @ConditionPool[0];
{i: CARDINAL;
FOR i IN [0..MaxCond) DO
Process.EnableAborts[@ConditionPool[i].cond];
Process.DisableTimeout[@ConditionPool[i].cond];
ENDLOOP;
FOR i IN [0..MaxCond-1) DO
ConditionPool[i].free ← @ConditionPool[i+1]
ENDLOOP};
ConditionPool[MaxCond-1].free ← NIL;
UniversalTime ← 0;
currentProcessSize ← 1;
watch ← FORK SakuraWatchProc[];
Process.Detach[watch];
}.