+
;;;; miscellaneous tests of thread stuff
;;;; This software is part of the SBCL system. See the README file for
(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")
+ #-sunos "cc" #+sunos "gcc"
+ (or #+(or linux freebsd sunos) '("-shared" "-o" "threads-foreign.so" "threads-foreign.c")
+ #+darwin '("-dynamiclib" "-o" "threads-foreign.so" "threads-foreign.c")
(error "Missing shared library compilation options for this platform"))
:search t)
(sb-alien:load-shared-object "threads-foreign.so")
(with-mutex (l)
(with-recursive-lock (l)))))
-(let ((l (make-spinlock :name "spinlock"))
- (p *current-thread*))
+(let ((l (make-spinlock :name "spinlock")))
(assert (eql (spinlock-value l) 0) nil "1")
(with-spinlock (l)
- (assert (eql (spinlock-value l) p) nil "2"))
+ (assert (eql (spinlock-value l) 1) nil "2"))
(assert (eql (spinlock-value l) 0) nil "3"))
;; test that SLEEP actually sleeps for at least the given time, even
(defun send-gc ()
(loop until (< *n-gcs-done* *n-gcs-requested*))
- (format t "G" *n-gcs-requested* *n-gcs-done*)
+ (format t "G")
(force-output)
(sb-ext:gc)
(incf *n-gcs-done*))
(push (sb-thread:make-thread #'exercise-binding) threads)
(push (sb-thread:make-thread (lambda ()
(loop
+ (sleep 0.1)
(send-gc))))
threads)
(sleep 4))
(format t "~&binding test done~%")
+;; Try to corrupt the NEXT-VECTOR. Operations on a hash table with a
+;; cyclic NEXT-VECTOR can loop endlessly in a WITHOUT-GCING form
+;; causing the next gc hang SBCL.
+(with-test (:name (:hash-table-thread-safety))
+ (let* ((hash (make-hash-table))
+ (threads (list (sb-thread:make-thread
+ (lambda ()
+ (loop
+ ;;(princ "1") (force-output)
+ (setf (gethash (random 100) hash) 'h))))
+ (sb-thread:make-thread
+ (lambda ()
+ (loop
+ ;;(princ "2") (force-output)
+ (remhash (random 100) hash))))
+ (sb-thread:make-thread
+ (lambda ()
+ (loop
+ (sleep (random 1.0))
+ (sb-ext:gc :full t)))))))
+ (unwind-protect
+ (sleep 5)
+ (mapc #'sb-thread:terminate-thread threads))))
+(format t "~&hash table test done~%")
#| ;; a cll post from eric marsden
| (defun crash ()
| (setq *debugger-hook*
| (mp:make-process #'roomy)
| (mp:make-process #'roomy)))
|#
+
+(with-test (:name (:condition-variable :notify-multiple))
+ (flet ((tester (notify-fun)
+ (let ((queue (make-waitqueue :name "queue"))
+ (lock (make-mutex :name "lock"))
+ (data nil))
+ (labels ((test (x)
+ (loop
+ (with-mutex (lock)
+ (format t "condition-wait ~a~%" x)
+ (force-output)
+ (condition-wait queue lock)
+ (format t "woke up ~a~%" x)
+ (force-output)
+ (push x data)))))
+ (let ((threads (loop for x from 1 to 10
+ collect
+ (let ((x x))
+ (sb-thread:make-thread (lambda ()
+ (test x)))))))
+ (sleep 5)
+ (with-mutex (lock)
+ (funcall notify-fun queue))
+ (sleep 5)
+ (mapcar #'terminate-thread threads)
+ ;; Check that all threads woke up at least once
+ (assert (= (length (remove-duplicates data)) 10)))))))
+ (tester (lambda (queue)
+ (format t "~&(condition-notify queue 10)~%")
+ (force-output)
+ (condition-notify queue 10)))
+ (tester (lambda (queue)
+ (format t "~&(condition-broadcast queue)~%")
+ (force-output)
+ (condition-broadcast queue)))))
+
+(with-test (:name (:mutex :finalization))
+ (let ((a nil))
+ (dotimes (i 500000)
+ (setf a (make-mutex)))))
+
+
+
+