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.

188 lines
4.3 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation
  6. //
  7. // File: kppool.cxx
  8. //
  9. // Contents: Routines to manage the thread pool
  10. //
  11. // History: 10-Jul-2001 t-ryanj Created
  12. //
  13. //------------------------------------------------------------------------
  14. #include "kppool.h"
  15. #include "kpcore.h"
  16. #define KP_THREAD_STACKSIZE 0
  17. #define KP_THREAD_CPUFACTOR 10
  18. HANDLE* KpThreadPool = NULL;
  19. ULONG KpThreadCount = 0;
  20. //+-------------------------------------------------------------------------
  21. //
  22. // Function: KpInitThreadPool
  23. //
  24. // Synopsis: Creates the thread pool.
  25. //
  26. // Effects:
  27. //
  28. // Arguments:
  29. //
  30. // Requires:
  31. //
  32. // Returns: Success status. On failure, no threads are running, no
  33. // memory is allocated.
  34. //
  35. // Notes: TODO: This is a bad way to do threadpools, apparently.
  36. // Find a better one.
  37. //
  38. //--------------------------------------------------------------------------
  39. BOOL
  40. KpInitThreadPool(
  41. VOID
  42. )
  43. {
  44. SYSTEM_INFO Sysinfo;
  45. ULONG TargetThreadCount;
  46. //
  47. // Get system info, so we can see how many procs we've got.
  48. //
  49. GetSystemInfo(&Sysinfo);
  50. //
  51. // Let's make KP_THREAD_CPUFACTOR * numprocs threads.
  52. //
  53. TargetThreadCount = Sysinfo.dwNumberOfProcessors * KP_THREAD_CPUFACTOR;
  54. //
  55. // Make memory to keep track of all these threads.
  56. //
  57. DsysAssert( KpThreadPool == NULL );
  58. KpThreadPool = (HANDLE*)KpAlloc( TargetThreadCount * sizeof(HANDLE) );
  59. if( !KpThreadPool )
  60. {
  61. DebugLog( DEB_ERROR, "%s(%d): Could not allocate memory to keep track of threads.\n" __FILE__, __LINE__ );
  62. goto Error;
  63. }
  64. //
  65. // Zero the memory so we can easily check if a thread creation failed.
  66. //
  67. RtlZeroMemory( KpThreadPool, TargetThreadCount * sizeof(HANDLE) );
  68. //
  69. // Create the Threads
  70. //
  71. DsysAssert(KpThreadCount == 0);
  72. for( KpThreadCount = 0; KpThreadCount < TargetThreadCount; KpThreadCount++ )
  73. {
  74. KpThreadPool[KpThreadCount] = CreateThread( NULL,
  75. KP_THREAD_STACKSIZE,
  76. KpThreadCore,
  77. NULL,
  78. 0,
  79. NULL );
  80. if( !KpThreadPool[KpThreadCount] )
  81. {
  82. DebugLog( DEB_ERROR, "%s(%d): Error creating thread: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  83. goto Error;
  84. }
  85. }
  86. return TRUE;
  87. Error:
  88. KpCleanupThreadPool();
  89. return FALSE;
  90. }
  91. //+-------------------------------------------------------------------------
  92. //
  93. // Function: KpCleanupThreadPool
  94. //
  95. // Synopsis: Asks all threads to terminate, waits for them to do so,
  96. // closes their handles, and frees the memory keeping track of
  97. // the threadpool.
  98. //
  99. // Effects:
  100. //
  101. // Arguments:
  102. //
  103. // Requires:
  104. //
  105. // Returns:
  106. //
  107. // Notes:
  108. //
  109. //
  110. //--------------------------------------------------------------------------
  111. VOID
  112. KpCleanupThreadPool(
  113. VOID
  114. )
  115. {
  116. DWORD dwWaitResult;
  117. BOOL fPostStatus;
  118. //
  119. // Post a terminate request for each thread.
  120. //
  121. for( ULONG i = KpThreadCount; i > 0; i-- )
  122. {
  123. fPostStatus = PostQueuedCompletionStatus(KpGlobalIocp,
  124. 0,
  125. KPCK_TERMINATE,
  126. NULL );
  127. if( !fPostStatus )
  128. {
  129. DebugLog( DEB_ERROR, "%s(%d): Unable to post terminate request to the completion port: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  130. // TODO: Consider if this fails.
  131. // we'll probably want to wait for however many threads to terminate
  132. // as we were able to post requests, then maybe try again or kill
  133. // the rest of the threads
  134. }
  135. }
  136. //
  137. // Wait for the threads to terminate
  138. //
  139. dwWaitResult = WaitForMultipleObjects(KpThreadCount,
  140. KpThreadPool,
  141. TRUE,
  142. INFINITE );
  143. if( dwWaitResult == WAIT_FAILED )
  144. {
  145. DebugLog( DEB_ERROR, "%s(%d): Error waiting for thread terminations: 0x%x.", __FILE__, __LINE__, GetLastError() );
  146. }
  147. //
  148. // Close all the handles
  149. //
  150. while( KpThreadCount-- )
  151. {
  152. CloseHandle(KpThreadPool[KpThreadCount]);
  153. }
  154. //
  155. // Free the memory
  156. //
  157. KpFree( KpThreadPool );
  158. KpThreadPool = NULL;
  159. }