00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
#include <nt.h>
00031
#include <ntrtl.h>
00032
#include <ntos.h>
00033
00034
#include <remlock.h>
00035
00036 #define MinutesToTicks(x) \
00037
(ULONGLONG) KeQueryTimeIncrement() * \
00038
10 * \
00039
1000 * \
00040
1000 * \
00041
60 * \
00042
x
00043
00044
00045
00046
00047 NTSYSAPI
00048
PRTL_REMOVE_LOCK
00049 NTAPI
00050 RtlAllocateRemoveLock(
00051 IN ULONG MaxLockedMinutes,
00052 IN ULONG AllocateTag,
00053 IN ULONG HighWatermark
00054 )
00055
00056
00057
00058
00059
00060
00061
00062 {
00063
PRTL_REMOVE_LOCK lock;
00064
00065 lock =
ExAllocatePoolWithTag (
NonPagedPool,
00066
sizeof (
RTL_REMOVE_LOCK),
00067 AllocateTag);
00068
00069
if (lock) {
00070
00071 lock->
Signature =
RTL_REMOVE_LOCK_SIG;
00072 lock->
Removed =
FALSE;
00073 lock->
IoCount = 1;
00074
KeInitializeEvent(&lock->
RemoveEvent, SynchronizationEvent,
FALSE);
00075
#if DBG
00076
lock->HighWatermark = HighWatermark;
00077 lock->MaxLockedMinutes = MaxLockedMinutes;
00078 lock->AllocateTag = AllocateTag;
00079
KeInitializeSpinLock (&lock->Spin);
00080 lock->Blocks.Link =
NULL;
00081
#endif
00082
}
00083
00084
return lock;
00085 }
00086
00087
00088 NTSYSAPI
00089
NTSTATUS
00090 NTAPI
00091 RtlAcquireRemoveLockEx(
00092 IN
PRTL_REMOVE_LOCK RemoveLock,
00093 IN OPTIONAL PVOID Tag,
00094 IN PCSTR File,
00095 IN ULONG Line
00096 )
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 {
00135 LONG lockValue;
00136
NTSTATUS status;
00137
00138
#if DBG
00139
PRTL_REMOVE_LOCK_TRACKING_BLOCK trackingBlock;
00140
#endif
00141
00142
00143
00144
00145
00146 lockValue = InterlockedIncrement(&RemoveLock->IoCount);
00147
00148
ASSERTMSG(
"RtlAcquireRemoveLock - lock value was negative : ",
00149 (lockValue > 0));
00150
00151
ASSERTMSG(
"RemoveLock increased to meet LockHighWatermark",
00152 ((0 == RemoveLock->HighWatermark) ||
00153 (lockValue <= RemoveLock->HighWatermark)));
00154
00155
if (! RemoveLock->Removed) {
00156
00157
#if DBG
00158
trackingBlock =
ExAllocatePoolWithTag(
00159
NonPagedPool,
00160
sizeof(RTL_REMOVE_LOCK_TRACKING_BLOCK),
00161 RemoveLock->AllocateTag);
00162
00163 RtlZeroMemory (trackingBlock,
00164
sizeof (RTL_REMOVE_LOCK_TRACKING_BLOCK));
00165
00166
if (
NULL == trackingBlock) {
00167
00168
ASSERTMSG (
"insufficient resources",
FALSE);
00169
00170 }
else {
00171
00172 KIRQL oldIrql;
00173
00174 trackingBlock->Tag = Tag;
00175 trackingBlock->File =
File;
00176 trackingBlock->Line = Line;
00177
00178
KeQueryTickCount(&trackingBlock->TimeLocked);
00179
00180
KeAcquireSpinLock (&RemoveLock->Spin, &oldIrql);
00181 trackingBlock->Link = RemoveLock->Blocks.Link;
00182 RemoveLock->Blocks.Link = trackingBlock;
00183
KeReleaseSpinLock(&RemoveLock->Spin, oldIrql);
00184 }
00185
#endif
00186
00187 status = STATUS_SUCCESS;
00188
00189 }
else {
00190
00191
if (0 == InterlockedDecrement (&RemoveLock->IoCount)) {
00192
KeSetEvent (&RemoveLock->RemoveEvent, 0,
FALSE);
00193 }
00194 status = STATUS_DELETE_PENDING;
00195 }
00196
00197
return status;
00198 }
00199
00200
00201 NTSYSAPI
00202
VOID
00203 NTAPI
00204 RtlReleaseRemoveLock(
00205 IN
PRTL_REMOVE_LOCK RemoveLock,
00206 IN PVOID Tag
00207 )
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 {
00236 LONG lockValue;
00237
00238
#if DBG
00239
KIRQL oldIrql;
00240 LARGE_INTEGER difference;
00241 BOOLEAN found;
00242 LONGLONG maxTime;
00243
00244 PRTL_REMOVE_LOCK_TRACKING_BLOCK last;
00245 PRTL_REMOVE_LOCK_TRACKING_BLOCK current;
00246
00247
00248
00249
00250
00251
00252 found =
FALSE;
00253
KeAcquireSpinLock(&RemoveLock->Spin, &oldIrql);
00254 last = (&RemoveLock->Blocks);
00255 current = last->Link;
00256
00257
00258
00259
00260
while (
NULL != current) {
00261
00262
KeQueryTickCount((&difference));
00263 difference.QuadPart -= current->TimeLocked.QuadPart;
00264 maxTime =
MinutesToTicks (RemoveLock->MaxLockedMinutes);
00265
00266
if (maxTime && (maxTime < difference.QuadPart)) {
00267
00268 KdPrint((
"RtlReleaseRemoveLock: Lock %#08lx (tag %#08lx) locked "
00269
"for %I64d ticks - TOO LONG\n",
00270 RemoveLock,
00271 current->Tag,
00272 difference.QuadPart));
00273
00274 KdPrint((
"RtlReleaseRemoveLock: Lock acquired in file "
00275
"%s on line %d\n",
00276 current->File,
00277 current->Line));
00278
ASSERT(
FALSE);
00279 }
00280
00281
if ((!found) && (current->Tag == Tag)) {
00282 found =
TRUE;
00283 last->Link = current->Link;
00284
ExFreePool (current);
00285 current = last->Link;
00286
continue;
00287 }
00288
00289 last = current;
00290 current = current->Link;
00291 }
00292
00293
KeReleaseSpinLock(&RemoveLock->Spin, oldIrql);
00294
00295
if (!found) {
00296
00297 KdPrint ((
"RtlReleaseRemoveLock: Couldn't find Tag %#08lx "
00298
"in the lock tracking list\n",
00299 Tag));
00300
ASSERT(
FALSE);
00301 }
00302
#endif
00303
00304 lockValue = InterlockedDecrement(&RemoveLock->IoCount);
00305
00306
ASSERT(0 <= lockValue);
00307
00308
if (0 == lockValue) {
00309
00310
ASSERT (RemoveLock->Removed);
00311
00312
00313
00314
00315
00316
00317
KeSetEvent(&RemoveLock->RemoveEvent,
00318
IO_NO_INCREMENT,
00319
FALSE);
00320 }
00321
return;
00322 }
00323
00324
00325 NTSYSAPI
00326
VOID
00327 NTAPI
00328 RtlReleaseRemoveLockAndWait (
00329 IN
PRTL_REMOVE_LOCK RemoveLock,
00330 IN PVOID Tag
00331 )
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 {
00353 LONG ioCount;
00354
00355
PAGED_CODE ();
00356
00357 RemoveLock->Removed =
TRUE;
00358
00359 ioCount = InterlockedDecrement (&RemoveLock->IoCount);
00360
ASSERT (0 < ioCount);
00361
00362
if (0 < InterlockedDecrement (&RemoveLock->IoCount)) {
00363
KeWaitForSingleObject (&RemoveLock->RemoveEvent,
00364
Executive,
00365
KernelMode,
00366
FALSE,
00367
NULL);
00368 }
00369
00370
#if DBG
00371
ASSERT (RemoveLock->Blocks.Link);
00372
if (Tag != RemoveLock->Blocks.Link->Tag) {
00373 KdPrint ((
"RtlRelaseRemoveLockAndWait last tag invalid %x %x\n",
00374 Tag,
00375 RemoveLock->Blocks.Link->Tag));
00376
00377
ASSERT (Tag != RemoveLock->Blocks.Link->Tag);
00378 }
00379
00380
ExFreePool (RemoveLock->Blocks.Link);
00381
#endif
00382
00383 }
00384
00385