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.

275 lines
7.8 KiB

  1. /************************************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. File Name: ThdPool.cpp
  4. Abstract: Implementation of the thread pool (CThreadPool class)
  5. Notes:
  6. History: 08/01/2001 Created by Hao Yu (haoyu)
  7. ************************************************************************************************/
  8. #include <stdafx.h>
  9. #include <ThdPool.hxx>
  10. #include <SockPool.hxx>
  11. #include <GlobalDef.h>
  12. // The common thread in the thread pool
  13. DWORD WINAPI ThreadProc(LPVOID lpParameter)
  14. {
  15. ASSERT(NULL != lpParameter);
  16. DWORD dwBytesRcvd=0;
  17. DWORD Flags=0;
  18. PIO_CONTEXT pIoContext=NULL;
  19. LPOVERLAPPED pOverlapped=NULL;
  20. HANDLE hCompPort=lpParameter;
  21. HRESULT hr=CoInitializeEx(NULL, COINIT_MULTITHREADED);
  22. if(FAILED(hr))
  23. {
  24. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  25. EVENT_POP3_COM_INIT_FAIL);
  26. ExitProcess(hr);
  27. }
  28. while(1)
  29. {
  30. GetQueuedCompletionStatus(hCompPort,
  31. &dwBytesRcvd,
  32. (PULONG_PTR)(&pIoContext),
  33. &pOverlapped,
  34. INFINITE);
  35. //We don't care about return value
  36. //since we use the failure case to clean up the IO Context
  37. if(NULL == pIoContext || SERVICE_STOP_PENDING == g_dwServerStatus)
  38. {
  39. // This is a shutdown signal
  40. break;
  41. }
  42. g_PerfCounters.DecPerfCntr(e_gcFreeThreadCnt);
  43. pIoContext->m_pCallBack((PULONG_PTR)pIoContext, pOverlapped, dwBytesRcvd);
  44. g_PerfCounters.IncPerfCntr(e_gcFreeThreadCnt);
  45. }
  46. g_PerfCounters.DecPerfCntr(e_gcFreeThreadCnt);
  47. CoUninitialize();
  48. return 0;
  49. }
  50. CThreadPool::CThreadPool()
  51. {
  52. InitializeCriticalSection(&m_csInitGuard);
  53. m_hIOCompPort = NULL;
  54. m_phTdArray = NULL;
  55. m_dwTdCount = 0;
  56. m_bInit = FALSE;
  57. }
  58. CThreadPool::~CThreadPool()
  59. {
  60. if(m_bInit)
  61. {
  62. Uninitialize();
  63. }
  64. DeleteCriticalSection(&m_csInitGuard);
  65. }
  66. // Job done in this function:
  67. // 1) Calculate the number of threads need to be created,
  68. // dwThreadPerProcessor * number of processors of the machine
  69. // 2) Create the IO Completion port
  70. // 3) Create threads
  71. BOOL CThreadPool::Initialize(DWORD dwThreadPerProcessor)
  72. {
  73. int i;
  74. BOOL bRtVal=TRUE;
  75. SYSTEM_INFO SystemInfo;
  76. EnterCriticalSection(&m_csInitGuard);
  77. if(!m_bInit)
  78. {
  79. //Get the number of processors of the machine
  80. GetSystemInfo(&SystemInfo);
  81. if( dwThreadPerProcessor == 0 ||
  82. dwThreadPerProcessor > MAX_THREAD_PER_PROCESSOR )
  83. {
  84. dwThreadPerProcessor = 1;
  85. }
  86. m_dwTdCount = SystemInfo.dwNumberOfProcessors * dwThreadPerProcessor;
  87. // Create the IO Completion Port
  88. m_hIOCompPort = CreateIoCompletionPort (
  89. INVALID_HANDLE_VALUE,
  90. NULL,
  91. NULL,
  92. m_dwTdCount);
  93. if (NULL == m_hIOCompPort)
  94. {
  95. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  96. POP3SVR_FAIL_TO_CREATE_IO_COMP_PORT,
  97. GetLastError());
  98. goto EXIT;
  99. }
  100. m_phTdArray=new HANDLE[m_dwTdCount];
  101. if( NULL == m_phTdArray)
  102. {
  103. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  104. POP3SVR_NOT_ENOUGH_MEMORY);
  105. goto EXIT;
  106. }
  107. // Create the threads
  108. for (i=0;i<m_dwTdCount; i++)
  109. {
  110. m_phTdArray[i] = CreateThread(
  111. NULL,
  112. 0,
  113. ThreadProc,
  114. m_hIOCompPort,
  115. 0,
  116. NULL);
  117. if(NULL == m_phTdArray[i])
  118. {
  119. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  120. POP3SVR_FAILED_TO_CREATE_THREAD,
  121. GetLastError());
  122. goto EXIT;
  123. }
  124. }
  125. m_bInit=TRUE;
  126. }
  127. //Set the total free thread count
  128. g_PerfCounters.SetPerfCntr(e_gcFreeThreadCnt, m_dwTdCount);
  129. LeaveCriticalSection(&m_csInitGuard);
  130. return TRUE;
  131. EXIT:
  132. //In case of error, cleanup and exit
  133. if(NULL != m_phTdArray)
  134. {
  135. for(i=0; i<m_dwTdCount && m_phTdArray[i]; i++ )
  136. {
  137. if(m_phTdArray[i]!=NULL)
  138. {
  139. TerminateThread(m_phTdArray[i], -1);
  140. CloseHandle(m_phTdArray[i]);
  141. }
  142. }
  143. delete[](m_phTdArray);
  144. m_phTdArray=NULL;
  145. }
  146. if(m_hIOCompPort)
  147. {
  148. CloseHandle(m_hIOCompPort);
  149. m_hIOCompPort=NULL;
  150. }
  151. LeaveCriticalSection(&m_csInitGuard);
  152. return FALSE;
  153. }
  154. // Terminate all threads and delete the completion port.
  155. void CThreadPool::Uninitialize()
  156. {
  157. int i;
  158. BOOL bFailedExit=FALSE;
  159. DWORD dwRt;
  160. DWORD dwStatus=0;
  161. EnterCriticalSection(&m_csInitGuard);
  162. if(m_bInit)
  163. {
  164. if(NULL != m_phTdArray)
  165. {
  166. for(i=0; i<m_dwTdCount; i++ )
  167. {
  168. PostQueuedCompletionStatus(m_hIOCompPort, 0, NULL, NULL);
  169. }
  170. dwRt=WaitForMultipleObjects(m_dwTdCount,
  171. m_phTdArray,
  172. TRUE,
  173. SHUTDOWN_WAIT_TIME);
  174. if( (WAIT_TIMEOUT == dwRt) ||
  175. (WAIT_FAILED == dwRt) )
  176. {
  177. for(i=0; i<m_dwTdCount; i++ )
  178. {
  179. //In case some thread did not exit after the wait time
  180. //terminate threads by force
  181. if(NULL!= m_phTdArray[i])
  182. {
  183. if( !GetExitCodeThread(m_phTdArray[i], &dwStatus) ||
  184. (STILL_ACTIVE==dwStatus))
  185. {
  186. // This is a bad case, however we can not wait
  187. // forever, cleanup won't be complete in this case.
  188. TerminateThread(m_phTdArray[i],0);
  189. bFailedExit=TRUE;
  190. }
  191. CloseHandle(m_phTdArray[i]);
  192. }
  193. }
  194. }
  195. else
  196. {
  197. for(i=0; i<m_dwTdCount; i++ )
  198. {
  199. if(NULL!= m_phTdArray[i])
  200. {
  201. CloseHandle(m_phTdArray[i]);
  202. }
  203. }
  204. }
  205. delete[](m_phTdArray);
  206. m_phTdArray=NULL;
  207. }
  208. if(m_hIOCompPort)
  209. {
  210. CloseHandle(m_hIOCompPort);
  211. m_hIOCompPort=NULL;
  212. }
  213. m_bInit=FALSE;
  214. }
  215. LeaveCriticalSection(&m_csInitGuard);
  216. if(bFailedExit)
  217. {
  218. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  219. EVENT_POP3_SERVER_STOP_ERROR,
  220. E_UNEXPECTED);
  221. ExitProcess(E_UNEXPECTED);
  222. }
  223. }
  224. // Associate an IO Context and the IO handle contained
  225. // with the IO Completion port
  226. BOOL CThreadPool::AssociateContext(PIO_CONTEXT pIoContext)
  227. {
  228. if(!m_bInit)
  229. {
  230. return FALSE;
  231. }
  232. return (NULL!=CreateIoCompletionPort(
  233. (HANDLE)(pIoContext->m_hAsyncIO),
  234. m_hIOCompPort,
  235. (ULONG_PTR)pIoContext,
  236. m_dwTdCount));
  237. }