The device numbering issue is EXACTLY one of the examples I mention. Then I
mention that it has interesting implications, such as it depends on the
order of enumeration of the devices, or for USB, the order of detection,
which has its own interesting set of implications…
The other one is the statistics (in fact, we chose the USB sniffer example
because it REQUIRES a global variable, just so we’d have an excuse to talk
about the global variable and how it has to be used.
Cross-controller global state: well, if it is different logical devices on
the same physical hardware, wouldn’t that be handled by a CONTROLLER_OBJECT?
You aren’t missing anything; also, you didn’t mention the trick of saving
the driver key from DriverEntry into a write-once global. And note that I
said “subject to roundoff error”.
OTOH, the number of crap drivers I’ve had to diagose where the programmer
uses a static local variable to hold state across two calls, or puts things
in a global variable (like a buffer pointer used by the ISR) “just because
that’s how you do it” are really horrendously high. While I don’t write
drivers, I get called in to diagnose drivers. I usually spend a few hours
reading the source code, looking for the global variables (usually too
many), static local variables (not often, but there in a few drivers), and
bad use of (or failure to use) spin locks. I look at every ++ or – to make
sure it isn’t using thread-shared data. I look for NT_SUCCESS tests instead
of == STATUS_SUCCESS. Then, after I’ve identified all the simple problems,
I start looking for the second-order disasters: failure to pass down power
IRPs, using the PnP completion trick in the Power handlers, and of course,
run the driver verifier (MTTF: < 2 seconds in 90% of the drivers I’ve had to
diagnose! Plug in USB connector, watch verifier choke…)
Nearly all of these drivers were written by offshore outsourcing, or by “Our
summer intern”.
Mostly, the use of global variables ignores both the notion of more than one
instance of the device (unlike the device-name counter, which exists BECAUSE
of multiple instances) or the notion of threading. So the warning “only if
you think about the implications” is the indication that the programmer
needs to *think* [Oh! Horror!] about *why* a global variable is used, *how*
it is used, *when* it is used, etc.
Oh, and here’s a great pattern I found, in two different drivers, from two
different unrelated companies:
InterlockedIncrement(&counter);
if(counter > value)
{
DoSomething(counter);
}
Where, in fact, this code could be hit by multiple threads at the same time.
The explanation (from the company that had their in-house programmer write
the driver): “Well, I was told that if I didn’t use InterlockedIncrement,
the counter wouldn’t increment properly. But once I’ve incremented it, then
it’s safe to use”. Duh. And yes, one of the drivers only failed on
multiprocessors (and should have on uniprocessors, but obviously luck was
present), but the bug was discovered by a customer who plugged two cards in
(Explanation for the static variable: “I didn’t put it in the device
extension because that would be too expensive to access it through a
pointer”)
joe
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@osr.com
Sent: Sunday, December 21, 2008 11:52 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] app or driver
How about… DEVICE NUMBER that’s used as part of the device name (ADC0,
ADC1, … ADCn)? How about global statistics? How about any
cross-controller global state… which is, ah, the definition of why you’d
have global data in your driver that’s not ‘const’.
What am I missing, pray tell?
Peter
OSR
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.