Update of /cvsroot/sbcl/sbcl/src/code
In directory sc8-pr-cvs1:/tmp/cvs-serv16649/src/code
Modified Files:
condition.lisp ntrace.lisp target-signal.lisp unix.lisp
Log Message:
0.pre8.7
Implement WITH-TIMEOUT macro, using the SIGALRM handler.
Write each output from TRACE in a single write() call, to make
it much much easier (as in, possible) to see what's happening
when multiple threads are calling TRACEd code at once
Delete some dead code in compiler/x86/macros.lisp
Index: condition.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/condition.lisp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- condition.lisp 24 Mar 2003 18:39:00 -0000 1.22
+++ condition.lisp 25 Mar 2003 13:40:14 -0000 1.23
@@ -769,6 +769,11 @@
(reader-error-format-control condition)
(reader-error-format-arguments condition)
(reader-impossible-number-error-error condition))))))
+
+;;; should this inherit from error? good question
+(define-condition timeout (error) ())
+
+
;;;; special SBCL extension conditions
Index: ntrace.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/ntrace.lisp,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- ntrace.lisp 14 Dec 2002 22:10:08 -0000 1.28
+++ ntrace.lisp 25 Mar 2003 13:40:17 -0000 1.29
@@ -250,7 +250,7 @@
(trace-wherein-p frame wherein)))))
(when conditionp
(let ((sb-kernel:*current-level-in-print* 0)
- (*standard-output* *trace-output*)
+ (*standard-output* (make-string-output-stream))
(*in-trace* t))
(fresh-line)
(print-trace-indentation)
@@ -263,7 +263,9 @@
(prin1 `(,(trace-info-what info) ,@arg-list)))
(print-frame-call frame))
(terpri)
- (trace-print frame (trace-info-print info)))
+ (trace-print frame (trace-info-print info))
+ (write-sequence (get-output-stream-string *standard-output*)
+ *trace-output*))
(trace-maybe-break info (trace-info-break info) "before" frame)))
(lambda (frame cookie)
@@ -290,7 +292,7 @@
(let ((cond (trace-info-condition-after info)))
(and cond (funcall (cdr cond) frame)))))
(let ((sb-kernel:*current-level-in-print* 0)
- (*standard-output* *trace-output*)
+ (*standard-output* (make-string-output-stream))
(*in-trace* t))
(fresh-line)
(pprint-logical-block (*standard-output* nil)
@@ -302,7 +304,9 @@
(pprint-newline :linear)
(prin1 v)))
(terpri)
- (trace-print frame (trace-info-print-after info)))
+ (trace-print frame (trace-info-print-after info))
+ (write-sequence (get-output-stream-string *standard-output*)
+ *trace-output*))
(trace-maybe-break info
(trace-info-break-after info)
"after"
Index: target-signal.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/target-signal.lisp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- target-signal.lisp 6 Jun 2002 14:08:09 -0000 1.12
+++ target-signal.lisp 25 Mar 2003 13:40:19 -0000 1.13
@@ -114,7 +114,12 @@
#!-linux
(define-signal-handler sigsys-handler "bad argument to a system call")
(define-signal-handler sigpipe-handler "SIGPIPE")
-(define-signal-handler sigalrm-handler "SIGALRM")
+
+(defun sigalrm-handler (signal info context)
+ (declare (ignore signal info context))
+ (declare (type system-area-pointer context))
+ (cerror "Continue" 'sb!kernel::timeout))
+
(defun sigquit-handler (signal code context)
(declare (ignore signal code context))
Index: unix.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/unix.lisp,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- unix.lisp 7 Jun 2002 01:54:42 -0000 1.30
+++ unix.lisp 25 Mar 2003 13:40:20 -0000 1.31
@@ -685,6 +685,98 @@
(addr tz))))
+;; Type of the second argument to `getitimer' and
+;; the second and third arguments `setitimer'.
+(define-alien-type nil
+ (struct itimerval
+ (it-interval (struct timeval)) ; timer interval
+ (it-value (struct timeval)))) ; current value
+
+(defconstant ITIMER-REAL 0)
+(defconstant ITIMER-VIRTUAL 1)
+(defconstant ITIMER-PROF 2)
+
+(defun unix-getitimer(which)
+ "Unix-getitimer returns the INTERVAL and VALUE slots of one of
+ three system timers (:real :virtual or :profile). On success,
+ unix-getitimer returns 5 values,
+ T, it-interval-secs, it-interval-usec, it-value-secs, it-value-usec."
+ (declare (type (member :real :virtual :profile) which)
+ (values t
+ (unsigned-byte 29) (mod 1000000)
+ (unsigned-byte 29) (mod 1000000)))
+ (let ((which (ecase which
+ (:real ITIMER-REAL)
+ (:virtual ITIMER-VIRTUAL)
+ (:profile ITIMER-PROF))))
+ (with-alien ((itv (struct itimerval)))
+ (syscall* ("getitimer" int (* (struct itimerval)))
+ (values T
+ (slot (slot itv 'it-interval) 'tv-sec)
+ (slot (slot itv 'it-interval) 'tv-usec)
+ (slot (slot itv 'it-value) 'tv-sec)
+ (slot (slot itv 'it-value) 'tv-usec))
+ which (alien-sap (addr itv))))))
+
+(defun unix-setitimer (which int-secs int-usec val-secs val-usec)
+ " Unix-setitimer sets the INTERVAL and VALUE slots of one of
+ three system timers (:real :virtual or :profile). A SIGALRM signal
+ will be delivered VALUE <seconds+microseconds> from now. INTERVAL,
+ when non-zero, is <seconds+microseconds> to be loaded each time
+ the timer expires. Setting INTERVAL and VALUE to zero disables
+ the timer. See the Unix man page for more details. On success,
+ unix-setitimer returns the old contents of the INTERVAL and VALUE
+ slots as in unix-getitimer."
+ (declare (type (member :real :virtual :profile) which)
+ (type (unsigned-byte 29) int-secs val-secs)
+ (type (integer 0 (1000000)) int-usec val-usec)
+ (values t
+ (unsigned-byte 29) (mod 1000000)
+ (unsigned-byte 29) (mod 1000000)))
+ (let ((which (ecase which
+ (:real ITIMER-REAL)
+ (:virtual ITIMER-VIRTUAL)
+ (:profile ITIMER-PROF))))
+ (with-alien ((itvn (struct itimerval))
+ (itvo (struct itimerval)))
+ (setf (slot (slot itvn 'it-interval) 'tv-sec ) int-secs
+ (slot (slot itvn 'it-interval) 'tv-usec) int-usec
+ (slot (slot itvn 'it-value ) 'tv-sec ) val-secs
+ (slot (slot itvn 'it-value ) 'tv-usec) val-usec)
+ (syscall* ("setitimer" int (* (struct timeval))(* (struct timeval)))
+ (values T
+ (slot (slot itvo 'it-interval) 'tv-sec)
+ (slot (slot itvo 'it-interval) 'tv-usec)
+ (slot (slot itvo 'it-value) 'tv-sec)
+ (slot (slot itvo 'it-value) 'tv-usec))
+ which (alien-sap (addr itvn))(alien-sap (addr itvo))))))
+
+(defmacro with-timeout (expires &body body)
+ "Execute the body, interrupting it with a SIGALRM after at least
+EXPIRES seconds have passed. Uses Unix setitimer(), restoring any
+previous timer after the body has finished executing"
+ (let ((saved-seconds (gensym "SAVED-SECONDS"))
+ (saved-useconds (gensym "SAVED-USECONDS"))
+ (s (gensym "S")) (u (gensym "U")))
+ `(let (- ,saved-seconds ,saved-useconds)
+ (multiple-value-setq (- - - ,saved-seconds ,saved-useconds)
+ (unix-getitimer :real))
+ (multiple-value-bind (,s ,u) (floor ,expires)
+ (setf ,u (floor (* ,u 1000000)))
+ (if (and (> ,expires 0)
+ (or (and (zerop ,saved-seconds) (zerop ,saved-useconds))
+ (> ,saved-seconds ,s)
+ (and (= ,saved-seconds ,s)
+ (> ,saved-useconds ,u))))
+ (unwind-protect
+ (progn
+ (unix-setitimer :real 0 0 ,s ,u)
+ ,@body)
+ (unix-setitimer :real 0 0 ,saved-seconds ,saved-useconds))
+ ,@body)))))
+
+
+
(defconstant ENOENT 2) ; Unix error code, "No such file or directory"
(defconstant EINTR 4) ; Unix error code, "Interrupted system call"
(defconstant EIO 5) ; Unix error code, "I/O error"
|