From owner-svn-src-projects@FreeBSD.ORG Sun Feb 23 18:49:53 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 81E7CBAF; Sun, 23 Feb 2014 18:49:53 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 623001955; Sun, 23 Feb 2014 18:49:53 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s1NInr5t073435; Sun, 23 Feb 2014 18:49:53 GMT (envelope-from markm@svn.freebsd.org) Received: (from markm@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s1NInrvj073433; Sun, 23 Feb 2014 18:49:53 GMT (envelope-from markm@svn.freebsd.org) Message-Id: <201402231849.s1NInrvj073433@svn.freebsd.org> From: Mark Murray Date: Sun, 23 Feb 2014 18:49:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r262380 - projects/random_number_generator/sys/dev/random X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Feb 2014 18:49:53 -0000 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 - * 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);