From: Ingo Molnar <mingo@elte.hu>
To: linux-kernel@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
Arjan van de Ven <arjan@infradead.org>,
Christoph Hellwig <hch@infradead.org>,
Andrew Morton <akpm@zip.com.au>,
Alan Cox <alan@lxorguk.ukuu.org.uk>,
Ulrich Drepper <drepper@redhat.com>,
Zach Brown <zach.brown@oracle.com>,
Evgeniy Polyakov <johnpol@2ka.mipt.ru>,
"David S. Miller" <davem@davemloft.net>,
Suparna Bhattacharya <suparna@in.ibm.com>,
Davide Libenzi <davidel@xmailserver.org>,
Jens Axboe <jens.axboe@oracle.com>,
Thomas Gleixner <tglx@linutronix.de>
Subject: [patch 04/13] syslets: core code
Date: Wed, 21 Feb 2007 22:15:16 +0100 [thread overview]
Message-ID: <20070221211516.GD7579@elte.hu> (raw)
In-Reply-To: <20070221211355.GA7302@elte.hu>
From: Ingo Molnar <mingo@elte.hu>
the core syslet / async system calls infrastructure code.
Is built only if CONFIG_ASYNC_SUPPORT is enabled.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
kernel/Makefile | 1
kernel/async.c | 958 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 959 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,958 @@
+/*
+ * kernel/async.c
+ *
+ * The syslet and threadlet subsystem - asynchronous syscall and user-space
+ * code execution support.
+ *
+ * Started by Ingo Molnar:
+ *
+ * Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * 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.
+ *
+ * "Threadlets" are the user-space equivalent of syslets: small
+ * functions of execution that the kernel attempts to execute
+ * without scheduling. If the threadlet blocks, the kernel creates
+ * a real thread from it, and execution continues in that thread.
+ * The 'head' context (the context that never blocks) returns to
+ * the original function that called the threadlet.
+ */
+#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>
+
+typedef asmlinkage long (*syscall_fn_t)(long, long, long, long, long, long);
+
+extern syscall_fn_t sys_call_table[NR_syscalls];
+
+/*
+ * An async 'cachemiss context' is either busy, or it is ready.
+ * If it is ready, the 'head' might switch its user-space context
+ * to that ready thread anytime - so that if the ex-head blocks,
+ * one ready thread can become the next head and can continue to
+ * execute user-space 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);
+ 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;
+}
+
+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;
+ spin_unlock(&ah->lock);
+}
+
+static struct async_thread *
+pick_ready_cachemiss_thread(struct async_head *ah)
+{
+ struct list_head *head = &ah->ready_async_threads;
+
+ if (list_empty(head))
+ return NULL;
+
+ return list_entry(head->next, struct async_thread, entry);
+}
+
+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;
+
+ WARN_ON(!ah);
+ 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);
+ if (ah->restore_stack) {
+ task_pt_regs(new_task)->esp = ah->restore_stack;
+ WARN_ON(!ah->restore_eip);
+ task_pt_regs(new_task)->eip = ah->restore_eip;
+ /*
+ * The return code 0 is needed to tell the
+ * head user-context that the threadlet went async:
+ */
+ task_pt_regs(new_task)->eax = 0;
+ }
+
+ new_task->at = NULL;
+ t->ah = NULL;
+ new_task->ah = ah;
+ ah->user_task = new_task;
+
+ wake_up_process(new_task);
+
+ __async_thread_init(t, async_ready, ah);
+ __mark_async_thread_busy(t->at, ah);
+
+ out_unlock:
+ spin_unlock(&ah->lock);
+}
+
+static void async_schedule(struct task_struct *t)
+{
+ if (t->async_ready)
+ __async_schedule(t);
+}
+
+static long __exec_atom(struct task_struct *t, struct syslet_atom *atom)
+{
+ struct async_thread *async_ready_save;
+ long ret;
+
+ /*
+ * If user-space expects the syscall to schedule then
+ * (try to) switch user-space to another thread straight
+ * away and execute the syscall asynchronously:
+ */
+ if (unlikely(atom->flags & SYSLET_ASYNC))
+ async_schedule(t);
+ /*
+ * Does user-space want synchronous execution for this atom?:
+ */
+ async_ready_save = t->async_ready;
+ if (unlikely(atom->flags & SYSLET_SYNC))
+ t->async_ready = NULL;
+
+ if (unlikely(atom->nr >= NR_syscalls))
+ return -ENOSYS;
+
+ ret = sys_call_table[atom->nr](atom->args[0], atom->args[1],
+ atom->args[2], atom->args[3],
+ atom->args[4], atom->args[5]);
+
+ if (atom->ret_ptr && put_user(ret, atom->ret_ptr))
+ return -EFAULT;
+
+ if (t->ah)
+ t->async_ready = async_ready_save;
+
+ return ret;
+}
+
+/*
+ * Arithmetics syscall, add a value to a user-space memory location.
+ *
+ * Generic C version - in case the architecture has not implemented it
+ * in assembly.
+ */
+asmlinkage __attribute__((weak)) long
+sys_umem_add(unsigned long __user *uptr, unsigned long inc)
+{
+ unsigned long val, new_val;
+
+ if (get_user(val, uptr))
+ return -EFAULT;
+ /*
+ * inc == 0 means 'read memory value':
+ */
+ if (!inc)
+ return val;
+
+ new_val = val + inc;
+ if (__put_user(new_val, uptr))
+ return -EFAULT;
+
+ return new_val;
+}
+
+/*
+ * Open-coded because this is a very hot codepath during syslet
+ * execution and every cycle counts ...
+ *
+ * [ NOTE: it's an explicit fastcall because optimized assembly code
+ * might depend on this. There are some kernels that disable regparm,
+ * so lets not break those if possible. ]
+ */
+fastcall __attribute__((weak)) long
+copy_uatom(struct syslet_atom *atom, struct syslet_uatom __user *uatom)
+{
+ unsigned long __user *arg_ptr;
+ long ret = 0;
+
+ if (!access_ok(VERIFY_READ, uatom, sizeof(*uatom)))
+ return -EFAULT;
+
+ ret = __get_user(atom->nr, &uatom->nr);
+ ret |= __get_user(atom->ret_ptr, &uatom->ret_ptr);
+ ret |= __get_user(atom->flags, &uatom->flags);
+ ret |= __get_user(atom->next, &uatom->next);
+
+ memset(atom->args, 0, sizeof(atom->args));
+
+ ret |= __get_user(arg_ptr, &uatom->arg_ptr[0]);
+ if (!arg_ptr)
+ return ret;
+ if (!access_ok(VERIFY_READ, arg_ptr, sizeof(*arg_ptr)))
+ return -EFAULT;
+ ret |= __get_user(atom->args[0], arg_ptr);
+
+ ret |= __get_user(arg_ptr, &uatom->arg_ptr[1]);
+ if (!arg_ptr)
+ return ret;
+ if (!access_ok(VERIFY_READ, arg_ptr, sizeof(*arg_ptr)))
+ return -EFAULT;
+ ret |= __get_user(atom->args[1], arg_ptr);
+
+ ret |= __get_user(arg_ptr, &uatom->arg_ptr[2]);
+ if (!arg_ptr)
+ return ret;
+ if (!access_ok(VERIFY_READ, arg_ptr, sizeof(*arg_ptr)))
+ return -EFAULT;
+ ret |= __get_user(atom->args[2], arg_ptr);
+
+ ret |= __get_user(arg_ptr, &uatom->arg_ptr[3]);
+ if (!arg_ptr)
+ return ret;
+ if (!access_ok(VERIFY_READ, arg_ptr, sizeof(*arg_ptr)))
+ return -EFAULT;
+ ret |= __get_user(atom->args[3], arg_ptr);
+
+ ret |= __get_user(arg_ptr, &uatom->arg_ptr[4]);
+ if (!arg_ptr)
+ return ret;
+ if (!access_ok(VERIFY_READ, arg_ptr, sizeof(*arg_ptr)))
+ return -EFAULT;
+ ret |= __get_user(atom->args[4], arg_ptr);
+
+ ret |= __get_user(arg_ptr, &uatom->arg_ptr[5]);
+ if (!arg_ptr)
+ return ret;
+ if (!access_ok(VERIFY_READ, arg_ptr, sizeof(*arg_ptr)))
+ return -EFAULT;
+ ret |= __get_user(atom->args[5], arg_ptr);
+
+ return ret;
+}
+
+/*
+ * Should the next atom run, depending on the return value of
+ * the current atom - or should we stop execution?
+ */
+static int run_next_atom(struct syslet_atom *atom, long ret)
+{
+ switch (atom->flags & SYSLET_STOP_MASK) {
+ case SYSLET_STOP_ON_NONZERO:
+ if (!ret)
+ return 1;
+ return 0;
+ case SYSLET_STOP_ON_ZERO:
+ if (ret)
+ return 1;
+ return 0;
+ case SYSLET_STOP_ON_NEGATIVE:
+ if (ret >= 0)
+ return 1;
+ return 0;
+ case SYSLET_STOP_ON_NON_POSITIVE:
+ if (ret > 0)
+ return 1;
+ return 0;
+ }
+ return 1;
+}
+
+static struct syslet_uatom __user *
+next_uatom(struct syslet_atom *atom, struct syslet_uatom *uatom, long ret)
+{
+ /*
+ * If the stop condition is false then continue
+ * to atom->next:
+ */
+ if (run_next_atom(atom, ret))
+ return atom->next;
+ /*
+ * Special-case: if the stop condition is true and the atom
+ * has SKIP_TO_NEXT_ON_STOP set, then instead of
+ * stopping we skip to the atom directly after this atom
+ * (in linear address-space).
+ *
+ * This, combined with the atom->next pointer and the
+ * stop condition flags is what allows true branches and
+ * loops in syslets:
+ */
+ if (atom->flags & SYSLET_SKIP_TO_NEXT_ON_STOP)
+ return uatom + 1;
+
+ return NULL;
+}
+
+/*
+ * If user-space requested a completion event then put the last
+ * executed uatom into the completion ring:
+ */
+static long
+complete_uatom(struct async_head *ah, struct task_struct *t,
+ struct syslet_atom *atom, struct syslet_uatom __user *uatom,
+ struct async_head_user __user *ahu)
+{
+ unsigned long ring_size_bytes, max_ring_idx, kernel_ring_idx;
+ struct syslet_uatom __user **ring_slot, *slot_val = NULL;
+ struct syslet_uatom __user **completion_ring;
+
+ WARN_ON(!t->at);
+ WARN_ON(t->ah);
+
+ if (atom->flags & SYSLET_NO_COMPLETE)
+ return 0;
+
+ if (!access_ok(VERIFY_WRITE, ahu, sizeof(*ahu)))
+ return -EFAULT;
+
+ if (__get_user(completion_ring, &ahu->completion_ring))
+ return -EFAULT;
+ if (__get_user(ring_size_bytes, &ahu->ring_size_bytes))
+ return -EFAULT;
+ if (!ring_size_bytes)
+ return -EINVAL;
+
+ max_ring_idx = ring_size_bytes / sizeof(void *);
+ if (ring_size_bytes != max_ring_idx * sizeof(void *))
+ return -EINVAL;
+ /*
+ * We pre-check the ring pointer, so that in the fastpath
+ * we can use __get_user():
+ */
+ if (!access_ok(VERIFY_WRITE, completion_ring, ring_size_bytes))
+ return -EFAULT;
+
+ mutex_lock(&ah->completion_lock);
+ /*
+ * Asynchron threads can complete in parallel so use the
+ * head-lock to serialize:
+ */
+ if (__get_user(kernel_ring_idx, &ahu->kernel_ring_idx))
+ goto fault_unlock;
+ if (kernel_ring_idx >= max_ring_idx)
+ goto err_unlock;
+
+ ring_slot = completion_ring + kernel_ring_idx;
+ if (__get_user(slot_val, ring_slot))
+ goto fault_unlock;
+ /*
+ * User-space submitted more work than what fits into the
+ * completion ring - do not stomp over it silently and signal
+ * the error condition:
+ */
+ if (slot_val)
+ goto err_unlock;
+
+ slot_val = uatom;
+ if (__put_user(slot_val, ring_slot))
+ goto fault_unlock;
+ /*
+ * Update the ring index:
+ */
+ kernel_ring_idx++;
+ if (kernel_ring_idx == max_ring_idx)
+ kernel_ring_idx = 0;
+
+ if (__put_user(kernel_ring_idx, &ahu->kernel_ring_idx))
+ goto fault_unlock;
+
+ /*
+ * See whether the async-head is waiting and needs a wakeup:
+ */
+ if (ah->events_left) {
+ if (!--ah->events_left) {
+ /*
+ * We first unlock the mutex - to reduce the size
+ * of the critical section. We have a safe
+ * reference to 'ah':
+ */
+ mutex_unlock(&ah->completion_lock);
+ wake_up(&ah->wait);
+ goto out;
+ }
+ }
+
+ mutex_unlock(&ah->completion_lock);
+ out:
+ return 0;
+
+ fault_unlock:
+ mutex_unlock(&ah->completion_lock);
+
+ return -EFAULT;
+
+ err_unlock:
+ mutex_unlock(&ah->completion_lock);
+
+ return -EINVAL;
+}
+
+/*
+ * This is the main syslet atom execution loop. This fetches atoms
+ * and executes them until it runs out of atoms or until the
+ * exit condition becomes false:
+ */
+static struct syslet_uatom __user *
+exec_atom(struct async_head *ah, struct task_struct *t,
+ struct syslet_uatom __user *uatom,
+ struct async_head_user __user *ahu)
+{
+ struct syslet_uatom __user *last_uatom;
+ struct syslet_atom atom;
+ long ret;
+
+ run_next:
+ 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()))
+ goto stop;
+
+ uatom = next_uatom(&atom, uatom, ret);
+ if (uatom)
+ goto run_next;
+ stop:
+ /*
+ * We do completion only in async context:
+ */
+ if (t->at && complete_uatom(ah, t, &atom, last_uatom, ahu))
+ return ERR_PTR(-EFAULT);
+
+ return last_uatom;
+}
+
+static void cachemiss_execute(struct async_thread *at, struct async_head *ah,
+ struct task_struct *t)
+{
+ struct syslet_uatom __user *uatom;
+
+ uatom = at->work;
+ WARN_ON(!uatom);
+ at->work = NULL;
+ WARN_ON(1); /* need to pass the ahu too */
+
+ exec_atom(ah, t, uatom, NULL);
+}
+
+static struct syslet_uatom __user *
+cachemiss_loop(struct async_thread *at, struct async_head *ah,
+ struct task_struct *t)
+{
+ for (;;) {
+ mark_async_thread_busy(at, ah);
+ set_task_state(t, TASK_INTERRUPTIBLE);
+ if (at->work)
+ cachemiss_execute(at, ah, t);
+ if (unlikely(t->ah || at->exit || signal_pending(t)))
+ break;
+ mark_async_thread_ready(at, ah);
+ schedule();
+ }
+ t->state = TASK_RUNNING;
+
+ async_thread_exit(at, t);
+
+ if (at->exit)
+ do_exit(0);
+
+ if (!t->ah) {
+ /*
+ * Cachemiss threads return to one given
+ * user-space instruction address and stack
+ * pointer:
+ */
+ task_pt_regs(t)->esp = at->user_stack;
+ task_pt_regs(t)->eip = at->user_eip;
+
+ return (void *)-1;
+ }
+ /*
+ * Head context: return to user-space with NULL:
+ */
+ return NULL;
+}
+
+/*
+ * This is what a newly created cachemiss thread executes for the
+ * first time: initialize, pick up the user stack/IP addresses from
+ * the head and then execute the cachemiss loop. If the cachemiss
+ * loop returns then we return back to user-space:
+ */
+static int cachemiss_thread(void *data)
+{
+ struct pt_regs *head_regs, *regs;
+ struct task_struct *t = current;
+ struct async_head *ah = data;
+ struct async_thread *at;
+ int ret;
+
+ at = &t->__at;
+ async_thread_init(t, at, ah);
+
+ /*
+ * Clone the head thread's user-space ptregs over,
+ * now that we are in kernel-space:
+ */
+ head_regs = task_pt_regs(ah->user_task);
+ regs = task_pt_regs(t);
+
+ *regs = *head_regs;
+ ret = get_user(at->user_stack, ah->new_stackp);
+ WARN_ON(ret);
+ /*
+ * Clear the stack pointer, signalling to user-space that
+ * this thread stack has been used up:
+ */
+ ret = put_user(0, ah->new_stackp);
+ WARN_ON(ret);
+
+ complete(&ah->start_done);
+
+ /*
+ * Fixme: 64-bit kernel threads should return long
+ */
+ return (int)cachemiss_loop(at, ah, t);
+}
+
+/**
+ * sys_async_thread - do work as an async cachemiss thread again
+ *
+ * If an async thread has returned back to user-space (due to say
+ * a signal) then it is a 'busy' thread during that period. It
+ * can again offer itself into the cachemiss pool by calling this
+ * syscall:
+ */
+asmlinkage long sys_async_thread(void)
+{
+ struct task_struct *t = current;
+ struct async_thread *at = t->at;
+ struct async_head *ah = t->__at.ah;
+
+ /*
+ * Only async threads are allowed to do this:
+ */
+ if (!ah || t->ah)
+ return -EINVAL;
+
+ /*
+ * If a cachemiss threadlet calls sys_async_thread()
+ * then we first have to mark it ready:
+ */
+ if (at) {
+ mark_async_thread_ready(at, ah);
+ } else {
+ at = &t->__at;
+ WARN_ON(!at->ah);
+
+ async_thread_init(t, at, ah);
+ }
+
+ return (long)cachemiss_loop(at, at->ah, t);
+}
+
+/*
+ * Initialize the in-kernel async head, based on the user-space async
+ * head:
+ */
+static long
+async_head_init(struct task_struct *t, struct async_head_user __user *ahu)
+{
+ struct async_head *ah;
+
+ ah = &t->__ah;
+
+ spin_lock_init(&ah->lock);
+ INIT_LIST_HEAD(&ah->ready_async_threads);
+ INIT_LIST_HEAD(&ah->busy_async_threads);
+ init_waitqueue_head(&ah->wait);
+ mutex_init(&ah->completion_lock);
+ ah->events_left = 0;
+ ah->ahu = NULL;
+ ah->new_stackp = NULL;
+ ah->new_eip = 0;
+ ah->restore_stack = 0;
+ ah->restore_eip = 0;
+ ah->user_task = t;
+ t->ah = ah;
+
+ return 0;
+}
+
+/*
+ * If the head cache-misses then it will become a cachemiss
+ * thread after having finished its current syslet. If it
+ * returns to user-space after that point (to handle a signal
+ * for example) then it will need a thread stack of its own:
+ */
+static long init_head(struct async_head *ah, struct task_struct *t,
+ struct async_head_user __user *ahu)
+{
+ unsigned long head_stack, head_eip;
+
+ if (get_user(head_stack, &ahu->head_stack))
+ return -EFAULT;
+ if (get_user(head_eip, &ahu->head_eip))
+ return -EFAULT;
+ t->__at.user_stack = head_stack;
+ t->__at.user_eip = head_eip;
+
+ return async_head_init(t, ahu);
+}
+
+/*
+ * Simple limit and pool management mechanism for now:
+ */
+static long
+refill_cachemiss_pool(struct async_head *ah, struct task_struct *t,
+ struct async_head_user __user *ahu)
+{
+ unsigned long new_eip;
+ long pid, ret;
+
+ init_completion(&ah->start_done);
+ ah->new_stackp = &ahu->new_thread_stack;
+ ret = get_user(new_eip, &ahu->new_thread_eip);
+ WARN_ON(ret);
+ ah->new_eip = new_eip;
+
+ pid = create_async_thread(cachemiss_thread, (void *)ah,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_THREAD | CLONE_SYSVSEM);
+ if (pid < 0)
+ return pid;
+
+ wait_for_completion(&ah->start_done);
+ ah->new_stackp = NULL;
+ ah->new_eip = 0;
+
+ return 0;
+}
+
+/**
+ * sys_async_exec - execute a syslet.
+ *
+ * returns the uatom that was last executed, if the kernel was able to
+ * execute the syslet synchronously, or NULL if the syslet became
+ * asynchronous. (in the latter case syslet completion will be notified
+ * via the completion ring)
+ *
+ * (Various errors might also be returned via the usual negative numbers.)
+ */
+asmlinkage struct syslet_uatom __user *
+sys_async_exec(struct syslet_uatom __user *uatom,
+ struct async_head_user __user *ahu)
+{
+ struct syslet_uatom __user *ret;
+ struct task_struct *t = current;
+ struct async_head *ah = t->ah;
+ struct async_thread *at = &t->__at;
+
+ /*
+ * Do not allow recursive calls of sys_async_exec():
+ */
+ if (async_syscall(t))
+ return ERR_PTR(-ENOSYS);
+
+ if (unlikely(!ah)) {
+ ret = (void *)init_head(ah, t, ahu);
+ if (ret)
+ return ret;
+ ah = t->ah;
+ }
+
+ if (unlikely(list_empty(&ah->ready_async_threads))) {
+ ret = (void *)refill_cachemiss_pool(ah, t, ahu);
+ if (ret)
+ return ret;
+ }
+
+ t->async_ready = at;
+ ah->ahu = ahu;
+
+ ret = exec_atom(ah, t, uatom, ahu);
+
+ /*
+ * Are we still executing as head?
+ */
+ if (t->ah) {
+ t->async_ready = NULL;
+
+ return ret;
+ }
+
+ /*
+ * We got turned into a cachemiss thread,
+ * enter the cachemiss loop:
+ */
+ set_task_state(t, TASK_INTERRUPTIBLE);
+ mark_async_thread_ready(at, ah);
+
+ return cachemiss_loop(at, ah, t);
+}
+
+/**
+ * sys_async_wait - wait for async completion events
+ *
+ * This syscall waits for @min_wait_events syslet completion events
+ * to finish or for all async processing to finish (whichever
+ * comes first).
+ */
+asmlinkage long
+sys_async_wait(unsigned long min_wait_events, unsigned long user_ring_idx,
+ struct async_head_user __user *ahu)
+{
+ struct task_struct *t = current;
+ struct async_head *ah = t->ah;
+ unsigned long kernel_ring_idx;
+
+ /*
+ * Do not allow async waiting:
+ */
+ if (async_syscall(t))
+ return -ENOSYS;
+ if (!ah)
+ return -EINVAL;
+
+ mutex_lock(&ah->completion_lock);
+ if (get_user(kernel_ring_idx, &ahu->kernel_ring_idx))
+ goto err_unlock;
+ /*
+ * Account any completions that happened since user-space
+ * checked the ring:
+ */
+ ah->events_left = min_wait_events - (kernel_ring_idx - user_ring_idx);
+ mutex_unlock(&ah->completion_lock);
+
+ return wait_event_interruptible(ah->wait,
+ list_empty(&ah->busy_async_threads) || ah->events_left <= 0);
+
+ err_unlock:
+ mutex_unlock(&ah->completion_lock);
+ return -EFAULT;
+}
+
+asmlinkage long
+sys_threadlet_on(unsigned long restore_stack,
+ unsigned long restore_eip,
+ struct async_head_user __user *ahu)
+{
+ struct task_struct *t = current;
+ struct async_head *ah = t->ah;
+ struct async_thread *at = &t->__at;
+ long ret;
+
+ /*
+ * Do not allow recursive calls of sys_threadlet_on():
+ */
+ if (t->async_ready || t->at)
+ return -EINVAL;
+
+ if (unlikely(!ah)) {
+ ret = init_head(ah, t, ahu);
+ if (ret)
+ return ret;
+ ah = t->ah;
+ }
+
+ if (unlikely(list_empty(&ah->ready_async_threads))) {
+ ret = refill_cachemiss_pool(ah, t, ahu);
+ if (ret)
+ return ret;
+ }
+
+ t->async_ready = at;
+ ah->restore_stack = restore_stack;
+ ah->restore_eip = restore_eip;
+
+ ah->ahu = ahu;
+
+ return 0;
+}
+
+asmlinkage long sys_threadlet_off(void)
+{
+ struct task_struct *t = current;
+ struct async_head *ah = t->ah;
+
+ /*
+ * Are we still executing as head?
+ */
+ if (ah) {
+ t->async_ready = NULL;
+
+ return 1;
+ }
+
+ /*
+ * We got turned into a cachemiss thread,
+ * return to user-space, which can do
+ * the notification, etc:
+ */
+ return 0;
+}
+
+static void __notify_async_thread_exit(struct async_thread *at,
+ struct async_head *ah)
+{
+ list_del_init(&at->entry);
+ at->exit = 1;
+ init_completion(&ah->exit_done);
+ wake_up_process(at->task);
+}
+
+static void stop_cachemiss_threads(struct async_head *ah)
+{
+ struct async_thread *at;
+
+repeat:
+ spin_lock(&ah->lock);
+ list_for_each_entry(at, &ah->ready_async_threads, entry) {
+
+ __notify_async_thread_exit(at, ah);
+ spin_unlock(&ah->lock);
+
+ wait_for_completion(&ah->exit_done);
+
+ goto repeat;
+ }
+
+ list_for_each_entry(at, &ah->busy_async_threads, entry) {
+
+ __notify_async_thread_exit(at, ah);
+ spin_unlock(&ah->lock);
+
+ wait_for_completion(&ah->exit_done);
+
+ goto repeat;
+ }
+ spin_unlock(&ah->lock);
+}
+
+static void async_head_exit(struct async_head *ah, struct task_struct *t)
+{
+ stop_cachemiss_threads(ah);
+ WARN_ON(!list_empty(&ah->ready_async_threads));
+ WARN_ON(!list_empty(&ah->busy_async_threads));
+ WARN_ON(spin_is_locked(&ah->lock));
+
+ t->ah = NULL;
+}
+
+/*
+ * fork()-time initialization:
+ */
+void async_init(struct task_struct *t)
+{
+ t->at = NULL;
+ t->async_ready = NULL;
+ t->ah = NULL;
+ t->__at.ah = NULL;
+}
+
+/*
+ * do_exit()-time cleanup:
+ */
+void async_exit(struct task_struct *t)
+{
+ struct async_thread *at = t->at;
+ struct async_head *ah = t->ah;
+
+ /*
+ * If head does a sys_exit() then the final schedule() must
+ * not be passed on to another cachemiss thread:
+ */
+ t->async_ready = NULL;
+
+ if (unlikely(at))
+ async_thread_exit(at, t);
+
+ if (unlikely(ah))
+ async_head_exit(ah, t);
+}
next prev parent reply other threads:[~2007-02-21 21:21 UTC|newest]
Thread overview: 337+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-21 21:13 [patch 00/13] Syslets, "Threadlets", generic AIO support, v3 Ingo Molnar
2007-02-21 21:14 ` [patch 01/13] syslets: add async.h include file, kernel-side API definitions Ingo Molnar
2007-02-21 21:15 ` [patch 02/13] syslets: add syslet.h include file, user API/ABI definitions Ingo Molnar
2007-02-21 21:15 ` [patch 03/13] syslets: generic kernel bits Ingo Molnar
2007-02-21 21:15 ` Ingo Molnar [this message]
2007-02-23 23:08 ` [patch 04/13] syslets: core code Davide Libenzi
2007-02-24 7:04 ` Ingo Molnar
2007-02-24 21:10 ` Davide Libenzi
2007-02-24 22:08 ` Kyle Moffett
2007-02-24 22:25 ` Davide Libenzi
2007-02-25 7:59 ` Ingo Molnar
2007-02-21 21:15 ` [patch 05/13] syslets: core, documentation Ingo Molnar
2007-02-26 21:32 ` Randy Dunlap
2007-02-27 6:20 ` Ingo Molnar
2007-02-21 21:15 ` [patch 06/13] x86: split FPU state from task state Ingo Molnar
2007-02-21 21:15 ` [patch 07/13] syslets: x86, add create_async_thread() method Ingo Molnar
2007-02-21 21:15 ` [patch 08/13] syslets: x86, add move_user_context() method Ingo Molnar
2007-02-21 23:03 ` Davide Libenzi
2007-02-21 23:20 ` Ingo Molnar
2007-02-22 4:10 ` Davide Libenzi
2007-02-21 21:15 ` [patch 09/13] syslets: x86, mark async unsafe syscalls Ingo Molnar
2007-02-21 21:15 ` [patch 10/13] syslets: x86: enable ASYNC_SUPPORT Ingo Molnar
2007-02-21 21:15 ` [patch 11/13] syslets: x86, wire up the syslet system calls Ingo Molnar
2007-02-21 21:15 ` [patch 12/13] syslets: x86: optimized copy_uatom() Ingo Molnar
2007-02-21 21:16 ` [patch 13/13] syslets: x86: optimized sys_umem_add() Ingo Molnar
2007-02-21 22:46 ` [patch 00/13] Syslets, "Threadlets", generic AIO support, v3 Michael K. Edwards
2007-02-21 22:57 ` Ingo Molnar
2007-02-22 0:53 ` Michael K. Edwards
2007-02-22 1:33 ` Michael K. Edwards
2007-02-22 6:51 ` Ingo Molnar
2007-02-22 8:59 ` Michael K. Edwards
2007-02-22 19:52 ` x86 hardware and transputers (Re: [patch 00/13] Syslets, "Threadlets", generic AIO support, v3) Oleg Verych
2007-02-22 20:45 ` Michael K. Edwards
2007-02-21 23:03 ` [patch 00/13] Syslets, "Threadlets", generic AIO support, v3 Ingo Molnar
2007-02-21 23:24 ` Ingo Molnar
2007-02-22 0:55 ` Michael K. Edwards
2007-02-21 23:31 ` Ingo Molnar
2007-02-21 23:46 ` Ulrich Drepper
2007-02-22 7:40 ` Ingo Molnar
2007-02-22 11:31 ` Evgeniy Polyakov
2007-02-22 11:52 ` Arjan van de Ven
2007-02-22 12:39 ` Evgeniy Polyakov
2007-02-22 13:41 ` David Miller
2007-02-22 14:31 ` Ingo Molnar
2007-02-22 14:47 ` David Miller
2007-02-22 15:02 ` Evgeniy Polyakov
2007-02-22 15:15 ` Ingo Molnar
2007-02-22 15:29 ` Ingo Molnar
2007-02-22 17:17 ` David Miller
2007-02-23 11:12 ` Ingo Molnar
2007-02-22 20:13 ` Davide Libenzi
2007-02-22 21:30 ` Zach Brown
2007-02-22 14:59 ` Ingo Molnar
2007-02-22 21:42 ` Michael K. Edwards
2007-02-22 14:53 ` Avi Kivity
2007-02-22 12:59 ` Ingo Molnar
2007-02-22 13:32 ` Evgeniy Polyakov
2007-02-22 19:46 ` Davide Libenzi
2007-02-23 12:15 ` Evgeniy Polyakov
2007-02-23 17:43 ` Davide Libenzi
2007-02-23 18:01 ` Evgeniy Polyakov
2007-02-23 20:43 ` Davide Libenzi
2007-02-23 11:51 ` Ingo Molnar
2007-02-23 12:22 ` Evgeniy Polyakov
2007-02-23 12:41 ` Evgeniy Polyakov
2007-02-25 17:45 ` Ingo Molnar
2007-02-25 18:09 ` Evgeniy Polyakov
2007-02-25 19:04 ` Ingo Molnar
2007-02-25 19:42 ` Evgeniy Polyakov
2007-02-25 20:38 ` Ingo Molnar
2007-02-26 12:39 ` Ingo Molnar
2007-02-26 14:05 ` Evgeniy Polyakov
2007-02-26 14:15 ` Ingo Molnar
2007-02-26 16:55 ` Evgeniy Polyakov
2007-02-26 20:35 ` Ingo Molnar
2007-02-26 22:06 ` Bill Huey
2007-02-27 10:09 ` Evgeniy Polyakov
2007-02-27 17:13 ` Pavel Machek
2007-02-27 2:18 ` Davide Libenzi
2007-02-27 10:13 ` Evgeniy Polyakov
2007-02-27 16:01 ` Davide Libenzi
2007-02-27 16:21 ` Evgeniy Polyakov
2007-02-27 16:58 ` Eric Dumazet
2007-02-27 17:06 ` Evgeniy Polyakov
2007-02-27 19:20 ` Davide Libenzi
2007-02-26 19:47 ` Davide Libenzi
2007-02-25 23:14 ` Michael K. Edwards
2007-02-22 14:17 ` Suparna Bhattacharya
2007-02-22 14:36 ` Ingo Molnar
2007-02-23 14:23 ` Suparna Bhattacharya
2007-02-22 21:24 ` Michael K. Edwards
2007-02-23 0:30 ` Alan
2007-02-23 2:47 ` Michael K. Edwards
2007-02-23 8:31 ` Michael K. Edwards
2007-02-23 10:22 ` Ingo Molnar
2007-02-23 12:37 ` Alan
2007-02-23 23:49 ` Michael K. Edwards
2007-02-24 1:08 ` Alan
2007-02-24 0:51 ` Michael K. Edwards
2007-02-24 2:17 ` Michael K. Edwards
2007-02-24 3:25 ` Michael K. Edwards
2007-02-23 12:17 ` Ingo Molnar
2007-02-24 19:52 ` Michael K. Edwards
2007-02-24 21:04 ` Davide Libenzi
2007-02-24 23:01 ` Michael K. Edwards
2007-02-25 22:44 ` Linus Torvalds
2007-02-26 13:11 ` Ingo Molnar
2007-02-26 17:37 ` Evgeniy Polyakov
2007-02-26 18:19 ` Arjan van de Ven
2007-02-26 18:38 ` Evgeniy Polyakov
2007-02-26 18:56 ` Chris Friesen
2007-02-26 19:20 ` Evgeniy Polyakov
2007-02-26 17:28 ` Evgeniy Polyakov
2007-02-26 17:57 ` Linus Torvalds
2007-02-26 18:32 ` Evgeniy Polyakov
2007-02-26 19:22 ` Linus Torvalds
2007-02-26 19:30 ` Evgeniy Polyakov
2007-02-26 20:04 ` Linus Torvalds
2007-02-27 8:09 ` Evgeniy Polyakov
2007-02-26 19:54 ` Ingo Molnar
2007-02-27 10:28 ` Evgeniy Polyakov
2007-02-27 11:52 ` Theodore Tso
2007-02-27 12:11 ` Evgeniy Polyakov
2007-02-27 12:13 ` Ingo Molnar
2007-02-27 12:40 ` Evgeniy Polyakov
2007-02-28 16:14 ` Pavel Machek
2007-03-01 8:18 ` Evgeniy Polyakov
2007-03-01 9:26 ` Pavel Machek
2007-03-01 9:47 ` Evgeniy Polyakov
2007-03-01 9:54 ` Ingo Molnar
2007-03-01 10:59 ` Evgeniy Polyakov
2007-03-01 11:00 ` Ingo Molnar
2007-03-01 11:16 ` Evgeniy Polyakov
2007-03-01 11:27 ` Ingo Molnar
2007-03-01 11:36 ` Evgeniy Polyakov
2007-03-01 11:41 ` Ingo Molnar
2007-03-01 11:47 ` Ingo Molnar
2007-03-01 12:10 ` Evgeniy Polyakov
2007-03-01 12:43 ` Ingo Molnar
2007-03-01 13:01 ` Evgeniy Polyakov
2007-03-01 13:11 ` Ingo Molnar
2007-03-01 13:30 ` Evgeniy Polyakov
2007-03-01 14:19 ` Eric Dumazet
2007-03-01 14:16 ` Ingo Molnar
2007-03-01 14:31 ` Eric Dumazet
2007-03-01 14:27 ` Ingo Molnar
2007-03-01 14:54 ` Evgeniy Polyakov
2007-03-01 15:09 ` Ingo Molnar
2007-03-01 15:36 ` Evgeniy Polyakov
2007-03-02 10:57 ` Ingo Molnar
2007-03-02 11:48 ` Evgeniy Polyakov
2007-03-02 17:32 ` Davide Libenzi
2007-03-02 19:39 ` Ingo Molnar
2007-03-02 20:18 ` Davide Libenzi
2007-03-02 20:29 ` Ingo Molnar
2007-03-02 20:53 ` Davide Libenzi
2007-03-02 21:21 ` Michael K. Edwards
2007-03-02 21:43 ` Nicholas Miell
2007-03-03 0:52 ` Davide Libenzi
2007-03-03 1:36 ` Nicholas Miell
2007-03-03 1:48 ` Benjamin LaHaise
2007-03-03 2:19 ` Davide Libenzi
2007-03-03 7:19 ` Ingo Molnar
2007-03-03 7:20 ` Ingo Molnar
2007-03-03 9:02 ` Davide Libenzi
2007-03-01 19:31 ` Davide Libenzi
2007-03-02 8:10 ` Evgeniy Polyakov
2007-03-02 17:13 ` Davide Libenzi
2007-03-02 19:13 ` Davide Libenzi
2007-03-03 10:06 ` Evgeniy Polyakov
2007-03-03 18:46 ` Davide Libenzi
2007-03-03 20:31 ` Evgeniy Polyakov
2007-03-03 21:57 ` Davide Libenzi
2007-03-03 22:10 ` Davide Libenzi
2007-03-04 16:23 ` Kirk Kuchov
2007-03-04 17:46 ` Kyle Moffett
2007-03-05 5:23 ` Michael K. Edwards
2007-03-04 21:17 ` Davide Libenzi
2007-03-04 22:49 ` Kirk Kuchov
2007-03-04 22:57 ` Davide Libenzi
2007-03-05 4:46 ` Magnus Naeslund(k)
2007-03-06 8:19 ` Pavel Machek
2007-03-07 12:02 ` Kirk Kuchov
2007-03-07 17:26 ` Linus Torvalds
2007-03-07 17:39 ` Ingo Molnar
2007-03-07 18:21 ` Kirk Kuchov
2007-03-07 18:24 ` Jens Axboe
2007-03-07 18:32 ` Evgeniy Polyakov
2007-03-01 12:01 ` Evgeniy Polyakov
2007-03-01 11:14 ` Eric Dumazet
2007-03-01 11:20 ` Evgeniy Polyakov
2007-03-01 11:28 ` Eric Dumazet
2007-03-01 11:47 ` Evgeniy Polyakov
2007-03-01 13:12 ` Eric Dumazet
2007-03-01 14:43 ` Evgeniy Polyakov
2007-03-01 14:47 ` Ingo Molnar
2007-03-01 15:23 ` Evgeniy Polyakov
2007-03-01 15:32 ` Eric Dumazet
2007-03-01 15:41 ` Eric Dumazet
2007-03-01 15:51 ` Evgeniy Polyakov
2007-03-01 15:47 ` Evgeniy Polyakov
2007-03-01 19:47 ` Davide Libenzi
2007-03-01 14:57 ` Evgeniy Polyakov
2007-03-01 12:19 ` Evgeniy Polyakov
2007-03-01 12:34 ` Ingo Molnar
2007-03-01 13:26 ` Evgeniy Polyakov
2007-03-01 13:32 ` Ingo Molnar
2007-03-01 14:24 ` Evgeniy Polyakov
2007-03-01 16:56 ` David Lang
2007-03-01 17:56 ` Evgeniy Polyakov
2007-03-01 18:41 ` David Lang
2007-03-01 19:19 ` Davide Libenzi
2007-03-01 10:11 ` Pavel Machek
2007-03-01 10:19 ` Ingo Molnar
2007-03-01 11:18 ` Evgeniy Polyakov
2007-03-02 10:27 ` Pavel Machek
2007-03-02 10:37 ` Evgeniy Polyakov
2007-03-02 10:56 ` Ingo Molnar
2007-03-02 11:08 ` Evgeniy Polyakov
2007-03-02 17:28 ` Davide Libenzi
2007-03-03 10:27 ` Evgeniy Polyakov
2007-03-01 19:24 ` Johann Borck
2007-03-01 19:37 ` David Lang
2007-03-01 20:34 ` Johann Borck
2007-02-27 12:34 ` Ingo Molnar
2007-02-27 13:14 ` Evgeniy Polyakov
2007-02-27 13:32 ` Avi Kivity
2007-02-28 3:03 ` Michael K. Edwards
2007-02-28 8:02 ` Evgeniy Polyakov
2007-02-28 17:01 ` Michael K. Edwards
2007-03-05 2:16 ` Discussing LKML community [OT from the Re: [patch 00/13] Syslets, "Threadlets", generic AIO support, v3] Oleg Verych
2007-02-28 16:38 ` [patch 00/13] Syslets, "Threadlets", generic AIO support, v3 Phillip Susi
2007-02-22 19:38 ` Davide Libenzi
2007-02-28 9:45 ` Ingo Molnar
2007-02-28 16:17 ` Davide Libenzi
2007-02-28 16:42 ` Linus Torvalds
2007-02-28 17:26 ` Ingo Molnar
2007-02-28 18:22 ` Davide Libenzi
2007-02-28 18:42 ` Linus Torvalds
2007-02-28 18:50 ` Davide Libenzi
2007-02-28 19:03 ` Chris Friesen
2007-02-28 19:42 ` Davide Libenzi
2007-03-01 8:38 ` Evgeniy Polyakov
2007-03-01 9:28 ` Evgeniy Polyakov
2007-02-28 23:12 ` Ingo Molnar
2007-03-01 1:33 ` Andrea Arcangeli
2007-03-01 9:15 ` Evgeniy Polyakov
2007-03-01 21:27 ` Linus Torvalds
2007-02-28 20:21 ` Ingo Molnar
2007-02-28 21:09 ` Davide Libenzi
2007-02-28 21:23 ` Ingo Molnar
2007-02-28 21:46 ` Davide Libenzi
2007-02-28 22:22 ` Ingo Molnar
2007-02-28 22:47 ` Davide Libenzi
2007-02-22 21:23 ` Zach Brown
2007-02-22 21:32 ` Benjamin LaHaise
2007-02-22 21:44 ` Zach Brown
2007-02-22 1:04 ` Michael K. Edwards
2007-02-22 7:00 ` Ingo Molnar
2007-02-22 9:29 ` Michael K. Edwards
2007-02-22 10:01 ` Suparna Bhattacharya
2007-02-22 11:20 ` Ingo Molnar
2007-02-23 12:52 ` A quick fio test (was Re: [patch 00/13] Syslets, "Threadlets", generic AIO support, v3) Jens Axboe
2007-02-23 13:55 ` Suparna Bhattacharya
2007-02-23 14:58 ` Ingo Molnar
2007-02-23 15:15 ` Suparna Bhattacharya
2007-02-23 16:25 ` Jens Axboe
2007-02-23 17:13 ` Suparna Bhattacharya
2007-02-23 18:35 ` Jens Axboe
2007-02-26 13:57 ` Jens Axboe
2007-02-26 14:13 ` Suparna Bhattacharya
2007-02-26 14:18 ` Ingo Molnar
2007-02-26 14:45 ` Jens Axboe
2007-02-27 4:33 ` Suparna Bhattacharya
2007-02-27 9:42 ` Jens Axboe
2007-02-27 11:12 ` Evgeniy Polyakov
2007-02-27 11:29 ` Jens Axboe
2007-02-27 12:19 ` Evgeniy Polyakov
2007-02-27 18:45 ` Jens Axboe
2007-02-27 19:08 ` Evgeniy Polyakov
2007-02-27 19:25 ` Jens Axboe
2007-02-27 12:39 ` Suparna Bhattacharya
2007-02-28 8:31 ` Jens Axboe
2007-02-28 8:38 ` Ingo Molnar
2007-02-28 9:07 ` Jens Axboe
2007-02-27 13:54 ` Avi Kivity
2007-02-27 15:25 ` Ingo Molnar
2007-02-27 16:15 ` Avi Kivity
2007-02-27 16:16 ` Ingo Molnar
2007-02-27 16:26 ` Avi Kivity
2007-02-27 18:49 ` Jens Axboe
2007-02-26 21:40 ` Davide Libenzi
2007-02-23 16:59 ` Ingo Molnar
2007-02-23 22:31 ` Joel Becker
2007-02-24 12:18 ` Jens Axboe
2007-02-24 7:41 ` [patchset] Syslets/threadlets, generic AIO support, v4 Ingo Molnar
2007-02-24 18:34 ` [patch 00/13] Syslets, "Threadlets", generic AIO support, v3 Evgeniy Polyakov
2007-02-25 17:23 ` Ingo Molnar
2007-02-25 17:44 ` Evgeniy Polyakov
2007-02-25 17:54 ` Ingo Molnar
2007-02-25 18:21 ` Evgeniy Polyakov
2007-02-25 18:22 ` Ingo Molnar
2007-02-25 18:37 ` Evgeniy Polyakov
2007-02-25 18:34 ` Ingo Molnar
2007-02-25 20:01 ` Frederik Deweerdt
2007-02-25 19:21 ` Ingo Molnar
[not found] ` <20070225194645.GB1353@2ka.mipt.ru>
[not found] ` <20070225195308.GC15681@elte.hu>
[not found] ` <Pine.LNX.4.64.0702251232350.6011@alien.or.mcafeemobile.com>
2007-02-25 21:34 ` threadlets as 'naive pool of threads', epoll, some measurements Ingo Molnar
2007-02-26 10:45 ` Ingo Molnar
2007-02-26 11:48 ` Ingo Molnar
2007-02-26 12:25 ` Evgeniy Polyakov
2007-02-26 12:50 ` Ingo Molnar
2007-02-26 14:32 ` Evgeniy Polyakov
2007-02-26 20:23 ` Ingo Molnar
2007-02-27 8:16 ` Evgeniy Polyakov
2007-02-27 8:27 ` Ingo Molnar
2007-02-27 10:37 ` Evgeniy Polyakov
2007-02-27 12:15 ` Ingo Molnar
2007-02-27 12:22 ` Evgeniy Polyakov
2007-02-26 21:22 ` Davide Libenzi
2007-02-26 8:16 ` [patch 00/13] Syslets, "Threadlets", generic AIO support, v3 Ingo Molnar
2007-02-26 9:25 ` Evgeniy Polyakov
2007-02-26 9:55 ` Ingo Molnar
2007-02-26 10:31 ` Ingo Molnar
2007-02-26 10:43 ` Evgeniy Polyakov
2007-02-26 20:02 ` Davide Libenzi
2007-02-26 10:33 ` Evgeniy Polyakov
2007-02-26 10:35 ` Ingo Molnar
2007-02-26 10:47 ` Evgeniy Polyakov
2007-02-26 12:51 ` Ingo Molnar
2007-02-26 16:46 ` Evgeniy Polyakov
2007-02-27 6:24 ` Ingo Molnar
2007-02-27 10:41 ` Evgeniy Polyakov
2007-02-27 10:49 ` Ingo Molnar
2007-02-25 18:25 ` Evgeniy Polyakov
2007-02-25 18:24 ` Ingo Molnar
2007-02-25 14:33 ` Threadlet/syslet v4 bug report Evgeniy Polyakov
2007-02-25 15:24 ` Evgeniy Polyakov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070221211516.GD7579@elte.hu \
--to=mingo@elte.hu \
--cc=akpm@zip.com.au \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=arjan@infradead.org \
--cc=davem@davemloft.net \
--cc=davidel@xmailserver.org \
--cc=drepper@redhat.com \
--cc=hch@infradead.org \
--cc=jens.axboe@oracle.com \
--cc=johnpol@2ka.mipt.ru \
--cc=linux-kernel@vger.kernel.org \
--cc=suparna@in.ibm.com \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=zach.brown@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox