Fix sync engine completion latency
[fio.git] / syslet.h
1 #ifndef _LINUX_SYSLET_H
2 #define _LINUX_SYSLET_H
3 /*
4  * The syslet subsystem - asynchronous syscall execution support.
5  *
6  * Started by Ingo Molnar:
7  *
8  *  Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
9  *
10  * User-space API/ABI definitions:
11  */
12
13 #ifndef __user
14 # define __user
15 #endif
16
17 /*
18  * This is the 'Syslet Atom' - the basic unit of execution
19  * within the syslet framework. A syslet always represents
20  * a single system-call plus its arguments, plus has conditions
21  * attached to it that allows the construction of larger
22  * programs from these atoms. User-space variables can be used
23  * (for example a loop index) via the special sys_umem*() syscalls.
24  *
25  * Arguments are implemented via pointers to arguments. This not
26  * only increases the flexibility of syslet atoms (multiple syslets
27  * can share the same variable for example), but is also an
28  * optimization: copy_uatom() will only fetch syscall parameters
29  * up until the point it meets the first NULL pointer. 50% of all
30  * syscalls have 2 or less parameters (and 90% of all syscalls have
31  * 4 or less parameters).
32  *
33  * [ Note: since the argument array is at the end of the atom, and the
34  *   kernel will not touch any argument beyond the final NULL one, atoms
35  *   might be packed more tightly. (the only special case exception to
36  *   this rule would be SKIP_TO_NEXT_ON_STOP atoms, where the kernel will
37  *   jump a full syslet_uatom number of bytes.) ]
38  */
39 struct syslet_uatom {
40         unsigned long                           flags;
41         unsigned long                           nr;
42         long __user                             *ret_ptr;
43         struct syslet_uatom     __user          *next;
44         unsigned long           __user          *arg_ptr[6];
45         /*
46          * User-space can put anything in here, kernel will not
47          * touch it:
48          */
49         void __user                             *private;
50 };
51
52 /*
53  * Flags to modify/control syslet atom behavior:
54  */
55
56 /*
57  * Immediately queue this syslet asynchronously - do not even
58  * attempt to execute it synchronously in the user context:
59  */
60 #define SYSLET_ASYNC                            0x00000001
61
62 /*
63  * Never queue this syslet asynchronously - even if synchronous
64  * execution causes a context-switching:
65  */
66 #define SYSLET_SYNC                             0x00000002
67
68 /*
69  * Do not queue the syslet in the completion ring when done.
70  *
71  * ( the default is that the final atom of a syslet is queued
72  *   in the completion ring. )
73  *
74  * Some syscalls generate implicit completion events of their
75  * own.
76  */
77 #define SYSLET_NO_COMPLETE                      0x00000004
78
79 /*
80  * Execution control: conditions upon the return code
81  * of the previous syslet atom. 'Stop' means syslet
82  * execution is stopped and the atom is put into the
83  * completion ring:
84  */
85 #define SYSLET_STOP_ON_NONZERO                  0x00000008
86 #define SYSLET_STOP_ON_ZERO                     0x00000010
87 #define SYSLET_STOP_ON_NEGATIVE                 0x00000020
88 #define SYSLET_STOP_ON_NON_POSITIVE             0x00000040
89
90 #define SYSLET_STOP_MASK                                \
91         (       SYSLET_STOP_ON_NONZERO          |       \
92                 SYSLET_STOP_ON_ZERO             |       \
93                 SYSLET_STOP_ON_NEGATIVE         |       \
94                 SYSLET_STOP_ON_NON_POSITIVE             )
95
96 /*
97  * Special modifier to 'stop' handling: instead of stopping the
98  * execution of the syslet, the linearly next syslet is executed.
99  * (Normal execution flows along atom->next, and execution stops
100  *  if atom->next is NULL or a stop condition becomes true.)
101  *
102  * This is what allows true branches of execution within syslets.
103  */
104 #define SYSLET_SKIP_TO_NEXT_ON_STOP             0x00000080
105
106 /*
107  * This is the (per-user-context) descriptor of the async completion
108  * ring. This gets registered via sys_async_register().
109  */
110 struct async_head_user {
111         /*
112          * Pointers to completed async syslets (i.e. syslets that
113          * generated a cachemiss and went async, returning -EASYNCSYSLET
114          * to the user context by sys_async_exec()) are queued here.
115          * Syslets that were executed synchronously are not queued here.
116          *
117          * Note: the final atom that generated the exit condition is
118          * queued here. Normally this would be the last atom of a syslet.
119          */
120         struct syslet_uatom __user              **completion_ring;
121         /*
122          * Ring size in bytes:
123          */
124         unsigned long                           ring_size_bytes;
125
126         /*
127          * Maximum number of asynchronous contexts the kernel creates.
128          *
129          * -1UL has a special meaning: the kernel manages the optimal
130          * size of the async pool.
131          *
132          * Note: this field should be valid for the lifetime of async
133          * processing, because future kernels detect changes to this
134          * field. (enabling user-space to control the size of the async
135          * pool in a low-overhead fashion)
136          */
137         unsigned long                           max_nr_threads;
138 };
139
140 #endif