Is local variable of driver dispatch routine paged or nonpaged?

I would clear a local variable in driver dispatch routine.
Data size is 26 bytes.
RtlZeroMemory can be called at any IRQL for nonpaged memory.
However, I don’t know whether local variable belongs to nonpaged memory.
Does anyone know this answer?

Besides, is it safe to use memset() to clear local variable?

Best Regards
Jack Huang

Driver stacks are not paged, so you can alway reference the code.
RtlZeroMemory is mapped into memset, but use RtlZeroMemory since that is
the documented way to do things in the kernel. Finally, most driver
dispactch routines are called at PASSIVE_LEVEL.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

“huangjj” wrote in message news:xxxxx@ntdev…
>I would clear a local variable in driver dispatch routine.
> Data size is 26 bytes.
> RtlZeroMemory can be called at any IRQL for nonpaged memory.
> However, I don’t know whether local variable belongs to nonpaged memory.
> Does anyone know this answer?
>
> Besides, is it safe to use memset() to clear local variable?
>
> Best Regards
> Jack Huang
>
>

There is one caveat to that rule - if your thread enters waits on an object with a WaitMode of UserMode then the stack may get swapped out to disk while the thread is blocked. Be aware of how the buffers you’re handing out are being used and what sorts of wait operations you’re doing while they are being used and you’ll be okay.

-p

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Tuesday, August 07, 2007 4:58 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Is local variable of driver dispatch routine paged or nonpaged?

Driver stacks are not paged, so you can alway reference the code.
RtlZeroMemory is mapped into memset, but use RtlZeroMemory since that is
the documented way to do things in the kernel. Finally, most driver
dispactch routines are called at PASSIVE_LEVEL.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

“huangjj” wrote in message news:xxxxx@ntdev…
>I would clear a local variable in driver dispatch routine.
> Data size is 26 bytes.
> RtlZeroMemory can be called at any IRQL for nonpaged memory.
> However, I don’t know whether local variable belongs to nonpaged memory.
> Does anyone know this answer?
>
> Besides, is it safe to use memset() to clear local variable?
>
> Best Regards
> Jack Huang
>
>


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

> There is one caveat to that rule - if your thread enters waits on an object with

a WaitMode of UserMode then the stack may get swapped out to disk while the
thread is blocked.

AFAIK, in this context it just does not matter if you wait in the kernel mode or in the user one - the stack may get swapped anyway while the thread is in the waiting state. Don’s statement “driver stacks are not paged” applies only to threads in the running state, because running thread may elevate IRQL at any moment, and, at this point , it will be disallowed to take page faults. However, as long as it is in the waiting state, it just does not matter - before the thread starts running stack swapper will bring its stack back to RAM anyway.

WaitMode parameter has rather different meaning - if thread waits in the user mode, it can get terminated before returning back to the user-mode caller. However, it cannot get terminated
before returning to the user mode if ‘KernelMode’ was specified as WaitMode (non-alertable kernel-mode wait cannot be interrupted by anything until wait condition is satisfied)

Anton Bassov

When waiting in KernelMode, the stack is locked into memory. There are a
lot of special considerations that involve knowing what object is being
waited upon, the thread context, and the IRQL. If you are not the highest
level device in the stack, you must use KernelMode since, except for some
stacks, you can’t be sure that you are running in the caller’s thread
context. FileSystem filters are one place where IRP_MJ_CREATE is normally
guaranteed to remain in the user context down to the FSD since that
information is needed for validating file access rights and to lock buffers
as required.

The WDK 6000 says under KeWaitForSingleObject():
If the WaitMode parameter is UserMode, the kernel stack can be swapped out
during the wait. Consequently, a caller must never attempt to pass
parameters on the stack when calling KeWaitForSingleObject using the
UserMode argument. If you allocate the event on the stack, you must set the
WaitMode parameter to KernelMode.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

