#include "history.h"
#include "osio.h"
#include "ossmp.h"
+#include "osproc.h" /* for OS_process_any_status_change */
#include <pthread.h>
/* The chain of processors, starting with processor0 -- main()'s thread: */
static void make_processors (int);
void
-smp_initialize (int count)
+setup_processors (int count)
{
make_processors (count-1);
new->heap_end = heap_start + saved_processor_heap_size;
processors = new;
- if (id != 0)
- create (id, &new->pthread, &work, new);
-
trace (";%d heap: 0x%0lx-0x%0lx", id,
(ulong)new->heap_start, (ulong)new->heap_end);
trace (";%d stack: 0x%0lx-0x%0lx", id,
make_processors (id - 1);
}
+static bool all_in (processor_state_t s);
+
+void
+start_processors (void)
+{
+ processor_t *p;
+
+ for (p = processors->next; p != NULL; p = p->next)
+ create (p->id, &p->pthread, &work, p);
+
+ mutex_lock (&state_mutex);
+ self->state = PROCESSOR_GC_WAIT;
+ trace (";0 Pausing.");
+ if (! all_in (PROCESSOR_GC_WAIT))
+ {
+ trace (";0 Waiting (for all to pause).");
+ cond_wait (&ready, &state_mutex);
+ }
+ trace (";0 Ready (all paused).");
+ self->state = PROCESSOR_RUNNING;
+ mutex_unlock (&state_mutex);
+}
+
static bool
all_in (processor_state_t s)
{
cond_broadcast (&finished);
mutex_unlock (&state_mutex);
}
-#endif
\f
+static SCHEME_OBJECT get_smp_idle_prim (void);
+#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);
- self->state = PROCESSOR_PAUSED;
- OS_pause ();
+
+ 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.")
+{
+ PRIMITIVE_HEADER (0);
+
+#ifdef ENABLE_SMP
+ assert (self->state == PROCESSOR_RUNNING || self->state == PROCESSOR_IDLE);
+
+ trace (";%d SMP-Idle.", self->id);
+ self->state = PROCESSOR_IDLE;
+
+ assert (GET_INT_MASK == INT_Mask);
+ while (! ((PENDING_INTERRUPTS_P)
+ || OS_process_any_status_change ()))
+ {
+ OS_pause ();
+ trace (";%d SMP-Idle awoke to 0x%04x.", self->id, GET_INT_CODE);
+ }
+
self->state = PROCESSOR_RUNNING;
+ if (OS_process_any_status_change ())
+ {
+ outf_error_line (";%d synthetic timer interrupt used", self->id);
+ REQUEST_INTERRUPT (INT_Timer); /* Wake to handle (maybe) a SIGCHLD. */
+ }
+ assert (PENDING_INTERRUPTS_P);
+ signal_interrupt_from_primitive ();
#else
signal_error_from_primitive (ERR_UNIMPLEMENTED_PRIMITIVE);
#endif
- PRIMITIVE_RETURN (UNSPECIFIC);
}
+#ifdef ENABLE_SMP
+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
+
DEFINE_PRIMITIVE ("SMP-GC-WAIT", Prim_smp_gc_wait, 0, 0, "(SMP-GC-WAIT)\n\
Put the current processor in the GC-WAIT state.\n\
Called by the global-gc interrupt handler.")