Source-Changes-HG archive

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

[src/trunk]: src/sys/dev - make rnd.c mpsafe



details:   https://anonhg.NetBSD.org/src/rev/afd7b13c1b7d
branches:  trunk
changeset: 770312:afd7b13c1b7d
user:      yamt <yamt%NetBSD.org@localhost>
date:      Tue Oct 11 23:55:30 2011 +0000

description:
- make rnd.c mpsafe
- malloc -> kmem_alloc

diffstat:

 sys/dev/rnd.c |  128 ++++++++++++++++++++++++++-------------------------------
 1 files changed, 59 insertions(+), 69 deletions(-)

diffs (271 lines):

diff -r ca4a92ab9fb1 -r afd7b13c1b7d sys/dev/rnd.c
--- a/sys/dev/rnd.c     Tue Oct 11 23:53:31 2011 +0000
+++ b/sys/dev/rnd.c     Tue Oct 11 23:55:30 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rnd.c,v 1.81 2011/06/30 20:09:40 wiz Exp $     */
+/*     $NetBSD: rnd.c,v 1.82 2011/10/11 23:55:30 yamt Exp $    */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -31,14 +31,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rnd.c,v 1.81 2011/06/30 20:09:40 wiz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rnd.c,v 1.82 2011/10/11 23:55:30 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/fcntl.h>
 #include <sys/select.h>
 #include <sys/poll.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
@@ -75,7 +75,7 @@
 #endif
 
 /*
- * The size of a temporary buffer, malloc()ed when needed, and used for
+ * The size of a temporary buffer, kmem_alloc()ed when needed, and used for
  * reading and writing data.
  */
 #define        RND_TEMP_BUFFER_SIZE    128
@@ -110,12 +110,6 @@
 struct selinfo rnd_selq;
 
 /*
- * Set when there are readers blocking on data from us
- */
-#define        RND_READWAITING 0x00000001
-volatile u_int32_t rnd_status;
-
-/*
  * Memory pool for sample buffers
  */
 static struct pool rnd_mempool;
@@ -130,6 +124,7 @@
  */
 rndpool_t rnd_pool;
 kmutex_t  rndpool_mtx;
