interrupt.scm 3.3 KB

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