interrupt.scm 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, David Frese
  3. ; Interrupts
  4. ; Create and install a vector of interrupt handlers. We want this to happen
  5. ; as early as possible. All but the post-gc and keyboard interrupts raise a
  6. ; VM exception by default. We exit when a keyboard interrupt occurs. The default
  7. ; post-gc handlers are defined below.
  8. (define (initialize-interrupts! spawn-on-root thunk)
  9. (primitive-cwcc
  10. (lambda (exit)
  11. (let ((handlers (make-vector interrupt-count 0)))
  12. (do ((i 0 (+ i 1)))
  13. ((= i interrupt-count))
  14. (vector-set! handlers
  15. i
  16. (lambda stuff
  17. (signal-condition (condition
  18. (make-interrupt-condition (car stuff))
  19. (make-irritants-condition (cdr stuff)))))))
  20. (vector-set! handlers
  21. (enum interrupt post-major-gc)
  22. (post-gc-handler #t spawn-on-root))
  23. (vector-set! handlers
  24. (enum interrupt post-minor-gc)
  25. (post-gc-handler #f spawn-on-root))
  26. (vector-set! handlers
  27. (enum interrupt keyboard)
  28. (lambda args
  29. (with-continuation exit (lambda () -1))))
  30. (set-interrupt-handlers! handlers)
  31. (session-data-set! interrupt-handlers handlers))
  32. (set-enabled-interrupts! all-interrupts)
  33. (thunk))))
  34. (define interrupt-handlers (make-session-data-slot! 0))
  35. ; Set an interrupt handler.
  36. (define (set-interrupt-handler! interrupt handler)
  37. (vector-set! (session-data-ref interrupt-handlers)
  38. interrupt
  39. handler))
  40. (define (get-interrupt-handler interrupt)
  41. (vector-ref (session-data-ref interrupt-handlers)
  42. interrupt))
  43. (define no-interrupts 0)
  44. (define all-interrupts
  45. (- (arithmetic-shift 1 interrupt-count) 1))
  46. (define (with-interrupts-inhibited thunk)
  47. (with-interrupts no-interrupts thunk))
  48. (define (with-interrupts-allowed thunk)
  49. (with-interrupts all-interrupts thunk))
  50. (define (disable-interrupts!)
  51. (set-enabled-interrupts! no-interrupts))
  52. (define (enable-interrupts!)
  53. (set-enabled-interrupts! all-interrupts))
  54. (define (with-interrupts interrupts thunk)
  55. ;; I might consider using dynamic-wind here, but (a) I'm worried
  56. ;; about the speed of thread switching (which uses this) and (b)
  57. ;; it's a pretty bad idea to throw in or out of one of these anyhow.
  58. (let ((ei (set-enabled-interrupts! interrupts)))
  59. (call-with-values thunk
  60. (lambda results
  61. (set-enabled-interrupts! ei)
  62. (apply values results)))))
  63. (define (enabled-interrupts) ;For debugging
  64. (let ((e (set-enabled-interrupts! 0)))
  65. (set-enabled-interrupts! e)
  66. e))
  67. ;----------------
  68. ; Post-GC interrupts
  69. (define *post-gc-procedures* '())
  70. (define (call-after-gc! thunk)
  71. (if (not (memq thunk *post-gc-procedures*))
  72. (set! *post-gc-procedures* (cons thunk *post-gc-procedures*))))
  73. (define (post-gc-handler major? spawn-on-root)
  74. (lambda (finalizer-list enabled-interrupts in-trouble?)
  75. (if in-trouble?
  76. (spawn-on-root
  77. (lambda ()
  78. ((session-data-ref space-shortage-handler)))))
  79. (spawn-on-root
  80. (lambda ()
  81. (for-each (lambda (p)
  82. ((cdr p) (car p)))
  83. finalizer-list)
  84. (if major?
  85. (for-each (lambda (thunk)
  86. (thunk))
  87. *post-gc-procedures*)))
  88. 'post-gc-handler)
  89. (set-enabled-interrupts! enabled-interrupts)))
  90. (define space-shortage-handler
  91. (make-session-data-slot! (lambda (required space) #f)))
  92. (define (call-before-heap-overflow! handler . maybe-required-space-percentage)
  93. (session-data-set! space-shortage-handler handler))