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
This commit is contained in:
Peter Wemm 1996-02-23 18:49:25 +00:00
parent e89de7b5c3
commit dabee6fecc
10 changed files with 248 additions and 50 deletions

View File

@ -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.
@ -700,6 +701,49 @@ ffree(fp)
FREE(fp, M_FILE);
}
/*
* 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.
*/

View File

@ -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, 1, retval));
return (fork1(p, ISVFORK, 0, 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 @@ fork1(p1, isvfork, retval)
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 @@ fork1(p1, isvfork, retval)
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;
@ -283,6 +323,15 @@ fork1(p1, isvfork, retval)
*/
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.
@ -293,7 +342,7 @@ fork1(p1, isvfork, retval)
*/
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 @@ fork1(p1, isvfork, retval)
* 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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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));

View File

@ -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

View File

@ -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>

View File

@ -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));

View File

@ -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

View File

@ -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:
@ -461,6 +490,48 @@ mprotect(p, uap, retval)
return (EINVAL);
}
#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;
@ -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);