KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

All,

I have a function that may be called at IRQL <= DISPATCH, I was using KeAcquireSpinLockAtDpc when IRQL == DISPATCH, but I’m experiencing what appear to be random deadlocks. I read that KeAcquireSpinLockAtDpc may block while I also read that it should be used for better performance in a driver.

KeAcquireSpinLock() may be called at IRQL <= DISPATCH, so what is the real difference between these two?

I’ve switched to always use KeAcquireSpinLock to see if the periodic deadlocks go away, my understanding is that this will do nothing if I’m already at DISPATCH.

Thanks in advance
~kenny

Hi,

It seems that if you are already at DPC and you call KeAcquireSpinLock
instead of KeAcquireSpinLockAtDpc than you spend some more time on that
instruction (If I remember correctly, something like 20ns compared with
80ns on my system). So if that time matters to you, you should call the
right function. On the other hand, calling KeAcquireSpinLockAtDpc when
you are not in DPC is a real problem that must be avoided.

In order to face the deadlock you should simply use Windbg to see what
each processor is doing. If this is a real deadlock than you will see
two processors each holding one lock while trying to acquire another.
You might also try and see what all the threads in the system are doing
(!process 0 7) in order to see the deadlock.

A different option that you might see is that someone took a spinlock
and didn’t free it.

Another option that I once saw was this: I have called a function in DPC
level that could only be allowed to be called at passive level. What
happened is that the same thread was replaced by a DPC and again the
system was locked. At that specific case, running with the verifier
found this immediately.

Thanks
Tzachi

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@netapp.com
Sent: Friday, May 18, 2007 6:46 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

All,

I have a function that may be called at IRQL <= DISPATCH, I
was using KeAcquireSpinLockAtDpc when IRQL == DISPATCH, but
I’m experiencing what appear to be random deadlocks. I read
that KeAcquireSpinLockAtDpc may block while I also read that
it should be used for better performance in a driver.

KeAcquireSpinLock() may be called at IRQL <= DISPATCH, so
what is the real difference between these two?

I’ve switched to always use KeAcquireSpinLock to see if the
periodic deadlocks go away, my understanding is that this
will do nothing if I’m already at DISPATCH.

Thanks in advance
~kenny


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online
at http://www.osronline.com/page.cfm?name=ListServer

> KeAcquireSpinLock() may be called at IRQL <= DISPATCH, so what is the real

difference between these two?

KeAcquireSpinLock raises to DISPATCH and then acquires spinlock.

KeAcquireSpinLockAtDpcLevel omits the first step - it just acquires the
spinlock.

You can use KeAcquireSpinLockAtDpcLevel only when you’re absolutely sure you’re
at DISPATCH.


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

If you were seeing deadlocks, then I submit that your code wasn’t always
correct that it was running at DISPATCH_LEVEL when it called
KeAcquireSpinlockAtDpc.

But, to answer your more general question, as Max said, KeAcquireSpinlock
raises to DISPATCH_LEVEL and then acquires a spinlock.
KeAcquireSpinlockAtDpc just acquires the spinlock.

Your next question is probably “what is entailed in raising to
DISPATCH_LEVEL?” The answer depends on what HAL you’re using. Since the
vast majority of machines today are using a HAL that uses the APIC interrupt
controller, and since nearly all future machines will, the answer for that
HAL is by far the most useful.

Raising to DISPATCH_LEVEL is a matter of writing a value to the “Task
Priority Register” in the processor’s Local APIC. (A checked build will
read that register first and verifiy that the previous value was
DISPATCH_LEVEL or lower.) It’s worth noting here that KeGetCurrentIrql will
read the TPR, which is about as expensive as writing it. So you don’t make
your code any more efficient by checking for current IRQL before deciding
whether to use KeAcquireSpinLock or KeAcquireSpinLockAtDpc. If your
function can be invoked at APC_LEVEL or PASSIVE_LEVEL, then use
KeAquireSpinLock. If you’re absolutely certain it can only be invoked at
DISPATCH_LEVEL, then use KeAcquireSpinLockAtDpc.

The most common use of KeAcquireSpinlockAtDpc is where you need to acquire
two locks in a row. You’ll often see code that looks like this:

KIRQL oldIrql;

KeAcquireSpinLock(&lock1, &oldIrql);
KeAcquireSpinLockAtDpc(&lock2);

(… do some work …)

KeReleaseSpinLockFromDpc(&lock2);
KeReleaseSpinLock(&lock1, oldIrql);

  • Jake Oshins
    Windows Kernel Team

