ReactOS  0.4.14-dev-49-gfb4591c
remlock.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for remlock.c:

Go to the source code of this file.

Classes

struct  _IO_REMOVE_LOCK_TRACKING_BLOCK
 

Macros

#define NDEBUG
 

Typedefs

typedef struct _IO_REMOVE_LOCK_TRACKING_BLOCK IO_REMOVE_LOCK_TRACKING_BLOCK
 

Functions

VOID NTAPI IoInitializeRemoveLockEx (IN PIO_REMOVE_LOCK RemoveLock, IN ULONG AllocateTag, IN ULONG MaxLockedMinutes, IN ULONG HighWatermark, IN ULONG RemlockSize)
 
NTSTATUS NTAPI IoAcquireRemoveLockEx (IN PIO_REMOVE_LOCK RemoveLock, IN OPTIONAL PVOID Tag, IN LPCSTR File, IN ULONG Line, IN ULONG RemlockSize)
 
VOID NTAPI IoReleaseRemoveLockEx (IN PIO_REMOVE_LOCK RemoveLock, IN PVOID Tag, IN ULONG RemlockSize)
 
VOID NTAPI IoReleaseRemoveLockAndWaitEx (IN PIO_REMOVE_LOCK RemoveLock, IN PVOID Tag, IN ULONG RemlockSize)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file remlock.c.

Typedef Documentation

◆ IO_REMOVE_LOCK_TRACKING_BLOCK

Function Documentation

◆ IoAcquireRemoveLockEx()

NTSTATUS NTAPI IoAcquireRemoveLockEx ( IN PIO_REMOVE_LOCK  RemoveLock,
IN OPTIONAL PVOID  Tag,
IN LPCSTR  File,
IN ULONG  Line,
IN ULONG  RemlockSize 
)

Definition at line 80 of file remlock.c.

85 {
86  KIRQL OldIrql;
87  LONG LockValue;
88  PIO_REMOVE_LOCK_TRACKING_BLOCK TrackingBlock;
90 
91  DPRINT("%s(%p %p %s %u %u)\n", __FUNCTION__, RemoveLock, Tag, File, Line, RemlockSize);
92 
93  /* Increase the lock count */
94  LockValue = InterlockedIncrement(&(Lock->Common.IoCount));
95  ASSERT(LockValue > 0);
96  if (!Lock->Common.Removed)
97  {
98  /* Check what kind of lock this is */
100  {
101  ASSERT(Lock->Dbg.HighWatermark == 0 || LockValue <= Lock->Dbg.HighWatermark);
102 
103  /* Allocate a tracking block */
104  TrackingBlock = ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_REMOVE_LOCK_TRACKING_BLOCK), Lock->Dbg.AllocateTag);
105  if (!TrackingBlock)
106  {
107  /* Keep count of failures for lock release and missing tags */
108  InterlockedIncrement(&(Lock->Dbg.LowMemoryCount));
109  }
110  else
111  {
112  /* Initialize block */
113  RtlZeroMemory(TrackingBlock, sizeof(IO_REMOVE_LOCK_TRACKING_BLOCK));
114  TrackingBlock->Tag = Tag;
115  TrackingBlock->File = File;
116  TrackingBlock->Line = Line;
117  KeQueryTickCount(&(TrackingBlock->LockMoment));
118 
119  /* Queue the block */
120  KeAcquireSpinLock(&(Lock->Dbg.Spin), &OldIrql);
121  TrackingBlock->Next = Lock->Dbg.Blocks;
122  Lock->Dbg.Blocks = TrackingBlock;
123  KeReleaseSpinLock(&(Lock->Dbg.Spin), OldIrql);
124  }
125  }
126  }
127  else
128  {
129  /* Otherwise, decrement the count and check if it's gone */
130  if (!InterlockedDecrement(&(Lock->Common.IoCount)))
131  {
132  /* Signal the event */
133  KeSetEvent(&(Lock->Common.RemoveEvent), IO_NO_INCREMENT, FALSE);
134  }
135 
136  /* Return pending delete */
137  return STATUS_DELETE_PENDING;
138  }
139 
140  /* Otherwise, return success */
141  return STATUS_SUCCESS;
142 }
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:308
PIO_REMOVE_LOCK_TRACKING_BLOCK Next
Definition: remlock.c:19
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
UCHAR KIRQL
Definition: env_spec_w32.h:591
long LONG
Definition: pedump.c:60
_In_opt_ PVOID _In_ PCSTR File
Definition: iofuncs.h:615
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
struct _EXTENDED_IO_REMOVE_LOCK * PEXTENDED_IO_REMOVE_LOCK
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
Definition: ncftp.h:79
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define InterlockedDecrement
Definition: armddk.h:52
_In_opt_ PVOID _In_ PCSTR _In_ ULONG _In_ ULONG RemlockSize
Definition: iofuncs.h:615
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
#define InterlockedIncrement
Definition: armddk.h:53
#define Dbg
Definition: acchksup.c:22
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
LARGE_INTEGER LockMoment
Definition: remlock.c:21
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
Definition: File.h:15
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define __FUNCTION__
Definition: types.h:112
struct Line Line

