KeSetEvent

Hi.

I’ve been reading into the Ke Functions about signaled events. I was told I probably wouldn’t need a workitem thread and looking at it I don’t seem to. However I am having problems when it comes to the KeSetEvent(pkEvent). I have tried executing this at passive level as well as the KeWaitForSingleObject without luck. I am either getting an unknown error (BSOD) or a IRQL_NOT_EQUAL_OR_LESS_THAN. If I rem this there isn’t a problem.

The code I have is.
PKEVENT pkEvent[700];

LoadImageNotifyRoutine(…)
{

KeInitializeEvent(pkEvent, NotificationEvent, FALSE);
KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0);
KeClear(pkEvent);

}

Inside a passive level run thread.
Thread.
{

KeSetEvent(pkEvent[i]);

}

You have an array of pointers, how does each pointer value in the array get initialized? Why do you need such a large global array?

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.co.uk
Sent: Monday, January 04, 2010 9:05 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] KeSetEvent

Hi.

I’ve been reading into the Ke Functions about signaled events. I was told I probably wouldn’t need a workitem thread and looking at it I don’t seem to. However I am having problems when it comes to the KeSetEvent(pkEvent). I have tried executing this at passive level as well as the KeWaitForSingleObject without luck. I am either getting an unknown error (BSOD) or a IRQL_NOT_EQUAL_OR_LESS_THAN. If I rem this there isn’t a problem.

The code I have is.
PKEVENT pkEvent[700];

LoadImageNotifyRoutine(…)
{

KeInitializeEvent(pkEvent, NotificationEvent, FALSE); KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0); KeClear(pkEvent); …
}

Inside a passive level run thread.
Thread.
{

KeSetEvent(pkEvent[i]);

}


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

You have an array of 700 event pointers instead of 700 event objects. Why
700? You then need to intialize each event.
You pass the address of each event to the event functions -
KeInitializeEvent(&pkEvent[i]) - KeSetEvent(&pkEvent[i]).

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com]
On Behalf Of xxxxx@hotmail.co.uk
Sent: Monday, January 04, 2010 12:05 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] KeSetEvent

Hi.

I’ve been reading into the Ke Functions about signaled events. I was told I
probably wouldn’t need a workitem thread and looking at it I don’t seem to.
However I am having problems when it comes to the KeSetEvent(pkEvent). I
have tried executing this at passive level as well as the
KeWaitForSingleObject without luck. I am either getting an unknown error
(BSOD) or a IRQL_NOT_EQUAL_OR_LESS_THAN. If I rem this there isn’t a
problem.

The code I have is.
PKEVENT pkEvent[700];

LoadImageNotifyRoutine(…)
{

KeInitializeEvent(pkEvent, NotificationEvent, FALSE);
KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0);
KeClear(pkEvent); …
}

Inside a passive level run thread.
Thread.
{

KeSetEvent(pkEvent[i]);

}


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

>KeInitializeEvent(pkEvent, NotificationEvent, FALSE);

KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0);
You should initialize one event by calling KeInitializeEvent not array of events.
And what is variable i have equal to?

Igor Sharovar

  1. You have an array of pointers, not a single KEVENT. You need to modify your call to KeSetEvent.

KeSetEvent(& pkEvent[0]) (or [1] or something).

  1. Backing up a bit, why do you need such a large array of KEVENTS (on the stack)? I’m not sure of the size of a KEVENT off the top of my head, but 700 of them on the stack in the kernel is curious.

Good luck,

mm

KeInitializeEvent(pkEvent[i], NotificationEvent, FALSE);

That is how I thought they were being initialized. (I’m sorry I missed the i.) The i is the current free pkEvent that is not in use. Used with the following code.

BOOLEAN pkEventInUse[700];

LoadImageNotifyRoutine(…)
{
DWORD i;

i = 0; while (pkEventInUse[i] == TRUE) { i++; } /* This code is a little bit better than this. It is just something simple to show. */
KeInitializeEvent(pkEvent[i], NotificationEvent, FALSE);
KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0);
KeClear(pkEvent);

}

