Fix .Xr abuse.
[dragonfly.git] / lib / libc / sys / upc_register.2
CommitLineData
a5ecd468
MD
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.\"
e38a3020 25.\" $DragonFly: src/lib/libc/sys/upc_register.2,v 1.8 2006/11/17 23:01:21 swildner Exp $
a5ecd468
MD
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
a559210f
HP
43The
44.Fn upc_register
45function
46registers an upcall.
47Note that the specified upcall structural pointer
48is per-process, not per-upcall.
49It points to a structure in user memory
a5ecd468
MD
50that both the user and kernel manipulate to deal with upcall/critical-section
51interlocks.
52.Fa ctxfunc
a559210f
HP
53is a pointer to context save and restore code.
54The native upcall interface
55does not necessarily save and restore call-used registers.
56This function
a5ecd468 57is typically written in assembly and supplied by
e38a3020 58.Em libc .
a5ecd468
MD
59.Fa cfunc
60is a pointer to a C style function and
61.Fa data
a559210f
HP
62is the data passed to it as an argument.
63A positive upcall identifier
64will be returned or -1 if an error occurred.
a5ecd468
MD
65.Pp
66When an upcall is executed the
a559210f
HP
67kernel will add
68.Dv LWKT_CRITPRI
69to the critical section count in the upcall
a5ecd468
MD
70structure, push a minimal context (not even call-used), and pass the C
71function and data pointers to
72.Fa ctxfunc
73in registers.
1bf4b486
SW
74.Fa ctxfunc
75will then proceed to save appropriate state, call the C function, and
a559210f
HP
76deal with cleanup.
77Cleanup typically involves an interlocking operation
a5ecd468 78and a call to
a559210f 79.Fn upc_control
a5ecd468
MD
80in order to undo the critical section count and process any additional
81pending upcalls atomically.
82.Fa ctxfunc
83will typically pop most of its state, set upcall->pending to 1,
a559210f
HP
84subtract
85.Dv LWKT_CRITPRI
1bf4b486 86from upcall->crit_count, and call
a5ecd468
MD
87.Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
88which atomically handles any further pending upcalls and/or pops the
89original stack context supplied to
90.Fn upc_control
a559210f
HP
91and resumes the originally interrupted code.
92This is all very complex which is why
e38a3020 93.Em libc
a5ecd468
MD
94typically supplies
95.Fa ctxfunc .
96.Pp
97Note that upcalls can only occur if the target process is not in a critical
a559210f
HP
98section.
99If an upcall cannot be dispatched it will instead be made pending
a5ecd468 100and the pending field in the user-supplied upcall structure will be set to
a559210f
HP
101non-zero.
102Userland critical-section-exiting code must check the pending
a5ecd468
MD
103bit and call the appropriate
104.Fn upc_control
105function to handle any pending upcalls.
106.Pp
a559210f
HP
107The upcall identifier space is shared amongst all processes sharing the
108same VM space.
109That is, all the processes created through
110.Fn clone
111or
112.Fn rfork "RFMEM" .
113Through appropriate
a5ecd468
MD
114.Fn upc_control
115calls any process within this domain can generate an upcall on any other
a559210f 116process within this domain, including itself.
1bf4b486 117Each process typically
a5ecd468
MD
118installs a different (per-process) upcall data structure.
119.Pp
a559210f
HP
120The
121.Fn upc_control
122function,
a5ecd468
MD
123is a multi-function system call capable of dispatching upcalls, handling
124the context assembly function's interlocks, deleting upcalls, and polling
125for upcalls.
126.Pp
127.Ft int
093dd88e 128.Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority"
a5ecd468 129.Pp
3bdb37ee 130.Bd -literal -offset indent
a559210f
HP
131Dispatch a particular upcall.
132The value
133.Li 0
134is returned on success,
135.Er ENOENT
136if
a5ecd468 137.Fa upcid
a559210f
HP
138does not exist.
139You can dispatch upcalls belonging to your process or
140to another process.
141You may specify a
a5ecd468
MD
142.Fa upcid
143of -1 to re-dispatch the first upcall owned by your own process that is
a559210f
HP
144pending from a previous operation.
145Note that that critical section and
a5ecd468
MD
146pending rules apply, and an actual dispatch will pushdown the stack.
147.Pp
093dd88e
MD
148The priority will be compared against the current crit_count to determine
149whether the upcall dispatches or is made pending.
150.Pp
a5ecd468
MD
151This command is most often used to alert a target process to a change in
152a shared structure, queue, etc.
153.Ed
154.Pp
155.Ft int
156.Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
157.Pp
3bdb37ee 158.Bd -literal -offset indent
a559210f
HP
159Do interlocking and stack munging to process additional upcalls.
160This
a5ecd468
MD
161system call should never be made directly by C code because it expects
162all registers not saved by the operating system in entering a context
163function to have been popped and a pointer to the base of the OS-supplied
a559210f
HP
164stack context on entry to the context routine to be supplied.
165This routine
a5ecd468
MD
166does not return to the caller but instead either regenerates the stack
167context for the next pending upcall or it restores the original context,
168resuming whomever was interrupted by the original upcall that entered the
169context routine.
170.Ed
171.Pp
172.Ft int
173.Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
174.Pp
3bdb37ee 175.Bd -literal -offset indent
a5ecd468
MD
176Delete the specified
177.Fa upcid
178or, if -1 is specified, delete all upcall registered by the current process.
179If -1 is specified, the upcalls registered by another process will not be
a559210f
HP
180deleted.
181If a particular
a5ecd468
MD
182.Fa upcid
183is specified, it will be deleted regardless of which process registered it.
1bf4b486 184The upcall structural pointer registered with this or any other process is
a5ecd468
MD
185not effected.
186.Ed
187.Pp
188.Ft int
189.Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
190.Pp
191.Ft int
093dd88e 192.Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
a5ecd468 193.Pp
3bdb37ee 194.Bd -literal -offset indent
a559210f
HP
195Poll or poll-and-clear the pending status for a particular upcall.
196The value
197.Li 0
198or
199.Li 1
200is returned, or
201.Li -1
202if an error occurred (e.g.
1bf4b486 203.Er ENOENT ).
a5ecd468
MD
204If a
205.Fa upcid
206of -1 is specified, locate a pending upcall for the current process and return
207it's
208.Fa upcid ,
209or 0 if no upcalls for the current process are pending.
093dd88e 210.Pp
a559210f
HP
211The priority will be compared against the upcall's pending priority.
212Only
093dd88e
MD
213upcalls with greater or equal pending priorities are returned. You must
214specify a minimum priority of 1 or this call will simply return a random
215registered upcall that may or may not be pending.
a5ecd468
MD
216.Ed
217.Pp
218.Bd -literal -offset indent -compact
219struct upcall {
220 int magic; /* must be UPCALL_MAGIC */
221 int crit_count; /* critical section count */
222 int pending; /* additional upcalls are pending */
223};
224.Ed
225.Pp
1bf4b486 226This is a user space structure a pointer to which is registered with the
a5ecd468
MD
227kernel via
228.Fn upc_register
229\.
230The
231.Fa crit_count
a559210f 232field prevents new upcalls from being dispatched.
1bf4b486 233When an upcall is
a5ecd468 234dispatched the kernel automatically adds
a559210f 235.Dv UPC_CRITADD
1bf4b486 236to
a5ecd468
MD
237.Fa crit_count
238and sets
239.Fa pending
a559210f
HP
240to indicate whether any additional upcalls are pending.
241A non-zero
a5ecd468
MD
242.Fa pending
243OR
244.Fa crit_count
a559210f
HP
245will prevent new upcalls from the being dispatched.
246The context function
a5ecd468 247code is expected to make appropriate checks to dispatch any remaining upcalls
a559210f
HP
248when the current upcall has completed.
249In particular, the context function
a5ecd468
MD
250must subtract
251.Va UPC_CRITADD
1bf4b486 252from
a5ecd468
MD
253.Fa crit_count
254before restoring the original context or calling
255.Fn upc_control "UPC_CONTROL_NEXT" "..."
256\.
257Note that
258.Fa pending
259may be set as a side effect to various
260.Fn upc_control
261system calls as well as as a side effect to upcall dispatches.
262.Pp
263Userland threading code typically uses
264.Fa crit_count
a559210f
HP
265to control critical sections within a virtual CPU (i.e., cloned process).
266Entering a critical section is as simply as add
267.Dv UPC_CRITADD
268to
a5ecd468
MD
269.Fa crit_count .
270No atomic or locked instructions are required as this field is accessed
271only by the current process and any upcalls or interrupts will restore it
a559210f
HP
272to the condition they found it before returning.
273Exiting a critical section
274is almost as simple as subtracting
275.Dv UPC_CRITADD
276from
a5ecd468
MD
277.Fa crit_count .
278The routine which performs this function must also check the
279.Fa pending
a559210f
HP
280field once the critical section count has reached 0.
281If the pending field
a5ecd468
MD
282is non-zero, the routine will generally call
283.Fn upc_control "UPC_CONTROL_DISPATCH" "-1" "NULL"
284to dispatch upcalls which were made pending while you were in the critical
285section.
286.Sh CONTEXT FUNCTION - IA32
1bf4b486 287The context function is called with the stack pointer pointing at a
a559210f
HP
288kernel-constructed stack frame.
289Only a minimal number of registers are
1bf4b486 290saved by the kernel.
a5ecd468
MD
291.Pp
292.Bd -literal -offset indent -compact
293frame {
294 int32_t eax;
295 int32_t ecx;
0a455ac5 296 int32_t edx;
a5ecd468
MD
297 int32_t eflags;
298 int32_t origip;
299}
300.Ed
301.Pp
a559210f 302On entry, %eax will hold the C function pointer, %ecx will hold the
0a455ac5 303C data pointer, and %edx will hold a pointer to the user-supplied upcall
a559210f
HP
304structure.
305The context code does not need to push %eax, %ecx, or %edx
0a455ac5
MD
306because these registers have already been pushed on the stack for it, but
307it must generally push any remaining registers that it might use and be
308careful in regards to others, such as floating point registers, which
a559210f
HP
309the OS has not saved.
310The operating system has already adjusted the
a5ecd468
MD
311.Fa crit_count
312and
313.Fa pending
314fields in the user-supplied
315.Fa upcall
316structure, so the context code will generally next push the data pointer
a559210f
HP
317(%ecx) and call the C function through %eax.
318Upon return the context code
a5ecd468
MD
319is responsible for interlocking the upcall return which it does by first
320setting
321.Fa pending
322to 1, then subtracting
323.Va UPC_CRITADD
324from
325.Fa crit_count ,
326then restoring its part of the context but leaving the OS context intact,
327then calling
328.Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
329\.
a559210f
HP
330The control function will not return.
331It will either restart the context
a5ecd468
MD
332at the next upcall, if more are pending, or it will restore the original
333context.
334.Pp
a559210f
HP
335The context code does not have to follow this regime.
336There is nothing
a5ecd468
MD
337preventing the context code from restoring the original frame itself and
338returning directly to the originally interrupted user code without having
a559210f
HP
339to make another kernel transition.
340It is possible to optimize this by
a5ecd468
MD
341having the context code subtract down
342.Va UPC_CRITADD
343as per normal but not pre-set the
344.Fa pending
345field. If it does this and
1bf4b486 346.Fa pending
a5ecd468
MD
347is 0, it is possible for the kernel to initiate another upcall before
348the context code has had a chance to pop its stack and restore the original
a559210f
HP
349user context.
350This is OK under controlled circumstances.
351On the other hand,
a5ecd468 352if
1bf4b486 353.Fa pending
a5ecd468
MD
354is 1
355the context code knows there is another upcall pending and can call
356.Fn upc_control
357as appropriate.
358.Pp
359.Bd -literal -offset indent -compact
360 /*
361 * upc is a global pointing to this process's upcall structure
362 * (just as an example). The Os-supplied stack frame is:
363 *
0a455ac5 364 * [%eax %ecx %edx,%eflags %original_ip]
a5ecd468
MD
365 */
366callused_wrapper:
0a455ac5 367 pushl %edx /* save %edx (upcall pointer) */
a5ecd468
MD
368 pushl %ecx /* func=%eax(data=%ecx) */
369 call *%eax /* call the C function */
370 addl $4,%esp
0a455ac5
MD
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 */
a5ecd468
MD
374 pushl %esp /* sp pointing to os user frame */
375 pushl $-1 /* upcid */
376 pushl $2 /* FETCH next */
377 call upc_control
378 /* not reached */
379 /* just for show, restore Os supplied user context */
380 popl %eax /* code just for show */
381 popl %ecx /* code just for show */
0a455ac5 382 popl %edx /* code just for show */
a5ecd468
MD
383 popfl /* code just for show */
384 ret /* code just for show */
385.Ed
a5ecd468 386.Sh ERRORS
a559210f
HP
387The
388.Fn upc_register
389function
390returns:
391.Bl -tag -width Er
a5ecd468 392.It Bq Er EFBIG
a559210f
HP
393if the kernel has reached its upcall registration limit.
394The limit is on a
395per-shared-vmspace basis and is no less then 32.
396Otherwise this function
a5ecd468
MD
397returns a non-zero, positive number indicating the upcall identifier that
398was registered.
399.Pp
a559210f
HP
400The
401.Fn upc_control
402function
a5ecd468
MD
403returns
404.It Bq Er ENOENT
405if a particular requested
406.Fa upcid
407cannot be found.
a559210f 408.El
a5ecd468 409.Sh SEE ALSO
a559210f 410.Xr rfork 2 ,
a5ecd468
MD
411.Xr clone 3
412.Sh HISTORY
413The
414.Fn upc_register
1bf4b486 415and
a5ecd468
MD
416.Fn upc_control
417function calls
418appeared in
a3220ac5 419.Dx 1.0 .