Helper to spawn kernel tasks (ktasks)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 4 Oct 2013 17:40:39 +0000 (10:40 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jan 2014 02:18:34 +0000 (18:18 -0800)
These are just kernel messages that might block.  Some subsystems launch
them, and they are meant to run for the life of the system.  We added a
name for debugging.

Also, since it's not clear how to schedule KMSGs or ktasks, we just send
them to the calling core, like with all KMSGs...

kern/include/kthread.h
kern/src/alarm.c
kern/src/kthread.c

index 395cd54..a0ffc08 100644 (file)
@@ -34,6 +34,7 @@ struct kthread {
        TAILQ_ENTRY(kthread)            link;
        /* ID, other shit, etc */
        bool                                            is_ktask;       /* default is FALSE */
+       char                                            *name;
 };
 
 /* Semaphore for kthreads to sleep on.  0 or less means you need to sleep */
@@ -67,6 +68,7 @@ struct kthread *__kthread_zalloc(void);
 void restart_kthread(struct kthread *kthread);
 void kthread_runnable(struct kthread *kthread);
 void kthread_yield(void);
+void ktask(char *name, void (*fn)(void*), void *arg);
 /* Debugging */
 void check_poison(char *msg);
 
index 5e68005..e539c5d 100644 (file)
@@ -285,8 +285,9 @@ void print_chain(struct timer_chain *tchain)
               tchain->latest_time);
        TAILQ_FOREACH(i, &tchain->waiters, next) {
                struct kthread *kthread = TAILQ_FIRST(&i->sem.waiters);
-               printk("\tWaiter %p, time: %llu, kthread: %p (%p)\n", i,
-                      i->wake_up_time, kthread, (kthread ? kthread->proc : 0));
+               printk("\tWaiter %p, time: %llu, kthread: %p (%p) %s\n", i,
+                      i->wake_up_time, kthread, (kthread ? kthread->proc : 0),
+                      (kthread ? kthread->name : 0));
 
        }
 }
index c6b098e..06a70ba 100644 (file)
@@ -179,6 +179,30 @@ void kthread_yield(void)
        sem_down(sem);
 }
 
+static void __ktask_wrapper(uint32_t srcid, long a0, long a1, long a2)
+{
+       void (*fn)(void*) = (void (*)(void*))a0;
+       void *arg = (void*)a1;
+       char *name = (char*)a2;
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       assert(pcpui->cur_kthread->is_ktask);
+       pcpui->cur_kthread->name = name;
+       fn(arg);
+       pcpui->cur_kthread->name = 0;
+       /* if we blocked, when we return, PRKM will smp_idle() */
+}
+
+/* Creates a kernel task, running fn(arg), named "name".  This is just a routine
+ * kernel message that happens to have a name, and is allowed to block.  It
+ * won't be associated with any process.  For lack of a better place, we'll just
+ * start it on the calling core.  Caller (and/or fn) need to deal with the
+ * storage for *name. */
+void ktask(char *name, void (*fn)(void*), void *arg)
+{
+       send_kernel_message(core_id(), __ktask_wrapper, (long)fn, (long)arg,
+                           (long)name, KMSG_ROUTINE);
+}
+
 void check_poison(char *msg)
 {
 #ifdef CONFIG_KTHREAD_POISON
@@ -250,6 +274,7 @@ void sem_down(struct semaphore *sem)
                 * spare kthread, that is launching another, has is_ktask set. */
                new_kthread->is_ktask = FALSE;
                new_kthread->proc = 0;
+               new_kthread->name = 0;
        } else {
                new_kthread = __kthread_zalloc();
                new_stacktop = get_kstack();