Shorten pseudo-atomic sequence on x86 and x86-64.
Do this by combining *pseudo-atomic-{atomic,interrupted}* into
a single variable, *pseudo-atomic-bits*, which is a fixnum
bitmask where bit 0 denotes atomic-ness and bit 1 denotes
interruptedness.
* Change genesis to initialize this variable properly (this
didn't need to be done for the old variables because the
allocation sequences would set them upon entrance);
* Modify functions and macros accessing pseudo-atomic variables
to reflect the new state of the world;
"PACKAGE-INTERNAL-SYMBOLS" "PACKAGE-EXTERNAL-SYMBOLS"
"PARSE-DEFMACRO" "PARSE-UNKNOWN-TYPE"
"PARSE-UNKNOWN-TYPE-SPECIFIER" "PATHNAME-DESIGNATOR"
- #!+(or x86 x86-64) "*PSEUDO-ATOMIC-ATOMIC*"
- #!+(or x86 x86-64) "*PSEUDO-ATOMIC-INTERRUPTED*"
+ #!+(or x86 x86-64) "*PSEUDO-ATOMIC-BITS*"
"PUNT-PRINT-IF-TOO-LONG" "READER-IMPOSSIBLE-NUMBER-ERROR"
"READER-PACKAGE-ERROR" "READER-EOF-ERROR"
"RESTART-DESIGNATOR"
;;; versions which break binary compatibility. But it certainly should
;;; be incremented for release versions which break binary
;;; compatibility.
-(def!constant +fasl-file-version+ 69)
+(def!constant +fasl-file-version+ 70)
;;; (record of versions before 2003 deleted in 2003-04-26/0.pre8.107 or so)
;;; 38: (2003-01-05) changed names of internal SORT machinery
;;; 39: (2003-02-20) in 0.7.12.1 a slot was added to
;;; 0.9.14.something
;;; 68: (2006-08-14) changed number of arguments of LOAD-DEFMETHOD
;;; 69: (2006-08-17) changed validity of various initargs for methods
+;;; 70: (2006-09-13) changes to *PSEUDO-ATOMIC* on x86 and x86-64
;;; the conventional file extension for our fasl files
(declaim (type simple-string *fasl-file-type*))
;; :X86. (Note that non-X86 ports mention
;; pseudo-atomicity too, but they handle it without
;; messing with special variables.)
- #!+(or x86 x86-64) *pseudo-atomic-atomic*
- #!+(or x86 x86-64) *pseudo-atomic-interrupted*
+ #!+(or x86 x86-64) *pseudo-atomic-bits*
sb!unix::*interrupts-enabled*
sb!unix::*interrupt-pending*
*free-interrupt-context-index*
;;; specials initialized by !COLD-INIT
;;; FIXME: These could be converted to DEFVARs.
-(declaim (special #!+(or x86 x86-64) *pseudo-atomic-atomic*
- #!+(or x86 x86-64) *pseudo-atomic-interrupted*
+(declaim (special #!+(or x86 x86-64) *pseudo-atomic-bits*
sb!unix::*interrupts-enabled*
sb!unix::*interrupt-pending*
*type-system-initialized*))
offset-wanted))))
;; Establish the value of T.
(let ((t-symbol (cold-intern t)))
- (cold-set t-symbol t-symbol))))
+ (cold-set t-symbol t-symbol))
+ ;; Establish the value of *PSEUDO-ATOMIC-BITS* so that the
+ ;; allocation sequences that expect it to be zero upon entrance
+ ;; actually find it to be so.
+ #!+(or x86-64 x86)
+ (let ((p-a-a-symbol (cold-intern 'sb!kernel:*pseudo-atomic-bits*)))
+ (cold-set p-a-a-symbol (make-fixnum-descriptor 0)))))
;;; a helper function for FINISH-SYMBOLS: Return a cold alist suitable
;;; to be stored in *!INITIAL-LAYOUTS*.
;; starting, running, suspended, dead
(state :c-type "volatile lispobj")
(tls-cookie) ; on x86, the LDT index
- #!+(or x86 x86-64) (pseudo-atomic-atomic)
- #!+(or x86 x86-64) (pseudo-atomic-interrupted)
+ #!+(or x86 x86-64) (pseudo-atomic-bits)
(interrupt-data :c-type "struct interrupt_data *"
:length #!+alpha 2 #!-alpha 1)
(interrupt-contexts :c-type "os_context_t *" :rest-p t))
;;; place and there's no logical single place to attach documentation.
;;; grep (mostly in src/runtime) is your friend
-;;; FIXME: *PSEUDO-ATOMIC-FOO* could be made into *PSEUDO-ATOMIC-BITS*,
-;;; set with a single operation and cleared with SHR *PSEUDO-ATOMIC-BITS*,-2;
-;;; the ATOMIC bit is bit 0, the INTERRUPTED bit is bit 1, and you check
-;;; the C flag after the shift to see whether you were interrupted.
-
;;; FIXME: THIS NAME IS BACKWARDS!
(defmacro maybe-pseudo-atomic (really-p &body body)
`(if ,really-p
(defmacro pseudo-atomic (&rest forms)
(with-unique-names (label)
`(let ((,label (gen-label)))
- (inst mov (make-ea :byte
+ (inst or (make-ea :byte
:base thread-base-tn
- :disp (* 8 thread-pseudo-atomic-atomic-slot))
+ :disp (* 8 thread-pseudo-atomic-bits-slot))
(fixnumize 1))
,@forms
- (inst mov (make-ea :byte
- :base thread-base-tn
- :disp (* 8 thread-pseudo-atomic-atomic-slot)) 0)
- (inst cmp (make-ea :byte
+ (inst xor (make-ea :byte
:base thread-base-tn
- :disp (* 8 thread-pseudo-atomic-interrupted-slot)) 0)
- (inst jmp :eq ,label)
+ :disp (* 8 thread-pseudo-atomic-bits-slot))
+ (fixnumize 1))
+ (inst jmp :z ,label)
;; if PAI was set, interrupts were disabled at the same
;; time using the process signal mask.
(inst break pending-interrupt-trap)
`(let ((,label (gen-label)))
;; FIXME: The MAKE-EA noise should become a MACROLET macro or
;; something. (perhaps SVLB, for static variable low byte)
- (inst mov (make-ea :byte :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-atomic*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
- (fixnumize 1))
+ (inst or (make-ea :byte :disp (+ nil-value
+ (static-symbol-offset
+ '*pseudo-atomic-bits*)
+ (ash symbol-value-slot word-shift)
+ (- other-pointer-lowtag)))
+ (fixnumize 1))
,@forms
- (inst mov (make-ea :byte :disp (+ nil-value
+ (inst xor (make-ea :byte :disp (+ nil-value
(static-symbol-offset
- '*pseudo-atomic-atomic*)
+ '*pseudo-atomic-bits*)
(ash symbol-value-slot word-shift)
(- other-pointer-lowtag)))
- 0)
- (inst cmp (make-ea :byte
- :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-interrupted*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
- 0)
- (inst jmp :eq ,label)
+ (fixnumize 1))
+ (inst jmp :z ,label)
;; if PAI was set, interrupts were disabled at the same time
;; using the process signal mask.
(inst break pending-interrupt-trap)
'(*alien-stack*
;; interrupt handling
- *pseudo-atomic-atomic*
- *pseudo-atomic-interrupted*
+ *pseudo-atomic-bits*
#!+sb-thread *stop-for-gc-pending*
;;; place and there's no logical single place to attach documentation.
;;; grep (mostly in src/runtime) is your friend
-;;; FIXME: *PSEUDO-ATOMIC-FOO* could be made into *PSEUDO-ATOMIC-BITS*,
-;;; set with a single operation and cleared with SHR *PSEUDO-ATOMIC-BITS*,-2;
-;;; the ATOMIC bit is bit 0, the INTERRUPTED bit is bit 1, and you check
-;;; the C flag after the shift to see whether you were interrupted.
-;;;
;;; KLUDGE: since the stack on the x86 is treated conservatively, it
;;; does not matter whether a signal occurs during construction of a
;;; dynamic-extent object, as the half-finished construction of the
(with-unique-names (label)
`(let ((,label (gen-label)))
(inst fs-segment-prefix)
- (inst mov (make-ea :byte :disp (* 4 thread-pseudo-atomic-atomic-slot))
+ (inst or (make-ea :byte :disp (* 4 thread-pseudo-atomic-bits-slot))
(fixnumize 1))
,@forms
(inst fs-segment-prefix)
- (inst mov (make-ea :byte :disp (* 4 thread-pseudo-atomic-atomic-slot)) 0)
- (inst fs-segment-prefix)
- (inst cmp (make-ea :byte
- :disp (* 4 thread-pseudo-atomic-interrupted-slot)) 0)
- (inst jmp :eq ,label)
+ (inst xor (make-ea :byte :disp (* 4 thread-pseudo-atomic-bits-slot))
+ (fixnumize 1))
+ (inst jmp :z ,label)
;; if PAI was set, interrupts were disabled at the same
;; time using the process signal mask.
(inst break pending-interrupt-trap)
;; FIXME: The MAKE-EA noise should become a MACROLET macro
;; or something. (perhaps SVLB, for static variable low
;; byte)
- (inst mov (make-ea :byte :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-atomic*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
+ (inst or (make-ea :byte :disp (+ nil-value
+ (static-symbol-offset
+ '*pseudo-atomic-bits*)
+ (ash symbol-value-slot word-shift)
+ (- other-pointer-lowtag)))
(fixnumize 1))
,@forms
- (inst mov (make-ea :byte :disp (+ nil-value
+ (inst xor (make-ea :byte :disp (+ nil-value
(static-symbol-offset
- '*pseudo-atomic-atomic*)
+ '*pseudo-atomic-bits*)
(ash symbol-value-slot word-shift)
(- other-pointer-lowtag)))
- 0)
- (inst cmp (make-ea :byte
- :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-interrupted*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
- 0)
- (inst jmp :eq ,label)
+ (fixnumize 1))
+ (inst jmp :z ,label)
;; if PAI was set, interrupts were disabled at the same
;; time using the process signal mask.
(inst break pending-interrupt-trap)
'(*alien-stack*
;; interrupt handling
- *pseudo-atomic-atomic*
- *pseudo-atomic-interrupted*
+ *pseudo-atomic-bits*
#!+sb-thread *stop-for-gc-pending*
#!+sb-thread *free-tls-index*
#!+sb-thread *tls-index-lock*
#include "globals.h"
#include "dynbind.h"
#include "thread.h"
+#include "pseudo-atomic.h"
#include "genesis/symbol.h"
#include "genesis/binding.h"
#include "genesis/thread.h"
if(!sym->tls_index) {
lispobj *tls_index_lock=
&((struct symbol *)native_pointer(TLS_INDEX_LOCK))->value;
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(0),th);
- SetSymbolValue(PSEUDO_ATOMIC_ATOMIC, make_fixnum(1),th);
+ clear_pseudo_atomic_interrupted(th);
+ set_pseudo_atomic_atomic(th);
get_spinlock(tls_index_lock,(long)th);
if(!sym->tls_index) {
sym->tls_index=SymbolValue(FREE_TLS_INDEX,0);
make_fixnum(fixnum_value(sym->tls_index)+1),0);
}
release_spinlock(tls_index_lock);
- SetSymbolValue(PSEUDO_ATOMIC_ATOMIC, make_fixnum(0),th);
- if (fixnum_value(SymbolValue(PSEUDO_ATOMIC_INTERRUPTED,th)))
+ clear_pseudo_atomic_atomic(th);
+ if (get_pseudo_atomic_interrupted(th))
do_pending_interrupt();
}
}
#include "fixnump.h"
-#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
-
-#define set_alloc_pointer(value) \
- SetSymbolValue(ALLOCATION_POINTER, value, 0)
-#define get_alloc_pointer() \
- SymbolValue(ALLOCATION_POINTER, 0)
-#define get_binding_stack_pointer(thread) \
- SymbolValue(BINDING_STACK_POINTER, thread)
-#define get_pseudo_atomic_atomic(thread) \
- SymbolValue(PSEUDO_ATOMIC_ATOMIC, thread)
-#define set_pseudo_atomic_atomic(thread) \
- SetSymbolValue(PSEUDO_ATOMIC_ATOMIC, make_fixnum(1), thread);
-#define clear_pseudo_atomic_atomic(thread) \
- SetSymbolValue(PSEUDO_ATOMIC_ATOMIC, make_fixnum(0), thread);
-#define get_pseudo_atomic_interrupted(thread) \
- fixnum_value(SymbolValue(PSEUDO_ATOMIC_INTERRUPTED, thread))
-#define clear_pseudo_atomic_interrupted(thread) \
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(0), thread)
-#define set_pseudo_atomic_interrupted(thread) \
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1), thread)
-
-#elif defined(LISP_FEATURE_PPC) && defined(LISP_FEATURE_GENCGC)
-
-#define set_alloc_pointer(value) \
- (dynamic_space_free_pointer = \
- (value) | (((unsigned long)dynamic_space_free_pointer) & LOWTAG_MASK))
-
-#define get_alloc_pointer() \
- ((unsigned long) dynamic_space_free_pointer & ~LOWTAG_MASK)
-#define get_binding_stack_pointer(thread) \
- (current_binding_stack_pointer)
-#define get_pseudo_atomic_atomic(thread) \
- ((unsigned long)dynamic_space_free_pointer & flag_PseudoAtomic)
-#define set_pseudo_atomic_atomic(thread) \
- (dynamic_space_free_pointer \
- = (lispobj*) ((unsigned long)dynamic_space_free_pointer | flag_PseudoAtomic))
-#define clear_pseudo_atomic_atomic(thread) \
- (dynamic_space_free_pointer \
- = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomic))
-#define get_pseudo_atomic_interrupted(thread) \
- ((unsigned long) dynamic_space_free_pointer & flag_PseudoAtomicInterrupted)
-#define clear_pseudo_atomic_interrupted(thread) \
- (dynamic_space_free_pointer \
- = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomicInterrupted))
-#define set_pseudo_atomic_interrupted(thread) \
- (dynamic_space_free_pointer \
- = (lispobj*) ((unsigned long) dynamic_space_free_pointer | flag_PseudoAtomicInterrupted))
-
-#endif
+#include "pseudo-atomic.h"
#endif /* _GC_H_ */
--- /dev/null
+/*
+ * macros for manipulating pseudo-atomic flags (per thread)
+ */
+
+/*
+ * This software is part of the SBCL system. See the README file for
+ * more information.
+ *
+ * This software is derived from the CMU CL system, which was
+ * written at Carnegie Mellon University and released into the
+ * public domain. The software is in the public domain and is
+ * provided with absolutely no warranty. See the COPYING and CREDITS
+ * files for more information.
+ */
+
+#ifndef PSEUDO_ATOMIC_H
+#define PSEUDO_ATOMIC_H
+
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+
+#define set_alloc_pointer(value) \
+ SetSymbolValue(ALLOCATION_POINTER, value, 0)
+#define get_alloc_pointer() \
+ SymbolValue(ALLOCATION_POINTER, 0)
+#define get_binding_stack_pointer(thread) \
+ SymbolValue(BINDING_STACK_POINTER, thread)
+#define get_pseudo_atomic_atomic(thread) \
+ (fixnum_value(SymbolValue(PSEUDO_ATOMIC_BITS, thread) & make_fixnum(1)))
+#define set_pseudo_atomic_atomic(thread) \
+ { \
+ lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread); \
+ SetSymbolValue(PSEUDO_ATOMIC_BITS, bits | make_fixnum(1), thread); \
+ }
+#define clear_pseudo_atomic_atomic(thread) \
+ { \
+ lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread); \
+ SetSymbolValue(PSEUDO_ATOMIC_BITS, bits & ~make_fixnum(1), thread); \
+ }
+#define get_pseudo_atomic_interrupted(thread) \
+ (fixnum_value(SymbolValue(PSEUDO_ATOMIC_BITS, thread) & make_fixnum(2)))
+#define clear_pseudo_atomic_interrupted(thread) \
+ { \
+ lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread); \
+ SetSymbolValue(PSEUDO_ATOMIC_BITS, bits & ~make_fixnum(2), thread); \
+ }
+
+#define set_pseudo_atomic_interrupted(thread) \
+ { \
+ lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread); \
+ SetSymbolValue(PSEUDO_ATOMIC_BITS, bits | make_fixnum(2), thread); \
+ }
+
+#elif defined(LISP_FEATURE_PPC) && defined(LISP_FEATURE_GENCGC)
+
+#define set_alloc_pointer(value) \
+ (dynamic_space_free_pointer = \
+ (value) | (((unsigned long)dynamic_space_free_pointer) & LOWTAG_MASK))
+
+#define get_alloc_pointer() \
+ ((unsigned long) dynamic_space_free_pointer & ~LOWTAG_MASK)
+#define get_binding_stack_pointer(thread) \
+ (current_binding_stack_pointer)
+#define get_pseudo_atomic_atomic(thread) \
+ ((unsigned long)dynamic_space_free_pointer & flag_PseudoAtomic)
+#define set_pseudo_atomic_atomic(thread) \
+ (dynamic_space_free_pointer \
+ = (lispobj*) ((unsigned long)dynamic_space_free_pointer | flag_PseudoAtomic))
+#define clear_pseudo_atomic_atomic(thread) \
+ (dynamic_space_free_pointer \
+ = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomic))
+#define get_pseudo_atomic_interrupted(thread) \
+ ((unsigned long) dynamic_space_free_pointer & flag_PseudoAtomicInterrupted)
+#define clear_pseudo_atomic_interrupted(thread) \
+ (dynamic_space_free_pointer \
+ = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomicInterrupted))
+#define set_pseudo_atomic_interrupted(thread) \
+ (dynamic_space_free_pointer \
+ = (lispobj*) ((unsigned long) dynamic_space_free_pointer | flag_PseudoAtomicInterrupted))
+
+#endif
+
+#endif /* PSEUDO_ATOMIC_H */
+
STATIC_TLS_INIT(CONTROL_STACK_END,control_stack_end);
STATIC_TLS_INIT(ALIEN_STACK,alien_stack_pointer);
#if defined(LISP_FEATURE_X86) || defined (LISP_FEATURE_X86_64)
- STATIC_TLS_INIT(PSEUDO_ATOMIC_ATOMIC,pseudo_atomic_atomic);
- STATIC_TLS_INIT(PSEUDO_ATOMIC_INTERRUPTED,pseudo_atomic_interrupted);
+ STATIC_TLS_INIT(PSEUDO_ATOMIC_BITS,pseudo_atomic_bits);
#endif
#undef STATIC_TLS_INIT
}
th->alien_stack_pointer=((void *)th->alien_stack_start);
#endif
#if defined(LISP_FEATURE_X86) || defined (LISP_FEATURE_X86_64)
- th->pseudo_atomic_interrupted=0;
- th->pseudo_atomic_atomic=0;
+ th->pseudo_atomic_bits=0;
#endif
#ifdef LISP_FEATURE_GENCGC
gc_set_region_empty(&th->alloc_region);
#if defined(LISP_FEATURE_X86) || defined (LISP_FEATURE_X86_64)
SetSymbolValue(BINDING_STACK_POINTER,(lispobj)th->binding_stack_pointer,th);
SetSymbolValue(ALIEN_STACK,(lispobj)th->alien_stack_pointer,th);
- SetSymbolValue(PSEUDO_ATOMIC_ATOMIC,(lispobj)th->pseudo_atomic_atomic,th);
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED,th->pseudo_atomic_interrupted,th);
+ SetSymbolValue(PSEUDO_ATOMIC_BITS,(lispobj)th->pseudo_atomic_bits,th);
#else
current_binding_stack_pointer=th->binding_stack_pointer;
current_control_stack_pointer=th->control_stack_start;
boolean
arch_pseudo_atomic_atomic(os_context_t *context)
{
- return SymbolValue(PSEUDO_ATOMIC_ATOMIC,arch_os_get_current_thread());
+ return get_pseudo_atomic_atomic(arch_os_get_current_thread());
}
void
arch_set_pseudo_atomic_interrupted(os_context_t *context)
{
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1),
- arch_os_get_current_thread());
+ struct thread *thread = arch_os_get_current_thread();
+ set_pseudo_atomic_interrupted(thread);
}
void
arch_clear_pseudo_atomic_interrupted(os_context_t *context)
{
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(0),
- arch_os_get_current_thread());
+ struct thread *thread = arch_os_get_current_thread();
+ clear_pseudo_atomic_interrupted(thread);
}
\f
/*
boolean
arch_pseudo_atomic_atomic(os_context_t *context)
{
- return SymbolValue(PSEUDO_ATOMIC_ATOMIC,arch_os_get_current_thread());
+ return get_pseudo_atomic_atomic(arch_os_get_current_thread());
}
void
arch_set_pseudo_atomic_interrupted(os_context_t *context)
{
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1),
- arch_os_get_current_thread());
+ struct thread *thread = arch_os_get_current_thread();
+ set_pseudo_atomic_interrupted(thread);
}
void
arch_clear_pseudo_atomic_interrupted(os_context_t *context)
{
- SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(0),
- arch_os_get_current_thread());
+ struct thread *thread = arch_os_get_current_thread();
+ clear_pseudo_atomic_interrupted(thread);
}
\f
/*
(lambda ()
(princ ".") (force-output)
(assert (thread-alive-p *current-thread*))
- (assert (zerop SB-KERNEL:*PSEUDO-ATOMIC-ATOMIC*)))))
+ (assert
+ (not (logbitp 0 SB-KERNEL:*PSEUDO-ATOMIC-BITS*))))))
(terminate-thread c)
(wait-for-threads (list c)))
;;; 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".)
-"0.9.16.27"
+"0.9.16.28"