wrote in message news:xxxxx@ntdev…
>> There is one caveat to that rule - if your thread enters waits on an
>> object with
>> a WaitMode of UserMode then the stack may get swapped out to disk while
>> the
>> thread is blocked.
>
> AFAIK, in this context it just does not matter if you wait in the kernel
> mode or in the user one - the stack may get swapped anyway while the
> thread is in the waiting state. Don’s statement “driver stacks are not
> paged” applies only to threads in the running state, because running
> thread may elevate IRQL at any moment, and, at this point , it will be
> disallowed to take page faults. However, as long as it is in the waiting
> state, it just does not matter - before the thread starts running stack
> swapper will bring its stack back to RAM anyway.
>
> WaitMode parameter has rather different meaning - if thread waits in the
> user mode, it can get terminated before returning back to the user-mode
> caller. However, it cannot get terminated
> before returning to the user mode if ‘KernelMode’ was specified as
> WaitMode (non-alertable kernel-mode wait cannot be interrupted by anything
> until wait condition is satisfied)
>
> Anton Bassov
>

David,

The WDK 6000 says under KeWaitForSingleObject():
If the WaitMode parameter is UserMode, the kernel stack can be swapped out
during the wait. Consequently, a caller must never attempt to pass
parameters on the stack when calling KeWaitForSingleObject using the
UserMode argument. If you allocate the event on the stack, you must set the
WaitMode parameter to KernelMode.

Actually, I prefer not to take MSDN too literally, and try my best to understand *why* it works this way (although, to be honest, sometimes it leads me to the wrong conclusions). Therefore, let’s do a bit of analysis.

Let’s say you have allocated an event on the stack, and wait on it. Who may possibly have an access to it, apart from your thread??? Who is going to signal it then???

Therefore, the only way you can use this event is to specify it as an argument in IoBuildxxx call in order to build IRP, and then to wait on it after having sent IRP to the target device. When the request completes, IoCompleteRequest() will issue a special kernel-mode APC to the thread, and APC routine will set the event. However, what happens if you have entered the waiting state at APC_LEVEL??? At this point APC delivery to the thread will be disabled, so that IoCompleteRequest(), apparently, will have to signal the event itself, and IoCompleteRequest() for asynchronously completed request normally runs at DPC level. At this point it event’s (and, hence, the target thread’s stack) constant presence in RAM becomes a requirement.

However, when you wait on, say, timer, why should your stack be always present on RAM, especially if you wait for extended periods of time, even if you wait in the kernel mode???

Therefore, I believe that by specifying "KernelMode’ as WaitMode parameter, you just tell the system
to do double-checking, because your stack’s presence in RAM *may* be required - you don’t give it
the precise directive to keep in in RAM all the time (when you specify ‘UserMode’, you tell the system that your stack’s presence in RAM is just not needed). In addition to that, it tells the system how possible thread termination should be handled - a thread that waits in the kernel mode cannot get terminated until the wait is satisfied, but the one that waits in the user mode can be terminated
while in the waiting state…

Anton Bassov

anton bassov wrote:

Therefore, I believe that by specifying "KernelMode’ as WaitMode parameter, you …
a thread that waits in the kernel mode cannot get terminated until the wait is satisfied,
but the one that waits in the user mode can be terminated while in the waiting state…

Btw, is it possible to wait in “UserMode” from a system dedicated thread? The idea is precisely to avoid the stack being locked on long waits.

How about an event that the dispatch code waits upon until your driver’s
completion routine signals it? The event is on the stack of the dispatch
function and is being waited upon. The completion routine may be run at
DISPATCH_LEVEL and the event signaled so your dispatch routine can continue
in the original context of that IRP.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

