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 "iop.h"
00031
00032
#include <remlock.h>
00033
00034
#pragma alloc_text(PAGE, IoInitializeRemoveLockEx)
00035
#pragma alloc_text(PAGE, IoReleaseRemoveLockAndWaitEx)
00036
00037 #define MinutesToTicks(x) \
00038
(ULONGLONG) KeQueryTimeIncrement() * \
00039
10 * \
00040
1000 * \
00041
1000 * \
00042
60 * \
00043
x
00044
00045
00046
00047
00048 typedef struct _IO_PRIVATE_REMOVE_LOCK {
00049 IO_REMOVE_LOCK_COMMON_BLOCK Common;
00050 IO_REMOVE_LOCK_DBG_BLOCK Dbg;
00051 }
IO_PRIVATE_REMOVE_LOCK, *
PIO_PRIVATE_REMOVE_LOCK;
00052
00053
00054 #define FREESIZE sizeof (IO_REMOVE_LOCK_COMMON_BLOCK)
00055 #define CHECKEDSIZE sizeof (IO_PRIVATE_REMOVE_LOCK)
00056
00057
00058 NTSYSAPI
00059
VOID
00060 NTAPI
00061 IoInitializeRemoveLockEx(
00062 IN
PIO_REMOVE_LOCK PublicLock,
00063 IN ULONG AllocateTag,
00064 IN ULONG MaxLockedMinutes,
00065 IN ULONG HighWatermark,
00066 IN ULONG RemlockSize
00067 )
00068
00069
00070
00071
00072
00073
00074
00075 {
00076
PIO_PRIVATE_REMOVE_LOCK Lock = (
PIO_PRIVATE_REMOVE_LOCK) PublicLock;
00077
00078
PAGED_CODE ();
00079
00080
if (
Lock) {
00081
00082
switch (RemlockSize) {
00083
00084
case CHECKEDSIZE:
00085
Lock->Dbg.Signature =
IO_REMOVE_LOCK_SIG;
00086
Lock->Dbg.HighWatermark = HighWatermark;
00087
Lock->Dbg.MaxLockedTicks =
MinutesToTicks (MaxLockedMinutes);
00088
Lock->Dbg.AllocateTag = AllocateTag;
00089
KeInitializeSpinLock (&
Lock->Dbg.Spin);
00090
Lock->Dbg.LowMemoryCount = 0;
00091
Lock->Dbg.Blocks =
NULL;
00092
00093
00094
00095
00096
case FREESIZE:
00097
Lock->Common.Removed =
FALSE;
00098
Lock->Common.IoCount = 1;
00099
KeInitializeEvent(&
Lock->Common.RemoveEvent,
00100 SynchronizationEvent,
00101
FALSE);
00102
break;
00103
00104
default:
00105
break;
00106 }
00107 }
00108 }
00109
00110
00111 NTSYSAPI
00112
NTSTATUS
00113 NTAPI
00114 IoAcquireRemoveLockEx(
00115 IN
PIO_REMOVE_LOCK PublicLock,
00116 IN OPTIONAL PVOID Tag,
00117 IN PCSTR File,
00118 IN ULONG Line,
00119 IN ULONG RemlockSize
00120 )
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 {
00159
PIO_PRIVATE_REMOVE_LOCK Lock = (
PIO_PRIVATE_REMOVE_LOCK) PublicLock;
00160 LONG lockValue;
00161
NTSTATUS status;
00162
00163
PIO_REMOVE_LOCK_TRACKING_BLOCK trackingBlock;
00164
00165
00166
00167
00168
00169 lockValue = InterlockedIncrement(&
Lock->Common.IoCount);
00170
00171
ASSERTMSG(
"IoAcquireRemoveLock - lock value was negative : ",
00172 (lockValue > 0));
00173
00174
if (!
Lock->Common.Removed) {
00175
00176
switch (RemlockSize) {
00177
case CHECKEDSIZE:
00178
00179
ASSERTMSG(
"RemoveLock increased to meet LockHighWatermark",
00180 ((0 ==
Lock->Dbg.HighWatermark) ||
00181 (lockValue <= Lock->
Dbg.HighWatermark)));
00182
00183 trackingBlock =
ExAllocatePoolWithTag(
00184
NonPagedPool,
00185
sizeof(
IO_REMOVE_LOCK_TRACKING_BLOCK),
00186
Lock->Dbg.AllocateTag);
00187
00188
if (
NULL == trackingBlock) {
00189
00190
00191 InterlockedIncrement (&
Lock->Dbg.LowMemoryCount);
00192
00193
00194
00195
00196
00197
00198
00199
00200 }
else {
00201
00202 KIRQL oldIrql;
00203
00204 RtlZeroMemory (trackingBlock,
00205
sizeof (
IO_REMOVE_LOCK_TRACKING_BLOCK));
00206
00207 trackingBlock->
Tag = Tag;
00208 trackingBlock->
File =
File;
00209 trackingBlock->
Line = Line;
00210
00211
KeQueryTickCount(&trackingBlock->
TimeLocked);
00212
00213 ExAcquireSpinLock (&
Lock->Dbg.Spin, &oldIrql);
00214 trackingBlock->
Link =
Lock->Dbg.Blocks;
00215
Lock->Dbg.Blocks = trackingBlock;
00216 ExReleaseSpinLock(&
Lock->Dbg.Spin, oldIrql);
00217 }
00218
break;
00219
00220
case FREESIZE:
00221
break;
00222
00223
default:
00224
break;
00225 }
00226
00227 status = STATUS_SUCCESS;
00228
00229 }
else {
00230
00231
if (0 == InterlockedDecrement (&
Lock->Common.IoCount)) {
00232
KeSetEvent (&
Lock->Common.RemoveEvent, 0,
FALSE);
00233 }
00234 status = STATUS_DELETE_PENDING;
00235 }
00236
00237
return status;
00238 }
00239
00240
00241 NTSYSAPI
00242
VOID
00243 NTAPI
00244 IoReleaseRemoveLockEx(
00245 IN
PIO_REMOVE_LOCK PublicLock,
00246 IN PVOID Tag,
00247 IN ULONG RemlockSize
00248 )
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 {
00277
PIO_PRIVATE_REMOVE_LOCK Lock = (
PIO_PRIVATE_REMOVE_LOCK) PublicLock;
00278 LONG lockValue;
00279 KIRQL oldIrql;
00280 LARGE_INTEGER ticks;
00281 LONGLONG difference;
00282 BOOLEAN found;
00283
00284
PIO_REMOVE_LOCK_TRACKING_BLOCK last;
00285
PIO_REMOVE_LOCK_TRACKING_BLOCK current;
00286
00287
switch (RemlockSize) {
00288
case CHECKEDSIZE:
00289
00290
00291
00292
00293
00294
00295 found =
FALSE;
00296 ExAcquireSpinLock(&
Lock->Dbg.Spin, &oldIrql);
00297 last = (
Lock->Dbg.Blocks);
00298 current = last;
00299
00300
KeQueryTickCount((&ticks));
00301
00302
while (
NULL != current) {
00303
00304
if (
Lock->Dbg.MaxLockedTicks) {
00305 difference = ticks.QuadPart - current->
TimeLocked.QuadPart;
00306
00307
if (
Lock->Dbg.MaxLockedTicks < difference) {
00308
00309 KdPrint((
"IoReleaseRemoveLock: Lock %#08lx (tag %#08lx) "
00310
"locked for %I64d ticks - TOO LONG\n",
00311
Lock,
00312 current->
Tag,
00313 difference));
00314
00315 KdPrint((
"IoReleaseRemoveLock: Lock acquired in file "
00316
"%s on line %d\n",
00317 current->
File,
00318 current->
Line));
00319
ASSERT(
FALSE);
00320 }
00321 }
00322
00323
if ((!found) && (current->
Tag == Tag)) {
00324 found =
TRUE;
00325
if (current ==
Lock->Dbg.Blocks) {
00326
Lock->Dbg.Blocks = current->
Link;
00327
ExFreePool (current);
00328 current =
Lock->Dbg.Blocks;
00329 }
else {
00330 last->Link = current->
Link;
00331
ExFreePool (current);
00332 current = last->
Link;
00333 }
00334
continue;
00335 }
00336
00337 last = current;
00338 current = current->
Link;
00339 }
00340
00341 ExReleaseSpinLock(&
Lock->Dbg.Spin, oldIrql);
00342
00343
if (!found) {
00344
00345
00346
00347
00348
00349
if (InterlockedDecrement (&
Lock->Dbg.LowMemoryCount) < 0) {
00350
00351
00352
00353
00354 InterlockedIncrement (&
Lock->Dbg.LowMemoryCount);
00355 KdPrint ((
"IoReleaseRemoveLock: Couldn't find Tag %#08lx "
00356
"in the lock tracking list\n",
00357 Tag));
00358
ASSERT(
FALSE);
00359 }
00360 }
00361
break;
00362
00363
case FREESIZE:
00364
break;
00365
00366
default:
00367
break;
00368 }
00369
00370 lockValue = InterlockedDecrement(&
Lock->Common.IoCount);
00371
00372
ASSERT(0 <= lockValue);
00373
00374
if (0 == lockValue) {
00375
00376
ASSERT (
Lock->Common.Removed);
00377
00378
00379
00380
00381
00382
00383
KeSetEvent(&
Lock->Common.RemoveEvent,
00384
IO_NO_INCREMENT,
00385
FALSE);
00386 }
00387
return;
00388 }
00389
00390
00391 NTSYSAPI
00392
VOID
00393 NTAPI
00394 IoReleaseRemoveLockAndWaitEx (
00395 IN
PIO_REMOVE_LOCK PublicLock,
00396 IN PVOID Tag,
00397 IN ULONG RemlockSize
00398 )
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 {
00420
PIO_PRIVATE_REMOVE_LOCK Lock = (
PIO_PRIVATE_REMOVE_LOCK) PublicLock;
00421 LONG ioCount;
00422
00423
PAGED_CODE ();
00424
00425
Lock->Common.Removed =
TRUE;
00426
00427 ioCount = InterlockedDecrement (&
Lock->Common.IoCount);
00428
ASSERT (0 < ioCount);
00429
00430
if (0 < InterlockedDecrement (&
Lock->Common.IoCount)) {
00431
KeWaitForSingleObject (&
Lock->Common.RemoveEvent,
00432
Executive,
00433
KernelMode,
00434
FALSE,
00435
NULL);
00436 }
00437
00438
switch (RemlockSize) {
00439
case CHECKEDSIZE:
00440
00441
ASSERT (
Lock->Dbg.Blocks);
00442
if (Tag !=
Lock->Dbg.Blocks->Tag) {
00443 KdPrint ((
"IoRelaseRemoveLockAndWait last tag invalid %x %x\n",
00444 Tag,
00445
Lock->Dbg.Blocks->Tag));
00446
00447
ASSERT (Tag !=
Lock->Dbg.Blocks->Tag);
00448 }
00449
00450
ExFreePool (
Lock->Dbg.Blocks);
00451
break;
00452
00453
case FREESIZE:
00454
break;
00455
00456
default:
00457
break;
00458
00459 }
00460 }
00461
00462