Hello, all.

I'm having a strange problem in my WDM driver. I'm using a kernel
thread to check something at 100 mS intervals with a KTIMER. The timer
is allocated from the nonpaged pool when the thread starts and freed
before it is terminated, and the thread itself runs for a second or more.
For some unknown reason, I started getting a 0xC2 bugcheck under
Windows 2K after about four executions of the thread. I'm only
deallocating the KTIMER once at the end of the thread, but since 0xC2
can be generated by double deallocations, I decided to see if the
bugcheck was occurring because I was allocating and deallocating the
KTIMER every time the thread executed. I changed the driver so that the
KTIMER was allocated when the device was created and deallocated when
the device was removed, and when I did that the 0xC2 bugcheck turned
into a 0x0A bugcheck.
The kicker is this: I changed the driver back to its original
state except that I left a declaration for a KTIMER pointer in my device
extension--that is, there is space for a KTIMER pointer in the device
extension, but it is unused--and I still get the 0x0A bugcheck. If I
take the declaration out, the bugcheck changes back to 0xC2.
One final note is this. The 0x0A exception is occurring inside of
KeWaitForSingleObject(), which is what I'm using to wait for the thread
to end under Win2K. 0x0A means something is ocurring at the wrong IRQL,
and when the exception occurs the IRQL is 2--DISPATCH_LEVEL. Just
before KeWaitForSingleObject() is called, I did a KdPrint() that showed
the IRQL as 1--APC_LEVEL.
Has anyone run into a problem like this, or does anyone have any
ideas? Thanks.

Mike

Mike McCully
mmccully@ionwerks.com

Re: Weird Exception by Calvin

Calvin
Thu Jun 24 12:01:19 CDT 2004

Ok, I don't have Show Stopper to fix today. Let me try to piece together
what I read from your post.

> I'm having a strange problem in my WDM driver. I'm using a kernel
> thread to check something at 100 mS intervals with a KTIMER. The timer
> is allocated from the nonpaged pool when the thread starts and freed
> before it is terminated, and the thread itself runs for a second or more.

I don't quite understand why a timer would be necessary and how it's
related to the thread. If the thread is to poll every 100ms, I would do
something like this:

VOID
ThreadMainRoutine(
IN PDEVICE_DATA pDevExt
)
{
LARGE_INTEGER time;
time.QuadPart = MILLISECONDS(100);
while (!pDevExt->kill) {

KeDelayExecutionThread(KernelMode,FALSE,&time);
DoMyPollingHere(pDevExt)
}
PsTerminateSystemThread(STATUS_SUCCESS);
}

> For some unknown reason, I started getting a 0xC2 bugcheck under
> Windows 2K after about four executions of the thread. I'm only
> deallocating the KTIMER once at the end of the thread,

What do you mean by deallocating the KTIMER?

>but since 0xC2
> can be generated by double deallocations, I decided to see if the
> bugcheck was occurring because I was allocating and deallocating the
> KTIMER every time the thread executed. I changed the driver so that the
> KTIMER was allocated when the device was created and deallocated when
> the device was removed, and when I did that the 0xC2 bugcheck turned
> into a 0x0A bugcheck.

Can you show the thread routine? I'm trying to understand its interaction
with the timer.

> The kicker is this: I changed the driver back to its original
> state except that I left a declaration for a KTIMER pointer in my device
> extension--that is, there is space for a KTIMER pointer in the device
> extension, but it is unused--and I still get the 0x0A bugcheck. If I
> take the declaration out, the bugcheck changes back to 0xC2.

Without a stack dump, it's hard to tell what went wrong. You mentioned space
for "KTIMER pointer", I hope you meant space for the "KTIMER structure".

> One final note is this. The 0x0A exception is occurring inside of
> KeWaitForSingleObject(), which is what I'm using to wait for the thread
> to end under Win2K. 0x0A means something is ocurring at the wrong IRQL,
> and when the exception occurs the IRQL is 2--DISPATCH_LEVEL. Just
> before KeWaitForSingleObject() is called, I did a KdPrint() that showed
> the IRQL as 1--APC_LEVEL.