You have an array of pointers, how does each pointer value in the array get
initialized? Why do you need such a large global array?

d

Whoops - you’re using PKEVENTS, not KEVENTS.

My bad.

Still a whole lot of events, though.

mm

You have array of pointers to KEVENTS. But you also need to allocate, statically or dynamically, memory for KEVENTs. I believe, KeInitializeEvent doesn’t allocate memory for KEVENT. It just initializes KEVENT.

Igor Sharovar

It could be made lower. It is only waiting for user approval on applications.

Would there be a problem with it being so high?

Whoops - you’re using PKEVENTS, not KEVENTS.

My bad.

Still a whole lot of events, though.

mm

It seems like you were absolutely right.

You have array of pointers to KEVENTS. But you also need to allocate, statically
or dynamically, memory for KEVENTs. I believe, KeInitializeEvent doesn’t
allocate memory for KEVENT. It just initializes KEVENT.

Igor Sharovar

Thankyou.

You have array of pointers to KEVENTS. But you also need to allocate, statically

or dynamically, memory for KEVENTs. I believe, KeInitializeEvent doesn’t
allocate memory for KEVENT. It just initializes KEVENT.

Igor Sharovar

xxxxx@hotmail.co.uk wrote:

KeInitializeEvent(pkEvent[i], NotificationEvent, FALSE);

That is how I thought they were being initialized. (I’m sorry I missed the i.) The i is the current free pkEvent that is not in use. Used with the following code.

You have a basic misunderstanding of C here, one that we are seeing more
and more often. The event routines take a PKEVENT, but that does NOT
mean that you create a PKEVENT and pass it in. Instead, you create a
KEVENT, and pass its address. Consider the code you posted. What are
you going to be passing to KeInitializeEvent? By the time this runs,
pkEvent[i] is just an uninitialized piece of memory.

Change this to
KEVENT pkEvent[700];
Then use & when you pass that to the handlers:
KeInitializeEvent( &pkEvent[i], … );

As with the others, I would argue this is a flawed design. If you need
more than a few, then sooner or later 700 will not be enough and your
driver will explode. Surely it would be better for you to allocate some
kind of “context” structure for each request, hold them in a linked
list, and have the KEVENT be part of that structure. That way, there
are no hard limits.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

The problem with it being so high is that you are consuming memory for no reason

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.co.uk
Sent: Monday, January 04, 2010 9:42 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeSetEvent

It could be made lower. It is only waiting for user approval on applications.

Would there be a problem with it being so high?

Whoops - you’re using PKEVENTS, not KEVENTS.

My bad.

Still a whole lot of events, though.

mm


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

In user space, there is a documented upper bound of 64 waitable objects in a
handle array. So I went to the DDK documentation, and it says if you give a
value > MAXIMUM_WAIT_OBJECTS that the system will terminate with a BugCheck
0x0C, MAXIMUM_WAIT_OBJECTS_EXCEEDED.

So a bit of groveling in the header files reveals

#define MAXIMUM_WAIT_OBJECTS 64

So if you need more than 64, you probably need a different solution.

(My own view: if you are doing a WaitForMultiple with a number of objects
which is not a compile-time-constant expression, You Are Doomed. The number
of times people code like this and forget to check for >
MAXIMUM_WAIT_OBJECTS is surprisingly high)

I would suggest some entirely different mechanism be considered, such as a
queue of completed requests and a simple KSEMAPHORE to indicate that there
is something in the queue.

Or, put another way, if you have 700 objects you are waiting for, you have
699 too many.

Note that KeWaitForMultipleObjects is subject to starvation; if objects of
some lower index are signaled frequently, objects of higher index, although
signaled, may never be seen, because the rule is that you get the index of
the lowest signaled object. I once had a client who had a CTC number of
handles (about 10, as I recall) do a “rotate” of the elements in the array
each time it came out of wait to guarantee antistarvation. But a queue is
cleaner.

