ReactOS 0.4.16-dev-257-g6aa11ac
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{
87 LONG LockValue;
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 */
138 }
139
140 /* Otherwise, return success */
141 return STATUS_SUCCESS;
142}
#define Dbg
Definition: acchksup.c:22
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
Definition: File.h:16
#define FALSE
Definition: types.h:117
#define __FUNCTION__
Definition: types.h:116
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
#define ASSERT(a)
Definition: mode.c:44
struct _EXTENDED_IO_REMOVE_LOCK * PEXTENDED_IO_REMOVE_LOCK
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
long LONG
Definition: pedump.c:60
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
Definition: ncftp.h:79
LARGE_INTEGER LockMoment
Definition: remlock.c:21
PIO_REMOVE_LOCK_TRACKING_BLOCK Next
Definition: remlock.c:19
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_In_opt_ PVOID _In_ PCSTR _In_ ULONG _In_ ULONG RemlockSize
Definition: iofuncs.h:620
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

◆ 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 PAGED_CODE()
#define NULL
Definition: types.h:112
LONG MaxLockedMinutes
Definition: lock.c:35
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
@ SynchronizationEvent
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
#define MAXLONG
Definition: umtypes.h:116
_In_ ULONG _In_ ULONG _In_ ULONG HighWatermark
Definition: iofuncs.h:1069
_In_ ULONG AllocateTag
Definition: iofuncs.h:1067
struct _IO_REMOVE_LOCK_COMMON_BLOCK IO_REMOVE_LOCK_COMMON_BLOCK

◆ 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,
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
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define KernelMode
Definition: asm.h:34
@ Executive
Definition: ketypes.h:415

◆ IoReleaseRemoveLockEx()

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

Definition at line 149 of file remlock.c.

152{
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}
unsigned char BOOLEAN
LONGLONG QuadPart
Definition: typedefs.h:114