KeWaitForXxxx will raise irql to dispatch_level at some point internally.
Make sure you are waiting for the thread object (not thread handle)

Calvin
-
Calvin Guan Software Engineer
ATI Technologies Inc. www.ati.com



Re: Weird Exception by Michael

Michael
Thu Jun 24 15:30:12 CDT 2004

Calvin,

Thanks for the post.

>> I'm having a strange problem in my WDM driver. I'm using a kernel
>>thread to check something at 100 mS intervals with a KTIMER. The timer
>>is allocated from the nonpaged pool when the thread starts and freed
>>before it is terminated, and the thread itself runs for a second or more.
>
>
> I don't quite understand why a timer would be necessary and how it's
> related to the thread. If the thread is to poll every 100ms, I would do
> something like this:
>
> VOID
> ThreadMainRoutine(
> IN PDEVICE_DATA pDevExt
> )
> {
> LARGE_INTEGER time;
> time.QuadPart = MILLISECONDS(100);
> while (!pDevExt->kill) {
>
> KeDelayExecutionThread(KernelMode,FALSE,&time);
> DoMyPollingHere(pDevExt)
> }
> PsTerminateSystemThread(STATUS_SUCCESS);
> }
You're right, I can use KeDelayExecutionThread() and was planning to
change the driver to do that, but when I wrote the driver last year, the
documentation I was reading pointed me to using a KTIMER. I didn't know
about KeDelayExecutionThread(). Even at the time I thought using a
KTIMER was too complicated, but that's sometimes the case when
programming under Windows (as you probably already know).
At this point, I'm just seeing if I can figure out why this crash is
happening, and it isn't happening in most places where the driver is
installed.


>> For some unknown reason, I started getting a 0xC2 bugcheck under
>>Windows 2K after about four executions of the thread. I'm only
>>deallocating the KTIMER once at the end of the thread,
>
>
> What do you mean by deallocating the KTIMER?
See the thread routine below. I originally worked from some example
code that allocated the KTIMER from the nonpaged pool.

>>but since 0xC2
>>can be generated by double deallocations, I decided to see if the
>>bugcheck was occurring because I was allocating and deallocating the
>>KTIMER every time the thread executed. I changed the driver so that the
>>KTIMER was allocated when the device was created and deallocated when
>>the device was removed, and when I did that the 0xC2 bugcheck turned
>>into a 0x0A bugcheck.
>
>
> Can you show the thread routine? I'm trying to understand its interaction
> with the timer.
Here are the essentials of the thread routine. It's a little bit messy,
so I hope you'll excuse me.
VOID Thread(DEVICE_EXTENSION *pdx) {
PKTIMER pkTimer;
LARGE_INTEGER Timeout, WaitTime;
int TimerEnabled = 0;
NTSTATUS WaitStatus;

// Set up a system timer. MustSucceed in case running under XP and low
// on resources.
pkTimer = ExAllocatePool(NonPagedPoolMustSucceed,sizeof(KTIMER));
KeInitializeTimer(pkTimer);
// Set Timeout to zero so that KeWaitForSingleObject will
// return immediately
Timeout.QuadPart = 0;
// Set WaitTime to 100 mS (or whatever)
WaitTime.QuadPart = -1000000;
// If KeWaitForSingleObject() returns STATUS_SUCCESS,
// then thread execution is done and it's time to exit
// the loop
WaitStatus =
KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout);
while (WaitStatus != STATUS_SUCCESS) {
// Enable the KTIMER if necessary
if (!TimerEnabled) {
KeSetTimer(pkTimer,WaitTime,NULL);
TimerEnabled = 1;
}
// Otherwise, if the timer has timed out, then do something
else if (KeReadStateTimer(pkTimer) == TRUE) {
.
.
.
TimerEnabled = 0;
}
WaitStatus =
KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout);
}
// Wait for timeout before freeing the KTIMER
do
;
while (KeReadStateTimer(pkTimer) != TRUE);
ExFreePool(pkTimer);
// Bye bye
PsTerminateSystemThread(STATUS_SUCCESS);
}

Here's the code that starts the thread under Win2K or XP:

