Leaked source code of windows server 2003
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.

1539 lines
42 KiB

  1. //=============================================================================
  2. // Copyright (c) 1997 Microsoft Corporation
  3. // File Name: igmptimer.c
  4. //
  5. // Abstract: This module implements the igmptimer
  6. //
  7. // Author: K.S.Lokesh (lokeshs@) 11-1-97
  8. //
  9. // Revision History:
  10. //=============================================================================
  11. #include "pchigmp.h"
  12. DWORD ksldel = 0; //deldel
  13. //DebugCheck //ksltodo
  14. //DWORD MyDebug = 0x0;
  15. DWORD MyDebug = 0x0; //DebugScanTimerQueue while running
  16. DWORD DebugIgmpVersion = 0x05;
  17. ULONG g_DebugPrint = 0; //flag to enable DebugPrintTimerQueue while running
  18. DWORD DEBUG_CHECK_LOW_INDEX_ARRAY[100][2]; //deldel
  19. DWORD DebugIgmpIndex; //deldel
  20. #if DEBUG_TIMER_LEVEL & DEBUG_TIMER_TIMERID
  21. DWORD TimerId =0;
  22. #endif
  23. ULONG g_Fire = 0; // global variable
  24. //------------------------------------------------------------------------------
  25. //
  26. // FUNCTION PROTOTYPES USED ONLY IN THIS FILE
  27. //
  28. VOID
  29. SetNextTime(
  30. DWORD dwLowIndex
  31. );
  32. VOID
  33. ResyncTimerBuckets(
  34. LONGLONG llCurTime
  35. );
  36. VOID
  37. InsertTimerInSortedList(
  38. PIGMP_TIMER_ENTRY pteNew,
  39. PLIST_ENTRY pHead
  40. );
  41. //------------------------------------------------------------------------------
  42. //
  43. // #DEFINES USED ONLY IN THIS FILE
  44. //
  45. //
  46. //approx 16 secs in each bucket:
  47. //it is approx not accurate as I divide by 2^10 instead of 1000
  48. //TIMER_BUCKET_GRANULARITY should be 2^TIMER_BUCKET_GRANULARITY_SHIFT
  49. //
  50. #define TIMER_BUCKET_GRANULARITY 16
  51. #define TIMER_BUCKET_GRANULARITY_SHIFT 4
  52. #define SEC_CONV_SHIFT 10
  53. #define TIMER_BUCKET_GRANULARITY_ABS \
  54. ((LONGLONG) ((LONGLONG)1 << (TIMER_BUCKET_GRANULARITY_SHIFT + SEC_CONV_SHIFT) ))
  55. #define MAP_TO_BUCKET(dwBucket, ilTime) \
  56. dwBucket = (DWORD) (((ilTime)-g_TimerStruct.SyncTime) \
  57. >> (TIMER_BUCKET_GRANULARITY_SHIFT+SEC_CONV_SHIFT)); \
  58. dwBucket = dwBucket>NUM_TIMER_BUCKETS-1? NUM_TIMER_BUCKETS-1: dwBucket
  59. // I fire a timer even if it is set to 10 millisec in the future.
  60. #define FORWARD_TIMER_FIRED 10
  61. //------------------------------------------------------------------------------
  62. ULONG
  63. QueryRemainingTime(
  64. PIGMP_TIMER_ENTRY pte,
  65. LONGLONG llCurTime
  66. )
  67. {
  68. if (llCurTime==0)
  69. llCurTime = GetCurrentIgmpTime();
  70. return llCurTime>pte->Timeout ? 0 : (ULONG)(pte->Timeout-llCurTime);
  71. }
  72. VOID
  73. DebugCheckLowTimer(
  74. DWORD Flags
  75. )
  76. {
  77. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  78. DWORD i;
  79. PIGMP_TIMER_ENTRY pte, pteMin;
  80. LONGLONG ilMinTime;
  81. PLIST_ENTRY pHead, ple;
  82. BOOL bMatchedTimeout=FALSE;
  83. Trace0(ENTER1, "In _DebugCheckLowTimer");
  84. if (ptg->NumTimers==0)
  85. return;
  86. if (g_TimerStruct.TableLowIndex>64 ) {
  87. CALL_MSG("1");
  88. return;
  89. }
  90. if (IsListEmpty(&ptg->TimesTable[ptg->TableLowIndex])){
  91. CALL_MSG("2");
  92. return;
  93. }
  94. for (i=0; i<=ptg->TableLowIndex&&i<64; i++) {
  95. pHead = &ptg->TimesTable[i];
  96. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  97. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  98. CHECK_TIMER_SIGNATURE(pte);
  99. if (Flags & 1) {
  100. if (pte->Timeout<ptg->WTTimeout) {
  101. CALL_MSG("3");
  102. return;
  103. }
  104. if (pte->Timeout==ptg->WTTimeout)
  105. bMatchedTimeout = TRUE;
  106. }
  107. if (i<ptg->TableLowIndex) {
  108. CALL_MSG("4");
  109. return;
  110. }
  111. }
  112. }
  113. if ((Flags & 1) && !bMatchedTimeout && ksldel)
  114. {
  115. DebugPrintTimerQueue();
  116. CALL_MSG("5");
  117. }
  118. return;
  119. }
  120. //------------------------------------------------------------------------------
  121. // _InsertTimer
  122. //
  123. // Inserts a timer into the local timer queue. Time should always be relative.
  124. //
  125. // Locks: Assumes lock taken on ptg->CS
  126. // LowIndex might not be correct
  127. //------------------------------------------------------------------------------
  128. DWORD
  129. InsertTimer (
  130. PIGMP_TIMER_ENTRY pte,
  131. LONGLONG llNewTime,
  132. BOOL bResync, //false if called within callback
  133. BOOL bDbg
  134. )
  135. {
  136. LONGLONG llCurTime = GetCurrentIgmpTime();
  137. PIGMP_TIMER_GLOBAL ptg;
  138. DWORD dwBucket, Error = NO_ERROR;
  139. CHECK_TIMER_SIGNATURE(pte);
  140. CHECK_IF_ACQUIRED_TIMER_LOCK();
  141. DebugCheckLowTimer(bResync);//deldel
  142. DEBUG_CHECK_LOW_INDEX(1);//deldel
  143. if (pte->Status & TIMER_STATUS_ACTIVE) {
  144. UpdateLocalTimer(pte, llNewTime, bDbg);
  145. return NO_ERROR;
  146. }
  147. // deldel
  148. if (MyDebug&0x1) DebugScanTimerQueue(1);
  149. Trace0(ENTER1, "_InsertTimer()");
  150. // print the queue before inserting the timer
  151. #if DEBUG_TIMER_INSERTTIMER1
  152. Trace0(TIMER1, "Printing Timer Queue before InsertTimer");
  153. DebugPrintTimerQueue();
  154. #endif
  155. ptg = &g_TimerStruct;
  156. // convert relative time to absolute time
  157. llNewTime += llCurTime;
  158. pte->Timeout = llNewTime;
  159. MAP_TO_BUCKET(dwBucket, pte->Timeout);
  160. // print info about the timer being inserted
  161. #if DEBUG_TIMER_ACTIVITY
  162. {
  163. DWORD TmpdwBucket, dwDiffTime;
  164. CHAR str1[20], str2[20];
  165. MAP_TO_BUCKET(TmpdwBucket, pte->Timeout);
  166. GetTimerDebugInfo(str1, str2, &dwDiffTime, pte, llCurTime);
  167. Trace7(TIMER, "Inserting timer <%d><%d><%d> Timeout:%lu <%s> "
  168. "<%s> Status:%d", TmpdwBucket, pte->Id, pte->Id2, dwDiffTime,
  169. str1, str2, pte->Status);
  170. }
  171. #endif
  172. //
  173. // insert timer in appropriate list
  174. //
  175. if (dwBucket==0) { // bucket 0 contains a sorted list
  176. InsertTimerInSortedList(pte, &ptg->TimesTable[0]);
  177. }
  178. else {
  179. InsertTailList(&ptg->TimesTable[dwBucket], &pte->Link);
  180. }
  181. DEBUG_CHECK_LOW_INDEX(2);//deldel
  182. ptg->NumTimers++;
  183. ptg->TableLowIndex = ptg->TableLowIndex<dwBucket
  184. ? ptg->TableLowIndex : dwBucket;
  185. DEBUG_CHECK_LOW_INDEX(3);//deldel
  186. //resynchronize timer list
  187. if (bResync) {
  188. if ( (ptg->TableLowIndex!=0)
  189. && (ptg->SyncTime + TIMER_BUCKET_GRANULARITY_ABS < llCurTime) ) {
  190. ResyncTimerBuckets(llCurTime);
  191. }
  192. }
  193. DEBUG_CHECK_LOW_INDEX(4);//deldel
  194. //
  195. // if time being inserted is lower than the minimum, then update wait timer
  196. //
  197. if ((IS_TIMER_INFINITE(ptg->WTTimeout)) || (pte->Timeout<=ptg->WTTimeout)) {
  198. ptg->WTTimeout = pte->Timeout;
  199. if (!IS_TIMER_INFINITE(ptg->WTTimeout)) {
  200. BOOL bSuccess ;
  201. bSuccess = ChangeTimerQueueTimer(ptg->WTTimer, ptg->WTTimer1,
  202. llCurTime<ptg->WTTimeout
  203. ?(ULONG) ((ptg->WTTimeout - llCurTime))
  204. : 0,
  205. 1000000 // set a periodic timer
  206. );
  207. if (!bSuccess) {
  208. Error = GetLastError();
  209. Trace1(ERR, "ChangeTimerQueueTimer returned error:%d", Error);
  210. IgmpAssertOnError(FALSE);
  211. }
  212. else {
  213. #if DEBUG_TIMER_ACTIVITY
  214. Trace1(TIMER1, "ChangeTimerQueueTimer set to %lu",
  215. (ULONG) ((ptg->WTTimeout - llCurTime))/1000);
  216. #if DEBUG_TIMER_ID
  217. g_Fire = (ULONG) ((ptg->WTTimeout - llCurTime)/1000);
  218. #endif
  219. #endif
  220. }
  221. }
  222. }
  223. pte->Status = TIMER_STATUS_ACTIVE;
  224. #if DEBUG_TIMER_INSERTTIMER2
  225. if (bDbg||g_DebugPrint) {
  226. Trace0(TIMER1, " ");
  227. Trace0(TIMER1, "Printing Timer Queue after _InsertTimer");
  228. DebugPrintTimerQueue();
  229. }
  230. #endif
  231. //kslksl
  232. if (MyDebug&0x2) DebugScanTimerQueue(2);
  233. DebugCheckLowTimer(bResync);//deldel
  234. DEBUG_CHECK_LOW_INDEX(5);//deldel
  235. Trace0(LEAVE1, "Leaving _InsertTimer()");
  236. return NO_ERROR;
  237. } //end _InsertTimer
  238. //------------------------------------------------------------------------------
  239. // _UpdateLocalTimer
  240. //
  241. // Change the time in a timer structure and (re)insert it in the timer queue.
  242. // Locks: Assumes lock on the global timer
  243. // LowIndex might not be correct
  244. //------------------------------------------------------------------------------
  245. VOID
  246. UpdateLocalTimer (
  247. PIGMP_TIMER_ENTRY pte,
  248. LONGLONG llNewTime,
  249. BOOL bDbgPrint
  250. )
  251. {
  252. Trace0(ENTER1, "_UpdateLocalTimer():");
  253. CHECK_TIMER_SIGNATURE(pte);
  254. CHECK_IF_ACQUIRED_TIMER_LOCK();
  255. DebugCheckLowTimer(1);//deldel
  256. DEBUG_CHECK_LOW_INDEX(6);//deldel
  257. // print info about the timer being updated
  258. #if DEBUG_TIMER_ACTIVITY
  259. {
  260. DWORD dwBucket, dwDiffTime;
  261. CHAR str1[20], str2[20];
  262. LONGLONG llCurTime = GetCurrentIgmpTime();
  263. MAP_TO_BUCKET(dwBucket, pte->Timeout);
  264. GetTimerDebugInfo(str1, str2, &dwDiffTime, pte, llCurTime);
  265. Trace0(TIMER, " \n");
  266. Trace8(TIMER, "Updating timer <%d><%d><%d> Timeout:%lu <%s> <%s> "
  267. "to %d Status:%d\n", dwBucket, pte->Id, pte->Id2, dwDiffTime,
  268. str1, str2, (DWORD)llNewTime, pte->Status);
  269. }
  270. #endif
  271. // first remove the timer
  272. if (pte->Status&TIMER_STATUS_ACTIVE) {
  273. RemoveTimer(pte, DBG_N);
  274. }
  275. DEBUG_CHECK_LOW_INDEX(7);//deldel
  276. // now insert the timer back into the timer queue. Resync flag is set
  277. InsertTimer(pte, llNewTime, TRUE, DBG_N);
  278. #if DEBUG_TIMER_UPDATETIMER1
  279. if (bDbgPrint||g_DebugPrint) {
  280. Trace0(TIMER1, " ");
  281. Trace0(TIMER1, "Printing Timer Queue after _UpdateTimer");
  282. DebugPrintTimerQueue();
  283. }
  284. #endif
  285. //kslksl
  286. if (MyDebug&0x4) DebugScanTimerQueue(4);
  287. DebugCheckLowTimer(1);//deldel
  288. DEBUG_CHECK_LOW_INDEX(8);//deldel
  289. Trace0(LEAVE1, "_UpdateLocalTimer()");
  290. return;
  291. }
  292. //------------------------------------------------------------------------------
  293. // _RemoveTimer
  294. //
  295. // Removes the timer from the list. Changes the status of the timer to CREATED.
  296. // Assumes global timer lock.
  297. // LowIndex might not be correct
  298. //------------------------------------------------------------------------------
  299. VOID
  300. RemoveTimer (
  301. PIGMP_TIMER_ENTRY pte,
  302. BOOL bDbg
  303. )
  304. {
  305. LONGLONG llCurTime = GetCurrentIgmpTime();
  306. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  307. Trace0(ENTER1, "_RemoveTimer()");
  308. CHECK_TIMER_SIGNATURE(pte);
  309. CHECK_IF_ACQUIRED_TIMER_LOCK();
  310. DebugCheckLowTimer(1);//deldel
  311. DEBUG_CHECK_LOW_INDEX(9);//deldel
  312. // print info about the timer being removed
  313. #if DEBUG_TIMER_ACTIVITY
  314. {
  315. DWORD dwBucket, dwDiffTime;
  316. CHAR str1[20], str2[20];
  317. MAP_TO_BUCKET(dwBucket, pte->Timeout);
  318. GetTimerDebugInfo(str1, str2, &dwDiffTime, pte, llCurTime);
  319. Trace7(TIMER, "Removing timer <%d><%d><%d> Timeout:%lu <%s> <%s> "
  320. "Status:%d", dwBucket, pte->Id, pte->Id2, dwDiffTime, str1,
  321. str2, pte->Status);
  322. }
  323. #endif
  324. // remove the timer from the timer queue and decrement the number of timers
  325. RemoveEntryList(&pte->Link);
  326. ptg->NumTimers--;
  327. // reset the minimum timeout for the timer queue, if this timer was the min
  328. if (pte->Timeout==ptg->WTTimeout) {
  329. SetNextTime(ptg->TableLowIndex);
  330. }
  331. DEBUG_CHECK_LOW_INDEX(10);//deldel
  332. // reset the timer status to created
  333. pte->Status = TIMER_STATUS_CREATED;
  334. // print timer queue
  335. #if DEBUG_TIMER_REMOVETIMER2
  336. if (bDbg||g_DebugPrint) {
  337. Trace0(TIMER1, " ");
  338. Trace0(TIMER1, "Printing Timer Queue after _RemoveTimer");
  339. DebugPrintTimerQueue();
  340. }
  341. #endif
  342. //kslksl
  343. if (MyDebug&0x8) DebugScanTimerQueue(8);
  344. DebugCheckLowTimer(1);//deldel
  345. DEBUG_CHECK_LOW_INDEX(11);//deldel
  346. Trace0(LEAVE1, "Leaving _RemoveTimer()");
  347. return;
  348. }
  349. //------------------------------------------------------------------------------
  350. // _SetNextTime
  351. // called when a timer==WTTimeout has been removed or fired,used to set the
  352. // next min time.
  353. // LowIndex might not be correct
  354. //------------------------------------------------------------------------------
  355. VOID
  356. SetNextTime (
  357. DWORD dwLowIndex
  358. )
  359. {
  360. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  361. PIGMP_TIMER_ENTRY pte, pteMin=NULL;
  362. LONGLONG ilMinTime;
  363. PLIST_ENTRY pHead, ple;
  364. DWORD Error = NO_ERROR;
  365. LONGLONG llCurTime=GetCurrentIgmpTime();
  366. //kslksl
  367. //Trace0(TIMER1, "entering _SetNextTime()");
  368. DEBUG_CHECK_LOW_INDEX(12);//deldel
  369. //kslksl
  370. if (MyDebug&0x11) DebugScanTimerQueue(0x11);
  371. //
  372. // if timer list empty, set lowIndex, and timer to infinite, and return.
  373. //
  374. if (ptg->NumTimers==0) {
  375. ptg->TableLowIndex = (DWORD)~0;
  376. SET_TIMER_INFINITE(ptg->WTTimeout);
  377. ptg->Status = TIMER_STATUS_INACTIVE;
  378. return;
  379. }
  380. DEBUG_CHECK_LOW_INDEX(13);//deldel
  381. //
  382. // find lowest table index having an entry
  383. //
  384. if (dwLowIndex>NUM_TIMER_BUCKETS-1)
  385. dwLowIndex = 0;
  386. for (; dwLowIndex<=NUM_TIMER_BUCKETS-1; dwLowIndex++) {
  387. if (IsListEmpty(&ptg->TimesTable[dwLowIndex]) )
  388. continue;
  389. else
  390. break;
  391. }
  392. DEBUG_CHECK_LOW_INDEX(14);//deldel
  393. ptg->TableLowIndex = dwLowIndex;
  394. DEBUG_CHECK_LOW_INDEX(15);//deldel
  395. //kslksl
  396. //if (dwLowIndex==NUM_TIMER_BUCKETS)
  397. // IgmpDbgBreakPoint();
  398. //
  399. // find timer entry with the lowest time
  400. //
  401. if (dwLowIndex==0) {
  402. pteMin = CONTAINING_RECORD(ptg->TimesTable[0].Flink,
  403. IGMP_TIMER_ENTRY, Link);
  404. }
  405. else {
  406. // except bucket[0], other buckets are not sorted
  407. pHead = &ptg->TimesTable[dwLowIndex];
  408. ilMinTime = (((LONGLONG)0x7FFFFFF)<<32)+ ~0;
  409. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  410. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  411. if (pte->Timeout<ilMinTime) {
  412. ilMinTime = pte->Timeout;
  413. pteMin = pte;
  414. }
  415. }
  416. }
  417. //
  418. // update global time
  419. //
  420. if ((IS_TIMER_INFINITE(ptg->WTTimeout))
  421. || (pteMin->Timeout!=ptg->WTTimeout))
  422. {
  423. ptg->WTTimeout = pteMin->Timeout;
  424. if (!IS_TIMER_INFINITE(ptg->WTTimeout)) {
  425. BOOL bSuccess ;
  426. bSuccess = ChangeTimerQueueTimer(ptg->WTTimer, ptg->WTTimer1,
  427. llCurTime<ptg->WTTimeout
  428. ?(ULONG) ((ptg->WTTimeout - llCurTime))
  429. : 0,
  430. 1000000 // set a periodic timer
  431. );
  432. if (!bSuccess) {
  433. Error = GetLastError();
  434. Trace1(ERR, "ChangeTimerQueueTimer returned error:%d in SetNextTime",
  435. Error);
  436. IgmpAssertOnError(FALSE);
  437. }
  438. else {
  439. #if DEBUG_TIMER_ACTIVITY
  440. Trace1(TIMER1, "ChangeTimerQueueTimer set to %lu",
  441. (ULONG) ((ptg->WTTimeout - llCurTime))/1000);
  442. #if DEBUG_TIMER_ID
  443. g_Fire = (ULONG) ((ptg->WTTimeout - llCurTime)/1000);
  444. #endif
  445. #endif
  446. }
  447. }
  448. ptg->Status = TIMER_STATUS_ACTIVE;
  449. }
  450. DEBUG_CHECK_LOW_INDEX(16);//deldel
  451. //
  452. // resynchronize timer list if required
  453. //
  454. if ( (ptg->TableLowIndex!=0)
  455. && (ptg->SyncTime + TIMER_BUCKET_GRANULARITY_ABS > llCurTime) ) {
  456. ResyncTimerBuckets(llCurTime);
  457. }
  458. //kslksl
  459. if (MyDebug&0x12) DebugScanTimerQueue(0x12);
  460. DebugCheckLowTimer(1);//deldel
  461. DEBUG_CHECK_LOW_INDEX(17);//deldel
  462. Trace0(LEAVE1, "_SetNextTime()");
  463. return;
  464. } //end _SetNextTime
  465. //------------------------------------------------------------------------------
  466. // _InitializeIgmpTime
  467. // Initialize the igmp absolute timer
  468. //------------------------------------------------------------------------------
  469. VOID
  470. InitializeIgmpTime(
  471. )
  472. {
  473. g_TimerStruct.CurrentTime.HighPart = 0;
  474. g_TimerStruct.CurrentTime.LowPart = GetTickCount();
  475. return;
  476. }
  477. //------------------------------------------------------------------------------
  478. // _GetCurrentIgmpTimer
  479. // uses GetTickCount(). converts it into 64 bit absolute timer.
  480. //------------------------------------------------------------------------------
  481. LONGLONG
  482. GetCurrentIgmpTime(
  483. )
  484. {
  485. ULONG ulCurTimeLow = GetTickCount();
  486. //
  487. // see if timer has wrapped
  488. //
  489. // since multi-threaded, it might get preempted and CurrentTime
  490. // might get lower than the global variable g_TimerStruct.CurrentTime.LowPart
  491. // which might be set by another thread. So we also explicitly verify the
  492. // switch from a very large DWORD to a small one.
  493. // (code thanks to murlik&jamesg)
  494. //
  495. if ( (ulCurTimeLow < g_TimerStruct.CurrentTime.LowPart)
  496. && ((LONG)g_TimerStruct.CurrentTime.LowPart < 0)
  497. && ((LONG)ulCurTimeLow > 0) )
  498. {
  499. // use global CS instead of creating a new CS
  500. ACQUIRE_GLOBAL_LOCK("_GetCurrentIgmpTime");
  501. // make sure that the global timer has not been updated meanwhile
  502. if ( (LONG)g_TimerStruct.CurrentTime.LowPart < 0)
  503. {
  504. g_TimerStruct.CurrentTime.HighPart++;
  505. g_TimerStruct.CurrentTime.LowPart = ulCurTimeLow;
  506. }
  507. RELEASE_GLOBAL_LOCK("_GetCurrentIgmpTime");
  508. }
  509. g_TimerStruct.CurrentTime.LowPart = ulCurTimeLow;
  510. return g_TimerStruct.CurrentTime.QuadPart;
  511. }
  512. //------------------------------------------------------------------------------
  513. // _WF_ProcessTimerEvent
  514. //
  515. // Processes the timer queue, firing events and sets the next timer at the end.
  516. // Is queued by the Wait Server Thread.
  517. //
  518. // Locks: Acquires global timer lock before entering into the timer queue.
  519. //------------------------------------------------------------------------------
  520. VOID
  521. WF_ProcessTimerEvent (
  522. PVOID pContext
  523. )
  524. {
  525. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  526. LONGLONG ilDiffTime, llCurTime = GetCurrentIgmpTime();
  527. DWORD Error = NO_ERROR;
  528. PLIST_ENTRY pHead, ple;
  529. PIGMP_TIMER_ENTRY pte;
  530. LONGLONG llFiredTimeout;
  531. #if DEBUG_TIMER_PROCESSQUEUE2
  532. BOOL bDbg = FALSE;
  533. #endif
  534. if (!EnterIgmpWorker()) {return;}
  535. Trace0(ENTER1, "Entering _WF_ProcessTimerEvent");
  536. // acquire timer lock
  537. ACQUIRE_TIMER_LOCK("_WF_ProcessTimerEvent");
  538. DebugCheckLowTimer(1); //deldel
  539. // print the timer queue
  540. #if DEBUG_TIMER_PROCESSQUEUE1
  541. Trace0(TIMER1, "Printing Timer Queue before processing the timer queue");
  542. DebugPrintTimerQueue();
  543. #endif
  544. BEGIN_BREAKOUT_BLOCK1 {
  545. // I fire a timer if it is set to within + FORWARD_TIMER_FIRED from now
  546. llFiredTimeout = llCurTime + FORWARD_TIMER_FIRED;
  547. // if there are no timers, then I am done
  548. if (ptg->NumTimers<1) {
  549. Trace1(TIMER1, "Num timers%d less than 1 in _WF_ProcessTimerEvent",
  550. ptg->NumTimers);
  551. GOTO_END_BLOCK1;
  552. }
  553. //
  554. // find all the timers with lower timeouts and fire callbacks in my context
  555. //
  556. BEGIN_BREAKOUT_BLOCK2 {
  557. for ( ; ptg->TableLowIndex <= NUM_TIMER_BUCKETS-1; ) {
  558. BOOL bDontCheckLowIndex = FALSE;
  559. pHead = &ptg->TimesTable[ptg->TableLowIndex];
  560. for (ple=pHead->Flink; ple!=pHead; ) {
  561. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  562. ple = ple->Flink;
  563. // this timer is fired
  564. if (pte->Timeout < llFiredTimeout) {
  565. RemoveEntryList(&pte->Link);
  566. pte->Status = TIMER_STATUS_FIRED;
  567. ptg->NumTimers --;
  568. if (IsListEmpty(&ptg->TimesTable[ptg->TableLowIndex])) {
  569. for (; ptg->TableLowIndex<=NUM_TIMER_BUCKETS-1; ptg->TableLowIndex++) {
  570. if (IsListEmpty(&ptg->TimesTable[ptg->TableLowIndex]) )
  571. continue;
  572. else
  573. break;
  574. }
  575. bDontCheckLowIndex = TRUE;
  576. if (ptg->TableLowIndex==NUM_TIMER_BUCKETS)
  577. ptg->TableLowIndex = ~0;
  578. }
  579. //or should i queue to other worker threads
  580. (pte->Function)(pte->Context);
  581. #if DEBUG_TIMER_PROCESSQUEUE2
  582. if (pte->Function!=WT_MibDisplay && pte->Function!=T_QueryTimer)
  583. bDbg = TRUE;
  584. #endif
  585. }
  586. else {
  587. if (ptg->TableLowIndex==0) //only the 1st bucket is sorted
  588. GOTO_END_BLOCK2;
  589. }
  590. }
  591. if (!bDontCheckLowIndex) {
  592. // if any bucket is not empty, then I am done, as I start with LowIndex
  593. if (!IsListEmpty(&ptg->TimesTable[ptg->TableLowIndex]))
  594. break;
  595. ptg->TableLowIndex++;
  596. }
  597. } //end for loop
  598. } END_BREAKOUT_BLOCK2;
  599. if ( (ptg->TableLowIndex!=0)
  600. && (ptg->SyncTime + TIMER_BUCKET_GRANULARITY_ABS < llCurTime) ) {
  601. ResyncTimerBuckets(llCurTime);
  602. }
  603. //
  604. // set the next lowest time
  605. //
  606. SET_TIMER_INFINITE(ptg->WTTimeout);
  607. SetNextTime(ptg->TableLowIndex);
  608. } END_BREAKOUT_BLOCK1;
  609. // print the timer queue
  610. #if DEBUG_TIMER_PROCESSQUEUE2
  611. if (bDbg||g_DebugPrint) {
  612. Trace0(TIMER1, " ");
  613. Trace0(TIMER1, "Printing Timer Queue after processing the timer queue");
  614. DebugPrintTimerQueue();
  615. }
  616. #endif
  617. //kslksl
  618. if (MyDebug&0x14) DebugScanTimerQueue(0x14);
  619. DebugCheckLowTimer(1); //deldel
  620. RELEASE_TIMER_LOCK("_WF_ProcessTimerEvent");
  621. Trace0(LEAVE1, "Leaving _WF_ProcessTimerEvent()");
  622. LeaveIgmpWorker();
  623. return ;
  624. } //end _WF_ProcessTimerEvent
  625. //------------------------------------------------------------------------------
  626. // WT_ProcessTimerEvent
  627. //
  628. // Callback: fired when the timer set by this dll is timed out by the NtdllTimer
  629. //------------------------------------------------------------------------------
  630. VOID
  631. WT_ProcessTimerEvent (
  632. PVOID pContext,
  633. BOOLEAN Unused
  634. )
  635. {
  636. //enter/leaveIgmpApi not required as the timer queue is persistent
  637. Trace0(ENTER1, "Entering _WT_ProcessTimerEvent()");
  638. QueueIgmpWorker((LPTHREAD_START_ROUTINE)WF_ProcessTimerEvent, pContext);
  639. Trace0(LEAVE1, "Leaving _WT_ProcessTimerEvent()");
  640. return;
  641. }
  642. //------------------------------------------------------------------------------
  643. // _InsertTimerInSortedList
  644. // Used to insert a timer in the sorted bucket=0
  645. //------------------------------------------------------------------------------
  646. VOID
  647. InsertTimerInSortedList(
  648. PIGMP_TIMER_ENTRY pteNew,
  649. PLIST_ENTRY pHead
  650. )
  651. {
  652. PLIST_ENTRY ple;
  653. PIGMP_TIMER_ENTRY pte;
  654. LONGLONG llNewTime;
  655. llNewTime = pteNew->Timeout;
  656. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  657. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  658. if (llNewTime<= pte->Timeout)
  659. break;
  660. }
  661. InsertTailList(ple, &pteNew->Link);
  662. return;
  663. }
  664. //------------------------------------------------------------------------------
  665. // _ResyncTimerBuckets
  666. //
  667. // Called during insert: when the 1st bucket is empty, and other buckets have
  668. // to be moved left
  669. // LowIndex might not be correct
  670. //------------------------------------------------------------------------------
  671. DWORD DebugIgmpNumShift[30];
  672. PLIST_ENTRY DebugIgmpNumShift1[64][3];
  673. DWORD DebugIgmpNumShiftCount;
  674. VOID
  675. ResyncTimerBuckets(
  676. LONGLONG llCurTime
  677. )
  678. {
  679. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  680. PLIST_ENTRY pHead, ple, pleCur;
  681. LIST_ENTRY le;
  682. PIGMP_TIMER_ENTRY pte;
  683. LONGLONG lastBucketTime;
  684. DWORD numShift, dwCount, dwBucket, i, j;
  685. Trace0(TIMER1, "entering _ResyncTimerBuckets()");
  686. //deldel
  687. for (DebugIgmpNumShiftCount=0; DebugIgmpNumShiftCount<30; DebugIgmpNumShiftCount++)
  688. DebugIgmpNumShift[DebugIgmpNumShiftCount] = 0;
  689. DebugCheckLowTimer(0);//deldel
  690. DEBUG_CHECK_LOW_INDEX(21);//deldel
  691. //Trace0(TIMER1, "Printing Timer Queue before _ResyncTimerBuckets"); //deldel
  692. //DebugPrintTimerQueue(); //deldel
  693. if (ptg->NumTimers == 0)
  694. return;
  695. //kslksl
  696. if (MyDebug&0x18) DebugScanTimerQueue(0x18);
  697. //
  698. // SyncTime should always be <= to currentTime
  699. //
  700. numShift = 0;
  701. DebugIgmpNumShift[0] = numShift;//deldel
  702. DebugIgmpNumShiftCount = 0; //deldel
  703. while (numShift<NUM_TIMER_BUCKETS
  704. && (ptg->SyncTime+TIMER_BUCKET_GRANULARITY_ABS <= llCurTime)
  705. ) {
  706. DebugIgmpNumShift1[numShift][0] = &ptg->TimesTable[numShift]; //deldel
  707. DebugIgmpNumShift1[numShift][1] = ptg->TimesTable[numShift].Flink; //deldel
  708. DebugIgmpNumShift1[numShift][2] = ptg->TimesTable[numShift].Blink; //deldel
  709. if (!IsListEmpty(&ptg->TimesTable[numShift]))
  710. break;
  711. ptg->SyncTime += TIMER_BUCKET_GRANULARITY_ABS;
  712. numShift++;
  713. }
  714. DebugIgmpNumShiftCount = DebugIgmpNumShift[1] = numShift;//deldel
  715. if (numShift==0 || numShift==NUM_TIMER_BUCKETS)
  716. return;
  717. //
  718. // shift all buckets left, except for the last bucket and reinitialize the
  719. // list heads
  720. //
  721. for (i=0,j=numShift; i<NUM_TIMER_BUCKETS-1-numShift; i++,j++) {
  722. if (IsListEmpty(&ptg->TimesTable[j])) {
  723. ptg->TimesTable[j].Flink = ptg->TimesTable[j].Blink
  724. = &ptg->TimesTable[i];
  725. }
  726. else {
  727. ptg->TimesTable[j].Flink->Blink = &ptg->TimesTable[i];
  728. ptg->TimesTable[j].Blink->Flink = &ptg->TimesTable[i];
  729. }
  730. }
  731. DebugIgmpNumShift[2] = numShift;//deldel
  732. MoveMemory( (PVOID)&(ptg->TimesTable[0]),
  733. (VOID *)&(ptg->TimesTable[numShift]),
  734. (sizeof(LIST_ENTRY) * (NUM_TIMER_BUCKETS-1-numShift))
  735. );
  736. for (dwCount=1; dwCount<=numShift; dwCount++)
  737. InitializeListHead(&ptg->TimesTable[NUM_TIMER_BUCKETS-1-dwCount]);
  738. DebugIgmpNumShift[3] = numShift;//deldel
  739. //
  740. // go through the last bucket and redistribute it
  741. //
  742. lastBucketTime = ptg->SyncTime
  743. + (TIMER_BUCKET_GRANULARITY_ABS*(NUM_TIMER_BUCKETS-1));
  744. pHead = &ptg->TimesTable[NUM_TIMER_BUCKETS-1];
  745. for (ple=pHead->Flink; ple!=pHead; ) {
  746. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  747. pleCur = ple;
  748. ple = ple->Flink;
  749. if (pte->Timeout<lastBucketTime) {
  750. RemoveEntryList(pleCur);
  751. MAP_TO_BUCKET(dwBucket, pte->Timeout);
  752. if (dwBucket==0) {
  753. InsertTimerInSortedList(pte, &ptg->TimesTable[0]);
  754. }
  755. else {
  756. InsertTailList(&ptg->TimesTable[dwBucket], pleCur);
  757. }
  758. }
  759. }
  760. DebugIgmpNumShift[4] = numShift;//deldel
  761. DEBUG_CHECK_LOW_INDEX(22);//deldel
  762. //
  763. // sort the times in the first bucket
  764. //
  765. InitializeListHead(&le);
  766. InsertHeadList(&ptg->TimesTable[0], &le);
  767. RemoveEntryList(&ptg->TimesTable[0]);
  768. InitializeListHead(&ptg->TimesTable[0]);
  769. for (ple=le.Flink; ple!=&le; ) {
  770. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  771. RemoveEntryList(ple);
  772. ple = ple->Flink;
  773. InsertTimerInSortedList(pte, &ptg->TimesTable[0]);
  774. }
  775. DEBUG_CHECK_LOW_INDEX(23);//deldel
  776. DebugIgmpNumShift[5] = numShift;//deldel
  777. //
  778. // set the TableLowIndex
  779. //
  780. if (ptg->TableLowIndex>=NUM_TIMER_BUCKETS-1) {
  781. for (ptg->TableLowIndex=0; ptg->TableLowIndex<=NUM_TIMER_BUCKETS-1;
  782. ptg->TableLowIndex++)
  783. {
  784. if (IsListEmpty(&ptg->TimesTable[ptg->TableLowIndex]) )
  785. continue;
  786. else
  787. break;
  788. }
  789. DEBUG_CHECK_LOW_INDEX(24);//deldel
  790. }
  791. else {
  792. DebugIgmpNumShift[6] = numShift;//deldel
  793. ptg->TableLowIndex -= numShift;
  794. DebugIgmpNumShift[7] = numShift;//deldel
  795. DEBUG_CHECK_LOW_INDEX(25);//deldel
  796. }
  797. //#if DEBUG_TIMER_RESYNCTIMER deldel
  798. //Trace0(TIMER1, "Printing Timer Queue after _ResyncTimerBuckets");
  799. //DebugPrintTimerQueue();
  800. //#endif deldel
  801. //kslksl
  802. if (MyDebug&0x21) DebugScanTimerQueue(0x21);
  803. DebugCheckLowTimer(0);//deldel
  804. DEBUG_CHECK_LOW_INDEX(26);//deldel
  805. // debugdebug
  806. if (g_TimerStruct.TableLowIndex>64 && g_TimerStruct.TableLowIndex!=~0) {
  807. IgmpDbgBreakPoint();
  808. g_TimerStruct.TableLowIndex = 0;
  809. SetNextTime(0);
  810. ResyncTimerBuckets(llCurTime);
  811. }
  812. Trace0(LEAVE1, "leaving _ResyncTimerBuckets()");
  813. return;
  814. } //end _ResyncTimerBuckets
  815. //------------------------------------------------------------------------------
  816. // _InitializeTimerGlobal
  817. //
  818. // create the timer CS and WaitTimer. registers a queue and timer with NtdllTimer.
  819. //
  820. // Called by: _StartProtocol()
  821. // Locks: no locks taken here.
  822. //------------------------------------------------------------------------------
  823. DWORD
  824. InitializeTimerGlobal (
  825. )
  826. {
  827. DWORD Error = NO_ERROR, i;
  828. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  829. BOOL bErr;
  830. LONGLONG llCurTime = GetTickCount();
  831. Trace0(ENTER1, "Entering _InitializeTimerGlobal()");
  832. bErr = TRUE;
  833. BEGIN_BREAKOUT_BLOCK1 {
  834. // initialize igmp timer used to get tick count
  835. InitializeIgmpTime();
  836. //
  837. // initialize timer critical section
  838. //
  839. try {
  840. InitializeCriticalSection(&ptg->CS);
  841. }
  842. except (EXCEPTION_EXECUTE_HANDLER) {
  843. Error = GetExceptionCode();
  844. Trace1(
  845. ANY, "exception %d initializing global timer critical section",
  846. Error
  847. );
  848. Logerr0(INIT_CRITSEC_FAILED, Error);
  849. GOTO_END_BLOCK1;
  850. }
  851. #if DEBUG_FLAGS_SIGNATURE
  852. ptg->CSFlag = 0; //deldel
  853. #endif
  854. // create WaitTimer for igmp
  855. ptg->WTTimer = CreateTimerQueue();
  856. if ( ! ptg->WTTimer) {
  857. Error = GetLastError();
  858. Trace1(ERR, "CreateTimerQueue() failed:%d", Error);
  859. IgmpAssertOnError(FALSE);
  860. GOTO_END_BLOCK1;
  861. }
  862. //
  863. // create a periodic timer which does not get deletd
  864. //
  865. if (! CreateTimerQueueTimer(
  866. &ptg->WTTimer1,
  867. ptg->WTTimer, WT_ProcessTimerEvent,
  868. NULL, //context
  869. 1000000,
  870. 1000000,
  871. 0
  872. ))
  873. {
  874. Error = GetLastError();
  875. Trace1(ERR, "CreateTimerQueue() failed:%d", Error);
  876. IgmpAssertOnError(FALSE);
  877. GOTO_END_BLOCK1;
  878. }
  879. // set initial timeout to infinite, and SyncTime to the current time
  880. SET_TIMER_INFINITE(ptg->WTTimeout);
  881. ptg->SyncTime = llCurTime;
  882. ptg->CurrentTime.QuadPart = llCurTime;
  883. ptg->NumTimers = 0;
  884. // initialize the timer buckets
  885. for (i=0; i<NUM_TIMER_BUCKETS; i++) {
  886. InitializeListHead(&ptg->TimesTable[i]);
  887. }
  888. // set the TableLowIndex
  889. ptg->TableLowIndex = (DWORD)~0;
  890. // set the status of the global timer
  891. ptg->Status = TIMER_STATUS_CREATED;
  892. bErr = FALSE;
  893. } END_BREAKOUT_BLOCK1;
  894. if (bErr) {
  895. DeInitializeTimerGlobal();
  896. Trace0(LEAVE1, "Leaving. Could not _InitializeTimerGlobal():");
  897. return ERROR_CAN_NOT_COMPLETE;
  898. }
  899. else {
  900. Trace0(LEAVE1, "Leaving _InitializeTimerGlobal()");
  901. return NO_ERROR;
  902. }
  903. } //end _InitializeTimerGlobal
  904. //------------------------------------------------------------------------------
  905. // _DeInitializeTimerGlobal
  906. //
  907. // deinitializes the timer CS, and deletes the timer queue with Rtl
  908. //------------------------------------------------------------------------------
  909. VOID
  910. DeInitializeTimerGlobal (
  911. )
  912. {
  913. DeleteCriticalSection(&g_TimerStruct.CS);
  914. DeleteTimerQueueEx(g_TimerStruct.WTTimer, NULL);
  915. return;
  916. } //end _DeInitializeTimerGlobal
  917. //------------------------------------------------------------------------------
  918. // _DebugPrintTimerEntry
  919. //
  920. // Assumes DEBUG_TIMER_TIMERID is true
  921. //------------------------------------------------------------------------------
  922. VOID
  923. DebugPrintTimerEntry (
  924. PIGMP_TIMER_ENTRY pte,
  925. DWORD dwBucket,
  926. LONGLONG llCurTime
  927. )
  928. {
  929. DWORD dwDiffTime;
  930. CHAR str1[20], str2[20];
  931. #if DEBUG_TIMER_TIMERID
  932. CHECK_TIMER_SIGNATURE(pte);
  933. //deldel
  934. //if (pte->Id==920)
  935. // return;
  936. if (dwBucket==(DWORD)~0) {
  937. MAP_TO_BUCKET(dwBucket, pte->Timeout);
  938. }
  939. GetTimerDebugInfo(str1, str2, &dwDiffTime, pte, llCurTime);
  940. if (pte->Timeout - llCurTime > 0) {
  941. Trace8(TIMER, "---- <%2d><%d><%d> Timeout:%lu <%s> <%s> Status:%d %x",
  942. dwBucket, pte->Id, pte->Id2, dwDiffTime, str1, str2,
  943. pte->Status, pte->Context);
  944. }
  945. else {
  946. Trace8(TIMER, "---- <%d><%d><%d> Timeout:--%lu <%s> <%s> Status:%d %x %x",
  947. dwBucket, pte->Id, pte->Id2, dwDiffTime, str1, str2,
  948. pte->Status, pte->Context);
  949. }
  950. #endif //#if DEBUG_TIMER_TIMERID
  951. return;
  952. }
  953. //------------------------------------------------------------------------------
  954. // _GetTimerDebugInfo
  955. //
  956. // returns info regarding what type of timer it is
  957. //------------------------------------------------------------------------------
  958. VOID
  959. GetTimerDebugInfo(
  960. CHAR str1[20],
  961. CHAR str2[20],
  962. DWORD *pdwDiffTime,
  963. PIGMP_TIMER_ENTRY pte,
  964. LONGLONG llCurTime
  965. )
  966. {
  967. LONGLONG diffTime;
  968. #if DEBUG_TIMER_TIMERID
  969. diffTime = (pte->Timeout - llCurTime > 0)
  970. ? pte->Timeout - llCurTime
  971. : llCurTime - pte->Timeout;
  972. diffTime /= (LONGLONG)1000; //in seconds
  973. *pdwDiffTime = (DWORD)diffTime;
  974. strcpy(str2, " ");
  975. switch (pte->Id) {
  976. case 110:
  977. case 120: strcpy(str1, "iGenQuery "); break;
  978. case 210:
  979. case 220: strcpy(str1, "iOtherQry "); break;
  980. case 211: strcpy(str1, "iOtherQry* "); break;
  981. case 331:
  982. case 321: strcpy(str1, "gMemTimer* "); INET_COPY(str2, pte->Group); break;
  983. case 300:
  984. case 320:
  985. case 330:
  986. case 340: strcpy(str1, "gMemTimer "); INET_COPY(str2, pte->Group); break;
  987. case 400:
  988. case 410:
  989. case 420: strcpy(str1, "gGrpSpQry "); INET_COPY(str2, pte->Group); break;
  990. case 510:
  991. case 520: strcpy(str1, "gLstV1Rpt "); INET_COPY(str2, pte->Group); break;
  992. case 511: strcpy(str1, "gLstV1Rpt* "); INET_COPY(str2, pte->Group); break;
  993. case 550:
  994. case 560: strcpy(str1, "gLstV2Rpt "); INET_COPY(str2, pte->Group); break;
  995. case 610:
  996. case 620: strcpy(str1, "gGSrcExp "); INET_COPY(str2, pte->Group);
  997. lstrcat(str2, ":"); INET_CAT(str2, pte->Source); break;
  998. case 720:
  999. case 740: strcpy(str1, "iV1Router "); break;
  1000. case 741: strcpy(str1, "iV1Router* "); break;
  1001. case 920:
  1002. case 910: strcpy(str1, "_MibTimer "); break;
  1003. case 1001: strcpy(str1, "_gSrcQry "); INET_COPY(str2, pte->Group); break;
  1004. default: strcpy(str1, "???? "); break;
  1005. }
  1006. #endif //DEBUG_TIMER_TIMERID
  1007. return;
  1008. }
  1009. VOID
  1010. DebugCheckTimerContexts(
  1011. )
  1012. {
  1013. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  1014. PIGMP_TIMER_ENTRY pte;
  1015. PLIST_ENTRY pHead, ple;
  1016. DWORD i;
  1017. ACQUIRE_TIMER_LOCK("_DebugPrintTimerQueue");
  1018. //Trace0(ERR, "%d*************", Id);
  1019. for (i=0; i<NUM_TIMER_BUCKETS; i++) {
  1020. pHead = &ptg->TimesTable[i];
  1021. if (IsListEmpty(pHead))
  1022. continue;
  1023. else {
  1024. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  1025. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  1026. if ( ((ULONG_PTR)pte->Context) & 0x3)
  1027. IgmpDbgBreakPoint();
  1028. }
  1029. }
  1030. }
  1031. RELEASE_TIMER_LOCK("_DebugPrintTimerQueue");
  1032. return;
  1033. }
  1034. DWORD g_igmp1, g_igmp2, g_igmp3;
  1035. PLIST_ENTRY g_ple1, g_pHead;
  1036. PIGMP_TIMER_ENTRY g_pte;
  1037. //DebugCheck
  1038. DWORD
  1039. DebugScanTimerQueue(
  1040. DWORD Id
  1041. )
  1042. {
  1043. Trace1(TIMER1, "_TimerQueue:%d", Id);
  1044. #if DEBUG_TIMER_TIMERID
  1045. if ( (g_igmp3++ & 0x7) == 0x7) { //deldel
  1046. //if ( 1){
  1047. DebugPrintTimerQueue();
  1048. return 0;
  1049. }
  1050. for (g_igmp1=0; g_igmp1<NUM_TIMER_BUCKETS; g_igmp1++) {
  1051. g_pHead = &g_TimerStruct.TimesTable[g_igmp1];
  1052. if (IsListEmpty(g_pHead))
  1053. continue;
  1054. else {
  1055. for (g_ple1=g_pHead->Flink; g_ple1!=g_pHead; g_ple1=g_ple1->Flink) {
  1056. g_pte = CONTAINING_RECORD(g_ple1, IGMP_TIMER_ENTRY, Link);
  1057. CHECK_TIMER_SIGNATURE(g_pte);
  1058. g_igmp2 = g_pte->Id;
  1059. }
  1060. }
  1061. }
  1062. return g_igmp1+g_igmp2;
  1063. #else
  1064. return 0;
  1065. #endif
  1066. }
  1067. //------------------------------------------------------------------------------
  1068. // _DebugPrintTimerQueue
  1069. // takes the timer lock
  1070. //------------------------------------------------------------------------------
  1071. VOID
  1072. APIENTRY
  1073. DebugPrintTimerQueue (
  1074. )
  1075. {
  1076. PIGMP_TIMER_GLOBAL ptg = &g_TimerStruct;
  1077. PIGMP_TIMER_ENTRY pte;
  1078. PLIST_ENTRY pHead, ple;
  1079. LONGLONG llCurTime = GetCurrentIgmpTime();
  1080. DWORD Error=NO_ERROR, i, count;
  1081. //kslksl
  1082. /*if (g_Info.CurrentGroupMemberships > 240)
  1083. return;
  1084. */
  1085. #if DEBUG_TIMER_TIMERID
  1086. ENTER_CRITICAL_SECTION(&g_CS, "g_CS", "_DebugPrintTimerQueue");
  1087. if (g_RunningStatus != IGMP_STATUS_RUNNING) {
  1088. Error = ERROR_CAN_NOT_COMPLETE;
  1089. }
  1090. else {
  1091. ++g_ActivityCount;
  1092. }
  1093. LEAVE_CRITICAL_SECTION(&g_CS, "g_CS", "_DebugPrintTimerQueue");
  1094. if (Error!=NO_ERROR)
  1095. return;
  1096. if (!EnterIgmpWorker()) {return;}
  1097. ACQUIRE_TIMER_LOCK("_DebugPrintTimerQueue");
  1098. if (g_TimerStruct.NumTimers==0) {
  1099. Trace0(TIMER, "No timers present in the timer queue");
  1100. }
  1101. else {
  1102. Trace0(TIMER, "---------------------LOCAL-TIMER-QUEUE-------------------------");
  1103. Trace6(TIMER, "-- LastFire:%d FireAfter:%d WTTimeout<%d:%lu> SyncTime<%d:%lu>",
  1104. g_Fire, (DWORD)(ptg->WTTimeout - llCurTime),
  1105. TIMER_HIGH(ptg->WTTimeout), TIMER_LOW(ptg->WTTimeout),
  1106. TIMER_HIGH(ptg->SyncTime), TIMER_LOW(ptg->SyncTime) );
  1107. Trace3(TIMER, "-- NumTimers:<%d> TableLowIndex:<%lu> Status:<%d>",
  1108. ptg->NumTimers, ptg->TableLowIndex, ptg->Status);
  1109. Trace0(TIMER, "---------------------------------------------------------------");
  1110. count =0;
  1111. for (i=0; i<NUM_TIMER_BUCKETS; i++) {
  1112. pHead = &ptg->TimesTable[i];
  1113. if (IsListEmpty(pHead))
  1114. continue;
  1115. else {
  1116. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  1117. pte = CONTAINING_RECORD(ple, IGMP_TIMER_ENTRY, Link);
  1118. DebugPrintTimerEntry(pte, i, llCurTime);
  1119. count ++;
  1120. }
  1121. }
  1122. }
  1123. Trace0(TIMER,
  1124. "---------------------------------------------------------------\n\n");
  1125. }
  1126. RELEASE_TIMER_LOCK("_DebugPrintTimerQueue");
  1127. LeaveIgmpWorker();
  1128. #endif //DEBUG_TIMER_TIMERID
  1129. return;
  1130. }