views:

197

answers:

1

Note: This is not a problem i'm experiencing, but it is something i'd like to understand (just because i want to be a better person, and to further the horizon of human understanding).

In the bonus chapter of Raymond Chen's book,

alt text

Raymond gives the example of a bug in a sound card driver:

The original function, called at hardware interrupt time, looks like this in the DDK:

void FAR PASCAL midiCallback(NPPORTALLOC pPortAlloc, WORD msg,
                             DWORD dwParam1, DWORD dwParm2) {
   if (pPostAlloc->dwCallback)
      DriverCallBack(pPortalloc->dwCallback, HIWORD(pPortalloc->dwFlags),
                     pPortalloc->hMidi, msg, dwParam1, dwParam2);
}

Their version of the function looked like this:

void FAR PASCAL midiCallback(NPPORTALLOC pPortAlloc, WORD msg,
                               DWORD dwParam1, DWORD dwParm2) {
   char szBuf[80];

   if (pPostAlloc->dwCallback) {
      wsprintf(szBuf, " Dc(hMidi=%X,wMsg=%X)", pPortalloc->hMidi, msg);
#ifdef DEBUG
   OutputDebugString(szBuf);
#endif
      DriverCallBack(pPortalloc->dwCallback, HIWORD(pPortalloc->dwFlags),
                     pPortalloc->hMidi, msg, dwParam1, dwParam2);
   }
} 

Not only is there leftover debug stuff in retail code, but it is calling a noninterrupt- safe function at hardware interrupt time. If the wsprintf function ever gets discarded, the system will take a segment-not-present fault inside a hardware interrupt, which leads to a pretty quick death.

Now if i'm looking at that code i wouldn't have guessed that a call to the library function wsprintf would be a problem. What happens if my driver code needs to make use of the Win32 API?

What is a segment fault? i understand the concept of a page-fault: the code i need is sitting on a page that has been swapped out to the hard-drive, and will need to get back from the hard drive before code execution can continue. What is a segment fault when we're inside a device-driver's interrupt?

Is page-faults the protected mode equivalent of a segment-fault? How does one avoid segment faults? Does Windows ever swap out device driver code? How would i stop "wsprintf from being discarded"? What would cause wsprintf to be "discarded"? What is "discarded"? What is the virtue of discarding? When it something *un*discarded

Why is calling an API call from inside a driver bad, and how would one work around it?

+3  A: 

A segmentation fault normally refers to an invalid memory access. In most modern operating systems the mechanism which generates seg-faults is also used to provide the demand paging mechanism. What they tend to do is "swap" pages of memory out to disc and mark them as invalid, the next time an instruction accesses that bit of memory the kernel recognises that it isn't really an error and will page in memory.

Windows cannot handle page-faults in certain contexts, one of them being in an interrupt. That is just the way it is designed. For example imagine you get a page fault in the code which reads memory pages data from the disk drive, how could it possible handle such an occurrance? So they define certain limitations on what modes of operation are allowed to page and what are not. If you cause a page fault in an interrupt the kernel will force a BSOD.

What you are supposed to do in an interrupt context if you need to do something which might need paging is to queue what is called a Deferred Procedure Call (DPC) in the interrupt handler. The DPC is then executed at DPC level (something you will see mentioned if you read some of the descriptions of DDK functions). DPC level can page and so you can use any function you need.

As for driver stuff, you can mark some of your code as non-pageable and you can allocate non-paged-pool which is memory you can access without causing page-faults. wsprintf could be paged out because no-one has used it and the kernel reclaims the memory.

tyranid
Is *wsprintf* part of "my code", that i can mark not pageable? Or is it stuck being pageable?
Ian Boyd