NTSTATUS StartThread(DEVICE_EXTENSION *pdx) {
NTSTATUS status;
HANDLE hThread;

KeInitializeEvent(&pdx->evKillThread,NotificationEvent,FALSE);
status =
PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,NULL,NULL,NULL,(PKSTART_ROUTINE)Thread,pdx);
if (!NT_SUCCESS(status))
return status;

ObReferenceObjectByHandle(hThread,THREAD_ALL_ACCESS,NULL,KernelMode,(PVOID)&pdx->ktThread,NULL);
ZwClose(hThread);
return STATUS_SUCCESS;
}

...and here's the code that stops it:

VOID StopThread(DEVICE_EXTENSION *pdx) {
KeSetEvent(&pdx->evKillThread,0,FALSE);
KeWaitForSingleObject(&pdx->ktThread,Executive,KernelMode,FALSE,NULL);
ObDereferenceObject(pdx->ktThread);
}

The call in StopThread() to KeWaitForSingleObject() appears to be where
the crash is occurring.


>> The kicker is this: I changed the driver back to its original
>>state except that I left a declaration for a KTIMER pointer in my device
>>extension--that is, there is space for a KTIMER pointer in the device
>>extension, but it is unused--and I still get the 0x0A bugcheck. If I
>>take the declaration out, the bugcheck changes back to 0xC2.
>
>
> Without a stack dump, it's hard to tell what went wrong.
I don't have a good stack dump yet.

> You mentioned space for "KTIMER pointer", I hope you meant space for the "KTIMER structure".
I tried it both ways--a KTIMER structure in the device extension and a
pointer to one that gets allocated by AddDevice() and freed by
RemoveDevice(). In both cases, I got the 0x0A exception.


>> One final note is this. The 0x0A exception is occurring inside of
>>KeWaitForSingleObject(), which is what I'm using to wait for the thread
>>to end under Win2K. 0x0A means something is ocurring at the wrong IRQL,
>>and when the exception occurs the IRQL is 2--DISPATCH_LEVEL. Just
>>before KeWaitForSingleObject() is called, I did a KdPrint() that showed
>>the IRQL as 1--APC_LEVEL.
>
>
> KeWaitForXxxx will raise irql to dispatch_level at some point internally.
> Make sure you are waiting for the thread object (not thread handle)
I figured KeWaitForSingleObject() was raising the IRQL, and as you can
see from the code above, I'm not waiting on the handle. Thanks again
for your comments. They are appreciated.

Mike
mmccully@ionwerks.com


Re: Weird Exception by Peter

Peter
Thu Jun 24 16:18:44 CDT 2004

I don't see the problem offhand ... but i've got some notes for future
designs:

You can wait on a timer using KeWaitForSingleObject(). You could wait on
the timer and the event both by calling KeWaitForMultipleObjects(). So you
don't need to test the state of the thread and then spin checking the timer
state.

As a general rule when you find yourself writing a spin loop like the one
you have below you've probably chosen a wrong design for Windows. Between
waiting on objects and proper use of DPCs and work items i find that
spinning is rarely necessary (except occasionally when i'm directly touching
hardware and then there are Ke routines to spin for me).

