init(8) is wanted to have process ID 1. It's also the only process which is assigned non-random PID (well, there's also swapper as PID 0).
This patch renames fork1() to fork1_to_pid() and introduces new argument "pid" which can be used to select PID for new process. When pid is 0, random PID is assigned. fork1() is then wrapper to fork1_to_pid() with pid argument being 0. No functional change in fork1(). Only caller (outside fork1()) for fork1_to_pid() should be in kernel main() to start the init(8) process. With above changes it's possible to remove global variable "randompid" which only purpose was to assign PID 1 to init(8). It's also possible to remove static variable "lastpid" from allocpid(). Tested in amd64 by building the base and kernel, and run some of the regress test set. diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index e21a8306854..20f92752921 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -437,14 +437,12 @@ main(void *framep) { struct proc *initproc; - if (fork1(p, FORK_FORK, NULL, 0, start_init, NULL, NULL, - &initproc)) + if (fork1_to_pid(p, 1, FORK_FORK, NULL, 0, start_init, NULL, + NULL, &initproc)) panic("fork init"); initprocess = initproc->p_p; } - randompid = 1; - /* * Create any kernel threads whose creation was deferred because * initprocess had not yet been created. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 3ff2085f732..b1d1d249ca7 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -71,7 +71,6 @@ int nprocesses = 1; /* process 0 */ int nthreads = 1; /* proc 0 */ -int randompid; /* when set to 1, pid's go random */ struct forkstat forkstat; void fork_return(void *); @@ -80,7 +79,7 @@ pid_t alloctid(void); pid_t allocpid(void); int ispidtaken(pid_t); -void process_new(struct proc *, struct process *, int); +void process_new(struct proc *, struct process *, pid_t, int); void fork_return(void *arg) @@ -176,7 +175,7 @@ process_initialize(struct process *pr, struct proc *p) * Allocate and initialize a new process. */ void -process_new(struct proc *p, struct process *parent, int flags) +process_new(struct proc *p, struct process *parent, pid_t pid, int flags) { struct process *pr; @@ -193,7 +192,7 @@ process_new(struct proc *p, struct process *parent, int flags) (caddr_t)&pr->ps_endcopy - (caddr_t)&pr->ps_startcopy); process_initialize(pr, p); - pr->ps_pid = allocpid(); + pr->ps_pid = pid ? pid : allocpid(); /* post-copy fixups */ pr->ps_pptr = parent; @@ -256,6 +255,15 @@ fork1(struct proc *curp, int flags, void *stack, pid_t *tidptr, void (*func)(void *), void *arg, register_t *retval, struct proc **rnewprocp) { + return (fork1_to_pid(curp, 0, flags, stack, tidptr, func, arg, retval, + rnewprocp)); +} + +int +fork1_to_pid(struct proc *curp, pid_t pid, int flags, void *stack, + pid_t *tidptr, void (*func)(void *), void *arg, register_t *retval, + struct proc **rnewprocp) +{ struct process *curpr = curp->p_p; struct process *pr; struct proc *p; @@ -270,7 +278,8 @@ fork1(struct proc *curp, int flags, void *stack, pid_t *tidptr, if (flags & FORK_THREAD) { if ((flags & FORK_SHAREFILES) == 0 || (flags & FORK_SIGHAND) == 0 || - (flags & FORK_SYSTEM) != 0) + (flags & FORK_SYSTEM) != 0 || + pid != 0) return (EINVAL); } if (flags & FORK_SIGHAND && (flags & FORK_SHAREVM) == 0) @@ -362,7 +371,7 @@ fork1(struct proc *curp, int flags, void *stack, pid_t *tidptr, p->p_p = pr = curpr; pr->ps_refcnt++; } else { - process_new(p, curpr, flags); + process_new(p, curpr, pid, flags); pr = p->p_p; } p->p_fd = pr->ps_fd; @@ -590,19 +599,12 @@ ispidtaken(pid_t pid) pid_t allocpid(void) { - static pid_t lastpid; pid_t pid; - if (!randompid) { - /* only used early on for system processes */ - pid = ++lastpid; - } else { - /* Find an unused pid satisfying lastpid < pid <= PID_MAX */ - do { - pid = arc4random_uniform(PID_MAX - lastpid) + 1 + - lastpid; - } while (ispidtaken(pid)); - } + /* Find an unused pid satisfying 1 < pid <= PID_MAX */ + do { + pid = 2 + arc4random_uniform(PID_MAX - 1); + } while (ispidtaken(pid)); return pid; } diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 1a1f0966518..c2163e1ac27 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -525,6 +525,8 @@ int dowait4(struct proc *, pid_t, int *, int, struct rusage *, register_t *); void cpu_exit(struct proc *); void process_initialize(struct process *, struct proc *); +int fork1_to_pid(struct proc *, pid_t, int, void *, pid_t *, + void (*)(void *), void *, register_t *, struct proc **); int fork1(struct proc *, int, void *, pid_t *, void (*)(void *), void *, register_t *, struct proc **); int groupmember(gid_t, struct ucred *); -- Ossi Herrala