home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / runtime / thread.scm < prev    next >
Text File  |  2001-04-02  |  37KB  |  1,138 lines

  1. #| -*-Scheme-*-
  2.  
  3. $Id: thread.scm,v 1.34 2001/04/03 03:44:02 cph Exp $
  4.  
  5. Copyright (c) 1991-1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. |#
  21.  
  22. ;;;; Multiple Threads of Control
  23. ;;; package: (runtime thread)
  24.  
  25. (declare (usual-integrations))
  26.  
  27. (define-structure (thread
  28.            (constructor %make-thread ())
  29.            (conc-name thread/))
  30.   (execution-state 'RUNNING)
  31.   ;; One of:
  32.   ;; RUNNING
  33.   ;; RUNNING-WITHOUT-PREEMPTION
  34.   ;; WAITING
  35.   ;; STOPPED
  36.   ;; DEAD
  37.  
  38.   (next #f)
  39.   ;; Pointer to next thread in run queue, or #F if none.
  40.  
  41.   (continuation #f)
  42.   ;; #F if current thread or exited, else continuation for thread.
  43.  
  44.   (block-events? #f)
  45.   ;; If true, events may not be delivered to this thread.  Instead,
  46.   ;; they are queued.
  47.  
  48.   (pending-events (make-ring) read-only #t)
  49.   ;; Doubly-linked circular list of events waiting to be delivered.
  50.  
  51.   (joined-threads '())
  52.   ;; List of threads that have successfully called JOIN-THREAD on this
  53.   ;; thread.
  54.  
  55.   (joined-to '())
  56.   ;; List of threads to which this thread has joined.
  57.  
  58.   (exit-value no-exit-value-marker)
  59.   ;; If the thread exits, the exit value is stored here so that
  60.   ;; joined threads can get it.  If the thread has been detached,
  61.   ;; this field holds a condition of type THREAD-DETACHED.
  62.  
  63.   (root-state-point #f)
  64.   ;; Root state-point of the local state space of the thread.  Used to
  65.   ;; unwind the thread's state space when it is exited.
  66.  
  67.   (mutexes '())
  68.   ;; List of mutexes that this thread owns or is waiting to own.  Used
  69.   ;; to disassociate the thread from those mutexes when it is exited.
  70.  
  71.   (properties (make-1d-table) read-only #t))
  72.  
  73. (define-integrable (guarantee-thread thread procedure)
  74.   (if (not (thread? thread))
  75.       (error:wrong-type-argument thread "thread" procedure)))
  76.  
  77. (define no-exit-value-marker
  78.   (list 'NO-EXIT-VALUE-MARKER))
  79.  
  80. (define-integrable (thread-dead? thread)
  81.   (eq? 'DEAD (thread/execution-state thread)))
  82.  
  83. (define thread-population)
  84. (define first-running-thread)
  85. (define last-running-thread)
  86. (define thread-timer-running?)
  87. (define root-continuation-default)
  88.  
  89. (define (initialize-package!)
  90.   (initialize-error-conditions!)
  91.   (set! thread-population (make-population))
  92.   (set! first-running-thread #f)
  93.   (set! last-running-thread #f)
  94.   (set! thread-timer-running? #f)
  95.   (set! timer-records #f)
  96.   (set! timer-interval 100)
  97.   (initialize-input-blocking)
  98.   (add-event-receiver! event:after-restore initialize-input-blocking)
  99.   (detach-thread (make-thread #f))
  100.   (add-event-receiver! event:before-exit stop-thread-timer))
  101.  
  102. (define (make-thread continuation)
  103.   (let ((thread (%make-thread)))
  104.     (set-thread/continuation! thread continuation)
  105.     (set-thread/root-state-point! thread
  106.                   (current-state-point state-space:local))
  107.     (add-to-population! thread-population thread)
  108.     (thread-running thread)
  109.     thread))
  110.  
  111. (define-integrable (without-interrupts thunk)
  112.   (let ((interrupt-mask (set-interrupt-enables! interrupt-mask/gc-ok)))
  113.     (let ((value (thunk)))
  114.       (set-interrupt-enables! interrupt-mask)
  115.       value)))
  116.  
  117. (define (threads-list)
  118.   (map-over-population thread-population (lambda (thread) thread)))
  119.  
  120. (define (thread-execution-state thread)
  121.   (guarantee-thread thread thread-execution-state)
  122.   (thread/execution-state thread))
  123.  
  124. (define (create-thread root-continuation thunk)
  125.   (if (not (or (not root-continuation) (continuation? root-continuation)))
  126.       (error:wrong-type-argument root-continuation
  127.                  "continuation or #f"
  128.                  create-thread))
  129.   (call-with-current-continuation
  130.    (lambda (return)
  131.      (%within-continuation (or root-continuation root-continuation-default)
  132.                #t
  133.        (lambda ()
  134.      (fluid-let ((state-space:local (make-state-space)))
  135.        (call-with-current-continuation
  136.         (lambda (continuation)
  137.           (let ((thread (make-thread continuation)))
  138.         (%within-continuation (let ((k return)) (set! return #f) k)
  139.                       #t
  140.                       (lambda () thread)))))
  141.        (set-interrupt-enables! interrupt-mask/all)
  142.        (exit-current-thread (thunk))))))))
  143.  
  144. (define (create-thread-continuation)
  145.   root-continuation-default)
  146.  
  147. (define (with-create-thread-continuation continuation thunk)
  148.   (if (not (continuation? continuation))
  149.       (error:wrong-type-argument continuation
  150.                  "continuation"
  151.                  with-create-thread-continuation))
  152.   (fluid-let ((root-continuation-default continuation))
  153.     (thunk)))
  154.  
  155. (define (current-thread)
  156.   (or first-running-thread
  157.       (let ((thread (console-thread)))
  158.     (if thread
  159.         (call-with-current-continuation
  160.          (lambda (continuation)
  161.            (let ((condition
  162.               (make-condition condition-type:no-current-thread
  163.                       continuation
  164.                       'BOUND-RESTARTS
  165.                       '())))
  166.          (signal-thread-event thread
  167.            (lambda ()
  168.              (error condition)))))))
  169.     (run-first-thread))))
  170.  
  171. (define (call-with-current-thread return? procedure)
  172.   (let ((thread first-running-thread))
  173.     (cond (thread (procedure thread))
  174.       ((not return?) (run-first-thread)))))
  175.  
  176. (define (console-thread)
  177.   (thread-mutex-owner (port/thread-mutex console-i/o-port)))
  178.  
  179. (define (other-running-threads?)
  180.   (thread/next (current-thread)))
  181.  
  182. (define (thread-continuation thread)
  183.   (guarantee-thread thread thread-continuation)
  184.   (without-interrupts
  185.    (lambda ()
  186.      (and (eq? 'WAITING (thread/execution-state thread))
  187.       (thread/continuation thread)))))
  188.  
  189. (define (thread-running thread)
  190.   (%thread-running thread)
  191.   (%maybe-toggle-thread-timer))
  192.  
  193. (define (%thread-running thread)
  194.   (set-thread/execution-state! thread 'RUNNING)
  195.   (let ((prev last-running-thread))
  196.     (if prev
  197.     (set-thread/next! prev thread)
  198.     (set! first-running-thread thread)))
  199.   (set! last-running-thread thread)
  200.   unspecific)
  201.  
  202. (define (thread-not-running thread state)
  203.   (set-thread/execution-state! thread state)
  204.   (let ((thread* (thread/next thread)))
  205.     (set-thread/next! thread #f)
  206.     (set! first-running-thread thread*))
  207.   (run-first-thread))
  208.  
  209. (define (run-first-thread)
  210.   (if first-running-thread
  211.       (run-thread first-running-thread)
  212.       (begin
  213.     (set! last-running-thread #f)
  214.     (%maybe-toggle-thread-timer)
  215.     (wait-for-input))))
  216.  
  217. (define (run-thread thread)
  218.   (let ((continuation (thread/continuation thread)))
  219.     (set-thread/continuation! thread #f)
  220.     (%within-continuation continuation #t
  221.       (lambda ()
  222.     (%resume-current-thread thread)))))
  223.  
  224. (define (%resume-current-thread thread)
  225.   (if (not (thread/block-events? thread))
  226.       (begin
  227.     (handle-thread-events thread)
  228.     (set-thread/block-events?! thread #f)))
  229.   (%maybe-toggle-thread-timer))
  230.  
  231. (define (suspend-current-thread)
  232.   (without-interrupts %suspend-current-thread))
  233.  
  234. (define (%suspend-current-thread)
  235.   (call-with-current-thread #f
  236.     (lambda (thread)
  237.       (let ((block-events? (thread/block-events? thread)))
  238.     (set-thread/block-events?! thread #f)
  239.     (maybe-signal-input-thread-events)
  240.     (let ((any-events? (handle-thread-events thread)))
  241.       (set-thread/block-events?! thread block-events?)
  242.       (if (not any-events?)
  243.           (call-with-current-continuation
  244.            (lambda (continuation)
  245.          (set-thread/continuation! thread continuation)
  246.          (set-thread/block-events?! thread #f)
  247.          (thread-not-running thread 'WAITING)))))))))
  248.  
  249. (define (stop-current-thread)
  250.   (without-interrupts
  251.    (lambda ()
  252.      (call-with-current-thread #f
  253.        (lambda (thread)
  254.      (call-with-current-continuation
  255.       (lambda (continuation)
  256.         (set-thread/continuation! thread continuation)
  257.         (thread-not-running thread 'STOPPED))))))))
  258.  
  259. (define (restart-thread thread discard-events? event)
  260.   (guarantee-thread thread restart-thread)
  261.   (let ((discard-events?
  262.      (if (eq? discard-events? 'ASK)
  263.          (prompt-for-confirmation
  264.           "Restarting other thread; discard events in its queue")
  265.          discard-events?)))
  266.     (without-interrupts
  267.      (lambda ()
  268.        (if (not (eq? 'STOPPED (thread/execution-state thread)))
  269.        (error:bad-range-argument thread restart-thread))
  270.        (if discard-events? (ring/discard-all (thread/pending-events thread)))
  271.        (if event (%signal-thread-event thread event))
  272.        (thread-running thread)))))
  273.  
  274. (define (disallow-preempt-current-thread)
  275.   (set-thread/execution-state! (current-thread) 'RUNNING-WITHOUT-PREEMPTION))
  276.  
  277. (define (allow-preempt-current-thread)
  278.   (set-thread/execution-state! (current-thread) 'RUNNING))
  279.  
  280. (define (thread-timer-interrupt-handler)
  281.   (set-interrupt-enables! interrupt-mask/gc-ok)
  282.   (deliver-timer-events)
  283.   (maybe-signal-input-thread-events)
  284.   (let ((thread first-running-thread))
  285.     (cond ((not thread)
  286.        (%maybe-toggle-thread-timer))
  287.       ((thread/continuation thread)
  288.        (run-thread thread))
  289.       ((not (eq? 'RUNNING-WITHOUT-PREEMPTION
  290.              (thread/execution-state thread)))
  291.        (yield-thread thread))
  292.       (else
  293.        (%resume-current-thread thread)))))
  294.  
  295. (define (yield-current-thread)
  296.   (without-interrupts
  297.    (lambda ()
  298.      (call-with-current-thread #t
  299.        (lambda (thread)
  300.      ;; Allow preemption now, since the current thread has
  301.      ;; volunteered to yield control.
  302.      (set-thread/execution-state! thread 'RUNNING)
  303.      (yield-thread thread))))))
  304.  
  305. (define (yield-thread thread)
  306.   (let ((next (thread/next thread)))
  307.     (if (not next)
  308.     (%resume-current-thread thread)
  309.     (call-with-current-continuation
  310.      (lambda (continuation)
  311.        (set-thread/continuation! thread continuation)
  312.        (set-thread/next! thread #f)
  313.        (set-thread/next! last-running-thread thread)
  314.        (set! last-running-thread thread)
  315.        (set! first-running-thread next)
  316.        (run-thread next))))))
  317.  
  318. (define (exit-current-thread value)
  319.   (let ((thread (current-thread)))
  320.     (set-interrupt-enables! interrupt-mask/gc-ok)
  321.     (set-thread/block-events?! thread #t)
  322.     (ring/discard-all (thread/pending-events thread))
  323.     (translate-to-state-point (thread/root-state-point thread))
  324.     (%deregister-input-thread-events thread #t)
  325.     (%discard-thread-timer-records thread)
  326.     (%disassociate-joined-threads thread)
  327.     (%disassociate-thread-mutexes thread)
  328.     (if (eq? no-exit-value-marker (thread/exit-value thread))
  329.     (release-joined-threads thread value))
  330.     (thread-not-running thread 'DEAD)))
  331.  
  332. (define (join-thread thread event-constructor)
  333.   (guarantee-thread thread join-thread)
  334.   (let ((self (current-thread)))
  335.     (if (eq? thread self)
  336.     (signal-thread-deadlock self "join thread" join-thread thread)
  337.     (without-interrupts
  338.      (lambda ()
  339.        (let ((value (thread/exit-value thread)))
  340.          (cond ((eq? value no-exit-value-marker)
  341.             (set-thread/joined-threads!
  342.              thread
  343.              (cons (cons self event-constructor)
  344.                (thread/joined-threads thread)))
  345.             (set-thread/joined-to!
  346.              self
  347.              (cons thread (thread/joined-to self))))
  348.            ((eq? value detached-thread-marker)
  349.             (signal-thread-detached thread))
  350.            (else
  351.             (signal-thread-event
  352.              self
  353.              (event-constructor thread value))))))))))
  354.  
  355. (define (detach-thread thread)
  356.   (guarantee-thread thread detach-thread)
  357.   (without-interrupts
  358.    (lambda ()
  359.      (if (eq? (thread/exit-value thread) detached-thread-marker)
  360.      (signal-thread-detached thread))
  361.      (release-joined-threads thread detached-thread-marker))))
  362.  
  363. (define detached-thread-marker
  364.   (list 'DETACHED-THREAD-MARKER))
  365.  
  366. (define (release-joined-threads thread value)
  367.   (set-thread/exit-value! thread value)
  368.   (do ((joined (thread/joined-threads thread) (cdr joined)))
  369.       ((null? joined))
  370.     (let ((joined (caar joined))
  371.       (event ((cdar joined) thread value)))
  372.       (set-thread/joined-to! joined (delq! thread (thread/joined-to joined)))
  373.       (%signal-thread-event joined event)))
  374.   (%maybe-toggle-thread-timer))
  375.  
  376. (define (%disassociate-joined-threads thread)
  377.   (do ((threads (thread/joined-to thread) (cdr threads)))
  378.       ((null? threads))
  379.     (set-thread/joined-threads!
  380.      (car threads)
  381.      (del-assq! thread (thread/joined-threads (car threads)))))
  382.   (set-thread/joined-to! thread '()))
  383.  
  384. ;;;; Input Thread Events
  385.  
  386. (define input-registry)
  387. (define input-registrations)
  388.  
  389. (define-structure (dentry (conc-name dentry/))
  390.   (descriptor #f read-only #t)
  391.   first-tentry
  392.   last-tentry
  393.   prev
  394.   next)
  395.  
  396. (define-structure (tentry (conc-name tentry/)
  397.               (constructor make-tentry (thread event permanent?)))
  398.   dentry
  399.   thread
  400.   event
  401.   (permanent? #f read-only #t)
  402.   prev
  403.   next)
  404.  
  405. (define (initialize-input-blocking)
  406.   (set! input-registry (and have-select? (make-select-registry)))
  407.   (set! input-registrations #f)
  408.   unspecific)
  409.  
  410. (define-integrable (maybe-signal-input-thread-events)
  411.   (if input-registrations
  412.       (signal-select-result (select-registry-test input-registry #f))))
  413.  
  414. (define (wait-for-input)
  415.   (let ((catch-errors
  416.      (lambda (thunk)
  417.        (let ((thread (console-thread)))
  418.          (if thread
  419.          (bind-condition-handler '()
  420.              (lambda (condition)
  421.                (error:derived-thread thread condition))
  422.            thunk)
  423.          (call-with-current-continuation
  424.           (lambda (k)
  425.             (bind-condition-handler '()
  426.             (lambda (condition)
  427.               condition
  428.               (within-continuation k thunk))
  429.               thunk))))))))
  430.     (if (not input-registrations)
  431.     (begin
  432.       ;; Busy-waiting here is a bad idea -- should implement a
  433.       ;; primitive to block the Scheme process while waiting for a
  434.       ;; signal.
  435.       (catch-errors
  436.        (lambda ()
  437.          (set-interrupt-enables! interrupt-mask/all)
  438.          (do () (#f)))))
  439.     (let ((result
  440.            (catch-errors
  441.         (lambda ()
  442.           (set-interrupt-enables! interrupt-mask/all)
  443.           (select-registry-test input-registry #t)))))
  444.       (set-interrupt-enables! interrupt-mask/gc-ok)
  445.       (signal-select-result result)
  446.       (let ((thread first-running-thread))
  447.         (if thread
  448.         (if (thread/continuation thread)
  449.             (run-thread thread))
  450.         (wait-for-input)))))))
  451.  
  452. (define (signal-select-result result)
  453.   (cond ((pair? result)
  454.      (signal-input-thread-events result))
  455.     ((eq? 'PROCESS-STATUS-CHANGE result)
  456.      (signal-input-thread-events '(PROCESS-STATUS-CHANGE)))))
  457.  
  458. (define (block-on-input-descriptor descriptor)
  459.   (without-interrupts
  460.    (lambda ()
  461.      (let ((result 'INTERRUPT)
  462.        (registration-1)
  463.        (registration-2))
  464.        (dynamic-wind
  465.     (lambda ()
  466.       (let ((thread (current-thread)))
  467.         (set! registration-1
  468.           (%register-input-thread-event
  469.            descriptor
  470.            thread
  471.            (lambda ()
  472.              (set! result 'INPUT-AVAILABLE)
  473.              unspecific)
  474.            #f #t))
  475.         (set! registration-2
  476.           (%register-input-thread-event
  477.            'PROCESS-STATUS-CHANGE
  478.            thread
  479.            (lambda ()
  480.              (set! result 'PROCESS-STATUS-CHANGE)
  481.              unspecific)
  482.            #f #t)))
  483.       unspecific)
  484.     (lambda ()
  485.       (%suspend-current-thread)
  486.       result)
  487.     (lambda ()
  488.       (%deregister-input-thread-event registration-1)
  489.       (%deregister-input-thread-event registration-2)))))))
  490.  
  491. (define (permanently-register-input-thread-event descriptor thread event)
  492.   (guarantee-thread thread permanently-register-input-thread-event)
  493.   (without-interrupts
  494.    (lambda ()
  495.      (%register-input-thread-event descriptor thread event #t #f))))
  496.  
  497. (define (register-input-thread-event descriptor thread event)
  498.   (guarantee-thread thread register-input-thread-event)
  499.   (without-interrupts
  500.    (lambda ()
  501.      (%register-input-thread-event descriptor thread event #f #f))))
  502.  
  503. (define (deregister-input-thread-event tentry)
  504.   (if (not (tentry? tentry))
  505.       (error:wrong-type-argument tentry "input thread event registration"
  506.                  'DEREGISTER-INPUT-THREAD-EVENT))
  507.   (without-interrupts
  508.    (lambda ()
  509.      (%deregister-input-thread-event tentry)
  510.      (%maybe-toggle-thread-timer))))
  511.  
  512. (define (%register-input-thread-event descriptor thread event
  513.                       permanent? front?)
  514.   (let ((tentry (make-tentry thread event permanent?))
  515.     (dentry
  516.      (let loop ((dentry input-registrations))
  517.        (and dentry
  518.         (if (eqv? descriptor (dentry/descriptor dentry))
  519.             dentry
  520.             (loop (dentry/next dentry)))))))
  521.     (if (not dentry)
  522.     (let ((dentry (make-dentry descriptor #f #f #f #f)))
  523.       (set-tentry/dentry! tentry dentry)
  524.       (set-tentry/prev! tentry #f)
  525.       (set-tentry/next! tentry #f)
  526.       (set-dentry/first-tentry! dentry tentry)
  527.       (set-dentry/last-tentry! dentry tentry)
  528.       (if input-registrations
  529.           (set-dentry/prev! input-registrations dentry))
  530.       (set-dentry/next! dentry input-registrations)
  531.       (set! input-registrations dentry)
  532.       (if (not (eq? 'PROCESS-STATUS-CHANGE descriptor))
  533.           (add-to-select-registry! input-registry descriptor)))
  534.     (begin
  535.       (set-tentry/dentry! tentry dentry)
  536.       (if front?
  537.           (let ((next (dentry/first-tentry dentry)))
  538.         (set-tentry/prev! tentry #f)
  539.         (set-tentry/next! tentry next)
  540.         (set-dentry/first-tentry! dentry tentry)
  541.         (set-tentry/prev! next tentry))
  542.           (let ((prev (dentry/last-tentry dentry)))
  543.         (set-tentry/prev! tentry prev)
  544.         (set-tentry/next! tentry #f)
  545.         (set-dentry/last-tentry! dentry tentry)
  546.         (set-tentry/next! prev tentry)))))
  547.     (%maybe-toggle-thread-timer)
  548.     tentry))
  549.  
  550. (define (%deregister-input-thread-event tentry)
  551.   (if (tentry/dentry tentry)
  552.       (delete-tentry! tentry)))
  553.  
  554. (define (%deregister-input-thread-events thread permanent?)
  555.   (let loop ((dentry input-registrations) (tentries '()))
  556.     (if (not dentry)
  557.     (do ((tentries tentries (cdr tentries)))
  558.         ((null? tentries))
  559.       (delete-tentry! (car tentries)))
  560.     (loop (dentry/next dentry)
  561.           (let loop
  562.           ((tentry (dentry/first-tentry dentry)) (tentries tentries))
  563.         (if (not tentry)
  564.             tentries
  565.             (loop (tentry/next tentry)
  566.               (if (and (eq? thread (tentry/thread tentry))
  567.                    (or permanent?
  568.                        (not (tentry/permanent? tentry))))
  569.                   (cons tentry tentries)
  570.                   tentries))))))))
  571.  
  572. (define (signal-input-thread-events descriptors)
  573.   (let loop ((dentry input-registrations) (events '()))
  574.     (cond ((not dentry)
  575.        (do ((events events (cdr events)))
  576.            ((null? events))
  577.          (%signal-thread-event (caar events) (cdar events)))
  578.        (%maybe-toggle-thread-timer))
  579.       ((let ((descriptor (dentry/descriptor dentry)))
  580.          (let loop ((descriptors descriptors))
  581.            (and (not (null? descriptors))
  582.             (or (eqv? descriptor (car descriptors))
  583.             (loop (cdr descriptors))))))
  584.        (let ((next (dentry/next dentry))
  585.          (tentry (dentry/first-tentry dentry)))
  586.          (let ((events
  587.             (cons (cons (tentry/thread tentry)
  588.                 (tentry/event tentry))
  589.               events)))
  590.            (if (tentry/permanent? tentry)
  591.            (move-tentry-to-back! tentry)
  592.            (delete-tentry! tentry))
  593.            (loop next events))))
  594.       (else
  595.        (loop (dentry/next dentry) events)))))
  596.  
  597. (define (move-tentry-to-back! tentry)
  598.   (let ((next (tentry/next tentry)))
  599.     (if next
  600.     (let ((dentry (tentry/dentry tentry))
  601.           (prev (tentry/prev tentry)))
  602.       (set-tentry/prev! tentry (dentry/last-tentry dentry))
  603.       (set-tentry/next! tentry #f)
  604.       (set-dentry/last-tentry! dentry tentry)
  605.       (set-tentry/prev! next prev)
  606.       (if (not prev) (set-dentry/first-tentry! dentry next))))))
  607.  
  608. (define (delete-tentry! tentry)
  609.   (let ((dentry (tentry/dentry tentry))
  610.     (prev (tentry/prev tentry))
  611.     (next (tentry/next tentry)))
  612.     (set-tentry/dentry! tentry #f)
  613.     (set-tentry/thread! tentry #f)
  614.     (set-tentry/event! tentry #f)
  615.     (set-tentry/prev! tentry #f)
  616.     (set-tentry/next! tentry #f)
  617.     (if prev
  618.     (set-tentry/next! prev next)
  619.     (set-dentry/first-tentry! dentry next))
  620.     (if next
  621.     (set-tentry/prev! next prev)
  622.     (set-dentry/last-tentry! dentry prev))
  623.     (if (not (or prev next))
  624.     (begin
  625.       (let ((descriptor (dentry/descriptor dentry)))
  626.         (if (not (eq? 'PROCESS-STATUS-CHANGE descriptor))
  627.         (remove-from-select-registry! input-registry descriptor)))
  628.       (let ((prev (dentry/prev dentry))
  629.         (next (dentry/next dentry)))
  630.         (if prev
  631.         (set-dentry/next! prev next)
  632.         (set! input-registrations next))
  633.         (if next
  634.         (set-dentry/prev! next prev))))))
  635.   unspecific)
  636.  
  637. ;;;; Events
  638.  
  639. (define (block-thread-events)
  640.   (without-interrupts
  641.    (lambda ()
  642.      (let ((thread first-running-thread))
  643.        (if thread
  644.        (let ((result (thread/block-events? thread)))
  645.          (set-thread/block-events?! thread #t)
  646.          result)
  647.        #f)))))
  648.  
  649. (define (unblock-thread-events)
  650.   (without-interrupts
  651.    (lambda ()
  652.      (call-with-current-thread #t
  653.        (lambda (thread)
  654.      (handle-thread-events thread)
  655.      (set-thread/block-events?! thread #f))))))
  656.  
  657. (define (with-thread-events-blocked thunk)
  658.   (let ((interrupt-mask (set-interrupt-enables! interrupt-mask/gc-ok)))
  659.     (let ((thread first-running-thread))
  660.       (if thread
  661.       (let ((block-events? (thread/block-events? thread)))
  662.         (set-thread/block-events?! thread #t)
  663.         (let ((value
  664.            ((ucode-primitive with-stack-marker 3)
  665.             (lambda ()
  666.               (set-interrupt-enables! interrupt-mask)
  667.               (let ((value (thunk)))
  668.             (set-interrupt-enables! interrupt-mask/gc-ok)
  669.             value))
  670.             with-thread-events-blocked
  671.             block-events?)))
  672.           (let ((thread first-running-thread))
  673.         (if thread
  674.             (set-thread/block-events?! thread block-events?)))
  675.           (set-interrupt-enables! interrupt-mask)
  676.           value))
  677.       (begin
  678.         (set-interrupt-enables! interrupt-mask)
  679.         (thunk))))))
  680.  
  681. (define (get-thread-event-block)
  682.   (without-interrupts
  683.    (lambda ()
  684.      (let ((thread first-running-thread))
  685.        (if thread
  686.        (thread/block-events? thread)
  687.        #f)))))
  688.  
  689. (define (set-thread-event-block! block?)
  690.   (without-interrupts
  691.    (lambda ()
  692.      (let ((thread first-running-thread))
  693.        (if thread
  694.        (set-thread/block-events?! thread block?)))
  695.      unspecific)))
  696.  
  697. (define (signal-thread-event thread event)
  698.   (guarantee-thread thread signal-thread-event)
  699.   (let ((self first-running-thread))
  700.     (if (eq? thread self)
  701.     (let ((block-events? (block-thread-events)))
  702.       (ring/enqueue (thread/pending-events thread) event)
  703.       (if (not block-events?)
  704.           (unblock-thread-events)))
  705.     (without-interrupts
  706.      (lambda ()
  707.        (if (eq? 'DEAD (thread/execution-state thread))
  708.            (signal-thread-dead thread "signal event to"
  709.                    signal-thread-event thread event))
  710.        (%signal-thread-event thread event)
  711.        (if (and (not self) first-running-thread)
  712.            (run-thread first-running-thread)
  713.            (%maybe-toggle-thread-timer)))))))
  714.  
  715. (define (%signal-thread-event thread event)
  716.   (ring/enqueue (thread/pending-events thread) event)
  717.   (if (and (not (thread/block-events? thread))
  718.        (eq? 'WAITING (thread/execution-state thread)))
  719.       (%thread-running thread)))
  720.  
  721. (define (handle-thread-events thread)
  722.   (let loop ((any-events? #f))
  723.     (let ((event (ring/dequeue (thread/pending-events thread) #t)))
  724.       (if (eq? #t event)
  725.       any-events?
  726.       (begin
  727.         (if event
  728.         (let ((block? (thread/block-events? thread)))
  729.           (set-thread/block-events?! thread #t)
  730.           (event)
  731.           (set-interrupt-enables! interrupt-mask/gc-ok)
  732.           (set-thread/block-events?! thread block?)))
  733.         (loop #t))))))
  734.  
  735. (define (allow-thread-event-delivery)
  736.   (without-interrupts
  737.    (lambda ()
  738.      (let ((thread first-running-thread))
  739.        (if thread
  740.        (let ((block-events? (thread/block-events? thread)))
  741.          (set-thread/block-events?! thread #f)
  742.          (deliver-timer-events)
  743.          (maybe-signal-input-thread-events)
  744.          (handle-thread-events thread)
  745.          (set-thread/block-events?! thread block-events?))
  746.        (begin
  747.          (deliver-timer-events)
  748.          (maybe-signal-input-thread-events)))))))
  749.  
  750. ;;;; Timer Events
  751.  
  752. (define timer-records)
  753. (define timer-interval)
  754.  
  755. (define-structure (timer-record
  756.            (conc-name timer-record/))
  757.   (time #f read-only #t)
  758.   thread
  759.   event
  760.   next)
  761.  
  762. (define (register-timer-event interval event)
  763.   (let ((time (+ (real-time-clock) interval)))
  764.     (let ((new-record (make-timer-record time (current-thread) event #f)))
  765.       (without-interrupts
  766.        (lambda ()
  767.      (let loop ((record timer-records) (prev #f))
  768.        (if (or (not record) (< time (timer-record/time record)))
  769.            (begin
  770.          (set-timer-record/next! new-record record)
  771.          (if prev
  772.              (set-timer-record/next! prev new-record)
  773.              (set! timer-records new-record)))
  774.            (loop (timer-record/next record) record)))))
  775.       new-record)))
  776.  
  777. (define (sleep-current-thread interval)
  778.   (let ((delivered? #f))
  779.     (let ((block-events? (block-thread-events)))
  780.       (register-timer-event interval
  781.                 (lambda () (set! delivered? #t) unspecific))
  782.       (do () (delivered?)
  783.     (suspend-current-thread))
  784.       (if (not block-events?)
  785.       (unblock-thread-events)))))
  786.  
  787. (define (deliver-timer-events)
  788.   (let ((time (real-time-clock)))
  789.     (do ((record timer-records (timer-record/next record)))
  790.     ((or (not record) (< time (timer-record/time record)))
  791.      (set! timer-records record))
  792.       (let ((thread (timer-record/thread record))
  793.         (event (timer-record/event record)))
  794.     (set-timer-record/thread! record #f)
  795.     (set-timer-record/event! record #f)
  796.     (%signal-thread-event thread event))))
  797.   unspecific)
  798.  
  799. (define (deregister-timer-event registration)
  800.   (if (not (timer-record? registration))
  801.       (error:wrong-type-argument registration "timer event registration"
  802.                  'DEREGISTER-TIMER-EVENT))
  803.   (without-interrupts
  804.    (lambda ()
  805.      (let loop ((record timer-records) (prev #f))
  806.        (if record
  807.        (let ((next (timer-record/next record)))
  808.          (if (eq? record registration)
  809.          (if prev
  810.              (set-timer-record/next! prev next)
  811.              (set! timer-records next))
  812.          (loop next record)))))
  813.      (%maybe-toggle-thread-timer))))
  814.  
  815. (define-integrable (threads-pending-timer-events?)
  816.   timer-records)
  817.  
  818. (define (deregister-all-events)
  819.   (let ((thread (current-thread)))
  820.     (set-interrupt-enables! interrupt-mask/gc-ok)
  821.     (let ((block-events? (thread/block-events? thread)))
  822.       (set-thread/block-events?! thread #t)
  823.       (ring/discard-all (thread/pending-events thread))
  824.       (%deregister-input-thread-events thread #f)
  825.       (%discard-thread-timer-records thread)
  826.       (set-thread/block-events?! thread block-events?))
  827.     (set-interrupt-enables! interrupt-mask/all)))
  828.  
  829. (define (%discard-thread-timer-records thread)
  830.   (let loop ((record timer-records) (prev #f))
  831.     (if record
  832.     (let ((next (timer-record/next record)))
  833.       (if (eq? thread (timer-record/thread record))
  834.           (begin
  835.         (if prev
  836.             (set-timer-record/next! prev next)
  837.             (set! timer-records next))
  838.         (loop next prev))
  839.           (loop next record))))))
  840.  
  841. (define (thread-timer-interval)
  842.   timer-interval)
  843.  
  844. (define (set-thread-timer-interval! interval)
  845.   (if (not (or (false? interval)
  846.            (and (exact-integer? interval)
  847.             (> interval 0))))
  848.       (error:wrong-type-argument interval #f 'SET-THREAD-TIMER-INTERVAL!))
  849.   (without-interrupts
  850.     (lambda ()
  851.       (set! timer-interval interval)
  852.       (%maybe-toggle-thread-timer))))
  853.  
  854. (define (start-thread-timer)
  855.   (without-interrupts %maybe-toggle-thread-timer))
  856.  
  857. (define (stop-thread-timer)
  858.   (without-interrupts %stop-thread-timer))
  859.  
  860. (define (with-thread-timer-stopped thunk)
  861.   (dynamic-wind %stop-thread-timer thunk %maybe-toggle-thread-timer))
  862.  
  863. (define (%maybe-toggle-thread-timer)
  864.   (cond ((and timer-interval
  865.           (or input-registrations
  866.           (let ((current-thread first-running-thread))
  867.             (and current-thread
  868.              (thread/next current-thread)))))
  869.      (%start-thread-timer timer-interval #t))
  870.     (timer-records
  871.      (let ((next-event-time (timer-record/time timer-records)))
  872.        (let ((next-event-interval (- next-event-time (real-time-clock))))
  873.          (if (or (not timer-interval)
  874.              (> next-event-interval timer-interval))
  875.          (%start-thread-timer next-event-interval next-event-time)
  876.          (%start-thread-timer timer-interval #t)))))
  877.     (else
  878.      (%stop-thread-timer))))
  879.  
  880. (define (%start-thread-timer interval time)
  881.   ;; If TIME is #T, that means interval is TIMER-INTERVAL.  Otherwise,
  882.   ;; INTERVAL is longer than TIMER-INTERVAL, and TIME is when INTERVAL
  883.   ;; ends.  The cases are as follows:
  884.   ;; 1. Timer not running: start it.
  885.   ;; 2. Timer running TIMER-INTERVAL: do nothing.
  886.   ;; 3. Timer running long interval, request sooner: restart it.
  887.   ;; 4. Otherwise: do nothing.
  888.   (if (or (not thread-timer-running?)
  889.       (and (not (eq? #t thread-timer-running?))
  890.            (< (if (eq? #t time)
  891.               (+ (real-time-clock) interval)
  892.               time)
  893.           thread-timer-running?)))
  894.       (begin
  895.     ((ucode-primitive real-timer-set) interval interval)
  896.     (set! thread-timer-running? time)
  897.     unspecific)))
  898.  
  899. (define (%stop-thread-timer)
  900.   (if thread-timer-running?
  901.       (begin
  902.     ((ucode-primitive real-timer-clear))
  903.     (set! thread-timer-running? #f)
  904.     ((ucode-primitive clear-interrupts!) interrupt-bit/timer))))
  905.  
  906. ;;;; Mutexes
  907.  
  908. (define-structure (thread-mutex
  909.            (constructor make-thread-mutex ())
  910.            (conc-name thread-mutex/))
  911.   (waiting-threads (make-ring) read-only #t)
  912.   (owner #f))
  913.  
  914. (define-integrable (guarantee-thread-mutex mutex procedure)
  915.   (if (not (thread-mutex? mutex))
  916.       (error:wrong-type-argument mutex "thread-mutex" procedure)))
  917.  
  918. (define (thread-mutex-owner mutex)
  919.   (guarantee-thread-mutex mutex thread-mutex-owner)
  920.   (thread-mutex/owner mutex))
  921.  
  922. (define (lock-thread-mutex mutex)
  923.   (guarantee-thread-mutex mutex lock-thread-mutex)
  924.   (without-interrupts
  925.    (lambda ()
  926.      (let ((thread (current-thread))
  927.        (owner (thread-mutex/owner mutex)))
  928.        (if (eq? owner thread)
  929.        (signal-thread-deadlock thread "lock thread mutex"
  930.                    lock-thread-mutex mutex))
  931.        (%lock-thread-mutex mutex thread owner)))))
  932.  
  933. (define (%lock-thread-mutex mutex thread owner)
  934.   (add-thread-mutex! thread mutex)
  935.   (if owner
  936.       (begin
  937.     (ring/enqueue (thread-mutex/waiting-threads mutex) thread)
  938.     (do () ((eq? thread (thread-mutex/owner mutex)))
  939.       (%suspend-current-thread)))
  940.       (set-thread-mutex/owner! mutex thread)))
  941.  
  942. (define (unlock-thread-mutex mutex)
  943.   (guarantee-thread-mutex mutex unlock-thread-mutex)
  944.   (without-interrupts
  945.    (lambda ()
  946.      (let ((owner (thread-mutex/owner mutex)))
  947.        (if (and thread (not (eq? owner (current-thread))))
  948.        (error "Don't own mutex:" mutex))
  949.        (%unlock-thread-mutex mutex owner)))))
  950.  
  951. (define (%unlock-thread-mutex mutex owner)
  952.   (remove-thread-mutex! owner mutex)
  953.   (if (%%unlock-thread-mutex mutex)
  954.       (%maybe-toggle-thread-timer)))
  955.  
  956. (define (%%unlock-thread-mutex mutex)
  957.   (let ((thread (ring/dequeue (thread-mutex/waiting-threads mutex) #f)))
  958.     (set-thread-mutex/owner! mutex thread)
  959.     (if thread (%signal-thread-event thread #f))
  960.     thread))
  961.  
  962. (define (try-lock-thread-mutex mutex)
  963.   (guarantee-thread-mutex mutex try-lock-thread-mutex)
  964.   (without-interrupts
  965.    (lambda ()
  966.      (and (not (thread-mutex/owner mutex))
  967.       (let ((thread (current-thread)))
  968.         (set-thread-mutex/owner! mutex thread)
  969.         (add-thread-mutex! thread mutex)
  970.         #t)))))
  971.  
  972. (define (with-thread-mutex-locked mutex thunk)
  973.   (guarantee-thread-mutex mutex lock-thread-mutex)
  974.   (let ((thread (current-thread))
  975.     (grabbed-lock?))
  976.     (dynamic-wind
  977.      (lambda ()
  978.        (let ((owner (thread-mutex/owner mutex)))
  979.      (if (eq? owner thread)
  980.          (begin
  981.            (set! grabbed-lock? #f)
  982.            unspecific)
  983.          (begin
  984.            (set! grabbed-lock? #t)
  985.            (%lock-thread-mutex mutex thread owner)))))
  986.      thunk
  987.      (lambda ()
  988.        (if (and grabbed-lock? (eq? (thread-mutex/owner mutex) thread))
  989.        (%unlock-thread-mutex mutex thread))))))
  990.  
  991. (define (%disassociate-thread-mutexes thread)
  992.   (do ((mutexes (thread/mutexes thread) (cdr mutexes)))
  993.       ((null? mutexes))
  994.     (let ((mutex (car mutexes)))
  995.       (if (eq? (thread-mutex/owner mutex) thread)
  996.       (%%unlock-thread-mutex mutex)
  997.       (ring/remove-item (thread-mutex/waiting-threads mutex) thread))))
  998.   (set-thread/mutexes! thread '()))
  999.  
  1000. (define-integrable (add-thread-mutex! thread mutex)
  1001.   (set-thread/mutexes! thread (cons mutex (thread/mutexes thread))))
  1002.  
  1003. (define-integrable (remove-thread-mutex! thread mutex)
  1004.   (set-thread/mutexes! thread (delq! mutex (thread/mutexes thread))))
  1005.  
  1006. ;;;; Circular Rings
  1007.  
  1008. (define-structure (link (conc-name link/))
  1009.   prev
  1010.   next
  1011.   item)
  1012.  
  1013. (define (make-ring)
  1014.   (let ((link (make-link #f #f #f)))
  1015.     (set-link/prev! link link)
  1016.     (set-link/next! link link)
  1017.     link))
  1018.  
  1019. (define-integrable (ring/empty? ring)
  1020.   (eq? (link/next ring) ring))
  1021.  
  1022. (define (ring/enqueue ring item)
  1023.   (let ((prev (link/prev ring)))
  1024.     (let ((link (make-link prev ring item)))
  1025.       (set-link/next! prev link)
  1026.       (set-link/prev! ring link))))
  1027.  
  1028. (define (ring/dequeue ring default)
  1029.   (let ((link (link/next ring)))
  1030.     (if (eq? link ring)
  1031.     default
  1032.     (begin
  1033.       (let ((next (link/next link)))
  1034.         (set-link/next! ring next)
  1035.         (set-link/prev! next ring))
  1036.       (link/item link)))))
  1037.  
  1038. (define (ring/discard-all ring)
  1039.   (set-link/prev! ring ring)
  1040.   (set-link/next! ring ring))
  1041.  
  1042. (define (ring/remove-item ring item)
  1043.   (let loop ((link (link/next ring)))
  1044.     (if (not (eq? link ring))
  1045.     (if (eq? (link/item link) item)
  1046.         (let ((prev (link/prev link))
  1047.           (next (link/next link)))
  1048.           (set-link/next! prev next)
  1049.           (set-link/prev! next prev))
  1050.         (loop (link/next link))))))
  1051.  
  1052. ;;;; Error Conditions
  1053.  
  1054. (define condition-type:thread-control-error)
  1055. (define thread-control-error/thread)
  1056. (define condition-type:thread-deadlock)
  1057. (define signal-thread-deadlock)
  1058. (define thread-deadlock/description)
  1059. (define thread-deadlock/operator)
  1060. (define thread-deadlock/operand)
  1061. (define condition-type:thread-detached)
  1062. (define signal-thread-detached)
  1063. (define condition-type:thread-dead)
  1064. (define signal-thread-dead)
  1065. (define thread-dead/verb)
  1066. (define condition-type:no-current-thread)
  1067.  
  1068. (define (initialize-error-conditions!)
  1069.   (set! condition-type:thread-control-error
  1070.     (make-condition-type 'THREAD-CONTROL-ERROR condition-type:control-error
  1071.         '(THREAD)
  1072.       (lambda (condition port)
  1073.         (write-string "Anonymous error associated with " port)
  1074.         (write (thread-control-error/thread condition) port)
  1075.         (write-string "." port))))
  1076.   (set! thread-control-error/thread
  1077.     (condition-accessor condition-type:thread-control-error 'THREAD))
  1078.  
  1079.   (set! condition-type:thread-deadlock
  1080.     (make-condition-type 'THREAD-DEADLOCK
  1081.         condition-type:thread-control-error
  1082.         '(DESCRIPTION OPERATOR OPERAND)
  1083.       (lambda (condition port)
  1084.         (write-string "Deadlock detected while trying to " port)
  1085.         (write-string (thread-deadlock/description condition) port)
  1086.         (write-string ": " port)
  1087.         (write (thread-deadlock/operand condition) port)
  1088.         (write-string "." port))))
  1089.   (set! signal-thread-deadlock
  1090.     (condition-signaller condition-type:thread-deadlock
  1091.                  '(THREAD DESCRIPTION OPERATOR OPERAND)
  1092.                  standard-error-handler))
  1093.   (set! thread-deadlock/description
  1094.     (condition-accessor condition-type:thread-deadlock 'DESCRIPTION))
  1095.   (set! thread-deadlock/operator
  1096.     (condition-accessor condition-type:thread-deadlock 'OPERATOR))
  1097.   (set! thread-deadlock/operand
  1098.     (condition-accessor condition-type:thread-deadlock 'OPERAND))
  1099.  
  1100.   (set! condition-type:thread-detached
  1101.     (make-condition-type 'THREAD-DETACHED
  1102.         condition-type:thread-control-error
  1103.         '()
  1104.       (lambda (condition port)
  1105.         (write-string "Attempt to join detached thread: " port)
  1106.         (write (thread-control-error/thread condition) port)
  1107.         (write-string "." port))))
  1108.   (set! signal-thread-detached
  1109.     (condition-signaller condition-type:thread-detached
  1110.                  '(THREAD)
  1111.                  standard-error-handler))
  1112.  
  1113.   (set! condition-type:thread-dead
  1114.     (make-condition-type 'THREAD-DEAD condition-type:thread-control-error
  1115.         '(VERB OPERATOR OPERANDS)
  1116.       (lambda (condition port)
  1117.         (write-string "Unable to " port)
  1118.         (write-string (thread-dead/verb condition) port)
  1119.         (write-string " thread " port)
  1120.         (write (thread-control-error/thread condition) port)
  1121.         (write-string " because it is dead." port))))
  1122.   (set! signal-thread-dead
  1123.     (let ((signaller
  1124.            (condition-signaller condition-type:thread-dead
  1125.                     '(THREAD VERB OPERATOR OPERANDS)
  1126.                     standard-error-handler)))
  1127.       (lambda (thread verb operator . operands)
  1128.         (signaller thread verb operator operands))))
  1129.   (set! thread-dead/verb
  1130.     (condition-accessor condition-type:thread-dead 'VERB))
  1131.  
  1132.   (set! condition-type:no-current-thread
  1133.     (make-condition-type 'NO-CURRENT-THREAD condition-type:control-error
  1134.         '()
  1135.       (lambda (condition port)
  1136.         condition
  1137.         (write-string "No current thread!" port))))
  1138.   unspecific)