You can also clear the timer by calling KeCancelTimer() so you don't need to
spin after the terminate event is set in order to rundown the timer. It's
possible the problem you're seeing has to do with the timer remaining in the
timer lists even after it's become signalled for some time unless you call
KeCancelTimer() before you free it (i'm guessing)

-p

--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Michael I. McCully" <Mike.McCully@pobox.com> wrote in message
news:I8ydnUw1H_ZIpEbd4p2dnA@texas.net...
> Calvin,
>
> Thanks for the post.
>
> >> I'm having a strange problem in my WDM driver. I'm using a kernel
> >>thread to check something at 100 mS intervals with a KTIMER. The timer
> >>is allocated from the nonpaged pool when the thread starts and freed
> >>before it is terminated, and the thread itself runs for a second or
more.
> >
> >
> > I don't quite understand why a timer would be necessary and how it's
> > related to the thread. If the thread is to poll every 100ms, I would do
> > something like this:
> >
> > VOID
> > ThreadMainRoutine(
> > IN PDEVICE_DATA pDevExt
> > )
> > {
> > LARGE_INTEGER time;
> > time.QuadPart = MILLISECONDS(100);
> > while (!pDevExt->kill) {
> >
> > KeDelayExecutionThread(KernelMode,FALSE,&time);
> > DoMyPollingHere(pDevExt)
> > }
> > PsTerminateSystemThread(STATUS_SUCCESS);
> > }
> You're right, I can use KeDelayExecutionThread() and was planning to
> change the driver to do that, but when I wrote the driver last year, the
> documentation I was reading pointed me to using a KTIMER. I didn't know
> about KeDelayExecutionThread(). Even at the time I thought using a
> KTIMER was too complicated, but that's sometimes the case when
> programming under Windows (as you probably already know).
> At this point, I'm just seeing if I can figure out why this crash is
> happening, and it isn't happening in most places where the driver is
> installed.
>
>
> >> For some unknown reason, I started getting a 0xC2 bugcheck under
> >>Windows 2K after about four executions of the thread. I'm only
> >>deallocating the KTIMER once at the end of the thread,
> >
> >
> > What do you mean by deallocating the KTIMER?
> See the thread routine below. I originally worked from some example
> code that allocated the KTIMER from the nonpaged pool.
>
> >>but since 0xC2
> >>can be generated by double deallocations, I decided to see if the
> >>bugcheck was occurring because I was allocating and deallocating the
> >>KTIMER every time the thread executed. I changed the driver so that the
> >>KTIMER was allocated when the device was created and deallocated when
> >>the device was removed, and when I did that the 0xC2 bugcheck turned
> >>into a 0x0A bugcheck.
> >
> >
> > Can you show the thread routine? I'm trying to understand its
interaction
> > with the timer.
> Here are the essentials of the thread routine. It's a little bit messy,
> so I hope you'll excuse me.
> VOID Thread(DEVICE_EXTENSION *pdx) {
> PKTIMER pkTimer;
> LARGE_INTEGER Timeout, WaitTime;
> int TimerEnabled = 0;
> NTSTATUS WaitStatus;
>
> // Set up a system timer. MustSucceed in case running under XP and low
> // on resources.
> pkTimer = ExAllocatePool(NonPagedPoolMustSucceed,sizeof(KTIMER));
> KeInitializeTimer(pkTimer);
> // Set Timeout to zero so that KeWaitForSingleObject will
> // return immediately
> Timeout.QuadPart = 0;
> // Set WaitTime to 100 mS (or whatever)
> WaitTime.QuadPart = -1000000;
> // If KeWaitForSingleObject() returns STATUS_SUCCESS,
> // then thread execution is done and it's time to exit
> // the loop
> WaitStatus =
>
KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout
);
> while (WaitStatus != STATUS_SUCCESS) {
> // Enable the KTIMER if necessary
> if (!TimerEnabled) {
> KeSetTimer(pkTimer,WaitTime,NULL);
> TimerEnabled = 1;
> }
> // Otherwise, if the timer has timed out, then do something
> else if (KeReadStateTimer(pkTimer) == TRUE) {
> .
> .
> .
> TimerEnabled = 0;
> }
> WaitStatus =
>
KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout
);
> }
> // Wait for timeout before freeing the KTIMER
> do
> ;
> while (KeReadStateTimer(pkTimer) != TRUE);
> ExFreePool(pkTimer);
> // Bye bye
> PsTerminateSystemThread(STATUS_SUCCESS);
> }
>
> Here's the code that starts the thread under Win2K or XP:
>
> NTSTATUS StartThread(DEVICE_EXTENSION *pdx) {
> NTSTATUS status;
> HANDLE hThread;
>
> KeInitializeEvent(&pdx->evKillThread,NotificationEvent,FALSE);
> status =
>
PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,NULL,NULL,NULL,(PKSTART_ROUT
INE)Thread,pdx);
> if (!NT_SUCCESS(status))
> return status;
>
>
ObReferenceObjectByHandle(hThread,THREAD_ALL_ACCESS,NULL,KernelMode,(PVOID)&
pdx->ktThread,NULL);
> ZwClose(hThread);
> return STATUS_SUCCESS;
> }
>
> ...and here's the code that stops it:
>
> VOID StopThread(DEVICE_EXTENSION *pdx) {
> KeSetEvent(&pdx->evKillThread,0,FALSE);
>
KeWaitForSingleObject(&pdx->ktThread,Executive,KernelMode,FALSE,NULL);
> ObDereferenceObject(pdx->ktThread);
> }
>
> The call in StopThread() to KeWaitForSingleObject() appears to be where
> the crash is occurring.
>
>
> >> The kicker is this: I changed the driver back to its original
> >>state except that I left a declaration for a KTIMER pointer in my device
> >>extension--that is, there is space for a KTIMER pointer in the device
> >>extension, but it is unused--and I still get the 0x0A bugcheck. If I
> >>take the declaration out, the bugcheck changes back to 0xC2.
> >
> >
> > Without a stack dump, it's hard to tell what went wrong.
> I don't have a good stack dump yet.
>
> > You mentioned space for "KTIMER pointer", I hope you meant space for the
"KTIMER structure".
> I tried it both ways--a KTIMER structure in the device extension and a
> pointer to one that gets allocated by AddDevice() and freed by
> RemoveDevice(). In both cases, I got the 0x0A exception.
>
>
> >> One final note is this. The 0x0A exception is occurring inside of
> >>KeWaitForSingleObject(), which is what I'm using to wait for the thread
> >>to end under Win2K. 0x0A means something is ocurring at the wrong IRQL,
> >>and when the exception occurs the IRQL is 2--DISPATCH_LEVEL. Just
> >>before KeWaitForSingleObject() is called, I did a KdPrint() that showed
> >>the IRQL as 1--APC_LEVEL.
> >
> >
> > KeWaitForXxxx will raise irql to dispatch_level at some point
internally.
> > Make sure you are waiting for the thread object (not thread handle)
> I figured KeWaitForSingleObject() was raising the IRQL, and as you can
> see from the code above, I'm not waiting on the handle. Thanks again
> for your comments. They are appreciated.
>
> Mike
> mmccully@ionwerks.com
>



