Author: tkreuzer Date: Wed Feb 6 08:09:26 2008 New Revision: 32149
URL: http://svn.reactos.org/svn/reactos?rev=32149&view=rev Log: - use intrinsic interlocked functions - add a function to get a full stackbacktrace including usermode
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c (original) +++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c Wed Feb 6 08:09:26 2008 @@ -32,6 +32,7 @@
#ifdef GDI_DEBUG BOOLEAN STDCALL KiRosPrintAddress(PVOID Address); +NTSYSAPI ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags); #endif
#define GDI_ENTRY_TO_INDEX(ht, e) \ @@ -170,7 +171,7 @@ }
ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */ - + HandleTable->FirstFree = 0; HandleTable->FirstUnused = RESERVE_ENTRIES_COUNT;
@@ -200,8 +201,8 @@
static int leak_reported = 0; #define GDI_STACK_LEVELS 12 -static ULONG GDIHandleAllocator[GDI_HANDLE_COUNT][GDI_STACK_LEVELS]; -static ULONG GDIHandleLocker[GDI_HANDLE_COUNT][GDI_STACK_LEVELS]; +static ULONG GDIHandleAllocator[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1]; +static ULONG GDIHandleLocker[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1]; struct DbgOpenGDIHandle { ULONG idx; @@ -287,6 +288,23 @@ if ( i < n && h[i].count == 1 ) DbgPrint ( "(list terminated - the remaining entries have 1 allocation only)\n" ); } + +ULONG +CaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture) +{ + ULONG nFrameCount; + + memset(pFrames, 0x00, (nFramesToCapture + 1) * sizeof(PVOID)); + + nFrameCount = RtlCaptureStackBackTrace(1, nFramesToCapture, pFrames, NULL); + + if (nFrameCount < nFramesToCapture) + { + nFrameCount += RtlWalkFrameChain(pFrames + nFrameCount, nFramesToCapture - nFrameCount, 1); + } + + return nFrameCount; +} #endif /* GDI_DEBUG */
@@ -334,7 +352,7 @@ idxNextFree = (ULONG)pFreeEntry->KernelData; idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstFree, idxNextFree, idxFirstFree); } - else + else { idxFirstFree = HandleTable->FirstUnused; idxNextFree = idxFirstFree + 1; @@ -470,7 +488,7 @@ Entry = &HandleTable->Entries[Index];
LockHandle: - PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, 0); + PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, 0); if(PrevProcId == NULL) { HGDIOBJ Handle; @@ -485,16 +503,15 @@ Entry->Type = TypeInfo;
/* unlock the entry */ - (void)InterlockedExchangePointer(&Entry->ProcessId, CurrentProcessId); - -#ifdef GDI_DEBUG - memset ( GDIHandleAllocator[Index], 0x00, GDI_STACK_LEVELS * sizeof(ULONG) ); - RtlCaptureStackBackTrace(1, GDI_STACK_LEVELS, (PVOID*)GDIHandleAllocator[Index], NULL); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, CurrentProcessId); + +#ifdef GDI_DEBUG + CaptureStackBackTace((PVOID*)GDIHandleAllocator[Index], GDI_STACK_LEVELS); #endif /* GDI_DEBUG */
if(W32Process != NULL) { - InterlockedIncrement(&W32Process->GDIObjects); + _InterlockedIncrement(&W32Process->GDIObjects); } Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo << GDI_ENTRY_UPPER_SHIFT));
@@ -586,8 +603,12 @@ HandleType != ExpectedType) || HandleType == 0 ) { - DPRINT1("Attempted to free object 0x%x of wrong type (Handle: 0x%x, expected: 0x%x)\n", - hObj, HandleType, ExpectedType); + DPRINT1("Attempted to free object 0x%x of wrong type (Handle: 0x%x, expected: 0x%x)\n", + hObj, HandleType, ExpectedType); +#ifdef GDI_DEBUG + DPRINT1("-> called from:\n"); + KeRosDumpStackFrames(NULL, 20); +#endif return FALSE; }
@@ -596,7 +617,7 @@ LockHandle: /* lock the object, we must not delete global objects, so don't exchange the locking process ID to zero when attempting to lock a global object... */ - PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); + PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { if( (Entry->KernelData != NULL) && @@ -616,14 +637,14 @@ Entry->Type = (Entry->Type + GDI_ENTRY_REUSE_INC) & ~GDI_ENTRY_BASETYPE_MASK;
/* unlock the handle slot */ - (void)InterlockedExchangePointer(&Entry->ProcessId, NULL); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL);
/* push this entry to the free list */ InterlockedPushFreeEntry(HandleTable, GDI_ENTRY_TO_INDEX(HandleTable, Entry));
if(W32Process != NULL) { - InterlockedDecrement(&W32Process->GDIObjects); + _InterlockedDecrement(&W32Process->GDIObjects); }
/* call the cleanup routine. */ @@ -662,7 +683,7 @@ else { LockErrorDebugOutput(hObj, Entry, "GDIOBJ_FreeObj"); - (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId); } } else if(PrevProcId == LockedProcessId) @@ -883,7 +904,7 @@ { /* Lock the handle table entry. */ LockedProcessId = (HANDLE)((ULONG_PTR)HandleProcessId | 0x1); - PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, + PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, HandleProcessId);
@@ -905,20 +926,19 @@ GdiHdr->LockingThread = Thread; GdiHdr->Locks = 1; #ifdef GDI_DEBUG - memset(GDIHandleLocker[GDI_HANDLE_GET_INDEX(hObj)], 0x00, GDI_STACK_LEVELS * sizeof(ULONG)); - RtlCaptureStackBackTrace(1, GDI_STACK_LEVELS, (PVOID*)GDIHandleLocker[GDI_HANDLE_GET_INDEX(hObj)], NULL); + CaptureStackBackTace((PVOID*)GDIHandleLocker[GDI_HANDLE_GET_INDEX(hObj)], GDI_STACK_LEVELS); #endif Object = Entry->KernelData; } else { - InterlockedIncrement((PLONG)&GdiHdr->Locks); + _InterlockedIncrement((PLONG)&GdiHdr->Locks); if (GdiHdr->LockingThread != Thread) { - InterlockedDecrement((PLONG)&GdiHdr->Locks); + _InterlockedDecrement((PLONG)&GdiHdr->Locks);
/* Unlock the handle table entry. */ - (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
DelayExecution(); continue; @@ -941,7 +961,7 @@ }
/* Unlock the handle table entry. */ - (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
break; } @@ -1028,7 +1048,7 @@ { /* Lock the handle table entry. */ LockedProcessId = (HANDLE)((ULONG_PTR)HandleProcessId | 0x1); - PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, + PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, HandleProcessId);
@@ -1045,13 +1065,13 @@ PGDIOBJHDR GdiHdr = GDIBdyToHdr(Entry->KernelData);
#ifdef GDI_DEBUG - if (InterlockedIncrement((PLONG)&GdiHdr->Locks) == 1) + if (_InterlockedIncrement((PLONG)&GdiHdr->Locks) == 1) { memset(GDIHandleLocker[HandleIndex], 0x00, GDI_STACK_LEVELS * sizeof(ULONG)); RtlCaptureStackBackTrace(1, GDI_STACK_LEVELS, (PVOID*)GDIHandleLocker[HandleIndex], NULL); } #else - InterlockedIncrement((PLONG)&GdiHdr->Locks); + _InterlockedIncrement((PLONG)&GdiHdr->Locks); #endif Object = Entry->KernelData; } @@ -1070,7 +1090,7 @@ }
/* Unlock the handle table entry. */ - (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
break; } @@ -1102,13 +1122,13 @@ { PGDIOBJHDR GdiHdr = GDIBdyToHdr(Object); #ifdef GDI_DEBUG - if (InterlockedDecrement((PLONG)&GdiHdr->Locks) == 0) + if (_InterlockedDecrement((PLONG)&GdiHdr->Locks) == 0) { memset(GDIHandleLocker[GDI_HANDLE_GET_INDEX(Object)], 0x00, GDI_STACK_LEVELS * sizeof(ULONG)); RtlCaptureStackBackTrace(1, GDI_STACK_LEVELS, (PVOID*)GDIHandleLocker[GDI_HANDLE_GET_INDEX(Object)], NULL); } #else - if (InterlockedDecrement((PLONG)&GdiHdr->Locks) < 0) + if (_InterlockedDecrement((PLONG)&GdiHdr->Locks) < 0) DPRINT1("Trying to unlock non-existant object\n"); #endif } @@ -1168,7 +1188,7 @@
LockHandle: /* lock the object, we must not convert stock objects, so don't check!!! */ - PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); + PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { LONG NewType, PrevType, OldType; @@ -1188,7 +1208,7 @@ NewType = OldType | GDI_ENTRY_STOCK_MASK;
/* Try to exchange the type field - but only if the old (previous type) matches! */ - PrevType = InterlockedCompareExchange(&Entry->Type, NewType, OldType); + PrevType = _InterlockedCompareExchange(&Entry->Type, NewType, OldType); if(PrevType == OldType && Entry->KernelData != NULL) { PETHREAD PrevThread; @@ -1217,14 +1237,14 @@ W32Process = (PW32PROCESS)OldProcess->Win32Process; if(W32Process != NULL) { - InterlockedDecrement(&W32Process->GDIObjects); + _InterlockedDecrement(&W32Process->GDIObjects); } ObDereferenceObject(OldProcess); } }
/* remove the process id lock and make it global */ - (void)InterlockedExchangePointer(&Entry->ProcessId, GDI_GLOBAL_PROCESS); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, GDI_GLOBAL_PROCESS);
hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK); *phObj = hObj; @@ -1246,7 +1266,7 @@ /* WTF?! The object is already locked by a different thread! Release the lock, wait a bit and try again! FIXME - we should give up after some time unless we want to wait forever! */ - (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
DelayExecution(); goto LockHandle; @@ -1304,7 +1324,7 @@
LockHandle: /* lock the object, we must not convert stock objects, so don't check!!! */ - PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, ProcessId, LockedProcessId); + PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, ProcessId, LockedProcessId); if(PrevProcId == ProcessId) { PETHREAD PrevThread; @@ -1330,7 +1350,7 @@ W32Process = (PW32PROCESS)OldProcess->Win32Process; if(W32Process != NULL) { - InterlockedDecrement(&W32Process->GDIObjects); + _InterlockedDecrement(&W32Process->GDIObjects); } ObDereferenceObject(OldProcess); } @@ -1344,14 +1364,14 @@ W32Process = (PW32PROCESS)NewOwner->Win32Process; if(W32Process != NULL) { - InterlockedIncrement(&W32Process->GDIObjects); + _InterlockedIncrement(&W32Process->GDIObjects); } } else ProcessId = 0;
/* remove the process id lock and change it to the new process id */ - (void)InterlockedExchangePointer(&Entry->ProcessId, ProcessId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, ProcessId);
/* we're done! */ return; @@ -1370,7 +1390,7 @@ being deleted in the meantime (because we don't have aquired a reference at this point). FIXME - we should give up after some time unless we want to wait forever! */ - (void)InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
DelayExecution(); goto LockHandle; @@ -1437,7 +1457,7 @@
LockHandleFrom: /* lock the object, we must not convert stock objects, so don't check!!! */ - FromPrevProcId = InterlockedCompareExchangePointer(&FromEntry->ProcessId, FromProcessId, FromLockedProcessId); + FromPrevProcId = _InterlockedCompareExchangePointer((PVOID*)&FromEntry->ProcessId, FromProcessId, FromLockedProcessId); if(FromPrevProcId == FromProcessId) { PETHREAD PrevThread; @@ -1470,7 +1490,7 @@ GDIOBJ_SetOwnership(HandleTable, CopyTo, NULL); }
- (void)InterlockedExchangePointer(&FromEntry->ProcessId, FromPrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&FromEntry->ProcessId, FromPrevProcId); } else { @@ -1486,7 +1506,7 @@ being deleted in the meantime (because we don't have aquired a reference at this point). FIXME - we should give up after some time unless we want to wait forever! */ - (void)InterlockedExchangePointer(&FromEntry->ProcessId, FromPrevProcId); + (void)_InterlockedExchangePointer((PVOID*)&FromEntry->ProcessId, FromPrevProcId);
DelayExecution(); goto LockHandleFrom;