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.

187 lines
3.5 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. blkwork.c
  5. Abstract:
  6. This module implements routines for managing work context blocks.
  7. Author:
  8. Chuck Lenzmeier (chuckl) 9-Feb-1994
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "blktimer.tmh"
  13. #pragma hdrstop
  14. #define BugCheckFileId SRV_FILE_BLKTIMER
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text( PAGE, SrvAllocateTimer )
  17. #pragma alloc_text( PAGE, SrvCancelTimer )
  18. #pragma alloc_text( PAGE, SrvSetTimer )
  19. #endif
  20. PSRV_TIMER
  21. SrvAllocateTimer (
  22. VOID
  23. )
  24. /*++
  25. Routine Description:
  26. This routine allocates a timer structure.
  27. Arguments:
  28. None.
  29. Return Value:
  30. PSRV_TIMER -- pointer to the allocated timer structure, or NULL.
  31. --*/
  32. {
  33. PSLIST_ENTRY entry;
  34. PSRV_TIMER timer;
  35. PAGED_CODE( );
  36. entry = ExInterlockedPopEntrySList( &SrvTimerList, &GLOBAL_SPIN_LOCK(Timer) );
  37. if ( entry == NULL ) {
  38. timer = ALLOCATE_NONPAGED_POOL( sizeof(SRV_TIMER), BlockTypeTimer );
  39. if ( timer != NULL ) {
  40. KeInitializeEvent( &timer->Event, NotificationEvent, FALSE );
  41. KeInitializeTimer( &timer->Timer );
  42. }
  43. } else {
  44. timer = CONTAINING_RECORD( entry, SRV_TIMER, Next );
  45. }
  46. return timer;
  47. } // SrvAllocateTimer
  48. VOID
  49. SrvCancelTimer (
  50. PSRV_TIMER Timer
  51. )
  52. /*++
  53. Routine Description:
  54. This routine cancels a timer.
  55. Arguments:
  56. Timer -- pointer to the timer
  57. Return Value:
  58. None.
  59. --*/
  60. {
  61. PAGED_CODE( );
  62. //
  63. // Cancel the timer.
  64. //
  65. if ( !KeCancelTimer( &Timer->Timer ) ) {
  66. //
  67. // We were unable to cancel the timer. This means that the
  68. // timer routine has either already run or is scheduled to run.
  69. // We need to wait for the timer routine to complete before we
  70. // continue.
  71. //
  72. // We expect that if we couldn't cancel the timer (which
  73. // shouldn't happen often), then the timer routine has probably
  74. // already completed, so we call KeReadStateEvent first to avoid
  75. // the overhead of KeWaitForSingleObject.
  76. //
  77. if ( !KeReadStateEvent( &Timer->Event ) ) {
  78. KeWaitForSingleObject(
  79. &Timer->Event,
  80. UserRequest,
  81. KernelMode, // don't let kernel stack be paged
  82. FALSE, // not alertable
  83. NULL // no timeout
  84. );
  85. }
  86. }
  87. return;
  88. } // SrvCancelTimer
  89. VOID
  90. SrvSetTimer (
  91. IN PSRV_TIMER Timer,
  92. IN PLARGE_INTEGER Timeout,
  93. IN PKDEFERRED_ROUTINE TimeoutHandler,
  94. IN PVOID Context
  95. )
  96. /*++
  97. Routine Description:
  98. This routine starts a timer.
  99. Arguments:
  100. Timer -- pointer to the timer
  101. Timeout -- number of milliseconds to wait
  102. TimeoutHandler -- routine to call if the timer expires
  103. Context -- context value for the timer routine
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. PRKDPC Dpc = &Timer->Dpc;
  109. PAGED_CODE( );
  110. //
  111. // Initialize the DPC associated with the timer. Reset the event
  112. // that indicates that the timer routine has run. Set the timer.
  113. //
  114. KeInitializeDpc( Dpc, TimeoutHandler, Context );
  115. KeSetTargetProcessorDpc( Dpc, (CCHAR)KeGetCurrentProcessorNumber() );
  116. KeClearEvent( &Timer->Event );
  117. KeSetTimer( &Timer->Timer, *Timeout, Dpc );
  118. return;
  119. } // SrvSetTimer