alarm.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include <thread.h>
  5. #include "netbios.h"
  6. static struct {
  7. int thread;
  8. int die;
  9. QLock;
  10. NbnsAlarm *head;
  11. } alarmlist = { -1 };
  12. #define MaxLong ((1 << (sizeof(long) * 8 - 1)) - 1)
  13. void
  14. alarmist(void *)
  15. {
  16. for (;;) {
  17. vlong now;
  18. long snooze;
  19. //print("running\n");
  20. qlock(&alarmlist);
  21. if (alarmlist.die) {
  22. qunlock(&alarmlist);
  23. break;
  24. }
  25. now = nsec() / 1000000;
  26. while (alarmlist.head && alarmlist.head->expirems <= now) {
  27. //print("expiring because %lld > %lld\n", alarmlist.head->expirems, now);
  28. sendul(alarmlist.head->c, 1);
  29. alarmlist.head = alarmlist.head->next;
  30. }
  31. if (alarmlist.head) {
  32. vlong vsnooze = alarmlist.head->expirems - now;
  33. if (vsnooze > MaxLong)
  34. snooze = MaxLong;
  35. else
  36. snooze = vsnooze;
  37. qunlock(&alarmlist);
  38. }
  39. else
  40. snooze = 60 * 1000;
  41. //print("snoozing for %ld\n", snooze);
  42. qunlock(&alarmlist);
  43. sleep(snooze);
  44. }
  45. }
  46. NbnsAlarm *
  47. nbnsalarmnew(void)
  48. {
  49. NbnsAlarm *a;
  50. a = mallocz(sizeof(*a), 1);
  51. if (a == nil)
  52. return nil;
  53. a->c = chancreate(sizeof(ulong), 1);
  54. if (a->c == nil) {
  55. free(a);
  56. return nil;
  57. }
  58. return a;
  59. }
  60. void
  61. nbnsalarmcancel(NbnsAlarm *a)
  62. {
  63. NbnsAlarm **ap;
  64. int rv;
  65. qlock(&alarmlist);
  66. for (ap = &alarmlist.head; *ap && *ap != a; ap = &(*ap)->next)
  67. ;
  68. if (*ap) {
  69. *ap = a->next;
  70. if (ap == &alarmlist.head)
  71. threadint(alarmlist.thread);
  72. }
  73. qunlock(&alarmlist);
  74. do {
  75. ulong v;
  76. rv = nbrecv(a->c, &v);
  77. } while (rv != 0);
  78. }
  79. void
  80. nbnsalarmend(void)
  81. {
  82. qlock(&alarmlist);
  83. if (alarmlist.thread >= 0) {
  84. alarmlist.die = 1;
  85. threadint(alarmlist.thread);
  86. }
  87. qunlock(&alarmlist);
  88. }
  89. void
  90. nbnsalarmset(NbnsAlarm *a, ulong millisec)
  91. {
  92. NbnsAlarm **ap;
  93. nbnsalarmcancel(a);
  94. a->expirems = nsec() / 1000000 + millisec;
  95. qlock(&alarmlist);
  96. for (ap = &alarmlist.head; *ap; ap = &(*ap)->next)
  97. if (a->expirems < (*ap)->expirems)
  98. break;
  99. a->next = (*ap);
  100. *ap = a;
  101. if (alarmlist.thread < 0)
  102. alarmlist.thread = proccreate(alarmist, nil, 16384);
  103. else
  104. threadint(alarmlist.thread);
  105. qunlock(&alarmlist);
  106. }
  107. void
  108. nbnsalarmfree(NbnsAlarm **ap)
  109. {
  110. NbnsAlarm *a;
  111. a = *ap;
  112. if (a) {
  113. nbnsalarmcancel(a);
  114. chanfree(a->c);
  115. free(a);
  116. *ap = nil;
  117. }
  118. }