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.

482 lines
12 KiB

  1. //*************************************************************
  2. //
  3. // File name: TSrvWork.c
  4. //
  5. // Description: Contains routines to support TShareSRV
  6. // work queue interaction
  7. //
  8. // Microsoft Confidential
  9. // Copyright (c) Microsoft Corporation 1991-1997
  10. // All rights reserved
  11. //
  12. //*************************************************************
  13. #include <TSrv.h>
  14. #include <TSrvInfo.h>
  15. #include <TSrvWork.h>
  16. #include <_TSrvWork.h>
  17. // Data declarations
  18. WORKQUEUE g_MainWorkQueue;
  19. //*************************************************************
  20. //
  21. // TSrvInitWorkQueue()
  22. //
  23. // Purpose: Initializes the given work queue
  24. //
  25. // Parameters: IN [pWorkQueue] -- Work queue
  26. //
  27. // Return: TRUE if successful
  28. // FALSE if not
  29. //
  30. // History: 07-17-97 BrianTa Created
  31. //
  32. //*************************************************************
  33. BOOL
  34. TSrvInitWorkQueue(IN PWORKQUEUE pWorkQueue)
  35. {
  36. BOOL fSuccess;
  37. TRACE((DEBUG_TSHRSRV_FLOW,
  38. "TShrSRV: TSrvInitWorkQueue entry\n"));
  39. fSuccess = TRUE;
  40. if (pWorkQueue == NULL)
  41. pWorkQueue = &g_MainWorkQueue;
  42. pWorkQueue->pHead = NULL;
  43. pWorkQueue->pTail = NULL;
  44. if (RtlInitializeCriticalSection(&pWorkQueue->cs) == STATUS_SUCCESS) {
  45. // Create a worker event to be used to signal that
  46. // a new work item has been placed in the queue
  47. pWorkQueue->hWorkEvent = CreateEvent(NULL, // security attributes
  48. FALSE, // manual-reset event
  49. FALSE, // initial state
  50. NULL); // pointer to event-object name
  51. if (pWorkQueue->hWorkEvent == NULL)
  52. {
  53. TRACE((DEBUG_TSHRSRV_WARN,
  54. "TShrSRV: Can't allocate hWorkEvent - 0x%x\n",
  55. GetLastError()));
  56. fSuccess = FALSE;
  57. }
  58. }
  59. else {
  60. TRACE((DEBUG_TSHRSRV_WARN,
  61. "TShrSRV: Can't initialize pWorkQueue->cs\n"));
  62. fSuccess = FALSE;
  63. }
  64. TRACE((DEBUG_TSHRSRV_FLOW,
  65. "TShrSRV: TSrvInitWorkQueue exit - 0x%x\n", fSuccess));
  66. return (fSuccess);
  67. }
  68. //*************************************************************
  69. //
  70. // TSrvFreeWorkQueue()
  71. //
  72. // Purpose: Frees the given work queue
  73. //
  74. // Parameters: IN [pWorkQueue] -- Work queue
  75. //
  76. // Return: void
  77. //
  78. // History: 07-17-97 BrianTa Created
  79. //
  80. //*************************************************************
  81. void
  82. TSrvFreeWorkQueue(IN PWORKQUEUE pWorkQueue)
  83. {
  84. TRACE((DEBUG_TSHRSRV_FLOW,
  85. "TShrSRV: TSrvFreeWorkQueue entry\n"));
  86. if (pWorkQueue == NULL)
  87. pWorkQueue = &g_MainWorkQueue;
  88. EnterCriticalSection(&pWorkQueue->cs);
  89. // We should not have any work items in the queue
  90. TS_ASSERT(pWorkQueue->pHead == NULL);
  91. // Release the worker event
  92. if (pWorkQueue->hWorkEvent)
  93. {
  94. CloseHandle(pWorkQueue->hWorkEvent);
  95. pWorkQueue->hWorkEvent = NULL;
  96. }
  97. LeaveCriticalSection(&pWorkQueue->cs);
  98. TRACE((DEBUG_TSHRSRV_FLOW,
  99. "TShrSRV: TSrvFreeWorkQueue exit\n"));
  100. }
  101. //*************************************************************
  102. //
  103. // TSrvWaitForWork()
  104. //
  105. // Purpose: Called by the work queue processing routine
  106. // to wait for posted work
  107. //
  108. // Parameters: IN [pWorkQueue] -- Work queue
  109. //
  110. // Return: void
  111. //
  112. // History: 07-17-97 BrianTa Created
  113. //
  114. //*************************************************************
  115. void
  116. TSrvWaitForWork(IN PWORKQUEUE pWorkQueue)
  117. {
  118. MSG msg;
  119. DWORD rc;
  120. TRACE((DEBUG_TSHRSRV_FLOW,
  121. "TShrSRV: TSrvWaitForWork entry\n"));
  122. if (pWorkQueue == NULL)
  123. pWorkQueue = &g_MainWorkQueue;
  124. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Waiting for work\n"));
  125. // FUTURE: PeekMessage mechanism ultimately needs removed when event based
  126. // callback is instrumented in GCC.
  127. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  128. {
  129. TranslateMessage(&msg);
  130. DispatchMessage(&msg);
  131. }
  132. else
  133. {
  134. // FUTURE: Add another object to the "wait" when GCC callback
  135. // mechanism is changed
  136. rc = MsgWaitForMultipleObjects(1,
  137. &pWorkQueue->hWorkEvent,
  138. FALSE,
  139. INFINITE,
  140. QS_ALLINPUT);
  141. if (rc != WAIT_OBJECT_0 &&
  142. rc != WAIT_OBJECT_0 + 1)
  143. {
  144. TRACE((DEBUG_TSHRSRV_ERROR,
  145. "TShrSRV: TSrvWaitForWork default case hit. rc 0x%x, GLE 0x%x\n",
  146. rc, GetLastError()));
  147. }
  148. }
  149. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Revived for work\n"));
  150. TRACE((DEBUG_TSHRSRV_FLOW,
  151. "TShrSRV: TSrvWaitForWork exit\n"));
  152. }
  153. //*************************************************************
  154. //
  155. // TSrvWorkToDo()
  156. //
  157. // Purpose: Determines if there is work to do
  158. //
  159. // Parameters: IN [pWorkQueue] -- Work queue
  160. //
  161. // Return: TRUE if successful
  162. // FALSE if not
  163. //
  164. // History: 07-17-97 BrianTa Created
  165. //
  166. //*************************************************************
  167. BOOL
  168. TSrvWorkToDo(IN PWORKQUEUE pWorkQueue)
  169. {
  170. if (pWorkQueue == NULL)
  171. pWorkQueue = &g_MainWorkQueue;
  172. return (pWorkQueue->pHead ? TRUE : FALSE);
  173. }
  174. //*************************************************************
  175. //
  176. // TSrvDoWork()
  177. //
  178. // Purpose: Processes work queue items
  179. //
  180. // Parameters: IN [pWorkQueue] -- Work queue
  181. //
  182. // Return: TRUE if successful
  183. // FALSE if not
  184. //
  185. // History: 07-17-97 BrianTa Created
  186. //
  187. //*************************************************************
  188. BOOL
  189. TSrvDoWork(IN PWORKQUEUE pWorkQueue)
  190. {
  191. PWORKITEM pWorkItem;
  192. BOOL fSuccess;
  193. TRACE((DEBUG_TSHRSRV_FLOW,
  194. "TShrSRV: TSrvDoWork entry\n"));
  195. fSuccess = FALSE;
  196. if (pWorkQueue == NULL)
  197. pWorkQueue = &g_MainWorkQueue;
  198. pWorkItem = TSrvDequeueWorkItem(pWorkQueue);
  199. // If we were able to dequeue a workitem, then (if defined) call
  200. // out to supplied worker routine to process the item
  201. if (pWorkItem)
  202. {
  203. if (pWorkItem->pfnCallout)
  204. {
  205. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Performing work callout\n"));
  206. (*pWorkItem->pfnCallout)(pWorkItem);
  207. }
  208. // Done with the work item
  209. TSrvFreeWorkItem(pWorkItem);
  210. fSuccess = TRUE;
  211. }
  212. TRACE((DEBUG_TSHRSRV_FLOW,
  213. "TShrSRV: TSrvDoWork exit - 0x%x\n", fSuccess));
  214. return (fSuccess);
  215. }
  216. //*************************************************************
  217. //
  218. // TSrvEnqueueWorkItem()
  219. //
  220. // Purpose: Enqueues a work item to a work queue
  221. //
  222. // Parameters: IN [pWorkQueue] -- Work queue
  223. // IN [pWorkItem] -- Work item
  224. // IN [pfnCallout] -- Worker callout
  225. // IN [ulParam] -- Worker callout param
  226. //
  227. // Return: TRUE if successful
  228. // FALSE if not
  229. //
  230. // History: 07-17-97 BrianTa Created
  231. //
  232. //*************************************************************
  233. BOOL
  234. TSrvEnqueueWorkItem(IN PWORKQUEUE pWorkQueue,
  235. IN PWORKITEM pWorkItem,
  236. IN PFI_WI_CALLOUT pfnCallout,
  237. IN ULONG ulParam)
  238. {
  239. BOOL fPosted;
  240. TRACE((DEBUG_TSHRSRV_FLOW,
  241. "TShrSRV: TSrvEnqueueWorkItem entry\n"));
  242. if (pWorkQueue == NULL)
  243. pWorkQueue = &g_MainWorkQueue;
  244. fPosted = FALSE;
  245. pWorkItem->pNext = NULL;
  246. pWorkItem->ulParam = ulParam;
  247. pWorkItem->pfnCallout = pfnCallout;
  248. EnterCriticalSection(&pWorkQueue->cs);
  249. // Add the workitem on the tail of the workqueue and
  250. // then signal the queue processing thread to wake up
  251. // and process the item
  252. if (pWorkQueue->hWorkEvent)
  253. {
  254. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Workitem enqueued\n"));
  255. fPosted = TRUE;
  256. if (pWorkQueue->pHead != NULL)
  257. pWorkQueue->pTail->pNext = pWorkItem;
  258. else
  259. pWorkQueue->pHead = pWorkItem;
  260. pWorkQueue->pTail = pWorkItem;
  261. SetEvent(pWorkQueue->hWorkEvent);
  262. }
  263. LeaveCriticalSection(&pWorkQueue->cs);
  264. TRACE((DEBUG_TSHRSRV_FLOW,
  265. "TShrSRV: TSrvEnqueueWorkItem exit - 0x%x\n", fPosted));
  266. return (fPosted);
  267. }
  268. //*************************************************************
  269. //
  270. // TSrvDequeueWorkItem()
  271. //
  272. // Purpose: Dequeues a work item from a work queue
  273. //
  274. // Parameters: IN [pTSrvInfo] -- TSrv instance object
  275. // IN [ulReason] -- Reason for disconnection
  276. //
  277. // Return: Ptr to dequeued work item if successful
  278. // NULL if not
  279. //
  280. // History: 07-17-97 BrianTa Created
  281. //
  282. //*************************************************************
  283. PWORKITEM
  284. TSrvDequeueWorkItem(IN PWORKQUEUE pWorkQueue)
  285. {
  286. PWORKITEM pWorkItem;
  287. TRACE((DEBUG_TSHRSRV_FLOW,
  288. "TShrSRV: TSrvDequeueWorkItem entry\n"));
  289. if (pWorkQueue == NULL)
  290. pWorkQueue = &g_MainWorkQueue;
  291. EnterCriticalSection(&pWorkQueue->cs);
  292. // If there is an item in the queue, remove it and
  293. // return it to the caller
  294. pWorkItem = pWorkQueue->pHead;
  295. if (pWorkItem)
  296. {
  297. pWorkQueue->pHead = pWorkItem->pNext;
  298. if (pWorkQueue->pHead == NULL)
  299. pWorkQueue->pTail = NULL;
  300. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Workitem dequeued\n"));
  301. }
  302. LeaveCriticalSection(&pWorkQueue->cs);
  303. if (pWorkItem)
  304. TS_ASSERT(pWorkItem->CheckMark == TSRVWORKITEM_CHECKMARK);
  305. TRACE((DEBUG_TSHRSRV_FLOW,
  306. "TShrSRV: TSrvDequeueWorkItem exit - %p\n", pWorkItem));
  307. return (pWorkItem);
  308. }
  309. //*************************************************************
  310. //
  311. // TSrvAllocWorkItem()
  312. //
  313. // Purpose: Allocates a new workitem
  314. //
  315. // Parameters: IN [pTSrvInfo] -- TSrv instance object
  316. //
  317. // Return: Ptr to dequeued work item if successful
  318. // NULL if not
  319. //
  320. // History: 07-17-97 BrianTa Created
  321. //
  322. //*************************************************************
  323. PWORKITEM
  324. TSrvAllocWorkItem(IN PTSRVINFO pTSrvInfo)
  325. {
  326. PWORKITEM pWorkItem;
  327. TRACE((DEBUG_TSHRSRV_FLOW,
  328. "TShrSRV: TSrvAllocWorkItem entry\n"));
  329. pWorkItem = TSHeapAlloc(HEAP_ZERO_MEMORY,
  330. sizeof(WORKITEM),
  331. TS_HTAG_TSS_WORKITEM);
  332. if (pWorkItem)
  333. {
  334. pWorkItem->pTSrvInfo = pTSrvInfo;
  335. #if DBG
  336. pWorkItem->CheckMark = TSRVWORKITEM_CHECKMARK;
  337. #endif
  338. TSrvReferenceInfo(pTSrvInfo);
  339. }
  340. TRACE((DEBUG_TSHRSRV_FLOW,
  341. "TShrSRV: TSrvAllocWorkItem exit - %p\n", pWorkItem));
  342. return (pWorkItem);
  343. }
  344. //*************************************************************
  345. //
  346. // TSrvFreeWorkItem()
  347. //
  348. // Purpose: Frees the given workitem
  349. //
  350. // Parameters: IN [pWorkItem] -- Workitem
  351. //
  352. // Return: void
  353. //
  354. // History: 07-17-97 BrianTa Created
  355. //
  356. //*************************************************************
  357. void
  358. TSrvFreeWorkItem(IN PWORKITEM pWorkItem)
  359. {
  360. TRACE((DEBUG_TSHRSRV_FLOW,
  361. "TShrSRV: TSrvFreeWorkItem entry\n"));
  362. TS_ASSERT(pWorkItem);
  363. TS_ASSERT(pWorkItem->pTSrvInfo);
  364. TSrvDereferenceInfo(pWorkItem->pTSrvInfo);
  365. TShareFree(pWorkItem);
  366. TRACE((DEBUG_TSHRSRV_FLOW,
  367. "TShrSRV: TSrvFreeWorkItem exit\n"));
  368. }