Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
7.2 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. etimer.cpp
  5. Abstract:
  6. SIS Groveler event timer
  7. Authors:
  8. John Douceur, 1998
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "all.hxx"
  14. #define NEW_HeapSegment(segment_size) \
  15. ((HeapSegment *)(new BYTE[sizeof(HeapSegment) + \
  16. ((segment_size) - 1) * sizeof(Event)]))
  17. #define DELETE_HeapSegment(heap_segment) delete[] ((BYTE *)(heap_segment))
  18. EventTimer::EventTimer()
  19. {
  20. ASSERT(this != 0);
  21. first_segment = NEW_HeapSegment(1);
  22. first_segment->previous = 0;
  23. first_segment->next = 0;
  24. last_segment = first_segment;
  25. population = 0;
  26. segment_size = 1;
  27. heap_ok = false;
  28. }
  29. EventTimer::~EventTimer()
  30. {
  31. ASSERT(this != 0);
  32. ASSERT(first_segment != 0);
  33. ASSERT(last_segment != 0);
  34. ASSERT(population >= 0);
  35. ASSERT(segment_size > 0);
  36. ASSERT((segment_size & (segment_size - 1)) == 0); // power of 2
  37. ASSERT(population >= segment_size - 1);
  38. ASSERT(!heap_ok || population >= segment_size);
  39. ASSERT(population < 2 * segment_size);
  40. ASSERT(first_segment != last_segment || segment_size == 1);
  41. ASSERT(first_segment == last_segment || segment_size > 1);
  42. while (first_segment != 0)
  43. {
  44. HeapSegment *next_segment = first_segment->next;
  45. ASSERT(first_segment != 0);
  46. DELETE_HeapSegment(first_segment);
  47. first_segment = next_segment;
  48. }
  49. }
  50. void
  51. EventTimer::run()
  52. {
  53. ASSERT(this != 0);
  54. running = true;
  55. while (running && population > 0)
  56. {
  57. ASSERT(first_segment != 0);
  58. ASSERT(last_segment != 0);
  59. ASSERT(population >= 0);
  60. ASSERT(segment_size > 0);
  61. ASSERT((segment_size & (segment_size - 1)) == 0); // power of 2
  62. ASSERT(population >= segment_size - 1);
  63. ASSERT(!heap_ok || population >= segment_size);
  64. ASSERT(population < 2 * segment_size);
  65. ASSERT(first_segment != last_segment || segment_size == 1);
  66. ASSERT(first_segment == last_segment || segment_size > 1);
  67. if (!heap_ok)
  68. {
  69. int final_position = (population + 1) % segment_size;
  70. unsigned int final_time =
  71. last_segment->events[final_position].event_time;
  72. HeapSegment *segment = first_segment;
  73. HeapSegment *next_segment = segment->next;
  74. int position = 0;
  75. int next_position = 0;
  76. while (segment != last_segment
  77. && (next_segment != last_segment
  78. || next_position < final_position))
  79. {
  80. if ((next_segment != last_segment ||
  81. next_position + 1 < final_position) &&
  82. signed(next_segment->events[next_position].event_time -
  83. next_segment->events[next_position + 1].event_time) > 0)
  84. {
  85. next_position++;
  86. }
  87. if (signed(final_time -
  88. next_segment->events[next_position].event_time) <= 0)
  89. {
  90. break;
  91. }
  92. segment->events[position] = next_segment->events[next_position];
  93. segment = next_segment;
  94. next_segment = segment->next;
  95. position = next_position;
  96. next_position = 2 * position;
  97. }
  98. segment->events[position] = last_segment->events[final_position];
  99. if (population < segment_size)
  100. {
  101. segment_size /= 2;
  102. last_segment = last_segment->previous;
  103. }
  104. heap_ok = true;
  105. }
  106. ASSERT(first_segment != 0);
  107. ASSERT(last_segment != 0);
  108. ASSERT(population >= 0);
  109. ASSERT(segment_size > 0);
  110. ASSERT((segment_size & (segment_size - 1)) == 0); // power of 2
  111. ASSERT(population >= segment_size - 1);
  112. ASSERT(!heap_ok || population >= segment_size);
  113. ASSERT(population < 2 * segment_size);
  114. ASSERT(first_segment != last_segment || segment_size == 1);
  115. ASSERT(first_segment == last_segment || segment_size > 1);
  116. unsigned int current_time = GET_TICK_COUNT();
  117. int sleep_time = __max(
  118. signed(first_segment->events[0].event_time - current_time), 0);
  119. do
  120. {
  121. bool event_triggered = sync_event.wait(sleep_time);
  122. if (event_triggered)
  123. {
  124. SERVICE_FOLLOW_COMMAND();
  125. if (!running)
  126. {
  127. return;
  128. }
  129. }
  130. current_time = GET_TICK_COUNT();
  131. sleep_time = __max(
  132. signed(first_segment->events[0].event_time - current_time), 0);
  133. } while (sleep_time > 0);
  134. heap_ok = false;
  135. population--;
  136. (*first_segment->events[0].callback)(first_segment->events[0].context);
  137. bool ok = shared_data->send_values();
  138. if (!ok)
  139. {
  140. PRINT_DEBUG_MSG((_T("GROVELER: SharedData::send_values() failed\n")));
  141. }
  142. }
  143. }
  144. void
  145. EventTimer::halt()
  146. {
  147. ASSERT(this != 0);
  148. ASSERT(first_segment != 0);
  149. ASSERT(last_segment != 0);
  150. ASSERT(population >= 0);
  151. ASSERT(segment_size > 0);
  152. ASSERT((segment_size & (segment_size - 1)) == 0); // power of 2
  153. ASSERT(population >= segment_size - 1);
  154. ASSERT(!heap_ok || population >= segment_size);
  155. ASSERT(population < 2 * segment_size);
  156. ASSERT(first_segment != last_segment || segment_size == 1);
  157. ASSERT(first_segment == last_segment || segment_size > 1);
  158. running = false;
  159. }
  160. void
  161. EventTimer::schedule(
  162. unsigned int event_time,
  163. void *context,
  164. EventCallback callback)
  165. {
  166. ASSERT(this != 0);
  167. ASSERT(first_segment != 0);
  168. ASSERT(last_segment != 0);
  169. ASSERT(population >= 0);
  170. ASSERT(segment_size > 0);
  171. ASSERT((segment_size & (segment_size - 1)) == 0); // power of 2
  172. ASSERT(population >= segment_size - 1);
  173. ASSERT(!heap_ok || population >= segment_size);
  174. ASSERT(population < 2 * segment_size);
  175. ASSERT(first_segment != last_segment || segment_size == 1);
  176. ASSERT(first_segment == last_segment || segment_size > 1);
  177. population++;
  178. HeapSegment *segment;
  179. int position;
  180. if (heap_ok)
  181. {
  182. if (population >= 2 * segment_size)
  183. {
  184. segment_size *= 2;
  185. if (last_segment->next == 0)
  186. {
  187. last_segment->next = NEW_HeapSegment(segment_size);
  188. last_segment->next->previous = last_segment;
  189. last_segment->next->next = 0;
  190. }
  191. last_segment = last_segment->next;
  192. }
  193. segment = last_segment;
  194. HeapSegment *previous_segment = segment->previous;
  195. position = population % segment_size;
  196. int next_position = position >> 1;
  197. while (previous_segment != 0 && signed(event_time
  198. - previous_segment->events[next_position].event_time) < 0)
  199. {
  200. segment->events[position] = previous_segment->events[next_position];
  201. segment = previous_segment;
  202. previous_segment = segment->previous;
  203. position = next_position;
  204. next_position >>= 1;
  205. }
  206. }
  207. else
  208. {
  209. int final_position = population % segment_size + 1;
  210. segment = first_segment;
  211. HeapSegment *next_segment = segment->next;
  212. position = 0;
  213. int next_position = 0;
  214. while (segment != last_segment
  215. && (next_segment != last_segment
  216. || next_position < final_position))
  217. {
  218. if ((next_segment != last_segment ||
  219. next_position + 1 < final_position) &&
  220. signed(next_segment->events[next_position].event_time -
  221. next_segment->events[next_position + 1].event_time) > 0)
  222. {
  223. next_position++;
  224. }
  225. if (signed(event_time -
  226. next_segment->events[next_position].event_time) <= 0)
  227. {
  228. break;
  229. }
  230. segment->events[position] = next_segment->events[next_position];
  231. segment = next_segment;
  232. next_segment = segment->next;
  233. position = next_position;
  234. next_position = 2 * position;
  235. }
  236. }
  237. segment->events[position].event_time = event_time;
  238. segment->events[position].context = context;
  239. segment->events[position].callback = callback;
  240. heap_ok = true;
  241. ASSERT(first_segment != 0);
  242. ASSERT(last_segment != 0);
  243. ASSERT(population >= 0);
  244. ASSERT(segment_size > 0);
  245. ASSERT((segment_size & (segment_size - 1)) == 0); // power of 2
  246. ASSERT(population >= segment_size);
  247. ASSERT(population < 2 * segment_size);
  248. ASSERT(first_segment != last_segment || segment_size == 1);
  249. ASSERT(first_segment == last_segment || segment_size > 1);
  250. return;
  251. }