It's no longer used for anything.
Requested-by: vsrinivas
Approved-by: dillon
TO_REMOVE+=/usr/share/man/man8/i386/stlstty.8.gz
TO_REMOVE+=/usr/libdata/stallion
TO_REMOVE+=/usr/include/bus/isa/isa_compat.h
+TO_REMOVE+=/usr/include/sys/upcall.h
+TO_REMOVE+=/usr/share/man/cat2/upc_control.2.gz
+TO_REMOVE+=/usr/share/man/man2/upc_control.2.gz
+TO_REMOVE+=/usr/share/man/cat2/upc_register.2.gz
+TO_REMOVE+=/usr/share/man/man2/upc_register.2.gz
.if ${MACHINE_ARCH} == "x86_64"
TO_REMOVE+=/usr/sbin/stlstats
sigstack.2 sigsuspend.2 socket.2 socketpair.2 stat.2 statfs.2 \
statvfs.2 swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 syslink.2 \
truncate.2 tls.2 umask.2 umtx.2 undelete.2 \
- unlink.2 unlinkat.2 utimes.2 utrace.2 upc_register.2 usched_set.2 \
+ unlink.2 unlinkat.2 utimes.2 utrace.2 usched_set.2 \
uuidgen.2 \
varsym.2 vfork.2 vquotactl.2 wait.2 write.2
MLINKS+=tls.2 set_tls_area.2 tls.2 get_tls_area.2
MLINKS+=truncate.2 ftruncate.2
MLINKS+=umtx.2 umtx_sleep.2 umtx.2 umtx_wakeup.2
-MLINKS+=upc_register.2 upc_control.2
MLINKS+=utimes.2 futimes.2 utimes.2 lutimes.2
MLINKS+=varsym.2 varsym_get.2 \
varsym.2 varsym_list.2 \
+++ /dev/null
-.\" Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $DragonFly: src/lib/libc/sys/upc_register.2,v 1.10 2008/05/02 02:05:04 swildner Exp $
-.\"
-.Dd November 20, 2003
-.Dt UPC_REGISTER 2
-.Os
-.Sh NAME
-.Nm upc_register ,
-.Nm upc_control
-.Nd configure and control upcalls
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In sys/upcall.h
-.Ft int
-.Fn upc_register "struct upcall *upc" "upcall_func_t ctxfunc" "upcall_func_t cfunc" "void *data"
-.Ft int
-.Fn upc_control "int command" "int upcall_id" "void *data"
-.Sh DESCRIPTION
-The
-.Fn 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.
-.Fa 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
-.Em libc .
-.Fa cfunc
-is a pointer to a C style function and
-.Fa data
-is the data passed to it as an argument.
-A positive upcall identifier
-will be returned or -1 if an error occurred.
-.Pp
-When an upcall is executed the
-kernel will add
-.Dv 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
-.Fa ctxfunc
-in registers.
-.Fa ctxfunc
-will then proceed to save appropriate state, call the C function, and
-deal with cleanup.
-Cleanup typically involves an interlocking operation
-and a call to
-.Fn upc_control
-in order to undo the critical section count and process any additional
-pending upcalls atomically.
-.Fa ctxfunc
-will typically pop most of its state, set upcall->pending to 1,
-subtract
-.Dv TDPRI_CRIT
-from upcall->crit_count, and call
-.Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
-which atomically handles any further pending upcalls and/or pops the
-original stack context supplied to
-.Fn upc_control
-and resumes the originally interrupted code.
-This is all very complex which is why
-.Em libc
-typically supplies
-.Fa ctxfunc .
-.Pp
-Note that upcalls can only occur if the target process is not in a critical
-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
-.Fn upc_control
-function to handle any pending upcalls.
-.Pp
-The upcall identifier space is shared amongst all processes sharing the
-same VM space.
-That is, all the processes created through
-.Fn clone
-or
-.Fn rfork "RFMEM" .
-Through appropriate
-.Fn 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.
-.Pp
-The
-.Fn 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.
-.Pp
-.Ft int
-.Fn upc_control "UPC_CONTROL_DISPATCH" "upcid" "(int)priority"
-.Bd -literal -offset indent
-Dispatch a particular upcall.
-The value
-.Li 0
-is returned on success,
-.Er ENOENT
-if
-.Fa upcid
-does not exist.
-You can dispatch upcalls belonging to your process or
-to another process.
-You may specify a
-.Fa 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.
-.Pp
-The priority will be compared against the current crit_count to determine
-whether the upcall dispatches or is made pending.
-.Pp
-This command is most often used to alert a target process to a change in
-a shared structure, queue, etc.
-.Ed
-.Pp
-.Ft int
-.Fn upc_control "UPC_CONTROL_NEXT" "-1" "stack_pointer"
-.Bd -literal -offset indent
-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.
-.Ed
-.Pp
-.Ft int
-.Fn upc_control "UPC_CONTROL_DELETE" "upcid" "NULL"
-.Bd -literal -offset indent
-Delete the specified
-.Fa 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
-.Fa 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.
-.Ed
-.Pp
-.Ft int
-.Fn upc_control "UPC_CONTROL_POLL" "upcid" "NULL"
-.Pp
-.Ft int
-.Fn upc_control "UPC_CONTROL_POLLANDCLEAR" "upcid" "(int)priority"
-.Bd -literal -offset indent
-Poll or poll-and-clear the pending status for a particular upcall.
-The value
-.Li 0
-or
-.Li 1
-is returned, or
-.Li -1
-if an error occurred (e.g.
-.Er ENOENT ).
-If a
-.Fa upcid
-of -1 is specified, locate a pending upcall for the current process and return
-it's
-.Fa upcid ,
-or 0 if no upcalls for the current process are pending.
-.Pp
-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.
-.Ed
-.Pp
-.Bd -literal -offset indent -compact
-struct upcall {
- int magic; /* must be UPCALL_MAGIC */
- int crit_count; /* critical section count */
- int pending; /* additional upcalls are pending */
-};
-.Ed
-.Pp
-This is a user space structure a pointer to which is registered with the
-kernel via
-.Fn upc_register
-\.
-The
-.Fa crit_count
-field prevents new upcalls from being dispatched.
-When an upcall is
-dispatched the kernel automatically adds
-.Dv UPC_CRITADD
-to
-.Fa crit_count
-and sets
-.Fa pending
-to indicate whether any additional upcalls are pending.
-A non-zero
-.Fa pending
-OR
-.Fa 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 function
-must subtract
-.Va UPC_CRITADD
-from
-.Fa crit_count
-before restoring the original context or calling
-.Fn upc_control "UPC_CONTROL_NEXT" "..."
-\.
-Note that
-.Fa pending
-may be set as a side effect to various
-.Fn upc_control
-system calls as well as as a side effect to upcall dispatches.
-.Pp
-Userland threading code typically uses
-.Fa crit_count
-to control critical sections within a virtual CPU (i.e., cloned process).
-Entering a critical section is as simply as add
-.Dv UPC_CRITADD
-to
-.Fa 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 condition they found it before returning.
-Exiting a critical section
-is almost as simple as subtracting
-.Dv UPC_CRITADD
-from
-.Fa crit_count .
-The routine which performs this function must also check the
-.Fa pending
-field once the critical section count has reached 0.
-If the pending field
-is non-zero, the routine will generally call
-.Fn upc_control "UPC_CONTROL_DISPATCH" "-1" "NULL"
-to dispatch upcalls which were made pending while you were in the critical
-section.
-.Sh CONTEXT FUNCTION - IA32
-The context function is called with the stack pointer pointing at a
-kernel-constructed stack frame.
-Only a minimal number of registers are
-saved by the kernel.
-.Pp
-.Bd -literal -offset indent -compact
-frame {
- int32_t eax;
- int32_t ecx;
- int32_t edx;
- int32_t eflags;
- int32_t origip;
-}
-.Ed
-.Pp
-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
-.Fa crit_count
-and
-.Fa pending
-fields in the user-supplied
-.Fa 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
-.Fa pending
-to 1, then subtracting
-.Va UPC_CRITADD
-from
-.Fa crit_count ,
-then restoring its part of the context but leaving the OS context intact,
-then calling
-.Fn 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.
-.Pp
-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
-.Va UPC_CRITADD
-as per normal but not pre-set the
-.Fa pending
-field. If it does this and
-.Fa pending
-is 0, it is possible 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
-.Fa pending
-is 1
-the context code knows there is another upcall pending and can call
-.Fn upc_control
-as appropriate.
-.Pp
-.Bd -literal -offset indent -compact
- /*
- * 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 */
-.Ed
-.Sh ERRORS
-The
-.Fn upc_register
-function
-returns:
-.Bl -tag -width Er
-.It Bq Er 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 identifier that
-was registered.
-.Pp
-The
-.Fn upc_control
-function
-returns
-.It Bq Er ENOENT
-if a particular requested
-.Fa upcid
-cannot be found.
-.El
-.Sh SEE ALSO
-.Xr rfork 2 ,
-.Xr clone 3
-.Sh HISTORY
-The
-.Fn upc_register
-and
-.Fn upc_control
-function calls
-appeared in
-.Dx 1.0 .
kern/kern_sig.c standard
kern/kern_memio.c standard
kern/kern_udev.c standard
-kern/kern_upcall.c standard
kern/kern_sfbuf.c standard
kern/kern_subr.c standard
kern/kern_iosched.c standard
*
* from: @(#)cpu.h 5.4 (Berkeley) 5/9/91
* $FreeBSD: src/sys/i386/include/cpu.h,v 1.43.2.2 2001/06/15 09:37:57 scottl Exp $
- * $DragonFly: src/sys/cpu/i386/include/cpu.h,v 1.25 2007/03/01 01:46:52 corecode Exp $
*/
#ifndef _CPU_CPU_H_
atomic_set_int(&mycpu->gd_reqflags, RQF_IPIQ)
#define signotify() \
atomic_set_int(&mycpu->gd_reqflags, RQF_AST_SIGNAL)
-#define sigupcall() \
- atomic_set_int(&mycpu->gd_reqflags, RQF_AST_UPCALL)
#define clear_user_resched() \
atomic_clear_int(&mycpu->gd_reqflags, RQF_AST_USER_RESCHED)
#define clear_lwkt_resched() \
*
* from: @(#)cpu.h 5.4 (Berkeley) 5/9/91
* $FreeBSD: src/sys/i386/include/cpu.h,v 1.43.2.2 2001/06/15 09:37:57 scottl Exp $
- * $DragonFly: src/sys/cpu/i386/include/cpu.h,v 1.25 2007/03/01 01:46:52 corecode Exp $
*/
#ifndef _CPU_CPU_H_
atomic_set_int(&mycpu->gd_reqflags, RQF_IPIQ)
#define signotify() \
atomic_set_int(&mycpu->gd_reqflags, RQF_AST_SIGNAL)
-#define sigupcall() \
- atomic_set_int(&mycpu->gd_reqflags, RQF_AST_UPCALL)
#define clear_user_resched() \
atomic_clear_int(&mycpu->gd_reqflags, RQF_AST_USER_RESCHED)
#define clear_lwkt_resched() \
{ AS(varsym_set_args), (sy_call_t *)sys_varsym_set }, /* 450 = varsym_set */
{ AS(varsym_get_args), (sy_call_t *)sys_varsym_get }, /* 451 = varsym_get */
{ AS(varsym_list_args), (sy_call_t *)sys_varsym_list }, /* 452 = varsym_list */
- { AS(upc_register_args), (sy_call_t *)sys_upc_register }, /* 453 = upc_register */
- { AS(upc_control_args), (sy_call_t *)sys_upc_control }, /* 454 = upc_control */
+ { 0, (sy_call_t *)sys_nosys }, /* 453 = obsolete upc_register */
+ { 0, (sy_call_t *)sys_nosys }, /* 454 = obsolete upc_control */
{ 0, (sy_call_t *)sys_nosys }, /* 455 = obsolete caps_sys_service */
{ 0, (sy_call_t *)sys_nosys }, /* 456 = obsolete caps_sys_client */
{ 0, (sy_call_t *)sys_nosys }, /* 457 = obsolete caps_sys_close */
map = &vmspace->vm_map;
} else if (vmspace->vm_sysref.refcnt == 1) {
shmexit(vmspace);
- if (vmspace->vm_upcalls)
- upc_release(vmspace, ONLY_LWP_IN_PROC(imgp->proc));
pmap_remove_pages(vmspace_pmap(vmspace),
0, VM_MAX_USER_ADDRESS);
vm_map_remove(map, 0, VM_MAX_USER_ADDRESS);
#include <sys/sem.h>
#include <sys/jail.h>
#include <sys/kern_syscall.h>
-#include <sys/upcall.h>
#include <sys/unistd.h>
#include <sys/eventhandler.h>
#include <sys/dsched.h>
vm = p->p_vmspace;
/*
- * Release upcalls associated with this process
- */
- if (vm->vm_upcalls)
- upc_release(vm, lp);
-
- /*
* Clean up data related to virtual kernel operation. Clean up
* any vkernel context related to the current lwp now so we can
* destroy p_vkernel.
+++ /dev/null
-/*
- * Copyright (c) 2003,2004,2006 The DragonFly Project. All rights reserved.
- *
- * This code is derived from software contributed to The DragonFly Project
- * by Matthew Dillon <dillon@backplane.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name of The DragonFly Project nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific, prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Implement upcall registration and dispatch.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/upcall.h>
-#include <sys/thread2.h>
-#include <sys/malloc.h>
-#include <sys/sysproto.h>
-#include <sys/lock.h>
-#include <sys/signalvar.h>
-
-#include <sys/mplock2.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-
-#include <machine/cpu.h>
-
-MALLOC_DEFINE(M_UPCALL, "upcalls", "upcall registration structures");
-
-static void
-sigupcall_remote(void *arg)
-{
- struct lwp *lp = arg;
- if (lp == lwkt_preempted_proc())
- sigupcall();
-}
-
-/*
- * upc_register:
- *
- * Register an upcall context wrapper and procedure. Note that the
- * upcall context is set globally for the process, not for each upcall.
- *
- * ARGS(struct upcall *upc, upcall_func_t ctx, upcall_func_t func, void *data)
- *
- * MPALMOSTSAFE
- */
-int
-sys_upc_register(struct upc_register_args *uap)
-{
- struct lwp *lp = curthread->td_lwp;
- struct vmspace *vm = curproc->p_vmspace;
- struct vmupcall *vu;
-
- /*
- * Note: inconsequential MP race
- */
- if (vm->vm_upccount >= UPCALL_MAXCOUNT)
- return(EFBIG);
-
- vu = kmalloc(sizeof(struct vmupcall), M_UPCALL, M_WAITOK|M_ZERO);
- vu->vu_ctx = uap->ctxfunc;
- vu->vu_func = uap->func;
- vu->vu_data = uap->data;
- vu->vu_lwp = lp;
- lp->lwp_upcall = uap->upc;
-
- get_mplock();
- if (vm->vm_upcalls != NULL)
- vu->vu_id = vm->vm_upcalls->vu_id + 1;
- else
- vu->vu_id = UPC_RESERVED;
- vu->vu_next = vm->vm_upcalls;
- vm->vm_upcalls = vu;
- ++vm->vm_upccount;
- rel_mplock();
- uap->sysmsg_result = vu->vu_id;
- return(0);
-}
-
-/*
- * upc_control:
- *
- * ARGS(int cmd, int upcid, void *data)
- *
- * MPALMOSTSAFE
- */
-int
-sys_upc_control(struct upc_control_args *uap)
-{
- struct lwp *lp = curthread->td_lwp;
- struct lwp *targlp;
- struct vmspace *vms = curproc->p_vmspace;
- struct vmupcall *vu;
- struct vmupcall *vu_send;
- struct vmupcall **vupp;
- int error;
-
- get_mplock();
- switch(uap->cmd) {
- case UPC_CONTROL_DISPATCH:
- /*
- * Dispatch the specified upcall id or the next pending id if -1.
- * the upcall will be marked pending but an actual upcall will only
- * occur if userland is not in a critical section and the userland
- * pending bit is not set.
- *
- * You can dispatch an upcall associated with your process or another
- * process sharing the same VM space.
- */
- error = (uap->upcid == -1) ? 0 : ENOENT;
- for (vu = vms->vm_upcalls; vu; vu = vu->vu_next) {
- if (vu->vu_id == uap->upcid ||
- (uap->upcid == -1 &&
- vu->vu_pending >= (int)(intptr_t)uap->data && vu->vu_lwp == lp)
- ) {
- if (vu->vu_pending < (int)(intptr_t)uap->data)
- vu->vu_pending = (int)(intptr_t)uap->data;
- error = 0;
- targlp = vu->vu_lwp;
- targlp->lwp_proc->p_flags |= P_UPCALLPEND; /* XXX lwp flags */
- if (targlp->lwp_proc->p_flags & P_UPCALLWAIT)
- wakeup(&targlp->lwp_upcall);
- if (targlp->lwp_thread->td_gd != mycpu)
- lwkt_send_ipiq(targlp->lwp_thread->td_gd, sigupcall_remote, targlp);
- else
- sigupcall();
- break;
- }
- }
- break;
- case UPC_CONTROL_NEXT:
- /*
- * This is used by the context code to fetch the next pending upcall.
- * The context code has two choices: (A) it can drop
- * upcall->crit_count and set upcall->pending then make this call
- * unconditionally or * (B) it can drop upcall->crit_count and then
- * test upcall->pending and only make this call if upcall->pending
- * is set. If upcall->pending is clear the context code can pop
- * the upcall stack itself and return without entering into the kernel
- * again. (B) is more efficient but leaves a small window of
- * opportunity where multiple upcalls can pushdown the stack.
- *
- * If another upcall is pending the crit_count will be bumped and
- * the function, data, and context pointers will be returned in
- * registers (C cannot call this routine). If no more upcalls are
- * pending the pending bit will be cleared and the 'data' argument
- * is expected to be pointing at the upcall context which we will
- * then pop, returning to the original code that was interrupted
- * (NOT the context code).
- */
- vu_send = NULL;
- for (vu = vms->vm_upcalls; vu; vu = vu->vu_next) {
- if (vu->vu_lwp == lp && vu->vu_pending) {
- if (vu_send)
- break;
- vu_send = vu;
- }
- }
- /*
- * vu_send may be NULL, indicating that no more upcalls are pending
- * for this cpu. We set the userland pending bit based on whether
- * additional upcalls are pending or not.
- */
- error = fetchupcall(vu_send, vu != NULL, uap->data);
- break;
- case UPC_CONTROL_DELETE:
- /*
- * Delete the specified upcall id. If the upcall id is -1, delete
- * all upcall id's associated with the current process.
- */
- error = (uap->upcid == -1) ? 0 : ENOENT;
- vupp = &vms->vm_upcalls;
- while ((vu = *vupp) != NULL) {
- if (vu->vu_id == uap->upcid ||
- (uap->upcid == -1 && vu->vu_lwp == lp)
- ) {
- *vupp = vu->vu_next;
- error = 0;
- kfree(vu, M_UPCALL);
- } else {
- vupp = &vu->vu_next;
- }
- }
- break;
- case UPC_CONTROL_POLL:
- case UPC_CONTROL_POLLANDCLEAR:
- case UPC_CONTROL_WAIT:
- /*
- * If upcid is -1 poll for the first pending upcall and return the
- * id or 0 if no upcalls are pending.
- *
- * If upcid is a particular upcall then poll that upcall and return
- * its pending status (0 or 1). For POLLANDCLEAR, also clear the
- * pending status. The userland pending bit is not modified by
- * this call (maybe we should modify it for poll-and-clear).
- */
- error = (uap->upcid == -1) ? 0 : ENOENT;
- for (vu = vms->vm_upcalls; vu; vu = vu->vu_next) {
- if (vu->vu_id == uap->upcid ||
- (uap->upcid == -1 &&
- vu->vu_pending >= (int)(intptr_t)uap->data && vu->vu_lwp == lp)
- ) {
- error = 0;
- if (uap->upcid == -1)
- uap->sysmsg_result = vu->vu_id;
- else
- uap->sysmsg_result = vu->vu_pending;
- if (uap->cmd == UPC_CONTROL_POLLANDCLEAR)
- vu->vu_pending = 0;
- break;
- }
- }
- if (uap->cmd == UPC_CONTROL_WAIT && vu == NULL) {
- lp->lwp_proc->p_flags |= P_UPCALLWAIT; /* XXX lwp flags */
- tsleep(&lp->lwp_upcall, PCATCH, "wupcall", 0);
- lp->lwp_proc->p_flags &= ~P_UPCALLWAIT; /* XXX lwp flags */
- }
- break;
- default:
- error = EINVAL;
- break;
- }
- rel_mplock();
- return(error);
-}
-
-void
-upc_release(struct vmspace *vm, struct lwp *lp)
-{
- struct vmupcall **vupp;
- struct vmupcall *vu;
-
- vupp = &vm->vm_upcalls;
- while ((vu = *vupp) != NULL) {
- if (vu->vu_lwp == lp) {
- *vupp = vu->vu_next;
- kfree(vu, M_UPCALL);
- --vm->vm_upccount;
- } else {
- vupp = &vu->vu_next;
- }
- }
-}
-
-/*
- * XXX eventually we should sort by vu_pending priority and dispatch
- * the highest priority upcall first.
- */
-void
-postupcall(struct lwp *lp)
-{
- struct vmspace *vm = lp->lwp_proc->p_vmspace;
- struct vmupcall *vu;
- struct vmupcall *vu_send = NULL;
-
- for (vu = vm->vm_upcalls; vu; vu = vu->vu_next) {
- if (vu->vu_lwp == lp && vu->vu_pending) {
- if (vu_send) {
- sendupcall(vu, 1);
- return;
- }
- vu_send = vu;
- }
- }
- if (vu_send)
- sendupcall(vu_send, 0);
-}
-
"varsym_set", /* 450 = varsym_set */
"varsym_get", /* 451 = varsym_get */
"varsym_list", /* 452 = varsym_list */
- "upc_register", /* 453 = upc_register */
- "upc_control", /* 454 = upc_control */
+ "obs_upc_register", /* 453 = obsolete upc_register */
+ "obs_upc_control", /* 454 = obsolete upc_control */
"obs_caps_sys_service", /* 455 = obsolete caps_sys_service */
"obs_caps_sys_client", /* 456 = obsolete caps_sys_client */
"obs_caps_sys_close", /* 457 = obsolete caps_sys_close */
450 STD BSD { int varsym_set(int level, const char *name, const char *data); }
451 STD BSD { int varsym_get(int mask, const char *wild, char *buf, int bufsize); }
452 STD BSD { int varsym_list(int level, char *buf, int maxsize, int *marker); }
-453 STD BSD { int upc_register(struct upcall *upc, void *ctxfunc, void *func, void *data); }
-454 STD BSD { int upc_control(int cmd, int upcid, void *data); }
+453 OBSOL BSD upc_register
+454 OBSOL BSD upc_control
455 OBSOL BSD caps_sys_service
456 OBSOL BSD caps_sys_client
457 OBSOL BSD caps_sys_close
ASSYM(RQF_AST_SIGNAL, RQF_AST_SIGNAL);
ASSYM(RQF_AST_USER_RESCHED, RQF_AST_USER_RESCHED);
ASSYM(RQF_AST_LWKT_RESCHED, RQF_AST_LWKT_RESCHED);
-ASSYM(RQF_AST_UPCALL, RQF_AST_UPCALL);
ASSYM(RQF_TIMER, RQF_TIMER);
ASSYM(RQF_AST_MASK, RQF_AST_MASK);
* to do is a reschedule.
*/
doreti_ast:
- andl $~(RQF_AST_SIGNAL|RQF_AST_UPCALL),PCPU(reqflags)
+ andl $~RQF_AST_SIGNAL,PCPU(reqflags)
sti
movl %eax,%esi /* save cpl (can't use stack) */
movl $T_ASTFLT,TF_TRAPNO(%esp)
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/bus.h>
-#include <sys/upcall.h>
#include <sys/usched.h>
#include <sys/reg.h>
}
/*
- * Stack frame on entry to function. %eax will contain the function vector,
- * %ecx will contain the function data. flags, ecx, and eax will have
- * already been pushed on the stack.
- */
-struct upc_frame {
- register_t eax;
- register_t ecx;
- register_t edx;
- register_t flags;
- register_t oldip;
-};
-
-void
-sendupcall(struct vmupcall *vu, int morepending)
-{
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- struct upcall upcall;
- struct upc_frame upc_frame;
- int crit_count = 0;
-
- /*
- * If we are a virtual kernel running an emulated user process
- * context, switch back to the virtual kernel context before
- * trying to post the signal.
- */
- if (lp->lwp_vkernel && lp->lwp_vkernel->ve) {
- lp->lwp_md.md_regs->tf_trapno = 0;
- vkernel_trap(lp, lp->lwp_md.md_regs);
- }
-
- /*
- * Get the upcall data structure
- */
- if (copyin(lp->lwp_upcall, &upcall, sizeof(upcall)) ||
- copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int))
- ) {
- vu->vu_pending = 0;
- kprintf("bad upcall address\n");
- return;
- }
-
- /*
- * If the data structure is already marked pending or has a critical
- * section count, mark the data structure as pending and return
- * without doing an upcall. vu_pending is left set.
- */
- if (upcall.upc_pending || crit_count >= vu->vu_pending) {
- if (upcall.upc_pending < vu->vu_pending) {
- upcall.upc_pending = vu->vu_pending;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- }
- return;
- }
-
- /*
- * We can run this upcall now, clear vu_pending.
- *
- * Bump our critical section count and set or clear the
- * user pending flag depending on whether more upcalls are
- * pending. The user will be responsible for calling
- * upc_dispatch(-1) to process remaining upcalls.
- */
- vu->vu_pending = 0;
- upcall.upc_pending = morepending;
- ++crit_count;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff,
- sizeof(int));
-
- /*
- * Construct a stack frame and issue the upcall
- */
- regs = lp->lwp_md.md_regs;
- upc_frame.eax = regs->tf_eax;
- upc_frame.ecx = regs->tf_ecx;
- upc_frame.edx = regs->tf_edx;
- upc_frame.flags = regs->tf_eflags;
- upc_frame.oldip = regs->tf_eip;
- if (copyout(&upc_frame, (void *)(regs->tf_esp - sizeof(upc_frame)),
- sizeof(upc_frame)) != 0) {
- kprintf("bad stack on upcall\n");
- } else {
- regs->tf_eax = (register_t)vu->vu_func;
- regs->tf_ecx = (register_t)vu->vu_data;
- regs->tf_edx = (register_t)lp->lwp_upcall;
- regs->tf_eip = (register_t)vu->vu_ctx;
- regs->tf_esp -= sizeof(upc_frame);
- }
-}
-
-/*
- * fetchupcall occurs in the context of a system call, which means that
- * we have to return EJUSTRETURN in order to prevent eax and edx from
- * being overwritten by the syscall return value.
- *
- * if vu is not NULL we return the new context in %edx, the new data in %ecx,
- * and the function pointer in %eax.
- */
-int
-fetchupcall(struct vmupcall *vu, int morepending, void *rsp)
-{
- struct upc_frame upc_frame;
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- int error;
- struct upcall upcall;
- int crit_count;
-
- regs = lp->lwp_md.md_regs;
-
- error = copyout(&morepending, &lp->lwp_upcall->upc_pending, sizeof(int));
- if (error == 0) {
- if (vu) {
- /*
- * This jumps us to the next ready context.
- */
- vu->vu_pending = 0;
- error = copyin(lp->lwp_upcall, &upcall, sizeof(upcall));
- crit_count = 0;
- if (error == 0)
- error = copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int));
- ++crit_count;
- if (error == 0)
- error = copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff, sizeof(int));
- regs->tf_eax = (register_t)vu->vu_func;
- regs->tf_ecx = (register_t)vu->vu_data;
- regs->tf_edx = (register_t)lp->lwp_upcall;
- regs->tf_eip = (register_t)vu->vu_ctx;
- regs->tf_esp = (register_t)rsp;
- } else {
- /*
- * This returns us to the originally interrupted code.
- */
- error = copyin(rsp, &upc_frame, sizeof(upc_frame));
- regs->tf_eax = upc_frame.eax;
- regs->tf_ecx = upc_frame.ecx;
- regs->tf_edx = upc_frame.edx;
- regs->tf_eflags = (regs->tf_eflags & ~PSL_USERCHANGE) |
- (upc_frame.flags & PSL_USERCHANGE);
- regs->tf_eip = upc_frame.oldip;
- regs->tf_esp = (register_t)((char *)rsp + sizeof(upc_frame));
- }
- }
- if (error == 0)
- error = EJUSTRETURN;
- return(error);
-}
-
-/*
* Machine dependent boot() routine
*
* I haven't seen anything to put here yet
#include <sys/ktrace.h>
#endif
#include <sys/ktr.h>
-#include <sys/upcall.h>
#include <sys/vkernel.h>
#include <sys/sysproto.h>
#include <sys/sysunion.h>
}
/*
- * Handle signals, upcalls, profiling, and other AST's and/or tasks that
+ * Handle signals, profiling, and other AST's and/or tasks that
* must be completed before we can return to or try to return to userland.
*
* Note that td_sticks is a 64 bit quantity, but there's no point doing 64
* Post any pending upcalls. If running a virtual kernel be sure
* to restore the virtual kernel's vmspace before posting the upcall.
*/
- if (p->p_flags & (P_SIGVTALRM | P_SIGPROF | P_UPCALLPEND)) {
+ if (p->p_flags & (P_SIGVTALRM | P_SIGPROF)) {
lwkt_gettoken(&p->p_token);
if (p->p_flags & P_SIGVTALRM) {
p->p_flags &= ~P_SIGVTALRM;
p->p_flags &= ~P_SIGPROF;
ksignal(p, SIGPROF);
}
- if (p->p_flags & P_UPCALLPEND) {
- p->p_flags &= ~P_UPCALLPEND;
- postupcall(lp);
- }
lwkt_reltoken(&p->p_token);
goto recheck;
}
ASSYM(RQF_AST_SIGNAL, RQF_AST_SIGNAL);
ASSYM(RQF_AST_USER_RESCHED, RQF_AST_USER_RESCHED);
ASSYM(RQF_AST_LWKT_RESCHED, RQF_AST_LWKT_RESCHED);
-ASSYM(RQF_AST_UPCALL, RQF_AST_UPCALL);
ASSYM(RQF_TIMER, RQF_TIMER);
ASSYM(RQF_AST_MASK, RQF_AST_MASK);
ASSYM(RQF_QUICKRET, RQF_QUICKRET);
* to do is a reschedule.
*/
doreti_ast:
- andl $~(RQF_AST_SIGNAL|RQF_AST_UPCALL),PCPU(reqflags)
+ andl $~RQF_AST_SIGNAL,PCPU(reqflags)
sti
movl %eax,%r12d /* save cpl (can't use stack) */
movl $T_ASTFLT,TF_TRAPNO(%rsp)
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/bus.h>
-#include <sys/upcall.h>
#include <sys/usched.h>
#include <sys/reg.h>
}
/*
- * Stack frame on entry to function. %rax will contain the function vector,
- * %rcx will contain the function data. flags, rcx, and rax will have
- * already been pushed on the stack.
- */
-struct upc_frame {
- register_t rax;
- register_t rcx;
- register_t rdx;
- register_t flags;
- register_t oldip;
-};
-
-void
-sendupcall(struct vmupcall *vu, int morepending)
-{
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- struct upcall upcall;
- struct upc_frame upc_frame;
- int crit_count = 0;
-
- /*
- * If we are a virtual kernel running an emulated user process
- * context, switch back to the virtual kernel context before
- * trying to post the signal.
- */
- if (lp->lwp_vkernel && lp->lwp_vkernel->ve) {
- lp->lwp_md.md_regs->tf_trapno = 0;
- vkernel_trap(lp, lp->lwp_md.md_regs);
- }
-
- /*
- * Get the upcall data structure
- */
- if (copyin(lp->lwp_upcall, &upcall, sizeof(upcall)) ||
- copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int))
- ) {
- vu->vu_pending = 0;
- kprintf("bad upcall address\n");
- return;
- }
-
- /*
- * If the data structure is already marked pending or has a critical
- * section count, mark the data structure as pending and return
- * without doing an upcall. vu_pending is left set.
- */
- if (upcall.upc_pending || crit_count >= vu->vu_pending) {
- if (upcall.upc_pending < vu->vu_pending) {
- upcall.upc_pending = vu->vu_pending;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- }
- return;
- }
-
- /*
- * We can run this upcall now, clear vu_pending.
- *
- * Bump our critical section count and set or clear the
- * user pending flag depending on whether more upcalls are
- * pending. The user will be responsible for calling
- * upc_dispatch(-1) to process remaining upcalls.
- */
- vu->vu_pending = 0;
- upcall.upc_pending = morepending;
- ++crit_count;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff,
- sizeof(int));
-
- /*
- * Construct a stack frame and issue the upcall
- */
- regs = lp->lwp_md.md_regs;
- upc_frame.rax = regs->tf_rax;
- upc_frame.rcx = regs->tf_rcx;
- upc_frame.rdx = regs->tf_rdx;
- upc_frame.flags = regs->tf_rflags;
- upc_frame.oldip = regs->tf_rip;
- if (copyout(&upc_frame, (void *)(regs->tf_rsp - sizeof(upc_frame) - 128),
- sizeof(upc_frame)) != 0) {
- kprintf("bad stack on upcall\n");
- } else {
- regs->tf_rax = (register_t)vu->vu_func;
- regs->tf_rcx = (register_t)vu->vu_data;
- regs->tf_rdx = (register_t)lp->lwp_upcall;
- regs->tf_rip = (register_t)vu->vu_ctx;
- regs->tf_rsp -= sizeof(upc_frame) + 128;
- }
-}
-
-/*
- * fetchupcall occurs in the context of a system call, which means that
- * we have to return EJUSTRETURN in order to prevent eax and edx from
- * being overwritten by the syscall return value.
- *
- * if vu is not NULL we return the new context in %edx, the new data in %ecx,
- * and the function pointer in %eax.
- */
-int
-fetchupcall(struct vmupcall *vu, int morepending, void *rsp)
-{
- struct upc_frame upc_frame;
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- int error;
- struct upcall upcall;
- int crit_count;
-
- regs = lp->lwp_md.md_regs;
-
- error = copyout(&morepending, &lp->lwp_upcall->upc_pending, sizeof(int));
- if (error == 0) {
- if (vu) {
- /*
- * This jumps us to the next ready context.
- */
- vu->vu_pending = 0;
- error = copyin(lp->lwp_upcall, &upcall, sizeof(upcall));
- crit_count = 0;
- if (error == 0)
- error = copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int));
- ++crit_count;
- if (error == 0)
- error = copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff, sizeof(int));
- regs->tf_rax = (register_t)vu->vu_func;
- regs->tf_rcx = (register_t)vu->vu_data;
- regs->tf_rdx = (register_t)lp->lwp_upcall;
- regs->tf_rip = (register_t)vu->vu_ctx;
- regs->tf_rsp = (register_t)rsp;
- } else {
- /*
- * This returns us to the originally interrupted code.
- */
- error = copyin(rsp, &upc_frame, sizeof(upc_frame));
- regs->tf_rax = upc_frame.rax;
- regs->tf_rcx = upc_frame.rcx;
- regs->tf_rdx = upc_frame.rdx;
- regs->tf_rflags = (regs->tf_rflags & ~PSL_USERCHANGE) |
- (upc_frame.flags & PSL_USERCHANGE);
- regs->tf_rip = upc_frame.oldip;
- regs->tf_rsp = (register_t)((char *)rsp + sizeof(upc_frame));
- }
- }
- if (error == 0)
- error = EJUSTRETURN;
- return(error);
-}
-
-/*
* Machine dependent boot() routine
*
* I haven't seen anything to put here yet
* Post any pending upcalls. If running a virtual kernel be sure
* to restore the virtual kernel's vmspace before posting the upcall.
*/
- if (p->p_flags & (P_SIGVTALRM | P_SIGPROF | P_UPCALLPEND)) {
+ if (p->p_flags & (P_SIGVTALRM | P_SIGPROF)) {
lwkt_gettoken(&p->p_token);
if (p->p_flags & P_SIGVTALRM) {
p->p_flags &= ~P_SIGVTALRM;
p->p_flags &= ~P_SIGPROF;
ksignal(p, SIGPROF);
}
- if (p->p_flags & P_UPCALLPEND) {
- p->p_flags &= ~P_UPCALLPEND;
- postupcall(lp);
- }
lwkt_reltoken(&p->p_token);
goto recheck;
}
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/bus.h>
-#include <sys/upcall.h>
#include <sys/usched.h>
#include <sys/reg.h>
}
/*
- * Stack frame on entry to function. %eax will contain the function vector,
- * %ecx will contain the function data. flags, ecx, and eax will have
- * already been pushed on the stack.
- */
-struct upc_frame {
- register_t eax;
- register_t ecx;
- register_t edx;
- register_t flags;
- register_t oldip;
-};
-
-void
-sendupcall(struct vmupcall *vu, int morepending)
-{
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- struct upcall upcall;
- struct upc_frame upc_frame;
- int crit_count = 0;
-
- /*
- * If we are a virtual kernel running an emulated user process
- * context, switch back to the virtual kernel context before
- * trying to post the signal.
- */
- if (lp->lwp_vkernel && lp->lwp_vkernel->ve) {
- lp->lwp_md.md_regs->tf_trapno = 0;
- vkernel_trap(lp, lp->lwp_md.md_regs);
- }
-
- /*
- * Get the upcall data structure
- */
- if (copyin(lp->lwp_upcall, &upcall, sizeof(upcall)) ||
- copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int))
- ) {
- vu->vu_pending = 0;
- kprintf("bad upcall address\n");
- return;
- }
-
- /*
- * If the data structure is already marked pending or has a critical
- * section count, mark the data structure as pending and return
- * without doing an upcall. vu_pending is left set.
- */
- if (upcall.upc_pending || crit_count >= vu->vu_pending) {
- if (upcall.upc_pending < vu->vu_pending) {
- upcall.upc_pending = vu->vu_pending;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- }
- return;
- }
-
- /*
- * We can run this upcall now, clear vu_pending.
- *
- * Bump our critical section count and set or clear the
- * user pending flag depending on whether more upcalls are
- * pending. The user will be responsible for calling
- * upc_dispatch(-1) to process remaining upcalls.
- */
- vu->vu_pending = 0;
- upcall.upc_pending = morepending;
- ++crit_count;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff,
- sizeof(int));
-
- /*
- * Construct a stack frame and issue the upcall
- */
- regs = lp->lwp_md.md_regs;
- upc_frame.eax = regs->tf_eax;
- upc_frame.ecx = regs->tf_ecx;
- upc_frame.edx = regs->tf_edx;
- upc_frame.flags = regs->tf_eflags;
- upc_frame.oldip = regs->tf_eip;
- if (copyout(&upc_frame, (void *)(regs->tf_esp - sizeof(upc_frame)),
- sizeof(upc_frame)) != 0) {
- kprintf("bad stack on upcall\n");
- } else {
- regs->tf_eax = (register_t)vu->vu_func;
- regs->tf_ecx = (register_t)vu->vu_data;
- regs->tf_edx = (register_t)lp->lwp_upcall;
- regs->tf_eip = (register_t)vu->vu_ctx;
- regs->tf_esp -= sizeof(upc_frame);
- }
-}
-
-/*
- * fetchupcall occurs in the context of a system call, which means that
- * we have to return EJUSTRETURN in order to prevent eax and edx from
- * being overwritten by the syscall return value.
- *
- * if vu is not NULL we return the new context in %edx, the new data in %ecx,
- * and the function pointer in %eax.
- */
-int
-fetchupcall (struct vmupcall *vu, int morepending, void *rsp)
-{
- struct upc_frame upc_frame;
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- int error;
- struct upcall upcall;
- int crit_count;
-
- regs = lp->lwp_md.md_regs;
-
- error = copyout(&morepending, &lp->lwp_upcall->upc_pending, sizeof(int));
- if (error == 0) {
- if (vu) {
- /*
- * This jumps us to the next ready context.
- */
- vu->vu_pending = 0;
- error = copyin(lp->lwp_upcall, &upcall, sizeof(upcall));
- crit_count = 0;
- if (error == 0)
- error = copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int));
- ++crit_count;
- if (error == 0)
- error = copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff, sizeof(int));
- regs->tf_eax = (register_t)vu->vu_func;
- regs->tf_ecx = (register_t)vu->vu_data;
- regs->tf_edx = (register_t)lp->lwp_upcall;
- regs->tf_eip = (register_t)vu->vu_ctx;
- regs->tf_esp = (register_t)rsp;
- } else {
- /*
- * This returns us to the originally interrupted code.
- */
- error = copyin(rsp, &upc_frame, sizeof(upc_frame));
- regs->tf_eax = upc_frame.eax;
- regs->tf_ecx = upc_frame.ecx;
- regs->tf_edx = upc_frame.edx;
- regs->tf_eflags = (regs->tf_eflags & ~PSL_USERCHANGE) |
- (upc_frame.flags & PSL_USERCHANGE);
- regs->tf_eip = upc_frame.oldip;
- regs->tf_esp = (register_t)((char *)rsp + sizeof(upc_frame));
- }
- }
- if (error == 0)
- error = EJUSTRETURN;
- return(error);
-}
-
-/*
* cpu_idle() represents the idle LWKT. You cannot return from this function
* (unless you want to blow things up!). Instead we look for runnable threads
* and loop or halt as appropriate. Giant is not held on entry to the thread.
ASSYM(RQF_AST_SIGNAL, RQF_AST_SIGNAL);
ASSYM(RQF_AST_USER_RESCHED, RQF_AST_USER_RESCHED);
ASSYM(RQF_AST_LWKT_RESCHED, RQF_AST_LWKT_RESCHED);
-ASSYM(RQF_AST_UPCALL, RQF_AST_UPCALL);
ASSYM(RQF_AST_MASK, RQF_AST_MASK);
ASSYM(FIRST_SOFTINT, FIRST_SOFTINT);
#include <sys/ktrace.h>
#endif
#include <sys/ktr.h>
-#include <sys/upcall.h>
#include <sys/vkernel.h>
#include <sys/sysproto.h>
#include <sys/sysunion.h>
}
/*
- * Handle signals, upcalls, profiling, and other AST's and/or tasks that
+ * Handle signals, profiling, and other AST's and/or tasks that
* must be completed before we can return to or try to return to userland.
*
* Note that td_sticks is a 64 bit quantity, but there's no point doing 64
* Post any pending upcalls. If running a virtual kernel be sure
* to restore the virtual kernel's vmspace before posting the upcall.
*/
- if (p->p_flags & (P_SIGVTALRM | P_SIGPROF | P_UPCALLPEND)) {
+ if (p->p_flags & (P_SIGVTALRM | P_SIGPROF)) {
lwkt_gettoken(&p->p_token);
if (p->p_flags & P_SIGVTALRM) {
p->p_flags &= ~P_SIGVTALRM;
p->p_flags &= ~P_SIGPROF;
ksignal(p, SIGPROF);
}
- if (p->p_flags & P_UPCALLPEND) {
- p->p_flags &= ~P_UPCALLPEND;
- postupcall(lp);
- }
lwkt_reltoken(&p->p_token);
goto recheck;
}
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/bus.h>
-#include <sys/upcall.h>
#include <sys/usched.h>
#include <sys/reg.h>
}
/*
- * Stack frame on entry to function. %rax will contain the function vector,
- * %rcx will contain the function data. flags, rcx, and rax will have
- * already been pushed on the stack.
- */
-struct upc_frame {
- register_t rax;
- register_t rcx;
- register_t rdx;
- register_t flags;
- register_t oldip;
-};
-
-void
-sendupcall(struct vmupcall *vu, int morepending)
-{
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- struct upcall upcall;
- struct upc_frame upc_frame;
- int crit_count = 0;
-
- /*
- * If we are a virtual kernel running an emulated user process
- * context, switch back to the virtual kernel context before
- * trying to post the signal.
- */
- if (lp->lwp_vkernel && lp->lwp_vkernel->ve) {
- lp->lwp_md.md_regs->tf_trapno = 0;
- vkernel_trap(lp, lp->lwp_md.md_regs);
- }
-
- /*
- * Get the upcall data structure
- */
- if (copyin(lp->lwp_upcall, &upcall, sizeof(upcall)) ||
- copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int))
- ) {
- vu->vu_pending = 0;
- kprintf("bad upcall address\n");
- return;
- }
-
- /*
- * If the data structure is already marked pending or has a critical
- * section count, mark the data structure as pending and return
- * without doing an upcall. vu_pending is left set.
- */
- if (upcall.upc_pending || crit_count >= vu->vu_pending) {
- if (upcall.upc_pending < vu->vu_pending) {
- upcall.upc_pending = vu->vu_pending;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- }
- return;
- }
-
- /*
- * We can run this upcall now, clear vu_pending.
- *
- * Bump our critical section count and set or clear the
- * user pending flag depending on whether more upcalls are
- * pending. The user will be responsible for calling
- * upc_dispatch(-1) to process remaining upcalls.
- */
- vu->vu_pending = 0;
- upcall.upc_pending = morepending;
- ++crit_count;
- copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
- sizeof(upcall.upc_pending));
- copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff,
- sizeof(int));
-
- /*
- * Construct a stack frame and issue the upcall
- */
- regs = lp->lwp_md.md_regs;
- upc_frame.rax = regs->tf_rax;
- upc_frame.rcx = regs->tf_rcx;
- upc_frame.rdx = regs->tf_rdx;
- upc_frame.flags = regs->tf_rflags;
- upc_frame.oldip = regs->tf_rip;
- if (copyout(&upc_frame, (void *)(regs->tf_rsp - sizeof(upc_frame)),
- sizeof(upc_frame)) != 0) {
- kprintf("bad stack on upcall\n");
- } else {
- regs->tf_rax = (register_t)vu->vu_func;
- regs->tf_rcx = (register_t)vu->vu_data;
- regs->tf_rdx = (register_t)lp->lwp_upcall;
- regs->tf_rip = (register_t)vu->vu_ctx;
- regs->tf_rsp -= sizeof(upc_frame);
- }
-}
-
-/*
- * fetchupcall occurs in the context of a system call, which means that
- * we have to return EJUSTRETURN in order to prevent eax and edx from
- * being overwritten by the syscall return value.
- *
- * if vu is not NULL we return the new context in %edx, the new data in %ecx,
- * and the function pointer in %eax.
- */
-int
-fetchupcall(struct vmupcall *vu, int morepending, void *rsp)
-{
- struct upc_frame upc_frame;
- struct lwp *lp = curthread->td_lwp;
- struct trapframe *regs;
- int error;
- struct upcall upcall;
- int crit_count;
-
- regs = lp->lwp_md.md_regs;
-
- error = copyout(&morepending, &lp->lwp_upcall->upc_pending, sizeof(int));
- if (error == 0) {
- if (vu) {
- /*
- * This jumps us to the next ready context.
- */
- vu->vu_pending = 0;
- error = copyin(lp->lwp_upcall, &upcall, sizeof(upcall));
- crit_count = 0;
- if (error == 0)
- error = copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int));
- ++crit_count;
- if (error == 0)
- error = copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff, sizeof(int));
- regs->tf_rax = (register_t)vu->vu_func;
- regs->tf_rcx = (register_t)vu->vu_data;
- regs->tf_rdx = (register_t)lp->lwp_upcall;
- regs->tf_rip = (register_t)vu->vu_ctx;
- regs->tf_rsp = (register_t)rsp;
- } else {
- /*
- * This returns us to the originally interrupted code.
- */
- error = copyin(rsp, &upc_frame, sizeof(upc_frame));
- regs->tf_rax = upc_frame.rax;
- regs->tf_rcx = upc_frame.rcx;
- regs->tf_rdx = upc_frame.rdx;
- regs->tf_rflags = (regs->tf_rflags & ~PSL_USERCHANGE) |
- (upc_frame.flags & PSL_USERCHANGE);
- regs->tf_rip = upc_frame.oldip;
- regs->tf_rsp = (register_t)((char *)rsp + sizeof(upc_frame));
- }
- }
- if (error == 0)
- error = EJUSTRETURN;
- return(error);
-}
-
-/*
* cpu_idle() represents the idle LWKT. You cannot return from this function
* (unless you want to blow things up!). Instead we look for runnable threads
* and loop or halt as appropriate. Giant is not held on entry to the thread.
#include <sys/ktrace.h>
#endif
#include <sys/ktr.h>
-#include <sys/upcall.h>
#include <sys/vkernel.h>
#include <sys/sysproto.h>
#include <sys/sysunion.h>
}
/*
- * Handle signals, upcalls, profiling, and other AST's and/or tasks that
+ * Handle signals, profiling, and other AST's and/or tasks that
* must be completed before we can return to or try to return to userland.
*
* Note that td_sticks is a 64 bit quantity, but there's no point doing 64
* Post any pending upcalls. If running a virtual kernel be sure
* to restore the virtual kernel's vmspace before posting the upcall.
*/
- if (p->p_flags & (P_SIGVTALRM | P_SIGPROF | P_UPCALLPEND)) {
+ if (p->p_flags & (P_SIGVTALRM | P_SIGPROF)) {
lwkt_gettoken(&p->p_token);
if (p->p_flags & P_SIGVTALRM) {
p->p_flags &= ~P_SIGVTALRM;
p->p_flags &= ~P_SIGPROF;
ksignal(p, SIGPROF);
}
- if (p->p_flags & P_UPCALLPEND) {
- p->p_flags &= ~P_UPCALLPEND;
- postupcall(lp);
- }
lwkt_reltoken(&p->p_token);
goto recheck;
}
#define RQB_AST_SIGNAL 3 /* 0008 */
#define RQB_AST_USER_RESCHED 4 /* 0010 */
#define RQB_AST_LWKT_RESCHED 5 /* 0020 */
-#define RQB_AST_UPCALL 6 /* 0040 */
+#define RQB_UNUSED6 6 /* 0040 */
#define RQB_TIMER 7 /* 0080 */
#define RQB_RUNNING 8 /* 0100 */
#define RQB_SPINNING 9 /* 0200 */
#define RQF_AST_SIGNAL (1 << RQB_AST_SIGNAL)
#define RQF_AST_USER_RESCHED (1 << RQB_AST_USER_RESCHED)
#define RQF_AST_LWKT_RESCHED (1 << RQB_AST_LWKT_RESCHED)
-#define RQF_AST_UPCALL (1 << RQB_AST_UPCALL)
#define RQF_RUNNING (1 << RQB_RUNNING)
#define RQF_SPINNING (1 << RQB_SPINNING)
#define RQF_QUICKRET (1 << RQB_QUICKRET)
#define RQF_AST_MASK (RQF_AST_OWEUPC|RQF_AST_SIGNAL|\
- RQF_AST_USER_RESCHED|RQF_AST_LWKT_RESCHED|\
- RQF_AST_UPCALL)
+ RQF_AST_USER_RESCHED|RQF_AST_LWKT_RESCHED)
#define RQF_IDLECHECK_MASK (RQF_IPIQ|RQF_INTPEND|RQF_TIMER)
#define RQF_IDLECHECK_WK_MASK (RQF_IDLECHECK_MASK|RQF_AST_LWKT_RESCHED)
#include <sys/sysent.h> /* For struct sysentvec */
#include <sys/thread.h>
#include <sys/varsym.h>
-#include <sys/upcall.h>
#include <sys/resourcevar.h>
#ifdef _KERNEL
#include <sys/globaldata.h>
struct mdproc lwp_md; /* Any machine-dependent fields. */
struct thread *lwp_thread; /* backpointer to proc's thread */
- struct upcall *lwp_upcall; /* REGISTERED USERLAND POINTER! */
+ void *lwp_unused01; /* for future fields */
struct kqueue lwp_kqueue; /* for select/poll */
u_int lwp_kqueue_serial;
struct lwkt_token lwp_token; /* per-lwp token for signal/state */
#define P_CONTINUED 0x08000 /* Proc has continued from a stopped state */
#define P_UNUSED16 0x00010000
-#define P_UPCALLPEND 0x00020000 /* an upcall is pending */
+#define P_UNUSED17 0x00020000
#define P_SWAPWAIT 0x00040000 /* Waiting for a swapin */
#define P_UNUSED19 0x00080000 /* was: Now in a zombied state */
#define P_SIGPROF 0x04000000 /* signal SIGPROF pending due to itimer */
#define P_INEXEC 0x08000000 /* Process is in execve(). */
#define P_UNUSED28 0x10000000
-#define P_UPCALLWAIT 0x20000000 /* Wait for upcall or signal */
+#define P_UNUSED29 0x20000000
#define P_XCPU 0x40000000 /* SIGXCPU */
#define LWP_ALTSTACK 0x0000001 /* have alternate signal stack */
*
* @(#)signalvar.h 8.6 (Berkeley) 2/19/95
* $FreeBSD: src/sys/sys/signalvar.h,v 1.34.2.1 2000/05/16 06:58:05 dillon Exp $
- * $DragonFly: src/sys/sys/signalvar.h,v 1.23 2008/04/21 15:47:58 dillon Exp $
*/
#ifndef _SYS_SIGNALVAR_H_ /* tmp for user.h */
struct pgrp;
struct proc;
struct sigio;
-struct vmupcall;
extern int sugid_coredump; /* Sysctl variable kern.sugid_coredump */
* Machine-dependent functions:
*/
void sendsig (sig_t action, int sig, sigset_t *retmask, u_long code);
-void sendupcall (struct vmupcall *vu, int morepending);
-int fetchupcall (struct vmupcall *vu, int morepending, void *rsp);
void sigexit (struct lwp *lp, int sig);
int checkpoint_signal_handler(struct lwp *p);
#define SYS_varsym_set 450
#define SYS_varsym_get 451
#define SYS_varsym_list 452
-#define SYS_upc_register 453
-#define SYS_upc_control 454
+ /* 453 is obsolete upc_register */
+ /* 454 is obsolete upc_control */
/* 455 is obsolete caps_sys_service */
/* 456 is obsolete caps_sys_client */
/* 457 is obsolete caps_sys_close */
varsym_set.o \
varsym_get.o \
varsym_list.o \
- upc_register.o \
- upc_control.o \
exec_sys_register.o \
exec_sys_unregister.o \
sys_checkpoint.o \
int maxsize; char maxsize_[PAD_(int)];
int * marker; char marker_[PAD_(int *)];
};
-struct upc_register_args {
-#ifdef _KERNEL
- struct sysmsg sysmsg;
-#endif
- struct upcall * upc; char upc_[PAD_(struct upcall *)];
- void * ctxfunc; char ctxfunc_[PAD_(void *)];
- void * func; char func_[PAD_(void *)];
- void * data; char data_[PAD_(void *)];
-};
-struct upc_control_args {
-#ifdef _KERNEL
- struct sysmsg sysmsg;
-#endif
- int cmd; char cmd_[PAD_(int)];
- int upcid; char upcid_[PAD_(int)];
- void * data; char data_[PAD_(void *)];
-};
struct exec_sys_register_args {
#ifdef _KERNEL
struct sysmsg sysmsg;
int sys_varsym_set (struct varsym_set_args *);
int sys_varsym_get (struct varsym_get_args *);
int sys_varsym_list (struct varsym_list_args *);
-int sys_upc_register (struct upc_register_args *);
-int sys_upc_control (struct upc_control_args *);
int sys_exec_sys_register (struct exec_sys_register_args *);
int sys_exec_sys_unregister (struct exec_sys_unregister_args *);
int sys_sys_checkpoint (struct sys_checkpoint_args *);
struct varsym_set_args varsym_set;
struct varsym_get_args varsym_get;
struct varsym_list_args varsym_list;
- struct upc_register_args upc_register;
- struct upc_control_args upc_control;
struct exec_sys_register_args exec_sys_register;
struct exec_sys_unregister_args exec_sys_unregister;
struct sys_checkpoint_args sys_checkpoint;
+++ /dev/null
-/*
- * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
- *
- * This code is derived from software contributed to The DragonFly Project
- * by Matthew Dillon <dillon@backplane.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name of The DragonFly Project nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific, prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $DragonFly: src/sys/sys/upcall.h,v 1.11 2006/09/10 21:35:11 dillon Exp $
- */
-
-#ifndef _SYS_UPCALL_H_
-#define _SYS_UPCALL_H_
-
-struct thread;
-struct lwp;
-
-typedef void (*upcall_func_t)(void *);
-
-struct upcall {
- int upc_magic;
- int upc_critoff; /* offset of crit_count in uthread */
- int upc_pending; /* must follow crit_count */
- struct thread *upc_uthread; /* pointer to user thread (opaque) */
-};
-
-#define UPCALL_MAGIC 0x55504331
-#define UPCALL_MAXCOUNT 32
-
-#define UPC_CONTROL_DISPATCH 1
-#define UPC_CONTROL_NEXT 2
-#define UPC_CONTROL_DELETE 3
-#define UPC_CONTROL_POLL 4
-#define UPC_CONTROL_POLLANDCLEAR 5
-#define UPC_CONTROL_WAIT 6
-
-#define UPC_RESERVED 32 /* # of reserved id's */
-
-#if defined(_KERNEL)
-/*
- * Kernel protoypes
- */
-
-struct vmspace;
-
-void upc_release(struct vmspace *vm, struct lwp *lp);
-void postupcall(struct lwp *lp);
-
-#else
-/*
- * Userland prototypes
- */
-int upc_register(struct upcall *, upcall_func_t, upcall_func_t, void *);
-int upc_control(int, int, void *);
-void upc_callused_wrapper(void *);
-
-#endif
-
-#endif
-
vm->vm_flags |= VMSPACE_EXIT2;
cpu_vmspace_free(vm);
shmexit(vm);
- KKASSERT(vm->vm_upcalls == NULL);
/*
* Lock the map, to wait out all other references to it.
lwkt_gettoken(&vm1->vm_map.token);
vm_map_lock(old_map);
- /*
- * XXX Note: upcalls are not copied.
- */
vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset);
lwkt_gettoken(&vm2->vm_map.token);
bcopy(&vm1->vm_startcopy, &vm2->vm_startcopy,
/*
* If we are execing a resident vmspace we fork it, otherwise
- * we create a new vmspace. Note that exitingcnt and upcalls
- * are not copied to the new vmspace.
+ * we create a new vmspace. Note that exitingcnt is not
+ * copied to the new vmspace.
*/
lwkt_gettoken(&oldvmspace->vm_map.token);
if (vmcopy) {
* rights to redistribute these changes.
*
* $FreeBSD: src/sys/vm/vm_map.h,v 1.54.2.5 2003/01/13 22:51:17 dillon Exp $
- * $DragonFly: src/sys/vm/vm_map.h,v 1.30 2007/04/29 18:25:41 dillon Exp $
*/
/*
*/
#define MAP_WIREFUTURE 0x0001 /* wire all future pages */
-/*
- * Registered upcall
- */
-struct upcall;
-
-struct vmupcall {
- struct vmupcall *vu_next;
- void *vu_func; /* user upcall function */
- void *vu_data; /* user data */
- void *vu_ctx; /* user context function */
- struct lwp *vu_lwp; /* process that registered upcall */
- int vu_id; /* upcall identifier */
- int vu_pending; /* upcall request pending */
-};
-
/*
* Shareable process virtual address space.
*
caddr_t vm_minsaddr; /* user VA at max stack growth */
#define vm_endcopy vm_exitingcnt
int vm_exitingcnt; /* exit/wait context reaping */
- int vm_upccount; /* number of registered upcalls */
+ int vm_unused01; /* for future fields */
int vm_pagesupply;
u_int vm_holdcount;
- struct vmupcall *vm_upcalls; /* registered upcalls */
+ void *vm_unused02; /* for future fields */
struct sysref vm_sysref; /* sysref, refcnt, etc */
};
-#
-# $DragonFly: src/test/sysperf/Makefile,v 1.17 2008/05/09 15:49:42 dillon Exp $
-#
-
TARGETS=/tmp/sc1 /tmp/sc2 /tmp/sc3 /tmp/sc4 /tmp/sc5 /tmp/sc6 /tmp/sc7 \
/tmp/loop1 /tmp/loop2 /tmp/loop3 /tmp/loop4 \
/tmp/call1 /tmp/call2 /tmp/call3 /tmp/cmp \
/tmp/sp1 \
/tmp/sw1 /tmp/sw2 /tmp/sw3 \
/tmp/mbw1 \
- /tmp/upc1 \
/tmp/exec1 /tmp/exec2 \
/tmp/mem1 /tmp/mem2 \
/tmp/cld1 \
/tmp/sw3: quicksw1.c blib.c sw.S
$(CC) $(CFLAGS) -DUSE_CALLU2 quicksw1.c blib.c sw.S -o /tmp/sw3
-/tmp/upc1: upcall.S upcall1.c blib.c
- $(CC) $(CFLAGS) -DUSE_CALLU2 upcall.S upcall1.c blib.c -o /tmp/upc1
-
/tmp/exec1: exec1.c blib.c
$(CC) $(CFLAGS) -static -DISSTATIC exec1.c blib.c -o /tmp/exec1
+++ /dev/null
- /*
- * $DragonFly: src/test/sysperf/upcall.S,v 1.2 2003/11/21 08:32:45 dillon Exp $
- */
- .text
- .globl callused_wrapper
-
-#define CRIT_COUNT 4 /* not a good idea to hardwire this XXX */
-#define PENDING 8 /* not a good idea to hardwire this XXX */
-
- /*
- * On entry: %eax contains function
- * %ecx contains data
- * Stack: [eax,ecx,eflags,oldip]
- */
-callused_wrapper:
- pushl %edx /* save %edx (upcall pointer) */
- pushl %ecx /* func(data) */
- call *%eax
- addl $4,%esp
- popl %edx /* upcall pointer */
- incl PENDING(%edx) /* set pending bit (prevents upcalls) */
- subl $32,CRIT_COUNT(%edx) /* cleanup critical section count */
- pushl %esp /* sp pointing to os supplied frame */
- pushl $-1 /* upcid */
- pushl $2 /* FETCH next */
- call upc_control
- popl %eax
- popl %ecx
- popl %edx
- popfl
- ret
-
+++ /dev/null
-/*
- * UPCALL1.C
- *
- * Test upcall performance. WARNING! This test does not reflect
- * reality... the test is effectively making two system calls for
- * each upcall when under normal conditions no system calls should be
- * necessary when handling an upcall.
- *
- * $DragonFly: src/test/sysperf/upcall1.c,v 1.3 2004/01/12 16:48:37 drhodus Exp $
- */
-
-#include <sys/types.h>
-#include <sys/upcall.h>
-#include <sys/time.h>
-#include <stdio.h>
-#include "blib.h"
-
-#define MAXCOUNT 10000000
-
-struct upcall upc; /* simple single-cpu upcall test */
-
-extern void callused_wrapper(void *); /* assembly */
-static void myfunc(void *data);
-
-int count = MAXCOUNT;
-int id;
-
-int
-main(int ac, char **av)
-{
- id = upc_register(&upc, callused_wrapper, myfunc, "blah");
- printf("Warning: extra system calls in test means performance\n");
- printf("does not reflect reality. Divide times by 3 for raw\n");
- printf("per-upcall overhead (approximately)\n");
- printf("register upcall %d\n", id);
- printf("try to dispatch the upcall\n");
- upc_control(UPC_CONTROL_DISPATCH, id, NULL);
- stop_timing(MAXCOUNT, "Full-up upcall test");
- printf("final: %d %d (should be 0 0)\n", upc.upc_critoff, upc.upc_pending);
- return 0;
-}
-
-static void
-myfunc(void *data)
-{
- /*
- * Dispatch a reentrant UPC. It should not stack because we are in a
- * critical section, but the context code will catch it when it calls
- * UPC_CONTROL_NEXT.
- */
- if (--count > 0) {
- upc_control(UPC_CONTROL_DISPATCH, id, NULL);
- }
- if (count > MAXCOUNT - 3) {
- printf("UPCALL! (%s) upc: %d crit=%d pend=%d (should be 32 1) @sp %p\n",
- data, upc.upc_magic, upc.upc_critoff, upc.upc_pending, &data);
- if (count == MAXCOUNT - 2) {
- printf("(sp should be same as before)\n");
- printf("doing a total of %d upcalls\n", MAXCOUNT);
- usleep(20000);
- start_timing();
- }
- }
-}
-