Merge branch 'vendor/ZLIB'
[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.10 2008/05/02 02:05:04 swildner 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 The
44 .Fn upc_register
45 function
46 registers an upcall.
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
51 interlocks.
52 .Fa ctxfunc
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.
56 This function
57 is typically written in assembly and supplied by
58 .Em libc .
59 .Fa cfunc
60 is a pointer to a C style function and
61 .Fa data
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.
65 .Pp
66 When an upcall is executed the
67 kernel will add
68 .Dv TDPRI_CRIT
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
72 .Fa ctxfunc
73 in registers.
74 .Fa ctxfunc
75 will then proceed to save appropriate state, call the C function, and
76 deal with cleanup.
77 Cleanup typically involves an interlocking operation
78 and a call to
79 .Fn upc_control
80 in order to undo the critical section count and process any additional
81 pending upcalls atomically.
82 .Fa ctxfunc
83 will typically pop most of its state, set upcall->pending to 1,
84 subtract
85 .Dv TDPRI_CRIT
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
90 .Fn upc_control
91 and resumes the originally interrupted code.
92 This is all very complex which is why
93 .Em libc
94 typically supplies
95 .Fa ctxfunc .
96 .Pp
97 Note that upcalls can only occur if the target process is not in a critical
98 section.
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
101 non-zero.
102 Userland critical-section-exiting code must check the pending
103 bit and call the appropriate
104 .Fn upc_control
105 function to handle any pending upcalls.
106 .Pp
107 The upcall identifier space is shared amongst all processes sharing the
108 same VM space.
109 That is, all the processes created through
110 .Fn clone
111 or
112 .Fn rfork "RFMEM" .
113 Through appropriate
114 .Fn upc_control
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.
119 .Pp
120 The
121 .Fn upc_control
122 function,
123 is a multi-function system call capable of dispatching upcalls, handling
124 the context assembly function's interlocks, deleting upcalls, and polling
125 for upcalls.
126 .Pp
127 .Ft int
128 .Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority"
129 .Bd -literal -offset indent
130 Dispatch a particular upcall.
131 The value
132 .Li 0
133 is returned on success,
134 .Er ENOENT
135 if
136 .Fa upcid
137 does not exist.
138 You can dispatch upcalls belonging to your process or
139 to another process.
140 You may specify a
141 .Fa upcid
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.
146 .Pp
147 The priority will be compared against the current crit_count to determine
148 whether the upcall dispatches or is made pending.
149 .Pp
150 This command is most often used to alert a target process to a change in
151 a shared structure, queue, etc.
152 .Ed
153 .Pp
154 .Ft int
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.
158 This
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.
163 This routine
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
167 context routine.
168 .Ed
169 .Pp
170 .Ft int
171 .Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
172 .Bd -literal -offset indent
173 Delete the specified
174 .Fa upcid
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
177 deleted.
178 If a particular
179 .Fa upcid
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
182 not effected.
183 .Ed
184 .Pp
185 .Ft int
186 .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
187 .Pp
188 .Ft int
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.
192 The value
193 .Li 0
194 or
195 .Li 1
196 is returned, or
197 .Li -1
198 if an error occurred (e.g.
199 .Er ENOENT ).
200 If a
201 .Fa upcid
202 of -1 is specified, locate a pending upcall for the current process and return
203 it's
204 .Fa upcid ,
205 or 0 if no upcalls for the current process are pending.
206 .Pp
207 The priority will be compared against the upcall's pending priority.
208 Only
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.
212 .Ed
213 .Pp
214 .Bd -literal -offset indent -compact
215 struct upcall {
216         int     magic;          /* must be UPCALL_MAGIC */
217         int     crit_count;     /* critical section count */
218         int     pending;        /* additional upcalls are pending */
219 };
220 .Ed
221 .Pp
222 This is a user space structure a pointer to which is registered with the
223 kernel via
224 .Fn upc_register
225 \.
226 The
227 .Fa crit_count
228 field prevents new upcalls from being dispatched.
229 When an upcall is
230 dispatched the kernel automatically adds
231 .Dv UPC_CRITADD
232 to
233 .Fa crit_count
234 and sets
235 .Fa pending
236 to indicate whether any additional upcalls are pending.
237 A non-zero
238 .Fa pending
239 OR
240 .Fa crit_count
241 will prevent new upcalls from the being dispatched.
242 The context function
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
246 must subtract
247 .Va UPC_CRITADD
248 from
249 .Fa crit_count
250 before restoring the original context or calling
251 .Fn upc_control "UPC_CONTROL_NEXT" "..."
252 \.
253 Note that
254 .Fa pending
255 may be set as a side effect to various
256 .Fn upc_control
257 system calls as well as as a side effect to upcall dispatches.
258 .Pp
259 Userland threading code typically uses
260 .Fa crit_count
261 to control critical sections within a virtual CPU (i.e., cloned process).
262 Entering a critical section is as simply as add
263 .Dv UPC_CRITADD
264 to
265 .Fa crit_count .
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
271 .Dv UPC_CRITADD
272 from
273 .Fa crit_count .
274 The routine which performs this function must also check the
275 .Fa pending
276 field once the critical section count has reached 0.
277 If the pending field
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
281 section.
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
286 saved by the kernel.
287 .Pp
288 .Bd -literal -offset indent -compact
289 frame {
290     int32_t     eax;
291     int32_t     ecx;
292     int32_t     edx;
293     int32_t     eflags;
294     int32_t     origip;
295 }
296 .Ed
297 .Pp
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
300 structure.
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
307 .Fa crit_count
308 and
309 .Fa pending
310 fields in the user-supplied
311 .Fa upcall
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
316 setting
317 .Fa pending
318 to 1, then subtracting
319 .Va UPC_CRITADD
320 from
321 .Fa crit_count ,
322 then restoring its part of the context but leaving the OS context intact,
323 then calling
324 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
325 \.
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
329 context.
330 .Pp
331 The context code does not have to follow this regime.
332 There is nothing
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
338 .Va UPC_CRITADD
339 as per normal but not pre-set the
340 .Fa pending
341 field.  If it does this and
342 .Fa pending
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
345 user context.
346 This is OK under controlled circumstances.
347 On the other hand,
348 if
349 .Fa pending
350 is 1
351 the context code knows there is another upcall pending and can call
352 .Fn upc_control
353 as appropriate.
354 .Pp
355 .Bd -literal -offset indent -compact
356         /*
357          * upc is a global pointing to this process's upcall structure
358          * (just as an example).  The Os-supplied stack frame is:
359          *
360          *      [%eax %ecx %edx,%eflags %original_ip]
361          */
362 callused_wrapper:
363         pushl   %edx            /* save %edx (upcall pointer) */
364         pushl   %ecx            /* func=%eax(data=%ecx) */
365         call    *%eax           /* call the C function */
366         addl    $4,%esp
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 */
373         call    upc_control
374         /* not reached */
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 */
381 .Ed
382 .Sh ERRORS
383 The
384 .Fn upc_register
385 function
386 returns:
387 .Bl -tag -width Er
388 .It Bq Er EFBIG
389 if the kernel has reached its upcall registration limit.
390 The limit is on a
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
394 was registered.
395 .Pp
396 The
397 .Fn upc_control
398 function
399 returns
400 .It Bq Er ENOENT
401 if a particular requested
402 .Fa upcid
403 cannot be found.
404 .El
405 .Sh SEE ALSO
406 .Xr rfork 2 ,
407 .Xr clone 3
408 .Sh HISTORY
409 The
410 .Fn upc_register
411 and
412 .Fn upc_control
413 function calls
414 appeared in
415 .Dx 1.0 .