Tech Support > Microsoft Windows > Drivers > Hyperthread issue
Hyperthread issue
Posted by Kans on November 14th, 2006


Hi ,

I have developed a virutal ethernet driver which runs on a pci card.
This works fine on a single cpu machine(celeron) with windows XPE.

when i want the same to work on the hyperthread machine (p4) with
windows XPE, i am facing a problem.

Send handler running in the Dispatch level, is called for the second
time by the same cpu(say cpu 1), even before the first call gets
completed.

The send handler holds a spinlock within that is sends the
acknowledgements to the application.

During the 2nd call, when the cpu tries to acquire the spinlock, the
system hangs.

Please let me know whether the above phenomenon is proper and how to
avoid this race condition.

Regards,
Kans.

Posted by soviet_bloke@hotmail.com on November 14th, 2006



How can something like that possibly happen????? When you hold a
spinlock, you are at DISPATCH_LEVEL, and, hence, the *ONLY* thing that
can interrupt execution of your code is hardware interrupt. Therefore,
the second call just cannot be processed by CPU1 until IRQL drops below
DISPATCH_LEVEL

In other words, you have to investigate your problem more thoroughly,
and provide us with more accurate description of it


Anton Bassov


Kans wrote:

Posted by Stephan Wolf [MVP] on November 14th, 2006


Sounds like you are calling some NDIS function from your send handler
while you are holding a spin lock. This is a programming fault, i.e.
you must not call any NDIS function while holding a spin lock because
NDIS may in turn call your miniport. If you then try to acquire the
same spin lock the current processor will deadlock.

If you are facing problems writing an NDIS miniport driver that is
multiprocessor safe, you can choose to use the "serialized" instead of
the "deserialized" NDIS miniport model. In a "serialized" miniport,
there is only at most one function active at any time (except for the
MiniportISR(), which can always run).

As a result, a "serialized" miniport does not need to use any spin
locks.

Otherwise, if you want to keep going with the "deserialized" model, we
will be happy to help you understand the way the system handles
synchronization mechanisms like spin locks.

Stephan
---
Kans wrote:

Posted by soviet_bloke@hotmail.com on November 14th, 2006


Stephan,

This is quite interesting idea......


In fact, the only possible reason why NDIS may call miniport's send
handler is NdisSend()
(or NdisSendPackets()) call that is made by a bound protocol. There is
a good chance that,
instead of returning NDIS_STATUS_PENDING, his send handler calls
NdisMSendComplete(). As a result, protocol's ProtocolSendComplete()
gets invoked, so that protocol sends one more packet (this is quite
likely to happen if the transmission has to be split into several
packets). At the same time, I think a code like that would not work on
UP machine either, and, according to the OP, it works just fine when HT
is disabled

I think the only way to detect a bug is to actually see the OP's
code...

Anton Bassov


Stephan Wolf [MVP] wrote:

Posted by Kans on November 14th, 2006


Thanks stephan.

Yes, I am calling NdisMEthIndicateReceive while holding the spinlock.

If I am changing it to a serialized driver, how does the DPCHandler and
SendHandler are scheduled to execute?

--
Kans.

Stephan Wolf [MVP] wrote:

Posted by soviet_bloke@hotmail.com on November 15th, 2006


Are you doing it right from MiniportSend()?????? It cannot be that bad,
can it - after all, you told us that your driver works fine on UP
machine.....

However, if you do it from DPC handler....... well, you can deadlock if
bound protocol's ProtocolReceive() calls NdisSend() and MiniportSend()
tries to acquire a spinlock that DPC handler holds, but then the
problem is quite different from the one that you have originally
described, don't you think???? After all, there is no nested call
to MiniportSend() at DISPATCH_LEVEL that you have described in your
original post - instead, MiniportSend() call is nested within a call to
DPC handler. This is a standard situation that anyone familiar with
NDIS would immediately recognize. Therefore, as I already told you, you
should try to give an accurate description of your problem

In general, you should keep in mind that, whenever miniport calls any
function that indicates
something to NDIS, it can receive a nested call, so you should be
carefull with spinlocks

Anton Bassov



Kans wrote:

Posted by Stephan Wolf [MVP] on November 15th, 2006


Kans wrote:
There is always some way to avoid holding a spin lock while calling
NDIS. If you think you cannot release the spin lock, your design needs
to be revised.

Please note that the serialized model implies some performance
penalties. If you are planning to get the maximum performance out of
your miniport, you are bound to the deserialized model. On the other
hand, serialized is ways easier to implement as you do not have to
bother with any synchronization issues.

As a general rule, serialized and deserialized have much in common. The
major difference is the fact that NDIS makes sure it does not call more
than one MiniportXxx() function at any time.

