| Commit | Line | Data |
|---|---|---|
| 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 | .\" | |
| 8a7bdfea | 25 | .\" $DragonFly: src/lib/libc/sys/upc_register.2,v 1.10 2008/05/02 02:05:04 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 |
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 | |
| a5ecd468 MD |
50 | that both the user and kernel manipulate to deal with upcall/critical-section |
| 51 | interlocks. | |
| 52 | .Fa ctxfunc | |
| a559210f HP |
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 | |
| a5ecd468 | 57 | is typically written in assembly and supplied by |
| e38a3020 | 58 | .Em libc . |
| a5ecd468 MD |
59 | .Fa cfunc |
| 60 | is a pointer to a C style function and | |
| 61 | .Fa data | |
| a559210f HP |
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. | |
| a5ecd468 MD |
65 | .Pp |
| 66 | When an upcall is executed the | |
| a559210f | 67 | kernel will add |
| de1a0a27 | 68 | .Dv TDPRI_CRIT |
| a559210f | 69 | to the critical section count in the upcall |
| a5ecd468 MD |
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. | |
| 1bf4b486 SW |
74 | .Fa ctxfunc |
| 75 | will then proceed to save appropriate state, call the C function, and | |
| a559210f HP |
76 | deal with cleanup. |
| 77 | Cleanup typically involves an interlocking operation | |
| a5ecd468 | 78 | and a call to |
| a559210f | 79 | .Fn upc_control |
| a5ecd468 MD |
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, | |
| a559210f | 84 | subtract |
| de1a0a27 | 85 | .Dv TDPRI_CRIT |
| 1bf4b486 | 86 | from upcall->crit_count, and call |
| a5ecd468 MD |
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 | |
| a559210f HP |
91 | and resumes the originally interrupted code. |
| 92 | This is all very complex which is why | |
| e38a3020 | 93 | .Em libc |
| a5ecd468 MD |
94 | typically supplies |
| 95 | .Fa ctxfunc . | |
| 96 | .Pp | |
| 97 | Note that upcalls can only occur if the target process is not in a critical | |
| a559210f HP |
98 | section. |
| 99 | If an upcall cannot be dispatched it will instead be made pending | |
| a5ecd468 | 100 | and the pending field in the user-supplied upcall structure will be set to |
| a559210f HP |
101 | non-zero. |
| 102 | Userland critical-section-exiting code must check the pending | |
| a5ecd468 MD |
103 | bit and call the appropriate |
| 104 | .Fn upc_control | |
| 105 | function to handle any pending upcalls. | |
| 106 | .Pp | |
| a559210f HP |
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 | |
| a5ecd468 MD |
114 | .Fn upc_control |
| 115 | calls any process within this domain can generate an upcall on any other | |
| a559210f | 116 | process within this domain, including itself. |
| 1bf4b486 | 117 | Each process typically |
| a5ecd468 MD |
118 | installs a different (per-process) upcall data structure. |
| 119 | .Pp | |
| a559210f HP |
120 | The |
| 121 | .Fn upc_control | |
| 122 | function, | |
| a5ecd468 MD |
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 | |
| 093dd88e | 128 | .Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority" |
| 3bdb37ee | 129 | .Bd -literal -offset indent |
| a559210f HP |
130 | Dispatch a particular upcall. |
| 131 | The value | |
| 132 | .Li 0 | |
| 133 | is returned on success, | |
| 134 | .Er ENOENT | |
| 135 | if | |
| a5ecd468 | 136 | .Fa upcid |
| a559210f HP |
137 | does not exist. |
| 138 | You can dispatch upcalls belonging to your process or | |
| 139 | to another process. | |
| 140 | You may specify a | |
| a5ecd468 MD |
141 | .Fa upcid |
| 142 | of -1 to re-dispatch the first upcall owned by your own process that is | |
| a559210f HP |
143 | pending from a previous operation. |
| 144 | Note that that critical section and | |
| a5ecd468 MD |
145 | pending rules apply, and an actual dispatch will pushdown the stack. |
| 146 | .Pp | |
| 093dd88e MD |
147 | The priority will be compared against the current crit_count to determine |
| 148 | whether the upcall dispatches or is made pending. | |
| 149 | .Pp | |
| a5ecd468 MD |
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" | |
| 3bdb37ee | 156 | .Bd -literal -offset indent |
| a559210f HP |
157 | Do interlocking and stack munging to process additional upcalls. |
| 158 | This | |
| a5ecd468 MD |
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 | |
| a559210f HP |
162 | stack context on entry to the context routine to be supplied. |
| 163 | This routine | |
| a5ecd468 MD |
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" | |
| 3bdb37ee | 172 | .Bd -literal -offset indent |
| a5ecd468 MD |
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 | |
| a559210f HP |
177 | deleted. |
| 178 | If a particular | |
| a5ecd468 MD |
179 | .Fa upcid |
| 180 | is specified, it will be deleted regardless of which process registered it. | |
| 1bf4b486 | 181 | The upcall structural pointer registered with this or any other process is |
| a5ecd468 MD |
182 | not effected. |
| 183 | .Ed | |
| 184 | .Pp | |
| 185 | .Ft int | |
| 186 | .Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL" | |
| 187 | .Pp | |
| 188 | .Ft int | |
| 093dd88e | 189 | .Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority" |
| 3bdb37ee | 190 | .Bd -literal -offset indent |
| a559210f HP |
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. | |
| 1bf4b486 | 199 | .Er ENOENT ). |
| a5ecd468 MD |
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. | |
| 093dd88e | 206 | .Pp |
| a559210f HP |
207 | The priority will be compared against the upcall's pending priority. |
| 208 | Only | |
| 093dd88e MD |
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. | |
| a5ecd468 MD |
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 | |
| 1bf4b486 | 222 | This is a user space structure a pointer to which is registered with the |
| a5ecd468 MD |
223 | kernel via |
| 224 | .Fn upc_register | |
| 225 | \. | |
| 226 | The | |
| 227 | .Fa crit_count | |
| a559210f | 228 | field prevents new upcalls from being dispatched. |
| 1bf4b486 | 229 | When an upcall is |
| a5ecd468 | 230 | dispatched the kernel automatically adds |
| a559210f | 231 | .Dv UPC_CRITADD |
| 1bf4b486 | 232 | to |
| a5ecd468 MD |
233 | .Fa crit_count |
| 234 | and sets | |
| 235 | .Fa pending | |
| a559210f HP |
236 | to indicate whether any additional upcalls are pending. |
| 237 | A non-zero | |
| a5ecd468 MD |
238 | .Fa pending |
| 239 | OR | |
| 240 | .Fa crit_count | |
| a559210f HP |
241 | will prevent new upcalls from the being dispatched. |
| 242 | The context function | |
| a5ecd468 | 243 | code is expected to make appropriate checks to dispatch any remaining upcalls |
| a559210f HP |
244 | when the current upcall has completed. |
| 245 | In particular, the context function | |
| a5ecd468 MD |
246 | must subtract |
| 247 | .Va UPC_CRITADD | |
| 1bf4b486 | 248 | from |
| a5ecd468 MD |
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 | |
| a559210f HP |
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 | |
| a5ecd468 MD |
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 | |
| a559210f HP |
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 | |
| a5ecd468 MD |
273 | .Fa crit_count . |
| 274 | The routine which performs this function must also check the | |
| 275 | .Fa pending | |
| a559210f HP |
276 | field once the critical section count has reached 0. |
| 277 | If the pending field | |
| a5ecd468 MD |
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 | |
| 1bf4b486 | 283 | The context function is called with the stack pointer pointing at a |
| a559210f HP |
284 | kernel-constructed stack frame. |
| 285 | Only a minimal number of registers are | |
| 1bf4b486 | 286 | saved by the kernel. |
| a5ecd468 MD |
287 | .Pp |
| 288 | .Bd -literal -offset indent -compact | |
| 289 | frame { | |
| 290 | int32_t eax; | |
| 291 | int32_t ecx; | |
| 0a455ac5 | 292 | int32_t edx; |
| a5ecd468 MD |
293 | int32_t eflags; |
| 294 | int32_t origip; | |
| 295 | } | |
| 296 | .Ed | |
| 297 | .Pp | |
| a559210f | 298 | On entry, %eax will hold the C function pointer, %ecx will hold the |
| 0a455ac5 | 299 | C data pointer, and %edx will hold a pointer to the user-supplied upcall |
| a559210f HP |
300 | structure. |
| 301 | The context code does not need to push %eax, %ecx, or %edx | |
| 0a455ac5 MD |
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 | |
| a559210f HP |
305 | the OS has not saved. |
| 306 | The operating system has already adjusted the | |
| a5ecd468 MD |
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 | |
| a559210f HP |
313 | (%ecx) and call the C function through %eax. |
| 314 | Upon return the context code | |
| a5ecd468 MD |
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 | \. | |
| a559210f HP |
326 | The control function will not return. |
| 327 | It will either restart the context | |
| a5ecd468 MD |
328 | at the next upcall, if more are pending, or it will restore the original |
| 329 | context. | |
| 330 | .Pp | |
| a559210f HP |
331 | The context code does not have to follow this regime. |
| 332 | There is nothing | |
| a5ecd468 MD |
333 | preventing the context code from restoring the original frame itself and |
| 334 | returning directly to the originally interrupted user code without having | |
| a559210f HP |
335 | to make another kernel transition. |
| 336 | It is possible to optimize this by | |
| a5ecd468 MD |
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 | |
| 1bf4b486 | 342 | .Fa pending |
| a5ecd468 MD |
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 | |
| a559210f HP |
345 | user context. |
| 346 | This is OK under controlled circumstances. | |
| 347 | On the other hand, | |
| a5ecd468 | 348 | if |
| 1bf4b486 | 349 | .Fa pending |
| a5ecd468 MD |
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 | * | |
| 0a455ac5 | 360 | * [%eax %ecx %edx,%eflags %original_ip] |
| a5ecd468 MD |
361 | */ |
| 362 | callused_wrapper: | |
| 0a455ac5 | 363 | pushl %edx /* save %edx (upcall pointer) */ |
| a5ecd468 MD |
364 | pushl %ecx /* func=%eax(data=%ecx) */ |
| 365 | call *%eax /* call the C function */ | |
| 366 | addl $4,%esp | |
| 0a455ac5 MD |
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 */ | |
| a5ecd468 MD |
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 */ | |
| 0a455ac5 | 378 | popl %edx /* code just for show */ |
| a5ecd468 MD |
379 | popfl /* code just for show */ |
| 380 | ret /* code just for show */ | |
| 381 | .Ed | |
| a5ecd468 | 382 | .Sh ERRORS |
| a559210f HP |
383 | The |
| 384 | .Fn upc_register | |
| 385 | function | |
| 386 | returns: | |
| 387 | .Bl -tag -width Er | |
| a5ecd468 | 388 | .It Bq Er EFBIG |
| a559210f HP |
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 | |
| a5ecd468 MD |
393 | returns a non-zero, positive number indicating the upcall identifier that |
| 394 | was registered. | |
| 395 | .Pp | |
| a559210f HP |
396 | The |
| 397 | .Fn upc_control | |
| 398 | function | |
| a5ecd468 MD |
399 | returns |
| 400 | .It Bq Er ENOENT | |
| 401 | if a particular requested | |
| 402 | .Fa upcid | |
| 403 | cannot be found. | |
| a559210f | 404 | .El |
| a5ecd468 | 405 | .Sh SEE ALSO |
| a559210f | 406 | .Xr rfork 2 , |
| a5ecd468 MD |
407 | .Xr clone 3 |
| 408 | .Sh HISTORY | |
| 409 | The | |
| 410 | .Fn upc_register | |
| 1bf4b486 | 411 | and |
| a5ecd468 MD |
412 | .Fn upc_control |
| 413 | function calls | |
| 414 | appeared in | |
| a3220ac5 | 415 | .Dx 1.0 . |