X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=tests%2Fthreads.impure.lisp;h=f33577a2545aa11e57827f91e81ca3df11fd7122;hb=9b55754d5328a5f44ee224d32865fc8dadee123b;hp=c0feefe3d25298b7a1b2811cc82c846fa6a6bfa7;hpb=fb9c34275389e23f32d80954ab4848fac48936d9;p=sbcl.git diff --git a/tests/threads.impure.lisp b/tests/threads.impure.lisp index c0feefe..f33577a 100644 --- a/tests/threads.impure.lisp +++ b/tests/threads.impure.lisp @@ -15,6 +15,30 @@ (in-package "SB-THREAD") ; this is white-box testing, really +;;; We had appalling scaling properties for a while. Make sure they +;;; don't reappear. +(defun scaling-test (function &optional (nthreads 5)) + "Execute FUNCTION with NTHREADS lurking to slow it down." + (let ((queue (sb-thread:make-waitqueue)) + (mutex (sb-thread:make-mutex))) + ;; Start NTHREADS idle threads. + (dotimes (i nthreads) + (sb-thread:make-thread (lambda () + (sb-thread:condition-wait queue mutex) + (sb-ext:quit)))) + (let ((start-time (get-internal-run-time))) + (funcall function) + (prog1 (- (get-internal-run-time) start-time) + (sb-thread:condition-broadcast queue))))) +(defun fact (n) + "A function that does work with the CPU." + (if (zerop n) 1 (* n (fact (1- n))))) +(let ((work (lambda () (fact 15000)))) + (let ((zero (scaling-test work 0)) + (four (scaling-test work 4))) + ;; a slightly weak assertion, but good enough for starters. + (assert (< four (* 1.5 zero))))) + ;;; For one of the interupt-thread tests, we want a foreign function ;;; that does not make syscalls @@ -25,7 +49,7 @@ (or #+linux '("-shared" "-o" "threads-foreign.so" "threads-foreign.c") (error "Missing shared library compilation options for this platform")) :search t) -(sb-alien:load-1-foreign "threads-foreign.so") +(sb-alien:load-shared-object "threads-foreign.so") (sb-alien:define-alien-routine loop-forever sb-alien:void) @@ -42,6 +66,14 @@ (assert (eql (mutex-lock l) 0) nil "6") (describe l)) +;; test that SLEEP actually sleeps for at least the given time, even +;; if interrupted by another thread exiting/a gc/anything +(let ((start-time (get-universal-time))) + (make-thread (lambda () (sleep 1))) ; kid waits 1 then dies ->SIG_THREAD_EXIT + (sleep 5) + (assert (>= (get-universal-time) (+ 5 start-time)))) + + (let ((queue (make-waitqueue :name "queue")) (lock (make-mutex :name "lock"))) (labels ((in-new-thread ()