fork: pass arguments to fork1 in a dedicated structure
Suggested by: kib
This commit is contained in:
parent
6c95c7903c
commit
33fd9b9a2b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=295232
@ -75,12 +75,18 @@ int
|
||||
cloudabi_sys_proc_fork(struct thread *td,
|
||||
struct cloudabi_sys_proc_fork_args *uap)
|
||||
{
|
||||
struct fork_req fr;
|
||||
struct filecaps fcaps = {};
|
||||
struct proc *p2;
|
||||
int error, fd;
|
||||
|
||||
cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_EVENT);
|
||||
error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC | RFPROCDESC;
|
||||
fr.fr_procp = &p2;
|
||||
fr.fr_pd_fd = &fd;
|
||||
fr.fr_pd_fcaps = &fcaps;
|
||||
error = fork1(td, &fr);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
/* Return the file descriptor to the parent process. */
|
||||
|
@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
|
||||
int
|
||||
linux_fork(struct thread *td, struct linux_fork_args *args)
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error;
|
||||
struct proc *p2;
|
||||
struct thread *td2;
|
||||
@ -73,8 +74,10 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
|
||||
printf(ARGS(fork, ""));
|
||||
#endif
|
||||
|
||||
if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0,
|
||||
NULL)) != 0)
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
|
||||
fr.fr_procp = &p2;
|
||||
if ((error = fork1(td, &fr)) != 0)
|
||||
return (error);
|
||||
|
||||
td2 = FIRST_THREAD_IN_PROC(p2);
|
||||
@ -97,6 +100,7 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
|
||||
int
|
||||
linux_vfork(struct thread *td, struct linux_vfork_args *args)
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error;
|
||||
struct proc *p2;
|
||||
struct thread *td2;
|
||||
@ -106,8 +110,10 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
|
||||
printf(ARGS(vfork, ""));
|
||||
#endif
|
||||
|
||||
if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED,
|
||||
0, &p2, NULL, 0, NULL)) != 0)
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED;
|
||||
fr.fr_procp = &p2;
|
||||
if ((error = fork1(td, &fr)) != 0)
|
||||
return (error);
|
||||
|
||||
td2 = FIRST_THREAD_IN_PROC(p2);
|
||||
@ -130,6 +136,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
|
||||
static int
|
||||
linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error, ff = RFPROC | RFSTOPPED;
|
||||
struct proc *p2;
|
||||
struct thread *td2;
|
||||
@ -170,7 +177,10 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
if (args->flags & LINUX_CLONE_VFORK)
|
||||
ff |= RFPPWAIT;
|
||||
|
||||
error = fork1(td, ff, 0, &p2, NULL, 0, NULL);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = ff;
|
||||
fr.fr_procp = &p2;
|
||||
error = fork1(td, &fr);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
|
@ -828,12 +828,15 @@ start_init(void *dummy)
|
||||
static void
|
||||
create_init(const void *udata __unused)
|
||||
{
|
||||
struct fork_req fr;
|
||||
struct ucred *newcred, *oldcred;
|
||||
struct thread *td;
|
||||
int error;
|
||||
|
||||
error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc,
|
||||
NULL, 0, NULL);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
|
||||
fr.fr_procp = &initproc;
|
||||
error = fork1(&thread0, &fr);
|
||||
if (error)
|
||||
panic("cannot fork init: %d\n", error);
|
||||
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
|
||||
|
@ -101,10 +101,14 @@ struct fork_args {
|
||||
int
|
||||
sys_fork(struct thread *td, struct fork_args *uap)
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error;
|
||||
struct proc *p2;
|
||||
|
||||
error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC;
|
||||
fr.fr_procp = &p2;
|
||||
error = fork1(td, &fr);
|
||||
if (error == 0) {
|
||||
td->td_retval[0] = p2->p_pid;
|
||||
td->td_retval[1] = 0;
|
||||
@ -118,16 +122,21 @@ sys_pdfork(td, uap)
|
||||
struct thread *td;
|
||||
struct pdfork_args *uap;
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error, fd;
|
||||
struct proc *p2;
|
||||
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC | RFPROCDESC;
|
||||
fr.fr_procp = &p2;
|
||||
fr.fr_pd_fd = &fd;
|
||||
fr.fr_pd_flags = uap->flags;
|
||||
/*
|
||||
* It is necessary to return fd by reference because 0 is a valid file
|
||||
* descriptor number, and the child needs to be able to distinguish
|
||||
* itself from the parent using the return value.
|
||||
*/
|
||||
error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2,
|
||||
&fd, uap->flags, NULL);
|
||||
error = fork1(td, &fr);
|
||||
if (error == 0) {
|
||||
td->td_retval[0] = p2->p_pid;
|
||||
td->td_retval[1] = 0;
|
||||
@ -140,11 +149,14 @@ sys_pdfork(td, uap)
|
||||
int
|
||||
sys_vfork(struct thread *td, struct vfork_args *uap)
|
||||
{
|
||||
int error, flags;
|
||||
struct fork_req fr;
|
||||
int error;
|
||||
struct proc *p2;
|
||||
|
||||
flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
|
||||
error = fork1(td, flags, 0, &p2, NULL, 0, NULL);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
|
||||
fr.fr_procp = &p2;
|
||||
error = fork1(td, &fr);
|
||||
if (error == 0) {
|
||||
td->td_retval[0] = p2->p_pid;
|
||||
td->td_retval[1] = 0;
|
||||
@ -155,6 +167,7 @@ sys_vfork(struct thread *td, struct vfork_args *uap)
|
||||
int
|
||||
sys_rfork(struct thread *td, struct rfork_args *uap)
|
||||
{
|
||||
struct fork_req fr;
|
||||
struct proc *p2;
|
||||
int error;
|
||||
|
||||
@ -163,7 +176,10 @@ sys_rfork(struct thread *td, struct rfork_args *uap)
|
||||
return (EINVAL);
|
||||
|
||||
AUDIT_ARG_FFLAGS(uap->flags);
|
||||
error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = uap->flags;
|
||||
fr.fr_procp = &p2;
|
||||
error = fork1(td, &fr);
|
||||
if (error == 0) {
|
||||
td->td_retval[0] = p2 ? p2->p_pid : 0;
|
||||
td->td_retval[1] = 0;
|
||||
@ -761,8 +777,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
|
||||
}
|
||||
|
||||
int
|
||||
fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
int *procdescp, int pdflags, struct filecaps *fcaps)
|
||||
fork1(struct thread *td, struct fork_req *fr)
|
||||
{
|
||||
struct proc *p1, *newproc;
|
||||
struct thread *td2;
|
||||
@ -772,6 +787,10 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
int error, nprocs_new, ok;
|
||||
static int curfail;
|
||||
static struct timeval lastfail;
|
||||
int flags, pages;
|
||||
|
||||
flags = fr->fr_flags;
|
||||
pages = fr->fr_pages;
|
||||
|
||||
/* Check for the undefined or unimplemented flags. */
|
||||
if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0)
|
||||
@ -795,7 +814,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
return (EINVAL);
|
||||
|
||||
/* Must provide a place to put a procdesc if creating one. */
|
||||
if (procdescp == NULL)
|
||||
if (fr->fr_pd_fd == NULL)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
@ -806,7 +825,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
* certain parts of a process from itself.
|
||||
*/
|
||||
if ((flags & RFPROC) == 0) {
|
||||
*procp = NULL;
|
||||
*fr->fr_procp = NULL;
|
||||
return (fork_norfproc(td, flags));
|
||||
}
|
||||
|
||||
@ -845,7 +864,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
* later.
|
||||
*/
|
||||
if (flags & RFPROCDESC) {
|
||||
error = falloc_caps(td, &fp_procdesc, procdescp, 0, fcaps);
|
||||
error = falloc_caps(td, &fp_procdesc, fr->fr_pd_fd, 0,
|
||||
fr->fr_pd_fcaps);
|
||||
if (error != 0)
|
||||
goto fail2;
|
||||
}
|
||||
@ -933,12 +953,12 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
lim_cur(td, RLIMIT_NPROC));
|
||||
}
|
||||
if (ok) {
|
||||
do_fork(td, flags, newproc, td2, vm2, pdflags);
|
||||
do_fork(td, flags, newproc, td2, vm2, fr->fr_pd_flags);
|
||||
|
||||
/*
|
||||
* Return child proc pointer to parent.
|
||||
*/
|
||||
*procp = newproc;
|
||||
*fr->fr_procp = newproc;
|
||||
if (flags & RFPROCDESC) {
|
||||
procdesc_finit(newproc->p_procdesc, fp_procdesc);
|
||||
fdrop(fp_procdesc, td);
|
||||
@ -962,7 +982,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
vmspace_free(vm2);
|
||||
uma_zfree(proc_zone, newproc);
|
||||
if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) {
|
||||
fdclose(td, fp_procdesc, *procdescp);
|
||||
fdclose(td, fp_procdesc, *fr->fr_pd_fd);
|
||||
fdrop(fp_procdesc, td);
|
||||
}
|
||||
atomic_add_int(&nprocs, -1);
|
||||
|
@ -80,6 +80,7 @@ int
|
||||
kproc_create(void (*func)(void *), void *arg,
|
||||
struct proc **newpp, int flags, int pages, const char *fmt, ...)
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error;
|
||||
va_list ap;
|
||||
struct thread *td;
|
||||
@ -88,8 +89,11 @@ kproc_create(void (*func)(void *), void *arg,
|
||||
if (!proc0.p_stats)
|
||||
panic("kproc_create called too soon");
|
||||
|
||||
error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
|
||||
pages, &p2, NULL, 0, NULL);
|
||||
bzero(&fr, sizeof(fr));
|
||||
fr.fr_flags = RFMEM | RFFDG | RFPROC | RFSTOPPED | flags;
|
||||
fr.fr_pages = pages;
|
||||
fr.fr_procp = &p2;
|
||||
error = fork1(&thread0, &fr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -907,6 +907,15 @@ struct proc *pfind_locked(pid_t pid);
|
||||
struct pgrp *pgfind(pid_t); /* Find process group by id. */
|
||||
struct proc *zpfind(pid_t); /* Find zombie process by id. */
|
||||
|
||||
struct fork_req {
|
||||
int fr_flags;
|
||||
int fr_pages;
|
||||
struct proc **fr_procp;
|
||||
int *fr_pd_fd;
|
||||
int fr_pd_flags;
|
||||
struct filecaps *fr_pd_fcaps;
|
||||
};
|
||||
|
||||
/*
|
||||
* pget() flags.
|
||||
*/
|
||||
@ -930,8 +939,7 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
|
||||
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
|
||||
void faultin(struct proc *p);
|
||||
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
|
||||
int fork1(struct thread *, int, int, struct proc **, int *, int,
|
||||
struct filecaps *);
|
||||
int fork1(struct thread *, struct fork_req *);
|
||||
void fork_exit(void (*)(void *, struct trapframe *), void *,
|
||||
struct trapframe *);
|
||||
void fork_return(struct thread *, struct trapframe *);
|
||||
|
Loading…
Reference in New Issue
Block a user