Commit 9a7dad1c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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().
parent 148b113a
......@@ -68,6 +68,7 @@ extern void sysctl_init(void);
extern void signals_init(void);
extern void buffer_init(void);
extern void pidhash_init(void);
extern void pidmap_init(void);
extern void pte_chain_init(void);
extern void radix_tree_init(void);
extern void free_initmem(void);
......@@ -394,6 +395,7 @@ asmlinkage void __init start_kernel(void)
extable_init();
rcu_init();
init_IRQ();
pidhash_init();
sched_init();
softirq_init();
time_init();
......@@ -419,7 +421,7 @@ asmlinkage void __init start_kernel(void)
page_address_init();
mem_init();
kmem_cache_sizes_init();
pidhash_init();
pidmap_init();
pgtable_cache_init();
pte_chain_init();
fork_init(num_physpages);
......
......@@ -23,10 +23,11 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/hash.h>
#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);
}
}
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