svn commit: r262380 - projects/random_number_generator/sys/dev/random
Mark Murray
markm at FreeBSD.org
Sun Feb 23 18:49:53 UTC 2014
Author: markm
Date: Sun Feb 23 18:49:52 2014
New Revision: 262380
URL: http://svnweb.freebsd.org/changeset/base/262380
Log:
Remove STAILQ manipulations from the harvest path. This will be a lot more friendly to the critical bits of the kernel.
Modified:
projects/random_number_generator/sys/dev/random/random_harvestq.c
projects/random_number_generator/sys/dev/random/random_harvestq.h
Modified: projects/random_number_generator/sys/dev/random/random_harvestq.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.c Sun Feb 23 18:45:04 2014 (r262379)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.c Sun Feb 23 18:49:52 2014 (r262380)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000-2013 Mark R V Murray
+ * Copyright (c) 2000-2014 Mark R V Murray
* Copyright (c) 2013 Arthur Mesh
* Copyright (c) 2004 Robert N. M. Watson
* All rights reserved.
@@ -70,16 +70,18 @@ static struct sysctl_ctx_list random_cli
*/
static struct mtx harvest_mtx;
-/* Lockable FIFO queue holding entropy buffers */
-struct entropyfifo {
- STAILQ_HEAD(harvestlist, harvest_event) head;
-};
-
-/* Empty entropy buffers */
-static struct entropyfifo emptyfifo;
-
-/* Harvested entropy */
-static struct entropyfifo harvestfifo;
+/*
+ * Lockable FIFO ring buffer holding entropy events
+ * If ring_in == ring_out,
+ * the buffer is empty.
+ * If (ring_in + 1) == ring_out (MOD RANDOM_FIFO_MAX),
+ * the buffer is full.
+ */
+static struct entropyfifo {
+ struct harvest_event ring[RANDOM_FIFO_MAX];
+ volatile u_int ring_in;
+ volatile u_int ring_out;
+} entropyfifo;
/* Round-robin destination cache. */
u_int harvest_destination[ENTROPYSOURCE];
@@ -107,32 +109,19 @@ static struct proc *random_kthread_proc;
static void
random_kthread(void *arg __unused)
{
- struct entropyfifo local_queue;
- struct harvest_event *event = NULL;
-
- STAILQ_INIT(&local_queue.head);
+ u_int maxloop;
/* Process until told to stop */
mtx_lock_spin(&harvest_mtx);
for (; random_kthread_control >= 0;) {
- /*
- * Grab all the entropy events.
- * Drain entropy source records into a thread-local
- * queue for processing while not holding the mutex.
- */
- STAILQ_CONCAT(&local_queue.head, &harvestfifo.head);
-
- /*
- * Deal with events, if any.
- * Then transfer the used events back into the empty fifo.
- */
- if (!STAILQ_EMPTY(&local_queue.head)) {
+ /* Deal with events, if any. Restrict the number we do in one go. */
+ maxloop = RANDOM_FIFO_MAX;
+ while ((entropyfifo.ring_out != entropyfifo.ring_in) && maxloop--) {
+ entropyfifo.ring_out = (entropyfifo.ring_out + 1)%RANDOM_FIFO_MAX;
mtx_unlock_spin(&harvest_mtx);
- STAILQ_FOREACH(event, &local_queue.head, he_next)
- harvest_process_event(event);
+ harvest_process_event(entropyfifo.ring + entropyfifo.ring_out);
mtx_lock_spin(&harvest_mtx);
- STAILQ_CONCAT(&emptyfifo.head, &local_queue.head);
}
/*
@@ -241,9 +230,8 @@ void
random_harvestq_init(void (*event_processor)(struct harvest_event *), int poolcount)
{
uint8_t *keyfile, *data;
- int error, i;
+ int error;
size_t size, j;
- struct harvest_event *np;
struct sysctl_oid *random_sys_o;
#ifdef RANDOM_DEBUG
@@ -272,25 +260,15 @@ random_harvestq_init(void (*event_proces
OID_AUTO, "mask_symbolic", CTLTYPE_STRING | CTLFLAG_RD,
NULL, 0, random_print_harvestmask_symbolic, "A", "Entropy harvesting mask (symbolic)");
- /* Initialise the harvest fifos */
-
- /* Contains the currently unused event structs. */
- STAILQ_INIT(&emptyfifo.head);
- for (i = 0; i < RANDOM_FIFO_MAX; i++) {
- np = malloc(sizeof(struct harvest_event), M_ENTROPY, M_WAITOK);
- STAILQ_INSERT_TAIL(&emptyfifo.head, np, he_next);
- }
-
- /* Will contain the queued-up events. */
- STAILQ_INIT(&harvestfifo.head);
-
/* Point to the correct event_processing function */
harvest_process_event = event_processor;
/* Store the pool count (used by live source feed) */
harvest_pool_count = poolcount;
+ /* Initialise the harvesting mutex and in/out indexes. */
mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN);
+ entropyfifo.ring_in = entropyfifo.ring_out = 0U;
/* Start the hash/reseed thread */
error = kproc_create(random_kthread, NULL,
@@ -321,7 +299,6 @@ random_harvestq_init(void (*event_proces
void
random_harvestq_deinit(void)
{
- struct harvest_event *np;
#ifdef RANDOM_DEBUG
printf("random: %s\n", __func__);
@@ -333,18 +310,6 @@ random_harvestq_deinit(void)
random_kthread_control = -1;
tsleep((void *)&random_kthread_control, 0, "term", 0);
- /* Destroy the harvest fifos */
- while (!STAILQ_EMPTY(&emptyfifo.head)) {
- np = STAILQ_FIRST(&emptyfifo.head);
- STAILQ_REMOVE_HEAD(&emptyfifo.head, he_next);
- free(np, M_ENTROPY);
- }
- while (!STAILQ_EMPTY(&harvestfifo.head)) {
- np = STAILQ_FIRST(&harvestfifo.head);
- STAILQ_REMOVE_HEAD(&harvestfifo.head, he_next);
- free(np, M_ENTROPY);
- }
-
mtx_destroy(&harvest_mtx);
sysctl_ctx_free(&random_clist);
@@ -370,6 +335,7 @@ random_harvestq_internal(const void *ent
{
struct harvest_event *event;
size_t c;
+ u_int ring_in;
KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE,
("random_harvest_internal: origin %d invalid\n", origin));
@@ -378,28 +344,24 @@ random_harvestq_internal(const void *ent
if (!(harvest_source_mask & (1U << origin)))
return;
- /* Lockless check to avoid lock operations if queue is empty. */
- if (STAILQ_EMPTY(&emptyfifo.head))
+ /* Lockless check to avoid lock operations if queue is full. */
+ ring_in = (entropyfifo.ring_in + 1)%RANDOM_FIFO_MAX;
+ if (ring_in == entropyfifo.ring_out)
return;
mtx_lock_spin(&harvest_mtx);
- event = STAILQ_FIRST(&emptyfifo.head);
- if (event != NULL) {
- /* Add the harvested data to the fifo */
- STAILQ_REMOVE_HEAD(&emptyfifo.head, he_next);
- event->he_somecounter = get_cyclecount();
- event->he_size = count;
- event->he_bits = bits;
- event->he_source = origin;
- event->he_destination = harvest_destination[origin]++;
- c = MIN(count, HARVESTSIZE);
- memcpy(event->he_entropy, entropy, c);
- memset(event->he_entropy + c, 0, HARVESTSIZE - c);
+ entropyfifo.ring_in = ring_in;
+ event = entropyfifo.ring + entropyfifo.ring_in;
- STAILQ_INSERT_TAIL(&harvestfifo.head,
- event, he_next);
- }
+ event->he_somecounter = get_cyclecount();
+ event->he_size = count;
+ event->he_bits = bits;
+ event->he_source = origin;
+ event->he_destination = harvest_destination[origin]++;
+ c = MIN(count, HARVESTSIZE);
+ memcpy(event->he_entropy, entropy, c);
+ memset(event->he_entropy + c, 0, HARVESTSIZE - c);
mtx_unlock_spin(&harvest_mtx);
}
Modified: projects/random_number_generator/sys/dev/random/random_harvestq.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.h Sun Feb 23 18:45:04 2014 (r262379)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.h Sun Feb 23 18:49:52 2014 (r262380)
@@ -1,6 +1,6 @@
/*-
+ * Copyright (c) 2013-2014 Mark R V Murray
* Copyright (c) 2013 Arthur Mesh <arthurmesh at gmail.com>
- * Copyright (c) 2013 Mark R V Murray
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,6 @@ struct harvest_event {
u_int he_bits; /* stats about the entropy */
u_int he_destination; /* destination pool of this entropy */
enum random_entropy_source he_source; /* origin of the entropy */
- STAILQ_ENTRY(harvest_event) he_next; /* next item on the list */
};
void random_harvestq_init(void (*)(struct harvest_event *), int);
More information about the svn-src-projects
mailing list