time.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <thread.h>
  12. #include <keyboard.h>
  13. #include <fcall.h>
  14. #include "dat.h"
  15. #include "fns.h"
  16. static Channel* ctimer; /* chan(Timer*)[100] */
  17. static Timer *timer;
  18. static
  19. uint
  20. msec(void)
  21. {
  22. print_func_entry();
  23. print_func_exit();
  24. return nsec()/1000000;
  25. }
  26. void
  27. timerstop(Timer *t)
  28. {
  29. print_func_entry();
  30. t->next = timer;
  31. timer = t;
  32. print_func_exit();
  33. }
  34. void
  35. timercancel(Timer *t)
  36. {
  37. print_func_entry();
  38. t->cancel = TRUE;
  39. print_func_exit();
  40. }
  41. static
  42. void
  43. timerproc(void* vacio)
  44. {
  45. print_func_entry();
  46. int i, nt, na, dt, del;
  47. Timer **t, *x;
  48. uint old, new;
  49. rfork(RFFDG);
  50. threadsetname("TIMERPROC");
  51. t = nil;
  52. na = 0;
  53. nt = 0;
  54. old = msec();
  55. for(;;){
  56. sleep(1); /* will sleep minimum incr */
  57. new = msec();
  58. dt = new-old;
  59. old = new;
  60. if(dt < 0) /* timer wrapped; go around, losing a tick */
  61. continue;
  62. for(i=0; i<nt; i++){
  63. x = t[i];
  64. x->dt -= dt;
  65. del = 0;
  66. if(x->cancel){
  67. timerstop(x);
  68. del = 1;
  69. }else if(x->dt <= 0){
  70. /*
  71. * avoid possible deadlock if client is
  72. * now sending on ctimer
  73. */
  74. if(nbsendul(x->c, 0) > 0)
  75. del = 1;
  76. }
  77. if(del){
  78. memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
  79. --nt;
  80. --i;
  81. }
  82. }
  83. if(nt == 0){
  84. x = recvp(ctimer);
  85. gotit:
  86. if(nt == na){
  87. na += 10;
  88. t = realloc(t, na*sizeof(Timer*));
  89. if(t == nil)
  90. abort();
  91. }
  92. t[nt++] = x;
  93. old = msec();
  94. }
  95. if(nbrecv(ctimer, &x) > 0)
  96. goto gotit;
  97. }
  98. print_func_exit();
  99. }
  100. void
  101. timerinit(void)
  102. {
  103. print_func_entry();
  104. ctimer = chancreate(sizeof(Timer*), 100);
  105. proccreate(timerproc, nil, STACK);
  106. print_func_exit();
  107. }
  108. /*
  109. * timeralloc() and timerfree() don't lock, so can only be
  110. * called from the main proc.
  111. */
  112. Timer*
  113. timerstart(int dt)
  114. {
  115. print_func_entry();
  116. Timer *t;
  117. t = timer;
  118. if(t)
  119. timer = timer->next;
  120. else{
  121. t = emalloc(sizeof(Timer));
  122. t->c = chancreate(sizeof(int), 0);
  123. }
  124. t->next = nil;
  125. t->dt = dt;
  126. t->cancel = FALSE;
  127. sendp(ctimer, t);
  128. print_func_exit();
  129. return t;
  130. }