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/libcr/sys/Attic/upc_register.2,v 1.1 2003/12/08 13:56:36 eirikn 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"
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
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
54 is a pointer to a C style function and
56 is the data passed to it as an argument. A positive upcall identifier
57 will be returned or -1 if an error occured.
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
66 will then proceed to save appropriate state, call the C function, and
67 deal with cleanup. Cleanup typically involves an interlocking operation
70 in order to undo the critical section count and process any additional
71 pending upcalls atomically.
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
79 and resumes the originally interrupted code. This is all very complex
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
91 function to handle any pending upcalls.
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
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.
102 is a multi-function system call capable of dispatching upcalls, handling
103 the context assembly function's interlocks, deleting upcalls, and polling
107 .Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority"
110 Dispatch a particular upcall. 0 is returned on success, ENOENT if
112 does not exist. You can dispatch upcalls belonging to your process or
113 to another process. You may specify a
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.
119 The priority will be compared against the current crit_count to determine
120 whether the upcall dispatches or is made pending.
122 This command is most often used to alert a target process to a change in
123 a shared structure, queue, etc.
127 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
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
142 .Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
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
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
157 .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
160 .Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
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).
167 of -1 is specified, locate a pending upcall for the current process and return
170 or 0 if no upcalls for the current process are pending.
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.
178 .Bd -literal -offset indent -compact
180 int magic; /* must be UPCALL_MAGIC */
181 int crit_count; /* critical section count */
182 int pending; /* additional upcalls are pending */
186 This is a user space structure a pointer to which is registered with the
192 field prevents new upcalls from being dispatched. When an upcall is
193 dispatched the kernel automatically adds
199 to indicate whether any additional upcalls are pending. A non-zero
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
210 before restoring the original context or calling
211 .Fn upc_control "UPC_CONTROL_NEXT" "..."
215 may be set as a side effect to various
217 system calls as well as as a side effect to upcall dispatches.
219 Userland threading code typically uses
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
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
229 The routine which performs this function must also check the
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
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
241 .Bd -literal -offset indent -compact
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
261 fields in the user-supplied
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
268 to 1, then subtracting
272 then restoring its part of the context but leaving the OS context intact,
274 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
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
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
286 as per normal but not pre-set the
288 field. If it does this and
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,
296 the context code knows there is another upcall pending and can call
300 .Bd -literal -offset indent -compact
302 * upc is a global pointing to this process's upcall structure
303 * (just as an example). The Os-supplied stack frame is:
305 * [%eax %ecx %edx,%eflags %original_ip]
308 pushl %edx /* save %edx (upcall pointer) */
309 pushl %ecx /* func=%eax(data=%ecx) */
310 call *%eax /* call the C function */
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 */
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 */
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
340 if a particular requested