SpyLog.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Maxwell, September 16, 1983 11:07 am
Russ Atkinson (RRA) February 16, 1987 11:18:09 am PST
Bob Hagmann October 24, 1986 11:25:23 am PDT
DIRECTORY
AMTypes USING [nullType],
IO USING [STREAM],
PrincOps USING [BytePC, GlobalFrameHandle, PsbHandle];
SpyLog: DEFINITIONS = BEGIN
The Spy log is a fast means of logging information. It is guaranteed not to cause any page faults or allocations for the client process. It is implemented with two pinned buffers, one of which is being written out to the disk by a separate process while the other is being filled with data. Normally there is only one log, which can be written or read, but not both. Calling OpenForRead with spyOnSpyLog = TRUE will create a second log that can be written to while the first log is being read. After the first log is read, calling OpenForRead again will open the second log for reading.
Control
active: READONLY BOOL; -- true iff the spy is open for writing.
OpenForRead: PROC;
Opens the spy log for reading.
OpenForWrite: PROC [spyOnSpyLog: BOOLFALSE];
Opens the spy log for writing. If spyOnSpyLog is TRUE, then use the secondary log.
Close: PROC;
Unpins the buffers and the module. Does not destroy any information. There is no need to close the log if you are just going to re-open it in a different mode.
Print: PROC [stream: IO.STREAMNIL];
Reading and Writing
Entry: TYPE = MACHINE DEPENDENT RECORD [
SELECT type:{endOfLog, nullEntry, trace, data} FROM
endOfLog => [fill: [0..16000)𡤀], -- marks the end of valid data
nullEntry => [size: [0..16000)𡤀], -- indicates data to be skipped (used internally).
trace => [ -- 6 words
fill: [0..16000)𡤀,
gfh: PrincOps.GlobalFrameHandle,
pc: PrincOps.BytePC,
process: PrincOps.PsbHandle,
timestamp: CARD],
data => [ -- 4 words + size
size: [0..16000),
rttype: CARDINAL,
timestamp: CARD,
data: SEQUENCE COMPUTED CARDINAL OF WORD],
ENDCASE];
InvisibleProcesses: PROC RETURNS [writeProcess:PROCESS, extendProcess: PROCESS];
Returns the processes that are the current writer and extender, or NIL if no process exists. Do not call WriteData or WriteTrace from either of these processes.
NextEntry: PROC RETURNS [LONG POINTER TO Entry];
Moves the index to the next entry. The last entry will contain [endOfLog[]]. Raises Error if the spy log is not open for reading.
WriteData: PROC [data: LONG POINTER, size: [0..8000], type: CARDINAL ← AMTypes.nullType];
Examples: WriteData[@foo, SIZE[Foo], CODE[Foo]]; WriteData[@data, size].
The system will store the type and use it to print the data. This doesn't slow down the spying; the costs are incurred when the log is printed. The type cannot be ref-containing. Raises Error if the spy log is not open for writing.
WriteTrace: PROC [gfh: PrincOps.GlobalFrameHandle ← NIL, pc: PrincOps.BytePC ← [0]];
Records the gfh and pc. This will be printed as a procedure and pc.
Defaults to the gfh and pc of the calling procedure. Raises Error if the spy log is not open for writing.
Here: PROC = INLINE {IF active THEN WriteTrace[]};
Very cheap if the log isn't activated.
Error: ERROR;
END.
Bob Hagmann October 24, 1986 11:25:34 am PDT
added WriteProcess