time.c 2.2 KB

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