smp: Initialize thread-local compiler_utilities.
authorMatt Birkholz <puck@birchwood-abbey.net>
Sat, 20 Dec 2014 15:50:09 +0000 (08:50 -0700)
committerMatt Birkholz <puck@birchwood-abbey.net>
Sun, 21 Dec 2014 19:19:09 +0000 (12:19 -0700)
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.

src/microcode/cmpint.c
src/microcode/cmpint.h
src/microcode/cmpintmd/i386.c
src/microcode/cmpintmd/i386.h
src/microcode/ossmp.h
src/microcode/prossmp.c

index f62662c6382e61c6aca83a81d7c8da96eaf09e59..e0c6e36a889a9cb0c5715a8ef09dee8ed6e6fdca 100644 (file)
@@ -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;
 \f
 /* 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
 }
 \f
 /* Main compiled-code entry points */
index 8c39638417ace097ea93cf73f88e99c303bef5f6..17350cfb14d6f639866a50a4df29e079f6b3e9dc 100644 (file)
@@ -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);
 
index 6948a8ffd4d9bc07f5fa56797f04aaeef604dcca..4d44d3039a5397a1d4ddfea7ce459d7d5602073e 100644 (file)
@@ -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
index b469ec48d2ee6efaf1f08ab5f46eae2e0682847a..5fe7acc884c6e4cb593cd4ba9071cde4b5eeae1c 100644 (file)
@@ -182,6 +182,7 @@ magic = ([TC_COMPILED_ENTRY | 0] - (offset + length_of_CALL_instruction))
 
 */
 \f
+#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;
index cf09e16d9374e6ef9c811115ab3966ed5b743687..46a9c1be55d7e5345f60bce6c80dbe89dfdd2793 100644 (file)
@@ -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;
index c47ebdb3ab1fcc2836ac280635cf44f8bc531e7f..1f99d547dff878c3432be374b2bc287b114cdd8c 100644 (file)
@@ -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);