smp: Add i386 assembly to allocate/access thread-local variables.
authorMatt Birkholz <puck@birchwood-abbey.net>
Tue, 25 Nov 2014 12:28:27 +0000 (05:28 -0700)
committerMatt Birkholz <puck@birchwood-abbey.net>
Sun, 21 Dec 2014 19:19:08 +0000 (12:19 -0700)
Change the storage class of thread-local variables in use thus far.

src/microcode/cmpauxmd/i386.m4
src/microcode/cmpint.c
src/microcode/extern.h
src/microcode/history.h
src/microcode/makegen/m4.sh
src/microcode/storage.c
src/microcode/utils.c

index bf538d6d3296fd758e5adff9f7e0dbfa8fd6c515..ee3534a76ec02cc0871739f80e8cc0428a11eb0b 100644 (file)
@@ -41,7 +41,7 @@
 ###    2) The C compiler divides registers into three groups:
 ###    - Linkage registers, used for procedure calls and global
 ###    references.  On i386 (gcc and Zortech C): %ebp, %esp.
-###    - super temporaries, not preserved accross procedure calls and
+###    - super temporaries, not preserved across procedure calls and
 ###    always usable. On i386 (gcc and Zortech C): %eax, %edx, %ecx.
 ###    - preserved registers saved by the callee if they are written.
 ###    On i386 (gcc and Zortech C): all others (%ebx, %esi, %edi).
