diff options
author | peter <peter@FreeBSD.org> | 1996-02-23 18:49:25 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-02-23 18:49:25 +0000 |
commit | 5239b23b5dd3a758a93e0c2186e188e829e7ba19 (patch) | |
tree | 8062bc6b4973f0a1762ce55c879b8c3019d7662e /sys/kern | |
parent | 834adf89dc86160b3de01b8991acc8ec96028a47 (diff) | |
download | FreeBSD-src-5239b23b5dd3a758a93e0c2186e188e829e7ba19.zip FreeBSD-src-5239b23b5dd3a758a93e0c2186e188e829e7ba19.tar.gz |
kern_descrip.c: add fdshare()/fdcopy()
kern_fork.c: add the tiny bit of code for rfork operation.
kern/sysv_*: shmfork() takes one less arg, it was never used.
sys/shm.h: drop "isvfork" arg from shmfork() prototype
sys/param.h: declare rfork args.. (this is where OpenBSD put it..)
sys/filedesc.h: protos for fdshare/fdcopy.
vm/vm_mmap.c: add minherit code, add rounding to mmap() type args where
it makes sense.
vm/*: drop unused isvfork arg.
Note: this rfork() implementation copies the address space mappings,
it does not connect the mappings together. ie: once the two processes
have split, the pages may be shared, but the address space is not. If one
does a mmap() etc, it does not appear in the other. This makes it not
useful for pthreads, but it is useful in it's own right for having
light-weight threads in a static shared address space.
Obtained from: Original by Ron Minnich, extended by OpenBSD
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_descrip.c | 46 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 73 | ||||
-rw-r--r-- | sys/kern/sysv_ipc.c | 5 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 5 |
4 files changed, 110 insertions, 19 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index d214f0d..8dc24d7 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 - * $Id: kern_descrip.c,v 1.24 1996/01/28 23:41:39 dyson Exp $ + * $Id: kern_descrip.c,v 1.25 1996/02/04 19:56:34 dyson Exp $ */ #include <sys/param.h> @@ -82,6 +82,7 @@ static int finishdup(struct filedesc *fdp, int old, int new, int *retval); */ struct file *filehead; /* head of list of open files */ int nfiles; /* actual number of open files */ +extern int cmask; /* * System calls on descriptors. @@ -701,6 +702,49 @@ ffree(fp) } /* + * Build a new filedesc structure. + */ +struct filedesc * +fdinit(p) + struct proc *p; +{ + register struct filedesc0 *newfdp; + register struct filedesc *fdp = p->p_fd; + + MALLOC(newfdp, struct filedesc0 *, sizeof(struct filedesc0), + M_FILEDESC, M_WAITOK); + bzero(newfdp, sizeof(struct filedesc0)); + newfdp->fd_fd.fd_cdir = fdp->fd_cdir; + VREF(newfdp->fd_fd.fd_cdir); + newfdp->fd_fd.fd_rdir = fdp->fd_rdir; + if (newfdp->fd_fd.fd_rdir) + VREF(newfdp->fd_fd.fd_rdir); + + /* Create the file descriptor table. */ + newfdp->fd_fd.fd_refcnt = 1; + newfdp->fd_fd.fd_cmask = cmask; + newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles; + newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags; + newfdp->fd_fd.fd_nfiles = NDFILE; + + newfdp->fd_fd.fd_freefile = 0; + newfdp->fd_fd.fd_lastfile = 0; + + return (&newfdp->fd_fd); +} + +/* + * Share a filedesc structure. + */ +struct filedesc * +fdshare(p) + struct proc *p; +{ + p->p_fd->fd_refcnt++; + return (p->p_fd); +} + +/* * Copy a filedesc structure. */ struct filedesc * diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index d73ff1a..dbb56c4 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_fork.c 8.6 (Berkeley) 4/8/94 - * $Id: kern_fork.c,v 1.15 1995/12/07 12:46:42 davidg Exp $ + * $Id: kern_fork.c,v 1.16 1996/01/03 21:42:02 wollman Exp $ */ #include "opt_ktrace.h" @@ -56,9 +56,17 @@ #include <vm/vm.h> #include <vm/vm_param.h> +#include <vm/lock.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> #include <vm/vm_extern.h> +#include <vm/vm_inherit.h> -static int fork1(struct proc *, int, int *); +static int fork1(struct proc *p, int forktype, int rforkflags, int *retval); + +#define ISFORK 0 +#define ISVFORK 1 +#define ISRFORK 2 #ifndef _SYS_SYSPROTO_H_ struct fork_args { @@ -73,27 +81,38 @@ fork(p, uap, retval) struct fork_args *uap; int retval[]; { - - return (fork1(p, 0, retval)); + return (fork1(p, ISFORK, 0, retval)); } /* ARGSUSED */ int vfork(p, uap, retval) struct proc *p; - struct fork_args *uap; + struct vfork_args *uap; int retval[]; { + return (fork1(p, ISVFORK, 0, retval)); +} - return (fork1(p, 1, retval)); +/* ARGSUSED */ +int +rfork(p, uap, retval) + struct proc *p; + struct rfork_args *uap; + int retval[]; +{ + return (fork1(p, ISRFORK, uap->flags, retval)); } + int nprocs = 1; /* process 0 */ static int -fork1(p1, isvfork, retval) +fork1(p1, forktype, rforkflags, retval) register struct proc *p1; - int isvfork, retval[]; + int forktype; + int rforkflags; + int retval[]; { register struct proc *p2; register uid_t uid; @@ -101,6 +120,21 @@ fork1(p1, isvfork, retval) struct proc **hash; int count; static int nextpid, pidchecked = 0; + int dupfd = 1, cleanfd = 0; + + if (forktype == ISRFORK) { + dupfd = 0; + if ((rforkflags & RFPROC) == 0) + return (EINVAL); + if ((rforkflags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) + return (EINVAL); + if (rforkflags & RFFDG) + dupfd = 1; + if (rforkflags & RFNOWAIT) + return (EINVAL); /* XXX unimplimented */ + if (rforkflags & RFCFDG) + cleanfd = 1; + } /* * Although process entries are dynamically created, we still keep @@ -235,7 +269,13 @@ again: if (p2->p_textvp) VREF(p2->p_textvp); - p2->p_fd = fdcopy(p1); + if (cleanfd) + p2->p_fd = fdinit(p1); + else if (dupfd) + p2->p_fd = fdcopy(p1); + else + p2->p_fd = fdshare(p1); + /* * If p_limit is still copy-on-write, bump refcnt, * otherwise get a copy that won't be modified. @@ -251,7 +291,7 @@ again: if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; - if (isvfork) + if (forktype == ISVFORK) p2->p_flag |= P_PPWAIT; p2->p_pgrpnxt = p1->p_pgrpnxt; p1->p_pgrpnxt = p2; @@ -284,6 +324,15 @@ again: p1->p_flag |= P_NOSWAP; /* + * share as much address space as possible + */ + if (forktype == ISRFORK && (rforkflags & RFMEM)) { + (void) vm_map_inherit(&p1->p_vmspace->vm_map, + VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS - MAXSSIZ, + VM_INHERIT_SHARE); + } + + /* * Set return values for child before vm_fork, * so they can be copied to child stack. * We return parent pid, and mark as child in retval[1]. @@ -293,7 +342,7 @@ again: */ retval[0] = p1->p_pid; retval[1] = 1; - if (vm_fork(p1, p2, isvfork)) { + if (vm_fork(p1, p2)) { /* * Child process. Set start time and get to work. */ @@ -321,7 +370,7 @@ again: * child to exec or exit, set P_PPWAIT on child, and sleep on our * proc (in case of exit). */ - if (isvfork) + if (forktype == ISVFORK) while (p2->p_flag & P_PPWAIT) tsleep(p1, PWAIT, "ppwait", 0); diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c index bd7c0c8..e62068e 100644 --- a/sys/kern/sysv_ipc.c +++ b/sys/kern/sysv_ipc.c @@ -1,4 +1,4 @@ -/* $Id: sysv_ipc.c,v 1.2 1996/01/05 16:37:52 wollman Exp $ */ +/* $Id: sysv_ipc.c,v 1.3 1996/01/08 04:30:48 peter Exp $ */ /* $NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $ */ /* @@ -278,9 +278,8 @@ shmsys(p, uap, retval) /* called from kern_fork.c */ void -shmfork(p1, p2, isvfork) +shmfork(p1, p2) struct proc *p1, *p2; - int isvfork; { return; } diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 72c8a22..a68f8a6 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -1,4 +1,4 @@ -/* $Id: sysv_shm.c,v 1.16 1995/12/26 16:03:32 joerg Exp $ */ +/* $Id: sysv_shm.c,v 1.17 1996/01/05 16:38:03 wollman Exp $ */ /* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */ /* @@ -565,9 +565,8 @@ shmsys(p, uap, retval) } void -shmfork(p1, p2, isvfork) +shmfork(p1, p2) struct proc *p1, *p2; - int isvfork; { struct shmmap_state *shmmap_s; size_t size; |