Commit f59ad67e authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds

[PATCH] use hlist for pid hash

Use hlists for the PID hashes.  This halves the memory footprint of these
hashes.  No benchmarks, but I think this is a worthy improvement because
the hashes are something that would be likely to have significant portions
loaded into the cache of every CPU on some workloads.

This comes at the "expense" of
	1. reintroducing the memory  prefetch into the hash traversal loop;
	2. adding new pids to the head of the list instead of the tail. I
	   suspect that if this was a big problem then the hash isn't sized
	   well or could benefit from moving hot entries to the head.

Also, account for all the pid hashes when reporting hash memory usage.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2c05d9eb
...@@ -16,7 +16,7 @@ struct pid ...@@ -16,7 +16,7 @@ struct pid
atomic_t count; atomic_t count;
struct task_struct *task; struct task_struct *task;
struct list_head task_list; struct list_head task_list;
struct list_head hash_chain; struct hlist_node hash_chain;
}; };
struct pid_link struct pid_link
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <linux/hash.h> #include <linux/hash.h>
#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
static struct list_head *pid_hash[PIDTYPE_MAX]; static struct hlist_head *pid_hash[PIDTYPE_MAX];
static int pidhash_shift; static int pidhash_shift;
int pid_max = PID_MAX_DEFAULT; int pid_max = PID_MAX_DEFAULT;
...@@ -148,11 +148,11 @@ int alloc_pidmap(void) ...@@ -148,11 +148,11 @@ int alloc_pidmap(void)
fastcall struct pid *find_pid(enum pid_type type, int nr) fastcall struct pid *find_pid(enum pid_type type, int nr)
{ {
struct list_head *elem, *bucket = &pid_hash[type][pid_hashfn(nr)]; struct hlist_node *elem;
struct pid *pid; struct pid *pid;
__list_for_each(elem, bucket) { hlist_for_each_entry(pid, elem,
pid = list_entry(elem, struct pid, hash_chain); &pid_hash[type][pid_hashfn(nr)], hash_chain) {
if (pid->nr == nr) if (pid->nr == nr)
return pid; return pid;
} }
...@@ -179,7 +179,8 @@ int fastcall attach_pid(task_t *task, enum pid_type type, int nr) ...@@ -179,7 +179,8 @@ int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
INIT_LIST_HEAD(&pid->task_list); INIT_LIST_HEAD(&pid->task_list);
pid->task = task; pid->task = task;
get_task_struct(task); get_task_struct(task);
list_add(&pid->hash_chain, &pid_hash[type][pid_hashfn(nr)]); hlist_add_head(&pid->hash_chain,
&pid_hash[type][pid_hashfn(nr)]);
} }
list_add_tail(&task->pids[type].pid_chain, &pid->task_list); list_add_tail(&task->pids[type].pid_chain, &pid->task_list);
task->pids[type].pidptr = pid; task->pids[type].pidptr = pid;
...@@ -198,7 +199,7 @@ static inline int __detach_pid(task_t *task, enum pid_type type) ...@@ -198,7 +199,7 @@ static inline int __detach_pid(task_t *task, enum pid_type type)
return 0; return 0;
nr = pid->nr; nr = pid->nr;
list_del(&pid->hash_chain); hlist_del(&pid->hash_chain);
put_task_struct(pid->task); put_task_struct(pid->task);
return nr; return nr;
...@@ -277,9 +278,9 @@ void __init pidhash_init(void) ...@@ -277,9 +278,9 @@ void __init pidhash_init(void)
pidhash_shift = min(12, pidhash_shift); pidhash_shift = min(12, pidhash_shift);
pidhash_size = 1 << pidhash_shift; pidhash_size = 1 << pidhash_shift;
printk("PID hash table entries: %d (order %d: %Zd bytes)\n", printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
pidhash_size, pidhash_shift, pidhash_size, pidhash_shift,
pidhash_size * sizeof(struct list_head)); PIDTYPE_MAX * pidhash_size * sizeof(struct hlist_head));
for (i = 0; i < PIDTYPE_MAX; i++) { for (i = 0; i < PIDTYPE_MAX; i++) {
pid_hash[i] = alloc_bootmem(pidhash_size * pid_hash[i] = alloc_bootmem(pidhash_size *
...@@ -287,7 +288,7 @@ void __init pidhash_init(void) ...@@ -287,7 +288,7 @@ void __init pidhash_init(void)
if (!pid_hash[i]) if (!pid_hash[i])
panic("Could not alloc pidhash!\n"); panic("Could not alloc pidhash!\n");
for (j = 0; j < pidhash_size; j++) for (j = 0; j < pidhash_size; j++)
INIT_LIST_HEAD(&pid_hash[i][j]); INIT_HLIST_HEAD(&pid_hash[i][j]);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment