Merge from vendor branch LIBPCAP:
[dragonfly.git] / lib / libc / sys / upc_register.2
1 .\" Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
2 .\" All rights reserved.
3 .\"
4 .\" Redistribution and use in source and binary forms, with or without
5 .\" modification, are permitted provided that the following conditions
6 .\" are met:
7 .\" 1. Redistributions of source code must retain the above copyright
8 .\"    notice, this list of conditions and the following disclaimer.
9 .\" 2. Redistributions in binary form must reproduce the above copyright
10 .\"    notice, this list of conditions and the following disclaimer in the
11 .\"    documentation and/or other materials provided with the distribution.
12 .\"
13 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 .\" SUCH DAMAGE.
24 .\"
25 .\" $DragonFly: src/lib/libc/sys/upc_register.2,v 1.3 2003/12/04 20:35:06 dillon Exp $
26 .\"
27 .Dd November 20, 2003
28 .Dt UPC_REGISTER 2
29 .Os
30 .Sh NAME
31 .Nm upc_register ,
32 .Nm upc_control
33 .Nd configure and control upcalls
34 .Sh LIBRARY
35 .Lb libc
36 .Sh SYNOPSIS
37 .In sys/upcall.h
38 .Ft int
39 .Fn upc_register "struct upcall *upc" "upcall_func_t ctxfunc" "upcall_func_t cfunc" "void *data"
40 .Ft int
41 .Fn upc_control "int command" "int upcall_id" "void *data"
42 .Sh DESCRIPTION
43 .Fn Upc_register
44 registers an upcall.  Note that the specified upcall structural pointer
45 is per-process, not per-upcall.  It points to a structure in user memory
46 that both the user and kernel manipulate to deal with upcall/critical-section
47 interlocks.
48 .Fa ctxfunc
49 is a pointer to context save and restore code.  The native upcall interface
50 does not necessarily save and restore call-used registers.  This function
51 is typically written in assembly and supplied by
52 .Lb libc .
53 .Fa cfunc
54 is a pointer to a C style function and
55 .Fa data
56 is the data passed to it as an argument.  A positive upcall identifier
57 will be returned or -1 if an error occured.
58 .Pp
59 When an upcall is executed the
60 kernel will add LWKT_CRITPRI to the critical section count in the upcall
61 structure, push a minimal context (not even call-used), and pass the C
62 function and data pointers to
63 .Fa ctxfunc
64 in registers.
65 .Fa ctxfunc 
66 will then proceed to save appropriate state, call the C function, and 
67 deal with cleanup.  Cleanup typically involves an interlocking operation
68 and a call to
69 .Fn Upc_control
70 in order to undo the critical section count and process any additional
71 pending upcalls atomically.
72 .Fa ctxfunc
73 will typically pop most of its state, set upcall->pending to 1,
74 subtract LWKT_CRITPRI from upcall->crit_count, and call  
75 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
76 which atomically handles any further pending upcalls and/or pops the
77 original stack context supplied to
78 .Fn upc_control
79 and resumes the originally interrupted code.  This is all very complex
80 which is why
81 .Lb libc
82 typically supplies
83 .Fa ctxfunc .
84 .Pp
85 Note that upcalls can only occur if the target process is not in a critical
86 section.  If an upcall cannot be dispatched it will instead be made pending
87 and the pending field in the user-supplied upcall structure will be set to
88 non-zero.  Userland critical-section-exiting code must check the pending
89 bit and call the appropriate
90 .Fn upc_control
91 function to handle any pending upcalls.
92 .Pp
93 The upcall identifier space is shared amoungst all processes sharing the
94 same VM space.  That is, all the processes created through clone() or
95 rfork(RFMEM).  Through appropriate
96 .Fn upc_control
97 calls any process within this domain can generate an upcall on any other
98 process within this domain, including itself.  Each process typically 
99 installs a different (per-process) upcall data structure.
100 .Pp
101 .Fn Upc_control
102 is a multi-function system call capable of dispatching upcalls, handling
103 the context assembly function's interlocks, deleting upcalls, and polling
104 for upcalls.
105 .Pp
106 .Ft int
107 .Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority"
108 .Pp
109 .Bd -offset indent
110 Dispatch a particular upcall.  0 is returned on success, ENOENT if
111 .Fa upcid
112 does not exist.  You can dispatch upcalls belonging to your process or
113 to another process.  You may specify a
114 .Fa upcid
115 of -1 to re-dispatch the first upcall owned by your own process that is
116 pending from a previous operation.  Note that that critical section and
117 pending rules apply, and an actual dispatch will pushdown the stack.
118 .Pp
119 The priority will be compared against the current crit_count to determine
120 whether the upcall dispatches or is made pending.
121 .Pp
122 This command is most often used to alert a target process to a change in
123 a shared structure, queue, etc.
124 .Ed
125 .Pp
126 .Ft int
127 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
128 .Pp
129 .Bd -offset indent
130 Do interlocking and stack munging to process additional upcalls.  This
131 system call should never be made directly by C code because it expects
132 all registers not saved by the operating system in entering a context
133 function to have been popped and a pointer to the base of the OS-supplied
134 stack context on entry to the context routine to be supplied.  This routine
135 does not return to the caller but instead either regenerates the stack
136 context for the next pending upcall or it restores the original context,
137 resuming whomever was interrupted by the original upcall that entered the
138 context routine.
139 .Ed
140 .Pp
141 .Ft int
142 .Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
143 .Pp
144 .Bd -offset indent
145 Delete the specified
146 .Fa upcid
147 or, if -1 is specified, delete all upcall registered by the current process.
148 If -1 is specified, the upcalls registered by another process will not be
149 deleted.  If a particular
150 .Fa upcid
151 is specified, it will be deleted regardless of which process registered it.
152 The upcall structural pointer registered with this or any other process is 
153 not effected.
154 .Ed
155 .Pp
156 .Ft int
157 .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
158 .Pp
159 .Ft int
160 .Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
161 .Pp
162 .Bd -offset indent
163 Poll or poll-and-clear the pending status for a particular upcall.  0 or 1
164 is returned, or -1 if an error occured (e.g. ENOENT).  
165 If a
166 .Fa upcid
167 of -1 is specified, locate a pending upcall for the current process and return
168 it's
169 .Fa upcid ,
170 or 0 if no upcalls for the current process are pending.
171 .Pp
172 The priority will be compared against the upcall's pending priority.  Only
173 upcalls with greater or equal pending priorities are returned.  You must
174 specify a minimum priority of 1 or this call will simply return a random
175 registered upcall that may or may not be pending.
176 .Ed
177 .Pp
178 .Bd -literal -offset indent -compact
179 struct upcall {
180         int     magic;          /* must be UPCALL_MAGIC */
181         int     crit_count;     /* critical section count */
182         int     pending;        /* additional upcalls are pending */
183 };
184 .Ed
185 .Pp
186 This is a user space structure a pointer to which is registered with the 
187 kernel via
188 .Fn upc_register
189 \.
190 The
191 .Fa crit_count
192 field prevents new upcalls from being dispatched.  When an upcall is 
193 dispatched the kernel automatically adds
194 .Va UPC_CRITADD
195 to 
196 .Fa crit_count
197 and sets
198 .Fa pending
199 to indicate whether any additional upcalls are pending.  A non-zero
200 .Fa pending
201 OR
202 .Fa crit_count
203 will prevent new upcalls from the being dispatched.  The context function
204 code is expected to make appropriate checks to dispatch any remaining upcalls
205 when the current upcall has completed.  In particular, the context function
206 must subtract
207 .Va UPC_CRITADD
208 from 
209 .Fa crit_count
210 before restoring the original context or calling
211 .Fn upc_control "UPC_CONTROL_NEXT" "..."
212 \.
213 Note that
214 .Fa pending
215 may be set as a side effect to various
216 .Fn upc_control
217 system calls as well as as a side effect to upcall dispatches.
218 .Pp
219 Userland threading code typically uses
220 .Fa crit_count
221 to control critical sections within a virtual cpu (aka cloned process).
222 Entering a critical section is as simply as add UPC_CRITADD to
223 .Fa crit_count .
224 No atomic or locked instructions are required as this field is accessed
225 only by the current process and any upcalls or interrupts will restore it
226 to the condition they found it before returning.  Exiting a critical section
227 is almost as simple as subtracting UPC_CRITADD from
228 .Fa crit_count .
229 The routine which performs this function must also check the
230 .Fa pending
231 field once the critical section count has reached 0.  If the pending field
232 is non-zero, the routine will generally call
233 .Fn upc_control "UPC_CONTROL_DISPATCH" "-1" "NULL"
234 to dispatch upcalls which were made pending while you were in the critical
235 section.
236 .Sh CONTEXT FUNCTION - IA32
237 The context function is called with the stack pointer pointing at a 
238 kernel-constructed stack frame.  Only a minimal number of registers are
239 saved by the kernel. 
240 .Pp
241 .Bd -literal -offset indent -compact
242 frame {
243     int32_t     eax;
244     int32_t     ecx;
245     int32_t     edx;
246     int32_t     eflags;
247     int32_t     origip;
248 }
249 .Ed
250 .Pp
251 On entry,  %eax will hold the C function pointer, %ecx will hold the
252 C data pointer, and %edx will hold a pointer to the user-supplied upcall
253 structure.  The context code does not need to push %eax, %ecx, or %edx
254 because these registers have already been pushed on the stack for it, but
255 it must generally push any remaining registers that it might use and be
256 careful in regards to others, such as floating point registers, which
257 the OS has not saved.  The operating system has already adjusted the
258 .Fa crit_count
259 and
260 .Fa pending
261 fields in the user-supplied
262 .Fa upcall
263 structure, so the context code will generally next push the data pointer
264 (%ecx) and call the C function through %eax.  Upon return the context code
265 is responsible for interlocking the upcall return which it does by first
266 setting
267 .Fa pending
268 to 1, then subtracting
269 .Va UPC_CRITADD
270 from
271 .Fa crit_count ,
272 then restoring its part of the context but leaving the OS context intact,
273 then calling
274 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
275 \.
276 The control function will not return.  It will either restart the context
277 at the next upcall, if more are pending, or it will restore the original
278 context.
279 .Pp
280 The context code does not have to follow this regimn.  There is nothing
281 preventing the context code from restoring the original frame itself and
282 returning directly to the originally interrupted user code without having
283 to make another kernel transition.  It is possible to optimize this by
284 having the context code subtract down
285 .Va UPC_CRITADD
286 as per normal but not pre-set the
287 .Fa pending
288 field.  If it does this and
289 .Fa pending 
290 is 0, it is possible for the kernel to initiate another upcall before
291 the context code has had a chance to pop its stack and restore the original
292 user context.  This is ok under controlled circumstances.  On the otherhand,
293 if
294 .Fa pending 
295 is 1
296 the context code knows there is another upcall pending and can call
297 .Fn upc_control
298 as appropriate.
299 .Pp
300 .Bd -literal -offset indent -compact
301         /*
302          * upc is a global pointing to this process's upcall structure
303          * (just as an example).  The Os-supplied stack frame is:
304          *
305          *      [%eax %ecx %edx,%eflags %original_ip]
306          */
307 callused_wrapper:
308         pushl   %edx            /* save %edx (upcall pointer) */
309         pushl   %ecx            /* func=%eax(data=%ecx) */
310         call    *%eax           /* call the C function */
311         addl    $4,%esp
312         popl    %edx            /* restore the upcall pointer */
313         incl    PENDING(%edx)   /* setting pending stops upcalls */
314         subl    $32,CRIT_COUNT(%edx) /* cleanup crit section count */
315         pushl   %esp            /* sp pointing to os user frame */
316         pushl   $-1             /* upcid */
317         pushl   $2              /* FETCH next */
318         call    upc_control
319         /* not reached */
320         /* just for show, restore Os supplied user context */
321         popl    %eax            /* code just for show */
322         popl    %ecx            /* code just for show */
323         popl    %edx            /* code just for show */
324         popfl                   /* code just for show */
325         ret                     /* code just for show */
326 .Ed
327
328 .Sh ERRORS
329 .Fn Upc_register
330 returns
331 .It Bq Er EFBIG
332 if the kernel has reached its upcall registration limit.  The limit is on a
333 per-shared-vmspace basis and is no less then 32.  Otherwise this function
334 returns a non-zero, positive number indicating the upcall identifier that
335 was registered.
336 .Pp
337 .Fh Upc_control
338 returns
339 .It Bq Er ENOENT
340 if a particular requested
341 .Fa upcid
342 cannot be found.
343 .Sh SEE ALSO
344 .Xr clone 3
345 .Sh HISTORY
346 The
347 .Fn upc_register
348 and 
349 .Fn upc_control
350 function calls
351 appeared in
352 DragonFly 1.0 .