(%%trace ";"id" thread-timer: interrupt in "old"\n")
(set! next-scheduled-timeout #f)
(deliver-timer-events)
+ (if (eq? id io-waiter)
+ (set! io-waiter #f))
(maybe-signal-io-thread-events)
(maybe-signal-subprocess-status)
(cond ((and (not first-runnable-thread) (not old))
(%lock)
(ring/discard-all (thread/pending-events thread))
(%deregister-io-thread-events thread)
+ (%maybe-wake-io-waiter)
(%discard-thread-timer-records thread)
(%disassociate-joined-threads thread)
(%disassociate-thread-mutexes thread)
(set! io-registry (and ((ucode-primitive have-select? 0))
(make-select-registry)))
(set! io-registrations #f)
+ (set! io-waiter-registry (and ((ucode-primitive have-select? 0))
+ enable-smp?
+ (make-select-registry)))
(set! io-waiter #f))
(define io-waiter)
+(define io-waiter-registry)
(define (%maybe-wake-idle-processor id)
(%%trace ";"id" %maybe-wake-idle-processor\n")
((ucode-primitive smp-wake 1) id*))
(loop (fix:1+ id*)))))))
+(define (%maybe-wake-io-waiter)
+ ;; The io-registry's length is cached when io-waiter copies it. The
+ ;; cache is cleared by any change (in membership OR mode). Use it
+ ;; to decide whether io-waiter needs to be interrupted.
+ (if (and io-waiter
+ (not (select-registry-length io-registry)))
+ ((ucode-primitive smp-wake 1) io-waiter)))
+
(define (wait-for-io id)
;; This procedure never returns.
(%%trace ";"id" wait-for-io\n")
(%maybe-toggle-thread-timer #f)
(%%trace ";"id" io-waiter-wait: next timeout = "next-scheduled-timeout"\n")
(let ((result
- (begin
+ (let ((registry
+ (if enable-smp?
+ (begin
+ (copy-select-registry! io-registry io-waiter-registry)
+ io-waiter-registry)
+ io-registry)))
(%%trace ";"id" io-waiter-wait: blocking for i/o\n")
(%unlock)
(set-interrupt-enables! interrupt-mask/all)
- (test-select-registry io-registry #t))))
+ (test-select-registry registry #t))))
(set-interrupt-enables! interrupt-mask/gc-ok)
(%lock)
(signal-select-result result)
(signal-io-thread-events 1 '#(PROCESS-STATUS-CHANGE) '#(READ)))
(define (maybe-signal-io-thread-events)
- (%%trace ";"(%%id)" maybe-signal-io-thread-events: testing\n")
(assert-locked 'maybe-signal-io-thread-events)
- (let ((result (test-select-registry io-registry #f)))
- (signal-select-result result)
- (%%trace ";"(%%id)" maybe-signal-io-thread-events => "
- (if (vector? result) (vector-ref result 0) result)"\n")))
+ (if (not io-waiter)
+ (begin
+ (%%trace ";"(%%id)" maybe-signal-io-thread-events: testing\n")
+ (let ((result (test-select-registry io-registry #f)))
+ (signal-select-result result)
+ (%%trace ";"(%%id)" maybe-signal-io-thread-events => "
+ (if (vector? result) (vector-ref result 0) result)"\n")))
+ (%%trace ";"(%%id)" maybe-signal-io-thread-events: punting\n")))
(define (maybe-signal-subprocess-status)
(assert-locked 'maybe-signal-subprocess-status)
(%register-io-thread-event descriptor mode registration-1 #t)
(%register-io-thread-event 'PROCESS-STATUS-CHANGE 'READ
registration-2 #t)
- (%maybe-toggle-thread-timer))))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter))))
(lambda ()
(%suspend-current-thread)
result)
(lambda ()
(%maybe-deregister-io-thread-event registration-2)
(%maybe-deregister-io-thread-event registration-1)
- (%maybe-toggle-thread-timer))))))))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter))))))))
(define (%maybe-deregister-io-thread-event tentry)
;; Ensure that another thread does not unwind our registration.
(lambda ()
(%register-io-thread-event descriptor mode
registration #f)
- (%maybe-toggle-thread-timer))))))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter))))))
(with-threads-locked
(lambda ()
(%register-io-thread-event descriptor mode registration #f)
- (%maybe-toggle-thread-timer)))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter)))
registration))
(define (register-io-thread-event descriptor mode thread event)
(with-threads-locked
(lambda ()
(%register-io-thread-event descriptor mode registration #f)
- (%maybe-toggle-thread-timer)))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter)))
registration))
(define (deregister-io-thread-event tentry)
(with-threads-locked
(lambda ()
(%deregister-io-thread-event tentry)
- (%maybe-toggle-thread-timer))))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter))))
(define (deregister-io-descriptor-events descriptor mode)
(guarantee-select-mode mode 'DEREGISTER-IO-DESCRIPTOR-EVENTS)
(set-dentry/prev! next prev))))
(else
(loop (dentry/next dentry)))))
- (%maybe-toggle-thread-timer))))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter))))
(define (%deregister-io-descriptor descriptor)
(%lock)
(else
(dloop (dentry/next dentry)))))
(%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter)
(%unlock))
\f
(define (%register-io-thread-event descriptor mode tentry front?)
(%deregister-io-thread-events thread)
(%discard-thread-timer-records thread)
(set-thread/block-events?! thread block-events?))
- (%maybe-toggle-thread-timer))))
+ (%maybe-toggle-thread-timer)
+ (%maybe-wake-io-waiter))))
(define (%discard-thread-timer-records thread)
(assert-locked '%discard-thread-timer-records)