This thread has gone on way too long, however I will add to the confusion.
The intent of the Wait parameter for KeSetEvent is to allow a caller to set
one event and then wait for another event as an atomic operation. On return
from KeSetEvent, not only is IRQL == DISPATCH_LEVEL, but it is at
DISPATCH_LEVEL because the dispatcher database spinlock is held and the
thread is marked as the owner. While the docs are unclear, the caller can
then proceed to ignore the admonition regarding calling KeWait* at
DISPATCH_LEVEL. The caller can wait for other event objects with a null or
non-zero timeout, in fact that is the entire point of this feature. KeWait*
will unlock the dispatcher database and return to the original irql (the one
before the call to KeSetEvent) to execute the timed or untimed wait. KeWait*
can do that as the calling thread is marked as the owner of the lock and the
appropriate IRQL is saved in the thread object.
The problem is simply the original problem mentioned when this thread
started: the callers code segment that executes the set and wait operations
cannot be pageable.
I have never found a good reason to use this feature.
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Andrei Zlate-Podani
Sent: Monday, August 20, 2007 5:10 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Is the DDK documentation on KeSetEvent() wrong?
Hello,
Let’s take it step by step:
KeSetEvent(
pEvent,
increment,
wait
);
pEvent will be accessed at DISPATCH_LEVEL -> it must be from nonpaged
pool
wait = = false -> no-brainer
wait = = true -> on return from KeSetEvent the irql is DISPATCH_LEVEL
At some point you have to call KeWaitXXX
If you call KeWaitForSingleObject, the original irql of the thread must
be <= DISPATCH_LEVEL
However, for KeWaitForMultipleObjects there is a chance that the wait
cannot be satisfied, so
the original irql must be <= APC_LEVEL
Good luck,
Andrei Zlate-Podani
John Smith wrote:
I examined the leaked Win2K source on KeSetEvent, and found the following
facts:
Fact 1:
KeSetEvent first raise current IRQL to DISPATCH_LEVEL, and if Wait is set
to
TRUE, KeSetEvent won’t lower the current IRQL. So, after
KeSetEvent(pEvent,
0, TRUE); has executed, the current thread is now running at IRQL =
DISPATCH_LEVEL.
Fact 2:
If the caller call KeWaitForSingleObject(…) with a timeout of non-zero,
KeWaitForSingleObject() might call KiSwapThread() to give up control to
the
thread scheduler which runs at IRQL = DISPATCH_LEVEL. If current IRQL is
DISPATCH_LEVEL, then the giving up (i.e. thread switch) will fail!
Now, let’s consider the code below:
// At this point, IRQL = PASSIVE_LEVEL
KeSetEvent(pEvent, 0, TRUE);
… // At this point, IRQL = DISPATCH_LEVEL, any page fault will cause
BSOD!
KeWaitForSingleObject(…); // Because fact 2, KeWaitForSingleObject(…)
might cause deadlock.
The comments are my thought, am I right?
xxxxx@ntdev…
>
>> Unless you process paging IO to the paging file, you can always afford a
>> page fault at IRQL< DISPATCH_LEVEL, and if your routine processes paging
>> IO to the paging file, you cannot make it pageable, in the first
>> place…
>>
>> Therefore, the second excerpt seems to be wrong…
>>
>> Anton Bassov
>>
>>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
>
>
—
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer