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.10 2008/05/02 02:05:04 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"
129 .Bd -literal -offset indent
130 Dispatch a particular upcall.
133 is returned on success,
138 You can dispatch upcalls belonging to your process or
142 of -1 to re-dispatch the first upcall owned by your own process that is
143 pending from a previous operation.
144 Note that that critical section and
145 pending rules apply, and an actual dispatch will pushdown the stack.
147 The priority will be compared against the current crit_count to determine
148 whether the upcall dispatches or is made pending.
150 This command is most often used to alert a target process to a change in
151 a shared structure, queue, etc.
155 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
156 .Bd -literal -offset indent
157 Do interlocking and stack munging to process additional upcalls.
159 system call should never be made directly by C code because it expects
160 all registers not saved by the operating system in entering a context
161 function to have been popped and a pointer to the base of the OS-supplied
162 stack context on entry to the context routine to be supplied.
164 does not return to the caller but instead either regenerates the stack
165 context for the next pending upcall or it restores the original context,
166 resuming whomever was interrupted by the original upcall that entered the
171 .Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
172 .Bd -literal -offset indent
175 or, if -1 is specified, delete all upcall registered by the current process.
176 If -1 is specified, the upcalls registered by another process will not be
180 is specified, it will be deleted regardless of which process registered it.
181 The upcall structural pointer registered with this or any other process is
186 .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
189 .Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
190 .Bd -literal -offset indent
191 Poll or poll-and-clear the pending status for a particular upcall.
198 if an error occurred (e.g.
202 of -1 is specified, locate a pending upcall for the current process and return
205 or 0 if no upcalls for the current process are pending.
207 The priority will be compared against the upcall's pending priority.
209 upcalls with greater or equal pending priorities are returned. You must
210 specify a minimum priority of 1 or this call will simply return a random
211 registered upcall that may or may not be pending.
214 .Bd -literal -offset indent -compact
216 int magic; /* must be UPCALL_MAGIC */
217 int crit_count; /* critical section count */
218 int pending; /* additional upcalls are pending */
222 This is a user space structure a pointer to which is registered with the
228 field prevents new upcalls from being dispatched.
230 dispatched the kernel automatically adds
236 to indicate whether any additional upcalls are pending.
241 will prevent new upcalls from the being dispatched.
243 code is expected to make appropriate checks to dispatch any remaining upcalls
244 when the current upcall has completed.
245 In particular, the context function
250 before restoring the original context or calling
251 .Fn upc_control "UPC_CONTROL_NEXT" "..."
255 may be set as a side effect to various
257 system calls as well as as a side effect to upcall dispatches.
259 Userland threading code typically uses
261 to control critical sections within a virtual CPU (i.e., cloned process).
262 Entering a critical section is as simply as add
266 No atomic or locked instructions are required as this field is accessed
267 only by the current process and any upcalls or interrupts will restore it
268 to the condition they found it before returning.
269 Exiting a critical section
270 is almost as simple as subtracting
274 The routine which performs this function must also check the
276 field once the critical section count has reached 0.
278 is non-zero, the routine will generally call
279 .Fn upc_control "UPC_CONTROL_DISPATCH" "-1" "NULL"
280 to dispatch upcalls which were made pending while you were in the critical
282 .Sh CONTEXT FUNCTION - IA32
283 The context function is called with the stack pointer pointing at a
284 kernel-constructed stack frame.
285 Only a minimal number of registers are
288 .Bd -literal -offset indent -compact
298 On entry, %eax will hold the C function pointer, %ecx will hold the
299 C data pointer, and %edx will hold a pointer to the user-supplied upcall
301 The context code does not need to push %eax, %ecx, or %edx
302 because these registers have already been pushed on the stack for it, but
303 it must generally push any remaining registers that it might use and be
304 careful in regards to others, such as floating point registers, which
305 the OS has not saved.
306 The operating system has already adjusted the
310 fields in the user-supplied
312 structure, so the context code will generally next push the data pointer
313 (%ecx) and call the C function through %eax.
314 Upon return the context code
315 is responsible for interlocking the upcall return which it does by first
318 to 1, then subtracting
322 then restoring its part of the context but leaving the OS context intact,
324 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
326 The control function will not return.
327 It will either restart the context
328 at the next upcall, if more are pending, or it will restore the original
331 The context code does not have to follow this regime.
333 preventing the context code from restoring the original frame itself and
334 returning directly to the originally interrupted user code without having
335 to make another kernel transition.
336 It is possible to optimize this by
337 having the context code subtract down
339 as per normal but not pre-set the
341 field. If it does this and
343 is 0, it is possible for the kernel to initiate another upcall before
344 the context code has had a chance to pop its stack and restore the original
346 This is OK under controlled circumstances.
351 the context code knows there is another upcall pending and can call
355 .Bd -literal -offset indent -compact
357 * upc is a global pointing to this process's upcall structure
358 * (just as an example). The Os-supplied stack frame is:
360 * [%eax %ecx %edx,%eflags %original_ip]
363 pushl %edx /* save %edx (upcall pointer) */
364 pushl %ecx /* func=%eax(data=%ecx) */
365 call *%eax /* call the C function */
367 popl %edx /* restore the upcall pointer */
368 incl PENDING(%edx) /* setting pending stops upcalls */
369 subl $32,CRIT_COUNT(%edx) /* cleanup crit section count */
370 pushl %esp /* sp pointing to os user frame */
371 pushl $-1 /* upcid */
372 pushl $2 /* FETCH next */
375 /* just for show, restore Os supplied user context */
376 popl %eax /* code just for show */
377 popl %ecx /* code just for show */
378 popl %edx /* code just for show */
379 popfl /* code just for show */
380 ret /* code just for show */
389 if the kernel has reached its upcall registration limit.
391 per-shared-vmspace basis and is no less then 32.
392 Otherwise this function
393 returns a non-zero, positive number indicating the upcall identifier that
401 if a particular requested