◆ IoInitializeRemoveLockEx()

VOID NTAPI IoInitializeRemoveLockEx ( IN PIO_REMOVE_LOCK  RemoveLock,
IN ULONG  AllocateTag,
IN ULONG  MaxLockedMinutes,
IN ULONG  HighWatermark,
IN ULONG  RemlockSize 
)

Definition at line 33 of file remlock.c.

38 {
40  PAGED_CODE();
41 
42  DPRINT("%s(%p 0x%08x %u %u %u)\n", __FUNCTION__, RemoveLock, AllocateTag, MaxLockedMinutes, HighWatermark, RemlockSize);
43 
45 
46  /* If no lock given, nothing to do */
47  if (!Lock)
48  {
49  return;
50  }
51 
52  switch (RemlockSize)
53  {
54  /* Check if this is a debug lock */
56  /* Setup debug parameters */
57  Lock->Dbg.Signature = 'COLR';
58  Lock->Dbg.HighWatermark = HighWatermark;
59  Lock->Dbg.MaxLockedTicks = KeQueryTimeIncrement() * MaxLockedMinutes * 600000000;
60  Lock->Dbg.AllocateTag = AllocateTag;
61  KeInitializeSpinLock(&(Lock->Dbg.Spin));
62  Lock->Dbg.LowMemoryCount = 0;
63  Lock->Dbg.Blocks = NULL;
64 
65  case sizeof(IO_REMOVE_LOCK_COMMON_BLOCK):
66  /* Setup a free block */
67  Lock->Common.Removed = FALSE;
68  Lock->Common.IoCount = 1;
69  KeInitializeEvent(&Lock->Common.RemoveEvent,
71  FALSE);
72  }
73 }
#define MAXLONG
Definition: umtypes.h:116
LONG MaxLockedMinutes
Definition: lock.c:29
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
#define PAGED_CODE()
Definition: video.h:57
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
struct _EXTENDED_IO_REMOVE_LOCK * PEXTENDED_IO_REMOVE_LOCK
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_In_opt_ PVOID _In_ PCSTR _In_ ULONG _In_ ULONG RemlockSize
Definition: iofuncs.h:615
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
_In_ ULONG AllocateTag
Definition: iofuncs.h:1065
struct _IO_REMOVE_LOCK_COMMON_BLOCK IO_REMOVE_LOCK_COMMON_BLOCK
_In_ ULONG _In_ ULONG _In_ ULONG HighWatermark
Definition: iofuncs.h:1065
#define __FUNCTION__
Definition: types.h:112

◆ IoReleaseRemoveLockAndWaitEx()

VOID NTAPI IoReleaseRemoveLockAndWaitEx ( IN PIO_REMOVE_LOCK  RemoveLock,
IN PVOID  Tag,
IN ULONG  RemlockSize 
)

Definition at line 243 of file remlock.c.

246 {
247  LONG LockValue;
248  PIO_REMOVE_LOCK_TRACKING_BLOCK TrackingBlock;
250  PAGED_CODE();
251 
252  DPRINT("%s(%p %p %u)\n", __FUNCTION__, RemoveLock, Tag, RemlockSize);
253 
254  /* Remove the lock and decrement the count */
255  Lock->Common.Removed = TRUE;
256  LockValue = InterlockedDecrement(&Lock->Common.IoCount);
257  ASSERT(LockValue > 0);
258 
259  /* If we are still > 0, then wait for the others to remove lock */
260  if (InterlockedDecrement(&Lock->Common.IoCount) > 0)
261  {
262  /* Wait for it */
263  KeWaitForSingleObject(&(Lock->Common.RemoveEvent),
264  Executive,
265  KernelMode,
266  FALSE,
267  NULL);
268  }
269 
270  /* Check what kind of lock this is */
272  {
273  /* A block must be remaining */
274  ASSERT(Lock->Dbg.Blocks);
275 
276  /* Get it */
277  TrackingBlock = Lock->Dbg.Blocks;
278  /* Tag should match */
279  if (TrackingBlock->Tag != Tag)
280  {
281  DPRINT("Last tracking block tag invalid! Expected: %p, having: %p\n", Tag, TrackingBlock->Tag);
282  ASSERT(TrackingBlock->Tag != Tag);
283  }
284 
285  /* Release block */
286  ExFreePoolWithTag(Lock->Dbg.Blocks, Lock->Dbg.AllocateTag);
287  }
288 }
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define PAGED_CODE()
Definition: video.h:57
long LONG
Definition: pedump.c:60
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
struct _EXTENDED_IO_REMOVE_LOCK * PEXTENDED_IO_REMOVE_LOCK
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InterlockedDecrement
Definition: armddk.h:52
_In_opt_ PVOID _In_ PCSTR _In_ ULONG _In_ ULONG RemlockSize
Definition: iofuncs.h:615
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define __FUNCTION__
Definition: types.h:112