wrote in message news:xxxxx@ntdev…
> David,
>
>> The WDK 6000 says under KeWaitForSingleObject():
>> If the WaitMode parameter is UserMode, the kernel stack can be swapped
>> out
>> during the wait. Consequently, a caller must never attempt to pass
>> parameters on the stack when calling KeWaitForSingleObject using the
>> UserMode argument. If you allocate the event on the stack, you must set
>> the
>> WaitMode parameter to KernelMode.
>
> Actually, I prefer not to take MSDN too literally, and try my best to
> understand why it works this way (although, to be honest, sometimes it
> leads me to the wrong conclusions). Therefore, let’s do a bit of analysis.
>
> Let’s say you have allocated an event on the stack, and wait on it. Who
> may possibly have an access to it, apart from your thread??? Who is going
> to signal it then???
>
>
> Therefore, the only way you can use this event is to specify it as an
> argument in IoBuildxxx call in order to build IRP, and then to wait on it
> after having sent IRP to the target device. When the request completes,
> IoCompleteRequest() will issue a special kernel-mode APC to the thread,
> and APC routine will set the event. However, what happens if you have
> entered the waiting state at APC_LEVEL??? At this point APC delivery to
> the thread will be disabled, so that IoCompleteRequest(), apparently, will
> have to signal the event itself, and IoCompleteRequest() for
> asynchronously completed request normally runs at DPC level. At this point
> it event’s (and, hence, the target thread’s stack) constant presence in
> RAM becomes a requirement.
>
> However, when you wait on, say, timer, why should your stack be always
> present on RAM, especially if you wait for extended periods of time, even
> if you wait in the kernel mode???
>
> Therefore, I believe that by specifying "KernelMode’ as WaitMode
> parameter, you just tell the system
> to do double-checking, because your stack’s presence in RAM may be
> required - you don’t give it
> the precise directive to keep in in RAM all the time (when you specify
> ‘UserMode’, you tell the system that your stack’s presence in RAM is just
> not needed). In addition to that, it tells the system how possible thread
> termination should be handled - a thread that waits in the kernel mode
> cannot get terminated until the wait is satisfied, but the one that waits
> in the user mode can be terminated
> while in the waiting state…
>
> Anton Bassov
>
>

David,

How about an event that the dispatch code waits upon until your driver’s
completion routine signals it?

In such case you have to pass this event as ‘Context’ parameter to IoSetCompletionRoutine(), and its documentation *explicitly* states that context that we pass to this routine must be stored in *nonpaged* memory, because the completion routine will access it at DPC level. However, pages for the stack don’t belong to nonpaged memory, do they? Therefore, I never tried it…

Anton Bassov

That is the point. If you use KernelMode the stack pages will be nonpaged
memory and will work. Rather common technique, I think.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

wrote in message news:xxxxx@ntdev…
> David,
>
>> How about an event that the dispatch code waits upon until your driver’s
>> completion routine signals it?
>
> In such case you have to pass this event as ‘Context’ parameter to
> IoSetCompletionRoutine(), and its documentation explicitly states that
> context that we pass to this routine must be stored in nonpaged memory,
> because the completion routine will access it at DPC level. However, pages
> for the stack don’t belong to nonpaged memory, do they? Therefore, I never
> tried it…
>
> Anton Bassov
>

David,

That is the point. If you use KernelMode the stack pages will be nonpaged
memory and will work.

Please pay a special attention to the very term *nonpaged* - I am afraid you confuse it with the one ‘locked’.

The term ‘nonpaged’ applies not to the page itself but to the virtual address - it desribes a characteristic feature that cannot get changed, so that the same address cannot be sometimes pageable and sometimes nonpageable. This is why they’ve got paged system area and non-paged one. Examples of nonpaged memory are non-paged pool, device extenstion, etc.

The term ‘locked’ applies to the page itself - it means that the page is not going get swapped to the disk while it is locked. In other words, it desribes page state, i.e. something that will change after
unlocking the page.

Therefore, if stack can be paged out under some circumstances, it cannot be nonpaged memory - the only thing that may happen is that its pages will temporarily get locked in RAM. In other words, by saying “context information must be stored in nonpaged memory”, MSDN, apparently, does not mean stack.

Rather common technique, I think.

Can you name some WDK sample that does it? I’ve seen samples that pass a pointer to the global memory as ‘Context’ parameter to IoSetCompletionRoutine(); I’ve seen samples that pass stack-allocated event to IoBuildDeviceIoControlRequest() or IoBuildSynchronousFsdRequest();
but I haven’t noticed any sample that uses stack-allocated context as a pointer to IoSetCompletionRoutine(). Probably, I just did not look properly…

Anton Bassov

How about 1394api.c and several other files in the same directory. Also
deviosup.c & flush.c from cdfs and fastfat. I saw many source files and not
headers in the WDK that use KEVENT. In most cases the KEVENT is on the
stack and an IRP is created with the event as the context parameter being
passed to the completion routine. The waits are always Executive and
KernelMode so their stack won’t get paged. The cdfs on is where a CD/DVD
has a volume and it is being mounted or unmounted which can take several
seconds depending.

I think you are over defining the word nonpaged and paged. A stack may be
pageable or non-pageable and the OS has rules to decide.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