+kcondvar_t rndpool_cv;
 
 /*
  * This source is used to easily "remove" queue entries when the source
@@ -156,13 +151,14 @@
 
 const struct cdevsw rnd_cdevsw = {
        rndopen, nullclose, rndread, rndwrite, rndioctl,
-       nostop, notty, rndpoll, nommap, rndkqfilter, D_OTHER,
+       nostop, notty, rndpoll, nommap, rndkqfilter, D_OTHER|D_MPSAFE,
 };
 
 static inline void     rnd_wakeup_readers(void);
 static inline u_int32_t rnd_estimate_entropy(rndsource_t *, u_int32_t);
 static inline u_int32_t rnd_counter(void);
 static        void     rnd_timeout(void *);
+static u_int32_t       rnd_extract_data_locked(void *, u_int32_t, u_int32_t);
 
 static int             rnd_ready = 0;
 static int             rnd_have_entropy = 0;
@@ -203,12 +199,7 @@
         */
        mutex_enter(&rndpool_mtx);
        if (rndpool_get_entropy_count(&rnd_pool) > RND_ENTROPY_THRESHOLD * 8) {
-               if (rnd_status & RND_READWAITING) {
-                       DPRINTF(RND_DEBUG_SNOOZE,
-                           ("waking up pending readers.\n"));
-                       rnd_status &= ~RND_READWAITING;
-                       wakeup(&rnd_selq);
-               }
+               cv_broadcast(&rndpool_cv);
                selnotify(&rnd_selq, 0, 0);
 
 #ifdef RND_VERBOSE
@@ -328,6 +319,7 @@
 
        rndpool_init(&rnd_pool);
        mutex_init(&rndpool_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
+       cv_init(&rndpool_cv, "rndread");
 
        /* Mix *something*, *anything* into the pool to help it get started.
         * However, it's not safe for rnd_counter() to call microtime() yet,
@@ -389,9 +381,7 @@
        }
 
        ret = 0;
-
-       bf = malloc(RND_TEMP_BUFFER_SIZE, M_TEMP, M_WAITOK);
-
+       bf = kmem_alloc(RND_TEMP_BUFFER_SIZE, KM_SLEEP);
        while (uio->uio_resid > 0) {
                n = min(RND_TEMP_BUFFER_SIZE, uio->uio_resid);
 
@@ -400,42 +390,37 @@
                 * is, do the I/O even if it is partial.  If not,
                 * sleep unless the user has requested non-blocking
                 * I/O.
+                *
+                * If not requesting strong randomness, we can always read.
                 */
-               for (;;) {
-                       /*
-                        * If not requesting strong randomness, we
-                        * can always read.
-                        */
-                       if (mode == RND_EXTRACT_ANY)
-                               break;
+               mutex_enter(&rndpool_mtx);
+               if (mode != RND_EXTRACT_ANY) {
+                       for (;;) {
+                               /*
+                                * How much entropy do we have?
+                                * If it is enough for one hash, we can read.
+                                */
+                               entcnt = rndpool_get_entropy_count(&rnd_pool);
+                               if (entcnt >= RND_ENTROPY_THRESHOLD * 8)
+                                       break;
 
-                       /*
-                        * How much entropy do we have?  If it is enough for
-                        * one hash, we can read.
-                        */
-                       mutex_enter(&rndpool_mtx);
-                       entcnt = rndpool_get_entropy_count(&rnd_pool);
-                       mutex_exit(&rndpool_mtx);
-                       if (entcnt >= RND_ENTROPY_THRESHOLD * 8)
-                               break;
-
-                       /*
-                        * Data is not available.
-                        */
-                       if (ioflag & IO_NDELAY) {
-                               ret = EWOULDBLOCK;
-                               goto out;
+                               /*
+                                * Data is not available.
+                                */
+                               if (ioflag & IO_NDELAY) {
+                                       mutex_exit(&rndpool_mtx);
+                                       ret = EWOULDBLOCK;
+                                       goto out;
+                               }
+                               ret = cv_wait_sig(&rndpool_cv, &rndpool_mtx);
+                               if (ret) {
+                                       mutex_exit(&rndpool_mtx);
+                                       goto out;
+                               }
                        }
-
-                       rnd_status |= RND_READWAITING;
-                       ret = tsleep(&rnd_selq, PRIBIO|PCATCH,
-                           "rndread", 0);
-
-                       if (ret)
-                               goto out;
                }
-
-               nread = rnd_extract_data(bf, n, mode);
+               nread = rnd_extract_data_locked(bf, n, mode);
+               mutex_exit(&rndpool_mtx);
 
                /*
                 * Copy (possibly partial) data to the user.
@@ -448,7 +433,7 @@
        }
 
 out:
-       free(bf, M_TEMP);
+       kmem_free(bf, RND_TEMP_BUFFER_SIZE);
        return (ret);
 }
 
@@ -463,11 +448,8 @@
 
        if (uio->uio_resid == 0)
                return (0);
-
        ret = 0;
-
-       bf = malloc(RND_TEMP_BUFFER_SIZE, M_TEMP, M_WAITOK);
-
+       bf = kmem_alloc(RND_TEMP_BUFFER_SIZE, KM_SLEEP);
        while (uio->uio_resid > 0) {
                n = min(RND_TEMP_BUFFER_SIZE, uio->uio_resid);
 
@@ -484,8 +466,7 @@
 
                DPRINTF(RND_DEBUG_WRITE, ("Random: Copied in %d bytes\n", n));
        }
-
-       free(bf, M_TEMP);
+       kmem_free(bf, RND_TEMP_BUFFER_SIZE);
        return (ret);
 }
 
@@ -711,12 +692,11 @@
         */
        mutex_enter(&rndpool_mtx);
        entcnt = rndpool_get_entropy_count(&rnd_pool);
-       mutex_exit(&rndpool_mtx);
-
        if (entcnt >= RND_ENTROPY_THRESHOLD * 8)
                revents |= events & (POLLIN | POLLRDNORM);
        else
                selrecord(l, &rnd_selq);
+       mutex_exit(&rndpool_mtx);
 
        return (revents);
 }
@@ -734,7 +714,9 @@
 {
        uint32_t entcnt;
 
+       mutex_enter(&rndpool_mtx);
        entcnt = rndpool_get_entropy_count(&rnd_pool);
+       mutex_exit(&rndpool_mtx);
        if (entcnt >= RND_ENTROPY_THRESHOLD * 8) {
                kn->kn_data = RND_TEMP_BUFFER_SIZE;
                return (1);
@@ -1071,14 +1053,14 @@
        rnd_wakeup_readers();
 }
 
-u_int32_t
-rnd_extract_data(void *p, u_int32_t len, u_int32_t flags)
+static u_int32_t
+rnd_extract_data_locked(void *p, u_int32_t len, u_int32_t flags)
 {
-       int retval;
-       u_int32_t c;
 
-       mutex_enter(&rndpool_mtx);
+       KASSERT(mutex_owned(&rndpool_mtx));
        if (!rnd_have_entropy) {
+               u_int32_t c;
+
 #ifdef RND_VERBOSE
                printf("rnd: WARNING! initial entropy low (%u).\n",
                       rndpool_get_entropy_count(&rnd_pool));
@@ -1087,8 +1069,16 @@
                c = rnd_counter();
                rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1);
        }
-       retval = rndpool_extract_data(&rnd_pool, p, len, flags);
-       mutex_exit(&rndpool_mtx);
+       return rndpool_extract_data(&rnd_pool, p, len, flags);
+}
 
-       return (retval);
+u_int32_t
+rnd_extract_data(void *p, u_int32_t len, u_int32_t flags)
+{
+       uint32_t retval;
+
+       mutex_enter(&rndpool_mtx);
+       retval = rnd_extract_data_locked(p, len, flags);
+       mutex_exit(&rndpool_mtx);
+       return retval;
 }



Home | Main Index | Thread Index | Old Index