cs & thread: fix thread termination with pending timeout callback

In other words, follow a note on line 77 of "atomic.rkt":

     ;; There's a small chance that `end-atomic-callback`
     ;; was set by the scheduler after the check and
     ;; before we exit atomic mode. Make sure that rare
     ;; possibility remains ok.

That note was originally written in the context of changes for
futures, but it also applies to plain old thread scheduling, where
`engine-timeout` can be installed as a callback, but it's not allowed
if an engine isn't running.
This commit is contained in:
Matthew Flatt 2021-01-08 13:15:12 -07:00
parent f347fe299a
commit 1d0fd9c40b
3 changed files with 17 additions and 2 deletions

View File

@ -1938,6 +1938,7 @@
(loop_0 (cdr cbs_0)))))))))
(loop_0 all-cbs_0))
(|#%app| host:enable-interrupts))))))
(define flush-end-atomic-callbacks! (lambda () (end-atomic-callback 0)))
(define future-block-for-atomic (lambda () (void)))
(define set-future-block!
(lambda (block_0) (set! future-block-for-atomic block_0)))
@ -12482,6 +12483,7 @@
(if (zero? (current-atomic))
(void)
(internal-error "terminated in atomic mode!"))
(flush-end-atomic-callbacks!)
(thread-dead! t_0)
(if (eq? (unsafe-place-local-ref cell.1$1) t_0)
(force-exit 0)

View File

@ -22,11 +22,14 @@
future-barrier
add-end-atomic-callback!
flush-end-atomic-callbacks!
start-implicit-atomic-mode
end-implicit-atomic-mode
assert-atomic-mode
assert-no-end-atomic-callbacks
set-future-block!)
;; "atomically" is atomic within a place; when a future-running
@ -123,6 +126,9 @@
(loop (cdr cbs)))]))
(host:enable-interrupts))
(define (flush-end-atomic-callbacks!)
(end-atomic-callback 0))
;; ----------------------------------------
(define future-block-for-atomic (lambda () (void)))
@ -151,8 +157,13 @@
[(_)
#`(unless (or (current-implicit-atomic)
(positive? (current-atomic)))
(internal-error #,(format "should be in atomic mode: ~s" stx)))]))]
(internal-error #,(format "should be in atomic mode: ~s" stx)))]))
(define (assert-no-end-atomic-callbacks)
(unless (eq? 0 (end-atomic-callback))
(internal-error "non-empty end-atomic callbacks")))]
#:off
[(define-syntax-rule (start-implicit-atomic-mode) (begin))
(define-syntax-rule (end-implicit-atomic-mode) (begin))
(define-syntax-rule (assert-atomic-mode) (begin))])
(define-syntax-rule (assert-atomic-mode) (begin))
(define-syntax-rule (assert-no-end-atomic-callbacks) (begin))])

View File

@ -132,6 +132,7 @@
(set-thread-engine! (current-thread/in-atomic) 'running))
(define (swap-in-engine e t leftover-ticks)
(assert-no-end-atomic-callbacks)
(let loop ([e e] [prefix check-break-prefix])
(end-implicit-atomic-mode)
(e
@ -149,6 +150,7 @@
(current-future #f)
(unless (zero? (current-atomic))
(internal-error "terminated in atomic mode!"))
(flush-end-atomic-callbacks!)
(thread-dead! t)
(when (eq? root-thread t)
(force-exit 0))