alarm.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. }
  38. else
  39. snooze = 60 * 1000;
  40. //print("snoozing for %ld\n", snooze);
  41. qunlock(&alarmlist);
  42. sleep(snooze);
  43. }
  44. }
  45. NbnsAlarm *
  46. nbnsalarmnew(void)
  47. {
  48. NbnsAlarm *a;
  49. a = mallocz(sizeof(*a), 1);
  50. if (a == nil)
  51. return nil;
  52. a->c = chancreate(sizeof(ulong), 1);
  53. if (a->c == nil) {
  54. free(a);
  55. return nil;
  56. }
  57. return a;
  58. }
  59. void
  60. nbnsalarmcancel(NbnsAlarm *a)
  61. {
  62. NbnsAlarm **ap;
  63. int rv;
  64. qlock(&alarmlist);
  65. for (ap = &alarmlist.head; *ap && *ap != a; ap = &(*ap)->next)
  66. ;
  67. if (*ap) {
  68. *ap = a->next;
  69. if (ap == &alarmlist.head)
  70. threadint(alarmlist.thread);
  71. }
  72. qunlock(&alarmlist);
  73. do {
  74. ulong v;
  75. rv = nbrecv(a->c, &v);
  76. } while (rv != 0);
  77. }
  78. void
  79. nbnsalarmend(void)
  80. {
  81. qlock(&alarmlist);
  82. if (alarmlist.thread >= 0) {
  83. alarmlist.die = 1;
  84. threadint(alarmlist.thread);
  85. }
  86. qunlock(&alarmlist);
  87. }
  88. void
  89. nbnsalarmset(NbnsAlarm *a, ulong millisec)
  90. {
  91. NbnsAlarm **ap;
  92. nbnsalarmcancel(a);
  93. a->expirems = nsec() / 1000000 + millisec;
  94. qlock(&alarmlist);
  95. for (ap = &alarmlist.head; *ap; ap = &(*ap)->next)
  96. if (a->expirems < (*ap)->expirems)
  97. break;
  98. a->next = (*ap);
  99. *ap = a;
  100. if (alarmlist.thread < 0)
  101. alarmlist.thread = proccreate(alarmist, nil, 16384);
  102. else
  103. threadint(alarmlist.thread);
  104. qunlock(&alarmlist);
  105. }
  106. void
  107. nbnsalarmfree(NbnsAlarm **ap)
  108. {
  109. NbnsAlarm *a;
  110. a = *ap;
  111. if (a) {
  112. nbnsalarmcancel(a);
  113. chanfree(a->c);
  114. free(a);
  115. *ap = nil;
  116. }
  117. }