// Stats.bcpl. Lisp statistics buffer // Last change April 5, 1981 3:56 PM by Beau Sheil // Tone change March 17, 1981 1:15 PM by Beau Sheil // Bar change February 5, 1981 6:54 PM by Beau Sheil // Phrase change November 23, 1980 5:50 PM by Beau Sheil // Chord change November 20, 1980 1:01 PM by Beau Sheil // Previous change August 4, 1980 9:38 PM by Beau Sheil get "LispBcpl.decl" get "Stats.decl" get "Streams.d" external [ // procedures defined here StatsOverflow // Punt Subr: WRITESTATS() WRITESTATS // Subr: WRITESTATS(type, lvX) GATHERSTATS // Subr: \GATHERSTATS(lvFID) OpenStats // (fid, windowing) CloseStats // () WriteStatsX // (x, y, z) DumpBlockToStats // (eventN, addr, numBlocks, blockSize) // static defined here @MiscSTATSbase // procedures used Bytes2; ReadClock; CallSwat; Smallp; SmallUnbox; VP2; Zero EqNIL; RAIDCode; MoveBlock; Closes; Puts; WriteBlock Version; Serial; IGetBase; OutputStream; MovePage // statics used @lvNIL; @lvKT; NPages; EmuDiskVp; EmuDiskBuffer ] static [ Stats = 0 // Stats disk stream MiscSTATSbase = 0 ] let StatsOverflow() = valof [ unless Stats resultis lvNIL // forget it if no stats file let t = vec 3 // space for two times ReadClock(t) // time of overflow WriteBlock(Stats, StatsBase, @StatsPtr-StatsBase) ReadClock(t+2) // time disk write finished @StatsPtr=StatsBase // Reset stats pointer WriteStatsX(evDmpBuff, 4, t) // log the dump event resultis lvNIL ] and WRITESTATS(lvType, lvX) = valof [ let typ = SmallUnbox(lvType)<<LoByte let v = vec 10 let lvArg = lvX for i=0 to 9 do // only got room for 10 [ unless Smallp(lvArg) break // args are all smallp v!i = SmallUnbox(lvArg); lvArg = lvArg+2 ] // sequential on stack test typ ls 200b ifso WriteStatsX(typ, (v!0)<<LoByte, v!1) ifnot WriteStatsX(typ, (lvArg-lvX) rshift 1, v) resultis lvNIL ] and GATHERSTATS(lvFID) = EqNIL(lvFID) ? valof [ CloseStats(); resultis lvNIL ] , valof [ if Stats then resultis RAIDCode("Multiple stats logs", lvNIL) Stats = OutputStream(lvFID) // create log stream @StatsPtr = StatsBase let v = vec 5 v!0, v!1, v!2, v!3, v!4, v!5 = Version(), Serial(), IGetBase(IFPRVersion), BcplVersion, IGetBase(IFPLVersion), NPages WriteStatsX(evVersions, 6, v) // write version event DumpMiscStats() // dump MiscStats at start resultis lvKT ] and CloseStats() be [ if Stats then [ DumpMiscStats(); StatsOverflow() Closes(Stats); Stats = 0 ] @StatsPtr = 0 ] and DumpMiscStats() be [ MovePage(EmuDiskVp, VP2(STATSspace, MISCSTATSbase)) WriteStatsX(evMStatsCnts, lenMiscStats, EmuDiskBuffer+(MISCSTATSbase<<LoByte)) ] and WriteStatsX(x,y,z) be [ unless @StatsPtr return // forget it if no stats action switchon x rshift 6 into // EventType: #xyz -> #x [ case 0: @StatsPtr!0 = Bytes2(x, y) // evnt, arg @StatsPtr = @StatsPtr+1 endcase case 1: @StatsPtr!0 = Bytes2(x, y) // evnt, arghi, arglo @StatsPtr!1 = z @StatsPtr = @StatsPtr+2 endcase case 2: @StatsPtr!0 = Bytes2(x, y-1) // evnt, N, lv Nwords MoveBlock(@StatsPtr+1, z, y) @StatsPtr = @StatsPtr+y+1 endcase default: CallSwat("Invalid event number") endcase ] if @StatsPtr gr StatsEdge then StatsOverflow() ] // DumpBlockToStats dumps large blocks. Dumps numBlocks of size blockSize // word 0: {eventN,,blockSize}; word 1: {0, num in sequence} // words 2 thru blockSize+1 {data} and DumpBlockToStats(eventN, addr, numBlocks, blockSize) be [ unless Stats return WriteBlock(Stats, StatsBase, @StatsPtr-StatsBase) // empty stats buffer for i = 1 to numBlocks do [ Puts(Stats, Bytes2(eventN, blockSize)); Puts(Stats, i) WriteBlock(Stats, addr, blockSize) addr = addr + blockSize ] @StatsPtr=StatsBase // Reset stats pointer ]