"%INSTANCE-REF"
"%INSTANCE-SET"
"SYSTEM-AREA-CLEAR"
+ "TLS-EXHAUSTED-ERROR"
"TWO-ARG-*" "TWO-ARG-+" "TWO-ARG--" "TWO-ARG-/"
"TWO-ARG-/=" "TWO-ARG-<" "TWO-ARG-<=" "TWO-ARG-="
"TWO-ARG->" "TWO-ARG->=" "TWO-ARG-AND" "TWO-ARG-EQV"
#!+linkage-table "LINKAGE-TABLE-SPACE-START"
#!+linkage-table "LINKAGE-TABLE-SPACE-END"
#!+linkage-table "LINKAGE-TABLE-ENTRY-SIZE"
+ "TLS-SIZE"
"TRACE-TABLE-CALL-SITE"
"TRACE-TABLE-FUN-EPILOGUE" "TRACE-TABLE-FUN-PROLOGUE"
"TRACE-TABLE-NORMAL" "N-WIDETAG-BITS" "WIDETAG-MASK"
(def r15))
#+sb-assembling
-(macrolet ((def (reg)
- (declare (ignorable reg))
- #!+sb-thread
- (let* ((name (intern (format nil "ALLOC-TLS-INDEX-IN-~A" reg)))
- (target-offset (intern (format nil "~A-OFFSET" reg)))
- (other-offset (if (eql 'rax reg)
- 'rcx-offset
- 'rax-offset)))
- ;; Symbol starts in TARGET, where the TLS-INDEX ends up in.
- `(define-assembly-routine ,name
- ((:temp other descriptor-reg ,other-offset)
- (:temp target descriptor-reg ,target-offset))
- (let ((get-tls-index-lock (gen-label))
- (release-tls-index-lock (gen-label)))
- (pseudo-atomic
- ;; Save OTHER & push the symbol. RAX is either one of the two.
- (inst push other)
- (inst push target)
- (emit-label get-tls-index-lock)
- (inst mov target 1)
- (zeroize rax-tn)
- (inst lock)
- (inst cmpxchg (make-ea-for-symbol-value *tls-index-lock*) target)
- (inst jmp :ne get-tls-index-lock)
- ;; The symbol is now in OTHER.
- (inst pop other)
- ;; Now with the lock held, see if the symbol's tls index has been
- ;; set in the meantime.
- (loadw target other symbol-tls-index-slot other-pointer-lowtag)
- (inst or target target)
- (inst jmp :ne release-tls-index-lock)
- ;; Allocate a new tls-index.
- (load-symbol-value target *free-tls-index*)
- (inst add (make-ea-for-symbol-value *free-tls-index*) (fixnumize 1))
- (storew target other symbol-tls-index-slot other-pointer-lowtag)
- (emit-label release-tls-index-lock)
- (store-symbol-value 0 *tls-index-lock*)
- ;; Restore OTHER.
- (inst pop other))
- (inst ret))))))
+(macrolet
+ ((def (reg)
+ (declare (ignorable reg))
+ #!+sb-thread
+ (let* ((name (intern (format nil "ALLOC-TLS-INDEX-IN-~A" reg)))
+ (target-offset (intern (format nil "~A-OFFSET" reg)))
+ (other-offset (if (eql 'rax reg)
+ 'rcx-offset
+ 'rax-offset)))
+ ;; Symbol starts in TARGET, where the TLS-INDEX ends up in.
+ `(define-assembly-routine ,name
+ ((:temp other descriptor-reg ,other-offset)
+ (:temp target descriptor-reg ,target-offset))
+ (let ((get-tls-index-lock (gen-label))
+ (release-tls-index-lock (gen-label)))
+ (pseudo-atomic
+ ;; Save OTHER & push the symbol. RAX is either one of the two.
+ (inst push other)
+ (inst push target)
+ (emit-label get-tls-index-lock)
+ (inst mov target 1)
+ (zeroize rax-tn)
+ (inst lock)
+ (inst cmpxchg (make-ea-for-symbol-value *tls-index-lock*) target)
+ (inst jmp :ne get-tls-index-lock)
+ ;; The symbol is now in OTHER.
+ (inst pop other)
+ ;; Now with the lock held, see if the symbol's tls index has been
+ ;; set in the meantime.
+ (loadw target other symbol-tls-index-slot other-pointer-lowtag)
+ (inst or target target)
+ (inst jmp :ne release-tls-index-lock)
+ ;; Allocate a new tls-index.
+ (load-symbol-value target *free-tls-index*)
+ (let ((error (generate-error-code nil 'tls-exhausted-error)))
+ (inst cmp target (fixnumize tls-size))
+ (inst jmp :ge error))
+ (inst add (make-ea-for-symbol-value *free-tls-index*)
+ (fixnumize 1))
+ (storew target other symbol-tls-index-slot other-pointer-lowtag)
+ (emit-label release-tls-index-lock)
+ (store-symbol-value 0 *tls-index-lock*)
+ ;; Restore OTHER.
+ (inst pop other))
+ (inst ret))))))
(def rax)
(def rcx)
(def rdx)
(frob-cons-routines))
#+sb-assembling
-(macrolet ((def (reg)
- (declare (ignorable reg))
- #!+sb-thread
- (let* ((name (intern (format nil "ALLOC-TLS-INDEX-IN-~A" reg)))
- (target-offset (intern (format nil "~A-OFFSET" reg)))
- (other-offset (if (eql 'eax reg)
- 'ecx-offset
- 'eax-offset)))
- ;; Symbol starts in TARGET, where the TLS-INDEX ends up in.
- `(define-assembly-routine ,name
- ((:temp other descriptor-reg ,other-offset)
- (:temp target descriptor-reg ,target-offset))
- (let ((get-tls-index-lock (gen-label))
- (release-tls-index-lock (gen-label)))
- (pseudo-atomic
- ;; Save OTHER & push the symbol. EAX is either one of the two.
- (inst push other)
- (inst push target)
- (emit-label get-tls-index-lock)
- (inst mov target 1)
- (inst xor eax-tn eax-tn)
- (inst lock)
- (inst cmpxchg (make-ea-for-symbol-value *tls-index-lock*) target)
- (inst jmp :ne get-tls-index-lock)
- ;; The symbol is now in OTHER.
- (inst pop other)
- ;; Now with the lock held, see if the symbol's tls index has been
- ;; set in the meantime.
- (loadw target other symbol-tls-index-slot other-pointer-lowtag)
- (inst or target target)
- (inst jmp :ne release-tls-index-lock)
- ;; Allocate a new tls-index.
- (load-symbol-value target *free-tls-index*)
- (inst add (make-ea-for-symbol-value *free-tls-index*) (fixnumize 1))
- (storew target other symbol-tls-index-slot other-pointer-lowtag)
- (emit-label release-tls-index-lock)
- (store-symbol-value 0 *tls-index-lock*)
- ;; Restore OTHER.
- (inst pop other))
- (inst ret))))))
+(macrolet
+ ((def (reg)
+ (declare (ignorable reg))
+ #!+sb-thread
+ (let* ((name (intern (format nil "ALLOC-TLS-INDEX-IN-~A" reg)))
+ (target-offset (intern (format nil "~A-OFFSET" reg)))
+ (other-offset (if (eql 'eax reg)
+ 'ecx-offset
+ 'eax-offset)))
+ ;; Symbol starts in TARGET, where the TLS-INDEX ends up in.
+ `(define-assembly-routine ,name
+ ((:temp other descriptor-reg ,other-offset)
+ (:temp target descriptor-reg ,target-offset))
+ (let ((get-tls-index-lock (gen-label))
+ (release-tls-index-lock (gen-label)))
+ (pseudo-atomic
+ ;; Save OTHER & push the symbol. EAX is either one of the two.
+ (inst push other)
+ (inst push target)
+ (emit-label get-tls-index-lock)
+ (inst mov target 1)
+ (inst xor eax-tn eax-tn)
+ (inst lock)
+ (inst cmpxchg (make-ea-for-symbol-value *tls-index-lock*) target)
+ (inst jmp :ne get-tls-index-lock)
+ ;; The symbol is now in OTHER.
+ (inst pop other)
+ ;; Now with the lock held, see if the symbol's tls index has been
+ ;; set in the meantime.
+ (loadw target other symbol-tls-index-slot other-pointer-lowtag)
+ (inst or target target)
+ (inst jmp :ne release-tls-index-lock)
+ ;; Allocate a new tls-index.
+ (load-symbol-value target *free-tls-index*)
+ (let ((error (generate-error-code nil 'tls-exhausted-error)))
+ (inst cmp target (fixnumize tls-size))
+ (inst jmp :ge error))
+ (inst add (make-ea-for-symbol-value *free-tls-index*)
+ (fixnumize 1))
+ (storew target other symbol-tls-index-slot other-pointer-lowtag)
+ (emit-label release-tls-index-lock)
+ (store-symbol-value 0 *tls-index-lock*)
+ ;; Restore OTHER.
+ (inst pop other))
+ (inst ret))))))
(def eax)
(def ebx)
(def ecx)
(def edx)
(def edi)
(def esi))
-
:datum object
:expected-type '(unsigned-byte 32)))
+(deferr tls-exhausted-error ()
+ ;; There is nothing we can do about it. A number of entries in the
+ ;; tls could be reserved and made available for recovery but since
+ ;; tls indices are never reused it would be kind of silly and
+ ;; without it signalling an error is more than likely to end in a
+ ;; recursive error.
+ (%primitive print "Thread local storage exhausted.")
+ (sb!impl::%halt))
+
(macrolet
((define-simple-array-internal-errors ()
`(progn
"Object layout is invalid. (indicates obsolete instance)")
(object-not-complex-vector
"Object is not a complex (non-SIMPLE-ARRAY) vector.")
+ (tls-exhausted
+ "Thread local storage exhausted.")
.
#.(map 'list
(lambda (saetp)
:value
:key-and-value
:key-or-value))
+
+;;; Number of entries in the thread local storage. Limits the number
+;;; of symbols with thread local bindings.
+(def!constant tls-size 4096)
sym->tls_index=SymbolValue(FREE_TLS_INDEX,0);
SetSymbolValue(FREE_TLS_INDEX,
make_fixnum(fixnum_value(sym->tls_index)+1),0);
+ if(fixnum_value(sym->tls_index)>=TLS_SIZE) {
+ lose("Thread local storage exhausted.");
+ }
}
release_spinlock(tls_index_lock);
clear_pseudo_atomic_atomic(th);
static struct freeable_stack * volatile freeable_stack = 0;
#endif
-int dynamic_values_bytes=4096*sizeof(lispobj); /* same for all threads */
+int dynamic_values_bytes=TLS_SIZE*sizeof(lispobj); /* same for all threads */
struct thread * volatile all_threads;
extern struct interrupt_data * global_interrupt_data;
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.16.20"
+"1.0.16.21"