Re: Weird Exception by Calvin

Calvin
Thu Jun 24 16:25:32 CDT 2004

Mike,

See reply inline.

> VOID Thread(DEVICE_EXTENSION *pdx) {
> PKTIMER pkTimer;
> LARGE_INTEGER Timeout, WaitTime;
> int TimerEnabled = 0;
> NTSTATUS WaitStatus;
>
> // Set up a system timer. MustSucceed in case running under XP and low
> // on resources.
> pkTimer = ExAllocatePool(NonPagedPoolMustSucceed,sizeof(KTIMER));
> KeInitializeTimer(pkTimer);
> // Set Timeout to zero so that KeWaitForSingleObject will
> // return immediately
> Timeout.QuadPart = 0;
> // Set WaitTime to 100 mS (or whatever)
> WaitTime.QuadPart = -1000000;
> // If KeWaitForSingleObject() returns STATUS_SUCCESS,
> // then thread execution is done and it's time to exit
> // the loop
> WaitStatus =
>
KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout
);
> while (WaitStatus != STATUS_SUCCESS) {
> // Enable the KTIMER if necessary
> if (!TimerEnabled) {
> KeSetTimer(pkTimer,WaitTime,NULL);
> TimerEnabled = 1;
> }
> // Otherwise, if the timer has timed out, then do something
> else if (KeReadStateTimer(pkTimer) == TRUE) {
> .
> .
> .
> TimerEnabled = 0;
> }
> WaitStatus =
>
KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout
);
> }
> // Wait for timeout before freeing the KTIMER
> do
> ;
> while (KeReadStateTimer(pkTimer) != TRUE);
> ExFreePool(pkTimer);
> // Bye bye
> PsTerminateSystemThread(STATUS_SUCCESS);
> }

Did you enable Driver Verifier for Low Resource Simulation? I would put an
ASSERT( pkTimer); after allocating the storage.


