46d29a3dcc013e6827c065980cf23d549f06515f
[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.7 2005/12/10 00:22:28 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 .Xr libc 3 .
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 LWKT_CRITPRI
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 LWKT_CRITPRI
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 .Xr libc 3
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 .Pp
130 .Bd -literal -offset indent
131 Dispatch a particular upcall.
132 The value
133 .Li 0
134 is returned on success,
135 .Er ENOENT
136 if
137 .Fa upcid
138 does not exist.
139 You can dispatch upcalls belonging to your process or
140 to another process.
141 You may specify a
142 .Fa upcid
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.
147 .Pp
148 The priority will be compared against the current crit_count to determine
149 whether the upcall dispatches or is made pending.
150 .Pp
151 This command is most often used to alert a target process to a change in
152 a shared structure, queue, etc.
153 .Ed
154 .Pp
155 .Ft int
156 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
157 .Pp
158 .Bd -literal -offset indent
159 Do interlocking and stack munging to process additional upcalls.
160 This
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.
165 This routine
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
169 context routine.
170 .Ed
171 .Pp
172 .Ft int
173 .Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
174 .Pp
175 .Bd -literal -offset indent
176 Delete the specified
177 .Fa upcid
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
180 deleted.
181 If a particular
182 .Fa upcid
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
185 not effected.
186 .Ed
187 .Pp
188 .Ft int
189 .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
190 .Pp
191 .Ft int
192 .Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
193 .Pp
194 .Bd -literal -offset indent
195 Poll or poll-and-clear the pending status for a particular upcall.
196 The value
197 .Li 0
198 or
199 .Li 1
200 is returned, or
201 .Li -1
202 if an error occurred (e.g.
203 .Er ENOENT ).
204 If a
205 .Fa upcid
206 of -1 is specified, locate a pending upcall for the current process and return
207 it's
208 .Fa upcid ,
209 or 0 if no upcalls for the current process are pending.
210 .Pp
211 The priority will be compared against the upcall's pending priority.
212 Only
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.
216 .Ed
217 .Pp
218 .Bd -literal -offset indent -compact
219 struct 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
226 This is a user space structure a pointer to which is registered with the
227 kernel via
228 .Fn upc_register
229 \.
230 The
231 .Fa crit_count
232 field prevents new upcalls from being dispatched.
233 When an upcall is
234 dispatched the kernel automatically adds
235 .Dv UPC_CRITADD
236 to
237 .Fa crit_count
238 and sets
239 .Fa pending
240 to indicate whether any additional upcalls are pending.
241 A non-zero
242 .Fa pending
243 OR
244 .Fa crit_count
245 will prevent new upcalls from the being dispatched.
246 The context function
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
250 must subtract
251 .Va UPC_CRITADD
252 from
253 .Fa crit_count
254 before restoring the original context or calling
255 .Fn upc_control "UPC_CONTROL_NEXT" "..."
256 \.
257 Note that
258 .Fa pending
259 may be set as a side effect to various
260 .Fn upc_control
261 system calls as well as as a side effect to upcall dispatches.
262 .Pp
263 Userland threading code typically uses
264 .Fa crit_count
265 to control critical sections within a virtual CPU (i.e., cloned process).
266 Entering a critical section is as simply as add
267 .Dv UPC_CRITADD
268 to
269 .Fa crit_count .
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
275 .Dv UPC_CRITADD
276 from
277 .Fa crit_count .
278 The routine which performs this function must also check the
279 .Fa pending
280 field once the critical section count has reached 0.
281 If the pending field
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
285 section.
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
290 saved by the kernel.
291 .Pp
292 .Bd -literal -offset indent -compact
293 frame {
294     int32_t     eax;
295     int32_t     ecx;
296     int32_t     edx;
297     int32_t     eflags;
298     int32_t     origip;
299 }
300 .Ed
301 .Pp
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
304 structure.
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
311 .Fa crit_count
312 and
313 .Fa pending
314 fields in the user-supplied
315 .Fa upcall
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
320 setting
321 .Fa pending
322 to 1, then subtracting
323 .Va UPC_CRITADD
324 from
325 .Fa crit_count ,
326 then restoring its part of the context but leaving the OS context intact,
327 then calling
328 .Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer_to_OS_context"
329 \.
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
333 context.
334 .Pp
335 The context code does not have to follow this regime.
336 There is nothing
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
342 .Va UPC_CRITADD
343 as per normal but not pre-set the
344 .Fa pending
345 field.  If it does this and
346 .Fa pending
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
349 user context.
350 This is OK under controlled circumstances.
351 On the other hand,
352 if
353 .Fa pending
354 is 1
355 the context code knows there is another upcall pending and can call
356 .Fn upc_control
357 as 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          *
364          *      [%eax %ecx %edx,%eflags %original_ip]
365          */
366 callused_wrapper:
367         pushl   %edx            /* save %edx (upcall pointer) */
368         pushl   %ecx            /* func=%eax(data=%ecx) */
369         call    *%eax           /* call the C function */
370         addl    $4,%esp
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 */
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 */
382         popl    %edx            /* code just for show */
383         popfl                   /* code just for show */
384         ret                     /* code just for show */
385 .Ed
386 .Sh ERRORS
387 The
388 .Fn upc_register
389 function
390 returns:
391 .Bl -tag -width Er
392 .It Bq Er EFBIG
393 if the kernel has reached its upcall registration limit.
394 The limit is on a
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
398 was registered.
399 .Pp
400 The
401 .Fn upc_control
402 function
403 returns
404 .It Bq Er ENOENT
405 if a particular requested
406 .Fa upcid
407 cannot be found.
408 .El
409 .Sh SEE ALSO
410 .Xr rfork 2 ,
411 .Xr clone 3
412 .Sh HISTORY
413 The
414 .Fn upc_register
415 and
416 .Fn upc_control
417 function calls
418 appeared in
419 .Dx 1.0 .