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.

365 lines
10 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: thread.c
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // This file contains functions associated with ParClass worker threads
  12. //
  13. #include "pch.h"
  14. #include "readwrit.h"
  15. VOID
  16. ParallelThread(
  17. IN PVOID Context
  18. )
  19. /*++
  20. Routine Description:
  21. This is the parallel thread routine. Loops performing I/O operations.
  22. Arguments:
  23. Context -- Really the extension
  24. Return Value:
  25. None
  26. --*/
  27. {
  28. PDEVICE_EXTENSION Extension;
  29. LONG ThreadPriority;
  30. KIRQL OldIrql;
  31. NTSTATUS Status;
  32. LARGE_INTEGER Timeout;
  33. PIRP CurrentIrp;
  34. BOOLEAN bRetry = TRUE; // REVISIT, dvrh's big usbly hack.
  35. Extension = Context;
  36. ParDumpV( ("Enter ParallelThread(...) - %wZ\r\n",
  37. &Extension->SymbolicLinkName) );
  38. //
  39. // Lower ourselves down just at tad so that we compete a
  40. // little less.
  41. //
  42. // If the registry indicates we should be running at the old
  43. // priority, don't lower our priority as much.
  44. //
  45. ThreadPriority = -2;
  46. if(Extension->UseNT35Priority) {
  47. ThreadPriority = -1;
  48. }
  49. // dvtw,
  50. // dvrh Wants higher prioroity on threads.
  51. #if 0
  52. ThreadPriority = 16;
  53. KeSetBasePriorityThread(
  54. KeGetCurrentThread(),
  55. ThreadPriority
  56. );
  57. #endif
  58. do {
  59. Timeout = Extension->IdleTimeout;
  60. // Timeout = - (250*10*1000);
  61. // dvdr we try to aquire this twice after we have locked the port
  62. // when we try to unlock the port this gets called also and we already have
  63. // mutex so we hang
  64. // ExAcquireFastMutex (&Extension->LockPortMutex);
  65. ParallelThread_WaitRetry:
  66. Status = KeWaitForSingleObject(
  67. &Extension->RequestSemaphore,
  68. UserRequest,
  69. KernelMode,
  70. FALSE,
  71. &Timeout
  72. );
  73. // dvdr
  74. // ExReleaseFastMutex (&Extension->LockPortMutex);
  75. if (Status == STATUS_TIMEOUT) {
  76. if ((TRUE == Extension->P12843DL.bEventActive) ) {
  77. if (ParHaveReadData(Extension)) {
  78. ParDump2(PARINFO, ("ParallelThread: Signaling Event [%x]\n", Extension->P12843DL.Event) );
  79. // D D(("-- thread::timeout - set event\n"));
  80. KeSetEvent(Extension->P12843DL.Event, 0, FALSE);
  81. ParDump2(PARINFO, ("ParallelThread: Event was signaled\n") );
  82. }
  83. }
  84. // dvrh's big ugly hack
  85. if (Extension->IsCritical) {
  86. ParDumpV( ("We're critical and want to terminate threads\n") );
  87. if (bRetry) {
  88. ParDumpV( ("Gonna give the thread more time\n") );
  89. bRetry = FALSE;
  90. goto ParallelThread_WaitRetry;
  91. }
  92. ParDumpV( ("Gonna hose our periph since we're killing threads\n") );
  93. // __asm int 3
  94. }
  95. // dvrh, Test hypothesis of potential port contention problems between
  96. // spooler and those going through.
  97. // if (!Extension->Connected)
  98. if (Extension->QueryNumWaiters(Extension->PortContext) != 0)
  99. {
  100. #define PAR_USE_TERMINATE_FUNCTION 1
  101. #if PAR_USE_TERMINATE_FUNCTION
  102. ParTerminate(Extension);
  103. #else
  104. if (afpForward[Extension->IdxForwardProtocol].fnDisconnect)
  105. {
  106. ParDump2(PARINFO, ("ParallelThread: STATUS_TIMEOUT: Calling afpForward.fnDisconnect\r\n"));
  107. afpForward[Extension->IdxForwardProtocol].fnDisconnect (Extension);
  108. }
  109. #endif
  110. ParFreePort(Extension);
  111. continue;
  112. }
  113. }
  114. // wait here if PnP has paused us (e.g., QUERY_STOP, STOP, QUERY_REMOVE)
  115. KeWaitForSingleObject(&Extension->PauseEvent, Executive, KernelMode, FALSE, 0);
  116. if ( Extension->TimeToTerminateThread ) {
  117. //
  118. // If we are currently connected...disconnect.
  119. //
  120. if (Extension->Connected) {
  121. #if PAR_USE_TERMINATE_FUNCTION
  122. ParTerminate(Extension);
  123. #else
  124. if (afpForward[Extension->IdxForwardProtocol].fnDisconnect)
  125. {
  126. ParDump2(PARINFO, ("ParallelThread: TimeToTerminateThread: Calling afpForward.fnDisconnect\r\n"));
  127. afpForward[Extension->IdxForwardProtocol].fnDisconnect (Extension);
  128. }
  129. #endif
  130. ParFreePort(Extension);
  131. }
  132. ParDumpV( ( "%wZ thread killing self\r\n", &Extension->SymbolicLinkName) );
  133. PsTerminateSystemThread( STATUS_SUCCESS );
  134. }
  135. //
  136. // While we are manipulating the queue we capture the
  137. // cancel spin lock.
  138. //
  139. IoAcquireCancelSpinLock(&OldIrql);
  140. ASSERT(!Extension->CurrentOpIrp);
  141. while (!IsListEmpty(&Extension->WorkQueue)) {
  142. // get next IRP from our list of work items
  143. PLIST_ENTRY HeadOfList;
  144. HeadOfList = RemoveHeadList(&Extension->WorkQueue);
  145. CurrentIrp = CONTAINING_RECORD(HeadOfList, IRP, Tail.Overlay.ListEntry);
  146. // we have started processing, this IRP can no longer be cancelled
  147. IoSetCancelRoutine(CurrentIrp, NULL);
  148. ASSERT(NULL == CurrentIrp->CancelRoutine);
  149. ASSERT(!CurrentIrp->Cancel);
  150. Extension->CurrentOpIrp = CurrentIrp;
  151. IoReleaseCancelSpinLock(OldIrql);
  152. //
  153. // Do the Io.
  154. //
  155. ParStartIo(Extension);
  156. if ((TRUE == Extension->P12843DL.bEventActive) && (ParHaveReadData(Extension))) {
  157. ParDump2(PARINFO, ("ParallelThread: Signaling Event [%x]\n", Extension->P12843DL.Event) );
  158. ASSERT(Extension->P12843DL.Event);
  159. KeSetEvent(Extension->P12843DL.Event, 0, FALSE);
  160. ParDump2(PARINFO, ("ParallelThread: Event was signaled\n") );
  161. }
  162. // wait here if PnP has paused us (e.g., QUERY_STOP, STOP, QUERY_REMOVE)
  163. KeWaitForSingleObject(&Extension->PauseEvent, Executive, KernelMode, FALSE, 0);
  164. IoAcquireCancelSpinLock(&OldIrql);
  165. }
  166. IoReleaseCancelSpinLock(OldIrql);
  167. } while (TRUE);
  168. }
  169. NTSTATUS
  170. ParCreateSystemThread(
  171. PDEVICE_EXTENSION Extension
  172. )
  173. {
  174. NTSTATUS Status;
  175. HANDLE ThreadHandle;
  176. OBJECT_ATTRIBUTES objAttrib;
  177. ParDump2(PARTHREAD, ("Enter ParCreateSystemThread(...)\r\n") );
  178. //
  179. // Start the thread and capture the thread handle into the extension
  180. //
  181. InitializeObjectAttributes( &objAttrib, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );
  182. Status = PsCreateSystemThread( &ThreadHandle, THREAD_ALL_ACCESS, &objAttrib, NULL, NULL,
  183. ParallelThread, Extension );
  184. if (!NT_ERROR(Status)) {
  185. //
  186. // We've got the thread. Now get a pointer to it.
  187. //
  188. // assert that this DO does not already have a thread
  189. ASSERT(!Extension->ThreadObjectPointer);
  190. Status = ObReferenceObjectByHandle( ThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode,
  191. &Extension->ThreadObjectPointer, NULL );
  192. if (NT_ERROR(Status)) {
  193. ParDump2(PARTHREAD, ("Bad status on open from ref by handle: %x\r\n", Status) );
  194. Extension->TimeToTerminateThread = TRUE;
  195. KeReleaseSemaphore( &Extension->RequestSemaphore, 0, 1, FALSE );
  196. } else {
  197. //
  198. // Now that we have a reference to the thread
  199. // we can simply close the handle.
  200. //
  201. ZwClose(ThreadHandle);
  202. }
  203. } else {
  204. ParDump2(PARTHREAD, ("Bad status on open from ref by handle: %x\r\n", Status) );
  205. }
  206. return Status;
  207. }
  208. VOID
  209. ParStartIo(
  210. IN PDEVICE_EXTENSION Extension
  211. )
  212. /*++
  213. Routine Description:
  214. This routine starts an I/O operation for the driver and
  215. then returns
  216. Arguments:
  217. Extension - The parallel device extension
  218. Return Value:
  219. None
  220. --*/
  221. {
  222. PIRP Irp;
  223. PIO_STACK_LOCATION IrpSp;
  224. KIRQL CancelIrql;
  225. NTSTATUS NtStatus;
  226. // ParDumpV( ("Enter ParStartIo\r\n") );
  227. Irp = Extension->CurrentOpIrp;
  228. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  229. Irp->IoStatus.Information = 0;
  230. if (!Extension->Connected && !ParAllocPort(Extension)) {
  231. #pragma message( "dvrh Left bad stuff in thread.c")
  232. ParDump2(PARTHREAD, ("Threads are hosed\n") );
  233. // __asm int 3
  234. //
  235. // If the allocation didn't succeed then fail this IRP.
  236. //
  237. goto CompleteIrp;
  238. }
  239. switch (IrpSp->MajorFunction) {
  240. case IRP_MJ_WRITE:
  241. ParDump2(PARTHREAD, ("ParStartIo: IRP \t[%x]\t Calling ParWriteIrp\n", Irp) );
  242. ParTimerMainCheck( ("SIo: IRP \t[%x]\t Pre WrtIrp\r\n", Irp) );
  243. Extension->IsCritical = TRUE;
  244. ParWriteIrp(Extension);
  245. Extension->IsCritical = FALSE;
  246. ParTimerMainCheck( ("SIo: IRP \t[%x]\t Post WrtIrp\r\n", Irp) );
  247. break;
  248. case IRP_MJ_READ:
  249. ParDump2(PARTHREAD, ("ParStartIo: IRP \t[%x]\t Calling ParReadIrp\n", Irp) );
  250. ParTimerMainCheck( ("SIo: IRP \t[%x]\t Pre RdIrp\r\n", Irp) );
  251. Extension->IsCritical = TRUE;
  252. ParReadIrp(Extension);
  253. Extension->IsCritical = FALSE;
  254. ParTimerMainCheck( ("SIo: IRP \t[%x]\t Post RdIrp\r\n", Irp) );
  255. break;
  256. default:
  257. ParDump2(PARTHREAD, ("ParStartIo: IRP \t[%x]\t Calling ParDeviceIo\n", Irp) );
  258. ParTimerMainCheck( ("SIo: IRP \t[%x]\t Pre DevIo\r\n", Irp) );
  259. ParDeviceIo(Extension);
  260. ParTimerMainCheck( ("SIo: IRP \t[%x]\t Post DevIo\r\n", Irp) );
  261. break;
  262. }
  263. if (!Extension->Connected && !Extension->AllocatedByLockPort) {
  264. // if we're not connected in a 1284 mode, then release host port
  265. // otherwise let the watchdog timer do it.
  266. ParFreePort(Extension);
  267. }
  268. CompleteIrp:
  269. IoAcquireCancelSpinLock(&CancelIrql);
  270. Extension->CurrentOpIrp = NULL;
  271. IoReleaseCancelSpinLock(CancelIrql);
  272. ParCompleteRequest(Irp, (CCHAR)(NT_SUCCESS(Irp->IoStatus.Status) ?
  273. IO_PARALLEL_INCREMENT : IO_NO_INCREMENT));
  274. return;
  275. }