From 9a7dad1c87fc2ba65f2fdc745c69fd5500e04b09 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 5 Jan 2003 03:51:56 -0800 Subject: [PATCH] Dynamically size the pidhash hash table. Patch from Bill Irwin. Prodding from me. The hashtables in kernel/pid.c are 128 kbytes, which is far too large for very small machines. So we dynamically size them and allocate them from bootmem. From 16 buckets on the very smallest machine up to 4096 buckets (effectively half the current size) with one gigabyte of memory or more. The patch also switches the hashing from a custom hash over to the more powerful hash_long(). --- kernel/pid.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'kernel') diff --git a/kernel/pid.c b/kernel/pid.c index ed6adbba677b..42e554bd7d30 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -23,10 +23,11 @@ #include #include #include +#include -#define PIDHASH_SIZE 4096 -#define pid_hashfn(nr) ((nr >> 8) ^ nr) & (PIDHASH_SIZE - 1) -static struct list_head pid_hash[PIDTYPE_MAX][PIDHASH_SIZE]; +#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) +static struct list_head *pid_hash[PIDTYPE_MAX]; +static int pidhash_shift; int pid_max = PID_MAX_DEFAULT; int last_pid; @@ -258,20 +259,46 @@ void switch_exec_pids(task_t *leader, task_t *thread) attach_pid(leader, PIDTYPE_SID, leader->session); } +/* + * The pid hash table is scaled according to the amount of memory in the + * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or + * more. + */ void __init pidhash_init(void) { - int i, j; + int i, j, pidhash_size; + unsigned long megabytes = max_pfn >> (20 - PAGE_SHIFT); + + pidhash_shift = max(4, fls(megabytes * 4)); + pidhash_shift = min(12, pidhash_shift); + pidhash_size = 1 << pidhash_shift; + + printk("PID hash table entries: %d (order %d: %d bytes)\n", + pidhash_size, pidhash_shift, + pidhash_size * sizeof(struct list_head)); + + for (i = 0; i < PIDTYPE_MAX; i++) { + pid_hash[i] = alloc_bootmem(pidhash_size * + sizeof(struct list_head)); + if (!pid_hash[i]) + panic("Could not alloc pidhash!\n"); + for (j = 0; j < pidhash_size; j++) + INIT_LIST_HEAD(&pid_hash[i][j]); + } +} + +void __init pidmap_init(void) +{ + int i; - /* - * Allocate PID 0, and hash it via all PID types: - */ pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL); set_bit(0, pidmap_array->page); atomic_dec(&pidmap_array->nr_free); - for (i = 0; i < PIDTYPE_MAX; i++) { - for (j = 0; j < PIDHASH_SIZE; j++) - INIT_LIST_HEAD(&pid_hash[i][j]); + /* + * Allocate PID 0, and hash it via all PID types: + */ + + for (i = 0; i < PIDTYPE_MAX; i++) attach_pid(current, i, 0); - } } -- cgit v1.2.3