Is the DDK documentation on KeSetEvent() wrong?

> According to the preceding statement, it is right to call KeSetEvent(pEvent,

0, TRUE) at DispatchRead routine which runs at IRQL = PASSIVE_LEVEL and
in a
nonarbitrary thread context.

Yes, if the code of DispatchRead is not pageable.

According to the later, it is wrong to call KeSetEvent(pEvent, 0, TRUE) at
DispatchRead routine which runs at IRQL = PASSIVE_LEVEL and in a
nonarbitrary thread context.

Yes, if the code of DispatchRead is pageable.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

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
>
>

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

Mark Roddy wrote:

I have never found a good reason to use this feature.

It’s main use is if you want to have a synchronization system which has
“your own” dispatcher lock. The only time you’re likely to do this is if
you implement your own set of synchronization primitives - e.g.
condition variables. So yeah, for the native windows programmer it’s not
that useful. For those who want to implement unix-like synchronization
primitives (pthreads / condvars / etc) efficiently on windows it’s vital.

MH.

> It’s main use is if you want to have a synchronization system which has

“your own” dispatcher lock. The only time you’re likely to do this is if
you implement your own set of synchronization primitives - e.g.
condition variables. So yeah, for the native windows programmer it’s not
that useful. For those who want to implement unix-like synchronization
primitives (pthreads / condvars / etc) efficiently on windows it’s vital.

Yes, this is what user-mode SignalObjectAndWait is about.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com