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.

172 lines
3.7 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. THREADS.C
  5. Abstract:
  6. This file contains thread management routines. Callers can register
  7. waitable object handles and the functions to be called when a handle
  8. becomes signaled. Also, work items can be queued, and operated on when
  9. threads become free.
  10. The implementation of the CWorkItemContext class resides in this file
  11. Author:
  12. Dan Lafferty (danl) 10-Jan-1994
  13. Environment:
  14. User Mode - Win32
  15. Revision History:
  16. 21-Jan-1999 jschwart
  17. Removed -- Service Controller and intrinsic services now use
  18. NT thread pool APIs.
  19. 27-Jun-1997 anirudhs
  20. SvcObjectWatcher: Fixed bug that sent WAIT_OBJECT_0 to all timed-
  21. out work items even when only one was signaled.
  22. Made global arrays static instead of heap-allocated.
  23. 04-Dec-1996 anirudhs
  24. Added CWorkItemContext, a higher-level wrapper for SvcAddWorkItem.
  25. 01-Nov-1995 anirudhs
  26. SvcAddWorkItem: Fixed race condition wherein a DLL could add a
  27. work item and another thread would execute the work item, decrement
  28. the DLL ref count and unload the DLL before its ref count was
  29. incremented.
  30. 18-Jul-1994 danl
  31. TmWorkerThread: Fixed Access Violation problem which will occur
  32. if pWorkItem is NULL and we go on to see if the DLL should be
  33. free'd. Now we check to see if pWorkItem is NULL first.
  34. 10-Jan-1994 danl
  35. Created
  36. --*/
  37. #include <nt.h>
  38. #include <ntrtl.h>
  39. #include <nturtl.h>
  40. #include <windows.h>
  41. #include <scdebug.h>
  42. #include <svcslib.h> // CWorkItemContext
  43. //----------
  44. // GLOBALS
  45. //----------
  46. HANDLE CWorkItemContext::s_hNeverSignaled;
  47. VOID
  48. CWorkItemContext::CallBack(
  49. IN PVOID pContext
  50. )
  51. /*++
  52. Routine Description:
  53. Wrapper function for the Perform method that is supplied by derived classes.
  54. --*/
  55. {
  56. //
  57. // Timeout value is meaningless in this case, so tell the
  58. // derived class it was signaled
  59. //
  60. (((CWorkItemContext *) pContext)->Perform(FALSE));
  61. }
  62. VOID
  63. CWorkItemContext::DelayCallBack(
  64. IN PVOID pContext,
  65. IN BOOLEAN fWaitStatus
  66. )
  67. /*++
  68. Routine Description:
  69. Wrapper function for the Perform method that is supplied by derived classes.
  70. --*/
  71. {
  72. (((CWorkItemContext *) pContext)->Perform(fWaitStatus));
  73. }
  74. BOOL
  75. CWorkItemContext::Init(
  76. )
  77. {
  78. ASSERT(s_hNeverSignaled == NULL);
  79. s_hNeverSignaled = CreateEvent(NULL, FALSE, FALSE, NULL);
  80. if (s_hNeverSignaled == NULL)
  81. {
  82. SC_LOG(ERROR, "Couldn't create never-signaled event, %lu\n", GetLastError());
  83. return FALSE;
  84. }
  85. return TRUE;
  86. }
  87. void
  88. CWorkItemContext::UnInit(
  89. )
  90. {
  91. if (s_hNeverSignaled != NULL)
  92. {
  93. CloseHandle(s_hNeverSignaled);
  94. }
  95. }
  96. NTSTATUS
  97. CWorkItemContext::AddDelayedWorkItem(
  98. IN DWORD dwTimeout,
  99. IN DWORD dwFlags
  100. )
  101. /*++
  102. Routine Description:
  103. Queues a work item to take the action after the delay has elapsed.
  104. --*/
  105. {
  106. //
  107. // Give RtlRegisterWait a waitable handle that will never get signaled
  108. // to force it to timeout. (Hack!)
  109. //
  110. // CODEWORK Use an RtlTimerQueue instead
  111. //
  112. if (s_hNeverSignaled == NULL)
  113. {
  114. SC_LOG0(ERROR, "Never-signaled event wasn't created\n");
  115. return STATUS_UNSUCCESSFUL;
  116. }
  117. //
  118. // The timeout mustn't be infinite
  119. //
  120. SC_ASSERT(dwTimeout != INFINITE);
  121. return (RtlRegisterWait(&m_hWorkItem, // work item handle
  122. s_hNeverSignaled, // waitable handle
  123. DelayCallBack, // callback
  124. this, // pContext;
  125. dwTimeout, // timeout
  126. dwFlags)); // flags
  127. }