X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fassembly%2Fx86%2Falloc.lisp;h=3131e454bf523bec6966b2fdec0b7e53967408bb;hb=518493eab883e50237043153c0d45b245e929c7d;hp=e52052d51eb88feb14c993320dd5288c0f48a2f9;hpb=91249484164b74b9df8b65f8ecd1fe228a08276c;p=sbcl.git diff --git a/src/assembly/x86/alloc.lisp b/src/assembly/x86/alloc.lisp index e52052d..3131e45 100644 --- a/src/assembly/x86/alloc.lisp +++ b/src/assembly/x86/alloc.lisp @@ -80,50 +80,60 @@ (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) + (let ((not-eax ,(if (eql 'eax reg) 'other 'target))) + (inst mov not-eax 1) + (inst xor eax-tn eax-tn) + (inst cmpxchg (make-ea-for-symbol-value *tls-index-lock*) + not-eax :lock) + (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 test target target) + (inst jmp :ne release-tls-index-lock) + ;; Allocate a new tls-index. + (load-symbol-value target *free-tls-index*) + (let ((not-error (gen-label)) + (error (generate-error-code nil 'tls-exhausted-error))) + (inst cmp target (ash tls-size word-shift)) + (inst jmp :l not-error) + (%clear-pseudo-atomic) + (inst jmp error) + (emit-label not-error)) + (inst add (make-ea-for-symbol-value *free-tls-index*) + n-word-bytes) + (storew target other symbol-tls-index-slot other-pointer-lowtag) + (emit-label release-tls-index-lock) + ;; No need for barriers on x86/x86-64 on unlock. + (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)) -