Commit c3ee1c75 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Reduce random driver lock contention

From: Matt Mackall <mpm@selenic.com>

The new locking in the random driver is consuming 60% of CPU resources in
Anton's monster power5 boxes.


Basically, when the primary pool is 7/8th full, we shut off the firehose
and go into a trickle mode to keep the pool fresh.  Saves CPU for everyone
and should make the contention drop off the charts too (though the trickle
factor might need adjusting again for Origin-class machines).
parent e623ce48
...@@ -253,6 +253,7 @@ ...@@ -253,6 +253,7 @@
#include <linux/genhd.h> #include <linux/genhd.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/percpu.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -280,6 +281,15 @@ static int random_read_wakeup_thresh = 64; ...@@ -280,6 +281,15 @@ static int random_read_wakeup_thresh = 64;
*/ */
static int random_write_wakeup_thresh = 128; static int random_write_wakeup_thresh = 128;
/*
* When the input pool goes over trickle_thresh, start dropping most
* samples to avoid wasting CPU time and reduce lock contention.
*/
static int trickle_thresh = DEFAULT_POOL_SIZE * 7;
static DEFINE_PER_CPU(int, trickle_count) = 0;
/* /*
* A pool of size .poolwords is stirred with a primitive polynomial * A pool of size .poolwords is stirred with a primitive polynomial
* of degree .poolwords over GF(2). The taps for various sizes are * of degree .poolwords over GF(2). The taps for various sizes are
...@@ -778,6 +788,11 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) ...@@ -778,6 +788,11 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
__s32 delta, delta2, delta3; __s32 delta, delta2, delta3;
int entropy = 0; int entropy = 0;
/* if over the trickle threshold, use only 1 in 4096 samples */
if ( random_state->entropy_count > trickle_thresh &&
(__get_cpu_var(trickle_count)++ & 0xfff))
return;
#if defined (__i386__) || defined (__x86_64__) #if defined (__i386__) || defined (__x86_64__)
if (cpu_has_tsc) { if (cpu_has_tsc) {
__u32 high; __u32 high;
......
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