Hi, all:
The wdk says
Driver code must be pageable if the driver does any of the following:
Accesses paged pool
Calls another pageable routine
References user buffers in the context of the user thread
But how can I know whether a routine which is called by my code is pageable or not without knowing implement of the routine(e.g ZwWriteFile)?
Best regards.
When calling system routines you must not think of them if they are pageable
or not. You must think interms of your IRQL and if the documentation says
that the particular API can be called from your particular IRQL.
for example : here is the documentation extract for *ZwWriteFile*
*" Requirements*
*IRQL: *PASSIVE_LEVEL (see Comments section)"
" Callers of *ZwWriteFile* must be running at IRQL = PASSIVE_LEVEL and with
APCs enabled."
Obeying this detail takes care of any dependency that API might have and it
will work as documented.
-rtshiva
On Wed, Aug 12, 2009 at 1:36 PM, wrote:
> Hi, all:
>
> The wdk says
> Driver code must be pageable if the driver does any of the following:
>
> Accesses paged pool
> Calls another pageable routine
> References user buffers in the context of the user thread
>
> But how can I know whether a routine which is called by my code is pageable
> or not without knowing implement of the routine(e.g ZwWriteFile)?
>
> Best regards.
>
> —
> 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
>
> But how can I know whether a routine which is called by my code is pageable or not without knowing
implement of the routine(e.g ZwWriteFile)?
You do not care.
You only care about the IRQL restrictions of the routine, which are documented.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
Words are misleading,
I searched for this on internet and checked the cached copy(google) of msdn and found this.
"Slight Wording Change Last Edit 11:34 PM by Tim Roberts
The wording above is just a bit confusing. When it says “Driver code must be pageable if the driver does any of the following”, it doesn’t mean that any function that does those things must be marked pageable. Rather, what it means is “Driver code cannot be in a non-pageable state when it does any of the following.” A non-pageable routine can certainly access paged pool, as long as it is not in a non-pageable state.
In fact, what it really means is that “any code that does any of the second three bullets cannot also do any of the first three bullets.”
– Tim"
I hope it clears the doubt.
Thanks
Aditya
>
> But how can I know whether a routine which is called by my code is
pageable
or not without knowing
>implement of the routine(e.g ZwWriteFile)?
You do not care.
You only care about the IRQL restrictions of the routine, which are
documented.
Two weeks ago I would have agreed with you, but if your driver is in the
paging path you have to be careful too when restoring from
hibernation…
On boot, things like ‘PsCreateSystemThread’ (PASSIVE_LEVEL) and
‘ExQueueWorkItem’ (<=DISPATCH_LEVEL) work fine, as there is no pagefile
yet to page out to, so the routines can’t possibly be paged out.
On resume from hibernation though, the ‘PsCreateSystemThread’ routine
itself (eg the page in the kernel that holds the code or data for that
routine) might have been paged to disk, and ‘ExQueueWorkItem’ itself
completes, but you might find that your work item never actually gets
any CPU time as all the worker threads are blocked waiting for the page
file [1].
If you have a scsiport or a storport driver and the device is enumerated
by the PCI bus then you probably never have to worry about such things
(assuming you obey the harsh restrictions placed on scsiport and
storport drivers - I have some better appreciation for why they exist
now :). My Xen drivers though have a bus driver which enumerates a pdo
and then my scsiport driver attaches to that, so I had to be extra
careful in my bus driver or I saw hangs on resume from hibernation (very
occasionally during normal use, and every time with the verifier
enabled).
James
[1] This is inferred by what I have observed. I may well have the cause
wrong but the net result is that when I do ‘ExQueueWorkItem’ when the
pagefile is not yet available on a resume from hibernation.
Thanks all.
And I have another question. If my code called KeAcquireSpinLock, should I add #pragma alloc_text(NONPAGED, DriverDispatch) in my code?
Dear James,
i am not sure i understand the scenario you are describing. The
driver is in passive mode, shouldn’t the code ( even those that are paged
out would ) be paged back in and then control be transfered to it ? why
would it wait on something that is paged out when you are in PASSIVE_LEVEL
?
-rtshiva
On Wed, Aug 12, 2009 at 2:46 PM, James Harper > wrote:
> >
> > > But how can I know whether a routine which is called by my code is
> pageable
> > or not without knowing
> > >implement of the routine(e.g ZwWriteFile)?
> >
> > You do not care.
> >
> > You only care about the IRQL restrictions of the routine, which are
> > documented.
> >
>
> Two weeks ago I would have agreed with you, but if your driver is in the
> paging path you have to be careful too when restoring from
> hibernation…
>
> On boot, things like ‘PsCreateSystemThread’ (PASSIVE_LEVEL) and
> ‘ExQueueWorkItem’ (<=DISPATCH_LEVEL) work fine, as there is no pagefile
> yet to page out to, so the routines can’t possibly be paged out.
>
> On resume from hibernation though, the ‘PsCreateSystemThread’ routine
> itself (eg the page in the kernel that holds the code or data for that
> routine) might have been paged to disk, and ‘ExQueueWorkItem’ itself
> completes, but you might find that your work item never actually gets
> any CPU time as all the worker threads are blocked waiting for the page
> file [1].
>
> If you have a scsiport or a storport driver and the device is enumerated
> by the PCI bus then you probably never have to worry about such things
> (assuming you obey the harsh restrictions placed on scsiport and
> storport drivers - I have some better appreciation for why they exist
> now :). My Xen drivers though have a bus driver which enumerates a pdo
> and then my scsiport driver attaches to that, so I had to be extra
> careful in my bus driver or I saw hangs on resume from hibernation (very
> occasionally during normal use, and every time with the verifier
> enabled).
>
> James
>
> [1] This is inferred by what I have observed. I may well have the cause
> wrong but the net result is that when I do ‘ExQueueWorkItem’ when the
> pagefile is not yet available on a resume from hibernation.
>
>
> —
> 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
>
My driver is a disk class upperfilter. Without some my functions executed, maybe the system can not read from or write into the disk. So should these code be resident? If I simply make all my code nonpaged, will it cause errors(ignore affect on performance)?
>>The driver is in passive mode, shouldn’t the code ( even those that are paged out would ) be paged back in and then control be transfered to it ? why would it wait on something that is paged out when you are in PASSIVE_LEVEL ?
Notice that he said “if your driver is in paging path”, i.e. is among the driver which get called when some page fault need to be satisfied.
Thanks
Aditya
>
Dear James,
i am not sure i understand the scenario you are describing. The
driver
is in passive mode, shouldn’t the code ( even those that are paged out
would )
be paged back in and then control be transfered to it ? why would it
wait on
something that is paged out when you are in PASSIVE_LEVEL ?
When you resume from hibernate, some tasks need to be completed before
the disk(s) holding the paging file are actually available. Some of
those tasks will be done at PASSIVE_LEVEL but obviously any attempt to
page will actually deadlock.
James
> Two weeks ago I would have agreed with you, but if your
driver is in the paging path you have to be careful too when
restoring from hibernation…
I’ll second that. Code/data in the paging/hibernation path needs to not
cause page faults, even if it’s running at passive_level. Or code/data in a
worker thread, needed to support code/data in the paging path. There also
are some little gotchas at system shutdown time like in a last chance
shutdown irp hander which is at passive_level but the pagefile volume has
been unmounted, or the power irp handler. The docs fuzzily mention some of
these passive_level with no page fault cases. A debugprint of a unicode
string is bad at these times too, as the unicode translation table is
pageable. It’s a good storage driver developer interview question, “is it
always ok to dbgprint unicode strings if your at passive level?”. The
dbgprint/dbgprintex docs seem to say yes, which is wrong (guess I should
click the feedback link). Crashing the OS right at system shutdown is very
rude, and unless a debugger is attached, you may not even know the system
crashed. It’s one of the reasons I suggest driver QA machines sometimes run
with enabled kernel debuggers.
Jan
So can I get a conclusion : if my code is paged out to the disk, when it is needed to execute, the code can be paged back, then my code is pageable, otherwise it is nonpageable?
Although James & Jan gave you excellent answers, they were talking about very specific edge cases that grossly complicate the picture, so unless you are writing a driver in the paging path or something to do with the hibernation stack, you’ll find it easier and totally safe to just follow the rules about IRQL. That works almost all the time.
Regarding your question about whether it would be a problem to mark everything as NONPAGED, the answer is that no it wouldn’t and it’s actually redundant, as that is what the linker defaults to. Conversely, if you want something to appear in a PAGED segment, you have to use #pragma to put it there.
Regarding your question about how you can tell if some API is paged or not, again, don’t worry about it - make sure that you are at the appropriate IRQL or lower when you call it, and all will be fine.
Regarding whether your functions can be safely marked as paged, the answer is once again to see what IRQL a given function will be called at, and if it’s elevated, then your function must be resident.
That statement you quoted originally is confusing in my opinion, and this is one of those things that one can easily make much more out of than there is in practice, leaving out the paging/hiber cases. I mean, to be sure, errors involving IRQL a HUGE percentage of the errors caused by drivers, but that’s not in my opinion about understanding as much as it is about discipline and testing.
Good luck,
mm
>
Although James & Jan gave you excellent answers, they were talking
about very
specific edge cases that grossly complicate the picture, so unless you
are
writing a driver in the paging path or something to do with the
hibernation
stack, you’ll find it easier and totally safe to just follow the rules
about
IRQL. That works almost all the time.
According to the OP, “My driver is a disk class upperfilter”. Unless it
is a disk class upperfilter that is never ever attached to a disk device
in the paging path, then the “specific edge cases” could be quite
relevant.
James
Thanks James and Aditya, i didnt notice the “in the paging path” part of the
explanation :). i have another question dont want to takeover the thread
now, will followup once the OP finished solving his issue.
-rtshiva
On Thu, Aug 13, 2009 at 10:36 AM, James Harper <
xxxxx@bendigoit.com.au> wrote:
>
> Although James & Jan gave you excellent answers, they were talking
about very
> specific edge cases that grossly complicate the picture, so unless you
are
> writing a driver in the paging path or something to do with the
hibernation
> stack, you’ll find it easier and totally safe to just follow the rules
about
> IRQL. That works almost all the time.
>
According to the OP, “My driver is a disk class upperfilter”. Unless it
is a disk class upperfilter that is never ever attached to a disk device
in the paging path, then the “specific edge cases” could be quite
relevant.
James
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
Thanks James&MM.
But can you explain how can I know whether a disk device is in the paging path or not?
Is it the system/boot drive? Does it have a pagefile.sys being used by the
currently executing operating system? Has any executable been executed from
that drive?
I think you are looking to over optimize and to do premature optimization.
Just don’t put in any directives for paging your code segments and let it
all be resident. I think the build environment will automatically page
DriverEntry for PnP drivers, but worry about that form of optimization later
after you understand how your driver interacts with the OS and the stack
where it is a member. Also stay away from C++ in the kernel as you can get
automatically generated functions created in unexpected segments where they
can cause a BSOD.
wrote in message news:xxxxx@ntdev…
> Thanks James&MM.
> But can you explain how can I know whether a disk device is in the paging
> path or not?
>
You will get a irp_mj_pnp/irp_mn_usage_notification with the type set to paging. Kmdf has a xallback for this
d
Sent from my phone with no t9, all spilling mistakes are not intentional.
-----Original Message-----
From: kuangnuzhiren@163.com
Sent: Thursday, August 13, 2009 2:32 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to judge a routine pageable?
Thanks James&MM.
But can you explain how can I know whether a disk device is in the paging path or not?
—
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
No. The default is nonpaged. You only have to mark code explicitly
pageable if you decide you want a routine to be pageable. In 16 years
I’ve never felt the need to do this to any driver routine.
Mark Roddy
On Wed, Aug 12, 2009 at 5:27 AM, wrote:
> Thanks all.
> And I have another question. If my code called KeAcquireSpinLock, should I add #pragma alloc_text(NONPAGED, DriverDispatch) in my code?
>
> —
> 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
>
>According to the OP, “My driver is a disk class upperfilter”. Unless it
is a disk class upperfilter that is never ever attached to a disk device
in the paging path, then the “specific edge cases” could be quite
relevant.
My bad; missed that part.
mm