wrote in message news:xxxxx@ntdev…
> David,
>
>> That is the point. If you use KernelMode the stack pages will be
>> nonpaged
>> memory and will work.
>
>
> Please pay a special attention to the very term nonpaged - I am afraid
> you confuse it with the one ‘locked’.
>
> The term ‘nonpaged’ applies not to the page itself but to the virtual
> address - it desribes a characteristic feature that cannot get changed, so
> that the same address cannot be sometimes pageable and sometimes
> nonpageable. This is why they’ve got paged system area and non-paged one.
> Examples of nonpaged memory are non-paged pool, device extenstion, etc.
>
> The term ‘locked’ applies to the page itself - it means that the page is
> not going get swapped to the disk while it is locked. In other words, it
> desribes page state, i.e. something that will change after
> unlocking the page.
>
> Therefore, if stack can be paged out under some circumstances, it cannot
> be nonpaged memory - the only thing that may happen is that its pages will
> temporarily get locked in RAM. In other words, by saying “context
> information must be stored in nonpaged memory”, MSDN, apparently, does not
> mean stack.
>
>
>> Rather common technique, I think.
>
> Can you name some WDK sample that does it? I’ve seen samples that pass a
> pointer to the global memory as ‘Context’ parameter to
> IoSetCompletionRoutine(); I’ve seen samples that pass stack-allocated
> event to IoBuildDeviceIoControlRequest() or
> IoBuildSynchronousFsdRequest();
> but I haven’t noticed any sample that uses stack-allocated context as a
> pointer to IoSetCompletionRoutine(). Probably, I just did not look
> properly…
>
> Anton Bassov
>
>
>
>

David,

Actually, deviosup.c uses stack-allocated KEVENTs only for IOBuildxxx calls, but flush.c, indeed, does something that you have described - it passes the address of stack-based KEVENT as a parameter
to IoSetCompletionRoutine()…

Anton Bassov

What kind of rules?

Thanks,

On 8/9/07, David J. Craig wrote:
> How about 1394api.c and several other files in the same directory. Also
> deviosup.c & flush.c from cdfs and fastfat. I saw many source files and not
> headers in the WDK that use KEVENT. In most cases the KEVENT is on the
> stack and an IRP is created with the event as the context parameter being
> passed to the completion routine. The waits are always Executive and
> KernelMode so their stack won’t get paged. The cdfs on is where a CD/DVD
> has a volume and it is being mounted or unmounted which can take several
> seconds depending.
>
> I think you are over defining the word nonpaged and paged. A stack may be
> pageable or non-pageable and the OS has rules to decide.
>
> –
> David J. Craig
> Engineer, Sr. Staff Software Systems
> Broadcom Corporation
>
>
> wrote in message news:xxxxx@ntdev…
> > David,
> >
> >> That is the point. If you use KernelMode the stack pages will be
> >> nonpaged
> >> memory and will work.
> >
> >
> > Please pay a special attention to the very term nonpaged - I am afraid
> > you confuse it with the one ‘locked’.
> >
> > The term ‘nonpaged’ applies not to the page itself but to the virtual
> > address - it desribes a characteristic feature that cannot get changed, so
> > that the same address cannot be sometimes pageable and sometimes
> > nonpageable. This is why they’ve got paged system area and non-paged one.
> > Examples of nonpaged memory are non-paged pool, device extenstion, etc.
> >
> > The term ‘locked’ applies to the page itself - it means that the page is
> > not going get swapped to the disk while it is locked. In other words, it
> > desribes page state, i.e. something that will change after
> > unlocking the page.
> >
> > Therefore, if stack can be paged out under some circumstances, it cannot
> > be nonpaged memory - the only thing that may happen is that its pages will
> > temporarily get locked in RAM. In other words, by saying “context
> > information must be stored in nonpaged memory”, MSDN, apparently, does not
> > mean stack.
> >
> >
> >> Rather common technique, I think.
> >
> > Can you name some WDK sample that does it? I’ve seen samples that pass a
> > pointer to the global memory as ‘Context’ parameter to
> > IoSetCompletionRoutine(); I’ve seen samples that pass stack-allocated
> > event to IoBuildDeviceIoControlRequest() or
> > IoBuildSynchronousFsdRequest();
> > but I haven’t noticed any sample that uses stack-allocated context as a
> > pointer to IoSetCompletionRoutine(). Probably, I just did not look
> > properly…
> >
> > 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
>

> flush.c, indeed, does something that you have described - it passes the

