#include <sys/acct.h>
#include <sys/ktrace.h>
+#include <vm/vm.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
int nprocs = 1; /* process 0 */
+#define ISFORK 0
+#define ISVFORK 1
+#define ISRFORK 2
+
int
sys_fork(p, v, retval)
struct proc *p;
register_t *retval;
{
- return (fork1(p, 0, retval));
+ return (fork1(p, ISFORK, 0, retval));
}
int
register_t *retval;
{
- return (fork1(p, 1, retval));
+ return (fork1(p, ISVFORK, 0, retval));
}
int
-fork1(p1, isvfork, retval)
+sys_rfork(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_rfork_args /* {
+ syscallarg(int) flags;
+ } */ *uap = v;
+
+ return (fork1(p, ISRFORK, SCARG(uap, flags), retval));
+}
+
+int
+fork1(p1, forktype, rforkflags, retval)
register struct proc *p1;
- int isvfork;
+ int forktype;
+ int rforkflags;
register_t *retval;
{
register struct proc *p2;
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
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.
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;
LIST_INSERT_AFTER(p1, p2, p_pglist);
p2->p_pptr = p1;
- LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling);
+ if (rforkflags & RFNOWAIT) {
+ /* XXX should we do anything? */
+ } else {
+ LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling);
+ }
LIST_INIT(&p2->p_children);
#ifdef KTRACE
*/
p1->p_holdcnt++;
+ if (forktype == ISRFORK && (rforkflags & RFMEM)) {
+ /* share as much address space as possible */
+ (void) vm_map_inherit(&p1->p_vmspace->vm_map,
+ VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS - MAXSSIZ,
+ VM_INHERIT_SHARE);
+ }
+
#ifdef __FORK_BRAINDAMAGE
/*
* Set return values for child before vm_fork,
* 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);
*/
#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 */