The documentation is surprisingly bad, at least the old version I have
available today (I had a server meltdown last week and I’m waiting for the
new server parts to arrive, so the latest WDK on the server is
inaccessible). I says “If KeWaitForMultipleObjects returns STATUS_SUCCESS,
and if WaitAny is specified, KeWaitForMultipleObjects also returns the
zero-based index of the object that satisfied the wait at NTSTATUS”.

This makes neither grammatical sense nor functional sense.

If it returns STATUS_SUCCESS, the literal value 0, then it cannot return any
other value such as an index. I never heard of a function returning a value
“at” its return type. It might return a value “as” its return value.

If it were consistent with the user-mode documentation, it might say

"KeWaitForMultipleObjects can return one of the following values:

STATUS_SUCCESS through STATUS_SUCCESS + Count - 1: A value indicating
successful resumption due to one or more objects being signaled. In the
case of WaitAll, the value is always STATUS_SUCCESS. In the case of
WaitAny, the value is the index of the object that satisfied the wait. In
the case where multiple objects became signaled to satisfy a WaitAny, the
index of the lowest object is returned. WARNING! This can lead to
starvation of response to higher-numbered objects!

STATUS_USER_APC…

STATUS_TIMEOUT…

STATUS_ALERTED…"

Note that NT_SUCCESS will recognize this as successful completion, but it
also means you cannot distinguish the various NT_SUCCESS-compliant
completions (which include STATUS_ALERTED (0x101), STATUS_USER_APC (0xC0)
and STATUS_TIMEOUT (0x102) by a simple test that includes a test of the
literal value STATUS_SUCCESS, since this value will typically will not
happen in a KeWaitForMultipleObjects/WaitAny.

I’m also not sure why the OP said “a thread would not be necessary” because
a KeWaitFor implies that there is a thread waiting, and some other mechanism
(typically a DPC) is going to do something to terminate that wait. So
somewhere there is a blocked thread. And the implications of this blocked
thread need to be carefully considered.
joe

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Monday, January 04, 2010 1:21 PM
To: Windows System Software Devs Interest List
Subject: RE: RE:[ntdev] KeSetEvent

The problem with it being so high is that you are consuming memory for no
reason

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.co.uk
Sent: Monday, January 04, 2010 9:42 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeSetEvent

It could be made lower. It is only waiting for user approval on
applications.

Would there be a problem with it being so high?

Whoops - you’re using PKEVENTS, not KEVENTS.

My bad.

Still a whole lot of events, though.

mm


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


This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Joseph M. Newcomer wrote:

In user space, there is a documented upper bound of 64 waitable objects in a
handle array. So I went to the DDK documentation, and it says if you give a
value > MAXIMUM_WAIT_OBJECTS that the system will terminate with a BugCheck
0x0C, MAXIMUM_WAIT_OBJECTS_EXCEEDED.

So a bit of groveling in the header files reveals

#define MAXIMUM_WAIT_OBJECTS 64

So if you need more than 64, you probably need a different solution.

He’s doing them one at a time. That is, he’s thinking he might have 700
simultaneous requests, each waiting for one event.

That’s equally bad, but badness in a different direction.

I would suggest some entirely different mechanism be considered, such as a
queue of completed requests and a simple KSEMAPHORE to indicate that there
is something in the queue.

Yes.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

That’s a bit strange. For example, you cannot have more than one thread
waiting on a KeWaitForSingleObject, so in that case an array would not make
sense. Or it would require 700 threads, each waiting on one object. Or one
thread, sequentially waiting on each of several objects, which means that
the priority inversion problem can be the major performance bottleneck.

When I teach a course in user-level systems programming, it is amazing how
convoluted the solutions are where the students try to implement
WaitForMultipleObjects with a loop or other construct doing
WaitForSingleObject. And they almost always manage to produce a wrong
answer.

But no matter what was intended, 700 objects sounds like 699 too many.
joe

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, January 04, 2010 2:43 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] KeSetEvent

Joseph M. Newcomer wrote:

