Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Release rnd_global.lock while calling an rndsource's cal...



details:   https://anonhg.NetBSD.org/src/rev/0abcdd9fcc09
branches:  trunk
changeset: 807749:0abcdd9fcc09
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Tue Apr 21 03:53:07 2015 +0000

description:
Release rnd_global.lock while calling an rndsource's callback.

Obviates the need for obnoxious double-lock dances in hardware RNG
drivers.

diffstat:

 sys/kern/kern_rndq.c |  35 ++++++++++++++++++++++++++++++-----
 sys/sys/rndsource.h  |   3 ++-
 2 files changed, 32 insertions(+), 6 deletions(-)

diffs (107 lines):

diff -r 41c181039a84 -r 0abcdd9fcc09 sys/kern/kern_rndq.c
--- a/sys/kern/kern_rndq.c      Tue Apr 21 03:46:46 2015 +0000
+++ b/sys/kern/kern_rndq.c      Tue Apr 21 03:53:07 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_rndq.c,v 1.67 2015/04/21 03:46:46 riastradh Exp $ */
+/*     $NetBSD: kern_rndq.c,v 1.68 2015/04/21 03:53:07 riastradh Exp $ */
 
 /*-
  * Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.67 2015/04/21 03:46:46 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.68 2015/04/21 03:53:07 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -126,6 +126,7 @@
        kmutex_t                lock;
        rndpool_t               pool;
        LIST_HEAD(, krndsource) sources;
+       kcondvar_t              cv;
 } rnd_global __cacheline_aligned;
 
 /*
@@ -260,15 +261,32 @@
 void
 rnd_getmore(size_t byteswanted)
 {
-       krndsource_t *rs;
+       krndsource_t *rs, *next;
 
        mutex_spin_enter(&rnd_global.lock);
-       LIST_FOREACH(rs, &rnd_global.sources, list) {
+       LIST_FOREACH_SAFE(rs, &rnd_global.sources, list, next) {
+               /* Skip if there's no callback.  */
                if (!ISSET(rs->flags, RND_FLAG_HASCB))
                        continue;
                KASSERT(rs->get != NULL);
-               KASSERT(rs->getarg != NULL);
+
+               /* Skip if there are too many users right now.  */
+               if (rs->refcnt == UINT_MAX)
+                       continue;
+
+               /*
+                * Hold a reference while we release rnd_global.lock to
+                * call the callback.  The callback may in turn call
+                * rnd_add_data, which acquires rnd_global.lock.
+                */
+               rs->refcnt++;
+               mutex_spin_exit(&rnd_global.lock);
                rs->get(byteswanted, rs->getarg);
+               mutex_spin_enter(&rnd_global.lock);
+               if (--rs->refcnt == 0)
+                       cv_broadcast(&rnd_global.cv);
+
+               /* Dribble some goo to the console.  */
                rnd_printf_verbose("rnd: entropy estimate %zu bits\n",
                    rndpool_get_entropy_count(&rnd_global.pool));
                rnd_printf_verbose("rnd: asking source %s for %zu bytes\n",
@@ -497,6 +515,7 @@
        mutex_init(&rnd_global.lock, MUTEX_DEFAULT, IPL_VM);
        rndpool_init(&rnd_global.pool);
        LIST_INIT(&rnd_global.sources);
+       cv_init(&rnd_global.cv, "rndsrc");
 
        rnd_mempc = pool_cache_init(sizeof(rnd_sample_t), 0, 0, 0,
                                    "rndsample", NULL, IPL_VM,
@@ -652,6 +671,7 @@
 
        rs->type = type;
        rs->flags = flags;
+       rs->refcnt = 1;
 
        rs->state = rnd_sample_allocate(rs);
 
@@ -691,6 +711,11 @@
 
        mutex_spin_enter(&rnd_global.lock);
        LIST_REMOVE(source, list);
+       if (0 < --source->refcnt) {
+               do {
+                       cv_wait(&rnd_global.cv, &rnd_global.lock);
+               } while (0 < source->refcnt);
+       }
        mutex_spin_exit(&rnd_global.lock);
 
        /*
diff -r 41c181039a84 -r 0abcdd9fcc09 sys/sys/rndsource.h
--- a/sys/sys/rndsource.h       Tue Apr 21 03:46:46 2015 +0000
+++ b/sys/sys/rndsource.h       Tue Apr 21 03:53:07 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rndsource.h,v 1.2 2015/04/13 16:02:48 riastradh Exp $  */
+/*     $NetBSD: rndsource.h,v 1.3 2015/04/21 03:53:07 riastradh Exp $  */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -63,6 +63,7 @@
        void            *getarg;        /* argument to get-function */
        void            (*enable)(struct krndsource *, bool); /* turn on/off */
        rngtest_t       *test;          /* test data for RNG type sources */
+       unsigned        refcnt;
 } krndsource_t;
 
 static inline void



Home | Main Index | Thread Index | Old Index