OpenCBM
thread.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2004 Spiro Trikaliotis
8  *
9  */
10 
19 #include <wdm.h>
20 #include "cbm_driver.h"
21 
33 NTSTATUS
34 cbm_start_thread(IN PDEVICE_EXTENSION Pdx)
35 {
36  NTSTATUS ntStatus;
37  PDEVICE_OBJECT fdo;
38 
39  FUNC_ENTER();
40 
41  DBG_ASSERT(Pdx != NULL);
42 
43  // get the FDO out of the PDX
44 
45  fdo = Pdx->Fdo;
46 
47  DBG_ASSERT(fdo != NULL);
48 
49  // The ThreadHandle as well as the thread object pointer should be
50  // 0. If not, it means that the thread has already been started.
51 
52  DBG_ASSERT(Pdx->ThreadHandle == 0);
53  DBG_ASSERT(Pdx->Thread == 0);
54 
56 
57  // The thread should not be quit yet.
59 
60  Pdx->QuitThread = FALSE;
61 
62  // Create the thread that will execute our IRPs
63 
64  DBG_IRQL( == PASSIVE_LEVEL);
65  ntStatus = PsCreateSystemThread(&Pdx->ThreadHandle,
66  THREAD_ALL_ACCESS, // Desired access
67  NULL, // No object attributes
68  NULL, // which process should the thread belong to?
69  NULL, // Client ID
70  cbm_thread, // the routine to be started
71  Pdx); // context value for the thread
72 
73  if (!NT_SUCCESS(ntStatus))
74  {
75  // The thread could not been started, make sure this is logged
76 
77  DBG_ERROR((DBG_PREFIX "Creation of system thread FAILED, deleting device"));
78  LogErrorString(fdo, CBM_START_FAILED, L"creation of the system thread.", NULL);
79  }
80  else
81  {
82  // Find out the thread object pointer, which is needed
83  // for setting the thread priority. Furthermore, as we have
84  // referenced the object, the driver will refuse to be unloaded
85  // until the object is dereferenced.
86 
87  DBG_IRQL( == PASSIVE_LEVEL);
88  ObReferenceObjectByHandle(Pdx->ThreadHandle,
89  THREAD_ALL_ACCESS, NULL, KernelMode, &Pdx->Thread, NULL);
90 
91  DBG_ASSERT(Pdx->Thread);
92 
93  if (Pdx->Thread)
94  {
95  // Set the priority of the thread to a realtime priority.
96 
97  DBG_IRQL( == PASSIVE_LEVEL);
98  KeSetPriorityThread(Pdx->Thread, LOW_REALTIME_PRIORITY);
99  }
100  }
101 
102  FUNC_LEAVE_NTSTATUS(ntStatus);
103 }
104 
116 VOID
117 cbm_stop_thread(IN PDEVICE_EXTENSION Pdx)
118 {
119  FUNC_ENTER();
120 
121  DBG_ASSERT(Pdx != NULL);
122  DBG_ASSERT(Pdx->QuitThread == FALSE);
123  DBG_ASSERT(Pdx->ThreadHandle != 0);
124  DBG_ASSERT(Pdx->Thread != 0);
125 
126  if ((Pdx->ThreadHandle != 0) && (Pdx->Thread != 0))
127  {
129 
130  // Signal the thread that it should QUIT
131 
132  Pdx->QuitThread = TRUE;
133 
134  // Wake up the thread so it can process the signalled QUIT event
135 
136  QueueSignal(&Pdx->IrpQueue);
137 
138  // Now, wait until the thread has been stopped
139 
140  KeWaitForSingleObject(Pdx->Thread, Executive, KernelMode, FALSE, NULL);
141 
142  // We're done, we do not need the thread's handle or object anymore
143 
144  ObDereferenceObject(Pdx->Thread);
145  ZwClose(Pdx->ThreadHandle);
146 
147  // Mark that we do not have a thread anymore
148 
149  Pdx->Thread = NULL;
150  Pdx->ThreadHandle = 0;
151  }
152 
153  FUNC_LEAVE();
154 }
155 
164 VOID
165 cbm_thread(IN PVOID Context)
166 {
167  PDEVICE_EXTENSION pdx;
168  NTSTATUS ntStatus;
169 
170  FUNC_ENTER();
171 
173 
174  // get the device extension
175 
176  pdx = Context;
177 
178  // If we are immediately quit, make sure we report STATUS_SUCCESS
179 
180  ntStatus = STATUS_SUCCESS;
181 
182  // As long as we do not have to quit the thread, poll the QUEUE
183 
184  while (!pdx->QuitThread)
185  {
187 
188  // Poll the QUEUE object and execute the IRP (if any)
189 
190  ntStatus = QueuePoll(&pdx->IrpQueue, pdx->Fdo);
191  }
192 
194 
195  // Termine the thread
196 
197  DBG_IRQL( == PASSIVE_LEVEL);
198  PsTerminateSystemThread(ntStatus);
199 
200  FUNC_LEAVE();
201 }
#define LogErrorString(_Fdo_, _UniqueErrorValue_, _String1_, _String2_)
Definition: util.h:39
#define PERF_EVENT_THREAD_START_EXEC()
Definition: cbm_driver.h:70
#define PERF_EVENT_THREAD_POLL()
Definition: cbm_driver.h:72
#define PERF_EVENT_THREAD_STOP_EXEC()
Definition: cbm_driver.h:76
NTSTATUS cbm_start_thread(IN PDEVICE_EXTENSION Pdx)
Start the worker thread.
Definition: thread.c:34
#define FUNC_LEAVE()
Definition: debug.h:349
NTSTATUS QueuePoll(PQUEUE Queue, PDEVICE_OBJECT Fdo)
Poll the QUEUE.
Definition: queue.c:816
#define PERF_EVENT_THREAD_START_SCHED()
Definition: cbm_driver.h:68
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define DBG_ERROR(_xxx)
Definition: debug.h:397
VOID cbm_thread(IN PVOID Context)
The thread function.
Definition: thread.c:165
#define PERF_EVENT_THREAD_STOP_SCHED()
Definition: cbm_driver.h:74
NTSTATUS QueueSignal(PQUEUE Queue)
Signal to the QUEUE need for processing.
Definition: queue.c:900
#define FUNC_ENTER()
Definition: debug.h:347
Definitions for the opencbm driver.
#define DBG_PREFIX
Definition: debug.h:320
VOID cbm_stop_thread(IN PDEVICE_EXTENSION Pdx)
Stop the worker thread.
Definition: thread.c:117