> NTSTATUS StartThread(DEVICE_EXTENSION *pdx) {
> NTSTATUS status;
> HANDLE hThread;
>
> KeInitializeEvent(&pdx->evKillThread,NotificationEvent,FALSE);
> status =
>
PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,NULL,NULL,NULL,(PKSTART_ROUT
INE)Thread,pdx);
> if (!NT_SUCCESS(status))
> return status;
>
>
ObReferenceObjectByHandle(hThread,THREAD_ALL_ACCESS,NULL,KernelMode,(PVOID)&
pdx->ktThread,NULL);
> ZwClose(hThread);
> return STATUS_SUCCESS;
> }
>
> ...and here's the code that stops it:
>
> VOID StopThread(DEVICE_EXTENSION *pdx) {
> KeSetEvent(&pdx->evKillThread,0,FALSE);
>
KeWaitForSingleObject(&pdx->ktThread,Executive,KernelMode,FALSE,NULL);
> ObDereferenceObject(pdx->ktThread);
> }
>

It should be:

VOID StopThread(DEVICE_EXTENSION *pdx)
{
KeSetEvent(&pdx->evKillThread,0,FALSE);

KeWaitForSingleObject(pdx->ktThread,Executive,KernelMode,FALSE,NULL); //
pdx->ktThread ought to be the pointer to the thread object.

ObDereferenceObject(pdx->ktThread);
}

HTH,
Calvin
-
Calvin Guan Software Engineer
ATI Technologies Inc. www.ati.com



Re: Weird Exception by Michael

Michael
Fri Jun 25 03:07:39 CDT 2004

Peter:

Thanks a lot for the comments from your notes. See mine below.

> I don't see the problem offhand ... but i've got some notes for future
> designs:
>
> You can wait on a timer using KeWaitForSingleObject(). You could wait on
> the timer and the event both by calling KeWaitForMultipleObjects(). So you
> don't need to test the state of the thread and then spin checking the timer
> state.
>
> As a general rule when you find yourself writing a spin loop like the one
> you have below you've probably chosen a wrong design for Windows. Between
> waiting on objects and proper use of DPCs and work items i find that
> spinning is rarely necessary (except occasionally when i'm directly touching
> hardware and then there are Ke routines to spin for me).
I'm doing the spin because I am directly touching the hardware.

> You can also clear the timer by calling KeCancelTimer() so you don't need to
> spin after the terminate event is set in order to rundown the timer.
You're exactly right. I should have used KeCancelTimer(). I changed
the code so I called it instead of spinning in a loop, and it didn't fix
the problem.

