upc_register man page on DragonFly

Man page or keyword search:  
man Server   44335 pages
apropos Keyword Search (all sections)
Output format
DragonFly logo
[printable version]

UPC_REGISTER(2)		    BSD System Calls Manual	       UPC_REGISTER(2)

NAME
     upc_register, upc_control — configure and control upcalls

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <sys/upcall.h>

     int
     upc_register(struct upcall *upc, upcall_func_t ctxfunc,
	 upcall_func_t cfunc, void *data);

     int
     upc_control(int command, int upcall_id, void *data);

DESCRIPTION
     The upc_register() function registers an upcall.  Note that the specified
     upcall structural pointer is per-process, not per-upcall.	It points to a
     structure in user memory that both the user and kernel manipulate to deal
     with upcall/critical-section interlocks.  ctxfunc is a pointer to context
     save and restore code.  The native upcall interface does not necessarily
     save and restore call-used registers.  This function is typically written
     in assembly and supplied by libc.	cfunc is a pointer to a C style func‐
     tion and data is the data passed to it as an argument.  A positive upcall
     identifier will be returned or -1 if an error occurred.

     When an upcall is executed the kernel will add TDPRI_CRIT to the critical
     section count in the upcall structure, push a minimal context (not even
     call-used), and pass the C function and data pointers to ctxfunc in reg‐
     isters.  ctxfunc will then proceed to save appropriate state, call the C
     function, and deal with cleanup.  Cleanup typically involves an inter‐
     locking operation and a call to upc_control() in order to undo the criti‐
     cal section count and process any additional pending upcalls atomically.
     ctxfunc will typically pop most of its state, set upcall->pending to 1,
     subtract TDPRI_CRIT from upcall->crit_count, and call
     upc_control(UPC_CONTROL_NEXT, -1, stack_pointer) which atomically handles
     any further pending upcalls and/or pops the original stack context sup‐
     plied to upc_control() and resumes the originally interrupted code.  This
     is all very complex which is why libc typically supplies ctxfunc.

     Note that upcalls can only occur if the target process is not in a criti‐
     cal section.  If an upcall cannot be dispatched it will instead be made
     pending and the pending field in the user-supplied upcall structure will
     be set to non-zero.  Userland critical-section-exiting code must check
     the pending bit and call the appropriate upc_control() function to handle
     any pending upcalls.

     The upcall identifier space is shared amongst all processes sharing the
     same VM space.  That is, all the processes created through clone() or
     rfork(RFMEM).  Through appropriate upc_control() calls any process within
     this domain can generate an upcall on any other process within this
     domain, including itself.	Each process typically installs a different
     (per-process) upcall data structure.

     The upc_control() function, is a multi-function system call capable of
     dispatching upcalls, handling the context assembly function's interlocks,
     deleting upcalls, and polling for upcalls.

     int upc_control(UPC_CONTROL_DISPATCH, upcid, (int)priority)

	   Dispatch a particular upcall.
	   The value
	   0
	   is returned on success,
	   ENOENT
	   if
	   upcid
	   does not exist.
	   You can dispatch upcalls belonging to your process or
	   to another process.
	   You may specify a
	   upcid
	   of -1 to re-dispatch the first upcall owned by your own process that is
	   pending from a previous operation.
	   Note that that critical section and
	   pending rules apply, and an actual dispatch will pushdown the stack.

	   The priority will be compared against the current crit_count to determine
	   whether the upcall dispatches or is made pending.

	   This command is most often used to alert a target process to a change in
	   a shared structure, queue, etc.

     int upc_control(UPC_CONTROL_NEXT, -1, stack_pointer)

	   Do interlocking and stack munging to process additional upcalls.
	   This
	   system call should never be made directly by C code because it expects
	   all registers not saved by the operating system in entering a context
	   function to have been popped and a pointer to the base of the OS-supplied
	   stack context on entry to the context routine to be supplied.
	   This routine
	   does not return to the caller but instead either regenerates the stack
	   context for the next pending upcall or it restores the original context,
	   resuming whomever was interrupted by the original upcall that entered the
	   context routine.

     int upc_control(UPC_CONTROL_DELETE, upcid, NULL)

	   Delete the specified
	   upcid
	   or, if -1 is specified, delete all upcall registered by the current process.
	   If -1 is specified, the upcalls registered by another process will not be
	   deleted.
	   If a particular
	   upcid
	   is specified, it will be deleted regardless of which process registered it.
	   The upcall structural pointer registered with this or any other process is
	   not effected.

     int upc_control(UPC_CONTROL_POLL, upcid, NULL)

     int upc_control(UPC_CONTROL_POLLANDCLEAR, upcid, (int)priority)

	   Poll or poll-and-clear the pending status for a particular upcall.
	   The value
	   0
	   or
	   1
	   is returned, or
	   -1
	   if an error occurred (e.g.
	   ENOENT ).
	   If a
	   upcid
	   of -1 is specified, locate a pending upcall for the current process and return
	   it's
	   upcid,
	   or 0 if no upcalls for the current process are pending.

	   The priority will be compared against the upcall's pending priority.
	   Only
	   upcalls with greater or equal pending priorities are returned.  You must
	   specify a minimum priority of 1 or this call will simply return a random
	   registered upcall that may or may not be pending.

	   struct upcall {
		   int	   magic;	   /* must be UPCALL_MAGIC */
		   int	   crit_count;	   /* critical section count */
		   int	   pending;	   /* additional upcalls are pending */
	   };

     This is a user space structure a pointer to which is registered with the
     kernel via upc_register() The crit_count field prevents new upcalls from
     being dispatched.	When an upcall is dispatched the kernel automatically
     adds UPC_CRITADD to crit_count and sets pending to indicate whether any
     additional upcalls are pending.  A non-zero pending OR crit_count will
     prevent new upcalls from the being dispatched.  The context function code
     is expected to make appropriate checks to dispatch any remaining upcalls
     when the current upcall has completed.  In particular, the context func‐
     tion must subtract UPC_CRITADD from crit_count before restoring the orig‐
     inal context or calling upc_control(UPC_CONTROL_NEXT, ...)	 Note that
     pending may be set as a side effect to various upc_control() system calls
     as well as as a side effect to upcall dispatches.

     Userland threading code typically uses crit_count to control critical
     sections within a virtual CPU (i.e., cloned process).  Entering a criti‐
     cal section is as simply as add UPC_CRITADD to crit_count.	 No atomic or
     locked instructions are required as this field is accessed only by the
     current process and any upcalls or interrupts will restore it to the con‐
     dition they found it before returning.  Exiting a critical section is
     almost as simple as subtracting UPC_CRITADD from crit_count.  The routine
     which performs this function must also check the pending field once the
     critical section count has reached 0.  If the pending field is non-zero,
     the routine will generally call upc_control(UPC_CONTROL_DISPATCH, -1,
     NULL) to dispatch upcalls which were made pending while you were in the
     critical section.

