Rename KMALLOC_* -> MEM_* [2/2]
[akaros.git] / kern / src / smp.c
index 701cfb6..12bbd6e 100644 (file)
 #include <trace.h>
 #include <kdebug.h>
 #include <kmalloc.h>
+#include <core_set.h>
+#include <completion.h>
 
-struct per_cpu_info per_cpu_info[MAX_NUM_CPUS];
+struct all_cpu_work {
+       struct completion comp;
+       void (*func)(void *);
+       void *opaque;
+};
+
+struct per_cpu_info per_cpu_info[MAX_NUM_CORES];
 
 // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
 atomic_t outstanding_calls = 0;
@@ -53,8 +61,9 @@ static void try_run_proc(void)
 static void __attribute__((noinline, noreturn)) __smp_idle(void)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+
        clear_rkmsg(pcpui);
-       pcpui->cur_kthread->is_ktask = FALSE;
+       pcpui->cur_kthread->flags = KTH_DEFAULT_FLAGS;
        enable_irq();   /* one-shot change to get any IRQs before we halt later */
        while (1) {
                disable_irq();
@@ -98,6 +107,10 @@ void smp_percpu_init(void)
        kthread = __kthread_zalloc();
        kthread->stacktop = get_stack_top();    /* assumes we're on the 1st page */
        pcpui->cur_kthread = kthread;
+       /* Treat the startup threads as ktasks.  This will last until smp_idle when
+        * they clear it, either in anticipation of being a user-backing kthread or
+        * to handle an RKM. */
+       kthread->flags = KTH_KTASK_FLAGS;
        per_cpu_info[coreid].spare = 0;
        /* Init relevant lists */
        spinlock_init_irqsave(&per_cpu_info[coreid].immed_amsg_lock);
@@ -148,7 +161,7 @@ void reset_cpu_state_ticks(int coreid)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
        uint64_t now_ticks;
-       if (coreid >= num_cpus)
+       if (coreid >= num_cores)
                return;
        /* need to update last_tick_cnt, so the current value doesn't get added in
         * next time we update */
@@ -220,18 +233,49 @@ void pcpui_tr_foreach(int coreid, int type)
 
 void pcpui_tr_foreach_all(int type)
 {
-       for (int i = 0; i < num_cpus; i++)
+       for (int i = 0; i < num_cores; i++)
                pcpui_tr_foreach(i, type);
 }
 
 void pcpui_tr_reset_all(void)
 {
-       for (int i = 0; i < num_cpus; i++)
+       for (int i = 0; i < num_cores; i++)
                trace_ring_reset(&per_cpu_info[i].traces);
 }
 
 void pcpui_tr_reset_and_clear_all(void)
 {
-       for (int i = 0; i < num_cpus; i++)
+       for (int i = 0; i < num_cores; i++)
                trace_ring_reset_and_clear(&per_cpu_info[i].traces);
 }
+
+static void smp_do_core_work(uint32_t srcid, long a0, long a1, long a2)
+{
+       struct all_cpu_work *acw = (struct all_cpu_work *) a0;
+
+       acw->func(acw->opaque);
+       completion_complete(&acw->comp, 1);
+}
+
+void smp_do_in_cores(const struct core_set *cset, void (*func)(void *),
+                                        void *opaque)
+{
+       int cpu = core_id();
+       struct all_cpu_work acw;
+
+       memset(&acw, 0, sizeof(acw));
+       completion_init(&acw.comp, core_set_remote_count(cset));
+       acw.func = func;
+       acw.opaque = opaque;
+
+       for (int i = 0; i < num_cores; i++) {
+               if (core_set_getcpu(cset, i)) {
+                       if (i == cpu)
+                               func(opaque);
+                       else
+                               send_kernel_message(i, smp_do_core_work, (long) &acw, 0, 0,
+                                                                       KMSG_ROUTINE);
+               }
+       }
+       completion_wait(&acw.comp);
+}