Megalith:
PUBLIC
TYPE ~
REF MegalithRep ¬ Druid.nullMegalith;
MegalithRep: PUBLIC TYPE ~ DruidPrivate.MegalithRep ¬ DruidPrivate.nullMegalithRep;
Set:
PUBLIC
PROCEDURE [
address: BreakWorldArchitecture.Address,
monitored:
BOOLEAN ¬
FALSE]
RETURNS [Druid.Megalith] ~ {
Sets a counting breakpoint at the given address.
If monitored, then changes to the megalith are monitored, else not.
megalith: Druid.Megalith ¬
NEW[MegalithRep ¬ [
count: 0, break: Breakpoint.nullBreak, monitored: monitored]];
ProcToAddress:
PROCEDURE [proc:
SAFE
PROCEDURE
ANY
RETURNS
ANY]
RETURNS [TargetArchitecture.Address] ~ {
cProc: UXProcs.CProc ~ UXProcs.FromCedarProc[proc: proc];
address: TargetArchitecture.Address ~ LOOPHOLE[cProc];
RETURN [address];
};
breakWorld: BreakWorldArchitecture.BreakWorld ~
BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address: address];
breakProcTargetAddress: TargetArchitecture.Address ~
ProcToAddress[proc: BreakProc];
breakProcWorldAddress: BreakWorldArchitecture.Address ~
BreakWorldArchitecture.NewAddress[
breakWorld: breakWorld, address: breakProcTargetAddress];
megalith.break ¬ Breakpoint.SetBreakpoint[
address: address,
clientData: megalith, -- anything useful to put here?
breakProc: breakProcWorldAddress,
breakData: LOOPHOLE[megalith]];
RETURN [megalith];
};
Clear:
PUBLIC
PROCEDURE [megalith: Druid.Megalith]
RETURNS [] ~ {
Clears the given counting break.
MonitoredClear:
ENTRY
PROCEDURE [megalith: Druid.Megalith]
RETURNS [] ~ {
ENABLE UNWIND => NULL;
UnmonitoredClear[megalith: megalith];
RETURN;
};
UnmonitoredClear:
PROCEDURE [megalith: Druid.Megalith]
RETURNS [] ~ {
IF megalith.IsActive[]
THEN {
Breakpoint.ClearBreakpoint[break: megalith.break];
megalith.break ¬ Breakpoint.nullBreak;
};
RETURN;
};
IF megalith #
NIL
THEN {
(IF megalith.monitored
THEN MonitoredClear ELSE UnmonitoredClear)[megalith: megalith];
};
RETURN;
};
IsActive:
PUBLIC
PROCEDURE [megalith: Druid.Megalith]
RETURNS [
BOOLEAN] ~ {
Checks whether the given megalith is active.
RETURN [megalith # NIL AND megalith.break # Breakpoint.nullBreak];
};
Zero:
PUBLIC
PROCEDURE [megalith: Druid.Megalith]
RETURNS [
CARD] ~ {
Zeroes the counter in the given counting break.
read: CARD ¬ 0;
MonitoredZero:
ENTRY
PROCEDURE [megalith: Druid.Megalith]
RETURNS [
CARD] ~ {
ENABLE UNWIND => NULL;
read: CARD ~ UnmonitoredZero[megalith: megalith];
RETURN [read];
};
UnmonitoredZero:
PROCEDURE [megalith: Druid.Megalith]
RETURNS [
CARD] ~ {
read: CARD ¬ 0;
IF megalith.IsActive[]
THEN {
read ¬ megalith.count;
megalith.count ¬ 0;
};
RETURN [read];
};
read ¬ (
IF megalith.monitored
THEN MonitoredZero ELSE UnmonitoredZero)[megalith: megalith];
RETURN [read];
};
BreakProc:
PRIVATE Breakpoint.BreakProcedure ~ {
PROCEDURE [breakData: BreakData] RETURNS []
ToRefAny:
PROCEDURE [breakData: Breakpoint.BreakData]
RETURNS [
REF
ANY] ~ {
refAny: REF ANY ¬ NIL;
IsARefAny:
PRIVATE
PROCEDURE [data:
CARD32]
RETURNS [
BOOLEAN] ~ {
Hans says he'll include this procedure in the next storage allocator package. For now ...
RETURN [TRUE];
};
IF IsARefAny[breakData]
THEN
TRUSTED {
refAny ¬ LOOPHOLE[breakData];
};
RETURN [refAny];
};
refData: REF ANY ~ ToRefAny[breakData: breakData];
WITH refData
SELECT
FROM
megalith: Megalith => {
MonitoredIncrement:
ENTRY
PROCEDURE [megalith: Druid.Megalith] ~ {
ENABLE UNWIND => NULL;
UnmonitoredIncrement[megalith: megalith];
RETURN;
};
UnmonitoredIncrement:
PROCEDURE [megalith: Druid.Megalith] ~ {
megalith.count ¬ megalith.count + 1;
RETURN;
};
(
IF megalith.monitored
THEN MonitoredIncrement ELSE UnmonitoredIncrement)[megalith: megalith];
};
ENDCASE => NULL;
RETURN;
};
}.