CONTEXT FUNCTION - IA32
     The context function is called with the stack pointer pointing at a ker‐
     nel-constructed stack frame.  Only a minimal number of registers are
     saved by the kernel.

	   frame {
	       int32_t	   eax;
	       int32_t	   ecx;
	       int32_t	   edx;
	       int32_t	   eflags;
	       int32_t	   origip;
	   }

     On entry, %eax will hold the C function pointer, %ecx will hold the C
     data pointer, and %edx will hold a pointer to the user-supplied upcall
     structure.	 The context code does not need to push %eax, %ecx, or %edx
     because these registers have already been pushed on the stack for it, but
     it must generally push any remaining registers that it might use and be
     careful in regards to others, such as floating point registers, which the
     OS has not saved.	The operating system has already adjusted the
     crit_count and pending fields in the user-supplied upcall structure, so
     the context code will generally next push the data pointer (%ecx) and
     call the C function through %eax.	Upon return the context code is
     responsible for interlocking the upcall return which it does by first
     setting pending to 1, then subtracting UPC_CRITADD from crit_count, then
     restoring its part of the context but leaving the OS context intact, then
     calling upc_control(UPC_CONTROL_NEXT, -1, stack_pointer_to_OS_context)
     The control function will not return.  It will either restart the context
     at the next upcall, if more are pending, or it will restore the original
     context.

     The context code does not have to follow this regime.  There is nothing
     preventing the context code from restoring the original frame itself and
     returning directly to the originally interrupted user code without having
     to make another kernel transition.	 It is possible to optimize this by
     having the context code subtract down UPC_CRITADD as per normal but not
     pre-set the pending field.	 If it does this and pending is 0, it is pos‐
     sible for the kernel to initiate another upcall before the context code
     has had a chance to pop its stack and restore the original user context.
     This is OK under controlled circumstances.	 On the other hand, if pending
     is 1 the context code knows there is another upcall pending and can call
     upc_control() as appropriate.

		   /*
		    * upc is a global pointing to this process's upcall structure
		    * (just as an example).  The Os-supplied stack frame is:
		    *
		    *	   [%eax %ecx %edx,%eflags %original_ip]
		    */
	   callused_wrapper:
		   pushl   %edx		   /* save %edx (upcall pointer) */
		   pushl   %ecx		   /* func=%eax(data=%ecx) */
		   call	   *%eax	   /* call the C function */
		   addl	   $4,%esp
		   popl	   %edx		   /* restore the upcall pointer */
		   incl	   PENDING(%edx)   /* setting pending stops upcalls */
		   subl	   $32,CRIT_COUNT(%edx) /* cleanup crit section count */
		   pushl   %esp		   /* sp pointing to os user frame */
		   pushl   $-1		   /* upcid */
		   pushl   $2		   /* FETCH next */
		   call	   upc_control
		   /* not reached */
		   /* just for show, restore Os supplied user context */
		   popl	   %eax		   /* code just for show */
		   popl	   %ecx		   /* code just for show */
		   popl	   %edx		   /* code just for show */
		   popfl		   /* code just for show */
		   ret			   /* code just for show */

ERRORS
     The upc_register() function returns:

     [EFBIG]		if the kernel has reached its upcall registration
			limit.	The limit is on a per-shared-vmspace basis and
			is no less then 32.  Otherwise this function returns a
			non-zero, positive number indicating the upcall iden‐
			tifier that was registered.

			The upc_control() function returns

     [ENOENT]		if a particular requested upcid cannot be found.

SEE ALSO
     rfork(2), clone(3)

HISTORY
     The upc_register() and upc_control() function calls appeared in
     DragonFly 1.0.

BSD			       November 20, 2003			   BSD
[top]

List of man pages available for DragonFly

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net