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

Reply via email to