random.c 2.4 KB

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