◆ IoReleaseRemoveLockEx()

VOID NTAPI IoReleaseRemoveLockEx ( IN PIO_REMOVE_LOCK  RemoveLock,
IN PVOID  Tag,
IN ULONG  RemlockSize 
)

Definition at line 149 of file remlock.c.

152 {
153  KIRQL OldIrql;
154  LONG LockValue;
155  BOOLEAN TagFound;
156  LARGE_INTEGER CurrentMoment;
157  PIO_REMOVE_LOCK_TRACKING_BLOCK TrackingBlock;
158  PIO_REMOVE_LOCK_TRACKING_BLOCK *TrackingBlockLink;
160 
161  DPRINT("%s(%p %p %u)\n", __FUNCTION__, RemoveLock, Tag, RemlockSize);
162 
163  /* Check what kind of lock this is */
165  {
166  /* Acquire blocks queue */
167  KeAcquireSpinLock(&(Lock->Dbg.Spin), &OldIrql);
168 
169  /* Get the release moment */
170  KeQueryTickCount(&CurrentMoment);
171 
172  /* Start browsing tracking blocks to find a block that would match given tag */
173  TagFound = FALSE;
174  TrackingBlock = Lock->Dbg.Blocks;
175  TrackingBlockLink = &(Lock->Dbg.Blocks);
176  while (TrackingBlock != NULL)
177  {
178  /* First of all, check if the lock was locked for too long */
179  if (Lock->Dbg.MaxLockedTicks &&
180  CurrentMoment.QuadPart - TrackingBlock->LockMoment.QuadPart > Lock->Dbg.MaxLockedTicks)
181  {
182  DPRINT("Lock %#08lx (with tag %#08lx) was supposed to be held at max %I64d ticks but lasted longer\n",
183  Lock, TrackingBlock->Tag, Lock->Dbg.MaxLockedTicks);
184  DPRINT("Lock was acquired in file %s at line %lu\n", TrackingBlock->File, TrackingBlock->Line);
185  ASSERT(FALSE);
186  }
187 
188  /* Check if this is the first matching tracking block */
189  if ((TagFound == FALSE) && (TrackingBlock->Tag == Tag))
190  {
191  /* Unlink this tracking block, and free it */
192  TagFound = TRUE;
193  *TrackingBlockLink = TrackingBlock->Next;
194  ExFreePoolWithTag(TrackingBlock, Lock->Dbg.AllocateTag);
195  TrackingBlock = *TrackingBlockLink;
196  }
197  else
198  {
199  /* Go to the next tracking block */
200  TrackingBlockLink = &(TrackingBlock->Next);
201  TrackingBlock = TrackingBlock->Next;
202  }
203  }
204 
205  /* We're done, release queue lock */
206  KeReleaseSpinLock(&(Lock->Dbg.Spin), OldIrql);
207 
208  /* If we didn't find any matching block */
209  if (TagFound == FALSE)
210  {
211  /* Check if it was because we were low in memory
212  * If yes, then ignore, that's normal
213  */
214  if (InterlockedDecrement(&(Lock->Dbg.LowMemoryCount)) < 0)
215  {
216  /* Otherwise signal the issue, it shouldn't happen */
217  InterlockedIncrement(&(Lock->Dbg.LowMemoryCount));
218  DPRINT("Failed finding block for tag: %#08lx\n", Tag);
219  ASSERT(FALSE);
220  }
221  }
222  }
223 
224  /* Decrement the lock count */
225  LockValue = InterlockedDecrement(&(Lock->Common.IoCount));
226  ASSERT(LockValue >= 0);
227 
228  if (!LockValue)
229  {
230  /* Someone should be waiting... */
231  ASSERT(Lock->Common.Removed);
232 
233  /* Signal the event */
234  KeSetEvent(&(Lock->Common.RemoveEvent), IO_NO_INCREMENT, FALSE);
235  }
236 }
#define TRUE
Definition: types.h:120
PIO_REMOVE_LOCK_TRACKING_BLOCK Next
Definition: remlock.c:19
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
UCHAR KIRQL
Definition: env_spec_w32.h:591
long LONG
Definition: pedump.c:60
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
struct _EXTENDED_IO_REMOVE_LOCK * PEXTENDED_IO_REMOVE_LOCK
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InterlockedDecrement
Definition: armddk.h:52
_In_opt_ PVOID _In_ PCSTR _In_ ULONG _In_ ULONG RemlockSize
Definition: iofuncs.h:615
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
#define InterlockedIncrement
Definition: armddk.h:53
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
LARGE_INTEGER LockMoment
Definition: remlock.c:21
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define __FUNCTION__
Definition: types.h:112
LONGLONG QuadPart
Definition: typedefs.h:112