diff --git a/pkgs/racket-test/tests/future/fsema-lock.rkt b/pkgs/racket-test/tests/future/fsema-lock.rkt new file mode 100644 index 0000000000..f76f332e4f --- /dev/null +++ b/pkgs/racket-test/tests/future/fsema-lock.rkt @@ -0,0 +1,28 @@ +#lang racket/base +(require racket/future) + +;; Make sure fsemaphores can work like locks, as +;; long as every future that might hold a lock is +;; demanded by a thread (so it must continue to +;; run if it takes a lock) + +(for ([N (in-range 4 20)]) + (define f (make-fsemaphore 1)) + (define working (box 'ok)) + (define fts + (for/list ([i (in-range N)]) + (define ft + (future + (lambda () + (for ([i (in-range 5000)]) + (fsemaphore-wait f) + (unless (box-cas! working 'ok 'not-ok) + (printf "FAIL\n") + (exit 1)) + (unless (box-cas! working 'not-ok 'ok) + (printf "FAIL\n") + (exit 1)) + (fsemaphore-post f))))) + (thread (lambda () (touch ft))) + ft)) + (for-each touch fts)) diff --git a/racket/src/racket/src/future.c b/racket/src/racket/src/future.c index 9295f5ac8b..4e1f87e5e6 100644 --- a/racket/src/racket/src/future.c +++ b/racket/src/racket/src/future.c @@ -1625,9 +1625,11 @@ Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object **argv) return scheme_void; } - mzrt_mutex_unlock(sema->mut); - sema = block_until_sema_ready(sema); - mzrt_mutex_lock(sema->mut); + do { + mzrt_mutex_unlock(sema->mut); + sema = block_until_sema_ready(sema); + mzrt_mutex_lock(sema->mut); + } while (!sema->ready); } else { /* On a future thread, suspend the future (to be resumed whenever the fsema becomes ready */