<<>> <> <> <> <> DIRECTORY Commander, CommanderOps, Convert, IO, Labels, Process, Real, RefText, Rope, ViewerClasses; ThreadsCountLabel: CEDAR PROGRAM IMPORTS Commander, CommanderOps, Convert, IO, Labels, Process, Real, RefText, Rope = BEGIN ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; CirioNubThreadDataRep: TYPE ~ MACHINE DEPENDENT RECORD [ --translated from CirioNubTypes.h index, gen: CARD, sStat: CARD, pri: CARD, dbMsg: INT, dbFrozen: INT, pc, sp, fp: POINTER]; Counts: TYPE ~ RECORD [f, ry, rn, m, c, o: NAT ¬ 0]; Style: TYPE ~ {twiddle, count}; pause: INT ¬ 15000; style: Style ¬ twiddle; divisor: NAT ¬ 1; nThreads: INT ¬ 121; buf: REF TEXT ¬ RefText.New[100]; twiddle: ARRAY [0..3] OF CHAR ¬ ['\\, '|, '/, '-]; hexChars: ARRAY [0..15] OF CHAR ~ ['0, '1, '2, '3, '4, '5, '6, '7, '8, '9, 'A, 'B, 'C, 'D, 'E, 'F]; LocalGetThread: UNSAFE PROC [idx: INT, buf: POINTER TO CirioNubThreadDataRep] RETURNS [INT] ~ UNCHECKED MACHINE CODE {"CirioNubLocalGetThread"}; GetMaxThreads: PROC RETURNS [INT] ~ TRUSTED MACHINE CODE {"CirioNubLocalGetMaxThreads"}; Watch: PROC [but: Viewer] ~ { twid: [0..255] ¬ 0; rem: NAT ¬ divisor; Process.SetPriority[Process.priorityForeground]; DO counts: Counts ¬ []; buf: CirioNubThreadDataRep; desc: ROPE; nThreads ¬ GetMaxThreads[]; FOR idx: NAT IN [0..nThreads) DO cc: INT; TRUSTED {cc ¬ LocalGetThread[idx, @buf]}; IF cc#0 THEN counts.f ¬ counts.f.SUCC ELSE SELECT buf.sStat FROM 1 => counts.f ¬ counts.f.SUCC; 2 => counts.ry ¬ counts.ry.SUCC; 3 => counts.rn ¬ counts.rn.SUCC; 4 => counts.m ¬ counts.m.SUCC; 5 => counts.c ¬ counts.c.SUCC; ENDCASE => counts.o ¬ counts.o.SUCC; ENDLOOP; IF (rem ¬ rem.PRED) = 0 THEN { desc ¬ FmtCounts[counts, style, twid]; Labels.Set[but, desc]; rem ¬ divisor}; Process.PauseMsec[pause]; twid ¬ (twid.SUCC) MOD 256; ENDLOOP; }; Control: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] ~ { argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; i: NAT ¬ 1; WHILE i < argv.argc DO len: INT ~ argv[i].Length; SELECT TRUE FROM len = 0 => RETURN [$Failure, usage]; argv[i].Fetch[len-1]='s => { rl: ROPE ~ argv[i].Substr[len: len-1]; period: REAL ¬ 0.0; period ¬ Convert.RealFromRope[rl !Convert.Error => { cmd.err.PutF["Convert.Error near %g trying to parse \"%q\" as a REAL.\n", [integer[index]], [rope[rl]] ]; GOTO Dont}]; IF period < 0.1 OR period > 1.0E3 THEN RETURN [$Failure, IO.PutFR1["Sample period should be in the range [0.1 .. 1000] seconds, not %g", [real[period]] ]]; pause ¬ Real.Round[period*1000]; cmd.out.PutF1["Sampling period set to %g seconds.\n", [real[period]] ]; EXITS Dont => i¬i}; argv[i].Fetch[0] = '/ => { ri: ROPE ~ argv[i].Substr[start: 1]; d: INT ~ Convert.IntFromRope[ri !Convert.Error => { cmd.err.PutF["Convert.Error near %g trying to parse \"%q\" as an INT.\n", [integer[index]], [rope[ri]] ]; GOTO Dont}]; IF d<1 OR d>65536 THEN RETURN [$Failure, IO.PutFR1["Painting divisor should be in the range [1 .. 65536], not %g", [integer[d]] ]]; divisor ¬ d; cmd.out.PutF1["Painting divisor set to %g.\n", [integer[d]] ]; EXITS Dont => i¬i}; argv[i].Equal["twiddle", FALSE] => style ¬ twiddle; argv[i].Equal["count", FALSE] => style ¬ count; ENDCASE => RETURN [$Failure, usage]; i ¬ i.SUCC; ENDLOOP; RETURN}; FmtCounts: PROC [counts: Counts, style: Style, it: [0..255]] RETURNS [ROPE] ~ { buf.length ¬ 0; buf ¬ RefText.AppendChar[buf, 'f]; buf ¬ Convert.AppendCard[buf, counts.f]; buf ¬ RefText.AppendRope[buf, " ry"]; buf ¬ Convert.AppendCard[buf, counts.ry]; buf ¬ RefText.AppendRope[buf, " rn"]; buf ¬ Convert.AppendCard[buf, counts.rn]; buf ¬ RefText.AppendRope[buf, " m"]; buf ¬ Convert.AppendCard[buf, counts.m]; buf ¬ RefText.AppendRope[buf, " c"]; buf ¬ Convert.AppendCard[buf, counts.c]; buf ¬ RefText.AppendRope[buf, " o"]; buf ¬ Convert.AppendCard[buf, counts.o]; buf ¬ RefText.AppendChar[buf, ' ]; SELECT style FROM twiddle => buf ¬ RefText.AppendChar[buf, twiddle[it MOD 4]]; count => { buf ¬ RefText.AppendChar[buf, hexChars[it/16]]; buf ¬ RefText.AppendChar[buf, hexChars[it MOD 16]]}; ENDCASE => ERROR; RETURN Rope.FromRefText[buf]}; usage: ROPE ~ "Usage: ThreadsCountLabel ( twiddle | count | s | /)*"; Start: PROC ~ { n0: ROPE ~ FmtCounts[[f: 22, rn: 12, m: 13], count, 255]; lab: Viewer ~ Labels.Create[[name: n0]]; TRUSTED {Process.Detach[FORK Watch[lab]]}; Commander.Register["ThreadsCountLabel", Control, usage]; RETURN}; Start[]; END.