}
}
+static void
+create (int id, pthread_t *thread, void *(*start_routine) (void *), void *arg)
+{
+ int err = pthread_create (thread, NULL, start_routine, arg);
+ if (err != 0)
+ {
+ pthread_error (err);
+ fatal ("\n;%d pthread_create failed: %d", id, err);
+ }
+}
+
static void
pthread_error (int code)
{
RESET_HISTORY ();
}
+static void *
+work (void *p)
+{
+ SCHEME_OBJECT expr;
+ self = (processor_t *)p;
+ trace (";%d Start.", self->id);
+ assert (self->id != 0);
+ assert (self != processors);
+ reset_processor_allocator (self);
+ RESET_HISTORY ();
+
+ /* expr: (SMP-PAUSE) */
+ expr = (MAKE_POINTER_OBJECT (TC_COMBINATION, Free));
+ (*Free++) = MAKE_OBJECT (TC_MANIFEST_VECTOR, 1);
+ (*Free++) = make_primitive ("SMP-PAUSE", 0);
+
+ /* Setup registers */
+ INITIALIZE_INTERRUPTS (0);
+ SET_ENV (THE_GLOBAL_ENV);
+ trapping = false;
+
+ /* Give the interpreter something to chew on, and ... */
+ Will_Push (CONTINUATION_SIZE);
+ SET_RC (RC_END_OF_COMPUTATION);
+ SET_EXP (SHARP_F);
+ SAVE_CONT ();
+ Pushed ();
+
+ SET_EXP (expr);
+
+ /* Go to it! */
+
+ Interpret (0);
+
+ trace (";%d Died.", self->id);
+ self->state = PROCESSOR_DEAD;
+ return (NULL);
+}
+
static void
make_processors (int id)
{
make_processors (id - 1);
}
+static bool all_in (processor_state_t s);
+
+void
+start_processors (void)
+{
+ for (processor_t *p = processors->next; p != NULL; p = p->next)
+ create (p->id, &p->pthread, &work, p);
+
+ mutex_lock (&state_mutex);
+ self->state = PROCESSOR_GC_WAIT;
+ if (! all_in (PROCESSOR_GC_WAIT))
+ {
+ trace (";0 Pausing.");
+ cond_wait (&ready, &state_mutex);
+ }
+ trace (";0 Paused.");
+ mutex_unlock (&state_mutex);
+}
+
static bool
all_in (processor_state_t s)
{
p->free_pointer = p->heap_start;
trace (";%d smp_gc_finish reset", self->id);
}
+
+static SCHEME_OBJECT smp_idle_prim = SHARP_F;
+
+static SCHEME_OBJECT
+get_smp_idle_prim (void)
+{
+ if (smp_idle_prim != SHARP_F)
+ return (smp_idle_prim);
+
+ smp_idle_prim = find_primitive_cname ("SMP-IDLE", false, false, 0);
+ if (smp_idle_prim == SHARP_F)
+ {
+ outf_error_line (";No SMP-IDLE primitive!");
+ signal_error_from_primitive (ERR_EXTERNAL_RETURN);
+ }
+ return (smp_idle_prim);
+}
#endif /* ENABLE_SMP */
\f
DEFINE_PRIMITIVE ("SMP-COUNT", Prim_smp_count, 0, 0, "(SMP-COUNT)\n\
#endif
}
+DEFINE_PRIMITIVE ("SMP-PAUSE", Prim_smp_pause, 0, 0, "(SMP-PAUSE)\n\
+Pause a new processor.")
+{
+ PRIMITIVE_HEADER (0);
+#ifdef ENABLE_SMP
+ assert (self->id != 0);
+ while (compiler_utilities == SHARP_F)
+ {
+ trace (";%d SMP-Pause.", self->id);
+ mutex_lock (&state_mutex);
+ gc_wait ();
+ mutex_unlock (&state_mutex);
+ trace (";%d SMP-Pause done.", self->id);
+ /* If no compiler_utilities, then not bootstrapping; must wait
+ for band-load. */
+ }
+
+ Will_Push (STACK_ENV_EXTRA_SLOTS + 1);
+ STACK_PUSH (get_smp_idle_prim ());
+ PUSH_APPLY_FRAME_HEADER (0);
+ Pushed ();
+
+ SET_INTERRUPT_MASK (INT_Mask);
+ PRIMITIVE_ABORT (PRIM_APPLY);
+#else
+ signal_error_from_primitive (ERR_UNIMPLEMENTED_PRIMITIVE);
+#endif
+}
+
DEFINE_PRIMITIVE ("SMP-IDLE", Prim_smp_idle, 0, 0, "(SMP-IDLE)\n\
Wait for interrupts.")
{