Add helper to run a function as a routine kmsg
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 20 Jul 2018 00:57:05 +0000 (20:57 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 20 Jul 2018 14:25:54 +0000 (10:25 -0400)
I often want to just create a kernel message that runs a particular
function that already exists.  This helper (and its associated magic)
will do that for you.

The one slightly nasty thing is that we pass the function pointer as the
first argument.  Kernel messages run functions of type amr_t, and those
functions first argument is the source of the message.  That means we
can't just pass an arbitrary function and run it.  We used to have to
make trampoline functions - now we have a generic trampoline.

If we ever drop the message source, then we could just cast the argument
'f' to an amr_t.

Gotta love the macros.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/trap.h
kern/src/trap.c

index 2a7f081..5f389e6 100644 (file)
@@ -119,6 +119,25 @@ bool has_routine_kmsg(void);
 void process_routine_kmsg(void);
 void print_kmsgs(uint32_t coreid);
 
+/* Runs a function with up to two arguments as a routine kernel message.  Kernel
+ * messages can have three arguments, but the deferred function pointer counts
+ * as one.  Note the arguments to the function will be treated as longs. */
+#define run_as_rkm(f, ...) do {                                                \
+       static_assert(MACRO_NR_ARGS(__VA_ARGS__) <= 2);                            \
+       PASTE(__run_as_rkm_, MACRO_NR_ARGS(__VA_ARGS__))(f, ##__VA_ARGS__);        \
+} while (0)
+
+#define __run_as_rkm_0(f) \
+       send_kernel_message(core_id(), __kmsg_trampoline, (long)f, 0xcafebabe, \
+                           0xcafebabe, KMSG_ROUTINE)
+#define __run_as_rkm_1(f, a1) \
+       send_kernel_message(core_id(), __kmsg_trampoline, (long)f, (long)a1, \
+                           0xcafebabe, KMSG_ROUTINE)
+#define __run_as_rkm_2(f, a1, a2) \
+       send_kernel_message(core_id(), __kmsg_trampoline, (long)f, (long)a1, \
+                           (long)a2, KMSG_ROUTINE)
+void __kmsg_trampoline(uint32_t srcid, long a0, long a1, long a2);
+
 /* Kernel context depths.  IRQ depth is how many nested IRQ stacks/contexts we
  * are working on.  Kernel trap depth is how many nested kernel traps (not
  * user-space traps) we have.
index a854866..2673c9f 100644 (file)
@@ -281,6 +281,11 @@ void print_kmsgs(uint32_t coreid)
        __print_kmsgs(&pcpui->routine_amsgs, "Routine");
 }
 
+void __kmsg_trampoline(uint32_t srcid, long a0, long a1, long a2)
+{
+       ((void (*)(long arg0, long arg1))a0)(a1, a2);
+}
+
 /* Debugging stuff */
 void kmsg_queue_stat(void)
 {