1 .\" Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
2 .\" All rights reserved.
4 .\" Redistribution and use in source and binary forms, with or without
5 .\" modification, are permitted provided that the following conditions
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.
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
25 .\" $DragonFly: src/lib/libc/sys/upc_register.2,v 1.8 2006/11/17 23:01:21 swildner Exp $
33 .Nd configure and control upcalls
39 .Fn upc_register "struct upcall *upc" "upcall_func_t ctxfunc" "upcall_func_t cfunc" "void *data"
41 .Fn upc_control "int command" "int upcall_id" "void *data"
47 Note that the specified upcall structural pointer
48 is per-process, not per-upcall.
49 It points to a structure in user memory
50 that both the user and kernel manipulate to deal with upcall/critical-section
53 is a pointer to context save and restore code.
54 The native upcall interface
55 does not necessarily save and restore call-used registers.
57 is typically written in assembly and supplied by
60 is a pointer to a C style function and
62 is the data passed to it as an argument.
63 A positive upcall identifier
64 will be returned or -1 if an error occurred.
66 When an upcall is executed the
69 to the critical section count in the upcall
70 structure, push a minimal context (not even call-used), and pass the C
71 function and data pointers to
75 will then proceed to save appropriate state, call the C function, and
77 Cleanup typically involves an interlocking operation
80 in order to undo the critical section count and process any additional
81 pending upcalls atomically.
83 will typically pop most of its state, set upcall->pending to 1,
86 from upcall->crit_count, and call
87 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
88 which atomically handles any further pending upcalls and/or pops the
89 original stack context supplied to
91 and resumes the originally interrupted code.
92 This is all very complex which is why
97 Note that upcalls can only occur if the target process is not in a critical
99 If an upcall cannot be dispatched it will instead be made pending
100 and the pending field in the user-supplied upcall structure will be set to
102 Userland critical-section-exiting code must check the pending
103 bit and call the appropriate
105 function to handle any pending upcalls.
107 The upcall identifier space is shared amongst all processes sharing the
109 That is, all the processes created through
115 calls any process within this domain can generate an upcall on any other
116 process within this domain, including itself.
117 Each process typically
118 installs a different (per-process) upcall data structure.
123 is a multi-function system call capable of dispatching upcalls, handling
124 the context assembly function's interlocks, deleting upcalls, and polling
128 .Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority"
130 .Bd -literal -offset indent
131 Dispatch a particular upcall.
134 is returned on success,
139 You can dispatch upcalls belonging to your process or
143 of -1 to re-dispatch the first upcall owned by your own process that is
144 pending from a previous operation.
145 Note that that critical section and
146 pending rules apply, and an actual dispatch will pushdown the stack.
148 The priority will be compared against the current crit_count to determine
149 whether the upcall dispatches or is made pending.
151 This command is most often used to alert a target process to a change in
152 a shared structure, queue, etc.
156 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
158 .Bd -literal -offset indent
159 Do interlocking and stack munging to process additional upcalls.
161 system call should never be made directly by C code because it expects
162 all registers not saved by the operating system in entering a context
163 function to have been popped and a pointer to the base of the OS-supplied
164 stack context on entry to the context routine to be supplied.
166 does not return to the caller but instead either regenerates the stack
167 context for the next pending upcall or it restores the original context,
168 resuming whomever was interrupted by the original upcall that entered the
173 .Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
175 .Bd -literal -offset indent
178 or, if -1 is specified, delete all upcall registered by the current process.
179 If -1 is specified, the upcalls registered by another process will not be
183 is specified, it will be deleted regardless of which process registered it.
184 The upcall structural pointer registered with this or any other process is
189 .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
192 .Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
194 .Bd -literal -offset indent
195 Poll or poll-and-clear the pending status for a particular upcall.
202 if an error occurred (e.g.
206 of -1 is specified, locate a pending upcall for the current process and return
209 or 0 if no upcalls for the current process are pending.
211 The priority will be compared against the upcall's pending priority.
213 upcalls with greater or equal pending priorities are returned. You must
214 specify a minimum priority of 1 or this call will simply return a random
215 registered upcall that may or may not be pending.
218 .Bd -literal -offset indent -compact
220 int magic; /* must be UPCALL_MAGIC */
221 int crit_count; /* critical section count */
222 int pending; /* additional upcalls are pending */
226 This is a user space structure a pointer to which is registered with the
232 field prevents new upcalls from being dispatched.
234 dispatched the kernel automatically adds
240 to indicate whether any additional upcalls are pending.
245 will prevent new upcalls from the being dispatched.
247 code is expected to make appropriate checks to dispatch any remaining upcalls
248 when the current upcall has completed.
249 In particular, the context function
254 before restoring the original context or calling
255 .Fn upc_control "UPC_CONTROL_NEXT" "..."
259 may be set as a side effect to various
261 system calls as well as as a side effect to upcall dispatches.
263 Userland threading code typically uses
265 to control critical sections within a virtual CPU (i.e., cloned process).
266 Entering a critical section is as simply as add
270 No atomic or locked instructions are required as this field is accessed
271 only by the current process and any upcalls or interrupts will restore it
272 to the condition they found it before returning.
273 Exiting a critical section
274 is almost as simple as subtracting
278 The routine which performs this function must also check the
280 field once the critical section count has reached 0.
282 is non-zero, the routine will generally call
283 .Fn upc_control "UPC_CONTROL_DISPATCH" "-1" "NULL"
284 to dispatch upcalls which were made pending while you were in the critical
286 .Sh CONTEXT FUNCTION - IA32
287 The context function is called with the stack pointer pointing at a
288 kernel-constructed stack frame.
289 Only a minimal number of registers are
292 .Bd -literal -offset indent -compact
302 On entry, %eax will hold the C function pointer, %ecx will hold the
303 C data pointer, and %edx will hold a pointer to the user-supplied upcall
305 The context code does not need to push %eax, %ecx, or %edx
306 because these registers have already been pushed on the stack for it, but
307 it must generally push any remaining registers that it might use and be
308 careful in regards to others, such as floating point registers, which
309 the OS has not saved.
310 The operating system has already adjusted the
314 fields in the user-supplied
316 structure, so the context code will generally next push the data pointer
317 (%ecx) and call the C function through %eax.
318 Upon return the context code
319 is responsible for interlocking the upcall return which it does by first
322 to 1, then subtracting
326 then restoring its part of the context but leaving the OS context intact,
328 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
330 The control function will not return.
331 It will either restart the context
332 at the next upcall, if more are pending, or it will restore the original
335 The context code does not have to follow this regime.
337 preventing the context code from restoring the original frame itself and
338 returning directly to the originally interrupted user code without having
339 to make another kernel transition.
340 It is possible to optimize this by
341 having the context code subtract down
343 as per normal but not pre-set the
345 field. If it does this and
347 is 0, it is possible for the kernel to initiate another upcall before
348 the context code has had a chance to pop its stack and restore the original
350 This is OK under controlled circumstances.
355 the context code knows there is another upcall pending and can call
359 .Bd -literal -offset indent -compact
361 * upc is a global pointing to this process's upcall structure
362 * (just as an example). The Os-supplied stack frame is:
364 * [%eax %ecx %edx,%eflags %original_ip]
367 pushl %edx /* save %edx (upcall pointer) */
368 pushl %ecx /* func=%eax(data=%ecx) */
369 call *%eax /* call the C function */
371 popl %edx /* restore the upcall pointer */
372 incl PENDING(%edx) /* setting pending stops upcalls */
373 subl $32,CRIT_COUNT(%edx) /* cleanup crit section count */
374 pushl %esp /* sp pointing to os user frame */
375 pushl $-1 /* upcid */
376 pushl $2 /* FETCH next */
379 /* just for show, restore Os supplied user context */
380 popl %eax /* code just for show */
381 popl %ecx /* code just for show */
382 popl %edx /* code just for show */
383 popfl /* code just for show */
384 ret /* code just for show */
393 if the kernel has reached its upcall registration limit.
395 per-shared-vmspace basis and is no less then 32.
396 Otherwise this function
397 returns a non-zero, positive number indicating the upcall identifier that
405 if a particular requested