The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bitsy/random.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "../port/error.h"
    7 
    8 
    9 struct Rb
   10 {
   11         QLock;
   12         Rendez  producer;
   13         Rendez  consumer;
   14         ulong   randomcount;
   15         uchar   buf[128];
   16         uchar   *ep;
   17         uchar   *rp;
   18         uchar   *wp;
   19         uchar   next;
   20         uchar   wakeme;
   21         ushort  bits;
   22         ulong   randn;
   23 } rb;
   24 
   25 static int
   26 rbnotfull(void*)
   27 {
   28         int i;
   29 
   30         i = rb.rp - rb.wp;
   31         return i != 1 && i != (1 - sizeof(rb.buf));
   32 }
   33 
   34 static int
   35 rbnotempty(void*)
   36 {
   37         return rb.wp != rb.rp;
   38 }
   39 
   40 static void
   41 genrandom(void*)
   42 {
   43         up->basepri = PriNormal;
   44         up->priority = up->basepri;
   45 
   46         for(;;){
   47                 for(;;)
   48                         if(++rb.randomcount > 100000)
   49                                 break;
   50                 if(anyhigher())
   51                         sched();
   52                 if(!rbnotfull(0))
   53                         sleep(&rb.producer, rbnotfull, 0);
   54         }
   55 }
   56 
   57 /*
   58  *  produce random bits in a circular buffer
   59  */
   60 static void
   61 randomclock(void)
   62 {
   63         if(rb.randomcount == 0 || !rbnotfull(0))
   64                 return;
   65 
   66         rb.bits = (rb.bits<<2) ^ rb.randomcount;
   67         rb.randomcount = 0;
   68 
   69         rb.next++;
   70         if(rb.next != 8/2)
   71                 return;
   72         rb.next = 0;
   73 
   74         *rb.wp ^= rb.bits;
   75         if(rb.wp+1 == rb.ep)
   76                 rb.wp = rb.buf;
   77         else
   78                 rb.wp = rb.wp+1;
   79 
   80         if(rb.wakeme)
   81                 wakeup(&rb.consumer);
   82 }
   83 
   84 void
   85 randominit(void)
   86 {
   87         addclock0link(randomclock, 1000/HZ);
   88         rb.ep = rb.buf + sizeof(rb.buf);
   89         rb.rp = rb.wp = rb.buf;
   90         kproc("genrandom", genrandom, 0);
   91 }
   92 
   93 /*
   94  *  consume random bytes from a circular buffer
   95  */
   96 ulong
   97 randomread(void *xp, ulong n)
   98 {
   99         uchar *e, *p;
  100         ulong x;
  101 
  102         p = xp;
  103 
  104         if(waserror()){
  105                 qunlock(&rb);
  106                 nexterror();
  107         }
  108 
  109         qlock(&rb);
  110         for(e = p + n; p < e; ){
  111                 if(rb.wp == rb.rp){
  112                         rb.wakeme = 1;
  113                         wakeup(&rb.producer);
  114                         sleep(&rb.consumer, rbnotempty, 0);
  115                         rb.wakeme = 0;
  116                         continue;
  117                 }
  118 
  119                 /*
  120                  *  beating clocks will be precictable if
  121                  *  they are synchronized.  Use a cheap pseudo
  122                  *  random number generator to obscure any cycles.
  123                  */
  124                 x = rb.randn*1103515245 ^ *rb.rp;
  125                 *p++ = rb.randn = x;
  126 
  127                 if(rb.rp+1 == rb.ep)
  128                         rb.rp = rb.buf;
  129                 else
  130                         rb.rp = rb.rp+1;
  131         }
  132         qunlock(&rb);
  133         poperror();
  134 
  135         wakeup(&rb.producer);
  136 
  137         return n;
  138 }

Cache object: b6cd3a6aeb078aa3c91811567ab41ce0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.