wrote in message news:xxxxx@ntdev…
> All,
>
> I have a function that may be called at IRQL <= DISPATCH, I was using
> KeAcquireSpinLockAtDpc when IRQL == DISPATCH, but I’m experiencing what
> appear to be random deadlocks. I read that KeAcquireSpinLockAtDpc may
> block while I also read that it should be used for better performance in a
> driver.
>
> KeAcquireSpinLock() may be called at IRQL <= DISPATCH, so what is the real
> difference between these two?
>
> I’ve switched to always use KeAcquireSpinLock to see if the periodic
> deadlocks go away, my understanding is that this will do nothing if I’m
> already at DISPATCH.
>
> Thanks in advance
> ~kenny
>

Thanks Jake, this is exactly what I was looking for.

I’ll have to investigate more. When I switched to not use KeGetCurrentIrql
and always use KeAcquireSpinLock(), I hit a deadlock very quickly. I didn’t
bother to investigate but I will now since it sounds like that’s the best
method.

~kenny

“Jake Oshins” wrote in message
news:xxxxx@ntdev…
> If you were seeing deadlocks, then I submit that your code wasn’t always
> correct that it was running at DISPATCH_LEVEL when it called
> KeAcquireSpinlockAtDpc.
>
> But, to answer your more general question, as Max said, KeAcquireSpinlock
> raises to DISPATCH_LEVEL and then acquires a spinlock.
> KeAcquireSpinlockAtDpc just acquires the spinlock.
>
> Your next question is probably “what is entailed in raising to
> DISPATCH_LEVEL?” The answer depends on what HAL you’re using. Since the
> vast majority of machines today are using a HAL that uses the APIC
> interrupt controller, and since nearly all future machines will, the
> answer for that HAL is by far the most useful.
>
> Raising to DISPATCH_LEVEL is a matter of writing a value to the “Task
> Priority Register” in the processor’s Local APIC. (A checked build will
> read that register first and verifiy that the previous value was
> DISPATCH_LEVEL or lower.) It’s worth noting here that KeGetCurrentIrql
> will read the TPR, which is about as expensive as writing it. So you
> don’t make your code any more efficient by checking for current IRQL
> before deciding whether to use KeAcquireSpinLock or
> KeAcquireSpinLockAtDpc. If your function can be invoked at APC_LEVEL or
> PASSIVE_LEVEL, then use KeAquireSpinLock. If you’re absolutely certain it
> can only be invoked at DISPATCH_LEVEL, then use KeAcquireSpinLockAtDpc.
>
> The most common use of KeAcquireSpinlockAtDpc is where you need to acquire
> two locks in a row. You’ll often see code that looks like this:
>
> KIRQL oldIrql;
>
> KeAcquireSpinLock(&lock1, &oldIrql);
> KeAcquireSpinLockAtDpc(&lock2);
>
> (… do some work …)
>
> KeReleaseSpinLockFromDpc(&lock2);
> KeReleaseSpinLock(&lock1, oldIrql);
>
>
> - Jake Oshins
> Windows Kernel Team
>
>
>
> wrote in message news:xxxxx@ntdev…
>> All,
>>
>> I have a function that may be called at IRQL <= DISPATCH, I was using
>> KeAcquireSpinLockAtDpc when IRQL == DISPATCH, but I’m experiencing what
>> appear to be random deadlocks. I read that KeAcquireSpinLockAtDpc may
>> block while I also read that it should be used for better performance in
>> a driver.
>>
>> KeAcquireSpinLock() may be called at IRQL <= DISPATCH, so what is the
>> real difference between these two?
>>
>> I’ve switched to always use KeAcquireSpinLock to see if the periodic
>> deadlocks go away, my understanding is that this will do nothing if I’m
>> already at DISPATCH.
>>
>> Thanks in advance
>> ~kenny
>>
>
>
>

> KIRQL oldIrql;

KeAcquireSpinLock(&lock1, &oldIrql);
> KeAcquireSpinLockAtDpc(&lock2);

(… do some work …)

KeReleaseSpinLockFromDpc(&lock2);
> KeReleaseSpinLock(&lock1, oldIrql);

The above code is nothing more that just a logical inconsistency - the inner spinlock is totally unnecessary here, because it is protected by the outer one anyway. If lock1 was getting released while lock2 is still being held, there would be no logical inconsistency, although, in my opinion, it would still be a poor design - in 99.9…9% of cases you hardly gain anything by this “optimization”, and, at the same time, make your code much more difficult to debug

