BSD taskqueues via KMSGs
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 14 Jan 2015 23:24:32 +0000 (15:24 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 Feb 2015 15:12:27 +0000 (10:12 -0500)
BSD taskqueues are kernel threads that execute work asynchronously.  Check out
http://www.freebsd.org/cgi/man.cgi?query=taskqueue for more info.

We could implement them with ktasks that sleep on queues, and pump the tasks
into the queues.  But the tasks are basically slimmed down kernel messages, so
we can just send a message.

In the future, we may want better support or more taskqueue behaviors, both in
BSD code and more generally throughout Akaros.  We can always reimplement
taskqueues in a more appropriate manner at that time.

kern/include/taskqueue.h [new file with mode: 0644]
kern/src/Kbuild
kern/src/taskqueue.c [new file with mode: 0644]

diff --git a/kern/include/taskqueue.h b/kern/include/taskqueue.h
new file mode 100644 (file)
index 0000000..a9b853a
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (c) 2015 Google Inc
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Hacked BSD taskqueues.  In lieu of actually running a kproc or something that
+ * sleeps on a queue of tasks, we'll just blast out a kmsg.  We can always
+ * change the implementation if we need more control. */
+
+#ifndef ROS_KERN_TASKQUEUE_H
+#define ROS_KERN_TASKQUEUE_H
+
+typedef void (*task_fn_t)(void *context, int pending);
+struct taskqueue {};
+struct task {
+       task_fn_t                                       ta_func;                /*      task handler */
+       void                                            *ta_context;    /*      argument for handler */
+};
+
+#define taskqueue_drain(x, y)
+#define taskqueue_free(x)
+#define taskqueue_create(a, b, c, d) ((struct taskqueue*)(0xcafebabe))
+#define taskqueue_create_fast taskqueue_create
+#define taskqueue_start_threads(a, b, c, d, e) (1)
+
+int taskqueue_enqueue(struct taskqueue *queue, struct task *task);
+/* We're already fast, no need for another ufnction! (sic) */
+#define taskqueue_enqueue_fast taskqueue_enqueue
+#define TASK_INIT(str, dummy, func, arg)                                       \
+       (str)->ta_func = func;                                                     \
+       (str)->ta_context = (void*)arg;
+
+#endif /* ROS_KERN_TASKQUEUE_H */
index 4b83645..57b5d5c 100644 (file)
@@ -49,6 +49,7 @@ obj-y                                         += string.o
 obj-y                                          += strstr.o
 obj-y                                          += syscall.o
 obj-y                                          += sysevent.o
+obj-y                                          += taskqueue.o
 obj-y                                          += time.o
 obj-y                                          += trace.o
 obj-y                                          += trap.o
diff --git a/kern/src/taskqueue.c b/kern/src/taskqueue.c
new file mode 100644 (file)
index 0000000..27606ee
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (c) 2015 Google Inc
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Hacked BSD taskqueues.  In lieu of actually running a kproc or something that
+ * sleeps on a queue of tasks, we'll just blast out a kmsg.  We can always
+ * change the implementation if we need more control. */
+
+#include <taskqueue.h>
+#include <trap.h>
+
+/* BSD Taskqueue wrappers. */
+static void __tq_wrapper(uint32_t srcid, long a0, long a1, long a2)
+{
+       task_fn_t tq_fn = (task_fn_t)a0;
+       void *tq_arg = (void*)a1;
+       tq_fn(tq_arg, 0);
+}
+
+int taskqueue_enqueue(struct taskqueue *queue, struct task *task)
+{
+       send_kernel_message(core_id(), __tq_wrapper, (long)task->ta_func,
+                           (long)task->ta_context, 0, KMSG_ROUTINE);
+       return 0;
+}