Instead of using a fixed size hash table for procs, use an rb tree.
Makes thread/process lookup even more web scale.
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.189
diff -u -p -r1.189 init_main.c
--- kern/init_main.c 3 Jun 2013 16:55:22 -0000 1.189
+++ kern/init_main.c 5 Jun 2013 02:36:56 -0000
@@ -274,7 +274,7 @@ main(void *framep)
LIST_INSERT_HEAD(&allproc, p, p_list);
pr->ps_pgrp = &pgrp0;
- LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
+ RB_INSERT(proc_rb_procs, &proc_rb_root, p);
LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
LIST_INIT(&pgrp0.pg_members);
LIST_INSERT_HEAD(&pgrp0.pg_members, pr, ps_pglist);
Index: kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.125
diff -u -p -r1.125 kern_exit.c
--- kern/kern_exit.c 5 Jun 2013 00:53:26 -0000 1.125
+++ kern/kern_exit.c 5 Jun 2013 02:40:47 -0000
@@ -254,7 +254,7 @@ exit1(struct proc *p, int rv, int flags)
* Remove proc from pidhash chain so looking it up won't
* work. Move it from allproc to zombproc, but do not yet
* wake up the reaper. We will put the proc on the
- * deadproc list later (using the p_hash member), and
+ * deadproc list later (using the p_rbtree member), and
* wake up the reaper when we do.
*/
/*
@@ -262,7 +262,7 @@ exit1(struct proc *p, int rv, int flags)
*/
p->p_stat = SDEAD;
- LIST_REMOVE(p, p_hash);
+ RB_REMOVE(proc_rb_procs, &proc_rb_root, p);
LIST_REMOVE(p, p_list);
LIST_INSERT_HEAD(&zombproc, p, p_list);
@@ -366,10 +366,10 @@ exit1(struct proc *p, int rv, int flags)
* critical section of process exit, and thus locking it can't
* modify interrupt state. We use a simple spin lock for this
* proclist. Processes on this proclist are also on zombproc;
- * we use the p_hash member to linkup to deadproc.
+ * we use the p_rbtree member to linkup to deadproc.
*/
struct mutex deadproc_mutex = MUTEX_INITIALIZER(IPL_NONE);
-struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc);
+struct proc_rb_procs deadproc = RB_INITIALIZER(&deadproc);
/*
* We are called from cpu_exit() once it is safe to schedule the
@@ -380,13 +380,13 @@ struct proclist deadproc = LIST_HEAD_INI
* we should refrain from changing any interrupt state.
*
* We lock the deadproc list, place the proc on that list (using
- * the p_hash member), and wake up the reaper.
+ * the p_rbtree member), and wake up the reaper.
*/
void
exit2(struct proc *p)
{
mtx_enter(&deadproc_mutex);
- LIST_INSERT_HEAD(&deadproc, p, p_hash);
+ RB_INSERT(proc_rb_procs, &deadproc, p);
mtx_leave(&deadproc_mutex);
wakeup(&deadproc);
@@ -408,11 +408,11 @@ reaper(void)
for (;;) {
mtx_enter(&deadproc_mutex);
- while ((p = LIST_FIRST(&deadproc)) == NULL)
+ while ((p = RB_ROOT(&deadproc)) == NULL)
msleep(&deadproc, &deadproc_mutex, PVM, "reaper", 0);
/* Remove us from the deadproc list. */
- LIST_REMOVE(p, p_hash);
+ RB_REMOVE(proc_rb_procs, &deadproc, p);
mtx_leave(&deadproc_mutex);
KERNEL_LOCK();
Index: kern/kern_fork.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.150
diff -u -p -r1.150 kern_fork.c
--- kern/kern_fork.c 5 Jun 2013 00:53:26 -0000 1.150
+++ kern/kern_fork.c 5 Jun 2013 02:24:32 -0000
@@ -438,7 +438,7 @@ fork1(struct proc *curp, int exitsig, in
p->p_pid = allocpid();
LIST_INSERT_HEAD(&allproc, p, p_list);
- LIST_INSERT_HEAD(PIDHASH(p->p_pid), p, p_hash);
+ RB_INSERT(proc_rb_procs, &proc_rb_root, p);
if ((flags & FORK_THREAD) == 0) {
LIST_INSERT_AFTER(curpr, pr, ps_pglist);
LIST_INSERT_HEAD(&curpr->ps_children, pr, ps_sibling);
Index: kern/kern_proc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.50
diff -u -p -r1.50 kern_proc.c
--- kern/kern_proc.c 17 Feb 2013 17:39:29 -0000 1.50
+++ kern/kern_proc.c 5 Jun 2013 02:54:12 -0000
@@ -56,8 +56,9 @@ u_long uihash; /* size of hash table -
/*
* Other process lists
*/
-struct pidhashhead *pidhashtbl;
-u_long pidhash;
+int rb_proc_compare(struct proc *, struct proc *);
+RB_GENERATE(proc_rb_procs, proc, p_rbtree, rb_proc_compare);
+struct proc_rb_procs proc_rb_root;
struct pgrphashhead *pgrphashtbl;
u_long pgrphash;
struct proclist allproc;
@@ -84,12 +85,11 @@ procinit(void)
{
LIST_INIT(&allproc);
LIST_INIT(&zombproc);
+ RB_INIT(&proc_rb_root);
-
- pidhashtbl = hashinit(maxthread / 4, M_PROC, M_NOWAIT, &pidhash);
pgrphashtbl = hashinit(maxprocess / 4, M_PROC, M_NOWAIT, &pgrphash);
uihashtbl = hashinit(maxprocess / 16, M_PROC, M_NOWAIT, &uihash);
- if (!pidhashtbl || !pgrphashtbl || !uihashtbl)
+ if (!pgrphashtbl || !uihashtbl)
panic("procinit: malloc");
pool_init(&proc_pool, sizeof(struct proc), 0, 0, 0, "procpl",
@@ -166,15 +166,23 @@ inferior(struct process *pr, struct proc
/*
* Locate a proc (thread) by number
*/
+int
+rb_proc_compare(struct proc *a, struct proc *b)
+{
+ if (a->p_pid < b->p_pid)
+ return -1;
+ if (a->p_pid > b->p_pid)
+ return 1;
+ return 0;
+}
+
struct proc *
pfind(pid_t pid)
{
- struct proc *p;
+ struct proc q;
- LIST_FOREACH(p, PIDHASH(pid), p_hash)
- if (p->p_pid == pid)
- return (p);
- return (NULL);
+ q.p_pid = pid;
+ return RB_FIND(proc_rb_procs, &proc_rb_root, &q);
}
/*
@@ -184,10 +192,12 @@ struct process *
prfind(pid_t pid)
{
struct proc *p;
+ struct proc q;
- LIST_FOREACH(p, PIDHASH(pid), p_hash)
- if (p->p_pid == pid)
- return (p->p_flag & P_THREAD ? NULL : p->p_p);
+ q.p_pid = pid;
+ p = RB_FIND(proc_rb_procs, &proc_rb_root, &q);
+ if (p && !(p->p_flag & P_THREAD))
+ return (p->p_p);
return (NULL);
}
Index: kern/kern_sched.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sched.c,v
retrieving revision 1.29
diff -u -p -r1.29 kern_sched.c
--- kern/kern_sched.c 3 Jun 2013 16:55:22 -0000 1.29
+++ kern/kern_sched.c 5 Jun 2013 02:50:35 -0000
@@ -88,7 +88,7 @@ sched_init_cpu(struct cpu_info *ci)
kthread_create_deferred(sched_kthreads_create, ci);
- LIST_INIT(&spc->spc_deadproc);
+ RB_INIT(&spc->spc_deadproc);
/*
* Slight hack here until the cpuset code handles cpu_info
@@ -148,8 +148,9 @@ sched_idle(void *v)
mi_switch();
SCHED_UNLOCK(s);
- while ((dead = LIST_FIRST(&spc->spc_deadproc))) {
- LIST_REMOVE(dead, p_hash);
+ while ((dead = RB_ROOT(&spc->spc_deadproc))) {
+ RB_REMOVE(proc_rb_procs, &spc->spc_deadproc,
+ dead);
exit2(dead);
}
}
@@ -198,7 +199,7 @@ sched_exit(struct proc *p)
timespecsub(&ts, &spc->spc_runtime, &ts);
timespecadd(&p->p_rtime, &ts, &p->p_rtime);
- LIST_INSERT_HEAD(&spc->spc_deadproc, p, p_hash);
+ RB_INSERT(proc_rb_procs, &spc->spc_deadproc, p);
/* This process no longer needs to hold the kernel lock. */
KERNEL_UNLOCK();
Index: sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.167
diff -u -p -r1.167 proc.h
--- sys/proc.h 5 Jun 2013 00:53:27 -0000 1.167
+++ sys/proc.h 5 Jun 2013 03:00:09 -0000
@@ -43,6 +43,7 @@
#include <machine/proc.h> /* Machine-dependent proc substruct. */
#include <sys/selinfo.h> /* For struct selinfo */
#include <sys/queue.h>
+#include <sys/tree.h>
#include <sys/timeout.h> /* For struct timeout */
#include <sys/event.h> /* For struct klist */
#include <sys/mutex.h> /* For struct mutex */
@@ -270,7 +271,7 @@ struct proc {
u_char p_descfd; /* if not 255, fdesc permits this fd */
pid_t p_pid; /* Process identifier. */
- LIST_ENTRY(proc) p_hash; /* Hash chain. */
+ RB_ENTRY(proc) p_rbtree; /* RB tree by pid. */
/* The following fields are all zeroed upon creation in fork. */
#define p_startzero p_dupfd
@@ -484,9 +485,8 @@ struct uidinfo *uid_find(uid_t);
#define EXIT_THREAD 0x00000002
#define EXIT_THREAD_NOCHECK 0x00000003
-#define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash])
-extern LIST_HEAD(pidhashhead, proc) *pidhashtbl;
-extern u_long pidhash;
+RB_PROTOTYPE(proc_rb_procs, proc, p_rbtree, rb_proc_compare);
+extern struct proc_rb_procs proc_rb_root;
#define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash])
extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl;
Index: sys/sched.h
===================================================================
RCS file: /cvs/src/sys/sys/sched.h,v
retrieving revision 1.33
diff -u -p -r1.33 sched.h
--- sys/sched.h 4 Jun 2013 22:17:34 -0000 1.33
+++ sys/sched.h 5 Jun 2013 02:50:30 -0000
@@ -70,6 +70,7 @@
#define _SYS_SCHED_H_
#include <sys/queue.h>
+#include <sys/tree.h>
/*
* Posix defines a <sched.h> which may want to include <sys/sched.h>
@@ -113,7 +114,7 @@ struct schedstate_percpu {
#ifdef notyet
struct proc *spc_reaper; /* dead proc reaper */
#endif
- LIST_HEAD(,proc) spc_deadproc;
+ RB_HEAD(proc_rb_procs,proc) spc_deadproc;
};
#ifdef _KERNEL