diff options
author | Eli Zaretskii <eliz@gnu.org> | 2017-01-13 11:48:51 +0200 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2017-01-13 11:48:51 +0200 |
commit | 03e4ab0d586069be65e4a17fbf4cd965a9984726 (patch) | |
tree | 729d86e3282165ca0d58bec8bde33661c9b60ed9 /test/src/thread-tests.el | |
parent | 62e27ebd54336d30a90ae71e5bdcb910e954c061 (diff) | |
download | emacs-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.el | 41 |
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 |