time.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <cursor.h>
  6. #include <mouse.h>
  7. #include <keyboard.h>
  8. #include <frame.h>
  9. #include <fcall.h>
  10. #include "dat.h"
  11. #include "fns.h"
  12. static Channel* ctimer; /* chan(Timer*)[100] */
  13. static Timer *timer;
  14. static
  15. uint
  16. msec(void)
  17. {
  18. return nsec()/1000000;
  19. }
  20. void
  21. timerstop(Timer *t)
  22. {
  23. t->next = timer;
  24. timer = t;
  25. }
  26. void
  27. timercancel(Timer *t)
  28. {
  29. t->cancel = TRUE;
  30. }
  31. static
  32. void
  33. timerproc(void*)
  34. {
  35. int i, nt, na, dt, del;
  36. Timer **t, *x;
  37. uint old, new;
  38. rfork(RFFDG);
  39. threadsetname("TIMERPROC");
  40. t = nil;
  41. na = 0;
  42. nt = 0;
  43. old = msec();
  44. for(;;){
  45. sleep(1); /* will sleep minimum incr */
  46. new = msec();
  47. dt = new-old;
  48. old = new;
  49. if(dt < 0) /* timer wrapped; go around, losing a tick */
  50. continue;
  51. for(i=0; i<nt; i++){
  52. x = t[i];
  53. x->dt -= dt;
  54. del = 0;
  55. if(x->cancel){
  56. timerstop(x);
  57. del = 1;
  58. }else if(x->dt <= 0){
  59. /*
  60. * avoid possible deadlock if client is
  61. * now sending on ctimer
  62. */
  63. if(nbsendul(x->c, 0) > 0)
  64. del = 1;
  65. }
  66. if(del){
  67. memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]);
  68. --nt;
  69. --i;
  70. }
  71. }
  72. if(nt == 0){
  73. x = recvp(ctimer);
  74. gotit:
  75. if(nt == na){
  76. na += 10;
  77. t = realloc(t, na*sizeof(Timer*));
  78. if(t == nil)
  79. abort();
  80. }
  81. t[nt++] = x;
  82. old = msec();
  83. }
  84. if(nbrecv(ctimer, &x) > 0)
  85. goto gotit;
  86. }
  87. }
  88. void
  89. timerinit(void)
  90. {
  91. ctimer = chancreate(sizeof(Timer*), 100);
  92. proccreate(timerproc, nil, STACK);
  93. }
  94. /*
  95. * timeralloc() and timerfree() don't lock, so can only be
  96. * called from the main proc.
  97. */
  98. Timer*
  99. timerstart(int dt)
  100. {
  101. Timer *t;
  102. t = timer;
  103. if(t)
  104. timer = timer->next;
  105. else{
  106. t = emalloc(sizeof(Timer));
  107. t->c = chancreate(sizeof(int), 0);
  108. }
  109. t->next = nil;
  110. t->dt = dt;
  111. t->cancel = FALSE;
  112. sendp(ctimer, t);
  113. return t;
  114. }