> It's possible the problem you're seeing has to do with the timer remaining in the
> timer lists even after it's become signalled for some time unless you call
> KeCancelTimer() before you free it (i'm guessing)
Good guess, but the crash occurs even if I don't allocate the timer or
use it. Thanks again for taking the time to answer my post.
>
> -p
>


Re: Weird Exception by Michael

Michael
Fri Jun 25 03:08:52 CDT 2004

Calvin,

You have sharp eyes. Now I feel stupid for not noticing the
problem with the KeWaitForSingleObject() thread pointer, but I guess
that's life. Too bad Verifier didn't help find the problem either. I
ran it for two months under Win2K and XP. I set it up for low
resources, too.
I'm not out of the woods yet with my weird problem. Fixing the
KeWaitForSingleObject() call did change the number of executions it
takes to cause the crash, but it still crashes. That's a clue. I also
changed the thread so it uses KeDelayExecutionThread() instead of
KeReadStateTimer() & Co., but that also didn't change anything. I guess
I need to keep looking.
Thanks again for your help.

Mike
mmccully@ionwerks.com


Calvin Guan wrote:
> Mike,
>
> See reply inline.
>
>
>>VOID Thread(DEVICE_EXTENSION *pdx) {
>> PKTIMER pkTimer;
>> LARGE_INTEGER Timeout, WaitTime;
>> int TimerEnabled = 0;
>> NTSTATUS WaitStatus;
>>
>>// Set up a system timer. MustSucceed in case running under XP and low
>>// on resources.
>> pkTimer = ExAllocatePool(NonPagedPoolMustSucceed,sizeof(KTIMER));
>> KeInitializeTimer(pkTimer);
>>// Set Timeout to zero so that KeWaitForSingleObject will
>>// return immediately
>> Timeout.QuadPart = 0;
>>// Set WaitTime to 100 mS (or whatever)
>> WaitTime.QuadPart = -1000000;
>>// If KeWaitForSingleObject() returns STATUS_SUCCESS,
>>// then thread execution is done and it's time to exit
>>// the loop
>> WaitStatus =
>>
>
> KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout
> );
>
>> while (WaitStatus != STATUS_SUCCESS) {
>> // Enable the KTIMER if necessary
>> if (!TimerEnabled) {
>> KeSetTimer(pkTimer,WaitTime,NULL);
>> TimerEnabled = 1;
>> }
>> // Otherwise, if the timer has timed out, then do something
>> else if (KeReadStateTimer(pkTimer) == TRUE) {
>> .
>> .
>> .
>> TimerEnabled = 0;
>> }
>> WaitStatus =
>>
>
> KeWaitForSingleObject(&pdx->evKillThread,Executive,KernelMode,FALSE,&Timeout
> );
>
>> }
>>// Wait for timeout before freeing the KTIMER
>> do
>> ;
>> while (KeReadStateTimer(pkTimer) != TRUE);
>> ExFreePool(pkTimer);
>>// Bye bye
>> PsTerminateSystemThread(STATUS_SUCCESS);
>>}
>
>
> Did you enable Driver Verifier for Low Resource Simulation? I would put an
> ASSERT( pkTimer); after allocating the storage.
>
>
>
>>NTSTATUS StartThread(DEVICE_EXTENSION *pdx) {
>> NTSTATUS status;
>> HANDLE hThread;
>>
>>KeInitializeEvent(&pdx->evKillThread,NotificationEvent,FALSE);
>> status =
>>
>
> PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,NULL,NULL,NULL,(PKSTART_ROUT
> INE)Thread,pdx);
>
>> if (!NT_SUCCESS(status))
>> return status;
>>
>>
>
> ObReferenceObjectByHandle(hThread,THREAD_ALL_ACCESS,NULL,KernelMode,(PVOID)&
> pdx->ktThread,NULL);
>
>> ZwClose(hThread);
>> return STATUS_SUCCESS;
>>}
>>
>>...and here's the code that stops it:
>>
>>VOID StopThread(DEVICE_EXTENSION *pdx) {
>> KeSetEvent(&pdx->evKillThread,0,FALSE);
>>
>
> KeWaitForSingleObject(&pdx->ktThread,Executive,KernelMode,FALSE,NULL);
>
>> ObDereferenceObject(pdx->ktThread);
>>}
>>
>
>
> It should be:
>
> VOID StopThread(DEVICE_EXTENSION *pdx)
> {
> KeSetEvent(&pdx->evKillThread,0,FALSE);
>
> KeWaitForSingleObject(pdx->ktThread,Executive,KernelMode,FALSE,NULL); //
> pdx->ktThread ought to be the pointer to the thread object.
>
> ObDereferenceObject(pdx->ktThread);
> }
>
> HTH,
> Calvin
> -
> Calvin Guan Software Engineer
> ATI Technologies Inc. www.ati.com
>
>


Re: Weird Exception by Calvin

Calvin
Fri Jun 25 10:15:46 CDT 2004

Mike,

> I set it up for low resources, too.

[snip]
> >> pkTimer = ExAllocatePool(NonPagedPoolMustSucceed,sizeof(KTIMER));
> > Did you enable Driver Verifier for Low Resource Simulation? I would put
an

If Low Resources Simulation is enabled, DV will inject allocation failures
at random. You may get BC_0xc2 (p1=0x9a) when mustSucceed is specified. This
why I was asking if you've done so in my previous post. Please disable Low
Resources to see if it make a difference.

If an allocation has to be made, I would suggest not to use
NonPagedPoolMustSucceed and handle allocation failure gracefully if
possible.

Good luck and cheers,
Calvin
-
Calvin Guan Software Engineer
ATI Technologies Inc. www.ati.com