Anton Bassov

Why the inner lock is totally unnecessary?

And why releasing lock1 while holding lock2 is not a problem?

What use case you are thinking ?

-pro

On 5/18/07, xxxxx@hotmail.com wrote:
>
>
> > KIRQL oldIrql;
>
> > KeAcquireSpinLock(&lock1, &oldIrql);
> > KeAcquireSpinLockAtDpc(&lock2);
>
> (… do some work …)
>
> > KeReleaseSpinLockFromDpc(&lock2);
> > KeReleaseSpinLock(&lock1, oldIrql);
>
>
> The above code is nothing more that just a logical inconsistency - the
> inner spinlock is totally unnecessary here, because it is protected by the
> outer one anyway. If lock1 was getting released while lock2 is still being
> held, there would be no logical inconsistency, although, in my opinion, it
> would still be a poor design - in 99.9…9% of cases you hardly gain
> anything by this “optimization”, and, at the same time, make your code much
> more difficult to debug
>
>
> Anton Bassov
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> Why the inner lock is totally unnecessary?

Simply because no one, apart from outer lock holder, is able to acquire it. Therefore, all code that inner lock protects is already protected by outer one anyway, so that inner lock is just unnecessary.
Think about it carefully, and you will understand it…

What use case you are thinking ?

I think of some *theoretical* case when something happens,first, in between acquisition of lock1 and lock2, and, second, while lock1 has been released but lock2 is still being held . To be honest, in practical terms I just cannot imagine the situation when such approach may give you anything, apart from unnecessary complexity and potential bugs, although there is no logical inconsistency in it - logical consistency of the code does not necessarily imply reasonable design. My statement refers strictly to this theoretical case and not to the sample code - using 2 locks in it is just unnnecessary here .

Anton Bassov

> ----------

From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of xxxxx@hotmail.com[SMTP:xxxxx@hotmail.com]
Reply To: Windows System Software Devs Interest List
Sent: Saturday, May 19, 2007 5:26 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

Simply because no one, apart from outer lock holder, is able to acquire it. Therefore, all code that inner lock protects is already protected by outer one anyway, so that inner lock is just unnecessary.
Think about it carefully, and you will understand it…

It was just an example how to use …AtDpc() function correctly. It wasn’t complete code. Imagine you can have two separate resources protected by two distinct spinlocks. In some cases you need only one of them but in this case you need both. Think about it carefully.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

> -----Original Message-----