address of stack-based KEVENT as a parameter to IoSetCompletionRoutine()
This happens in FatHijackIrpAndFlushDevice.

Now, from H:\WinDDK\6000\src\filesys\fastfat\wxp\flush.c:

#pragma alloc_text(PAGE, FatHijackIrpAndFlushDevice)

Yes, FatHijackIrpAndFlushDevice waits for this stack-based event, but
it should not matter - nobody said that CR will be called in the same
thread.

Looks like a bug, no?

Here’s my logic: the code and its stack go together so that when the
code is accessible (resident) so is the stack of the thread it runs in.
“Stack’s fate == code fate.”

FatHijackIrpAndFlushDevice is pageable, it sets its
FatHijackCompletionRoutine which may run in a different context,
so at this moment in time the memory range that FatHijackIrpAndFlushDevice
used to allocate the KEVENT may be paged out.

The fact that FatHijackIrpAndFlushDevice waits for this event does not
change anything: pretty soon its code will be pulled back in from
pagefile.sys along with its stack (with a KEVENT inside), but …

Am I missing something?

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Thursday, August 09, 2007 3:34 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Is local variable of driver dispatch routine paged or nonpaged?

David,

Actually, deviosup.c uses stack-allocated KEVENTs only for IOBuildxxx calls, but flush.c, indeed, does something that you have described - it passes the address of stack-based KEVENT as a parameter
to IoSetCompletionRoutine()…

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

Alex,

Consider the scenario when FatHijackCompletionRoutine() runs at DPC level - it sets the event, which means the event has to be in RAM all the time. Therefore, the equation “Stack’s fate == code fate” does not necessarily hold true - FatHijackCompletionRoutine() does not need FatHijackIrpAndFlushDevice()'s code to be present in RAM, but if it runs at DPC level, the original caller’s stack has to be present in RAM all the time, because the context it accesses the context that
had been allocated on the original caller’s stack…

Anton Bassov

>FatHijackIrpAndFlushDevice is pageable, it sets its

FatHijackCompletionRoutine which may run in a different context,
so at this moment in time the memory range that FatHijackIrpAndFlushDevice
used to allocate the KEVENT may be paged out.

No.

The “pageable function calls IoCallDriver and then waits for a stack-placed
event signaled from the nonpageable completion routine” is one of the most
common and safe patterns in driver development.

Stack can be paged out if the thread is in UserMode wait. If the thread is
running/ready/in KernelMode wait - the stack cannot be paged out.

So, KEVENT on the stack is safe, even if the code of FatHijackIrpAndFlushDevice
is paged out.

The completion routine is also safe, since it is nonpageable.


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

> Stack can be paged out if the thread is in UserMode wait.
Yep, that’s the key, my bad.
Forgot about it.
My hunch was telling me that I’m wrong but where?

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Thursday, August 09, 2007 5:36 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Is local variable of driver dispatch routine paged or nonpaged?

FatHijackIrpAndFlushDevice is pageable, it sets its
FatHijackCompletionRoutine which may run in a different context,
so at this moment in time the memory range that FatHijackIrpAndFlushDevice
used to allocate the KEVENT may be paged out.

No.

The “pageable function calls IoCallDriver and then waits for a stack-placed
event signaled from the nonpageable completion routine” is one of the most
common and safe patterns in driver development.

Stack can be paged out if the thread is in UserMode wait. If the thread is
running/ready/in KernelMode wait - the stack cannot be paged out.

So, KEVENT on the stack is safe, even if the code of FatHijackIrpAndFlushDevice
is paged out.

The completion routine is also safe, since it is nonpageable.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
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

> the equation “Stack’s fate == code fate” does not necessarily hold true
… and you are saying “why” whilst Max explained “how”.
Thanks guys.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Thursday, August 09, 2007 5:16 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Is local variable of driver dispatch routine paged or nonpaged?

Alex,

Consider the scenario when FatHijackCompletionRoutine() runs at DPC level - it sets the event, which means the event has to be in RAM all the time. Therefore, the equation “Stack’s fate == code fate” does not necessarily hold true - FatHijackCompletionRoutine() does not need FatHijackIrpAndFlushDevice()'s code to be present in RAM, but if it runs at DPC level, the original caller’s stack has to be present in RAM all the time, because the context it accesses the context that
had been allocated on the original caller’s stack…

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