(define default-safety-margin)
\f
(define (default/gc-flip safety-margin)
- (if (and (not (eq? '() constant-space-queue))
- (not (object-constant? constant-space-queue)))
- (purify-internal constant-space-queue safety-margin)
- (gc-flip-internal safety-margin)))
+ (with-gc-lock
+ (lambda ()
+ (if (and (not (eq? '() constant-space-queue))
+ (not (object-constant? constant-space-queue)))
+ (purify-internal constant-space-queue safety-margin)
+ (gc-flip-internal safety-margin)))))
(define (default/purify item pure-space? queue?)
pure-space?
(lambda ()
(set! constant-space-queue (cons item constant-space-queue))
unspecific))
- (purify-internal item default-safety-margin))))
+ (with-heap-lock
+ (lambda ()
+ (purify-internal item default-safety-margin))))))
(define (default/stack-overflow)
(abort->nearest "Aborting!: maximum recursion depth exceeded"))
(let ((do-it
(lambda ()
(let loop ()
- (if (not ((ucode-primitive primitive-fasdump)
- object filename dump-option))
+ (if (not (with-heap-lock
+ (lambda ()
+ ((ucode-primitive primitive-fasdump)
+ object filename dump-option))))
(begin
(with-simple-restart 'RETRY "Try again."
(lambda ()
args
(abort->nearest "Aborting! Out of memory"))
+(define (global-gc-interrupt-handler interrupt-code interrupt-enables)
+ interrupt-code interrupt-enables
+ ((ucode-primitive smp-gc-wait 0)))
+
(define after-gc-interrupt-handler
(let ((running? #f))
(named-lambda (after-gc-interrupt-handler interrupt-code interrupt-enables)
(vector-set! interrupt-mask-vector gc-slot
interrupt-mask/none)
+ (vector-set! system-interrupt-vector global-gc-slot
+ global-gc-interrupt-handler)
+ (vector-set! interrupt-mask-vector global-gc-slot
+ interrupt-mask/none)
+
(vector-set! system-interrupt-vector timer-slot
timer-interrupt-handler)
(vector-set! interrupt-mask-vector timer-slot
with-values
write-to-string)
(import (runtime thread)
+ with-heap-lock
with-obarray-lock)
(initialization (initialize-package!)))
hook/hardware-trap)
(export (runtime gc-notification)
abort-if-heap-low)
+ (import (runtime thread)
+ with-gc-lock
+ with-heap-lock)
(initialization (initialize-package!)))
(define-package (runtime gc-daemons)
trigger-secondary-gc-daemons!)
(export (runtime interrupt-handler)
trigger-gc-daemons!)
+ (import (runtime thread)
+ enable-smp?)
(initialization (initialize-package!)))
(define-package (runtime gc-finalizer)
(set-interrupt-enables! mask)
value)))
+(define (with-gc-lock thunk)
+ ;; Serialize processors wanting to GC.
+ ;; If this processor loses the race to lock the heap, punt THUNK and
+ ;; just wait for the winner to perform the GC.
+ (%assert (eq? interrupt-mask/none (get-interrupt-enables))
+ "with-gc-lock: wrong interrupt mask")
+ (if enable-smp?
+ (if ((ucode-primitive smp-gc-lock 0))
+ (let ((value (thunk)))
+ ((ucode-primitive smp-gc-unlock 0))
+ value)
+ (begin
+ ((ucode-primitive smp-gc-wait 0))
+ (let ((space ((ucode-primitive gc-space-status))))
+ (- (vector-ref space 14) ;shared_heap_end
+ (vector-ref space 13) ;shared_heap_free
+ ))))
+ (thunk)))
+
+(define (with-heap-lock thunk)
+ ;; Serialize other access (besides GC) to the heap.
+ ;; If this processor loses the race to lock the heap, wait and then
+ ;; try again.
+ (with-absolutely-no-interrupts
+ (lambda ()
+ (if enable-smp?
+ (let retry ()
+ (if ((ucode-primitive smp-gc-lock 0))
+ (let ((value (thunk)))
+ ((ucode-primitive smp-gc-unlock 0))
+ value)
+ (begin
+ ((ucode-primitive smp-gc-wait 0))
+ (retry))))
+ (thunk)))))
+
(define (threads-list)
(with-thread-lock
(lambda ()