From: xxxxx@lists.osr.com [mailto:bounce-287275-
xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Friday, May 18, 2007 11:26 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

> Why the inner lock is totally unnecessary?

Simply because no one, apart from outer lock holder, is able to acquire
it. Therefore, all code that inner lock protects is already protected
by outer one anyway, so that inner lock is just unnecessary.
Think about it carefully, and you will understand it…

> What use case you are thinking ?

I think of some *theoretical* case when something happens,first, in
between acquisition of lock1 and lock2, and, second, while lock1 has
been released but lock2 is still being held . To be honest, in
practical terms I just cannot imagine the situation when such approach
may give you anything, apart from unnecessary complexity and potential
bugs, although there is no logical inconsistency in it - logical
consistency of the code does not necessarily imply reasonable design.
My statement refers strictly to this theoretical case and not to the
sample code - using 2 locks in it is just unnnecessary here .

[PCAUSA] I can always be convinced otherwise. But…

Consider two tables 1 with lock1 and 2 with lock2. Some methods may need only to add/modify/remove on table 1. Others only table 2. Yet others may need to access both tables (e.g., to move between them).

I think the construct has its place.

Thomas F. Divine

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Ummm… So, I guess you Soviet blokes haven’t gotten any a’them new fangled
multiprocessor systems yet?

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Friday, May 18, 2007 9:26 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

Why the inner lock is totally unnecessary?

Simply because no one, apart from outer lock holder, is able to acquire it.
Therefore, all code that inner lock protects is already protected by outer
one anyway, so that inner lock is just unnecessary. Think about it
carefully, and you will understand it…

What use case you are thinking ?

I think of some *theoretical* case when something happens,first, in between
acquisition of lock1 and lock2, and, second, while lock1 has been released
but lock2 is still being held . To be honest, in practical terms I just
cannot imagine the situation when such approach may give you anything, apart
from unnecessary complexity and potential bugs, although there is no logical
inconsistency in it - logical consistency of the code does not necessarily
imply reasonable design. My statement refers strictly to this theoretical
case and not to the sample code - using 2 locks in it is just unnnecessary
here .

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thomas,

> Simply because no one, apart from outer lock holder, is able to acquire
[PCAUSA] I can always be convinced otherwise. But…

Well, I just did not express myself properly - I should have said “execute code, protected by the inner spinlock”. This is what I meant.

Consider two tables 1 with lock1 and 2 with lock2. Some methods may need only to
add/modify/remove on table 1. Others only table 2. Yet others may need to access
both tables (e.g., to move between them).

Has it ever happened that you wrote some fairly complex code, spent some time debugging it, made it work well… and then realized that you could have done it much easier way and with with very little (if any at all) performance cost? It happened to me more than once. Therefore, I am trying my best to keep my code “simple and stupid”, without trying to optimize it, unless I am not satisfied with the performance…

From the logical standpoint, your example makes a perfect sense . At the same time, once I am so concerned about the simplicity, I am not so sure that , in practical terms, it is perfectly reasonable design, although *theoretically* it sounds reasonable - probably, in practical terms it would be better to use a single table, protected by a single spinlock. As an indirect proof of concept, I can give you the following example.

Apparently, you know that kernel dispatcher database is protected by a *SINGLE* spinlock, so that, whenever you call a function that deals with dispatcher objects (KeWait…,KeSetEvent(), etc), you have to obtain this lock behind the scenes. I believe MSFT had a good reason to implement things this way, although it seems to be unreasonable and inefficient, at the first glance - apparently, in practical terms, the potential “issues” with some more seemingly reasonable design far outweight some minor inefficiency, arising from the use of a single spinlock…

Anton Bassov

> -----Original Message-----

From: xxxxx@lists.osr.com [mailto:bounce-287280-
xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Saturday, May 19, 2007 12:39 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

Thomas,

>> Simply because no one, apart from outer lock holder, is able to
acquire
>[PCAUSA] I can always be convinced otherwise. But…

Well, I just did not express myself properly - I should have said
“execute code, protected by the inner spinlock”. This is what I meant.

> Consider two tables 1 with lock1 and 2 with lock2. Some methods may
need only to
> add/modify/remove on table 1. Others only table 2. Yet others may
need to access
> both tables (e.g., to move between them).

Has it ever happened that you wrote some fairly complex code, spent
some time debugging it, made it work well… and then realized that
you could have done it much easier way and with with very little (if
any at all) performance cost? It happened to me more than once.
Therefore, I am trying my best to keep my code “simple and stupid”,
without trying to optimize it, unless I am not satisfied with the
performance…

>From the logical standpoint, your example makes a perfect sense . At
the same time, once I am so concerned about the simplicity, I am not so
sure that , in practical terms, it is perfectly reasonable design,
although *theoretically* it sounds reasonable - probably, in practical
terms it would be better to use a single table, protected by a single
spinlock. As an indirect proof of concept, I can give you the following
example.

Apparently, you know that kernel dispatcher database is protected by a
*SINGLE* spinlock, so that, whenever you call a function that deals
with dispatcher objects (KeWait…,KeSetEvent(), etc), you have to
obtain this lock behind the scenes. I believe MSFT had a good reason to
implement things this way, although it seems to be unreasonable and
inefficient, at the first glance - apparently, in practical terms, the
potential “issues” with some more seemingly reasonable design far
outweight some minor inefficiency, arising from the use of a single
spinlock…

[PCAUSA] Well, my friend, I do confirm that I have never had the occasion to use this sort of construct myself and would avoid it if possible.

That doesn’t mean that it isn’t a logical and potentially necessary construct in some situations.

Thomas

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> Simply because no one, apart from outer lock holder, is able to acquire it.

No. There can be other paths protected by the inner lock only.


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

The OP did not intimate what the locks were for AFAIK. Moreover, spinlocks
rarely protect ‘code’. They protect data - and in particularly the
consitency of update and access to the state of something from operations
performed on multiple processors.

This construct of nested locks is almost always necessary for any assemblage
of objects with a parent-child relationship where the parent state and child
state are indpendently protected.

Releasing locks out of LiFo order, however, does not seem like a very usual
case however but nested locks are not at all uncommon or an indication of
uncessary complexity.

The only restriction on spinlock acquisition AFAIK is that the processor
acquiring the spinlock must be at or below the lock IRQL. If the lock is
not already owned by another processor, ownership is granted; otherwise, the
processor spins until ownership is granted. There is no implicit or
explicit prohibition or impossiblity to acquiring the second lock from
another CPU without acquiring the first that I have ever seen stated.

-dave

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Friday, May 18, 2007 11:26 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

Why the inner lock is totally unnecessary?

Simply because no one, apart from outer lock holder, is able to acquire it.
Therefore, all code that inner lock protects is already protected by outer
one anyway, so that inner lock is just unnecessary.
Think about it carefully, and you will understand it…

What use case you are thinking ?

I think of some *theoretical* case when something happens,first, in between
acquisition of lock1 and lock2, and, second, while lock1 has been released
but lock2 is still being held . To be honest, in practical terms I just
cannot imagine the situation when such approach may give you anything, apart
from unnecessary complexity and potential bugs, although there is no logical
inconsistency in it - logical consistency of the code does not necessarily
imply reasonable design. My statement refers strictly to this theoretical
case and not to the sample code - using 2 locks in it is just unnnecessary
here .

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> There is no implicit or explicit prohibition or impossiblity to acquiring the second lock from

another CPU without acquiring the first that I have ever seen stated.

Well, this is not really an argument - after all, one can do unreasonable things even if the system does not start in his way…

Taking into consideration the fact that you should try to make an operation, guarded by the spinlock,
as fast as possible, I think that in most ( probably even in all) cases introducing some fairly complex constructs into this operation is not a good idea at all - although your code may become more logical, from academical standpoint, practical implications may be rather different.
In practical terms, performance gains may be just negligible, but the price you pay for these negligible gains may be fairly high (i.e. unnecessarily complex code that is difficult to debug)

I would rather keep it “stupid and simple”, unless I am not satisfied with the performance …

Anton Bassov

I’m afraid you missed the whole point of what those lines of code was for

-pro

On 5/19/07, xxxxx@hotmail.com wrote:
>
> > There is no implicit or explicit prohibition or impossiblity to
> acquiring the second lock from
> > another CPU without acquiring the first that I have ever seen stated.
>
> Well, this is not really an argument - after all, one can do unreasonable
> things even if the system does not start in his way…
>
> Taking into consideration the fact that you should try to make an
> operation, guarded by the spinlock,
> as fast as possible, I think that in most ( probably even in all) cases
> introducing some fairly complex constructs into this operation is not a good
> idea at all - although your code may become more logical, from academical
> standpoint, practical implications may be rather different.
> In practical terms, performance gains may be just negligible, but the
> price you pay for these negligible gains may be fairly high (i.e.
> unnecessarily complex code that is difficult to debug)
>
> I would rather keep it “stupid and simple”, unless I am not satisfied with
> the performance …
>
> Anton Bassov
>
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

I guess I would prefer to keep it correct first and minimally complex
second. Performance is generally not something to trade correctness for.

-dc

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Saturday, May 19, 2007 7:47 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] KeAcquireSpinLock vs KeAcquireSpinLockAtDPC

There is no implicit or explicit prohibition or impossiblity to
acquiring the second lock from another CPU without acquiring the first
that I have ever seen stated.

Well, this is not really an argument - after all, one can do unreasonable
things even if the system does not start in his way…

Taking into consideration the fact that you should try to make an operation,
guarded by the spinlock, as fast as possible, I think that in most (
probably even in all) cases introducing some fairly complex constructs into
this operation is not a good idea at all - although your code may become
more logical, from academical standpoint, practical implications may be
rather different.
In practical terms, performance gains may be just negligible, but the price
you pay for these negligible gains may be fairly high (i.e. unnecessarily
complex code that is difficult to debug)

I would rather keep it “stupid and simple”, unless I am not satisfied with
the performance …

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> I’m afraid you missed the whole point of what those lines of code was for

I did not - I just changed the topic of a discussion from “KeAcquireSpinLock vs KeAcquireSpinLockAtDPC” into “Is there any need for nesting spinlocks”…

Concerning the original topic, everything seems to be clear - the OP calls KeAcquireSpinLockAtDPC()
at IRQL< DISPATCH__LEVEL, and, as a result, ends up as a spinlock owner at IRQL< DISPATCH__LEVEL (because KeAcquireSpinLockAtDPC() does not modify Task Priority Register), i.e. context switches and DPC queue flushes after interrupt are still possible on the target CPU while he holds a spinlock. As a result, he deadlocks - not that much to discuss here…

Anton Bassov

> Performance is generally not something to trade correctness for.

Exactly…

This is why I believe nesting spinlocks is not so good idea in itself (because you have a higher chance of making an error somewhere). To make things worse, when it comes to spinlock-related bugs it is not always easy to detect a problem, let alone identify its source …

Anton Bassov