random.c 2.0 KB

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