0.8.21.20
[sbcl.git] / tests / threads.impure.lisp
index 4b59604..f33577a 100644 (file)
 
 (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
 
-(with-open-file (o "threads-foreign.c" :direction :output)
+(with-open-file (o "threads-foreign.c" :direction :output :if-exists :supersede)
   (format o "void loop_forever() { while(1) ; }~%"))
 (sb-ext:run-program    
  "cc"
  (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)
 
 
   (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 ()