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 | |
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
-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 | ||||
-rw-r--r-- | sys/sys/filedesc.h | 4 | ||||
-rw-r--r-- | sys/sys/param.h | 18 | ||||
-rw-r--r-- | sys/sys/shm.h | 4 | ||||
-rw-r--r-- | sys/vm/vm_extern.h | 4 | ||||
-rw-r--r-- | sys/vm/vm_glue.c | 10 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 127 |
10 files changed, 247 insertions, 49 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; diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index 7f71cd8..7bd4578 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 - * $Id: filedesc.h,v 1.6 1995/05/30 08:14:20 rgrimes Exp $ + * $Id: filedesc.h,v 1.7 1995/11/04 10:35:17 bde Exp $ */ #ifndef _SYS_FILEDESC_H_ @@ -100,6 +100,8 @@ int fdalloc __P((struct proc *p, int want, int *result)); int fdavail __P((struct proc *p, int n)); int falloc __P((struct proc *p, struct file **resultfp, int *resultfd)); void ffree __P((struct file *)); +struct filedesc *fdinit __P((struct proc *p)); +struct filedesc *fdshare __P((struct proc *p)); struct filedesc *fdcopy __P((struct proc *p)); void fdfree __P((struct proc *p)); int closef __P((struct file *fp,struct proc *p)); diff --git a/sys/sys/param.h b/sys/sys/param.h index 88e0e16..6766c2f 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)param.h 8.2 (Berkeley) 1/21/94 - * $Id: param.h,v 1.10 1995/12/05 21:03:13 bde Exp $ + * $Id: param.h,v 1.11 1996/01/30 23:01:04 mpp Exp $ */ #ifndef _SYS_PARAM_H_ @@ -226,4 +226,20 @@ #define FSHIFT 11 /* bits to right of fixed binary point */ #define FSCALE (1<<FSHIFT) +/* + * rfork() options. + * + * XXX currently, operations without RFPROC set are not supported. + */ +#define RFNAMEG (1<<0) /* UNIMPL new plan9 `name space' */ +#define RFENVG (1<<1) /* UNIMPL copy plan9 `env space' */ +#define RFFDG (1<<2) /* copy fd table */ +#define RFNOTEG (1<<3) /* UNIMPL create new plan9 `note group' */ +#define RFPROC (1<<4) /* change child (else changes curproc) */ +#define RFMEM (1<<5) /* share `address space' */ +#define RFNOWAIT (1<<6) /* UNIMPL parent need not wait() on child */ +#define RFCNAMEG (1<<10) /* UNIMPL zero plan9 `name space' */ +#define RFCENVG (1<<11) /* UNIMPL zero plan9 `env space' */ +#define RFCFDG (1<<12) /* zero fd table */ + #endif diff --git a/sys/sys/shm.h b/sys/sys/shm.h index 7cc6e5a..8dcf9de 100644 --- a/sys/sys/shm.h +++ b/sys/sys/shm.h @@ -1,4 +1,4 @@ -/* $Id: shm.h,v 1.6 1995/08/30 00:33:35 bde Exp $ */ +/* $Id: shm.h,v 1.7 1996/01/30 23:01:19 mpp Exp $ */ /* $NetBSD: shm.h,v 1.15 1994/06/29 06:45:17 cgd Exp $ */ /* @@ -80,7 +80,7 @@ extern struct shminfo shminfo; extern struct shmid_ds *shmsegs; void shmexit __P((struct proc *)); -void shmfork __P((struct proc *, struct proc *, int)); +void shmfork __P((struct proc *, struct proc *)); #else /* !KERNEL */ #include <sys/cdefs.h> diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index c6b3067..b0d7480 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94 - * $Id: vm_extern.h,v 1.22 1995/12/14 09:54:55 phk Exp $ + * $Id: vm_extern.h,v 1.23 1996/02/04 22:08:57 dyson Exp $ */ #ifndef _VM_EXTERN_H_ @@ -88,7 +88,7 @@ int vm_fault __P((vm_map_t, vm_offset_t, vm_prot_t, boolean_t)); void vm_fault_copy_entry __P((vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t)); void vm_fault_unwire __P((vm_map_t, vm_offset_t, vm_offset_t)); int vm_fault_wire __P((vm_map_t, vm_offset_t, vm_offset_t)); -int vm_fork __P((struct proc *, struct proc *, int)); +int vm_fork __P((struct proc *, struct proc *)); void vm_map_print __P((/* db_expr_t */ int, boolean_t, /* db_expr_t */ int, char *)); int vm_mmap __P((vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, caddr_t, vm_ooffset_t)); vm_offset_t vm_page_alloc_contig __P((vm_offset_t, vm_offset_t, vm_offset_t, vm_offset_t)); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 1d45e37..3dfa281 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -59,10 +59,9 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_glue.c,v 1.38 1996/01/29 12:10:30 davidg Exp $ + * $Id: vm_glue.c,v 1.39 1996/02/22 10:57:36 davidg Exp $ */ -#include "opt_sysvipc.h" #include "opt_ddb.h" #include <sys/param.h> @@ -210,9 +209,8 @@ vsunlock(addr, len, dirtied) * after cpu_fork returns. */ int -vm_fork(p1, p2, isvfork) +vm_fork(p1, p2) register struct proc *p1, *p2; - int isvfork; { register struct user *up; vm_offset_t addr, ptaddr, ptpa; @@ -234,10 +232,8 @@ vm_fork(p1, p2, isvfork) UPT_MIN_ADDRESS - UPAGES * PAGE_SIZE, VM_MAX_ADDRESS, VM_INHERIT_NONE); p2->p_vmspace = vmspace_fork(p1->p_vmspace); -#ifdef SYSVSHM if (p1->p_vmspace->vm_shm) - shmfork(p1, p2, isvfork); -#endif + shmfork(p1, p2); /* * Allocate a wired-down (for now) pcb and kernel stack for the diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index c68f5f4..d7d597d 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -38,7 +38,7 @@ * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ * * @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94 - * $Id: vm_mmap.c,v 1.34 1995/12/17 07:19:57 bde Exp $ + * $Id: vm_mmap.c,v 1.35 1996/01/19 03:59:59 dyson Exp $ */ /* @@ -319,7 +319,7 @@ msync(p, uap, retval) int *retval; { vm_offset_t addr; - vm_size_t size; + vm_size_t size, pageoff; int flags; vm_map_t map; int rv; @@ -329,8 +329,18 @@ msync(p, uap, retval) size = round_page((vm_size_t) uap->len); flags = uap->flags; - if (((int) addr & PAGE_MASK) || addr + size < addr || - (flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE)) + /* + * Align the address to a page boundary, + * and adjust the size accordingly. + */ + pageoff = (addr & PAGE_MASK); + addr -= pageoff; + size += pageoff; + size = (vm_size_t) round_page(size); + if ((int)size < 0) + return(EINVAL); + + if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE)) return (EINVAL); /* @@ -385,15 +395,25 @@ munmap(p, uap, retval) int *retval; { vm_offset_t addr; - vm_size_t size; + vm_size_t size, pageoff; vm_map_t map; addr = (vm_offset_t) uap->addr; - if ((addr & PAGE_MASK) || uap->len < 0) - return (EINVAL); - size = (vm_size_t) round_page(uap->len); + size = (vm_size_t) uap->len; + + /* + * Align the address to a page boundary, + * and adjust the size accordingly. + */ + pageoff = (addr & PAGE_MASK); + addr -= pageoff; + size += pageoff; + size = (vm_size_t) round_page(size); + if ((int)size < 0) + return(EINVAL); if (size == 0) return (0); + /* * Check for illegal addresses. Watch out for address wrap... Note * that VM_*_ADDRESS are not constants due to casts (argh). @@ -442,15 +462,24 @@ mprotect(p, uap, retval) int *retval; { vm_offset_t addr; - vm_size_t size; + vm_size_t size, pageoff; register vm_prot_t prot; addr = (vm_offset_t) uap->addr; - if ((addr & PAGE_MASK) || uap->len < 0) - return (EINVAL); size = (vm_size_t) uap->len; prot = uap->prot & VM_PROT_ALL; + /* + * Align the address to a page boundary, + * and adjust the size accordingly. + */ + pageoff = (addr & PAGE_MASK); + addr -= pageoff; + size += pageoff; + size = (vm_size_t) round_page(size); + if ((int)size < 0) + return(EINVAL); + switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot, FALSE)) { case KERN_SUCCESS: @@ -462,6 +491,48 @@ mprotect(p, uap, retval) } #ifndef _SYS_SYSPROTO_H_ +struct minherit_args { + caddr_t addr; + int len; + int inherit; +}; +#endif +int +minherit(p, uap, retval) + struct proc *p; + struct minherit_args *uap; + int *retval; +{ + vm_offset_t addr; + vm_size_t size, pageoff; + register vm_inherit_t inherit; + + addr = (vm_offset_t)uap->addr; + size = (vm_size_t)uap->len; + inherit = uap->inherit; + + /* + * Align the address to a page boundary, + * and adjust the size accordingly. + */ + pageoff = (addr & PAGE_MASK); + addr -= pageoff; + size += pageoff; + size = (vm_size_t) round_page(size); + if ((int)size < 0) + return(EINVAL); + + switch (vm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size, + inherit)) { + case KERN_SUCCESS: + return (0); + case KERN_PROTECTION_FAILURE: + return (EACCES); + } + return (EINVAL); +} + +#ifndef _SYS_SYSPROTO_H_ struct madvise_args { caddr_t addr; int len; @@ -536,13 +607,24 @@ mlock(p, uap, retval) int *retval; { vm_offset_t addr; - vm_size_t size; + vm_size_t size, pageoff; int error; addr = (vm_offset_t) uap->addr; - if ((addr & PAGE_MASK) || uap->addr + uap->len < uap->addr) + size = (vm_size_t) uap->len; + /* + * Align the address to a page boundary, + * and adjust the size accordingly. + */ + pageoff = (addr & PAGE_MASK); + addr -= pageoff; + size += pageoff; + size = (vm_size_t) round_page(size); + + /* disable wrap around */ + if (addr + (int)size < addr) return (EINVAL); - size = round_page((vm_size_t) uap->len); + if (atop(size) + cnt.v_wire_count > vm_page_max_wired) return (EAGAIN); #ifdef pmap_wired_count @@ -572,18 +654,29 @@ munlock(p, uap, retval) int *retval; { vm_offset_t addr; - vm_size_t size; + vm_size_t size, pageoff; int error; addr = (vm_offset_t) uap->addr; - if ((addr & PAGE_MASK) || uap->addr + uap->len < uap->addr) + size = (vm_size_t) uap->len; + /* + * Align the address to a page boundary, + * and adjust the size accordingly. + */ + pageoff = (addr & PAGE_MASK); + addr -= pageoff; + size += pageoff; + size = (vm_size_t) round_page(size); + + /* disable wrap around */ + if (addr + (int)size < addr) return (EINVAL); + #ifndef pmap_wired_count error = suser(p->p_ucred, &p->p_acflag); if (error) return (error); #endif - size = round_page((vm_size_t) uap->len); error = vm_map_pageable(&p->p_vmspace->vm_map, addr, addr + size, TRUE); return (error == KERN_SUCCESS ? 0 : ENOMEM); |