reactos/drivers/filesystems/udfs/udf_dbg.cpp

528 lines
13 KiB
C++

////////////////////////////////////////////////////////////////////
// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
// All rights reserved
// This file was released under the GPLv2 on June 2015.
////////////////////////////////////////////////////////////////////
#include "udffs.h"
#if defined(UDF_DBG) || defined(PRINT_ALWAYS)
//#define TRACK_RESOURCES
//#define TRACK_REF_COUNTERS
ULONG ResCounter = 0;
ULONG AcqCounter = 0;
ULONG UdfTimeStamp = -1;
BOOLEAN
UDFDebugAcquireResourceSharedLite(
IN PERESOURCE Resource,
IN BOOLEAN Wait,
ULONG BugCheckId,
ULONG Line
) {
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
BOOLEAN Success;
#ifdef USE_DLD
if (Wait) {
DLDAcquireShared(Resource, BugCheckId, Line,FALSE);
Success = TRUE;
} else {
Success = ExAcquireResourceSharedLite(Resource,Wait);
}
#else
Success = ExAcquireResourceSharedLite(Resource,Wait);
#endif // USE_DLD
if(Success) {
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
AcqCounter++;
return Success;
}
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
return FALSE;
}
BOOLEAN
UDFDebugAcquireSharedStarveExclusive(
IN PERESOURCE Resource,
IN BOOLEAN Wait,
ULONG BugCheckId,
ULONG Line
) {
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
BOOLEAN Success;
#ifdef USE_DLD
if (Wait) {
DLDAcquireShared(Resource, BugCheckId, Line,FALSE);
Success = TRUE;
} else {
Success = ExAcquireResourceSharedLite(Resource,Wait);
}
#else
Success = ExAcquireResourceSharedLite(Resource,Wait);
#endif // USE_DLD
if(Success) {
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha*:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
AcqCounter++;
return Success;
}
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
return FALSE;
}
BOOLEAN
UDFDebugAcquireResourceExclusiveLite(
IN PERESOURCE Resource,
IN BOOLEAN Wait,
ULONG BugCheckId,
ULONG Line
) {
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Exc:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
BOOLEAN Success;
#ifdef USE_DLD
if (Wait) {
DLDAcquireExclusive(Resource, BugCheckId, Line);
Success = TRUE;
} else {
Success = ExAcquireResourceExclusiveLite(Resource,Wait);
}
#else
Success = ExAcquireResourceExclusiveLite(Resource,Wait);
#endif // USE_DLD
if(Success) {
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Exc:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
AcqCounter++;
return Success;
}
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Exc:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
// BrutePoint();
return FALSE;
}
VOID
UDFDebugReleaseResourceForThreadLite(
IN PERESOURCE Resource,
IN ERESOURCE_THREAD ResourceThreadId,
ULONG BugCheckId,
ULONG Line
)
{
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Free:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
ExReleaseResourceForThreadLite(Resource, ResourceThreadId);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Free:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
AcqCounter--;
}
VOID
UDFDebugDeleteResource(
IN PERESOURCE Resource,
IN ERESOURCE_THREAD ResourceThreadId,
ULONG BugCheckId,
ULONG Line
)
{
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Del:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
_SEH2_TRY {
ASSERT((*((PULONG)Resource)));
ASSERT((*(((PULONG)Resource)+1)));
ExDeleteResourceLite(Resource);
RtlZeroMemory(Resource, sizeof(ERESOURCE));
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
BrutePoint();
} _SEH2_END;
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Del:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
ResCounter--;
}
NTSTATUS
UDFDebugInitializeResourceLite(
IN PERESOURCE Resource,
IN ERESOURCE_THREAD ResourceThreadId,
ULONG BugCheckId,
ULONG Line
)
{
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
NTSTATUS RC;
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Ini:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
ASSERT(!(*((PULONG)Resource)));
ASSERT(!(*(((PULONG)Resource)+1)));
RC = ExInitializeResourceLite(Resource);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Ini:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
if(NT_SUCCESS(RC)) {
ResCounter++;
}
return RC;
}
VOID
UDFDebugConvertExclusiveToSharedLite(
IN PERESOURCE Resource,
IN ERESOURCE_THREAD ResourceThreadId,
ULONG BugCheckId,
ULONG Line
)
{
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:2Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
ExConvertExclusiveToSharedLite(Resource);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:2Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,ResourceThreadId));
#endif
}
BOOLEAN
UDFDebugAcquireSharedWaitForExclusive(
IN PERESOURCE Resource,
IN BOOLEAN Wait,
ULONG BugCheckId,
ULONG Line
) {
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
BOOLEAN Success;
#ifdef USE_DLD
if (Wait) {
DLDAcquireShared(Resource, BugCheckId, Line,TRUE);
Success = TRUE;
} else {
Success = ExAcquireSharedWaitForExclusive(Resource,Wait);
}
#else
Success = ExAcquireSharedWaitForExclusive(Resource,Wait);
#endif // USE_DLD
if(Success) {
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha*:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
return Success;
}
#ifdef TRACK_RESOURCES
UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource,
BugCheckId,Line,PsGetCurrentThread()));
#endif
// BrutePoint();
return FALSE;
}
LONG
UDFDebugInterlockedIncrement(
IN PLONG addr,
ULONG BugCheckId,
ULONG Line)
{
#ifdef TRACK_REF_COUNTERS
LONG a;
a = InterlockedIncrement(addr);
UDFPrint(("ThId:%x:Ilck:Inc:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n",
PsGetCurrentThread(),BugCheckId,Line,addr,a-1,a));
return a;
#else
return InterlockedIncrement(addr);
#endif
}
LONG
UDFDebugInterlockedDecrement(
IN PLONG addr,
ULONG BugCheckId,
ULONG Line)
{
#ifdef TRACK_REF_COUNTERS
LONG a;
a = InterlockedDecrement(addr);
UDFPrint(("ThId:%x:Ilck:Dec:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n",
PsGetCurrentThread(),BugCheckId,Line,addr,a+1,a));
return a;
#else
return InterlockedDecrement(addr);
#endif
}
LONG
UDFDebugInterlockedExchangeAdd(
IN PLONG addr,
IN LONG i,
ULONG BugCheckId,
ULONG Line)
{
#ifdef TRACK_REF_COUNTERS
LONG a;
a = InterlockedExchangeAdd(addr,i);
UDFPrint(("ThId:%x:Ilck:Add:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n",
PsGetCurrentThread(),BugCheckId,Line,addr,a,a+i));
return a;
#else
return InterlockedExchangeAdd(addr,i);
#endif
}
#define MAX_MEM_DEBUG_DESCRIPTORS 8192
typedef struct _MEM_DESC {
ULONG Length;
PCHAR Addr;
#ifdef TRACK_SYS_ALLOC_CALLERS
ULONG SrcId;
ULONG SrcLine;
#endif //TRACK_SYS_ALLOC_CALLERS
POOL_TYPE Type;
} MEM_DESC, *PMEM_DESC;
MEM_DESC MemDesc[MAX_MEM_DEBUG_DESCRIPTORS];
ULONG cur_max = 0;
ULONG AllocCountPaged = 0;
ULONG AllocCountNPaged = 0;
ULONG MemDescInited = 0;
PVOID
DebugAllocatePool(
POOL_TYPE Type,
ULONG size
#ifdef TRACK_SYS_ALLOC_CALLERS
, ULONG SrcId,
ULONG SrcLine
#endif //TRACK_SYS_ALLOC_CALLERS
) {
ULONG i;
// UDFPrint(("SysAllocated: %x\n",AllocCount));
if(!MemDescInited) {
RtlZeroMemory(&MemDesc, sizeof(MemDesc));
MemDescInited = 1;
}
for (i=0;i<cur_max;i++) {
if (MemDesc[i].Addr==NULL) {
MemDesc[i].Addr = (PCHAR)ExAllocatePoolWithTag(Type, (size), 'Fnwd'); // dwnF
ASSERT(MemDesc[i].Addr);
if(MemDesc[i].Addr) {
if(Type == PagedPool) {
AllocCountPaged += (size+7) & ~7;
} else {
AllocCountNPaged += (size+7) & ~7;
}
}
MemDesc[i].Length = size;
MemDesc[i].Type = Type;
#ifdef TRACK_SYS_ALLOC_CALLERS
MemDesc[i].SrcId = SrcId;
MemDesc[i].SrcLine = SrcLine;
#endif //TRACK_SYS_ALLOC_CALLERS
return MemDesc[i].Addr;
}
}
if(cur_max == MAX_MEM_DEBUG_DESCRIPTORS) {
UDFPrint(("Debug memory descriptor list full\n"));
return ExAllocatePoolWithTag(Type, (size) , 'Fnwd');
}
MemDesc[i].Addr = (PCHAR)ExAllocatePoolWithTag(Type, (size) , 'Fnwd');
if(MemDesc[i].Addr) {
if(Type == PagedPool) {
AllocCountPaged += (size+7) & ~7;
} else {
AllocCountNPaged += (size+7) & ~7;
}
}
MemDesc[i].Length = (size);
#ifdef TRACK_SYS_ALLOC_CALLERS
MemDesc[i].SrcId = SrcId;
MemDesc[i].SrcLine = SrcLine;
#endif //TRACK_SYS_ALLOC_CALLERS
MemDesc[i].Type = Type;
cur_max++;
return MemDesc[cur_max-1].Addr;
}
VOID DebugFreePool(PVOID addr) {
ULONG i;
ASSERT(addr);
for (i=0;i<cur_max;i++) {
if (MemDesc[i].Addr == addr) {
if(MemDesc[i].Type == PagedPool) {
AllocCountPaged -= (MemDesc[i].Length+7) & ~7;
} else {
AllocCountNPaged -= (MemDesc[i].Length+7) & ~7;
}
MemDesc[i].Addr = NULL;
MemDesc[i].Length = 0;
#ifdef TRACK_SYS_ALLOC_CALLERS
MemDesc[i].SrcId = 0;
MemDesc[i].SrcLine = 0;
#endif //TRACK_SYS_ALLOC_CALLERS
goto not_bug;
}
}
if (i==cur_max && cur_max != MAX_MEM_DEBUG_DESCRIPTORS) {
UDFPrint(("Buug! - Deallocating nonallocated block\n"));
return;
}
not_bug:
// UDFPrint(("SysAllocated: %x\n",AllocCount));
ExFreePool(addr);
}
NTSTATUS
UDFWaitForSingleObject(
IN PLONG Object,
IN PLARGE_INTEGER Timeout OPTIONAL
)
{
UDFPrint(("UDFWaitForSingleObject\n"));
LARGE_INTEGER LocalTimeout;
LARGE_INTEGER delay;
delay.QuadPart = -(WAIT_FOR_XXX_EMU_DELAY);
if(Timeout && (Timeout->QuadPart)) LocalTimeout = *Timeout;
else LocalTimeout.QuadPart = 0x7FFFFFFFFFFFFFFFLL;
UDFPrint(("SignalState %x\n", *Object));
if(!Object) return STATUS_INVALID_PARAMETER;
if((*Object)) return STATUS_SUCCESS;
while(LocalTimeout.QuadPart>0 && !(*Object) ) {
UDFPrint(("SignalState %x\n", *Object));
// Stall for a while.
KeDelayExecutionThread(KernelMode, FALSE, &delay);
LocalTimeout.QuadPart -= WAIT_FOR_XXX_EMU_DELAY;
}
return STATUS_SUCCESS;
} // end UDFWaitForSingleObject()
NTSTATUS
DbgWaitForSingleObject_(
IN PVOID Object,
IN PLARGE_INTEGER Timeout OPTIONAL
)
{
PLARGE_INTEGER to;
LARGE_INTEGER dto;
// LARGE_INTEGER cto;
NTSTATUS RC;
ULONG c = 20;
dto.QuadPart = -5LL*1000000LL*10LL; // 5 sec
// cto.QuadPart = Timeout->QuadPart;
if(Timeout) {
if(dto.QuadPart > Timeout->QuadPart) {
to = Timeout;
} else {
to = &dto;
}
} else {
to = &dto;
}
for(; c--; c) {
RC = KeWaitForSingleObject(Object, Executive, KernelMode, FALSE, to);
if(RC == STATUS_SUCCESS)
break;
UDFPrint(("No response ?\n"));
if(c<2)
BrutePoint();
}
return RC;
}
#endif // UDF_DBG