From: Matt Birkholz Date: Sat, 20 Dec 2014 15:50:09 +0000 (-0700) Subject: smp: Initialize thread-local compiler_utilities. X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=1d941eb9638d49c98f7584248bbf652a9b78bcc2;p=mit-scheme.git smp: Initialize thread-local compiler_utilities. Split the thread-local parts of compiler_initialize into compiler_initialize_processor, those of compiler_reset into compiler_reset_processor. Split the non-thread-local parts of ASM_RESET_HOOK into ASM_INIT_HOOK, i.e. i386_reset_hook into i386_init_hook. Call the _processor versions in co-processor startup and SMP-GC-WAITs. Add compiler_reset_p flag to processor_t so that load-band (compiler_reset) can notify the other processors to load the new compiler_utilities into their Registers slots. --- diff --git a/src/microcode/cmpint.c b/src/microcode/cmpint.c index f62662c63..e0c6e36a8 100644 --- a/src/microcode/cmpint.c +++ b/src/microcode/cmpint.c @@ -258,6 +258,9 @@ long C_return_value; # endif #endif +#ifndef ASM_INIT_HOOK +# define ASM_INIT_HOOK() do {} while (false) +#endif #ifndef ASM_RESET_HOOK # define ASM_RESET_HOOK() do {} while (false) #endif @@ -291,11 +294,18 @@ long C_return_value; /* Initialization */ +void +compiler_initialize_processor (void) +{ + SET_PRIMITIVE (SHARP_F); + assert (compiler_utilities != SHARP_F); + compiler_reset_processor (); +} + void compiler_initialize (bool fasl_p) { /* Called when scheme started. */ - SET_PRIMITIVE (SHARP_F); compiler_processor_type = COMPILER_PROCESSOR_TYPE; compiler_interface_version = COMPILER_INTERFACE_VERSION; if (fasl_p) @@ -360,6 +370,17 @@ make_compiler_utilities (void) return (MAKE_CC_BLOCK (block)); } +void +compiler_reset_processor (void) +{ + SET_PRIMITIVE (SHARP_F); + SET_CLOSURE_FREE (0); + SET_CLOSURE_SPACE (0); + SET_REFLECTOR (reflect_to_interface); + + ASM_RESET_HOOK (); +} + void compiler_reset (SCHEME_OBJECT new_block) { @@ -385,11 +406,20 @@ compiler_reset (SCHEME_OBJECT new_block) compiler_utilities = new_block; return_to_interpreter = (MAKE_CC_ENTRY (trampoline_entry_addr (nbp, 0))); reflect_to_interface = (MAKE_CC_ENTRY (trampoline_entry_addr (nbp, 1))); - SET_CLOSURE_FREE (0); - SET_CLOSURE_SPACE (0); - SET_REFLECTOR (reflect_to_interface); - ASM_RESET_HOOK (); + ASM_INIT_HOOK (); + + compiler_reset_processor (); +#ifdef ENABLE_SMP + { + processor_t *p; + for (p = processors; p != NULL; p = p->next) + { + if (p != self) + p->compiler_reset_p = true; + } + } +#endif } /* Main compiled-code entry points */ diff --git a/src/microcode/cmpint.h b/src/microcode/cmpint.h index 8c3963841..17350cfb1 100644 --- a/src/microcode/cmpint.h +++ b/src/microcode/cmpint.h @@ -417,7 +417,9 @@ extern void compiled_with_interrupt_mask extern void compiled_with_stack_marker (SCHEME_OBJECT); extern void compiler_initialize (bool); +extern void compiler_initialize_processor (void); extern void compiler_reset (SCHEME_OBJECT); +extern void compiler_reset_processor (void); extern void declare_compiled_code_block (SCHEME_OBJECT); diff --git a/src/microcode/cmpintmd/i386.c b/src/microcode/cmpintmd/i386.c index 6948a8ffd..4d44d3039 100644 --- a/src/microcode/cmpintmd/i386.c +++ b/src/microcode/cmpintmd/i386.c @@ -238,12 +238,136 @@ store_trampoline_insns (insn_t * entry, byte_t code) # define VM_PROT_SCHEME (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) #endif +static bool fp_support_present = false; + +void +i386_init_hook (void) +{ + fp_support_present = (i386_interface_initialize ()); + + declare_builtin ((unsigned long)asm_scheme_to_interface, "asm_scheme_to_interface"); + declare_builtin ((unsigned long)asm_scheme_to_interface_call, "asm_scheme_to_interface_call"); + declare_builtin ((unsigned long)asm_trampoline_to_interface, "asm_trampoline_to_interface"); + declare_builtin ((unsigned long)asm_interrupt_procedure, "asm_interrupt_procedure"); + declare_builtin ((unsigned long)asm_interrupt_continuation, "asm_interrupt_continuation"); + declare_builtin ((unsigned long)asm_interrupt_closure, "asm_interrupt_closure"); + declare_builtin ((unsigned long)asm_interrupt_dlink, "asm_interrupt_dlink"); + declare_builtin ((unsigned long)asm_primitive_apply, "asm_primitive_apply"); + declare_builtin ((unsigned long)asm_primitive_lexpr_apply, "asm_primitive_lexpr_apply"); + declare_builtin ((unsigned long)asm_assignment_trap, "asm_assignment_trap"); + declare_builtin ((unsigned long)asm_reference_trap, "asm_reference_trap"); + declare_builtin ((unsigned long)asm_safe_reference_trap, "asm_safe_reference_trap"); + declare_builtin ((unsigned long)asm_link, "asm_link"); + declare_builtin ((unsigned long)asm_error, "asm_error"); + declare_builtin ((unsigned long)asm_primitive_error, "asm_primitive_error"); + declare_builtin ((unsigned long)asm_short_primitive_apply, "asm_short_primitive_apply"); + if (fp_support_present) + { + declare_builtin ((unsigned long)asm_generic_add, "asm_generic_add"); + declare_builtin ((unsigned long)asm_generic_subtract, "asm_generic_subtract"); + declare_builtin ((unsigned long)asm_generic_multiply, "asm_generic_multiply"); + declare_builtin ((unsigned long)asm_generic_divide, "asm_generic_divide"); + declare_builtin ((unsigned long)asm_generic_equal, "asm_generic_equal"); + declare_builtin ((unsigned long)asm_generic_less, "asm_generic_less"); + declare_builtin ((unsigned long)asm_generic_greater, "asm_generic_greater"); + declare_builtin ((unsigned long)asm_generic_increment, "asm_generic_increment"); + declare_builtin ((unsigned long)asm_generic_decrement, "asm_generic_decrement"); + declare_builtin ((unsigned long)asm_generic_zero, "asm_generic_zero"); + declare_builtin ((unsigned long)asm_generic_positive, "asm_generic_positive"); + declare_builtin ((unsigned long)asm_generic_negative, "asm_generic_negative"); + declare_builtin ((unsigned long)asm_generic_quotient, "asm_generic_quotient"); + declare_builtin ((unsigned long)asm_generic_remainder, "asm_generic_remainder"); + declare_builtin ((unsigned long)asm_generic_modulo, "asm_generic_modulo"); + } + else + { + declare_builtin ((unsigned long)asm_nofp_add, "asm_nofp_add"); + declare_builtin ((unsigned long)asm_nofp_subtract, "asm_nofp_subtract"); + declare_builtin ((unsigned long)asm_nofp_multiply, "asm_nofp_multiply"); + declare_builtin ((unsigned long)asm_nofp_divide, "asm_nofp_divide"); + declare_builtin ((unsigned long)asm_nofp_equal, "asm_nofp_equal"); + declare_builtin ((unsigned long)asm_nofp_less, "asm_nofp_less"); + declare_builtin ((unsigned long)asm_nofp_greater, "asm_nofp_greater"); + declare_builtin ((unsigned long)asm_nofp_increment, "asm_nofp_increment"); + declare_builtin ((unsigned long)asm_nofp_decrement, "asm_nofp_decrement"); + declare_builtin ((unsigned long)asm_nofp_zero, "asm_nofp_zero"); + declare_builtin ((unsigned long)asm_nofp_positive, "asm_nofp_positive"); + declare_builtin ((unsigned long)asm_nofp_negative, "asm_nofp_negative"); + declare_builtin ((unsigned long)asm_nofp_quotient, "asm_nofp_quotient"); + declare_builtin ((unsigned long)asm_nofp_remainder, "asm_nofp_remainder"); + declare_builtin ((unsigned long)asm_nofp_modulo, "asm_nofp_modulo"); + } + declare_builtin ((unsigned long)asm_sc_apply, "asm_sc_apply"); + declare_builtin ((unsigned long)asm_sc_apply_size_1, "asm_sc_apply_size_1"); + declare_builtin ((unsigned long)asm_sc_apply_size_2, "asm_sc_apply_size_2"); + declare_builtin ((unsigned long)asm_sc_apply_size_3, "asm_sc_apply_size_3"); + declare_builtin ((unsigned long)asm_sc_apply_size_4, "asm_sc_apply_size_4"); + declare_builtin ((unsigned long)asm_sc_apply_size_5, "asm_sc_apply_size_5"); + declare_builtin ((unsigned long)asm_sc_apply_size_6, "asm_sc_apply_size_6"); + declare_builtin ((unsigned long)asm_sc_apply_size_7, "asm_sc_apply_size_7"); + declare_builtin ((unsigned long)asm_sc_apply_size_8, "asm_sc_apply_size_8"); + declare_builtin ((unsigned long)asm_interrupt_continuation_2, "asm_interrupt_continuation_2"); + if (ia32_cpuid_needed) + declare_builtin ((unsigned long)asm_serialize_cache, "asm_serialize_cache"); + else + declare_builtin ((unsigned long)asm_dont_serialize_cache, "asm_dont_serialize_cache"); + declare_builtin ((unsigned long)asm_fixnum_shift, "asm_fixnum_shift"); + declare_builtin ((unsigned long)asm_set_interrupt_enables, "asm_set_interrupt_enables"); + +#ifdef _MACH_UNIX + { + vm_address_t addr; + vm_size_t size; + vm_prot_t prot; + vm_prot_t max_prot; + vm_inherit_t inheritance; + boolean_t shared; + port_t object; + vm_offset_t offset; + + addr = ((vm_address_t) Heap); + if ((vm_region ((task_self ()), &addr, &size, &prot, &max_prot, + &inheritance, &shared, &object, &offset)) + != KERN_SUCCESS) + { + outf_fatal ( "compiler_reset: vm_region() failed.\n"); + Microcode_Termination (TERM_EXIT); + /*NOTREACHED*/ + } + if ((prot & VM_PROT_SCHEME) != VM_PROT_SCHEME) + { + if ((max_prot & VM_PROT_SCHEME) != VM_PROT_SCHEME) + { + outf_fatal ( + "compiler_reset: inadequate protection for Heap.\n"); + outf_fatal ( "maximum = 0x%lx; desired = 0x%lx\n", + ((unsigned long) (max_prot & VM_PROT_SCHEME)), + ((unsigned long) VM_PROT_SCHEME)); + Microcode_Termination (TERM_EXIT); + /*NOTREACHED*/ + } + if ((vm_protect ((task_self ()), ((vm_address_t) Heap), + (((char *) constant_end) - ((char *) Heap)), + 0, VM_PROT_SCHEME)) + != KERN_SUCCESS) + { + outf_fatal ("Unable to change protection for Heap.\n"); + outf_fatal ("actual = 0x%lx; desired = 0x%lx\n", + ((unsigned long) (prot & VM_PROT_SCHEME)), + ((unsigned long) VM_PROT_SCHEME)); + Microcode_Termination (TERM_EXIT); + /*NOTREACHED*/ + } + } + } +#endif /* _MACH_UNIX */ +} + #define SETUP_REGISTER(hook) do \ { \ (* ((unsigned long *) (esi_value + offset))) \ = ((unsigned long) (hook)); \ offset += (COMPILER_HOOK_SIZE * (sizeof (SCHEME_OBJECT))); \ - declare_builtin (((unsigned long) hook), #hook); \ } while (0) void @@ -251,7 +375,6 @@ i386_reset_hook (void) { unsigned int offset = (COMPILER_REGBLOCK_N_FIXED * (sizeof (SCHEME_OBJECT))); unsigned char * esi_value = ((unsigned char *) Registers); - bool fp_support_present = (i386_interface_initialize ()); /* These must match machines/i386/lapgen.scm */ @@ -341,54 +464,6 @@ i386_reset_hook (void) SETUP_REGISTER (asm_dont_serialize_cache); /* -7 */ SETUP_REGISTER (asm_fixnum_shift); /* -6 */ SETUP_REGISTER (asm_set_interrupt_enables); /* -5 */ - -#ifdef _MACH_UNIX - { - vm_address_t addr; - vm_size_t size; - vm_prot_t prot; - vm_prot_t max_prot; - vm_inherit_t inheritance; - boolean_t shared; - port_t object; - vm_offset_t offset; - - addr = ((vm_address_t) Heap); - if ((vm_region ((task_self ()), &addr, &size, &prot, &max_prot, - &inheritance, &shared, &object, &offset)) - != KERN_SUCCESS) - { - outf_fatal ( "compiler_reset: vm_region() failed.\n"); - Microcode_Termination (TERM_EXIT); - /*NOTREACHED*/ - } - if ((prot & VM_PROT_SCHEME) != VM_PROT_SCHEME) - { - if ((max_prot & VM_PROT_SCHEME) != VM_PROT_SCHEME) - { - outf_fatal ( - "compiler_reset: inadequate protection for Heap.\n"); - outf_fatal ( "maximum = 0x%lx; desired = 0x%lx\n", - ((unsigned long) (max_prot & VM_PROT_SCHEME)), - ((unsigned long) VM_PROT_SCHEME)); - Microcode_Termination (TERM_EXIT); - /*NOTREACHED*/ - } - if ((vm_protect ((task_self ()), ((vm_address_t) Heap), - (((char *) constant_end) - ((char *) Heap)), - 0, VM_PROT_SCHEME)) - != KERN_SUCCESS) - { - outf_fatal ("Unable to change protection for Heap.\n"); - outf_fatal ("actual = 0x%lx; desired = 0x%lx\n", - ((unsigned long) (prot & VM_PROT_SCHEME)), - ((unsigned long) VM_PROT_SCHEME)); - Microcode_Termination (TERM_EXIT); - /*NOTREACHED*/ - } - } - } -#endif /* _MACH_UNIX */ } #ifndef HAVE_FENV_H diff --git a/src/microcode/cmpintmd/i386.h b/src/microcode/cmpintmd/i386.h index b469ec48d..5fe7acc88 100644 --- a/src/microcode/cmpintmd/i386.h +++ b/src/microcode/cmpintmd/i386.h @@ -182,6 +182,7 @@ magic = ([TC_COMPILED_ENTRY | 0] - (offset + length_of_CALL_instruction)) */ +#define ASM_INIT_HOOK i386_init_hook #define ASM_RESET_HOOK i386_reset_hook #define CMPINT_USE_STRUCS 1 @@ -331,6 +332,7 @@ extern void start_closure_relocation (SCHEME_OBJECT *, reloc_ref_t *); extern insn_t * read_compiled_closure_target (insn_t *, reloc_ref_t *); extern void start_operator_relocation (SCHEME_OBJECT *, reloc_ref_t *); extern insn_t * read_uuo_target (SCHEME_OBJECT *, reloc_ref_t *); +extern void i386_init_hook (void); extern void i386_reset_hook (void); extern int ia32_cpuid_needed; diff --git a/src/microcode/ossmp.h b/src/microcode/ossmp.h index cf09e16d9..46a9c1be5 100644 --- a/src/microcode/ossmp.h +++ b/src/microcode/ossmp.h @@ -44,6 +44,8 @@ typedef struct processor processor_t; struct processor { struct processor *next; char id; + /* Set by compiler_reset (load-band) when there are new compiler utilities. */ + bool compiler_reset_p; processor_state_t state; pthread_t pthread; SCHEME_OBJECT * stack_end; diff --git a/src/microcode/prossmp.c b/src/microcode/prossmp.c index c47ebdb3a..1f99d547d 100644 --- a/src/microcode/prossmp.c +++ b/src/microcode/prossmp.c @@ -266,6 +266,7 @@ make_processors (int id) + id * saved_processor_heap_size); new->next = processors; new->id = id; + new->compiler_reset_p = false; new->state = PROCESSOR_NEW; new->stack_start = stack_start; new->stack_end = stack_start + saved_stack_size; @@ -467,6 +468,17 @@ Pause a new processor.") PRIMITIVE_HEADER (0); #ifdef ENABLE_SMP assert (self->id != 0); + mutex_lock (&state_mutex); + while (compiler_utilities == SHARP_F) + { + trace (";%d SMP-Pause.", self->id); + gc_wait (); + /* If no compiler_utilities, then not bootstrapping; must wait + for band-load. */ + } + mutex_unlock (&state_mutex); + + compiler_reset_processor (); Will_Push (STACK_ENV_EXTRA_SLOTS + 1); STACK_PUSH (get_smp_idle_prim ()); @@ -541,6 +553,11 @@ Called by the global-gc interrupt handler.") CLEAR_INTERRUPT (INT_Global_GC); mutex_lock (&state_mutex); gc_wait (); + if (self->compiler_reset_p) + { + compiler_reset_processor (); + self->compiler_reset_p = false; + } mutex_unlock (&state_mutex); #else signal_error_from_primitive (ERR_UNIMPLEMENTED_PRIMITIVE);