--- /dev/null
+
+Things in SBCL that look like special variables (list created by
+(apropos "*")) and could conceivably indicate potental thread safety
+issues. Organised by functional area.
+
+The goals are
+
+ (1) classify the unclassified symbols (in such a way as to
+ make sense for 2)
+
+ (2) read through the subsystems identified looking for places
+ where global state is mutated. Use this list of symbols as a
+ guide, but be open to the possibility that other state
+ (e.g. closures, foreign variables) is touched too.
+
+ When looking at a particular symbol, please annotate it in
+ this file when you figure out what it's for and how it's
+ changed. To give us some confidence that we have reasonable
+ coverage, please don't just delete it if it looks ok. Symbols
+ shoud only be deleted here if they're obviously not specials
+ at all (e.g. functions with * in their names), or if the same
+ commit actually rids SBCL of the symbol itself (as we may soon
+ do for e.g. SB-SYS:*TASK-SELF*). Otherwise, just add a
+ comment saying "read-only" or "unused" or whatever.
+
+ (3) anything else that comes to mind as potential trouble
+ spots. Global state in closures, etc etc
+
+ (4) suggest strategies (e.g. rewrites of affected code, suitable
+ locks and lock acquitision/release places) to fix the issues
+ revealed in (2) and (3)
+
+ (5) implement same
+
+ Candidates may attempt any of the above simultaneously.
+ Points will be awarded for style
+
+
+Summary so far:
+
+= loop
+= PCL (probably ok if PCL authors did *without-interrupts* right)
+= debugger
+= profiler
+= disassembler
+= assembler (I assume protected by *big-compiler-lock*)
+= unix interface (apparently ok)
+= toplevel/environment stuff
+= the formatter & pretty printer (two vars need checking)
+= compiler (protected by *big-compiler-lock*)
+= fasloader (protected by *big-compiler-lock*)
+= runtime stuff - gc, control stacks, interrupts etc
+= backend constants
+= dead
+= unclassified
+
+==================
+
+= loop
+
+I suspect that stuff in sb-loop is only ever frobbed at
+macroexpand/compile time anyway, so covered by *big-compiler-lock*.
+Haven't thought about this too hard, though
+
+SB-LOOP::*LOOP-PROLOGUE*
+SB-LOOP::*LOOP-SOURCE-CODE*
+SB-LOOP::*LOOP-MINIMAX-TYPE-INFINITIES-ALIST*
+SB-LOOP::*LOOP-NAMES*
+SB-LOOP::*LOOP-BODY*
+SB-LOOP::*LOOP-AFTER-BODY*
+SB-LOOP::*LOOP-DESETQ-CROCKS*
+SB-LOOP::*LOOP-EPILOGUE*
+SB-LOOP::*LOOP-EMITTED-BODY*
+SB-LOOP::*LOOP-NEVER-STEPPED-VAR*
+SB-LOOP::*LOOP-NAMED-VARS*
+SB-LOOP::*LOOP-ITERATION-VARS*
+SB-LOOP::*LOOP-WHEN-IT-VAR*
+SB-LOOP::*LOOP-BEFORE-LOOP*
+SB-LOOP::*ESTIMATE-CODE-SIZE-PUNT*
+SB-LOOP::*LOOP-WRAPPERS*
+SB-LOOP::*LOOP-DESETQ-TEMPORARY*
+SB-LOOP::*LOOP-MACRO-ENVIRONMENT*
+SB-LOOP::*LOOP-VARS*
+SB-LOOP::*IGNORES*
+SB-LOOP::*LOOP-SOURCE-CONTEXT*
+SB-LOOP::*LOOP-AFTER-EPILOGUE*
+SB-LOOP::*LOOP-DECLARATIONS*
+SB-LOOP::*LOOP-FINAL-VALUE-CULPRIT*
+SB-LOOP::*LOOP-COLLECTION-CRUFT*
+SB-LOOP::*SPECIAL-CODE-SIZES*
+SB-LOOP::*LOOP-UNIVERSE*
+SB-LOOP::*LOOP-DUPLICATE-CODE*
+SB-LOOP::*LOOP-INSIDE-CONDITIONAL*
+SB-LOOP::*LOOP-ORIGINAL-SOURCE-CODE*
+SB-LOOP::*LOOP-ITERATION-FLAG-VAR*
+SB-LOOP::*LOOP-ANSI-UNIVERSE*
+SB-LOOP::*LOOP-BIND-STACK*
+
+= PCL
+
+The PCL authors thought a bit about thread safety, adding
+(without-interrupts ...) in some places to protect critical forms.
+We've implemented their without-interrupts macro as an acquitision of
+*pcl-lock*, so we hope they've done it properly.
+
+SB-PCL::*STRUCTURE-TYPEP-COST*
+SB-PCL::*SLOT-NAME-LISTS-OUTER*
+SB-PCL::*THE-WRAPPER-OF-T*
+SB-PCL::*CREATE-CLASSES-FROM-INTERNAL-STRUCTURE-DEFINITIONS-P*
+SB-PCL::*WRITERS-FOR-THIS-DEFCLASS*
+SB-PCL::*BOOT-STATE*
+SB-PCL::*THE-WRAPPER-OF-BIT-VECTOR*
+SB-PCL::*EFFECTIVE-METHOD-TABLE*
+SB-PCL::*THE-WRAPPER-OF-COMPLEX-DOUBLE-FLOAT*
+SB-PCL::*THE-CLASS-COMPLEX-DOUBLE-FLOAT*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-SINGLE-FLOAT*
+SB-PCL::*CACHE-LOOKUP-COST*
+SB-PCL::*SLOT-NAME-LISTS-INNER*
+SB-PCL::*MF2P*
+SB-PCL::*THE-CLASS-RATIONAL*
+SB-PCL::WRAPPER-CLASS*
+SB-PCL::*PREVIOUS-NWRAPPERS*
+SB-PCL::*MF1*
+SB-PCL::*THE-CLASS-STANDARD-OBJECT*
+SB-PCL::*THE-CLASS-CONDITION-DIRECT-SLOT-DEFINITION*
+SB-PCL::*THE-CLASS-RATIO*
+SB-PCL::*SHOW-MAKE-UNORDERED-METHODS-EMF-CALLS*
+SB-PCL::*ALL-CTORS*
+SB-PCL::*SUBTYPEP
+SB-PCL::*THE-WRAPPER-OF-LRA*
+SB-PCL::*INITFUNCTIONS-FOR-THIS-DEFCLASS*
+SB-PCL::*STANDARD-SLOT-VALUE-USING-CLASS-METHOD*
+SB-PCL::*EMPTY-PV*
+SB-PCL::*CACHE-EXPAND-THRESHOLD*
+SB-PCL::*THE-CLASS-INTEGER*
+SB-PCL::*SGF-DFUN-STATE-INDEX*
+SB-PCL::*ALL-PV-TABLE-LIST*
+SB-PCL::*THE-WRAPPER-OF-RANDOM-CLASS*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-COMPLEX-SINGLE-FLOAT*
+SB-PCL::*THE-CLASS-FDEFN*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-UNSIGNED-BYTE-32*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-VECTOR*
+SB-PCL::*CHECK-CACHE-P*
+SB-PCL::*SGF-WRAPPER*
+SB-PCL::*CONDITION-SLOT-VALUE-USING-CLASS-METHOD*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-BIT-VECTOR*
+SB-PCL::*THE-CLASS-SPECIALIZER*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-COMPLEX-DOUBLE-FLOAT*
+SB-PCL::*THE-CLASS-STANDARD-CLASS*
+SB-PCL::*THE-CLASS-STANDARD-ACCESSOR-METHOD*
+SB-PCL::*THE-CLASS-STANDARD-READER-METHOD*
+SB-PCL::*THE-WRAPPER-OF-DOUBLE-FLOAT*
+SB-PCL::*NON-BUILT-IN-TYPEP-COST*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-UNSIGNED-BYTE-8*
+SB-PCL::*THE-CLASS-DOCUMENTATION-MIXIN*
+SB-PCL::*EMF-CALL-TRACE-SIZE*
+SB-PCL::*OLD-C-A-M-GF-METHODS*
+SB-PCL::*EMPTY-CACHE*
+SB-PCL::*THE-WRAPPER-OF-SYMBOL*
+SB-PCL::*THE-CLASS-STANDARD-METHOD-COMBINATION*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-DOUBLE-FLOAT*
+SB-PCL::*THE-CLASS-METHOD*
+SB-PCL::*PRECOMPILING-LAP*
+SB-PCL::*STRUCTURE-SLOT-BOUNDP-USING-CLASS-METHOD*
+SB-PCL::*ENABLE-DFUN-CONSTRUCTOR-CACHING*
+SB-PCL::*THE-CLASS-CONDITION-EFFECTIVE-SLOT-DEFINITION*
+SB-PCL::*THE-WRAPPER-OF-STRUCTURE-OBJECT*
+SB-PCL::*THE-CLASS-WEAK-POINTER*
+SB-PCL::*STANDARD-SLOT-BOUNDP-USING-CLASS-METHOD*
+SB-PCL::*THE-CLASS-FUNCALLABLE-STANDARD-OBJECT*
+SB-PCL::*VAR-DECLARATIONS-WITH-ARG*
+SB-PCL::*PV-TABLE-CACHE-UPDATE-INFO*
+SB-PCL::*THE-WRAPPER-OF-STRING*
+SB-PCL::*THE-CLASS-CONDITION*
+SB-PCL::*THE-CLASS-PCL-CLASS*
+SB-PCL::*THE-CLASS-CLASS*
+SB-PCL::*PCL-LOCK* ; protecting the rest
+SB-PCL::*EARLY-P*
+SB-PCL::*PCL-CLASS-BOOT*
+SB-PCL::*THE-CLASS-EFFECTIVE-SLOT-DEFINITION*
+SB-PCL::*THE-WRAPPER-OF-CONS*
+SB-PCL::*THE-CLASS-LRA*
+SB-PCL::*THE-CLASS-EQL-SPECIALIZER*
+SB-PCL::*EQL-SPECIALIZER-METHODS*
+SB-PCL::*THE-WRAPPER-OF-FLOAT*
+SB-PCL::*INITIAL-PV-TABLE*
+SB-PCL::*THE-CLASS-COMPLEX-SINGLE-FLOAT*
+SB-PCL::*STRUCTURE-SLOT-VALUE-USING-CLASS-METHOD*
+SB-PCL::*EMF-CALL-TRACE*
+SB-PCL::*IN-OBSOLETE-INSTANCE-TRAP*
+SB-PCL::*BUILT-IN-CLASS-SYMBOLS*
+SB-PCL::*FREE-HASH-TABLES*
+SB-PCL::*THE-WRAPPER-OF-WEAK-POINTER*
+SB-PCL::*THE-CLASS-RANDOM-CLASS*
+SB-PCL::*PVS*
+SB-PCL::*THE-WRAPPER-OF-REAL*
+SB-PCL::*LONG-METHOD-COMBINATION-FUNCTIONS*
+SB-PCL::*EMIT-FUNCTION-P*
+SB-PCL::*THE-CLASS-DOUBLE-FLOAT*
+SB-PCL::*NAME->CLASS->SLOTD-TABLE*
+SB-PCL::*DFUN-COUNT*
+SB-PCL::*COMPUTE-STD-CPL-CLASS->ENTRY-TABLE-SIZE*
+SB-PCL::*THE-CLASS-SYMBOL*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-SIGNED-BYTE-16*
+SB-PCL::*THE-CLASS-STANDARD-DIRECT-SLOT-DEFINITION*
+SB-PCL::*THE-CLASS-EXACT-CLASS-SPECIALIZER*
+SB-PCL::*THE-CLASS-FLOAT*
+SB-PCL::*THE-CLASS-BASE-CHAR*
+SB-PCL::*PV-KEY-TO-PV-TABLE-TABLE*
+SB-PCL::*THE-CLASS-STD-CLASS*
+SB-PCL::*THE-CLASS-SLOT-OBJECT*
+SB-PCL::*OPTIMIZE-SPEED*
+SB-PCL::*THE-CLASS-STRUCTURE-EFFECTIVE-SLOT-DEFINITION*
+SB-PCL::*VAR-DECLARATIONS-WITHOUT-ARG*
+SB-PCL::*THE-CLASS-INSTANCE*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-UNSIGNED-BYTE-4*
+SB-PCL::*THE-CLASS-CONS*
+SB-PCL::*THE-WRAPPER-OF-FIXNUM*
+SB-PCL::*THE-SYSTEM-II-METHOD*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-SIGNED-BYTE-8*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-UNSIGNED-BYTE-16*
+SB-PCL::*THE-WRAPPER-OF-COMPLEX-SINGLE-FLOAT*
+SB-PCL::*THE-WRAPPER-OF-SINGLE-FLOAT*
+SB-PCL::*DFUN-MISS-GFS-ON-STACK*
+SB-PCL::*THE-CLASS-CONDITION-CLASS*
+SB-PCL::*THE-WRAPPER-OF-BIGNUM*
+SB-PCL::*THE-CLASS-SPECIALIZER-WITH-OBJECT*
+SB-PCL::*THE-CLASS-COMPLEX*
+SB-PCL::*THE-WRAPPER-OF-INTEGER*
+SB-PCL::*CONDITION-SLOT-BOUNDP-USING-CLASS-METHOD*
+SB-PCL::*THE-CLASS-CHARACTER*
+SB-PCL::*EARLY-CLASS-DEFINITIONS*
+SB-PCL::*THE-WRAPPER-OF-NULL*
+SB-PCL::*INTERNAL-PCL-GENERALIZED-FUN-NAME-SYMBOLS*
+SB-PCL::*THE-CLASS-STRUCTURE-CLASS*
+SB-PCL::*UNSPECIFIC-ARG*
+SB-PCL::*SECONDARY-DFUN-CALL-COST*
+SB-PCL::*THE-CLASS-SIMPLE-STRING*
+SB-PCL::*THE-CLASS-STRUCTURE-SLOT-DEFINITION*
+SB-PCL::*METHOD-FUNCTION-PLIST*
+SB-PCL::*STANDARD-METHOD-COMBINATION*
+SB-PCL::*LAZY-DFUN-COMPUTE-P*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-SIGNED-BYTE-8*
+SB-PCL::*THE-CLASS-STRING*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-UNSIGNED-BYTE-2*
+SB-PCL::*EQL-SPECIALIZER-TABLE*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-COMPLEX-DOUBLE-FLOAT*
+SB-PCL::*BUILT-IN-WRAPPER-SYMBOLS*
+SB-PCL::*THE-CLASS-STREAM*
+SB-PCL::*CLASS-EQ-SPECIALIZER-METHODS*
+SB-PCL::*THE-CLASS-REAL*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-UNSIGNED-BYTE-32*
+SB-PCL::*THE-CLASS-SIMPLE-VECTOR*
+SB-PCL::*THE-CLASS-GENERIC-FUNCTION*
+SB-PCL::*STANDARD-SETF-SLOT-VALUE-USING-CLASS-METHOD*
+SB-PCL::*STD-CAM-METHODS*
+SB-PCL::*THE-CLASS-STRUCTURE-DIRECT-SLOT-DEFINITION*
+SB-PCL::*THE-WRAPPER-OF-FDEFN*
+SB-PCL::*THE-WRAPPER-OF-VECTOR*
+SB-PCL::*THE-CLASS-NULL*
+SB-PCL::*NORMALIZE-TYPE
+SB-PCL::*REBOUND-EFFECTIVE-METHOD-GENSYMS*
+SB-PCL::*THE-CLASS-NUMBER*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-STRING*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-SIGNED-BYTE-30*
+SB-PCL::*MF2CP*
+SB-PCL::*THE-CLASS-DEPENDENT-UPDATE-MIXIN*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-SIGNED-BYTE-32*
+SB-PCL::*THE-CLASS-VECTOR*
+SB-PCL::*FIND-CLASS*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-SIGNED-BYTE-16*
+SB-PCL::*STANDARD-SLOT-LOCATIONS*
+SB-PCL::*FGENS*
+SB-PCL::*PCL-PACKAGE*
+SB-PCL::*THE-CLASS-ARRAY*
+SB-PCL::*CASE-TABLE-LIMIT*
+SB-PCL::*THE-CLASS-METHOD-COMBINATION*
+SB-PCL::*THE-CLASS-DIRECT-SLOT-DEFINITION*
+SB-PCL::*THE-CLASS-FIXNUM*
+SB-PCL::*THE-CLASS-STD-OBJECT*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-SIGNED-BYTE-32*
+SB-PCL::*EARLY-CLASS-PREDICATES*
+SB-PCL::*WRAPPER-OF-COST*
+SB-PCL::*STANDARD-CLASSES*
+SB-PCL::*THE-CLASS-LONG-METHOD-COMBINATION*
+SB-PCL::*READERS-FOR-THIS-DEFCLASS*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-SIGNED-BYTE-30*
+SB-PCL::*EMF-CALL-TRACE-INDEX*
+SB-PCL::*BUILT-IN-TYPEP-COST*
+SB-PCL::*THE-CLASS-STANDARD-SLOT-DEFINITION*
+SB-PCL::*THE-CLASS-PLIST-MIXIN*
+SB-PCL::*CONDITION-SETF-SLOT-VALUE-USING-CLASS-METHOD*
+SB-PCL::*THE-CLASS-BIGNUM*
+SB-PCL::*THE-WRAPPER-OF-CODE-COMPONENT*
+SB-PCL::*THE-ESLOTD-STANDARD-CLASS-SLOTS*
+SB-PCL::*SLOT-NAMES-FOR-THIS-DEFCLASS*
+SB-PCL::*THE-CLASS-FUNCTION*
+SB-PCL::*THE-WRAPPER-OF-SYSTEM-AREA-POINTER*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY*
+SB-PCL::*THE-CLASS-STANDARD-EFFECTIVE-SLOT-DEFINITION*
+SB-PCL::*THE-WRAPPER-OF-SEQUENCE*
+SB-PCL::*THE-CLASS-FUNCALLABLE-STANDARD-CLASS*
+SB-PCL::*THE-CLASS-SYSTEM-AREA-POINTER*
+SB-PCL::*THE-WRAPPER-OF-LIST*
+SB-PCL::*THE-CLASS-BUILT-IN-CLASS*
+SB-PCL::*STRUCTURE-SETF-SLOT-VALUE-USING-CLASS-METHOD*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-UNSIGNED-BYTE-4*
+SB-PCL::*THE-CLASS-SIMPLE-BIT-VECTOR*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-COMPLEX-SINGLE-FLOAT*
+SB-PCL::*GLOBAL-EFFECTIVE-METHOD-GENSYMS*
+SB-PCL::*DFUN-CONSTRUCTORS*
+SB-PCL::*THE-CLASS-CODE-COMPONENT*
+SB-PCL::*THE-CLASS-STANDARD-WRITER-METHOD*
+SB-PCL::*NON-VAR-DECLARATIONS*
+SB-PCL::*IN-PRECOMPUTE-EFFECTIVE-METHODS-P*
+SB-PCL::*CHECKING-OR-CACHING-LIST*
+SB-PCL::*THE-CLASS-BIT-VECTOR*
+SB-PCL::*THE-WRAPPER-OF-CHARACTER*
+SB-PCL::*THE-WRAPPER-OF-COMPLEX*
+SB-PCL::*BUILT-IN-CLASSES*
+SB-PCL::*ALLOW-EXPERIMENTAL-SPECIALIZERS-P*
+SB-PCL::*ALLOW-EMF-CALL-TRACING-P*
+SB-PCL::*SGF-METHOD-CLASS-INDEX*
+SB-PCL::*SGF-METHODS-INDEX*
+SB-PCL::*THE-WRAPPER-OF-NUMBER*
+SB-PCL::*THE-WRAPPER-OF-RATIO*
+SB-PCL::*RAISE-METATYPES-TO-CLASS-P*
+SB-PCL::*EARLY-CLASS-SLOTS*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY*
+SB-PCL::*MF1CP*
+SB-PCL::*THE-WRAPPER-OF-RATIONAL*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-UNSIGNED-BYTE-16*
+SB-PCL::*THE-WRAPPER-OF-ARRAY*
+SB-PCL::*THE-ESLOTD-FUNCALLABLE-STANDARD-CLASS-SLOTS*
+SB-PCL::*THE-CLASS-SLOT-CLASS*
+SB-PCL::*THE-CLASS-SLOT-DEFINITION*
+SB-PCL::*OPTIMIZE-CACHE-FUNCTIONS-P*
+SB-PCL::*MF2*
+SB-PCL::*THE-CLASS-SEQUENCE*
+SB-PCL::*EQ-CASE-TABLE-LIMIT*
+SB-PCL::*THE-CLASS-STRUCTURE-OBJECT*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-DOUBLE-FLOAT*
+SB-PCL::*SLOT-VECTOR-SYMBOLS*
+SB-PCL::*ENABLE-EMF-CALL-TRACING-P*
+SB-PCL::*THE-CLASS-SINGLE-FLOAT*
+SB-PCL::*THE-SYSTEM-SI-METHOD*
+SB-PCL::*THE-WRAPPER-OF-BASE-CHAR*
+SB-PCL::*THE-CLASS-CONDITION-SLOT-DEFINITION*
+SB-PCL::*DFUN-LIST*
+SB-PCL::*THE-CLASS-STANDARD-METHOD*
+SB-PCL::*DFUN-ARG-SYMBOLS*
+SB-PCL::*NOT-IN-CACHE*
+SB-PCL::*THE-CLASS-STANDARD-BOUNDP-METHOD*
+SB-PCL::*THE-CLASS-LIST*
+SB-PCL::*NEW-CLASS*
+SB-PCL::*THE-WRAPPER-OF-SIMPLE-ARRAY-UNSIGNED-BYTE-8*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-UNSIGNED-BYTE-2*
+SB-PCL::*THE-CLASS-CLASS-EQ-SPECIALIZER*
+SB-PCL::*THE-CLASS-FUNCALLABLE-INSTANCE*
+SB-PCL::*IN-GF-ARG-INFO-P*
+SB-PCL::*THE-CLASS-STANDARD-GENERIC-FUNCTION*
+SB-PCL::*SGF-ARG-INFO-INDEX*
+SB-PCL::*ALLOW-FORWARD-REFERENCED-CLASSES-IN-CPL-P*
+SB-PCL::*THE-CLASS-FORWARD-REFERENCED-CLASS*
+SB-PCL::*THE-CLASS-SIMPLE-ARRAY-SINGLE-FLOAT*
+SB-PCL::*MF1P*
+SB-PCL::*MINIMUM-CACHE-SIZE-TO-LIST*
+SB-PCL::*THE-CLASS-CLASS-PROTOTYPE-SPECIALIZER*
+SB-PCL::*THE-CLASS-T*
+SB-PCL::*CACHE-MISS-VALUES-STACK*
+SB-PCL::*SGF-NAME-INDEX*
+SB-PCL::*THE-CLASS-DEFINITION-SOURCE-MIXIN*
+SB-PCL::*SGF-SLOTS-INIT*
+
+
+= debugger
+
+*DEBUG-PRINT-LENGTH*
+*TRACE-FRAME*
+*TRACE-ENCAPSULATE-DEFAULT*
+*MAX-TRACE-INDENTATION*
+*IN-THE-DEBUGGER*
+*DEBUG-BEGINNER-HELP-P*
+*STACK-TOP-HINT*
+*DEBUG-HELP-STRING*
+*ONLY-BLOCK-START-LOCATIONS*
+*FLUSH-DEBUG-ERRORS*
+*DEBUG-CONDITION*
+*TRACE-VALUES*
+*PRINT-LOCATION-KIND*
+*DEBUG-PRINT-LEVEL*
+*TRACED-FUN-LIST*
+*TRACE-INDENTATION-STEP*
+*DEBUG-READTABLE*
+SB-DEBUG::*CACHED-DEBUG-SOURCE*
+SB-DEBUG::*POSSIBLE-BREAKPOINTS*
+SB-DEBUG::*BAD-CODE-LOCATION-TYPES*
+SB-DEBUG::*TRACED-ENTRIES*
+SB-DEBUG::*DEBUG-COMMAND-LEVEL*
+SB-DEBUG::*CACHED-SOURCE-STREAM*
+SB-DEBUG::*DEBUG-LOOP-FUN*
+SB-DEBUG::*NESTED-DEBUG-CONDITION*
+SB-DEBUG::*STEP-BREAKPOINTS*
+SB-DEBUG::*DEBUG-RESTARTS*
+SB-DEBUG::*CACHED-FORM-NUMBER-TRANSLATIONS*
+SB-DEBUG::*BREAKPOINTS*
+SB-DEBUG::*TRACED-FUNS*
+SB-DEBUG::*DEBUG-COMMANDS*
+SB-DEBUG::*DEFAULT-BREAKPOINT-DEBUG-FUN*
+SB-DEBUG::*CACHED-READTABLE*
+SB-DEBUG::*IN-TRACE*
+SB-DEBUG::*CACHED-TOPLEVEL-FORM-OFFSET*
+SB-DEBUG::*STACK-TOP*
+SB-DEBUG::*CURRENT-FRAME*
+SB-DEBUG::*CACHED-TOPLEVEL-FORM*
+SB-DEBUG::*NUMBER-OF-STEPS*
+SB-DEBUG::*REAL-STACK-TOP*
+SB-DI::*PARSING-BUFFER*
+SB-DI::*IR1-BLOCK-DEBUG-BLOCK*
+SB-DI::*OTHER-PARSING-BUFFER*
+SB-DI::*COMPILED-DEBUG-FUNS*
+SB-DI::*FORM-NUMBER-TEMP*
+SB-DI::*COMPONENT-BREAKPOINT-OFFSETS*
+SB-DI::*FUN-END-COOKIES*
+SB-DI::*FORM-NUMBER-CIRCULARITY-TABLE*
+SB-DI::*EXECUTING-BREAKPOINT-HOOKS*
+SB-DI::*IR1-LAMBDA-DEBUG-FUN*
+
+= profiler
+
+SB-PROFILE::*PROFILED-FUN-NAME->INFO*
+SB-PROFILE::*ENCLOSED-CONSING*
+SB-PROFILE::*COMPUTING-PROFILING-DATA-FOR*
+SB-PROFILE::*ENCLOSED-PROFILES*
+SB-PROFILE::*TIMER-OVERHEAD-ITERATIONS*
+SB-PROFILE::*OVERHEAD*
+SB-PROFILE::*ENCLOSED-TICKS*
+
+= disassembler
+
+SB-DISASSEM:*DISASSEM-INST-ALIGNMENT-BYTES*
+SB-DISASSEM:*DISASSEM-NOTE-COLUMN*
+SB-DISASSEM:*DEFAULT-DSTATE-HOOKS*
+SB-DISASSEM:*DISASSEM-OPCODE-COLUMN-WIDTH*
+SB-DISASSEM:*DISASSEM-SCHEDULER-P*
+SB-DISASSEM:*DISASSEM-LOCATION-COLUMN-WIDTH*
+SB-DISASSEM::*FOREIGN-SYMBOLS-BY-ADDR*
+SB-DISASSEM::*ARG-FUN-PARAMS*
+SB-DISASSEM::*ADDRESS-OF-NIL-OBJECT*
+SB-DISASSEM::*DISASSEM-INSTS*
+SB-DISASSEM::*DISASSEM-FUN-CACHE*
+SB-DISASSEM::*DISASSEM-INST-FORMATS*
+SB-DISASSEM::*GROKKED-SYMBOL-SLOTS*
+SB-DISASSEM::*ARG-FORM-KINDS*
+SB-DISASSEM::*DISASSEM-INST-SPACE*
+SB-DISASSEM::*CURRENT-INSTRUCTION-FLAVOR*
+SB-DISASSEM::*DISASSEM-ARG-TYPES*
+SB-DISASSEM::*ASSEMBLER-ROUTINES-BY-ADDR*
+
+= assembler
+
+Currently protected by *big-compiler-lock*. Mostly uninvestigated
+
+SB-ASSEM:*ASSEM-MAX-LOCATIONS*
+SB-ASSEM:*ASSEM-INSTRUCTIONS*
+SB-ASSEM:*ASSEM-SCHEDULER-P*
+SB-ASSEM::*INSTRUCTION-ATTRIBUTE-TRANSLATIONS*
+SB-ASSEM::**CURRENT-VOP**
+SB-ASSEM::**CURRENT-SEGMENT**
+
+
+= unix interface
+
+Looks good to me
+
+SB-UNIX::*INTERRUPTS-ENABLED* ; ok, bound
+SB-UNIX::*UNIX-SIGNALS* ; ok, read-only
+SB-UNIX::*INTERRUPT-PENDING* ; ok, bound
+
+= toplevel/environment stuff
+
+Some of these should probably be bound on thread entry. I haven't
+checked them yet, except where indicated
+
+*DEBUG-IO*
+SB-SYS:*TTY*
+SB-SYS:*STDIN*
+SB-SYS:*STDOUT*
+SB-SYS:*STDERR*
+SB-SYS:*LONG-SITE-NAME* ; readonly
+SB-SYS:*SHORT-SITE-NAME* ; readonly
+SB-SYS::*SOFTWARE-VERSION* ; readonly
+SB-THREAD::*SESSION-LOCK* ; bound
+SB-THREAD::*BACKGROUND-THREADS-WAIT-FOR-DEBUGGER* ; intentionally global
+*** ; bound
+** ; bound
+* ; bound
+*PRINT-PRETTY*
+*LOAD-VERBOSE*
+*LOAD-TRUENAME*
+*READ-BASE*
+*BREAK-ON-SIGNALS*
+*PRINT-READABLY*
+*PRINT-CIRCLE*
+*FEATURES* ; write at own risk
+*PRINT-BASE*
+*PACKAGE*
+*PRINT-RADIX*
+*READ-SUPPRESS*
+*ERROR-OUTPUT*
+*DEFAULT-PATHNAME-DEFAULTS*
+*LOAD-PATHNAME*
+*STANDARD-OUTPUT*
+*PRINT-RIGHT-MARGIN*
+*READTABLE*
+*PRINT-CASE*
+*PRINT-MISER-WIDTH*
+*PRINT-PPRINT-DISPATCH*
+*PRINT-LENGTH*
+*TERMINAL-IO*
+*PRINT-GENSYM*
+*QUERY-IO*
+*STANDARD-INPUT*
+*LOAD-PRINT*
+*DEBUGGER-HOOK*
+*PRINT-LINES*
+*PRINT-ESCAPE*
+*PRINT-LEVEL*
+*ERROR-PRINT-LENGTH*
+*ERROR-PRINT-LINES*
+*READ-EVAL*
+*PRINT-ESCAPE*
+*TRACE-OUTPUT*
+SB-IMPL::*INSPECT-LENGTH*
+*ERROR-PRINT-LEVEL*
+SB-IMPL::*DRIBBLE-STREAM* ; what to do with dribble in threaded lisp?
+SB-IMPL::*HELP-FOR-INSPECT* ; read-only
+*PRINT-ARRAY*
+
+
+
+*POSIX-ARGV* ; read-only
+*READ-DEFAULT-FLOAT-FORMAT* ; probably "change at own risk"
+*MODULES* ; should be changed only by provide/require, needs locking
+*MODULE-PROVIDER-FUNCTIONS* ; probably "change at own risk"
+SB-IMPL::*REPL-FUN*
+SB-INT:*REPL-READ-FORM-FUN*
+SB-INT:*REPL-PROMPT-FUN*
+
+= the formatter & pretty printer
+
+== probably safe (readonly unless indicated)
+
+(defparameter *format-whitespace-chars*
+(defvar *format-directive-expanders*
+(defvar *format-directive-interpreters*
+(defvar *default-format-error-control-string* nil)
+(defvar *default-format-error-offset* nil)
+SB-FORMAT::*CARDINAL-ONES* ; readonly
+SB-FORMAT::*CARDINAL-TENS*
+SB-FORMAT::*CARDINAL-TEENS*
+SB-FORMAT::*ORDINAL-ONES*
+SB-FORMAT::*ORDINAL-TENS*
+SB-FORMAT::*CARDINAL-PERIODS*
+SB-FORMAT::*ILLEGAL-INSIDE-JUSTIFICATION*
+SB-FORMAT::*OUTSIDE-ARGS* ; safe, bound
+
+
+(defvar *up-up-and-out-allowed* nil) ; safe, bound
+(defvar *logical-block-popper* nil) ; bound
+(defvar *expander-next-arg-macro* 'expander-next-arg) ; bound
+(defvar *orig-args-available* nil) ; bound
+
+== needs checking
+
+;;; Used by the expander stuff. Initially starts as T, and gets set to NIL
+;;; if someone needs to do something strange with the arg list (like use
+;;; the rest, or something). Setf in late-format, haven't checked if it's
+;;; always in a bound context
+(defvar *only-simple-args*)
+
+;;; setf in late-format, haven't checked
+(defvar *simple-args*)
+
+== haven't looked at yet
+
+SB-PRETTY::*INITIAL-PPRINT-DISPATCH*
+SB-PRETTY::*BUILDING-INITIAL-TABLE*
+SB-PRETTY::*PRECOMPILED-PPRINT-DISPATCH-FUNS*
+
+
+= compiler
+
+Note that the compiler and fasloader are strongly believed not to be
+thread-safe, so there is currently a big lock (*big-compiler-lock*)
+around all calls to the compiler or fasloader
+
+*COMPILE-FILE-PATHNAME*
+*COMPILE-FILE-TRUENAME*
+*COMPILE-PRINT*
+*COMPILE-VERBOSE*
+*COMPILE-PROGRESS*
+SB-C:*BACKEND-INTERNAL-ERRORS*
+SB-C:*BACKEND-SPECIAL-ARG-TYPES*
+SB-C:*ASSEMBLY-OPTIMIZE*
+SB-C:*LEXENV*
+SB-C:*CODE-SEGMENT*
+SB-C:*COMPONENT-BEING-COMPILED*
+SB-C:*BACKEND-SB-NAMES*
+SB-C:*BACKEND-PAGE-SIZE*
+SB-C:*BACKEND-SC-NUMBERS*
+SB-C:*ELSEWHERE*
+SB-C:*BACKEND-T-PRIMITIVE-TYPE*
+SB-C:*BACKEND-SB-LIST*
+SB-C:*SETF-ASSUMED-FBOUNDP*
+SB-C:*FREE-FUNS*
+SB-C:*BACKEND-DISASSEM-PARAMS*
+SB-C:*BACKEND-SUBFEATURES*
+SB-C:*COUNT-VOP-USAGES*
+SB-C:*SUPPRESS-VALUES-DECLARATION*
+SB-C:*BACKEND-SC-NAMES*
+SB-C::*CURRENT-COMPONENT*
+SB-C::*SLOT-INHERIT-ALIST*
+SB-C::*COMPILER-NOTE-COUNT*
+SB-C::*BACKEND-PREDICATE-TYPES*
+SB-C::*POLICY*
+SB-C::*INLINEP-TRANSLATIONS*
+SB-C::*PACK-OPTIMIZE-SAVES*
+SB-C::*DELETION-IGNORED-OBJECTS*
+SB-C::*LAST-FORMAT-ARGS*
+SB-C::*CONSTANTS-BEING-CREATED*
+SB-C::*IGNORED-ERRORS*
+SB-C::*COMPILE-OBJECT*
+SB-C::*TN-IDS*
+SB-C::*LOSSAGE-FUN*
+SB-C::*COMPILER-ERROR-COUNT*
+SB-C::*EVENT-NOTE-THRESHOLD*
+SB-C::*LAST-MESSAGE-COUNT*
+SB-C::*EMIT-ASSEMBLY-CODE-NOT-VOPS-P*
+SB-C::*LAST-FORMAT-STRING*
+SB-C::*UNWINNAGE-FUN*
+SB-C::*COMPILER-ERROR-CONTEXT*
+SB-C::*SEEN-BLOCKS*
+SB-C::*TN-ID*
+SB-C::*IR1-OPTIMIZE-UNTIL-DONE-EVENT-INFO*
+SB-C::*SPECIALIZED-ARRAY-ELEMENT-TYPE-PROPERTIES*
+SB-C::*NUMBER-CONTINUATIONS*
+SB-C::*CTYPE-TEST-FUN*
+SB-C::*IGNORE-COST-VOPS*
+SB-C::*QUEUED-PROCLAIMS*
+SB-C::*COMPILER-STYLE-WARNING-COUNT*
+SB-C::*LABEL-IDS*
+SB-C::TN-NEXT*
+SB-C::*BACKEND-SUPPORT-ROUTINES*
+SB-C::*COMPILED-CODE-LOCATION-KINDS*
+SB-C::*VOP-TN-REFS*
+SB-C::*INFO-CACHE-VECTOR*
+SB-C::*FAILURE-P*
+SB-C::*LAST-ORIGINAL-SOURCE*
+SB-C::NEXT*
+SB-C::LIST*-IR2-CONVERT-OPTIMIZER
+SB-C::*COMPILER-ERROR-BAILOUT*
+SB-C::*DELAYED-IR1-TRANSFORMS*
+SB-C::*INFO-TYPES*
+SB-C::*CACHED-INFO-ENVIRONMENT*
+SB-C::*CHECK-CONSISTENCY*
+SB-C::*SEEN-FUNS*
+SB-C::*USING-VOP-TN-REFS*
+SB-C::*MAKE-VALUE-CELL-EVENT-EVENT-INFO*
+SB-C::*IN-PACK*
+SB-C::*REPACK-BLOCK-EVENT-INFO*
+SB-C::*UNPACK-TN-EVENT-INFO*
+SB-C::*COALESCE-MORE-LTN-NUMBERS-EVENT-INFO*
+SB-C::*IN-COMPILATION-UNIT*
+SB-C::*BACKEND-TEMPLATE-NAMES*
+SB-C::*BACKEND-PRIMITIVE-TYPE-NAMES*
+SB-C::*CONSTRAINT-PROPAGATE*
+SB-C::*BACKEND-PRIMITIVE-TYPE-ALIASES*
+SB-C::*NO-COSTS*
+SB-C::*PACK-ASSIGN-COSTS*
+SB-C::*CURRENT-FORM-NUMBER*
+SB-C::*BACKEND-META-SC-NAMES*
+SB-C::*BLOCK-COMPILE-ARG*
+SB-C::*COMPILER-ERROR-PRINT-LENGTH*
+SB-C::*CONTINUATION-NUMBER*
+SB-C::*PREV-SEGMENT*
+SB-C::*ALL-COMPONENTS*
+SB-C::*CONTROL-DELETED-BLOCK-EVENT-INFO*
+SB-C::*ALLOW-DEBUG-CATCH-TAG*
+SB-C::*ID-LABELS*
+SB-C::*BACKEND-TYPE-PREDICATES*
+SB-C::*COMPILER-WARNING-COUNT*
+SB-C::*SUPPRESS-NOTE-VOPS*
+SB-C::*COMPILER-ERROR-PRINT-LEVEL*
+SB-C::*COMPLEMENT-TYPE-CHECKS*
+SB-C::*META-PRIMITIVE-TYPE-NAMES*
+SB-C::*FUN-NAMES-IN-THIS-FILE*
+SB-C::*SPLIT-IR2-BLOCK-EVENT-INFO*
+SB-C::*TRACE-TABLE*
+SB-C::*LAST-SOURCE-FORM*
+SB-C::*WEAKEN-TYPE-CACHE-VECTOR*
+SB-C::*-DERIVE-TYPE-AUX
+SB-C::*BLOCK-COMPILE*
+SB-C::*BIG-COMPILER-LOCK* ; protecting the rest
+SB-C::*VM-SUPPORT-ROUTINES*
+SB-C::*PRIMITIVE-TYPE-SLOT-ALIST*
+SB-C::*PREVIOUS-LOCATION*
+SB-C::*BYTE-BUFFER*
+SB-C::*CONSTANTS-CREATED-SINCE-LAST-INIT*
+SB-C::*LAST-SOURCE-CONTEXT*
+SB-C::*FIXUPS*
+SB-C::VOP*
+SB-C::*REOPTIMIZE-MAXED-OUT-EVENT-INFO*
+SB-C::*LIST-CONFLICTS-TABLE*
+SB-C::*LOSSAGE-DETECTED*
+SB-C::*LAST-ERROR-CONTEXT*
+SB-C::*PREV-VOP*
+SB-C::*POLICY-DEPENDENT-QUALITIES*
+SB-C::*REOPTIMIZE-AFTER-TYPE-CHECK-MAX*
+SB-C::*-DERIVE-TYPE-OPTIMIZER
+SB-C::*IR1-ATTRIBUTE-TRANSLATIONS*
+SB-C::*ARGS*
+SB-C::*DYNAMIC-COUNTS-TN*
+SB-C::*EXTREME-NTHCDR-OPEN-CODE-LIMIT*
+SB-C::*BACKEND-PARSED-VOPS*
+SB-C::*ABORTED-COMPILATION-UNIT-COUNT*
+SB-C::*COPY-DELETED-MOVE-EVENT-INFO*
+SB-C::*MAX-OPTIMIZE-ITERATIONS*
+SB-C::*TOPLEVEL-LAMBDAS*
+SB-C::*SC-VOP-SLOTS*
+SB-C::*IR1-OPTIMIZE-MAXED-OUT-EVENT-INFO*
+SB-C::*CONTINUATION-NUMBERS*
+SB-C::*WARNINGS-P*
+SB-C::*BACKEND-META-SC-NUMBERS*
+SB-C::*FLAME-ON-NECESSARILY-UNDEFINED-FUNCTION*
+SB-C::*UNPACK-FALLBACK-EVENT-INFO*
+SB-C::*SOURCE-INFO*
+SB-C::*LIVE-BLOCK*
+SB-C::*BACKEND-META-PRIMITIVE-TYPE-NAMES*
+SB-C::*NEXT-LOCATION*
+SB-C::*ELSEWHERE-LABEL*
+SB-C::*SOURCE-PATHS*
+SB-C::*CONSTANTS*
+SB-C::*BACKEND-META-SB-NAMES*
+SB-C::*DEFAULT-NTHCDR-OPEN-CODE-LIMIT*
+SB-C::*ALWAYS-OPTIMIZED-AWAY*
+SB-C::*CURRENT-PATH*
+SB-C::*LABEL-ID*
+SB-C::*ENTRY-POINTS*
+SB-C::*COMPILER-TRACE-OUTPUT*
+SB-C::*CONSTRAINT-NUMBER*
+SB-C::*INFO-CLASSES*
+SB-C::*RESULT-FIXUPS*
+SB-C::*REPACK-BLOCKS*
+SB-C::IR1-CONVERT-LET*
+SB-C::*CODE-VECTOR*
+SB-C::*FREE-VARS*
+SB-C::*SOURCE-CONTEXT-METHODS*
+SB-C::*VOP-ATTRIBUTE-TRANSLATIONS*
+SB-C::*COMPILER-ERROR-PRINT-LINES*
+SB-C::*LIVE-VOP*
+SB-C::*POLICY-QUALITIES*
+SB-C::*NO-LOADS*
+SB-C::*TRACE-TABLE-INFO*
+SB-C::*UNDEFINED-WARNINGS*
+SB-C::*BLOCK-ATTRIBUTE-TRANSLATIONS*
+SB-C::*EVENT-INFO*
+SB-C::*BURP-ACTION*
+SB-C::*UNWINNAGE-DETECTED*
+SB-C::*ID-TNS*
+
+= fasloader
+
+SB-FASL:*STATIC-FOREIGN-SYMBOLS*
+SB-FASL:*ASSEMBLER-ROUTINES*
+SB-FASL:*FASL-FILE-TYPE*
+SB-FASL::FOP-LIST*-4
+SB-FASL::*COLD-LOAD-DUMP*
+SB-FASL::FOP-LIST*-7
+SB-FASL::FOP-LIST*-8
+SB-FASL::FOP-LIST*-1
+SB-FASL::FOP-LIST*-2
+SB-FASL::*FASL-INPUT-STREAM*
+SB-FASL::*FOP-STACK*
+SB-FASL::*LOAD-DEPTH*
+SB-FASL::*FEATURES-AFFECTING-FASL-FORMAT*
+SB-FASL::*DUMP-ONLY-VALID-STRUCTURES*
+SB-FASL::*CURRENT-FOP-TABLE-SIZE*
+SB-FASL::*FOP-STACK-POINTER-ON-ENTRY*
+SB-FASL::*FREE-FOP-TABLES*
+SB-FASL::*LOAD-SYMBOL-BUFFER*
+SB-FASL::*CURRENT-CATCH-BLOCK*
+SB-FASL::*FASL-HEADER-STRING-START-STRING*
+SB-FASL::DUMP-FOP*
+SB-FASL::FOP-LIST*
+SB-FASL::*CIRCULARITIES-DETECTED*
+SB-FASL::*LOAD-CODE-VERBOSE*
+SB-FASL::*FEATURES-POTENTIALLY-AFFECTING-FASL-FORMAT*
+SB-FASL::*LOAD-SYMBOL-BUFFER-SIZE*
+SB-FASL::*CURRENT-FOP-TABLE*
+SB-FASL::*FOP-STACK-POINTER*
+SB-FASL::*CURRENT-FOP-TABLE-INDEX*
+SB-FASL::*FOP-FUNS*
+SB-FASL::*CURRENT-UNWIND-PROTECT-BLOCK*
+SB-FASL::FOP-LIST*-5
+SB-FASL::*FOP-NAMES*
+SB-FASL::FOP-LIST*-6
+SB-FASL::FOP-LIST*-3
+
+
+= runtime stuff
+SB-VM:*STATIC-SPACE-FREE-POINTER*
+SB-VM:*INITIAL-DYNAMIC-SPACE-FREE-POINTER*
+SB-VM:*CURRENT-CATCH-BLOCK*
+SB-VM:*STATIC-SYMBOLS*
+SB-VM:*CONTROL-STACK-START* ; bound at thread entry
+SB-VM:*READ-ONLY-SPACE-FREE-POINTER*
+SB-VM:*BINDING-STACK-START*
+SB-VM:*CONTROL-STACK-END*
+SB-VM::*CURRENT-UNWIND-PROTECT-BLOCK*
+SB-VM::*FREE-TLS-INDEX*
+SB-VM::*BINDING-STACK-POINTER*
+SB-VM::*ALLOCATION-POINTER* ; may be mostly unused ?
+SB-KERNEL:*PSEUDO-ATOMIC-ATOMIC* ; bound
+SB-KERNEL:*CONTROL-STACK-EXHAUSTION-SAP*
+SB-KERNEL:*FREE-INTERRUPT-CONTEXT-INDEX* ; bound
+SB-KERNEL:*GC-INHIBIT* ; do not touch directly. accessors may be broke too
+SB-KERNEL:*NEED-TO-COLLECT-GARBAGE*
+SB-KERNEL:*ALREADY-MAYBE-GCING*
+SB-KERNEL:*PSEUDO-ATOMIC-INTERRUPTED* ; bound
+SB-KERNEL::*GC-TRIGGER* ; I think this is dead, check
+SB-IMPL::*CURRENT-UNWIND-PROTECT-BLOCK*
+SB-IMPL::*CURRENT-CATCH-BLOCK*
+SB-IMPL::*READ-ONLY-SPACE-FREE-POINTER*
+SB-VM::*ALIEN-STACK*
+
+*GC-NOTIFY-STREAM* ; going away
+*BEFORE-GC-HOOKS* ; must be global
+*AFTER-GC-HOOKS* ; ditto
+*GC-NOTIFY-AFTER* ; going away
+*GC-NOTIFY-BEFORE* ; going away
+*GC-RUN-TIME*
+SB-INT:*N-BYTES-FREED-OR-PURIFIED*
+
+Note also the following may need attention
+SB-PROFILE::TOTAL-CONSED
+GET-BYTES-CONSED (fbound)
+BYTES-CONSED-BETWEEN-GCS (fbound)
+
+
+= backend constants
+
+These are believed to be constant (in the general sense, not necessarily
+eligible for defconstant). Mostly they're attributes of the backend machine
+
+
+SB-C:*BACKEND-REGISTER-SAVE-PENALTY*
+SB-C:*BACKEND-BYTE-ORDER*
+SB-C:*BACKEND-INSTRUCTION-FORMATS*
+SB-C:*BACKEND-INSTRUCTION-FLAVORS*
+SB-VM:*PRIMITIVE-OBJECTS*
+SB-VM:*ASSEMBLY-UNIT-LENGTH*
+SB-VM::*FP-CONSTANT-L2E*
+SB-VM::*FLOAT-REGISTER-NAMES*
+SB-VM::*FP-CONSTANT-1L0*
+SB-VM::*BYTE-REGISTER-NAMES*
+SB-VM::*DWORD-SC-NAMES*
+SB-VM::*FP-CONSTANT-1F0*
+SB-VM::*WORD-REGS*
+SB-VM::*BYTE-SC-NAMES*
+SB-VM::*DEFAULT-ADDRESS-SIZE*
+SB-VM::*FP-CONSTANT-0D0*
+SB-VM::*FP-CONSTANT-LG2*
+SB-VM::*FP-CONSTANT-L2T*
+SB-VM::*DWORD-REGS*
+SB-VM::*WORD-REGISTER-NAMES*
+SB-VM::*FP-CONSTANT-0F0*
+SB-VM::*FLOAT-SC-NAMES*
+SB-VM::*FLOAT-REGS*
+SB-VM::*DWORD-REGISTER-NAMES*
+SB-VM::*WORD-SC-NAMES*
+SB-VM::*FP-CONSTANT-PI*
+SB-VM::*BYTE-REGS*
+SB-VM::*FP-CONSTANT-1D0*
+SB-VM::*DOUBLE-SC-NAMES*
+SB-VM::*FP-CONSTANT-0L0*
+SB-VM::*REGISTER-ARG-OFFSETS*
+SB-VM::*FLOAT-TRAP-ALIST*
+SB-VM::*DWORD-REG-NAMES*
+SB-VM::*BYTE-REG-NAMES*
+SB-VM::*ROUNDING-MODE-ALIST*
+SB-VM::*REGISTER-ARG-NAMES*
+SB-VM::*FUN-HEADER-WIDETAGS*
+SB-VM::*FIXNUM-PRIMITIVE-TYPE*
+SB-VM:*STATIC-FUNS*
+SB-VM::*FP-CONSTANT-LN2*
+SB-VM::*WORD-REG-NAMES*
+SB-KERNEL::*BUILT-IN-CLASSES*
+
+= dead stuff
+
+SB-SYS:*TASK-NOTIFY* ; unused
+SB-SYS:*TASK-SELF* ; unused
+SB-SYS:*TASK-DATA* ; unused
+SB-SYS:*TYPESCRIPTPORT* ' unused
+SB-THREAD::*FOREGROUND-THREAD-STACK* ; unused, I think
+
+
+
+
+------------------------------------------------------------------------
+
+= unclassified
+
+SB-ALIEN-INTERNALS:*VALUES-TYPE-OKAY*
+SB-ALIEN::ALIEN-*-TYPE-TRANSLATOR
+SB-ALIEN::*DSO-LINKER*
+SB-ALIEN::*HANDLES-FROM-DLOPEN*
+SB-ALIEN::*ALIEN-TYPE-CLASSES*
+SB-ALIEN::*RECORD-TYPES-ALREADY-UNPARSED*
+SB-ALIEN::*NEW-AUXILIARY-TYPES*
+SB-ALIEN::*DSO-LINKER-OPTIONS*
+SB-ALIEN::*METHOD-SLOT-ALIST*
+
+SB-VM::*SIGNED-IMM-BYTE-PREFILTER-WRAPPER*
+SB-VM::*DISPLACEMENT-PRINTER-WRAPPER*
+SB-VM::*ACCUM-PRINTER-WRAPPER*
+SB-VM::*WIDTH-PRINTER-WRAPPER*
+SB-VM::*LABEL-1-PREFILTER-WRAPPER*
+SB-VM::*WORD-ACCUM-PRINTER-WRAPPER*
+SB-VM::*NUM-FIXUPS*
+SB-VM::*SIGNED-IMM-DATA-PREFILTER-WRAPPER*
+SB-VM::*FIXNUM-PRIMITIVE-TYPE*
+SB-VM::*CONDITIONS*
+SB-VM::*IGNORE-AFTER*
+SB-VM::*IMM-WORD-PREFILTER-WRAPPER*
+SB-VM::*REGISTER-ARG-TNS*
+SB-VM::*IMM-DATA-PREFILTER-WRAPPER*
+SB-VM::*PRIMITIVE-TYPE-AUX-CACHE-VECTOR*
+SB-VM::*LABEL-2-PREFILTER-WRAPPER*
+SB-VM::*ROOM-INFO*
+SB-VM::*ADJUSTABLE-VECTORS*
+SB-VM::*CONDITION-NAME-VEC*
+SB-VM::*IMM-WORD-16-PREFILTER-WRAPPER*
+SB-VM::*SIMPLE-ARRAY-PRIMITIVE-TYPES*
+SB-VM::*MAYBE-USE-INLINE-ALLOCATION*
+SB-VM::*SIGNED-IMM-DWORD-PREFILTER-WRAPPER*
+SB-VM::*IMMEDIATE-TYPES*
+
+SB-KERNEL:*WILD-TYPE*
+SB-KERNEL:*UNPARSE-FUN-TYPE-SIMPLIFY*
+SB-KERNEL:*CURRENT-LEVEL-IN-PRINT*
+SB-KERNEL:*UNIVERSAL-FUN-TYPE*
+SB-KERNEL:*COLD-INIT-COMPLETE-P*
+SB-KERNEL:*UNIVERSAL-TYPE*
+SB-KERNEL:*HANDLER-CLUSTERS*
+SB-KERNEL:*EMPTY-TYPE*
+SB-KERNEL:*MAXIMUM-ERROR-DEPTH*
+SB-KERNEL:*CONDITION-RESTARTS*
+SB-KERNEL:*TYPE-SYSTEM-INITIALIZED*
+SB-KERNEL:*RESTART-CLUSTERS*
+SB-KERNEL::*MAKE-VALUES-TYPE-CACHED-CACHE-VECTOR*
+SB-KERNEL::*BUILT-IN-CLASS-CODES*
+SB-KERNEL::*DEF!STRUCT-TYPE-MAKE-LOAD-FORM-FUN*
+SB-KERNEL::*LAYOUT-CLOS-HASH-RANDOM-STATE*
+SB-KERNEL::*TYPE-TEST-ORDERING*
+SB-KERNEL::*COMMON-TYPESPECS*
+SB-KERNEL::*TYPE=-CACHE-VECTOR*
+SB-KERNEL::*VALUES-SUBTYPEP-CACHE-VECTOR*
+SB-KERNEL::*TYPECHECKFUNS*
+SB-KERNEL::*%TYPE-INTERSECTION-CACHE-VECTOR*
+SB-KERNEL::*TYPE-INTERSECTION2-CACHE-VECTOR*
+SB-KERNEL::*COLD-INIT-FORMS*
+SB-KERNEL::*DEFAULT-DEFAULT*
+SB-KERNEL::*RAW-SLOT-DATA-LIST*
+SB-KERNEL::*SPECIALIZED-ARRAY-ELEMENT-TYPES*
+SB-KERNEL::*DEFSTRUCT-HOOKS*
+SB-KERNEL::*VALUES-TYPE-UNION-CACHE-VECTOR*
+SB-KERNEL::*INTERNAL-ERRORS*
+SB-KERNEL::*VALUES-TYPE-INTERSECTION-CACHE-VECTOR*
+SB-KERNEL::*FORWARD-REFERENCED-LAYOUTS*
+SB-KERNEL::*SYSTEM-LETS*
+SB-KERNEL::*%COERCE-TO-VALUES-CACHE-VECTOR*
+SB-KERNEL::*IGNORABLE-VARS*
+SB-KERNEL::*ENV-VAR*
+SB-KERNEL::|*%%MAKE-UNION-TYPE-cached-CACHE-VECTOR*|
+SB-KERNEL::*CSUBTYPEP-CACHE-VECTOR*
+SB-KERNEL::*EMPTY-CONDITION-SLOT*
+SB-KERNEL::*TYPE-UNION2-CACHE-VECTOR*
+SB-KERNEL::*TYPE-CLASS-FUN-SLOTS*
+SB-KERNEL::*ARG-TESTS*
+SB-KERNEL::*USER-LETS*
+SB-KERNEL::|*%%MAKE-ARRAY-TYPE-cached-CACHE-VECTOR*|
+SB-KERNEL::*FINDING-NAME*
+SB-KERNEL::*TYPE-CLASSES*
+SB-KERNEL::*VALUES-SPECIFIER-TYPE-CACHE-VECTOR*
+SB-KERNEL::*FLOAT-FORMATS*
+SB-KERNEL::*INTERNAL-ERROR-ARGS*
+SB-KERNEL::*DEF!STRUCT-SUPERTYPE*
+SB-KERNEL::*%TYPE-UNION-CACHE-VECTOR*
+SB-KERNEL::*CTYPE-OF-CACHE-VECTOR*
+
+SB-IMPL::*READ-BUFFER*
+SB-IMPL::*SECONDARY-ATTRIBUTE-TABLE*
+SB-IMPL::*STANDARD-READTABLE*
+SB-IMPL::*OUCH-PTR*
+SB-IMPL::*ERROR-ERROR-DEPTH*
+SB-IMPL::*CURRENT-ERROR-DEPTH*
+SB-IMPL::*INTERNAL-REAL-TIME-BASE-SECONDS*
+SB-IMPL::*DAYLIGHT-TABLE*
+SB-IMPL::*OFFENDING-DATUM*
+SB-IMPL::*HANDLERS-INSTALLED*
+SB-IMPL::*READ-FROM-STRING-SPARES*
+SB-IMPL::*HASH-TABLE-TESTS*
+SB-IMPL::*ATTRIBUTE-NAMES*
+SB-IMPL::*DAYS-BEFORE-MONTH*
+SB-IMPL::*CHARACTER-ATTRIBUTES*
+SB-IMPL::*UNIX-HOST*
+SB-IMPL::*DESCRIPTOR-HANDLERS*
+SB-IMPL::*STRING-OUTPUT-STREAMS*
+SB-IMPL::*CLOSE-ON-ERROR*
+SB-IMPL::*INTEGER-READER-SAFE-DIGITS*
+SB-IMPL::*TIMEZONE-TABLE*
+SB-IMPL::*BQ-COMMA-FLAG*
+SB-IMPL::*PRINT-OBJECT-IS-DISABLED-P*
+SB-IMPL::*MERGE-SORT-TEMP-VECTOR*
+SB-IMPL::*PROFILE-HASH-CACHE*
+SB-IMPL::*FIXNUM-POWER--1*
+SB-IMPL::*OBJECTS-PENDING-FINALIZATION*
+SB-IMPL::*SHARP-EQUAL-CIRCLE-TABLE*
+SB-IMPL::*SOFTWARE-INTERRUPT-VECTOR* ; suspect unused
+SB-IMPL::*INSPECT-UNBOUND-OBJECT-MARKER*
+SB-IMPL::*IN-PACKAGE-INIT*
+SB-IMPL::*DELAYED-DEF!METHOD-ARGS*
+SB-IMPL::*GENTEMP-COUNTER*
+SB-IMPL::*CLOSE-IN-PARENT*
+SB-IMPL::*IN-COMPILATION-UNIT*
+SB-IMPL::*CIRCULARITY-HASH-TABLE*
+SB-IMPL::*LOAD-PRINT-STUFF*
+SB-IMPL::*ZAP-ARRAY-DATA-TEMP*
+SB-IMPL::*ACTIVE-PROCESSES*
+SB-IMPL::*SHARP-SHARP-ALIST*
+SB-IMPL::*BASE-POWER*
+SB-IMPL::*LOGICAL-PATHNAME-DEFAULTS*
+SB-IMPL::*AVAILABLE-BUFFERS*
+SB-IMPL::*BQ-DOT-FLAG*
+SB-IMPL::*CIRCULARITY-COUNTER*
+SB-IMPL::*DIGITS*
+SB-IMPL::*PREVIOUS-READTABLE-CASE*
+SB-IMPL::*BQ-VECTOR-FLAG*
+SB-IMPL::*ABBREV-WEEKDAY-TABLE*
+SB-IMPL::*LOGICAL-HOSTS*
+SB-IMPL::*PACKAGE-NAMES*
+SB-IMPL::*INSPECT-FUN*
+SB-IMPL::*ABBREV-MONTH-TABLE*
+SB-IMPL::*OUTPUT-ROUTINES*
+SB-IMPL::*CHAR-NAME-ALIST*
+SB-IMPL::*VALID-FUN-NAMES-ALIST*
+SB-IMPL::*PERIODIC-POLLING-FUNCTION*
+SB-IMPL::*ABORTED-COMPILATION-UNIT-COUNT*
+SB-IMPL::*LONG-WEEKDAY-TABLE*
+SB-IMPL::*INTERNAL-SYMBOL-OUTPUT-FUN*
+SB-IMPL::*BACKQUOTE-COUNT*
+SB-IMPL::*DIGIT-BASES*
+SB-IMPL::*PREVIOUS-DRIBBLE-STREAMS*
+SB-IMPL::*MAX-EVENT-TO-USEC*
+SB-IMPL::*INPUT-ROUTINES*
+SB-IMPL::*MAX-EVENT-TO-SEC*
+SB-IMPL::*READ-BUFFER-LENGTH*
+SB-IMPL::*LONG-MONTH-TABLE*
+SB-IMPL::*OLD-PACKAGE*
+SB-IMPL::*INTEGER-READER-BASE-POWER*
+SB-IMPL::*ERROR-THROW-UP-COUNT*
+SB-IMPL::*BQ-AT-FLAG*
+SB-IMPL::*MACHINE-VERSION* ; unset/unbound ? are we using this?
+SB-IMPL::*IGNORE-WILDCARDS*
+SB-IMPL::*INCH-PTR*
+SB-IMPL::*SHARP-EQUAL-ALIST*
+SB-IMPL::*PREVIOUS-CASE*
+
+*INLINE-EXPANSION-LIMIT*
+*DERIVE-FUNCTION-TYPES*
+*ENCLOSING-SOURCE-CUTOFF*
+*INSPECTED*
+*UNDEFINED-WARNING-LIMIT*
+*EFFICIENCY-NOTE-COST-THRESHOLD*
+*EFFICIENCY-NOTE-LIMIT*
+*USE-IMPLEMENTATION-TYPES*
+*INTEXP-MAXIMUM-EXPONENT*
+*GENSYM-COUNTER*
+*MACROEXPAND-HOOK*
+*RANDOM-STATE*
+
+SB-BIGNUM::*TRUNCATE-Y*
+SB-BIGNUM::*TRUNCATE-X*
+
+SB-INT:*CL-PACKAGE*
+SB-INT:*KEYWORD-PACKAGE*
+SB-INT:*SETF-FDEFINITION-HOOK*
+SB-INT:*DEFAULT-INIT-CHAR-FORM*
+SB-INT:*EOF-OBJECT*
+SB-INT:*AFTER-SAVE-INITIALIZATIONS*
+SB-INT:*LOAD-SOURCE-DEFAULT-TYPE*
+SB-INT:*BEFORE-SAVE-INITIALIZATIONS*
+SB-INT:*INFO-ENVIRONMENT*
* files for more information.
*/
+
+/* As far as I can tell, what's going on here is:
+ *
+ * In the case of most signals, when Lisp asks us to handle the
+ * signal, the outermost handler (the one actually passed to UNIX) is
+ * either interrupt_handle_now(..) or maybe_now_maybe_later(..).
+ * In that case, the Lisp-level handler is stored in interrupt_handlers[..]
+ * and interrupt_low_level_handlers[..] is cleared.
+ *
+ * However, some signals need special handling, e.g.
+ *
+ * o the SIGSEGV (for e.g. Linux) or SIGBUS (for e.g. FreeBSD) used by the
+ * garbage collector to detect violations of write protection,
+ * because some cases of such signals (e.g. GC-related violations of
+ * write protection) are handled at C level and never passed on to
+ * Lisp. For such signals, we still store any Lisp-level handler
+ * in interrupt_handlers[..], but for the outermost handle we use
+ * the value from interrupt_low_level_handlers[..], instead of the
+ * ordinary interrupt_handle_now(..) or interrupt_handle_later(..).
+ *
+ * o the SIGTRAP (Linux/Alpha) which Lisp code uses to handle breakpoints,
+ * pseudo-atomic sections, and some classes of error (e.g. "function
+ * not defined"). This never goes anywhere near the Lisp handlers at all.
+ * See runtime/alpha-arch.c and code/signal.lisp
+ *
+ * - WHN 20000728, dan 20010128 */
+
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "genesis/fdefn.h"
#include "genesis/simple-fun.h"
+void run_deferred_handler(struct interrupt_data *data, void *v_context) ;
+static void store_signal_data_for_later (struct interrupt_data *data,
+ void *handler, int signal,
+ siginfo_t *info,
+ os_context_t *context);
+boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *v_context);
+
+extern lispobj all_threads_lock;
+extern int countdown_to_gc;
+
+/*
+ * This is a workaround for some slightly silly Linux/GNU Libc
+ * behaviour: glibc defines sigset_t to support 1024 signals, which is
+ * more than the kernel. This is usually not a problem, but becomes
+ * one when we want to save a signal mask from a ucontext, and restore
+ * it later into another ucontext: the ucontext is allocated on the
+ * stack by the kernel, so copying a libc-sized sigset_t into it will
+ * overflow and cause other data on the stack to be corrupted */
+
+#define REAL_SIGSET_SIZE_BYTES ((NSIG/8))
+
void sigaddset_blockable(sigset_t *s)
{
sigaddset(s, SIGHUP);
sigaddset(s, SIGWINCH);
sigaddset(s, SIGUSR1);
sigaddset(s, SIGUSR2);
+#ifdef LISP_FEATURE_SB_THREAD
+ /* don't block STOP_FOR_GC, we need to be able to interrupt threads
+ * for GC purposes even when they are blocked on queues etc */
+ sigaddset(s, SIG_INTERRUPT_THREAD);
+#endif
}
/* When we catch an internal error, should we pass it back to Lisp to
struct interrupt_data * global_interrupt_data;
-/* As far as I can tell, what's going on here is:
- *
- * In the case of most signals, when Lisp asks us to handle the
- * signal, the outermost handler (the one actually passed to UNIX) is
- * either interrupt_handle_now(..) or maybe_now_maybe_later(..).
- * In that case, the Lisp-level handler is stored in interrupt_handlers[..]
- * and interrupt_low_level_handlers[..] is cleared.
- *
- * However, some signals need special handling, e.g.
- *
- * o the SIGSEGV (for e.g. Linux) or SIGBUS (for e.g. FreeBSD) used by the
- * garbage collector to detect violations of write protection,
- * because some cases of such signals (e.g. GC-related violations of
- * write protection) are handled at C level and never passed on to
- * Lisp. For such signals, we still store any Lisp-level handler
- * in interrupt_handlers[..], but for the outermost handle we use
- * the value from interrupt_low_level_handlers[..], instead of the
- * ordinary interrupt_handle_now(..) or interrupt_handle_later(..).
- *
- * o the SIGTRAP (Linux/Alpha) which Lisp code uses to handle breakpoints,
- * pseudo-atomic sections, and some classes of error (e.g. "function
- * not defined"). This never goes anywhere near the Lisp handlers at all.
- * See runtime/alpha-arch.c and code/signal.lisp
- *
- * - WHN 20000728, dan 20010128 */
-
-
-boolean maybe_gc_pending = 0;
\f
/*
* utility routines used by various signal handlers
foreign_function_call_active = 1;
}
+/* blocks all blockable signals. If you are calling from a signal handler,
+ * the usual signal mask will be restored from the context when the handler
+ * finishes. Otherwise, be careful */
+
void
undo_fake_foreign_function_call(os_context_t *context)
{
/* going back into Lisp */
foreign_function_call_active = 0;
- /* Undo dynamic binding. */
- /* ### Do I really need to unbind_to_here()? */
- /* FIXME: Is this to undo the binding of
- * FREE_INTERRUPT_CONTEXT_INDEX? If so, we should say so. And
- * perhaps yes, unbind_to_here() really would be clearer and less
- * fragile.. */
- /* dan (2001.08.10) thinks the above supposition is probably correct */
+ /* Undo dynamic binding of FREE_INTERRUPT_CONTEXT_INDEX */
unbind(thread);
#ifdef reg_ALLOC
}
}
-/* This function handles pending interrupts. Note that in C/kernel
- * terms we dealt with the signal already; we just haven't decided
- * whether to call a Lisp handler or do a GC or something like that.
- * If it helps, you can think of pending_{signal,mask,info} as a
- * one-element queue of signals that we have acknowledged but not
- * processed */
-
void
interrupt_handle_pending(os_context_t *context)
{
struct thread *thread;
struct interrupt_data *data;
-#ifndef __i386__
- boolean were_in_lisp = !foreign_function_call_active;
-#endif
-#ifdef LISP_FEATURE_SB_THREAD
- while(stop_the_world) kill(getpid(),SIGSTOP);
-#endif
thread=arch_os_get_current_thread();
data=thread->interrupt_data;
SetSymbolValue(INTERRUPT_PENDING, NIL,thread);
- if (maybe_gc_pending) {
-#ifndef __i386__
- if (were_in_lisp)
-#endif
- {
- fake_foreign_function_call(context);
- }
- funcall0(SymbolFunction(SUB_GC));
-#ifndef __i386__
- if (were_in_lisp)
-#endif
- {
- undo_fake_foreign_function_call(context);
- }
- }
+ /* restore the saved signal mask from the original signal (the
+ * one that interrupted us during the critical section) into the
+ * os_context for the signal we're currently in the handler for.
+ * This should ensure that when we return from the handler the
+ * blocked signals are unblocked */
+
+ memcpy(os_context_sigmask_addr(context), &data->pending_mask,
+ REAL_SIGSET_SIZE_BYTES);
- /* FIXME: This isn't very clear. It would be good to reverse
- * engineer it and rewrite the code more clearly, or write a clear
- * explanation of what's going on in the comments, or both.
- *
- * WHN's question 1a: How come we unconditionally copy from
- * pending_mask into the context, and then test whether
- * pending_signal is set?
- *
- * WHN's question 1b: If pending_signal wasn't set, how could
- * pending_mask be valid?
- *
- * Dan Barlow's reply (sbcl-devel 2001-03-13): And the answer is -
- * or appears to be - because interrupt_maybe_gc set it that way
- * (look in the #ifndef __i386__ bit). We can't GC during a
- * pseudo-atomic, so we set maybe_gc_pending=1 and
- * arch_set_pseudo_atomic_interrupted(..) When we come out of
- * pseudo_atomic we're marked as interrupted, so we call
- * interrupt_handle_pending, which does the GC using the pending
- * context (it needs a context so that it has registers to use as
- * GC roots) then notices there's no actual interrupt handler to
- * call, so doesn't. That's the second question [1b] answered,
- * anyway. Why we still need to copy the pending_mask into the
- * context given that we're now done with the context anyway, I
- * couldn't say. */
-#if 0
- memcpy(os_context_sigmask_addr(context), &pending_mask,
- 4 /* sizeof(sigset_t) */ );
-#endif
sigemptyset(&data->pending_mask);
- if (data->pending_signal) {
- int signal = data->pending_signal;
- siginfo_t info;
- memcpy(&info, &data->pending_info, sizeof(siginfo_t));
- data->pending_signal = 0;
- interrupt_handle_now(signal, &info, context);
- }
+ /* This will break on sparc linux: the deferred handler really wants
+ * to be called with a void_context */
+ run_deferred_handler(data,(void *)context);
}
\f
/*
lose("no handler for signal %d in interrupt_handle_now(..)", signal);
} else if (lowtag_of(handler.lisp) == FUN_POINTER_LOWTAG) {
+ /* Once we've decided what to do about contexts in a
+ * return-elsewhere world (the original context will no longer
+ * be available; should we copy it or was nobody using it anyway?)
+ * then we should convert this to return-elsewhere */
+
+ /* CMUCL comment said "Allocate the SAPs while the interrupts
+ * are still disabled.". I (dan, 2003.08.21) assume this is
+ * because we're not in pseudoatomic and allocation shouldn't
+ * be interrupted. In which case it's no longer an issue as
+ * all our allocation from C now goes through a PA wrapper,
+ * but still, doesn't hurt */
- /* Allocate the SAPs while the interrupts are still disabled.
- * (FIXME: Why? This is the way it was done in CMU CL, and it
- * even had the comment noting that this is the way it was
- * done, but no motivation..) */
lispobj info_sap,context_sap = alloc_sap(context);
info_sap = alloc_sap(info);
/* Allow signals again. */
#endif
}
+/* This is called at the end of a critical section if the indications
+ * are that some signal was deferred during the section. Note that as
+ * far as C or the kernel is concerned we dealt with the signal
+ * already; we're just doing the Lisp-level processing now that we
+ * put off then */
+
+void
+run_deferred_handler(struct interrupt_data *data, void *v_context) {
+ (*(data->pending_handler))
+ (data->pending_signal,&(data->pending_info), v_context);
+}
+
+boolean
+maybe_defer_handler(void *handler, struct interrupt_data *data,
+ int signal, siginfo_t *info, os_context_t *context)
+{
+ struct thread *thread=arch_os_get_current_thread();
+ if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) {
+ store_signal_data_for_later(data,handler,signal,info,context);
+ SetSymbolValue(INTERRUPT_PENDING, T,thread);
+ return 1;
+ }
+ /* a slightly confusing test. arch_pseudo_atomic_atomic() doesn't
+ * actually use its argument for anything on x86, so this branch
+ * may succeed even when context is null (gencgc alloc()) */
+ if (
+#ifndef __i386__
+ (!foreign_function_call_active) &&
+#endif
+ arch_pseudo_atomic_atomic(context)) {
+ store_signal_data_for_later(data,handler,signal,info,context);
+ arch_set_pseudo_atomic_interrupted(context);
+ return 1;
+ }
+ return 0;
+}
static void
-store_signal_data_for_later (struct interrupt_data *data, int signal,
+store_signal_data_for_later (struct interrupt_data *data, void *handler,
+ int signal,
siginfo_t *info, os_context_t *context)
{
+ data->pending_handler = handler;
data->pending_signal = signal;
- memcpy(&(data->pending_info), info, sizeof(siginfo_t));
- memcpy(&(data->pending_mask),
- os_context_sigmask_addr(context),
- sizeof(sigset_t));
- sigaddset_blockable(os_context_sigmask_addr(context));
+ if(info)
+ memcpy(&(data->pending_info), info, sizeof(siginfo_t));
+ if(context) {
+ /* the signal mask in the context (from before we were
+ * interrupted) is copied to be restored when
+ * run_deferred_handler happens. Then the usually-blocked
+ * signals are added to the mask in the context so that we are
+ * running with blocked signals when the handler returns */
+ sigemptyset(&(data->pending_mask));
+ memcpy(&(data->pending_mask),
+ os_context_sigmask_addr(context),
+ REAL_SIGSET_SIZE_BYTES);
+ sigaddset_blockable(os_context_sigmask_addr(context));
+ } else {
+ /* this is also called from gencgc alloc(), in which case
+ * there has been no signal and is therefore no context. */
+ sigset_t new;
+ sigemptyset(&new);
+ sigaddset_blockable(&new);
+ sigprocmask(SIG_BLOCK,&new,&(data->pending_mask));
+ }
}
#ifdef LISP_FEATURE_LINUX
os_restore_fp_control(context);
#endif
- /* see comments at top of code/signal.lisp for what's going on here
- * with INTERRUPTS_ENABLED/INTERRUPT_HANDLE_NOW
- */
- if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) {
- store_signal_data_for_later(data,signal,info,context);
- SetSymbolValue(INTERRUPT_PENDING, T,thread);
- } else if (
-#ifndef __i386__
- (!foreign_function_call_active) &&
-#endif
- arch_pseudo_atomic_atomic(context)) {
- store_signal_data_for_later(data,signal,info,context);
- arch_set_pseudo_atomic_interrupted(context);
- } else {
- interrupt_handle_now(signal, info, context);
+ if(maybe_defer_handler(interrupt_handle_now,data,
+ signal,info,context))
+ return;
+ interrupt_handle_now(signal, info, context);
+}
+
+void
+sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context)
+{
+ os_context_t *context = arch_os_get_context(&void_context);
+ struct thread *thread=arch_os_get_current_thread();
+ struct interrupt_data *data=thread->interrupt_data;
+ sigset_t block;
+
+ if(maybe_defer_handler(sig_stop_for_gc_handler,data,
+ signal,info,context)){
+ return;
}
+ sigemptyset(&block);
+ sigaddset_blockable(&block);
+ sigprocmask(SIG_BLOCK, &block, 0);
+ get_spinlock(&all_threads_lock,thread->pid);
+ countdown_to_gc--;
+ release_spinlock(&all_threads_lock);
+ /* need the context stored so it can have registers scavenged */
+ fake_foreign_function_call(context);
+ kill(getpid(),SIGSTOP);
+ undo_fake_foreign_function_call(context);
}
-\f
void
interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
}
#ifdef LISP_FEATURE_SB_THREAD
-boolean handle_rt_signal(int num, siginfo_t *info, void *v_context)
+void handle_rt_signal(int num, siginfo_t *info, void *v_context)
{
- struct
- os_context_t *context = (os_context_t*)arch_os_get_context(&v_context);
+ os_context_t *context = (os_context_t*)arch_os_get_context(&v_context);
+ struct thread *th=arch_os_get_current_thread();
+ struct interrupt_data *data=
+ th ? th->interrupt_data : global_interrupt_data;
+ if(maybe_defer_handler(handle_rt_signal,data,num,info,context)){
+ return ;
+ }
arrange_return_to_lisp_function(context,info->si_value.sival_int);
}
#endif
-boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr)
-{
+boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr){
struct thread *th=arch_os_get_current_thread();
/* note the os_context hackery here. When the signal handler returns,
* it won't go back to what it was doing ... */
if(!foreign_function_call_active && gc_trigger_hit(signal, info, context)){
clear_auto_gc_trigger();
-
- if (arch_pseudo_atomic_atomic(context)) {
- /* don't GC during an atomic operation. Instead, copy the
- * signal mask somewhere safe. interrupt_handle_pending
- * will detect pending_signal==0 and know to do a GC with the
- * signal context instead of calling a Lisp-level handler */
- maybe_gc_pending = 1;
- if (data->pending_signal == 0) {
- /* FIXME: This copy-pending_mask-then-sigaddset_blockable
- * idiom occurs over and over. It should be factored out
- * into a function with a descriptive name. */
- memcpy(&(data->pending_mask),
- os_context_sigmask_addr(context),
- sizeof(sigset_t));
- sigaddset_blockable(os_context_sigmask_addr(context));
- }
- arch_set_pseudo_atomic_interrupted(context);
- }
- else {
- fake_foreign_function_call(context);
- /* SUB-GC may return without GCing if *GC-INHIBIT* is set,
- * in which case we will be running with no gc trigger
- * barrier thing for a while. But it shouldn't be long
- * until the end of WITHOUT-GCING. */
- funcall0(SymbolFunction(SUB_GC));
- undo_fake_foreign_function_call(context);
- }
+ if(!maybe_defer_handler
+ (interrupt_maybe_gc_int,data,signal,info,void_context))
+ interrupt_maybe_gc_int(signal,info,void_context);
return 1;
- } else {
- return 0;
}
+ return 0;
}
+
#endif
+
+/* this is also used by from gencgc.c alloc() */
+boolean
+interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context)
+{
+ os_context_t *context=(os_context_t *) void_context;
+ fake_foreign_function_call(context);
+ /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in
+ * which case we will be running with no gc trigger barrier
+ * thing for a while. But it shouldn't be long until the end
+ * of WITHOUT-GCING. */
+ funcall0(SymbolFunction(SUB_GC));
+ undo_fake_foreign_function_call(context);
+ return 1;
+}
+
\f
/*
* noise to install handlers
*/
-/* SBCL used to have code to restore signal handlers on exit, which
- * has been removed from the threaded version until we decide: exit of
- * _what_ ? */
-
-/* SBCL comment: The "undoably" aspect is because we also arrange with
- * atexit() for the handler to be restored to its old value. This is
- * for tidiness: it shouldn't matter much ordinarily, but it does
- * remove a window where e.g. memory fault signals (SIGSEGV or SIGBUS,
- * which in ordinary operation of SBCL are sent to the generational
- * garbage collector, then possibly onward to Lisp code) or SIGINT
- * (which is ordinarily passed to Lisp code) could otherwise be
- * handled bizarrely/brokenly because the Lisp code would try to deal
- * with them using machinery (like stream output buffers) which has
- * already been dismantled. */
-
-/* I'm not sure (a) whether this is a real concern, (b) how it helps
- anyway */
-
-void
-uninstall_low_level_interrupt_handlers_atexit(void)
-{
-}
-
void
undoably_install_low_level_interrupt_handler (int signal,
void handler(int,