Some other differences apply however. In order to keep things easy, I
suggest you provide a MiniportSend() function rather than a
MiniportSendPackets() function. Note that you need to provide only one
of these two functions.

Make sure to carefully read the description of MiniportSend().
Especially understand the way NDIS handles a return status of
NDIS_STATUS_RESOURCES.

Another rule to follow is that you should call any NDIS complete
functions only from your MiniportHandleInterrupt(). For instance, do
*not* call NdisMSendComplete() from your MiniportSend().

If you have an immediate send status other than NDIS_STATUS_PENDING
available in your MiniportSend(), simply return this status. In this
case, NdisMSendComplete() must not be called.

Otherwise, if your MiniportSend() returns NDIS_STATUS_PENDING, you need
to call NdisMSendComplete() from your MiniportHandleInterrupt().

Stephan


Posted by Kans on November 15th, 2006


Stephen,

Thanks for your comments and support.

As of now I am using the serialized driver. The driver is working fine
throughout the day.

As I stated in my first posting, this driver is virtual network driver.
The driver handles the tcp, ip, icmp, arp protocol management.

so there raises the contention for Rx (from board to application) and
Tx ( application to the board), which sends the acknowledgement to the
application. so I should use spinlocks to protect the data (Rx and the
Acks).

I my case, if the driver needs to be deserialized, as you have
mentioned NdisMcomplete() function should be called from
InterruptHandler and MiniportSend() returning NDIS_STATUS_PENDING.

for making that change, I need to analyze the impact in the
functionality, as my receive(interrupthandler) function will force to
get tcp ack from the host. This will lead to more design changes.

One more question:

the eventlog(eventviewer)
"The system detected that network adapter <device description in INF> -
Packet scheduler Miniport was connected to the network, and has
initiated normal operation over the network adapter"

is filled with the above message every 5 secs. What could be the
reason? I am not using NdisWriteEventLogEntry in my driver. What
should I do to avoid that?

--
Kans

Stephan Wolf [MVP] wrote:

Posted by Stephan Wolf [MVP] on November 15th, 2006


Kans wrote:
No spin locks are required at all in a serialized miniport as there can
be no more than one thread/function at any time accessing some
resource.

As a general rule, it is a good idea to call any NDIS complete handlers
only from MiniportHandleInterrupt() context. (Timer callbacks are also
ok.)

This restriction is AFAIK a must for serialized drivers. Deserialized
drivers are however allowed to call NDIS complete handlers from just
anywhere, but I would not recommend to do so either (as doing so is
usually not required anyway).

Umm, you cannot wait for any acknowledges in a miniport as you are
usually at IRQL DISPATCH_LEVEL. But even at lower IRQL I would strongly
recommend to not actively wait for any external events. Instead, use
mechanisms like NdisScheduleWorkItem() to handle any delayed events.

Not sure as to *why* you see this message, but can probably avoid it by
simply disabling the Packet Scheduler for your miniport in the network
configuration.

Also, it is a good idea to run the official NDISTest tool against your
miniport, see

"Testing Network Drivers with NDIS the Test Tool"
http://www.wd-3.com/archive/NDISTest.htm

"Using NDISTest During Driver Development"
http://www.microsoft.com/whdc/DevToo.../NDIStest.mspx

Stephan


Posted by Pavel A. on November 15th, 2006


"Stephan Wolf [MVP]" wrote:
Stephan,
is this still true for multi-CPU machines? Will NDIS ensure for
a serialized miniport, that only one timer or interrupt DPC runs
at any time on all CPUs?

Usually these messages mean that media connect/disconnect events osccur on
the interface.

Regards,
--PA


Posted by Stephan Wolf [MVP] on November 16th, 2006


Pavel A. wrote:
[..]
AFAIK, yes. But now that you are asking I am not actually sure. OTOH,
the whole sense and idea of "serialized" would be broken if more than
one miniport routine could run at any time (except for MiniportISR() of
course).

[Packet Scheduler]
Ah, yes, indeed.

Stephan


Posted by Pavel A. on November 18th, 2006


Thanks Stephan. I've asked this out of pure curiosity.
After having learned about synch in NDIS, I guess there is no
reason to go back for the serialized model.
--PA

"Stephan Wolf [MVP]" <stewo68@hotmail.com> wrote in message news:1163687251.625380.32820@e3g2000cwe.googlegrou ps.com...


Posted by Stephan Wolf [MVP] on November 19th, 2006


Pavel A. wrote:
Well, "serialized" can still make sense if performance is not the major
issue. Also, a serialized miniport can be implemented much quicker than
a deserialized one.

Stephan



Similar Posts