Using PUSH_LOCK

Hi All,

As per documentation:
A. If acquiring shared push lock:

  1. If the caller already has acquired the push lock for shared access, it can receive shared access again.
  2. If the caller already has acquired the push lock for exclusive, the thread will hang.
  3. If there is another thread waiting for exclusive access, the current thread is put into a wait state.

B. If acquiring exclusive push lock:

  1. If the caller already has acquired the push lock for shared access, it can receive shared access again.
  2. If the caller already has acquired the push lock for exclusive, the thread will hang.

Query:
Can a thread acquire push lock shared recursively(already have share access), if another thread is waiting for exclusive access?

Thanks,
Rajendra.

I’d strongly recommend using an ERESOURCE rather than a push lock in your initial implementation. ERESOURCE locks are vastly easier to debug (“!locks” in the debugger). While push locks are faster (in the non-contended case), CPU cycles are rarely an issue for file systems or file system filter drivers, but your own cycles in trying to figure out deadlocks will be. It can be replaced with a push lock in the future if your performance tests indicate it’s useful.

A thread that owns a push lock shared and attempts to reacquire it is permitted to do so, even if there are other threads waiting for exclusive access. Otherwise, the scenario that you described would guarantee a deadlock.

Tony
OSR

A very interesting question, and one that the documentation does not appear
to address. I ran a quick experiment:

Thread A: Acquire push lock shared
Thread A: Create Thread B
Thread A: Sleep for bit
Thread B: Acquire push lock Ex - Blocks
Thread A: Attempt to reacquire push lock shared - *Blocks*

Here’s the resulting thread state for the shared blocker:

0: kd> !THREAD ffffe00127147880 f
THREAD ffffe00127147880 Cid 0004.06c4 Teb: 0000000000000000 Win32Thread:
0000000000000000 WAIT: (WrPushLock) KernelMode Non-Alertable
ffffd000a6217840 SynchronizationEvent
Not impersonating
DeviceMap ffffc00066e0a080
Owning Process ffffe0012446a900 Image: System
Attached Process N/A Image: N/A
Wait Start TickCount 30281 Ticks: 819 (0:00:00:12.796)
Context Switch Count 1655 IdealProcessor: 0
UserTime 00:00:00.000
KernelTime 00:00:04.562
Win32 Start Address nt!ExpWorkerThread (0xfffff803f66b6100)
Stack Init ffffd000a6217dd0 Current ffffd000a62174e0
Base ffffd000a6218000 Limit ffffd000a6212000 Call 0
Priority 12 BasePriority 12 UnusualBoost 0 ForegroundBoost 0 IoPriority 2
PagePriority 5
Child-SP RetAddr Call Site
ffffd000a6217520 fffff803f664bd7e nt!KiSwapContext+0x76
ffffd000a6217660 fffff803f664b7f9 nt!KiSwapThread+0x14e
ffffd000a6217700 fffff803f66738d0 nt!KiCommitThreadWait+0x129
ffffd000a6217780 fffff803f66b7bb1 nt!KeWaitForSingleObject+0x2c0
ffffd000a6217810 fffff803f66ef162 nt!ExfAcquirePushLockSharedEx+0x171
ffffd000a62178c0 fffff801bbcbb3f5 nt!ExAcquirePushLockSharedEx+0x142
ffffd000a6217900 fffff803f6ad48b3 Nothing!DriverEntry+0x85
ffffd000a6217990 fffff803f6ad303a nt!IopLoadDriver+0x553
ffffd000a6217c50 fffff803f66b638c nt!IopLoadUnloadDriver+0x4e
ffffd000a6217c90 fffff803f671bc70 nt!ExpWorkerThread+0x28c
ffffd000a6217d40 fffff803f6770fc6 nt!PspSystemThreadStartup+0x58
ffffd000a6217da0 0000000000000000 nt!KiStartSystemThread+0x16

That’s pretty ugly…I’d stay away from recursive shared acquires.

I’ll file a documentation bug to try to get clarification on this.

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntfsd…

Hi All,

As per documentation:
A. If acquiring shared push lock:

  1. If the caller already has acquired the push lock for shared access, it
    can receive shared access again.
  2. If the caller already has acquired the push lock for exclusive, the
    thread will hang.
  3. If there is another thread waiting for exclusive access, the current
    thread is put into a wait state.

B. If acquiring exclusive push lock:

  1. If the caller already has acquired the push lock for shared access, it
    can receive shared access again.
  2. If the caller already has acquired the push lock for exclusive, the
    thread will hang.

Query:
Can a thread acquire push lock shared recursively(already have share
access), if another thread is waiting for exclusive access?

Thanks,
Rajendra.

That sounds like an implementation bug, as it guarantees a deadlock when used in a re-entrant environment in precisely the way they are intended.

Once again, I’ll say: use ERESOURCE locks.

Tony
OSR

Push Locks are not recursively acquirable.

From the latest issue of The NT Insider:

“If you need reader/writer semantics and your locking mechanism also needs to support recursion then your choice is the Executive Resource. On the other hand, if recursion is not needed, then the Pushlock now becomes a candidate as well.” (http: Page 14).

Peter
OSR
@OSRDrivers</http:>

The docs allow for shared recursive acquisition:

" If the caller already has acquired the push lock for shared access, it can
receive shared access again"

https://msdn.microsoft.com/en-us/library/windows/hardware/ff541672(v=vs.85).aspx

And it works just fine, until an exclusive waiter comes along in which case
you’re hosed.

A doc bug has been filed.

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntfsd…

Push Locks are not recursively acquirable.

From the latest issue of The NT Insider:

“If you need reader/writer semantics and your locking mechanism also needs
to support recursion then your choice is the Executive Resource. On the
other hand, if recursion is not needed, then the Pushlock now becomes a
candidate as well.” (http:
Page 14).

Peter
OSR
@OSRDrivers</http:>

This is what I’ve always taught, but the documentation disagrees. In fact, it makes sense. Without ownership there is no way to distinguish between a “recursive acquisition” and the initial acquisition by a thread. But then it leads to a situation in which when one does “recursively acquire” there’s no way to prevent the deadlock that arises when there is a thread waiting for exclusive ownership.

So, once more: my advice is to stick with using the ERESOURCE, especially if you are posting your question in NTFSD where we live with re-entrancy. When you find that lock acquisition is a bottleneck in your code, then you can look at switching to push locks. If you find that lock contention is an issue, switching to push locks won’t help. Changing the lock model (finer grained locks) will help.

Tony
OSR