Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problems with KeWaitForSingleObject and KeSetEvent and W2K

592 views
Skip to first unread message

Jens Kunath

unread,
Oct 23, 2001, 6:44:22 AM10/23/01
to
Hello,

It seems that I have some problems with KeWaitForSingleObject and KeSetEvent
and Windows 2000. My driver uses these functions in order to synchronize one
or more user mode applications.
These applications are waiting for data from the driver. If the driver has
no data for the application then it calls KeWaitForSingleObject to set every
of these waiting applications in a wait state. Later, when data are
available for one these applications it wakes up the application using
KeSetEvent. The problem is that sometimes the application does not wake up
(although the call of KeSetEvent was completed sucessfully) - the previous
call of KeWaitForSingleObject does not return!

Under Windows NT 4.0 this mechanism works properly over a long time without
any problems. Using Windows 2000 this mechanism works only for few minutes.
What could be the problem ??

Some information about the driver:
- it is a minimal WDM driver (that means it supports only a subset of WDM
major functions)
- the events are created in a nonpageable memory area
- the call of KeWaitForSingleObject is:
KeWaitForSingleObject(pkevent, UserRequest, UserMode, TRUE, NULL);
(there are no changes when I use KernelMode und FALSE for Alertable)
- the call of KeSetEvent is:
KeSetEvent(pkevent, 0, 0);
- the function KeSetEvent is called from a interrupt service routine
- the initialization of the event is:
KeInitializeEvent(event_addr, SynchronizationEvent, FALSE)

Has anyone any idea on that matter ?

Thanks in advance for any answer
Jens Kunath

Stephan Wolf

unread,
Oct 23, 2001, 7:57:32 AM10/23/01
to
I don't know much about non-NDIS kernel driver programming but calling
KeSetEvent() from an ISR is for sure illegal since an ISR runs at
DIRQL but KeSetEvent() (with 'Wait' == FALSE) must be called from IRQL
<= DISPATCH_LEVEL. See

http://msdn.microsoft.com/library/en-us/kmarch/k105_1prm.asp

Stephan
---

Greg Livengood

unread,
Oct 24, 2001, 12:16:47 PM10/24/01
to
Not sure if this response is leading you to your solution, but if it
is then here is some more information to complement Stephan's
response.
An Interrupt Service Routine (ISR) does run at the Dispatch
Interrupt Request Level (DIRQL) so you can invoke both the KeSetEvent
and KeWaitForSingleObject functions; they can only be invoked for code
running at IRQL <= DIRQL. The caveat is that if running at DIRQL
KeWaitForSingleObject must set the timeout parameter to 0 so that it
doesn't block.
If you do need to block in the ISR the IPC that is available for
code runing at >= DIRQL is a SpinLock. Ideally though routines
running at an IRQL >= DIRQL leverage Deferred Procedures (DPCs) or
some other approach to avoid blocking. This is so that our drivers
play nice with each other ;-)

Hope that this helps you on your way,
--Greg Livengood

ste...@hotmail.com (Stephan Wolf) wrote in message news:<3bd559f5...@news.t-online.de>...

Stephan Wolf

unread,
Oct 24, 2001, 1:28:58 PM10/24/01
to
Hmm, I think what you say is not actually correct. I think you mix up
DIRQL and DISPATCH_LEVEL.

DIRQL means "Device Interrupt Request Level". IRQLs from lowest to
highest priority:

PASSIVE_LEVEL
APC_LEVEL
DISPATCH_LEVEL
DIRQL

The docs clearly say (and it makes perfect sense):

|KeSetEvent
...
|If Wait is set to FALSE, the caller can be running at IRQL <=
|DISPATCH_LEVEL. Otherwise, callers of KeSetEvent must be running at
|IRQL PASSIVE_LEVEL and in a nonarbitrary thread context.

Thus, calling KeSetEvent() from DIRQL is not allowed.

More, an ISR runs at DIRQL, not at an IRQL >= DIRQL as you state.
Simply because there is no IRQL > DIRQL.

And no, spinlocks cannot be acquired at DIRQL either.

Blocking in an ISR or, in general, at DIRQL is a programming fault.
Blocking at DISPATCH_LEVEL is allowed for very short time periods only
(some microseconds). This is where spinlocks come into play.

Someone correct me if I'm wrong.

Stephan
---
On 24 Oct 2001 09:16:47 -0700, gr...@livengood.com (Greg Livengood)
wrote:

billy_driverhound

unread,
Oct 24, 2001, 2:51:28 PM10/24/01
to
Well, to be clear, there is an interrupt spinlock, although you can't
acquire it directly. Essentially, the interrupt spinlock is taken on your
behalf before your ISR is called. This spinlock can also be taken by a call
to KeSynchronizeExecution. This allows code at < DIRQL to synchronize with
the ISR. In this case the IRQL is raised, the interrupt spinlock is taken
and your synchronize routine is called, not necessarily in that order, I
can't remember.

You can never block at >= DISPATCH_LEVEL. You can spin at >=
DISPATCH_LEVEL. Spinning and blocking are different things. So, you could
never call KeWaitForSingleObject with a non-zero timeout at DISPATCH_LEVEL.
The reason you cannot block at DISPATCH_LEVEL is that the scheduler runs at
DISPATCH_LEVEL. Thus, there is no preemption at IRQLs >= DISPATCH_LEVEL.
That is why a DPC is guaranteed to run to completion. A DPC can only be
interrupted, not preempted and no other DPC will be scheduled to run on a
given processor until the currently running DPC is completed. Check out a
good driver book for a more detailed discussion of all of this.

Bill M.

"Stephan Wolf" <ste...@hotmail.com> wrote in message
news:3bd6f762...@news.t-online.de...

Stephan Wolf

unread,
Oct 24, 2001, 4:14:03 PM10/24/01
to
On Wed, 24 Oct 2001 13:51:28 -0500, "billy_driverhound"
<billy_dr...@my-deja.com> wrote:
[..]

>You can never block at >= DISPATCH_LEVEL. You can spin at >=
>DISPATCH_LEVEL. Spinning and blocking are different things.

Sure, blocking is not allowed. It is just that if some thread acquires
a spinlock, its IRQL is raised to DISPATCH_LEVEL and other threads (on
other CPUs!) trying to acquire the same spinlock will then actually
spin waiting for the lock. (This is why "a driver should never hold a
spin lock for an extended period (more than a few instructions)".) So,
if you will, the spinning threads are "blocked" although this is
probably not correct terminology.

AFAIK, "blocking" usually means "wait for some external event". That
is for sure not allowed at any IRQL >= DISPATCH_LEVEL because
"blocking" usually also implies thread switching. But, as you already
said, thread switching does not take place at IRQL >= DISPATCH_LEVEL.
With one exception: Interrupts.

Sorry for the confusion.

Stephan

billy_driverhound

unread,
Oct 24, 2001, 5:34:36 PM10/24/01
to
Right, just a terminology problem. Also, one note. Even if a DPC is
interrupted, that DPC will run to completion before any other DPC on that
processor is run. So, interruption is much different than preemption. Thus
spinning is much different than blocking, but you get the jist.

Bill M.


"Stephan Wolf" <ste...@hotmail.com> wrote in message

news:3bd71dcc...@news.t-online.de...

0 new messages