-#ifndef _LINUX_SYSLET_H
-#define _LINUX_SYSLET_H
-/*
- * The syslet subsystem - asynchronous syscall execution support.
- *
- * Started by Ingo Molnar:
- *
- * Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *
- * User-space API/ABI definitions:
- */
+#ifndef _SYSLET_H_
+#define _SYSLET_H_
-#ifndef __user
-# define __user
-#endif
+#include "kcompat.h"
-/*
- * This is the 'Syslet Atom' - the basic unit of execution
- * within the syslet framework. A syslet always represents
- * a single system-call plus its arguments, plus has conditions
- * attached to it that allows the construction of larger
- * programs from these atoms. User-space variables can be used
- * (for example a loop index) via the special sys_umem*() syscalls.
- *
- * Arguments are implemented via pointers to arguments. This not
- * only increases the flexibility of syslet atoms (multiple syslets
- * can share the same variable for example), but is also an
- * optimization: copy_uatom() will only fetch syscall parameters
- * up until the point it meets the first NULL pointer. 50% of all
- * syscalls have 2 or less parameters (and 90% of all syscalls have
- * 4 or less parameters).
- *
- * [ Note: since the argument array is at the end of the atom, and the
- * kernel will not touch any argument beyond the final NULL one, atoms
- * might be packed more tightly. (the only special case exception to
- * this rule would be SKIP_TO_NEXT_ON_STOP atoms, where the kernel will
- * jump a full syslet_uatom number of bytes.) ]
- */
-struct syslet_uatom {
- unsigned long flags;
- unsigned long nr;
- long __user *ret_ptr;
- struct syslet_uatom __user *next;
- unsigned long __user *arg_ptr[6];
- /*
- * User-space can put anything in here, kernel will not
- * touch it:
- */
- void __user *private;
+struct syslet_frame {
+ u64 ip;
+ u64 sp;
};
-/*
- * Flags to modify/control syslet atom behavior:
- */
-
-/*
- * Immediately queue this syslet asynchronously - do not even
- * attempt to execute it synchronously in the user context:
- */
-#define SYSLET_ASYNC 0x00000001
-
-/*
- * Never queue this syslet asynchronously - even if synchronous
- * execution causes a context-switching:
- */
-#define SYSLET_SYNC 0x00000002
+struct syslet_args {
+ u64 ring_ptr;
+ u64 caller_data;
+ struct syslet_frame frame;
+};
-/*
- * Do not queue the syslet in the completion ring when done.
- *
- * ( the default is that the final atom of a syslet is queued
- * in the completion ring. )
- *
- * Some syscalls generate implicit completion events of their
- * own.
- */
-#define SYSLET_NO_COMPLETE 0x00000004
+struct syslet_completion {
+ u64 status;
+ u64 caller_data;
+};
-/*
- * Execution control: conditions upon the return code
- * of the previous syslet atom. 'Stop' means syslet
- * execution is stopped and the atom is put into the
- * completion ring:
- */
-#define SYSLET_STOP_ON_NONZERO 0x00000008
-#define SYSLET_STOP_ON_ZERO 0x00000010
-#define SYSLET_STOP_ON_NEGATIVE 0x00000020
-#define SYSLET_STOP_ON_NON_POSITIVE 0x00000040
+struct syslet_ring {
+ u32 kernel_head;
+ u32 user_tail;
+ u32 elements;
+ u32 wait_group;
+ struct syslet_completion comp[0];
+};
-#define SYSLET_STOP_MASK \
- ( SYSLET_STOP_ON_NONZERO | \
- SYSLET_STOP_ON_ZERO | \
- SYSLET_STOP_ON_NEGATIVE | \
- SYSLET_STOP_ON_NON_POSITIVE )
+#ifdef __x86_64__
+#define __NR_syslet_ring_wait 287
+#elif defined __i386__
+#define __NR_syslet_ring_wait 326
+#endif
-/*
- * Special modifier to 'stop' handling: instead of stopping the
- * execution of the syslet, the linearly next syslet is executed.
- * (Normal execution flows along atom->next, and execution stops
- * if atom->next is NULL or a stop condition becomes true.)
- *
- * This is what allows true branches of execution within syslets.
- */
-#define SYSLET_SKIP_TO_NEXT_ON_STOP 0x00000080
+#define ESYSLETPENDING 132
-/*
- * This is the (per-user-context) descriptor of the async completion
- * ring. This gets registered via sys_async_register().
- */
-struct async_head_user {
- /*
- * Pointers to completed async syslets (i.e. syslets that
- * generated a cachemiss and went async, returning -EASYNCSYSLET
- * to the user context by sys_async_exec()) are queued here.
- * Syslets that were executed synchronously are not queued here.
- *
- * Note: the final atom that generated the exit condition is
- * queued here. Normally this would be the last atom of a syslet.
- */
- struct syslet_uatom __user **completion_ring;
- /*
- * Ring size in bytes:
- */
- unsigned long ring_size_bytes;
+typedef void (*syslet_return_func_t)(void);
- /*
- * Maximum number of asynchronous contexts the kernel creates.
- *
- * -1UL has a special meaning: the kernel manages the optimal
- * size of the async pool.
- *
- * Note: this field should be valid for the lifetime of async
- * processing, because future kernels detect changes to this
- * field. (enabling user-space to control the size of the async
- * pool in a low-overhead fashion)
- */
- unsigned long max_nr_threads;
-};
+void fill_syslet_args(struct syslet_args *args, struct syslet_ring *ring,
+ uint64_t caller_data, syslet_return_func_t func,
+ void *stack)
+{
+ args->ring_ptr = (u64)(unsigned long)ring;
+ args->caller_data = caller_data;
+ args->frame.ip = (u64)(unsigned long)func;
+ args->frame.sp = (u64)(unsigned long)stack;
+}
#endif