diff options
author | markm <markm@FreeBSD.org> | 2001-02-11 16:21:35 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2001-02-11 16:21:35 +0000 |
commit | ea5e661a0c8897c76720c291763c1873f300514d (patch) | |
tree | f84a3ea37ff846fb029887eaaeefe44253b81bc7 | |
parent | c7a67722025c1c7a6f659d955a11b7b85887920c (diff) | |
download | FreeBSD-src-ea5e661a0c8897c76720c291763c1873f300514d.zip FreeBSD-src-ea5e661a0c8897c76720c291763c1873f300514d.tar.gz |
Make a big improvement to entropy-harvesting speed by not having any
locks (only atomic assigns) in the harvest ringbuffer.
-rw-r--r-- | sys/dev/random/yarrow.c | 103 | ||||
-rw-r--r-- | sys/dev/random/yarrow.h | 4 |
2 files changed, 41 insertions, 66 deletions
diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c index f1325e5..9b07af8 100644 --- a/sys/dev/random/yarrow.c +++ b/sys/dev/random/yarrow.c @@ -50,7 +50,6 @@ #include <dev/random/yarrow.h> /* #define DEBUG */ -/* #define DEBUG1 */ /* Very noisy - prints plenty harvesting stats */ static void generator_gate(void); static void reseed(int); @@ -69,14 +68,12 @@ struct harvest { u_char entropy[HARVESTSIZE]; /* the harvested entropy */ u_int size, bits, frac; /* stats about the entropy */ enum esource source; /* stats about the entropy */ - u_int pool; /* which pool this goes into */ }; /* Ring buffer holding harvested entropy */ static struct harvestring { - struct mtx lockout_mtx; - int head; - int tail; + volatile int head; + volatile int tail; struct harvest data[HARVEST_RING_SIZE]; } harvestring; @@ -91,7 +88,7 @@ static struct proc *random_kthread_proc; static void random_kthread(void *arg /* NOTUSED */) { - int pl, src, overthreshhold[2], head, newtail; + int pl, src, overthreshhold[2], newtail; struct harvest *event; struct source *source; @@ -107,31 +104,29 @@ random_kthread(void *arg /* NOTUSED */) for (;;) { - head = atomic_load_acq_int(&harvestring.head); - newtail = (harvestring.tail + 1) % HARVEST_RING_SIZE; - if (harvestring.tail == head) - tsleep(&harvestring.head, PUSER, "rndslp", hz/10); + if (harvestring.tail == harvestring.head) + tsleep(&harvestring, PUSER, "rndslp", hz/10); else { -#ifdef DEBUG1 - mtx_lock(&Giant); - printf("HARVEST src=%d bits=%d/%d pool=%d count=%lld\n", - event->source, event->bits, event->frac, - event->pool, event->somecounter); - mtx_unlock(&Giant); -#endif /* Suck the harvested entropy out of the queue and hash * it into the appropriate pool. */ + newtail = (harvestring.tail + 1) & HARVEST_RING_MASK; event = &harvestring.data[harvestring.tail]; + + /* Bump the ring counter. This action is assumed + * to be atomic. + */ harvestring.tail = newtail; - source = &random_state.pool[event->pool].source[event->source]; - yarrow_hash_iterate(&random_state.pool[event->pool].hash, + pl = random_state.which = !random_state.which; + + source = &random_state.pool[pl].source[event->source]; + yarrow_hash_iterate(&random_state.pool[pl].hash, event->entropy, sizeof(event->entropy)); - yarrow_hash_iterate(&random_state.pool[event->pool].hash, + yarrow_hash_iterate(&random_state.pool[pl].hash, &event->somecounter, sizeof(event->somecounter)); source->frac += event->frac; source->bits += event->bits + source->frac/1024; @@ -189,6 +184,9 @@ random_init(void) */ random_state.seeded = 1; + /* Yarrow parameters. Do not adjust these unless you have + * have a very good clue about what they do! + */ random_state.gengateinterval = 10; random_state.bins = 10; random_state.pool[0].thresh = 100; @@ -196,9 +194,7 @@ random_init(void) random_state.slowoverthresh = 2; random_state.which = FAST; - /* Initialise the mutexes */ mtx_init(&random_reseed_mtx, "random reseed", MTX_DEF); - mtx_init(&harvestring.lockout_mtx, "random harvest", MTX_DEF); harvestring.head = 0; harvestring.tail = 0; @@ -240,11 +236,8 @@ random_deinit(void) #endif /* Command the hash/reseed thread to end and wait for it to finish */ - mtx_lock(&harvestring.lockout_mtx); random_kthread_control = -1; - msleep((void *)&random_kthread_control, &harvestring.lockout_mtx, PUSER, - "rndend", 0); - mtx_unlock(&harvestring.lockout_mtx); + tsleep((void *)&random_kthread_control, PUSER, "rndend", 0); #ifdef DEBUG mtx_lock(&Giant); @@ -252,9 +245,7 @@ random_deinit(void) mtx_unlock(&Giant); #endif - /* Remove the mutexes */ mtx_destroy(&random_reseed_mtx); - mtx_destroy(&harvestring.lockout_mtx); #ifdef DEBUG mtx_lock(&Giant); @@ -492,52 +483,32 @@ random_harvest_internal(u_int64_t somecounter, void *entropy, u_int count, u_int bits, u_int frac, enum esource origin) { struct harvest *harvest; - int newhead, tail; + int newhead; -#ifdef DEBUG1 - mtx_lock(&Giant); - printf("Random harvest\n"); - mtx_unlock(&Giant); -#endif - if (origin < ENTROPYSOURCE) { + newhead = (harvestring.head + 1) & HARVEST_RING_MASK; - /* Add the harvested data to the ring buffer, but - * do not block. - */ - if (mtx_trylock(&harvestring.lockout_mtx)) { - - tail = atomic_load_acq_int(&harvestring.tail); - newhead = (harvestring.head + 1) % HARVEST_RING_SIZE; - - if (newhead != tail) { + if (newhead != harvestring.tail) { - harvest = &harvestring.data[harvestring.head]; + /* Add the harvested data to the ring buffer */ - /* toggle the pool for next insertion */ - harvest->pool = random_state.which; - random_state.which = !random_state.which; + harvest = &harvestring.data[harvestring.head]; - /* Stuff the harvested data into the ring */ - harvest->somecounter = somecounter; - count = count > HARVESTSIZE ? HARVESTSIZE : count; - memcpy(harvest->entropy, entropy, count); - harvest->size = count; - harvest->bits = bits; - harvest->frac = frac; - harvest->source = origin; + /* Stuff the harvested data into the ring */ + harvest->somecounter = somecounter; + count = count > HARVESTSIZE ? HARVESTSIZE : count; + memcpy(harvest->entropy, entropy, count); + harvest->size = count; + harvest->bits = bits; + harvest->frac = frac; + harvest->source = origin < ENTROPYSOURCE ? origin : 0; - /* Bump the ring counter and shake the reseed - * process - */ - harvestring.head = newhead; - wakeup(&harvestring.head); - - } - mtx_unlock(&harvestring.lockout_mtx); - - } + /* Bump the ring counter. This action is assumed + * to be atomic. + */ + harvestring.head = newhead; } + } /* Helper routine to perform explicit reseeds */ diff --git a/sys/dev/random/yarrow.h b/sys/dev/random/yarrow.h index 3c76d96..d605356 100644 --- a/sys/dev/random/yarrow.h +++ b/sys/dev/random/yarrow.h @@ -31,7 +31,10 @@ * an enum in sys/random.h */ +/* The ring size _MUST_ be a power of 2 */ #define HARVEST_RING_SIZE 1024 /* harvest ring buffer size */ +#define HARVEST_RING_MASK (HARVEST_RING_SIZE - 1) + #define TIMEBIN 16 /* max value for Pt/t */ #define HARVESTSIZE 16 /* max size of each harvested entropy unit */ @@ -72,6 +75,7 @@ struct random_state { int which; /* toggle - shows the current insertion pool */ int seeded; /* 0 causes blocking 1 allows normal output */ struct selinfo rsel; /* For poll(2) */ + u_char raw[HARVESTSIZE];/* Raw buffer for checking */ }; extern struct random_state random_state; |