summaryrefslogtreecommitdiff
path: root/test/src/thread-tests.el
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2017-01-13 11:48:51 +0200
committerEli Zaretskii <eliz@gnu.org>2017-01-13 11:48:51 +0200
commit03e4ab0d586069be65e4a17fbf4cd965a9984726 (patch)
tree729d86e3282165ca0d58bec8bde33661c9b60ed9 /test/src/thread-tests.el
parent62e27ebd54336d30a90ae71e5bdcb910e954c061 (diff)
downloademacs-03e4ab0d586069be65e4a17fbf4cd965a9984726.tar.gz
Fix a bug in waiting for condition variable
* src/thread.c (lisp_mutex_lock, lisp_mutex_unlock) (lisp_mutex_unlock_for_wait, condition_wait_callback) (condition_notify_callback): Improve commentary. (condition_wait_callback): Call post_acquire_global_lock before attempting to lock the mutex, to make sure the lock's owner is recorded correctly. * test/src/thread-tests.el (threads-condvar-wait): New test.
Diffstat (limited to 'test/src/thread-tests.el')
-rw-r--r--test/src/thread-tests.el41
1 files changed, 41 insertions, 0 deletions
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index 2e5a3bcc1fa..71b20185d76 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -244,4 +244,45 @@
(sit-for 1)
(should-not (thread-alive-p thread))))
+(defvar threads-condvar nil)
+(defun threads-test-condvar-wait ()
+ ;; Wait for condvar to be notified
+ (mutex-lock (condition-mutex threads-condvar))
+ (condition-wait threads-condvar)
+ (mutex-unlock (condition-mutex threads-condvar))
+ ;; Wait again, it will be signaled.
+ (with-mutex (condition-mutex threads-condvar)
+ (condition-wait threads-condvar)))
+
+(ert-deftest threads-condvar-wait ()
+ "test waiting on conditional variable"
+ (let* ((cv-mutex (make-mutex))
+ (nthreads (length (all-threads)))
+ new-thread)
+ (setq threads-condvar (make-condition-variable cv-mutex))
+ (setq new-thread (make-thread #'threads-test-condvar-wait))
+ (while (not (eq (thread--blocker new-thread) threads-condvar))
+ (thread-yield))
+ (should (thread-alive-p new-thread))
+ (should (= (length (all-threads)) (1+ nthreads)))
+ ;; Notify the waiting thread.
+ (with-mutex cv-mutex
+ (condition-notify threads-condvar t))
+
+ ;; Allow new-thread to process the notification.
+ (sleep-for 0.1)
+ ;; Make sure the thread is still there. This used to fail due to
+ ;; a bug in condition_wait_callback.
+ (should (thread-alive-p new-thread))
+ (should (= (length (all-threads)) (1+ nthreads)))
+ (should (memq new-thread (all-threads)))
+ ;; Make sure the other thread waits at the condition variable again.
+ (should (eq (thread--blocker new-thread) threads-condvar))
+
+ ;; Signal the thread.
+ (thread-signal new-thread 'error '("Die, die, die!"))
+ (sleep-for 0.1)
+ ;; Make sure the thread died.
+ (should (= (length (all-threads)) nthreads))))
+
;;; threads.el ends here