;;; -*- Mode:LISP; Package:TV; Base:8; Readtable:ZL -*- ;;; ** (c) Copyright 1980 Massachusetts Institute of Technology ** ;;; PEEK -- displays status information about the Lisp Machine ;; Define the Peek display modes, and how to select them. (DEFVAR *PEEK-DEFAULT-MODE-ALIST* NIL "This variable has one element for each Peek display mode. Elements are added by calls to DEFINE-PEEK-MODE which appear in this file and the other source files of PEEK, and are executed at load time. Each element looks like: /(character display-function menu-item-string no-updating-flag long-documentation). That is also what the five arguments to DEFINE-PEEK-MODE look like. The menu-item-string is a short phrase of documentation which is also what appears in the menu proper. The display function is what is called to update the display. NO-UPDATING-FLAG is either T or NIL. If T, it means simply call the function once and leave what it prints on the screen. Normally it is NIL, which means that the updating function returns a set of scroll items.") (DEFVAR *PEEK-MENU-ITEM-ALIST* NIL "This is the item alist for the command menu. The first element of each element is the menu item string. The third element is the corresponding element of *PEEK-DEFAULT-MODE-ALIST*.") (DEFMACRO DEFINE-PEEK-MODE (FUNCTION CHARACTER DOCUMENTATION &OPTIONAL FUNCTION-P &BODY LONG-DOCUMENTATION) ;this is to get the indentation right (DECLARE (ARGLIST FUNCTION CHARACTER DOCUMENTATION &OPTIONAL FUNCTION-P LONG-DOCUMENTATION)) `(DEFINE-PEEK-MODE-1 ',FUNCTION ,CHARACTER ,DOCUMENTATION ,FUNCTION-P ,(CAR LONG-DOCUMENTATION))) (DEFUN DEFINE-PEEK-MODE-1 (FUNCTION CHARACTER DOCUMENTATION FUNCTION-P LONG-DOCUMENTATION) ;character lossage (IF (NUMBERP CHARACTER) (SETQ CHARACTER (INT-CHAR CHARACTER))) (WITHOUT-INTERRUPTS (SETQ *PEEK-DEFAULT-MODE-ALIST* (NCONC (DELQ (ASSQ CHARACTER *PEEK-DEFAULT-MODE-ALIST*) *PEEK-DEFAULT-MODE-ALIST*) (NCONS (LIST CHARACTER FUNCTION DOCUMENTATION FUNCTION-P LONG-DOCUMENTATION)))) (SETQ *PEEK-MENU-ITEM-ALIST* (MAPCAR (LAMBDA (ELT) `(,(THIRD ELT) :VALUE ,ELT :DOCUMENTATION ,(OR (FIFTH ELT) "This PEEK mode is undocumented."))) *PEEK-DEFAULT-MODE-ALIST*)))) ;;; This is meant to be called inside the PEEK-TOP-LEVEL, ;;; and MODE should be a character and the first arg can be a numeric argument. (DEFUN PEEK-SET-MODE (WINDOW MODE &REST ARGS &AUX OLD-MODE) ;character lossage (IF (NUMBERP MODE) (SETQ MODE (INT-CHAR MODE))) (WHEN (SETQ MODE (ASSQ MODE *PEEK-DEFAULT-MODE-ALIST*)) (SETQ OLD-MODE (LABEL-STRING (SEND WINDOW :LABEL))) (SEND (SEND (SEND WINDOW :SUPERIOR) :GET-PANE 'MENU) :SET-HIGHLIGHTED-ITEMS (LIST (SYS:ASSOC-EQUALP (THIRD MODE) *PEEK-MENU-ITEM-ALIST*))) (SEND WINDOW :SET-LABEL (THIRD MODE)) (IF (FOURTH MODE) ;; If you want to execute only once, (UNWIND-PROTECT (APPLY (SECOND MODE) WINDOW ARGS) ;; Then on exit restore the old mode in the menu and label. ;; Since probably the typeout window is going away now ;; and that old mode's data is reappearing. (PEEK-ASSURE-NO-TYPEOUT WINDOW) (DOLIST (ELT *PEEK-DEFAULT-MODE-ALIST*) (IF (EQUALP OLD-MODE (THIRD ELT)) (RETURN (SETQ MODE ELT)))) (SEND (SEND (SEND WINDOW :SUPERIOR) :GET-PANE 'MENU) :SET-HIGHLIGHTED-ITEMS (LIST (SYS:ASSOC-EQUALP (THIRD MODE) *PEEK-MENU-ITEM-ALIST*))) (SEND WINDOW :SET-LABEL (THIRD MODE))) ;; Here if we are entering a mode that really does update. ;; We stay in it semipermanently. (PEEK-ASSURE-NO-TYPEOUT WINDOW) (SEND WINDOW :SET-DISPLAY-ITEM (APPLY (SECOND MODE) ARGS))) T)) ;;;; Windows for PEEK. (DEFFLAVOR BASIC-PEEK ((NEEDS-REDISPLAY NIL)) (SCROLL-MOUSE-MIXIN SCROLL-WINDOW-WITH-TYPEOUT FULL-SCREEN-HACK-MIXIN) :SETTABLE-INSTANCE-VARIABLES :GETTABLE-INSTANCE-VARIABLES (:DEFAULT-INIT-PLIST :SAVE-BITS T :LABEL "Peek" :TRUNCATION T) (:DOCUMENTATION :SPECIAL-PURPOSE "The actual peek window. This has the capability to display in a PEEK display mode.")) (DEFMETHOD (BASIC-PEEK :NAME-FOR-SELECTION) () (STRING-APPEND "Peek: " (LABEL-STRING LABEL))) (DEFFLAVOR PEEK-WINDOW () (PROCESS-MIXIN TV:INITIALLY-INVISIBLE-MIXIN BASIC-PEEK) (:DEFAULT-INIT-PLIST :PROCESS '(PEEK-STANDALONE-TOP-LEVEL :SPECIAL-PDL-SIZE #o4000 :REGULAR-PDL-SIZE #o10000)) (:DOCUMENTATION :COMBINATION "Peek window with a process. Usable as a stand-alone window that does PEEK display, but with no menu -- only keyboard commands will be available.")) (DEFUN PEEK-MOUSE-CLICK (ITEM LEADER-TO-COMPLEMENT) (DECLARE (:SELF-FLAVOR BASIC-PEEK)) (SETQ NEEDS-REDISPLAY T) (SETF (ARRAY-LEADER ITEM (+ SCROLL-ITEM-LEADER-OFFSET LEADER-TO-COMPLEMENT)) (NOT (ARRAY-LEADER ITEM (+ SCROLL-ITEM-LEADER-OFFSET LEADER-TO-COMPLEMENT))))) ;This is the top level function that runs in the process of a window of flavor PEEK. (DEFUN PEEK-STANDALONE-TOP-LEVEL (WINDOW) (PEEK-TOP-LEVEL WINDOW #/HELP) (DO-FOREVER (DESELECT-AND-MAYBE-BURY-WINDOW (SEND WINDOW :ALIAS-FOR-SELECTED-WINDOWS) :FIRST) (PEEK-TOP-LEVEL WINDOW NIL))) ;;; Peek frames that have command menus of Peek modes, as well as a peek-window ;;; to do the actual displaying in. (DEFFLAVOR PEEK-FRAME () (PROCESS-MIXIN FRAME-DONT-SELECT-INFERIORS-WITH-MOUSE-MIXIN BORDERED-CONSTRAINT-FRAME-WITH-SHARED-IO-BUFFER) (:DEFAULT-INIT-PLIST :SAVE-BITS :DELAYED :PROCESS )) (DEFMETHOD (PEEK-FRAME :BEFORE :INIT) (INIT-PLIST) (SETQ PANES (LIST (IF (GETL INIT-PLIST '(:PROCESS)) `(PEEK PEEK-WINDOW :SAVE-BITS NIL :PROCESS ,(GET INIT-PLIST :PROCESS)) '(PEEK PEEK-WINDOW :SAVE-BITS NIL)) `(MENU DYNAMIC-HIGHLIGHTING-COMMAND-MENU-PANE :FONT-MAP ,(LIST FONTS:CPTFONT) ;not the usual large menu font :LABEL "Peek Modes" :ITEM-LIST-POINTER *PEEK-MENU-ITEM-ALIST*))) (SETQ CONSTRAINTS `((MAIN . ((MENU PEEK) ((MENU :ASK :PANE-SIZE)) ((PEEK :EVEN))))))) (DEFMETHOD (PEEK-FRAME :AFTER :INIT) (IGNORE) (LET ((PANE (SEND SELF :GET-PANE 'PEEK))) (SEND SELF :SELECT-PANE PANE) (SETQ PROCESS (SEND PANE :PROCESS)))) (DEFMETHOD (PEEK-FRAME :BEFORE :EXPOSE) (&REST IGNORE) (OR EXPOSED-P (EQUAL *PEEK-MENU-ITEM-ALIST* (SEND (SEND SELF :GET-PANE 'MENU) :ITEM-LIST)) (SEND SELF :SET-CONFIGURATION 'MAIN))) (DEFFLAVOR DYNAMIC-HIGHLIGHTING-COMMAND-MENU-PANE () (DYNAMIC-ITEM-LIST-MIXIN MENU-HIGHLIGHTING-MIXIN COMMAND-MENU)) (COMPILE-FLAVOR-METHODS PEEK-FRAME PEEK-WINDOW DYNAMIC-HIGHLIGHTING-COMMAND-MENU-PANE) (DEFUN PEEK (&OPTIONAL INITIAL-MODE) "Select a new or old Peek window. An argument sets the Peek display mode." (SELECT-OR-CREATE-WINDOW-OF-FLAVOR 'PEEK-FRAME) (IF INITIAL-MODE (SEND SELECTED-WINDOW :FORCE-KBD-INPUT (TYPECASE INITIAL-MODE (STRING (CHAR INITIAL-MODE 0)) (SYMBOL (CHAR (SYMBOL-NAME INITIAL-MODE) 0)) (T INITIAL-MODE)))) (AWAIT-WINDOW-EXPOSURE)) (DEFVAR PEEK-SLEEP-TIME 120. "This is how long, in 60'ths of a second, to wait between updates of the screen in PEEK.") ;;; This is the command reading loop. (DEFUN PEEK-TOP-LEVEL (WINDOW MODE) (COND-EVERY ((AND MODE (SYMBOLP MODE)) (SETQ MODE (SYMBOL-NAME MODE))) ((STRINGP MODE) (SETQ MODE (CHAR MODE 0))) ((CHARACTERP MODE) (SETQ MODE (CHAR-INT MODE))) ;character lossage ((NUMBERP MODE) (SEND WINDOW :FORCE-KBD-INPUT MODE))) (BLOCK PEEK (DO-FOREVER (CATCH-ERROR-RESTART ((SYS:ABORT ERROR) "Return to PEEK command level.") (DO ((SLEEP-TIME PEEK-SLEEP-TIME) (WAKEUP-TIME (TIME-DIFFERENCE (TIME) (- PEEK-SLEEP-TIME))) (wakeup-time-passed nil) (*TERMINAL-IO* (SEND WINDOW :TYPEOUT-WINDOW)) (ARG) (CHAR)) (()) (when (or (TIME-LESSP WAKEUP-TIME (TIME)) wakeup-time-passed) (SETQ WAKEUP-TIME (TIME-DIFFERENCE (TIME) (- SLEEP-TIME))) (setq wakeup-time-passed nil)) (OR (= SLEEP-TIME 0) (PROCESS-WAIT "Peek Timeout or TYI" (LAMBDA (TIME FLAG-LOC STREAM PEEK-WINDOW) (if (SHEET-EXPOSED-P PEEK-WINDOW) (OR wakeup-time-passed (TIME-LESSP TIME (TIME)) (CONTENTS FLAG-LOC) (SEND STREAM :LISTEN)) ;;If sheet not exposed, notice when wakeup-time is passed ;;If we don't do this and sheet is deexposed for a long time, peek ;;stops redisplaying (when (time-lessp time (time)) (setq wakeup-time-passed t) nil))) WAKEUP-TIME (LOCATE-IN-INSTANCE WINDOW 'NEEDS-REDISPLAY) *TERMINAL-IO* (SEND WINDOW :ALIAS-FOR-SELECTED-WINDOWS))) (DO () ((PROGN (PEEK-ASSURE-NO-TYPEOUT WINDOW) (NULL (SETQ CHAR (SEND *TERMINAL-IO* :ANY-TYI-NO-HANG))))) (COND-EVERY ((CONSP CHAR) ;; A special command (forced input, no doubt) (CASE (CAR CHAR) (SUPDUP (SUPDUP (CADR CHAR))) (SUPDUP:TELNET (TELNET (CADR CHAR))) (QSEND (QSEND (CADR CHAR)) (SEND WINDOW :SET-NEEDS-REDISPLAY T) (SEND *TERMINAL-IO* :MAKE-COMPLETE)) (EH (EH (CADR CHAR))) (INSPECT (INSPECT (CADR CHAR))) (DESCRIBE (DESCRIBE (CADR CHAR))) (:eval (eval (cadr char))) (:MENU (SETQ CHAR (FIRST (THIRD (SECOND CHAR))))) (:mouse-button (mouse-call-system-menu)) (OTHERWISE (BEEP))) (SETQ ARG NIL)) ((NUMBERP CHAR) (SETQ CHAR (INT-CHAR CHAR))) ((CHARACTERP CHAR) ;; Standard character, either accumulate arg or select new mode (SETQ CHAR (CHAR-UPCASE CHAR)) (IF (DIGIT-CHAR-P CHAR) (SETQ ARG (+ (* 10. (OR ARG 0)) (DIGIT-CHAR-P CHAR))) (IF (PEEK-SET-MODE WINDOW CHAR ARG) (SETQ ARG NIL) ;; Check for standard character assignments (CASE CHAR (#/HELP (SEND *STANDARD-OUTPUT* :CLEAR-WINDOW) (LET (INPUT) (SETQ INPUT (SEND *STANDARD-INPUT* :LISTEN)) (UNLESS INPUT (FORMAT T "The Peek program shows a continuously updating status display. There are several modes that display different status. Here is a list of modes. Select a mode by typing the character or by clicking on the corresponding menu item.~2%")) (DOLIST (E *PEEK-DEFAULT-MODE-ALIST*) (WHEN (OR INPUT (SETQ INPUT (SEND *STANDARD-INPUT* :LISTEN))) (RETURN)) (FORMAT T "~:@C~5T~A~%~@[~6T~A~%~]" (FIRST E) (THIRD E) (FIFTH E))) (UNLESS INPUT (FORMAT T "~%Q~5TQuit.~%") (FORMAT T "nZ~5TSets sleep time between updates to n seconds.~2%") (FORMAT T "[Help] Prints this message.~2%"))) (SETQ ARG NIL)) (#/Q (RETURN-FROM PEEK NIL)) (#/Z (AND ARG (SETQ SLEEP-TIME (* 60. ARG))) (SEND WINDOW :SET-NEEDS-REDISPLAY T) (SETQ ARG NIL)) (#/SPACE (SEND WINDOW :SET-NEEDS-REDISPLAY T)) (OTHERWISE (BEEP)))))))) (WHEN (OR (SEND WINDOW :NEEDS-REDISPLAY) (TIME-LESSP WAKEUP-TIME (TIME))) ;; We want to redisplay. If have typeout, hang until user confirms. (SEND WINDOW :SET-NEEDS-REDISPLAY NIL) (SEND WINDOW :REDISPLAY))))))) (DEFUN PEEK-ASSURE-NO-TYPEOUT (WINDOW) (WHEN (SEND (SETQ WINDOW (SEND WINDOW :TYPEOUT-WINDOW)) :INCOMPLETE-P) (FORMAT T "~&Type any character to flush:") (LET ((CHAR (SEND *TERMINAL-IO* :ANY-TYI))) (SEND WINDOW :MAKE-COMPLETE) (UNLESS (EQ CHAR #/SPACE) (SEND *TERMINAL-IO* :UNTYI CHAR))))) ;;;; Processes, meters (DEFINE-PEEK-MODE PEEK-PROCESSES #/P "Active Processes" NIL "List status of every process -- why waiting, how much run recently.") (DEFUN PEEK-PROCESSES (IGNORE) "Shows state of all active processes." (LIST () ;; 30 of process name, 25 of state, 5 of priority, 10 of quantum left/quantum, ;; 8 of percentage, followed by idle time (11 columns) (SCROLL-PARSE-ITEM (FORMAT NIL "~30A~21A~10A~10A~8A~8A" "Process Name" "State" "Priority" "Quantum" " %" "Idle")) (SCROLL-PARSE-ITEM "") (SCROLL-MAINTAIN-LIST #'(LAMBDA () ALL-PROCESSES) #'(LAMBDA (PROCESS) (SCROLL-PARSE-ITEM `(:MOUSE-ITEM (NIL :EVAL (PEEK-PROCESS-MENU ',PROCESS 'ITEM 0) :DOCUMENTATION "Menu of useful things to do to this process.") :STRING ,(PROCESS-NAME PROCESS) 30.) `(:FUNCTION ,#'PEEK-WHOSTATE ,(NCONS PROCESS) 25.) `(:FUNCTION ,PROCESS (:PRIORITY) 5. ("~D.")) `(:FUNCTION ,PROCESS (:QUANTUM-REMAINING) 5. ("~4D//")) `(:FUNCTION ,PROCESS (:QUANTUM) 5. ("~D.")) `(:FUNCTION ,PROCESS (:PERCENT-UTILIZATION) 8. ("~1,1,4$%")) `(:FUNCTION ,PROCESS (:IDLE-TIME) NIL ("~\TV::PEEK-PROCESS-IDLE-TIME\")))) NIL NIL) (SCROLL-PARSE-ITEM "") (SCROLL-PARSE-ITEM "Clock Function List") (SCROLL-MAINTAIN-LIST #'(LAMBDA () SI::CLOCK-FUNCTION-LIST) #'(LAMBDA (FUNC) (SCROLL-PARSE-ITEM `(:STRING ,(WITH-OUTPUT-TO-STRING (STR) (PRINC FUNC STR)))))))) (FORMAT:DEFFORMAT PEEK-PROCESS-IDLE-TIME (:ONE-ARG) (ARG IGNORE) (COND ((NULL ARG) (SEND *STANDARD-OUTPUT* :STRING-OUT "forever")) ; character too small ((ZEROP ARG)) ;Not idle ((< ARG 60.) (FORMAT T "~D sec" ARG)) ((< ARG 3600.) (FORMAT T "~D min" (TRUNCATE ARG 60.))) (T (FORMAT T "~D hr" (TRUNCATE ARG 3600.))))) (DEFUN PEEK-WHOSTATE (PROCESS) (COND ((SI::PROCESS-ARREST-REASONS PROCESS) "Arrest") ((SI::PROCESS-RUN-REASONS PROCESS) (or (si::process-wait-whostate process) (string-append "Running: " (si::process-run-whostate process)))) (T "Stop"))) (DEFINE-PEEK-MODE PEEK-RATES #/R "Counter Rates" NIL "Display the rate of change of the counters.") (defstruct (peek-rate (:type :list)) peek-rate-counter-name peek-rate-counter-type peek-rate-last-value peek-rate-average ) (defconst peek-rate-list nil) (defun put-meters-on-peek-rate-list (meter-list function-list) (dolist (m meter-list) (cond ((null (memq m si:a-memory-counter-block-names))) ((null (assq m peek-rate-list)) (let ((pr (make-peek-rate))) (setf (peek-rate-counter-type pr) :meter) (setf (peek-rate-counter-name pr) m) (setf (peek-rate-last-value pr) (read-meter m)) (setf (peek-rate-average pr) 0) (without-interrupts (setq peek-rate-list (nconc peek-rate-list (list pr)))))))) (dolist (f function-list) (cond ((null (assq f peek-rate-list)) (let ((pr (make-peek-rate))) (setf (peek-rate-counter-type pr) :function) (setf (peek-rate-counter-name pr) f) (setf (peek-rate-last-value pr) (funcall f)) (setf (peek-rate-average pr) 0) (without-interrupts (setq peek-rate-list (nconc peek-rate-list (list pr))))))))) (put-meters-on-peek-rate-list '(si:%count-first-level-map-reloads si:%count-second-level-map-reloads %COUNT-PDL-BUFFER-READ-FAULTS %COUNT-PDL-BUFFER-WRITE-FAULTS %COUNT-PDL-BUFFER-MEMORY-FAULTS %COUNT-DISK-PAGE-READS %COUNT-DISK-PAGE-WRITES %COUNT-FRESH-PAGES %COUNT-AGED-PAGES %COUNT-AGE-FLUSHED-PAGES %COUNT-META-BITS-MAP-RELOADS %COUNT-CONS-WORK %COUNT-SCAVENGER-WORK %AGING-DEPTH %COUNT-FINDCORE-STEPS %COUNT-FINDCORE-EMERGENCIES %COUNT-DISK-PAGE-READ-OPERATIONS %COUNT-DISK-PAGE-WRITE-OPERATIONS %COUNT-DISK-PAGE-WRITE-WAITS %COUNT-DISK-PAGE-WRITE-BUSYS %COUNT-DISK-PREPAGES-USED %COUNT-DISK-PREPAGES-NOT-USED %DISK-WAIT-TIME %COUNT-DISK-PAGE-WRITE-APPENDS %COUNT-DISK-PAGE-READ-APPENDS %COUNT-ILLOP-DEBUG %COUNT-MICRO-FAULTS ) '( ; si:read-main-stat-counter ; si:read-aux-stat-counter time:microsecond-time )) (defconst peek-maintain-rates-time-constant 16.) (defconst peek-maintain-rates-number-of-sixtieths 30.) (defvar peek-maintain-rates-ticks-to-go 0) (defun peek-maintain-rates (time-delta) (condition-case () (progn (decf peek-maintain-rates-ticks-to-go time-delta) (cond ((<= peek-maintain-rates-ticks-to-go 0) (setq peek-maintain-rates-ticks-to-go peek-maintain-rates-number-of-sixtieths) (dolist (pr peek-rate-list) (let* ((new-value (selectq (peek-rate-counter-type pr) (:meter (read-meter (peek-rate-counter-name pr))) (:function (funcall (peek-rate-counter-name pr))))) (delta (- new-value (peek-rate-last-value pr)))) (decf (peek-rate-average pr) (// (peek-rate-average pr) peek-maintain-rates-time-constant)) (incf (peek-rate-average pr) delta) (setf (peek-rate-last-value pr) new-value))) ))) (error (without-interrupts (setq clock-function-list (delq 'peek-maintain-rates si:clock-function-list)))))) (defun activate-peek-rate-maintainer (on-p) (peek-maintain-rates 1) (without-interrupts (cond ((null on-p) (setq si:clock-function-list (delq 'peek-maintain-rates si:clock-function-list))) ((memq 'peek-maintain-rates si:clock-function-list)) (t (setq peek-maintain-rates-ticks-to-go 0) (push 'peek-maintain-rates si:clock-function-list))))) (defmethod (peek-frame :after :deexpose) (&rest ignore) (activate-peek-rate-maintainer nil)) (DEFUN PEEK-RATES (IGNORE) "Statistics counter rates" (activate-peek-rate-maintainer t) (SCROLL-MAINTAIN-LIST #'(LAMBDA () peek-rate-list) #'(LAMBDA (pr) (SCROLL-PARSE-ITEM `(:STRING ,(STRING (peek-rate-counter-name pr)) 35.) `(:function ,#'(lambda (pr) (case (peek-rate-counter-type pr) (:meter (read-meter (peek-rate-counter-name pr))) (:function (funcall (peek-rate-counter-name pr))))) (,pr) nil ("~15:d" 10. T)) `(:function ,#'(lambda (pr) ; (// (* (// 60. peek-maintain-rates-number-of-sixtieths) ; (peek-rate-average pr)) ; peek-maintain-rates-time-constant) (fix (* 0.12 (peek-rate-average pr))) ) (,pr) nil ("~15:d" 10. T)))))) (DEFINE-PEEK-MODE PEEK-COUNTERS #/% "Statistics Counters" NIL "Display the values of all the microcode meters.") (DEFUN PEEK-COUNTERS (IGNORE) "Statistics counters" (cond (t ;(not (fboundp 'si::read-main-stat-counter)) (LIST () (SCROLL-MAINTAIN-LIST #'(LAMBDA () SYS:A-MEMORY-COUNTER-BLOCK-NAMES) #'(LAMBDA (COUNTER) (SCROLL-PARSE-ITEM `(:STRING ,(STRING COUNTER) 35.) `(:FUNCTION READ-METER (,COUNTER) NIL ("~@15A" 10. T))))))) ; (t ; (LIST () ; (SCROLL-MAINTAIN-LIST #'(LAMBDA () SYS:A-MEMORY-COUNTER-BLOCK-NAMES) ; #'(LAMBDA (COUNTER) ; (SCROLL-PARSE-ITEM ; `(:STRING ,(STRING COUNTER) 35.) ; `(:FUNCTION READ-METER (,COUNTER) NIL ; ("~@15A" 10. T))))) ; (SCROLL-PARSE-ITEM "") ; (scroll-parse-item ; `(:mouse-item ; (nil :eval (peek-stat-counter-controls-menu) ; :documentation ; "Change stat counter controls.") ; :string "Statistics Counters" 20.)) ; (scroll-parse-item "Main: " ; `(:function ,#'(lambda () ; (nth (ldb si::%%main-stat-clock-control ; (si::read-rg-mode)) ; stat-clock-values)) ; () nil ("~a")) ; "; " ; `(:function ,#'(lambda () ; (nth (ldb si::%%main-stat-count-control ; (si::read-rg-mode)) ; stat-count-values)) ; () nil ("~a"))) ; (scroll-parse-item "Aux : " ; `(:function ,#'(lambda () ; (nth (ldb si::%%aux-stat-clock-control ; (si::read-rg-mode)) ; stat-clock-values)) ; () nil ("~a")) ; "; " ; `(:function ,#'(lambda () ; (nth (ldb si::%%aux-stat-count-control ; (si::read-rg-mode)) ; stat-count-values)) ; () nil ("~a"))) ; (scroll-parse-item "Main counter: " ; `(:function si::read-main-stat-counter () nil ("~20:d"))) ; (scroll-parse-item "Aux counter: " ; `(:function si::read-aux-stat-counter () nil ("~20:d"))) ; (scroll-parse-item "Main - Aux: " ; `(:function ,#'(lambda () ; (- (si::read-main-stat-counter) ; (si::read-aux-stat-counter))) ; () nil ("~20:d"))) ; (scroll-parse-item "Main // Aux: " ; `(:function ,#'(lambda () ; (let ((main (si::read-main-stat-counter)) ; (aux (si::read-aux-stat-counter))) ; (cond ((zerop aux) ; "***") ; (t ; (// (float main) aux))))) ; () nil ("~20f"))) ; (scroll-parse-item "Aux // Main: " ; `(:function ,#'(lambda () ; (let ((main (si::read-main-stat-counter)) ; (aux (si::read-aux-stat-counter))) ; (cond ((zerop main) ; "***") ; (t ; (// (float aux) main))))) ; () nil ("~20f"))) ; )) ; )) ;(defun peek-stat-counter-controls-menu () ; (process-run-function "Change Stat Counters" 'peek-stat-counter-controls-function)) ;(defvar peek-main-stat-clock :sm.clock) ;(defvar peek-main-stat-count :hi) ;(defvar peek-aux-stat-clock :sm.clock) ;(defvar peek-aux-stat-count :hi) ;(defconst stat-clock-values '(:SM.CLOCK :UINST.CLOCK)) ;(defconst stat-count-values '(:VALID.STATISTICS.BIT ; :MEMORY.START.NEXT.CYCLE ; :CSM.STATISTICS.BIT ; :INCREMENT.LC ; :T.HOLD ; :T.STATISTICS.BIT ; :1.MHZ.CLOCK ; :HI)) ;(defun make-atom-list-into-menu-alist (atom-list) ; (loop for a in atom-list ; collect (list (string a) a))) ;(defun peek-stat-counter-controls-function () ; (tv:choose-variable-values `((peek-main-stat-clock ; "Main stat clock" ; :menu-alist ,(make-atom-list-into-menu-alist stat-clock-values)) ; (peek-main-stat-count ; "Main stat count control" ; :menu-alist ,(make-atom-list-into-menu-alist stat-count-values)) ; (peek-aux-stat-clock ; "Aux stat clock" ; :menu-alist ,(make-atom-list-into-menu-alist stat-clock-values)) ; (peek-aux-stat-count ; "Aux stat count control" ; :menu-alist ,(make-atom-list-into-menu-alist stat-count-values)) ; "foo" ; "bar" ; ) ; ) ; (si::write-main-stat-control (find-position-in-list peek-main-stat-clock stat-clock-values) ; (find-position-in-list peek-main-stat-count stat-count-values)) ; (si::write-aux-stat-control (find-position-in-list peek-aux-stat-clock stat-clock-values) ; (find-position-in-list peek-aux-stat-count stat-count-values)) ;; (si::reset-stat-counters) ; ) ;;;; Memory (defun peek-memory-header () (scroll-parse-item "Physical memory: " `(:function ,(lambda (&aux (val (aref (symbol-function 'system-communication-area) %sys-com-memory-size))) (setf (value 0) (truncate val #o2000)) val) nil nil (nil 8.)) `(:value 0 nil (" (~DK), ")) "Free space: " `(:function ,(lambda (&aux (val (si::free-space))) (setf (value 0) (truncate val #o2000)) val) nil nil (nil 8.)) `(:value 0 nil (" (~DK)")) ", Wired pages " `(:function ,(lambda () (multiple-value-bind (n-wired-pages n-fixed-wired-pages) (si::count-wired-pages) (setf (value 0) (- n-wired-pages n-fixed-wired-pages)) (setf (value 1) (truncate n-wired-pages (truncate 2000 page-size))) (setf (value 2) (\ n-wired-pages (truncate 2000 page-size))) n-fixed-wired-pages)) nil nil ("~D")) `(:value 0 nil ("+~D ")) `(:value 1 nil ("(~D")) `(:value 2 nil ("~[~;.25~;.5~;.75~]K)")))) (define-peek-mode peek-areas #/A "Areas" nil "Display status of areas, including how much memory allocated and used.") (defconst *first-interesting-area* working-storage-area "All areas  this are uninteresting crufty system frobs and kludges.") (defun peek-areas (ignore) "Areas" (list () (peek-memory-header) (scroll-parse-item "") (scroll-maintain-list (lambda () 'boring) (lambda (area) (if (eq area 'boring) (list '(:pre-process-function peek-areas-boring-display) (scroll-parse-item :mouse-self '(nil :eval (peek-mouse-click 'self 0) :documentation "Insert//remove display of boring areas.") :leader `(nil) `(:function ,(lambda () (1- *first-interesting-area*)) () nil (" 0-~D /"Uninteresting/" system-internal areas")))) (list '(:pre-process-function peek-areas-region-display) (scroll-parse-item :mouse-self '(nil :eval (peek-mouse-click 'self 0) :documentation "Insert//remove display of all regions in this area.") :leader `(nil ,area) `(:function identity (,area) 4 ("~3D")) `(:string ,(string (area-name area)) 40.) `(:function ,(lambda (area) (multiple-value-bind (length used n-regions) (si::room-get-area-length-used area) (setf (value 0) used) (setf (value 1) length) (setf (value 2) (cond ((zerop length) 0) ((< length #o40000) (truncate (* 100. (- length used)) length)) (t (truncate (- length used) (truncate length 100.))))) n-regions)) (,area) 15. ("(~D region~0@*~P)")) `(:value 2 nil ("~@3A% free, " 10. t)) `(:value 0 nil ("~8O")) `(:value 1 nil ("//~8O used")))))) nil (lambda (state &aux next-one this-one (len (array-length (symbol-function 'area-name)))) (if (eq state 'boring) (values 'boring *first-interesting-area* nil) (do ((i state (1+ i))) (( i len) nil) (cond ((and (null this-one) (aref (symbol-function 'area-name) i)) (setq this-one i)) ((and this-one (aref (symbol-function 'area-name) i)) (setq next-one i) (return t)))) (values this-one next-one (null next-one))))))) (defun peek-areas-boring-display (item) "Handles adding/deleting of the boring areas when a mouse button is clicked." (cond ((null (array-leader (cadr item) scroll-item-leader-offset))) ;; Clicked on this item, need to complement state ((= (length item) 2) ;; If aren't displaying boredom now, display it (setf (cddr item) (ncons (scroll-maintain-list (lambda () 0) (lambda (area) (list '(:pre-process-function peek-areas-region-display) (scroll-parse-item :mouse-self '(nil :eval (peek-mouse-click 'self 0) :documentation "Insert//remove display of all regions in this boring area.") :leader `(nil ,area) `(:function identity (,area) 5 (" ~3D")) `(:string ,(string (area-name area)) 39.) `(:function ,(lambda (area) (multiple-value-bind (length used n-regions) (si::room-get-area-length-used area) (setf (value 0) used) (setf (value 1) length) (setf (value 2) (cond ((zerop length) 0) ((< length #o40000) (truncate (* 100. (- length used)) length)) (t (truncate (- length used) (truncate length 100.))))) n-regions)) (,area) 15. ("(~D region~0@*~P)")) `(:value 2 nil ("~@3A% free, " 10. t)) `(:value 0 nil ("~O")) `(:value 1 nil ("//~O used"))))) nil (lambda (state &aux next-one this-one) (do ((i state (1+ i))) (( i *first-interesting-area*) nil) (cond ((and (null this-one) (aref (symbol-function 'area-name) i)) (setq this-one i)) ((and this-one (aref (symbol-function 'area-name) i)) (setq next-one i) (return t)))) (values this-one next-one (null next-one))))))) (t (setf (cddr item) nil))) (setf (array-leader (cadr item) scroll-item-leader-offset) nil)) (defun peek-areas-region-display (item) "Handles adding/deleting of the region display when a mouse button is clicked." (cond ((null (array-leader (cadr item) scroll-item-leader-offset))) ;; Clicked on this item, need to complement state ((= (length item) 2) ;; If aren't displaying regions now, display them (setf (cddr item) (ncons (scroll-maintain-list (lambda () (si:%area-region-list (array-leader (first (scroll-items item)) (1+ scroll-item-leader-offset)))) (lambda (region) (if (minusp region) (scroll-parse-item `(:string " No regions in this area")) (scroll-parse-item `(:string ,(format nil " ~3O: Origin ~8O, Length ~8O, " region (si:%pointer-unsigned (si::%region-origin region)) (si::%region-length region))) `(:function ,#'si::%region-free-pointer (,region) nil ("Used ~8O, ")) `(:function ,(lambda (region) (let ((used (si::%region-free-pointer region)) (scavenged (si::%region-gc-pointer region))) (cond ((not (si::%region-scavenge-enable region)) "Scavenger off, ") ((= used scavenged) "Scavenge done, ") ((= used 0) "Scavenged 0%, ") (t (format nil "Scavenged ~D%, " (round (* 100. (// (float scavenged) (float used))))))))) (,region)) `(:string ,(format nil "~A space, Vol=~D." (nth (si::%region-type region) '(free old new new1 new2 new3 new4 new5 new6 static fixed extra-pdl copy)) (si::%region-volatility region)))))) nil (lambda (state) (if (minusp state) ;; no regions at all in this area (values -1 -1 t) (values state (si:%region-list-thread state) (minusp (si:%region-list-thread state))))))))) (t (setf (cddr item) nil))) (setf (array-leader (cadr item) scroll-item-leader-offset) nil)) (DEFINE-PEEK-MODE PEEK-page-status #/M "Memory Usage" NIL "Percent of each area paged in.") (DEFUN PEEK-page-status (IGNORE) "Page Status" (LIST () (scroll-maintain-list #'(lambda () (loop for i from si:VIRTUAL-PAGE-DATA below (array-length #'area-name) when (aref #'area-name i) collect (aref #'area-name i))) #'(lambda (area) (scroll-parse-item `(:string ,(string area) 40.) `(:function page-status-function (,area) nil ("~@15A" 10. t))))))) (defun page-status-function (area &aux (total-pages 0) (paged-in-pages 0)) (gc:without-flipping (si:for-every-region-in-area (region (symbol-value area)) (select (ldb %%region-space-type (si:%region-bits region)) ((%REGION-SPACE-FREE %REGION-SPACE-OLD %REGION-SPACE-EXTRA-PDL %REGION-SPACE-MOBY-FIXED %REGION-SPACE-MOBY-NEW)) ((%REGION-SPACE-NEW %REGION-SPACE-STATIC %REGION-SPACE-FIXED %REGION-SPACE-COPY) (let ((pages-in-this-region (ceiling (si:%region-free-pointer region) page-size))) (incf total-pages pages-in-this-region) (dotimes (page-number pages-in-this-region) (if (%page-status (ash page-number 8)) (incf paged-in-pages))))) (t (ferror nil "unknown region space type"))))) (when (not (zerop total-pages)) (format nil "~2d% of ~5d pages" (round (* 100. (// (float paged-in-pages) total-pages))) total-pages))) ;;;; File system status (DEFINE-PEEK-MODE PEEK-FILE-SYSTEM #/F "File System Status" NIL "Display status of FILE protocol connections to remote file systems.") (DEFUN NEXT-INTERESTING-FILE-HOST-STEPPER (LIST) (LET ((GOOD (SOME LIST (LAMBDA (X) (SEND-IF-HANDLES X :ACCESS))))) (VALUES (CAR GOOD) (CDR GOOD) (NULL GOOD)))) (defun file-host-item-function (host) (when host (list (list :pre-process-function 'peek-file-host-pre-process :host host :access nil :host-units nil) '(nil) '(nil)))) (defun peek-file-host-pre-process (item) (let* ((host (getf (tv:scroll-item-plist item) :host)) (access (getf (tv:scroll-item-plist item) :access)) (host-units (getf (tv:scroll-item-plist item) :host-units)) (new-access (send host :access)) (new-host-units (send-if-handles new-access :host-units))) (unless (and (eq access new-access) (equal host-units new-host-units)) (setf (getf (tv:scroll-item-plist item) :access) new-access) (setf (getf (tv:scroll-item-plist item) :host-units) new-host-units) (setf (cdr (tv:scroll-item-component-items item)) (append (send host :peek-file-system-header) (send host :peek-file-system)))))) (defun peek-file-system (ignore) "Display status of file system" (scroll-maintain-list #'(lambda () fs:*pathname-host-list*) 'file-host-item-function nil 'next-interesting-file-host-stepper)) (DEFMETHOD (SI::FILE-DATA-STREAM-MIXIN :PEEK-FILE-SYSTEM) (&OPTIONAL (INDENT 0) &AUX DIRECTION) "Returns a scroll item describing a stream" (TV:SCROLL-PARSE-ITEM :MOUSE `(NIL :EVAL (PEEK-FILE-SYSTEM-STREAM-MENU ',SELF) :DOCUMENTATION "Menu of useful things to do to this open file.") (AND ( INDENT 0) (FORMAT NIL "~V@T" INDENT)) (CASE (SETQ DIRECTION (SEND SELF :DIRECTION)) (:INPUT "Input ") (:OUTPUT "Output ") (OTHERWISE "?Direction? ")) (SEND (SEND SELF :PATHNAME) :STRING-FOR-PRINTING) (IF (SEND SELF :CHARACTERS) ", Character, " ", Binary, ") `(:FUNCTION ,#'(LAMBDA (STREAM) (SETF (TV:VALUE 0) (SEND STREAM :READ-POINTER)) (TV:VALUE 0)) (,SELF) NIL ("~D")) (AND (EQ DIRECTION :INPUT) `(:FUNCTION ,#'(LAMBDA (STREAM) (LET ((LENGTH (SEND STREAM :LENGTH))) (AND LENGTH (NOT (ZEROP LENGTH)) (TRUNCATE (* 100. (TV:VALUE 0)) LENGTH)))) (,SELF) NIL ("~@[ (~D%)~]"))) " bytes")) (DEFUN PEEK-FILE-SYSTEM-STREAM-MENU (STREAM) (APPLY #'PROCESS-RUN-FUNCTION "Peek File System Menu" SELF :PEEK-FILE-SYSTEM-MENU (LIST STREAM))) (DEFMETHOD (BASIC-PEEK :PEEK-FILE-SYSTEM-MENU) (STREAM) (LET ((*TERMINAL-IO* TYPEOUT-WINDOW)) (MENU-CHOOSE `(("Close" :EVAL (SEND ',STREAM :CLOSE) :DOCUMENTATION "Close selected file (normally).") ("Abort" :EVAL (SEND ',STREAM :CLOSE :ABORT) :DOCUMENTATION "Close selected file (aborts writing).") ("Delete" :EVAL (SEND ',STREAM :DELETE) :DOCUMENTATION "Delete selected file, but don't close it.") ("Describe" :EVAL (DESCRIBE ',STREAM) :DOCUMENTATION "Describe the file's stream.") ("Inspect" :EVAL (INSPECT ',STREAM) :DOCUMENTATION "Inspect the file's stream.") ) (STRING (SEND STREAM :TRUENAME))))) (DEFUN PEEK-PROCESS-MENU (&REST ARGS) (APPLY #'PROCESS-RUN-FUNCTION "Peek Process Menu" SELF :PEEK-PROCESS-MENU ARGS)) (DEFMETHOD (BASIC-PEEK :PEEK-PROCESS-MENU) (PROCESS &REST IGNORE &AUX CHOICE) "Menu for interesting operations on processes in a peek display" (LET ((*TERMINAL-IO* TYPEOUT-WINDOW) (CHOICES '(("Debugger" :VALUE PROCESS-EH :DOCUMENTATION "Call the debugger to examine the selected process.") ("Arrest" :VALUE PROCESS-ARREST :DOCUMENTATION "Arrest the selected process. Undone by Un-Arrest.") ("Un-Arrest" :VALUE PROCESS-UN-ARREST :DOCUMENTATION "Un-Arrest the selected process. Complement of Arrest.") ("Flush" :VALUE PROCESS-FLUSH :DOCUMENTATION "Unwind the selected process' stack and make it unrunnable. Ask for confirmation.") ("Reset" :VALUE PROCESS-RESET :DOCUMENTATION "Reset the selected process. Ask for confirmation.") ("Kill" :VALUE PROCESS-KILL :DOCUMENTATION "Kill the selected process. Ask for confirmation.") ("Describe" :VALUE PROCESS-DESCRIBE :DOCUMENTATION "Call DESCRIBE on this process.") ("Inspect" :VALUE PROCESS-INSPECT :DOCUMENTATION "Call INSPECT on this process.")))) ;; Don't offer EH for a simple process. (OR (TYPEP (PROCESS-STACK-GROUP PROCESS) 'STACK-GROUP) (POP CHOICES)) (SETQ CHOICE (MENU-CHOOSE CHOICES (PROCESS-NAME PROCESS))) (CASE CHOICE (PROCESS-ARREST (SEND PROCESS :ARREST-REASON)) (PROCESS-UN-ARREST (SEND PROCESS :REVOKE-ARREST-REASON)) (PROCESS-FLUSH (IF (MOUSE-Y-OR-N-P (FORMAT NIL "Flush ~A" PROCESS)) (SEND PROCESS :FLUSH))) (PROCESS-RESET (IF (MOUSE-Y-OR-N-P (FORMAT NIL "Reset ~A" PROCESS)) (SEND PROCESS :RESET))) (PROCESS-KILL (IF (MOUSE-Y-OR-N-P (FORMAT NIL "Kill ~A" PROCESS)) (SEND PROCESS :KILL))) (PROCESS-EH (SEND SELF :FORCE-KBD-INPUT `(EH ,PROCESS))) (PROCESS-DESCRIBE (SEND SELF :FORCE-KBD-INPUT `(DESCRIBE ,PROCESS))) (PROCESS-INSPECT (SEND SELF :FORCE-KBD-INPUT `(INSPECT ,PROCESS))) (NIL) (OTHERWISE (BEEP))))) ;;;; Peeking at windows ;; Copied from LAD: RELEASE-3.WINDOW; PEEK.LISP#191 on 2-Oct-86 04:12:43 (DEFINE-PEEK-MODE PEEK-WINDOW-HIERARCHY #/W "Window Hierarchy" NIL "Display the hierarchy of window inferiors, saying which are exposed.") (DEFUN PEEK-WINDOW-HIERARCHY (IGNORE) (SCROLL-MAINTAIN-LIST #'(LAMBDA () ALL-THE-SCREENS) #'(LAMBDA (SCREEN) (LIST () (SCROLL-PARSE-ITEM (FORMAT NIL "Screen ~A" SCREEN)) (PEEK-WINDOW-INFERIORS SCREEN 2) (SCROLL-PARSE-ITEM ""))))) (DEFUN PEEK-WINDOW-INFERIORS (WINDOW INDENT) (SCROLL-MAINTAIN-LIST #'(LAMBDA () (SHEET-INFERIORS WINDOW)) #'(LAMBDA (SHEET) (LIST () (SCROLL-PARSE-ITEM (FORMAT NIL "~V@T" INDENT) `(:MOUSE (NIL :EVAL (PEEK-WINDOW-MENU ',SHEET) :DOCUMENTATION "Menu of useful things to do to this window.") :STRING ,(SEND SHEET :NAME))) (PEEK-WINDOW-INFERIORS SHEET (+ INDENT 4)))))) (DEFUN PEEK-WINDOW-MENU (&REST ARGS) (APPLY #'PROCESS-RUN-FUNCTION "Peek Window Menu" #'PEEK-WINDOW-MENU-INTERNAL SELF ARGS)) (DEFUN PEEK-WINDOW-MENU-INTERNAL (PEEK-WINDOW SHEET &REST IGNORE &AUX CHOICE) "Menu for interesting operations on sheets in a peek display" (SETQ CHOICE (MENU-CHOOSE '(("Deexpose" :VALUE :DEEXPOSE :DOCUMENTATION "Deexpose the window.") ("Expose" :VALUE :EXPOSE :DOCUMENTATION "Expose the window.") ("Select" :VALUE :SELECT :DOCUMENTATION "Select the window.") ("Deselect" :VALUE :DESELECT :DOCUMENTATION "Deselect the window.") ("Deactivate" :VALUE :DEACTIVATE :DOCUMENTATION "Deactivate the window.") ("Kill" :VALUE :KILL :DOCUMENTATION "Kill the window.") ("Bury" :VALUE :BURY :DOCUMENTATION "Bury the window.") ("Inspect" :VALUE :INSPECT :DOCUMENTATION "Look at window data structure.")) (SEND SHEET :NAME))) (AND CHOICE (OR (NEQ CHOICE :KILL) (MOUSE-Y-OR-N-P (FORMAT NIL "Kill ~A" (SEND SHEET :NAME)))) (IF (EQ CHOICE :INSPECT) (SEND PEEK-WINDOW :FORCE-KBD-INPUT `(INSPECT ,SHEET)) (SEND SHEET CHOICE)))) (DEFINE-PEEK-MODE PEEK-SERVERS #/S "Active Servers" NIL "List all servers, who they are serving, and their status.") (DEFUN PEEK-SERVERS (IGNORE) (LIST () (SCROLL-PARSE-ITEM "Active Servers") (SCROLL-PARSE-ITEM "Contact Name Host Process // State") (SCROLL-PARSE-ITEM " Connection") (SCROLL-PARSE-ITEM "") (SCROLL-MAINTAIN-LIST #'(LAMBDA () (SEND TV:WHO-LINE-FILE-STATE-SHEET :SERVERS)) #'(LAMBDA (SERVER-DESC) (LET* ((PROCESS (SERVER-DESC-PROCESS SERVER-DESC)) (CONN (SERVER-DESC-CONNECTION SERVER-DESC)) (contact (server-desc-contact-name server-desc)) (HOST (if (typep conn 'chaos:conn) (SI:GET-HOST-FROM-ADDRESS (CHAOS:FOREIGN-ADDRESS CONN) :CHAOS) (nth-value 1 (ip:parse-internet-address (send conn :remote-address)))))) (LIST '(:PRE-PROCESS-FUNCTION PEEK-SERVER-PREPROCESS) (SCROLL-PARSE-ITEM :LEADER '(NIL NIL NIL) `(:FUNCTION ,#'values (,contact) 20. ("~A")) `(:MOUSE-ITEM (NIL :EVAL (CHAOS:PEEK-CHAOS-HOST-MENU ',HOST 'TV:ITEM 0) :DOCUMENTATION "Menu of useful things to do to this host.") :FUNCTION ,#'VALUES (,HOST) 20. ("~A")) `(:MOUSE (NIL :EVAL (PEEK-PROCESS-MENU ',PROCESS) :DOCUMENTATION "Menu of useful things to do to this process.") :STRING ,(FORMAT NIL "~S" PROCESS)) " " `(:FUNCTION ,#'PEEK-WHOSTATE ,(NCONS PROCESS))) (SCROLL-PARSE-ITEM :LEADER '(NIL NIL NIL NIL NIL NIL) ;6 " " `(:MOUSE-ITEM (NIL :EVAL (PEEK-CONNECTION-MENU ',CONN 'ITEM ',host ',contact) :DOCUMENTATION "Menu of useful things to do this connection") :STRING ,(FORMAT NIL "~S" CONN))) NIL ;Connection stat NIL ;hostat (AND (SERVER-DESC-FUNCTION SERVER-DESC) (APPLY (SERVER-DESC-FUNCTION SERVER-DESC) (SERVER-DESC-ARGS SERVER-DESC))))))))) (DEFUN PEEK-CONNECTION-MENU (CONN ITEM host contact) (APPLY #'PROCESS-RUN-FUNCTION "Peek Server Connection Menu" SELF :PEEK-SERVER-CONNECTION-MENU (LIST CONN ITEM host contact))) (DEFMETHOD (BASIC-PEEK :PEEK-SERVER-CONNECTION-MENU) (CONN ITEM host contact) (LET ((*TERMINAL-IO* TYPEOUT-WINDOW)) (LET ((CHOICE (MENU-CHOOSE (append '(("Close" :VALUE :CLOSE :DOCUMENTATION "Close connection forcibly.")) (when (typep conn 'chaos:conn) '(("Insert Detail" :VALUE :DETAIL :DOCUMENTATION "Insert detailed info about chaos connection."))) (when (typep conn 'chaos:conn) '(("Remove Detail" :VALUE :UNDETAIL :DOCUMENTATION "Remove detailed info from Peek display."))) '(("Inspect" :VALUE :INSPECT :DOCUMENTATION "Inspect the connection"))) (STRING-APPEND host "//" contact)))) (CASE CHOICE (:CLOSE (if (typep conn 'chaos:conn) (CHAOS:CLOSE-CONN CONN "Manual Close from PEEK") (send conn :close))) (:INSPECT (INSPECT CONN)) (:DETAIL (SETF (ARRAY-LEADER ITEM (+ 4 TV:SCROLL-ITEM-LEADER-OFFSET)) CONN) (SETF (ARRAY-LEADER ITEM (+ 5 TV:SCROLL-ITEM-LEADER-OFFSET)) T)) (:UNDETAIL (SETF (ARRAY-LEADER ITEM (+ 4 TV:SCROLL-ITEM-LEADER-OFFSET)) NIL) (SETF (ARRAY-LEADER ITEM (+ 5 TV:SCROLL-ITEM-LEADER-OFFSET)) NIL)))))) (DEFUN PEEK-SERVER-PREPROCESS (LIST-ITEM &AUX HOST) (LET* ((LINE-ITEM (THIRD LIST-ITEM)) (HOST-ITEM (SECOND LIST-ITEM)) (WANTED (ARRAY-LEADER LINE-ITEM (+ 4 TV:SCROLL-ITEM-LEADER-OFFSET))) (GOT (ARRAY-LEADER LINE-ITEM (+ 5 TV:SCROLL-ITEM-LEADER-OFFSET)))) (COND ((NULL WANTED) (SETF (ARRAY-LEADER LINE-ITEM (+ 5 TV:SCROLL-ITEM-LEADER-OFFSET)) NIL) (SETF (FOURTH LIST-ITEM) NIL)) ((EQ WANTED GOT)) (T (SETF (FOURTH LIST-ITEM) (CHAOS:PEEK-CHAOS-CONN WANTED)) (SETF (ARRAY-LEADER LINE-ITEM (+ 5 TV:SCROLL-ITEM-LEADER-OFFSET)) WANTED))) ;; Hack hostat (COND ((ARRAY-LEADER HOST-ITEM TV:SCROLL-ITEM-LEADER-OFFSET) ;; Want a hostat, make sure it's there and for the right host (IF (AND (EQ (SETQ HOST (ARRAY-LEADER HOST-ITEM (1+ TV:SCROLL-ITEM-LEADER-OFFSET))) (ARRAY-LEADER HOST-ITEM (+ TV:SCROLL-ITEM-LEADER-OFFSET 2))) (FIFTH LIST-ITEM)) NIL (SETF (FIFTH LIST-ITEM) (CONS '() (CHAOS:PEEK-CHAOS-HOSTAT HOST 1))) (SETF (ARRAY-LEADER HOST-ITEM (+ TV:SCROLL-ITEM-LEADER-OFFSET 2)) HOST))) (T (SETF (FIFTH LIST-ITEM) NIL) (SETF (ARRAY-LEADER HOST-ITEM (+ TV:SCROLL-ITEM-LEADER-OFFSET 2)) NIL))))) (define-peek-mode peek-devices #/D "Devices" NIL "Display information about devices.") (defun peek-devices (ignore) "Devices" (list () (scroll-maintain-list #'(lambda () (reverse (loop for x in fs:*pathname-host-list* when (typep x 'si:shared-device) collect x))) #'(lambda (dev) (scroll-parse-item `(:mouse-item (nil :eval (peek-device-menu ',dev 'item 0) :documentation "Menu of useful things to do to this device.") :string ,(send dev :name) 20.) `(:function peek-dev-lock (,dev) nil ("~30a")) `(:function peek-dev-owner (,dev) nil ("~10a")) ))))) (defun peek-dev-lock (dev) (let ((lock (car (send dev :lock)))) (cond ((null lock) "not locked") (t (send lock :name))))) (defun peek-dev-owner (dev) (let ((owner (send dev :owner))) (cond ((null owner) "free") ((eq owner :not-on-bus) "not on bus") (t (format nil "slot ~d" owner))))) (defun peek-device-menu (&rest args) (apply #'process-run-function "Peek Device Menu" self :peek-device-menu args)) (defmethod (basic-peek :peek-device-menu) (dev &rest ignore &aux choice) "Menu for interesting operations on devices in a peek display" (let ((*terminal-io* typeout-window) (choices '(("Select window with lock" :value select :documentation "Select the window who holds the lock for this device.") ("Clear lock" :value clear :documentation "Clear the lock for this device.") ))) (setq choice (menu-choose choices (send dev :name))) (case choice (select (let ((proc (car (send dev :lock)))) (if (null proc) (beep) (dolist (w (send proc :run-reasons) (beep)) (when (typep w 'tv:minimum-window) (send w :select) (return nil)))))) (clear (rplaca (send dev :lock) nil)) (nil) (otherwise (beep))))) (define-peek-mode peek-general-status #/G "General Status" NIL "Random internal processor state.") (defstruct (peek-general-status-item (:type :named-array) (:conc-name peek-gs-) (:print (format nil "#" (peek-gs-pretty-name peek-general-status-item) ))) name pretty-name get-function set-function ) (defun peek-gs-get-from-processor-switches (bit-name) (ldb (symeval bit-name) (%processor-switches nil))) (defun peek-gs-set-processor-switches (bit-name val) (%processor-switches (dpb val (symeval bit-name) (%processor-switches nil)))) (defvar peek-processor-switch-items ()) (defun peek-processor-switch-items () (or peek-processor-switch-items (setq peek-processor-switch-items (loop for x in si::lambda-processor-switches-bits by 'cddr collect (make-peek-general-status-item :name x :pretty-name (string-capitalize-words (if (string-equal x "%%PROCESSOR-SWITCH-" :end1 #o23) (substring x #o23) x)) :get-function 'peek-gs-get-from-processor-switches :set-function 'peek-gs-set-processor-switches))))) (defun peek-general-status (ignore) "General Status" (list () (scroll-maintain-list #'(lambda () (peek-processor-switch-items)) #'(lambda (item) (scroll-parse-item `(:function ,(peek-gs-get-function item) (,(peek-gs-name item)) () ("~@5A " 10. T)) `(:string ,(peek-gs-pretty-name item) 50.) ))))) (defun create-first-peek-frame () (or (dolist (x (selectable-windows tv:main-screen)) (when (typep (second x) 'peek-frame) (return t))) (make-instance 'peek-frame :activate-p t))) (add-initialization "Create a Peek Frame" '(create-first-peek-frame) '(:once)) (tv:add-system-key #/P 'PEEK-FRAME "Peek" T)