Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

thread.c

Go to the documentation of this file.
00001 /*
00002  *  This program is free software; you can redistribute it and/or
00003  *  modify it under the terms of the GNU General Public License
00004  *  as published by the Free Software Foundation; either version
00005  *  2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 2004 Spiro Trikaliotis
00008  *
00009  */
00010 
00020 #include <wdm.h>
00021 #include "cbm_driver.h"
00022 
00034 NTSTATUS
00035 cbm_start_thread(IN PDEVICE_EXTENSION Pdx)
00036 {
00037     NTSTATUS ntStatus;
00038     PDEVICE_OBJECT fdo;
00039 
00040     FUNC_ENTER();
00041 
00042     DBG_ASSERT(Pdx != NULL);
00043 
00044     // get the FDO out of the PDX
00045 
00046     fdo = Pdx->Fdo;
00047 
00048     DBG_ASSERT(fdo != NULL);
00049 
00050     // The ThreadHandle as well as the thread object pointer should be
00051     // 0. If not, it means that the thread has already been started.
00052 
00053     DBG_ASSERT(Pdx->ThreadHandle == 0);
00054     DBG_ASSERT(Pdx->Thread == 0);
00055 
00056     PERF_EVENT_THREAD_START_SCHED();
00057 
00058     // The thread should not be quit yet.
00060 
00061     Pdx->QuitThread = FALSE;
00062 
00063     // Create the thread that will execute our IRPs
00064 
00065     DBG_IRQL( == PASSIVE_LEVEL);
00066     ntStatus = PsCreateSystemThread(&Pdx->ThreadHandle,
00067         THREAD_ALL_ACCESS, // Desired access
00068         NULL,              // No object attributes
00069         NULL,              // which process should the thread belong to?
00070         NULL,              // Client ID
00071         cbm_thread,        // the routine to be started
00072         Pdx);              // context value for the thread
00073 
00074     if (!NT_SUCCESS(ntStatus))
00075     {
00076         // The thread could not been started, make sure this is logged
00077 
00078         DBG_ERROR((DBG_PREFIX "Creation of system thread FAILED, deleting device"));
00079         LogErrorString(fdo, CBM_START_FAILED, L"creation of the system thread.", NULL);
00080     }
00081     else
00082     {
00083         // Find out the thread object pointer, which is needed
00084         // for setting the thread priority. Furthermore, as we have
00085         // referenced the object, the driver will refuse to be unloaded
00086         // until the object is dereferenced.
00087 
00088         DBG_IRQL( == PASSIVE_LEVEL);
00089         ObReferenceObjectByHandle(Pdx->ThreadHandle,
00090             THREAD_ALL_ACCESS, NULL, KernelMode, &Pdx->Thread, NULL);
00091 
00092         DBG_ASSERT(Pdx->Thread);
00093 
00094         if (Pdx->Thread)
00095         {
00096             // Set the priority of the thread to a realtime priority.
00097 
00098             DBG_IRQL( == PASSIVE_LEVEL);
00099             KeSetPriorityThread(Pdx->Thread, LOW_REALTIME_PRIORITY);
00100         }
00101     }
00102 
00103     FUNC_LEAVE_NTSTATUS(ntStatus);
00104 }
00105 
00117 VOID
00118 cbm_stop_thread(IN PDEVICE_EXTENSION Pdx)
00119 {
00120     FUNC_ENTER();
00121 
00122     DBG_ASSERT(Pdx != NULL);
00123     DBG_ASSERT(Pdx->QuitThread == FALSE);
00124     DBG_ASSERT(Pdx->ThreadHandle != 0);
00125     DBG_ASSERT(Pdx->Thread != 0);
00126 
00127     if ((Pdx->ThreadHandle != 0) && (Pdx->Thread != 0))
00128     {
00129         PERF_EVENT_THREAD_STOP_SCHED();
00130 
00131         // Signal the thread that it should QUIT
00132 
00133         Pdx->QuitThread = TRUE;
00134 
00135         // Wake up the thread so it can process the signalled QUIT event
00136 
00137         QueueSignal(&Pdx->IrpQueue);
00138 
00139         // Now, wait until the thread has been stopped
00140 
00141         KeWaitForSingleObject(Pdx->Thread, Executive, KernelMode, FALSE, NULL);
00142 
00143         // We're done, we do not need the thread's handle or object anymore
00144 
00145         ObDereferenceObject(Pdx->Thread);
00146         ZwClose(Pdx->ThreadHandle);
00147 
00148         // Mark that we do not have a thread anymore
00149 
00150         Pdx->Thread = NULL;
00151         Pdx->ThreadHandle = 0;
00152     }
00153 
00154     FUNC_LEAVE();
00155 }
00156 
00165 VOID
00166 cbm_thread(IN PVOID Context)
00167 {
00168     PDEVICE_EXTENSION pdx;
00169     NTSTATUS ntStatus;
00170 
00171     FUNC_ENTER();
00172 
00173     PERF_EVENT_THREAD_START_EXEC();
00174 
00175     // get the device extension
00176 
00177     pdx = Context;
00178 
00179     // If we are immediately quit, make sure we report STATUS_SUCCESS
00180 
00181     ntStatus = STATUS_SUCCESS;
00182 
00183     // As long as we do not have to quit the thread, poll the QUEUE
00184 
00185     while (!pdx->QuitThread)
00186     {
00187         PERF_EVENT_THREAD_POLL();
00188 
00189         // Poll the QUEUE object and execute the IRP (if any)
00190 
00191         ntStatus = QueuePoll(&pdx->IrpQueue, pdx->Fdo);
00192     }
00193 
00194     PERF_EVENT_THREAD_STOP_EXEC();
00195 
00196     // Termine the thread
00197 
00198     DBG_IRQL( == PASSIVE_LEVEL);
00199     PsTerminateSystemThread(ntStatus);
00200 
00201     FUNC_LEAVE();
00202 }

Generated on Sun Apr 30 18:45:59 2006 for opencbm by  doxygen 1.4.2