@@ -176,6 +176,9 @@ IFNDASM(`define(popfd,`popf')')
 ifdef(`SUPPRESS_LEADING_UNDERSCORE',
        `define(EVR,`$1')',
        `define(EVR,`_$1')')
+ifdef(`ENABLE_SMP',
+      `define(TLVR,`%gs:$1\@ntpoff')',
+      `define(TLVR,`EVR($1)')')
 
 # When using the Watcom C compiler with register-based calling
 # conventions, source-code function names normally expand to `FOO_',
@@ -350,6 +353,38 @@ define(rmask,REG(ebp))
 IFDASM(`.586p
 .model flat')
 
+use_external_data(EVR(utility_table))
+
+ifdef(`ENABLE_SMP',`
+       .section .tbss,"awT",\@nobits
+       .align 4
+define(`define_tllong',`
+       .globl $1
+       .type $1 STT_TLS
+       .size $1, 4
+$1:
+       .zero   4
+')
+       define_tllong(Free)
+       define_tllong(heap_alloc_limit)
+       define_tllong(heap_end)
+       define_tllong(stack_guard)
+       define_tllong(stack_pointer)
+       define_tllong(stack_start)
+       define_tllong(C_Stack_Pointer)
+       define_tllong(C_Frame_Pointer)
+
+       .zero 128
+       .globl Registers
+       .type Registers STT_TLS
+       .size Registers, eval(REGBLOCK_SIZE_IN_OBJECTS*4)
+Registers:
+       .zero eval(REGBLOCK_SIZE_IN_OBJECTS*4)
+',`
+ifdef(`WIN32',`
+use_external_data(EVR(RegistersPtr))
+',`
+
 DECLARE_DATA_SEGMENT()
 declare_alignment(2)
 
@@ -359,29 +394,25 @@ use_external_data(EVR(heap_end))
 use_external_data(EVR(stack_guard))
 use_external_data(EVR(stack_pointer))
 use_external_data(EVR(stack_start))
-use_external_data(EVR(utility_table))
 
-ifdef(`WIN32',`
-use_external_data(EVR(RegistersPtr))
-',`
 define_data(Regstart)
 allocate_space(Regstart,128)
 
 define_data(Registers)
 allocate_space(Registers,eval(REGBLOCK_SIZE_IN_OBJECTS*4))
-')
-
-define_data(i387_presence)
-allocate_longword(i387_presence)
-
-define_data(sse_presence)
-allocate_longword(sse_presence)
 
 define_data(C_Stack_Pointer)
 allocate_longword(C_Stack_Pointer)
 
 define_data(C_Frame_Pointer)
 allocate_longword(C_Frame_Pointer)
+')')
+
+define_data(i387_presence)
+allocate_longword(i387_presence)
+
+define_data(sse_presence)
+allocate_longword(sse_presence)
 
 define_data(ia32_cpuid_supported)
 allocate_longword(ia32_cpuid_supported)
@@ -559,7 +590,7 @@ no_cpuid_instr:
 # set esp to something funny.
 
 define_c_label(within_c_stack)
-       OP(mov,l)       TW(EVR(C_Stack_Pointer),REG(eax))
+       OP(mov,l)       TW(TLVR(C_Stack_Pointer),REG(eax))
        # Are we currently in C, signalled by having no saved C stack pointer?
        OP(cmp,l)       TW(IMM(0),REG(eax))
        # Yes: just call the function without messing with esp.
@@ -568,7 +599,7 @@ define_c_label(within_c_stack)
        OP(push,l)      REG(ebp)                        # Save frame pointer
        OP(mov,l)       TW(REG(esp),REG(ebp))
        OP(mov,l)       TW(REG(eax),REG(esp))           # Switch to C stack
-       OP(mov,l)       TW(IMM(0),EVR(C_Stack_Pointer))
+       OP(mov,l)       TW(IMM(0),TLVR(C_Stack_Pointer))
        OP(push,l)      IMM(0)                          # Align sp to 16 bytes
        OP(push,l)      REG(ebp)                        # Save stack pointer
        OP(push,l)      LOF(HEX(c),REG(ebp))            # Push argument
@@ -578,7 +609,7 @@ define_debugging_label(within_c_stack_restore)
        OP(pop,l)       REG(eax)                        # Pop argument
        OP(mov,l)       TW(REG(esp),REG(eax))           # Restore C stack ptr
        OP(add,l)       TW(IMM(8),REG(eax))
-       OP(mov,l)       TW(REG(eax),EVR(C_Stack_Pointer))
+       OP(mov,l)       TW(REG(eax),TLVR(C_Stack_Pointer))
        OP(pop,l)       REG(esp)                        # Restore stack pointer
                                                        #   and switch back to
                                                        #   Scheme stack
@@ -603,15 +634,18 @@ define_c_label(C_to_interface)
        OP(push,l)      REG(ebx)
        OP(mov,l)       TW(LOF(8,REG(ebp)),REG(edx))    # Entry point
                                                        # Preserve frame ptr
-       OP(mov,l)       TW(REG(ebp),EVR(C_Frame_Pointer))
+       OP(mov,l)       TW(REG(ebp),TLVR(C_Frame_Pointer))
                                                        # Preserve stack ptr
-       OP(mov,l)       TW(REG(esp),EVR(C_Stack_Pointer))
+       OP(mov,l)       TW(REG(esp),TLVR(C_Stack_Pointer))
                                                        # Register block = %esi
                                                        # Scheme offset in NT
 
 ifdef(`WIN32',
 `      OP(mov,l)       TW(ABS(EVR(RegistersPtr)),regs)',
-`      OP(lea,l)       TW(ABS(EVR(Registers)),regs)')
+`ifdef(`ENABLE_SMP',
+`      OP(mov,l)       TW(%gs:0,regs)
+       OP(add,l)       TW($Registers\@ntpoff,regs)',
+`      OP(lea,l)       TW(ABS(EVR(Registers)),regs)')')
        jmp     EPFR(interface_to_scheme)
 
 define_hook_label(trampoline_to_interface)
@@ -630,8 +664,8 @@ define_debugging_label(scheme_to_interface)
 
 # These two moves must happen _before_ the ffree instructions below.
 # Otherwise recovery from SIGFPE there will fail.
-       OP(mov,l)       TW(REG(esp),EVR(stack_pointer))
-       OP(mov,l)       TW(rfree,EVR(Free))
+       OP(mov,l)       TW(REG(esp),TLVR(stack_pointer))
+       OP(mov,l)       TW(rfree,TLVR(Free))
 
 IF387(`
        OP(cmp,l)       TW(IMM(0),ABS(EVR(i387_presence)))
@@ -647,11 +681,11 @@ IF387(`
 scheme_to_interface_proceed:
 ')
 
-       OP(mov,l)       TW(EVR(C_Stack_Pointer),REG(esp))
-       OP(mov,l)       TW(EVR(C_Frame_Pointer),REG(ebp))
+       OP(mov,l)       TW(TLVR(C_Stack_Pointer),REG(esp))
+       OP(mov,l)       TW(TLVR(C_Frame_Pointer),REG(ebp))
 
        # Signal to within_c_stack that we are now in C land.
-       OP(mov,l)       TW(IMM(0),EVR(C_Stack_Pointer))
+       OP(mov,l)       TW(IMM(0),TLVR(C_Stack_Pointer))
 
        OP(sub,l)       TW(IMM(8),REG(esp))     # alloc struct return
 
@@ -689,14 +723,14 @@ IF387(`
        ffree   ST(7)
 interface_to_scheme_proceed:
 ')
-       OP(mov,l)       TW(EVR(Free),rfree)             # Free pointer = %edi
+       OP(mov,l)       TW(TLVR(Free),rfree)            # Free pointer = %edi
        OP(mov,l)       TW(LOF(REGBLOCK_VAL(),regs),REG(eax)) # Value/dynamic link
        OP(mov,l)       TW(IMM(ADDRESS_MASK),rmask)     # = %ebp
 
        # Restore the C stack pointer, which we zeroed back in
        # scheme_to_interface, for within_c_stack.
-       OP(mov,l)       TW(REG(esp),EVR(C_Stack_Pointer))
-       OP(mov,l)       TW(EVR(stack_pointer),REG(esp))
+       OP(mov,l)       TW(REG(esp),TLVR(C_Stack_Pointer))
+       OP(mov,l)       TW(TLVR(stack_pointer),REG(esp))
        OP(mov,l)       TW(REG(eax),REG(ecx))           # Preserve if used
        OP(and,l)       TW(rmask,REG(ecx))              # Restore potential dynamic link
        OP(mov,l)       TW(REG(ecx),LOF(REGBLOCK_DLINK(),regs))
@@ -889,13 +923,13 @@ set_interrupt_enables_memtop_1:
        # If GC is enabled, set memtop to the heap allocation limit.
        OP(test,l)      TW(IMM(INT_GC),REG(ecx))
        jz      set_interrupt_enables_memtop_2
-       OP(mov,l)       TW(ABS(EVR(heap_alloc_limit)),REG(edx))
+       OP(mov,l)       TW(ABS(TLVR(heap_alloc_limit)),REG(edx))
        jmp     set_interrupt_enables_set_memtop
 
 set_interrupt_enables_memtop_2:
        # Otherwise, there is no interrupt pending, and GC is not
        # enabled, so set memtop to the absolute heap end.
-       OP(mov,l)       TW(ABS(EVR(heap_end)),REG(edx))
+       OP(mov,l)       TW(ABS(TLVR(heap_end)),REG(edx))
 
 set_interrupt_enables_set_memtop:
        OP(mov,l)       TW(REG(edx),LOF(REGBLOCK_MEMTOP(),regs))
@@ -903,11 +937,11 @@ set_interrupt_enables_set_memtop:
 set_interrupt_enables_determine_stack_guard:
        OP(test,l)      TW(IMM(INT_Stack_Overflow),REG(ecx))
        jz      set_interrupt_enables_stack_guard_1
-       OP(mov,l)       TW(ABS(EVR(stack_guard)),REG(edx))
+       OP(mov,l)       TW(ABS(TLVR(stack_guard)),REG(edx))
        jmp     set_interrupt_enables_set_stack_guard
 
 set_interrupt_enables_stack_guard_1:
-       OP(mov,l)       TW(ABS(EVR(stack_start)),REG(edx))
+       OP(mov,l)       TW(ABS(TLVR(stack_start)),REG(edx))
 
 set_interrupt_enables_set_stack_guard:
        OP(mov,l)       TW(REG(edx),LOF(REGBLOCK_STACK_GUARD(),regs))
index 5774d1b221cdd2a65d330f804692df60447dbb60..f62662c6382e61c6aca83a81d7c8da96eaf09e59 100644 (file)
@@ -251,7 +251,11 @@ long C_return_value;
    + COMPILER_REGBLOCK_EXTRA_SIZE)
 
 #ifndef REGBLOCK_ALLOCATED_BY_INTERFACE
-  SCHEME_OBJECT Registers [REGBLOCK_LENGTH];
+  __thread SCHEME_OBJECT Registers [REGBLOCK_LENGTH];
+#  ifdef ENABLE_SMP
+    __thread void *C_Stack_Pointer;
+    __thread void *C_Frame_Pointer;
+#  endif
 #endif
 
 #ifndef ASM_RESET_HOOK
index 515abce7a0d52049aed1b4a2fcb78073d90b9d0b..4b14358656f64710ac2f52d5e347a3cfe8f0d1a7 100644 (file)
@@ -37,7 +37,7 @@ USA.
    extern SCHEME_OBJECT * RegistersPtr;
 #  define Registers RegistersPtr
 #else
-   extern SCHEME_OBJECT Registers [];
+   extern __thread SCHEME_OBJECT Registers [];
 #endif
 
 #define GET_REG_O(i) (Registers[REGBLOCK_##i])
@@ -138,11 +138,11 @@ extern void set_ulong_register (unsigned int, unsigned long);
 #  define Bignum_Debug 0
 #endif
 
-extern SCHEME_OBJECT * Free;
-extern SCHEME_OBJECT * Free_primitive;
-extern SCHEME_OBJECT * heap_alloc_limit;
-extern SCHEME_OBJECT * heap_start;
-extern SCHEME_OBJECT * heap_end;
+extern __thread SCHEME_OBJECT * Free;
+extern __thread SCHEME_OBJECT * Free_primitive;
+extern __thread SCHEME_OBJECT * heap_alloc_limit;
+extern __thread SCHEME_OBJECT * heap_start;
+extern __thread SCHEME_OBJECT * heap_end;
 #ifdef ENABLE_SMP
 extern SCHEME_OBJECT * p0_heap_start;
 extern SCHEME_OBJECT * shared_heap_start;
@@ -150,10 +150,10 @@ extern SCHEME_OBJECT * shared_heap_free;
 extern SCHEME_OBJECT * shared_heap_end;
 #endif
 
-extern SCHEME_OBJECT * stack_pointer;
-extern SCHEME_OBJECT * stack_guard;
-extern SCHEME_OBJECT * stack_start;
-extern SCHEME_OBJECT * stack_end;
+extern __thread SCHEME_OBJECT * stack_pointer;
+extern __thread SCHEME_OBJECT * stack_guard;
+extern __thread SCHEME_OBJECT * stack_start;
+extern __thread SCHEME_OBJECT * stack_end;
 
 extern SCHEME_OBJECT * constant_alloc_next;
 extern SCHEME_OBJECT * constant_start;
@@ -161,7 +161,7 @@ extern SCHEME_OBJECT * constant_end;
 \f
 /* Address of the most recent return code in the stack.  This is
    only meaningful while in compiled code.  */
-extern SCHEME_OBJECT * last_return_code;
+extern __thread SCHEME_OBJECT * last_return_code;
 extern SCHEME_OBJECT fixed_objects;
 
 extern SCHEME_OBJECT ephemeron_array;
@@ -182,7 +182,7 @@ extern const char * Term_Names [];
 extern const char * term_messages [];
 extern const char * fixed_objects_names [];
 
-extern bool trapping;
+extern __thread bool trapping;
 
 extern const char * scheme_program_name;
 extern const char * OS_Name;
@@ -196,9 +196,9 @@ extern SCHEME_OBJECT * memory_block_end;
 extern unsigned long heap_reserved;
 
 /* Amount of space needed when GC requested */
-extern unsigned long gc_space_needed;
+extern __thread unsigned long gc_space_needed;
 #ifdef ENABLE_SMP
-extern unsigned long gc_shared_space_needed;
+extern __thread unsigned long gc_shared_space_needed;
 #endif
 
 /* Number of new ephemerons requested from the GC.  */
index e9b450a6eede052dfbc92434f1f935793e947747..eead1850901079eb393739a54b8f74f84288a0bd 100644 (file)
@@ -75,8 +75,8 @@ USA.
 #  define COMPILER_END_SUBPROBLEM() do {} while (false)
 #endif
 
-extern SCHEME_OBJECT * history_register;
-extern unsigned long prev_restore_history_offset;
+extern __thread SCHEME_OBJECT * history_register;
+extern __thread unsigned long prev_restore_history_offset;
 
 extern void reset_history (void);
 extern SCHEME_OBJECT * make_dummy_history (void);
index 7e92f218e89a17546bd9c3e3cb1ce91bf34c123f..be1ac28554c98f4e260aa4d1e465d85a1d711416 100755 (executable)
@@ -52,7 +52,8 @@ touch "${TMP_FILE}"
 
 if [ $# = 0 ]
 then
-  sed -e '/^#/D' | run_m4 | sed -e 's/@/$/g' -e 's/^\f$//'
+  sed -e '/^#/D' | run_m4 \
+  | sed -e 's/\([^\]\)@/\1$/g' -e 's/\\@/@/g' -e 's/^\f$//'
 else
   SEEN_INPUT=0
   while [ $# != 0 ]; do
@@ -68,7 +69,8 @@ else
   if [ ${SEEN_INPUT} -eq 0 ]; then
     sed -e '/^#/D' >> "${TMP_FILE}"
   fi
-  run_m4 < "${TMP_FILE}" | sed -e 's/@/$/g' -e 's/^\f$//'
+  run_m4 < "${TMP_FILE}" \
+  | sed -e 's/\([^\]\)@/\1$/g' -e 's/\\@/@/g' -e 's/^\f$//'
 fi
 
 # If m4 was successful, run_m4 has deleted the temporary file.  If
index 246413973a6dba06389c16ede5ca63c382910f92..e1d4538886e3ea710095c9f6161e08b23daeb588 100644 (file)
@@ -33,13 +33,17 @@ USA.
 #endif
 
 /* next free word in heap */
+#ifndef ENABLE_SMP
 SCHEME_OBJECT * Free;
+#endif
 
 /* value of Free on entry to primitive, or 0 if not in primitive */
-SCHEME_OBJECT * Free_primitive = 0;
+__thread SCHEME_OBJECT * Free_primitive = 0;
 
 /* strict limit for Free */
+#ifndef ENABLE_SMP
 SCHEME_OBJECT * heap_alloc_limit;
+#endif
 
 #ifdef ENABLE_SMP
 /* the start of From space */
@@ -54,18 +58,26 @@ SCHEME_OBJECT * shared_heap_free;
 #endif
 
 /* limits of local heap */
-SCHEME_OBJECT * heap_start;
+__thread SCHEME_OBJECT * heap_start;
+#ifndef ENABLE_SMP
 SCHEME_OBJECT * heap_end;
+#endif
 
 /* pointer to most-recently pushed item */
+#ifndef ENABLE_SMP
 SCHEME_OBJECT * stack_pointer;
+#endif
 
 /*-strict limit for stack_pointer */
+#ifndef ENABLE_SMP
 SCHEME_OBJECT * stack_guard;
+#endif
 
 /* limits of stack */
+#ifndef ENABLE_SMP
 SCHEME_OBJECT * stack_start;
-SCHEME_OBJECT * stack_end;
+#endif
+__thread SCHEME_OBJECT * stack_end;
 
 /* next free word in constant space */
 SCHEME_OBJECT * constant_alloc_next;
@@ -76,7 +88,7 @@ SCHEME_OBJECT * constant_end;
 
 /* Address of the most recent return code in the stack.
    This is only meaningful while in compiled code.  */
-SCHEME_OBJECT * last_return_code;
+__thread SCHEME_OBJECT * last_return_code;
 
 SCHEME_OBJECT fixed_objects;
 
@@ -87,7 +99,7 @@ SCHEME_OBJECT fixed_objects;
 SCHEME_OBJECT ephemeron_array = SHARP_F;
 unsigned long ephemeron_count = 0;
 
-bool trapping;
+__thread bool trapping;
 
 SCHEME_OBJECT * memory_block_start;
 SCHEME_OBJECT * memory_block_end;
@@ -95,9 +107,9 @@ SCHEME_OBJECT * memory_block_end;
 unsigned long heap_reserved;
 
 /* Amount of space needed when GC requested */
-unsigned long gc_space_needed;
+__thread unsigned long gc_space_needed;
 #ifdef ENABLE_SMP
-unsigned long gc_shared_space_needed;
+__thread unsigned long gc_shared_space_needed;
 #endif
 
 /* Number of new ephemerons requested from the GC.  */
index 2ed5d4bf19271e4db78ae0f44ba570adbb089d51..b6ad533f0c932f92e2082e9051357017bce20080 100644 (file)
@@ -35,8 +35,8 @@ USA.
   extern void OS2_handle_attention_interrupt (void);
 #endif
 
-SCHEME_OBJECT * history_register;
-unsigned long prev_restore_history_offset;
+__thread SCHEME_OBJECT * history_register;
+__thread unsigned long prev_restore_history_offset;
 
 static SCHEME_OBJECT copy_history (SCHEME_OBJECT);
 static void error_death (long, const char *) NORETURN;
@@ -993,8 +993,8 @@ C_call_scheme (SCHEME_OBJECT proc,
   SCHEME_OBJECT * callers_last_return_code;
 
 #ifdef CC_IS_NATIVE
-  extern void * C_Frame_Pointer;
-  extern void * C_Stack_Pointer;
+  extern __thread void * C_Frame_Pointer;
+  extern __thread void * C_Stack_Pointer;
   void * cfp = C_Frame_Pointer;
   void * csp = C_Stack_Pointer;
 #ifdef CL386