Re: [patch 05/14] syslets: core code
On Thu, 15 Feb 2007, Ingo Molnar wrote: > + spin_lock(>lock); > + > + new_async_thread = pick_ready_cachemiss_thread(ah); > + if (!new_async_thread) > + goto out_unlock; > + > + async_ready = t->async_ready; > + WARN_ON(!async_ready); > + t->async_ready = NULL; > + > + new_task = new_async_thread->task; > + > + move_user_context(new_task, t); Since I lost the email where you were describing the todo list, I'll hook into this one. I haven't seen you mentioning it, but at least TID and signal handling need to be swapped to. So it'd be better to have a generic move_user_context() that does system independent work, and an arch_move_user_context() that takes care of system dependent stuff (that is called by move_user_context()). - Davide - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 05/14] syslets: core code
On Thu, 15 Feb 2007, Ingo Molnar wrote: + spin_lock(ah-lock); + + new_async_thread = pick_ready_cachemiss_thread(ah); + if (!new_async_thread) + goto out_unlock; + + async_ready = t-async_ready; + WARN_ON(!async_ready); + t-async_ready = NULL; + + new_task = new_async_thread-task; + + move_user_context(new_task, t); Since I lost the email where you were describing the todo list, I'll hook into this one. I haven't seen you mentioning it, but at least TID and signal handling need to be swapped to. So it'd be better to have a generic move_user_context() that does system independent work, and an arch_move_user_context() that takes care of system dependent stuff (that is called by move_user_context()). - Davide - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 05/14] syslets: core code
On Thu, Feb 15, 2007 at 05:52:28PM +0100, Ingo Molnar wrote: > From: Ingo Molnar <[EMAIL PROTECTED]> > +static struct syslet_uatom __user * > +exec_atom(struct async_head *ah, struct task_struct *t, > + struct syslet_uatom __user *uatom) > +{ > + struct syslet_uatom __user *last_uatom; > + struct syslet_atom atom; > + long ret; > + - run_next: + do { > + if (unlikely(copy_uatom(, uatom))) > + return ERR_PTR(-EFAULT); > + > + last_uatom = uatom; > + ret = __exec_atom(t, ); > + if (unlikely(signal_pending(t) || need_resched())) + break; - goto stop; > + > + uatom = next_uatom(, uatom, ret); + } while(uatom); - if (uatom) - goto run_next; - stop: > + /* > + * We do completion only in async context: > + */ > + if (t->at && complete_uatom(ah, t, , last_uatom)) > + return ERR_PTR(-EFAULT); > + > + return last_uatom; > +} Goto's are cool granted :), but IMO the "do {} while()" is more natural here. > +asmlinkage long > +sys_async_register(struct async_head_user __user *ahu, unsigned int len) > +{ > + struct task_struct *t = current; > + > + /* > + * This 'len' check enables future extension of > + * the async_head ABI: > + */ I'm not sure I understand why this isn't a '>' check. If you want to extend the ABI, you'll add members to async_head_user. So you just need to check that you understand all the information that userspace passes to you, or did I missed something? > + if (len != sizeof(struct async_head_user)) > + return -EINVAL; > + /* > + * Already registered? > + */ > + if (t->ah) > + return -EEXIST; > + > + return async_head_init(t, ahu); > +} > + Regards, Frederik - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 05/14] syslets: core code
+static void +__mark_async_thread_ready(struct async_thread *at, struct async_head *ah) +{ + list_del(>entry); + list_add_tail(>entry, >ready_async_threads); +__mark_async_thread_busy(struct async_thread *at, struct async_head *ah) +{ + list_del(>entry); + list_add_tail(>entry, >busy_async_threads); list_move_tail()? - z - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[patch 05/14] syslets: core code
From: Ingo Molnar <[EMAIL PROTECTED]> the core syslet / async system calls infrastructure code. Is built only if CONFIG_ASYNC_SUPPORT is enabled. Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]> Signed-off-by: Arjan van de Ven <[EMAIL PROTECTED]> --- kernel/Makefile |1 kernel/async.c | 897 2 files changed, 898 insertions(+) Index: linux/kernel/Makefile === --- linux.orig/kernel/Makefile +++ linux/kernel/Makefile @@ -10,6 +10,7 @@ obj-y = sched.o fork.o exec_domain.o kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o +obj-$(CONFIG_ASYNC_SUPPORT) += async.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += time/ obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o Index: linux/kernel/async.c === --- /dev/null +++ linux/kernel/async.c @@ -0,0 +1,897 @@ +/* + * kernel/async.c + * + * The syslet subsystem - asynchronous syscall execution support. + * + * Started by Ingo Molnar: + * + * Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <[EMAIL PROTECTED]> + * + * This file is released under the GPLv2. + * + * This code implements asynchronous syscalls via 'syslets'. + * + * Syslets consist of a set of 'syslet atoms' which are residing + * purely in user-space memory and have no kernel-space resource + * attached to them. These atoms can be linked to each other via + * pointers. Besides the fundamental ability to execute system + * calls, syslet atoms can also implement branches, loops and + * arithmetics. + * + * Thus syslets can be used to build small autonomous programs that + * the kernel can execute purely from kernel-space, without having + * to return to any user-space context. Syslets can be run by any + * unprivileged user-space application - they are executed safely + * by the kernel. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "async.h" + +typedef asmlinkage long (*syscall_fn_t)(long, long, long, long, long, long); + +extern syscall_fn_t sys_call_table[NR_syscalls]; + +static void +__mark_async_thread_ready(struct async_thread *at, struct async_head *ah) +{ + list_del(>entry); + list_add_tail(>entry, >ready_async_threads); + if (list_empty(>busy_async_threads)) + wake_up(>wait); +} + +static void +mark_async_thread_ready(struct async_thread *at, struct async_head *ah) +{ + spin_lock(>lock); + __mark_async_thread_ready(at, ah); + spin_unlock(>lock); +} + +static void +__mark_async_thread_busy(struct async_thread *at, struct async_head *ah) +{ + list_del(>entry); + list_add_tail(>entry, >busy_async_threads); +} + +static void +mark_async_thread_busy(struct async_thread *at, struct async_head *ah) +{ + spin_lock(>lock); + __mark_async_thread_busy(at, ah); + spin_unlock(>lock); +} + +static void +__async_thread_init(struct task_struct *t, struct async_thread *at, + struct async_head *ah) +{ + INIT_LIST_HEAD(>entry); + at->exit = 0; + at->task = t; + at->ah = ah; + at->work = NULL; + + t->at = at; + ah->nr_threads++; +} + +static void +async_thread_init(struct task_struct *t, struct async_thread *at, + struct async_head *ah) +{ + spin_lock(>lock); + __async_thread_init(t, at, ah); + __mark_async_thread_ready(at, ah); + spin_unlock(>lock); +} + + +static void +async_thread_exit(struct async_thread *at, struct task_struct *t) +{ + struct async_head *ah = at->ah; + + spin_lock(>lock); + list_del_init(>entry); + if (at->exit) + complete(>exit_done); + t->at = NULL; + at->task = NULL; + WARN_ON(!ah->nr_threads); + ah->nr_threads--; + spin_unlock(>lock); +} + +static struct async_thread * +pick_ready_cachemiss_thread(struct async_head *ah) +{ + struct list_head *head = >ready_async_threads; + struct async_thread *at; + + if (list_empty(head)) + return NULL; + + at = list_entry(head->next, struct async_thread, entry); + + return at; +} + +void __async_schedule(struct task_struct *t) +{ + struct async_thread *new_async_thread; + struct async_thread *async_ready; + struct async_head *ah = t->ah; + struct task_struct *new_task; + + spin_lock(>lock); + + new_async_thread = pick_ready_cachemiss_thread(ah); + if (!new_async_thread) + goto out_unlock; + + async_ready = t->async_ready; + WARN_ON(!async_ready); + t->async_ready = NULL; + + new_task = new_async_thread->task; + + move_user_context(new_task, t); + + new_task->at = NULL; + t->ah = NULL; + new_task->ah = ah; + +
[patch 05/14] syslets: core code
From: Ingo Molnar [EMAIL PROTECTED] the core syslet / async system calls infrastructure code. Is built only if CONFIG_ASYNC_SUPPORT is enabled. Signed-off-by: Ingo Molnar [EMAIL PROTECTED] Signed-off-by: Arjan van de Ven [EMAIL PROTECTED] --- kernel/Makefile |1 kernel/async.c | 897 2 files changed, 898 insertions(+) Index: linux/kernel/Makefile === --- linux.orig/kernel/Makefile +++ linux/kernel/Makefile @@ -10,6 +10,7 @@ obj-y = sched.o fork.o exec_domain.o kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o +obj-$(CONFIG_ASYNC_SUPPORT) += async.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += time/ obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o Index: linux/kernel/async.c === --- /dev/null +++ linux/kernel/async.c @@ -0,0 +1,897 @@ +/* + * kernel/async.c + * + * The syslet subsystem - asynchronous syscall execution support. + * + * Started by Ingo Molnar: + * + * Copyright (C) 2007 Red Hat, Inc., Ingo Molnar [EMAIL PROTECTED] + * + * This file is released under the GPLv2. + * + * This code implements asynchronous syscalls via 'syslets'. + * + * Syslets consist of a set of 'syslet atoms' which are residing + * purely in user-space memory and have no kernel-space resource + * attached to them. These atoms can be linked to each other via + * pointers. Besides the fundamental ability to execute system + * calls, syslet atoms can also implement branches, loops and + * arithmetics. + * + * Thus syslets can be used to build small autonomous programs that + * the kernel can execute purely from kernel-space, without having + * to return to any user-space context. Syslets can be run by any + * unprivileged user-space application - they are executed safely + * by the kernel. + */ +#include linux/syscalls.h +#include linux/syslet.h +#include linux/delay.h +#include linux/async.h +#include linux/sched.h +#include linux/init.h +#include linux/err.h + +#include asm/uaccess.h +#include asm/unistd.h + +#include async.h + +typedef asmlinkage long (*syscall_fn_t)(long, long, long, long, long, long); + +extern syscall_fn_t sys_call_table[NR_syscalls]; + +static void +__mark_async_thread_ready(struct async_thread *at, struct async_head *ah) +{ + list_del(at-entry); + list_add_tail(at-entry, ah-ready_async_threads); + if (list_empty(ah-busy_async_threads)) + wake_up(ah-wait); +} + +static void +mark_async_thread_ready(struct async_thread *at, struct async_head *ah) +{ + spin_lock(ah-lock); + __mark_async_thread_ready(at, ah); + spin_unlock(ah-lock); +} + +static void +__mark_async_thread_busy(struct async_thread *at, struct async_head *ah) +{ + list_del(at-entry); + list_add_tail(at-entry, ah-busy_async_threads); +} + +static void +mark_async_thread_busy(struct async_thread *at, struct async_head *ah) +{ + spin_lock(ah-lock); + __mark_async_thread_busy(at, ah); + spin_unlock(ah-lock); +} + +static void +__async_thread_init(struct task_struct *t, struct async_thread *at, + struct async_head *ah) +{ + INIT_LIST_HEAD(at-entry); + at-exit = 0; + at-task = t; + at-ah = ah; + at-work = NULL; + + t-at = at; + ah-nr_threads++; +} + +static void +async_thread_init(struct task_struct *t, struct async_thread *at, + struct async_head *ah) +{ + spin_lock(ah-lock); + __async_thread_init(t, at, ah); + __mark_async_thread_ready(at, ah); + spin_unlock(ah-lock); +} + + +static void +async_thread_exit(struct async_thread *at, struct task_struct *t) +{ + struct async_head *ah = at-ah; + + spin_lock(ah-lock); + list_del_init(at-entry); + if (at-exit) + complete(ah-exit_done); + t-at = NULL; + at-task = NULL; + WARN_ON(!ah-nr_threads); + ah-nr_threads--; + spin_unlock(ah-lock); +} + +static struct async_thread * +pick_ready_cachemiss_thread(struct async_head *ah) +{ + struct list_head *head = ah-ready_async_threads; + struct async_thread *at; + + if (list_empty(head)) + return NULL; + + at = list_entry(head-next, struct async_thread, entry); + + return at; +} + +void __async_schedule(struct task_struct *t) +{ + struct async_thread *new_async_thread; + struct async_thread *async_ready; + struct async_head *ah = t-ah; + struct task_struct *new_task; + + spin_lock(ah-lock); + + new_async_thread = pick_ready_cachemiss_thread(ah); + if (!new_async_thread) + goto out_unlock; + + async_ready = t-async_ready; + WARN_ON(!async_ready); + t-async_ready = NULL; + + new_task = new_async_thread-task; + +
Re: [patch 05/14] syslets: core code
+static void +__mark_async_thread_ready(struct async_thread *at, struct async_head *ah) +{ + list_del(at-entry); + list_add_tail(at-entry, ah-ready_async_threads); +__mark_async_thread_busy(struct async_thread *at, struct async_head *ah) +{ + list_del(at-entry); + list_add_tail(at-entry, ah-busy_async_threads); list_move_tail()? - z - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 05/14] syslets: core code
On Thu, Feb 15, 2007 at 05:52:28PM +0100, Ingo Molnar wrote: From: Ingo Molnar [EMAIL PROTECTED] +static struct syslet_uatom __user * +exec_atom(struct async_head *ah, struct task_struct *t, + struct syslet_uatom __user *uatom) +{ + struct syslet_uatom __user *last_uatom; + struct syslet_atom atom; + long ret; + - run_next: + do { + if (unlikely(copy_uatom(atom, uatom))) + return ERR_PTR(-EFAULT); + + last_uatom = uatom; + ret = __exec_atom(t, atom); + if (unlikely(signal_pending(t) || need_resched())) + break; - goto stop; + + uatom = next_uatom(atom, uatom, ret); + } while(uatom); - if (uatom) - goto run_next; - stop: + /* + * We do completion only in async context: + */ + if (t-at complete_uatom(ah, t, atom, last_uatom)) + return ERR_PTR(-EFAULT); + + return last_uatom; +} Goto's are cool granted :), but IMO the do {} while() is more natural here. +asmlinkage long +sys_async_register(struct async_head_user __user *ahu, unsigned int len) +{ + struct task_struct *t = current; + + /* + * This 'len' check enables future extension of + * the async_head ABI: + */ I'm not sure I understand why this isn't a '' check. If you want to extend the ABI, you'll add members to async_head_user. So you just need to check that you understand all the information that userspace passes to you, or did I missed something? + if (len != sizeof(struct async_head_user)) + return -EINVAL; + /* + * Already registered? + */ + if (t-ah) + return -EEXIST; + + return async_head_init(t, ahu); +} + Regards, Frederik - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/