time.c 2.1 KB

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