In user space, there is a documented upper bound of 64 waitable objects in
a
handle array. So I went to the DDK documentation, and it says if you give
a
value > MAXIMUM_WAIT_OBJECTS that the system will terminate with a
BugCheck
0x0C, MAXIMUM_WAIT_OBJECTS_EXCEEDED.

So a bit of groveling in the header files reveals

#define MAXIMUM_WAIT_OBJECTS 64

So if you need more than 64, you probably need a different solution.

He’s doing them one at a time. That is, he’s thinking he might have 700
simultaneous requests, each waiting for one event.

That’s equally bad, but badness in a different direction.

I would suggest some entirely different mechanism be considered, such as a
queue of completed requests and a simple KSEMAPHORE to indicate that there
is something in the queue.

Yes.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


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 message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

> PKEVENT pkEvent[700];

Must be:

KEVENT pkEvent[700];

700 structures, not 700 pointers.

Also, please do not declare such large arrays on stack. Allocate them off pool.

KeInitializeEvent(pkEvent, NotificationEvent, FALSE);

Must be:

for( i = 0; i < 700; i++ )
KeInitializeEvent(&(pkEvent[i]), NotificationEvent, FALSE);

KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0);

KeWaitForSingleObject(&(pkEvent[i]), Executive, KernelMode, FALSE, 0);


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Joseph M. Newcomer wrote:

That’s a bit strange.

I think you have accurately summed up the situation.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Note the common failure of Hungarian Notation: if you change the type from
PKEVENT to KEVENT, you need must change the variable name from pkEvent to
kEvent. Of course, once you realize that HN is one of the silliest ideas to
have come down since using $ to name string variables in Basic, you realize
that the sensible declaration would have been
KEVENT Events[700];

(We will ignore, for purposes of this discussion, the idea that 700 events
is 699 too many; I’ve already belabored that point).

700 PKEVENTs is 2800 bytes of Win32 stack space, so this is REALLY a
marginal idea in a driver! 700 KEVENTs on the stack is 11,200 bytes on a
Win32 stack (it appears that a Win32 KEVENT is 16 bytes, based on my
superficial reading of the structure). This is far, far over threshold for
a stack variable. My suspicion is that this would cause a stack overflow
with very likely fatal consequences, but whether immediately (at the point
of entering the function and trying to allocate more space than the stack
had) or deferred (the stack overrun clobbers something else) is unknown to
me. I believe the rule-of-thumb was that there was only 8K stack, total,
for a driver, and some of that had already been consumed.

[Most people seem to forget that HN was invented so K&R C programmers
(that’s pre-ANSI C, no prototypes) could visually determine argument types
by reading the header file. The same as the silly prefixes in structure
field names that include the structure name are a throwback to the days when
structure names were global and if you had a field “x” in one structure, no
other structure could have a field called “x” unless it was at exactly the
same offset, so the names had to be scoped by using silly prefixes. Yet in
2010, new structures that are being created use this same insane naming
convention because “it is traditional”. It is also completely silly]
joe

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Monday, January 04, 2010 3:41 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] KeSetEvent

PKEVENT pkEvent[700];

Must be:

KEVENT pkEvent[700];

700 structures, not 700 pointers.

Also, please do not declare such large arrays on stack. Allocate them off
pool.

KeInitializeEvent(pkEvent, NotificationEvent, FALSE);

Must be:

for( i = 0; i < 700; i++ )
KeInitializeEvent(&(pkEvent[i]), NotificationEvent, FALSE);

KeWaitForSingleObject(pkEvent[i], Executive, KernelMode, FALSE, 0);

KeWaitForSingleObject(&(pkEvent[i]), Executive, KernelMode, FALSE, 0);


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


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 message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

> [Most people seem to forget that HN was invented so K&R C programmers

(that’s pre-ANSI C, no prototypes) could visually determine argument types

HN was mainly invented to denote not the type, but the use case.

Like dCoordX and dCoordY for in-document coordinates and wCoordX/wCoordY for in-window ones.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com