implemented reuse counters for gdi objects Modified: trunk/reactos/include/win32k/gdiobj.h Modified: trunk/reactos/subsys/win32k/objects/gdiobj.c Modified: trunk/reactos/subsys/win32k/objects/region.c _____
Modified: trunk/reactos/include/win32k/gdiobj.h --- trunk/reactos/include/win32k/gdiobj.h 2005-02-18 09:17:56 UTC (rev 13627) +++ trunk/reactos/include/win32k/gdiobj.h 2005-02-18 12:54:17 UTC (rev 13628) @@ -19,13 +19,16 @@
#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1) #define GDI_HANDLE_TYPE_MASK 0x007f0000 #define GDI_HANDLE_STOCK_MASK 0x00800000 +#define GDI_HANDLE_REUSE_MASK 0xff000000
+#define GDI_HANDLE_REUSECNT_SHIFT 24 + #define GDI_HANDLE_CREATE(i, t) ((HANDLE)(((i) & GDI_HANDLE_INDEX_MASK) | ((t) & GDI_HANDLE_TYPE_MASK))) -#define GDI_HANDLE_GET_INDEX(h) (((DWORD)(h)) & GDI_HANDLE_INDEX_MASK) -#define GDI_HANDLE_GET_TYPE(h) (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK) -#define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK)) -#define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((DWORD)(h)) & GDI_HANDLE_STOCK_MASK)) -#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((DWORD)(h)) | GDI_HANDLE_STOCK_MASK)) +#define GDI_HANDLE_GET_INDEX(h) (((ULONG_PTR)(h)) & GDI_HANDLE_INDEX_MASK) +#define GDI_HANDLE_GET_TYPE(h) (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK) +#define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK)) +#define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((ULONG_PTR)(h)) & GDI_HANDLE_STOCK_MASK)) +#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((ULONG_PTR)(h)) | GDI_HANDLE_STOCK_MASK))
/*! \defgroup GDI object types @@ -74,20 +77,10 @@ #endif } GDIOBJHDR, *PGDIOBJHDR;
-typedef struct _GDIMULTILOCK -{ - HGDIOBJ hObj; - PGDIOBJ pObj; - DWORD ObjectType; -} GDIMULTILOCK, *PGDIMULTILOCK; - -BOOL INTERNAL_CALL GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj); -BOOL INTERNAL_CALL GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj); BOOL INTERNAL_CALL GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle); void INTERNAL_CALL GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS Owner); void INTERNAL_CALL GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo); BOOL INTERNAL_CALL GDIOBJ_ConvertToStockObj(HGDIOBJ *hObj); -BOOL INTERNAL_CALL GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj);
#define GDIOBJ_GetObjectType(Handle) \ GDI_HANDLE_GET_TYPE(Handle) _____
Modified: trunk/reactos/subsys/win32k/objects/gdiobj.c --- trunk/reactos/subsys/win32k/objects/gdiobj.c 2005-02-18 09:17:56 UTC (rev 13627) +++ trunk/reactos/subsys/win32k/objects/gdiobj.c 2005-02-18 12:54:17 UTC (rev 13628) @@ -377,28 +377,31 @@
RtlZeroMemory(ObjectBody, GetObjectSize(ObjectType));
- TypeInfo = (ObjectType & 0xFFFF0000) | (ObjectType >> 16); + TypeInfo = (ObjectType & GDI_HANDLE_TYPE_MASK) | (ObjectType >> 16);
FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead); if(FreeEntry != NULL) { HANDLE PrevProcId; UINT Index; - HGDIOBJ Handle;
/* calculate the entry from the address of the entry in the free slot array */ Index = ((ULONG_PTR)FreeEntry - (ULONG_PTR)&HandleTable->FreeEntries[0]) / sizeof(HandleTable->FreeEntries[0]); Entry = &HandleTable->Entries[Index]; - Handle = (HGDIOBJ)((Index & 0xFFFF) | (ObjectType & 0xFFFF0000));
LockHandle: PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, 0); if(PrevProcId == NULL) { + HGDIOBJ Handle; + ASSERT(Entry->KernelData == NULL);
Entry->KernelData = ObjectBody; + + /* copy the reuse-counter */ + TypeInfo |= Entry->Type & GDI_HANDLE_REUSE_MASK;
/* we found a free entry, no need to exchange this field atomically since we're holding the lock */ @@ -416,6 +419,7 @@ { InterlockedIncrement(&W32Process->GDIObjects); } + Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo & (GDI_HANDLE_TYPE_MASK | GDI_HANDLE_REUSE_MASK)));
DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, ObjectBody); return Handle; @@ -425,7 +429,7 @@ #ifdef GDI_DEBUG if(++Attempts > 20) { - DPRINT1("[%d]Waiting on 0x%x\n", Attempts, Handle); + DPRINT1("[%d]Waiting on handle in index 0x%x\n", Attempts, Index); } #endif /* damn, someone is trying to lock the object even though it doesn't @@ -508,7 +512,8 @@ PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { - if(Entry->Type != 0 && Entry->KernelData != NULL && (ExpectedType == 0 || ((Entry->Type << 16) == ExpectedType))) + if(Entry->Type != 0 && Entry->KernelData != NULL && + (ExpectedType == 0 || ((Entry->Type << 16) == ExpectedType))) { PGDIOBJHDR GdiHdr;
@@ -520,8 +525,8 @@ PW32PROCESS W32Process = PsGetWin32Process(); ULONG Type = Entry->Type << 16;
- /* Clear the type field so when unlocking the handle it gets finally deleted */ - Entry->Type = 0; + /* Clear the type field so when unlocking the handle it gets finally deleted and increment reuse counter */ + Entry->Type = ((Entry->Type >> GDI_HANDLE_REUSECNT_SHIFT) + 1) << GDI_HANDLE_REUSECNT_SHIFT; Entry->KernelData = NULL;
/* unlock the handle slot */ @@ -551,8 +556,9 @@ else { /* the object is currently locked. just clear the type field so when the - object gets unlocked it will be finally deleted from the table. */ - Entry->Type = 0; + object gets unlocked it will be finally deleted from the table. Also + incrment the reuse counter! */ + Entry->Type = ((Entry->Type >> GDI_HANDLE_REUSECNT_SHIFT) + 1) << GDI_HANDLE_REUSECNT_SHIFT;
/* unlock the handle slot */ InterlockedExchangePointer(&Entry->ProcessId, NULL); @@ -563,7 +569,7 @@ } else { - if(Entry->Type != 0) + if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0) { DPRINT1("Attempted to delete object 0x%x, type mismatch (0x%x : 0x%x)\n", hObj, ObjectType, ExpectedType); } @@ -610,85 +616,6 @@ }
/*! - * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be - * duplicates. You should use this function to avoid trying to lock the same object twice! - * - * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields. - * \param nObj number of objects to lock - * \return for each entry in pList this function sets pObj field to point to the object. - * - * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects. -*/ -BOOL INTERNAL_CALL -GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj) -{ - INT i, j; - ASSERT( pList ); - /* FIXME - check for "invalid" handles */ - /* go through the list checking for duplicate objects */ - for (i = 0; i < nObj; i++) - { - pList[i].pObj = NULL; - for (j = 0; j < i; j++) - { - if (pList[i].hObj == pList[j].hObj) - { - /* already locked, so just copy the pointer to the object */ - pList[i].pObj = pList[j].pObj; - break; - } - } - - if (NULL == pList[i].pObj) - { - /* object hasn't been locked, so lock it. */ - if (NULL != pList[i].hObj) - { - pList[i].pObj = GDIOBJ_LockObj(pList[i].hObj, pList[i].ObjectType); - } - } - } - - return TRUE; -} - -/*! - * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be - * duplicates. - * - * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields. - * \param nObj number of objects to lock - * - * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects. -*/ -BOOL INTERNAL_CALL -GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj) -{ - INT i, j; - ASSERT(pList); - - /* go through the list checking for duplicate objects */ - for (i = 0; i < nObj; i++) - { - if (NULL != pList[i].pObj) - { - for (j = i + 1; j < nObj; j++) - { - if ((pList[i].pObj == pList[j].pObj)) - { - /* set the pointer to zero for all duplicates */ - pList[j].pObj = NULL; - } - } - GDIOBJ_UnlockObj(pList[i].hObj); - pList[i].pObj = NULL; - } - } - - return TRUE; -} - -/*! * Initialization of the GDI object engine. */ VOID INTERNAL_CALL @@ -744,11 +671,11 @@
End = &HandleTable->Entries[GDI_HANDLE_COUNT]; for(Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT]; - Entry < End; + Entry != End; Entry++, Index++) { /* ignore the lock bit */ - if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && Entry->Type != 0) + if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0) { HGDIOBJ ObjectHandle;
@@ -824,7 +751,8 @@ /* we're locking an object that belongs to our process or it's a global object if ProcessId == 0 here. ProcessId can only be 0 here if it previously failed to lock the object and it turned out to be a global object. */ - if(EntryType != 0 && Entry->KernelData != NULL && (ExpectedType == 0 || (EntryType == ExpectedType))) + if(EntryType != 0 && Entry->KernelData != NULL && + (ExpectedType == 0 || (EntryType == ExpectedType))) { PETHREAD PrevThread; PGDIOBJHDR GdiHdr; @@ -870,14 +798,15 @@ { InterlockedExchangePointer(&Entry->ProcessId, PrevProcId);
- if(EntryType == 0) + if((EntryType & ~GDI_HANDLE_REUSE_MASK) == 0) { DPRINT1("Attempted to lock object 0x%x that is deleted!\n", hObj); KeRosDumpStackFrames ( NULL, 20 ); } else { - DPRINT1("Attempted to lock object 0x%x, type mismatch (0x%x : 0x%x)\n", hObj, EntryType, ExpectedType); + DPRINT1("Attempted to lock object 0x%x, type mismatch (0x%x : 0x%x)\n", + hObj, EntryType & ~GDI_HANDLE_REUSE_MASK, ExpectedType & ~GDI_HANDLE_REUSE_MASK); KeRosDumpStackFrames ( NULL, 20 ); } #ifdef GDI_DEBUG @@ -981,7 +910,7 @@ #endif }
- if(Entry->Type == 0 && GdiHdr->Locks == 0) + if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) == 0 && GdiHdr->Locks == 0) { PPAGED_LOOKASIDE_LIST LookasideList; PW32PROCESS W32Process = PsGetWin32Process(); @@ -1095,7 +1024,7 @@
Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle); Ret = Entry->KernelData != NULL && - Entry->Type != 0 && + (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 && (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId;
return Ret; @@ -1143,6 +1072,8 @@ exchange it.*/ NewType = GDI_HANDLE_GET_TYPE(*hObj); NewType |= NewType >> 16; + NewType |= (ULONG_PTR)(*hObj) & GDI_HANDLE_REUSE_MASK; + /* This is the type that the object should have right now, save it */ OldType = NewType; /* As the object should be a stock object, set it's flag, but only in the upper 16 bits */ @@ -1268,7 +1199,7 @@ { PETHREAD PrevThread;
- if(Entry->Type != 0 && Entry->KernelData != NULL) + if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 && Entry->KernelData != NULL) { PGDIOBJHDR GdiHdr = GDIBdyToHdr(Entry->KernelData);
@@ -1401,7 +1332,7 @@ PETHREAD PrevThread; PGDIOBJHDR GdiHdr;
- if(FromEntry->Type != 0 && FromEntry->KernelData != NULL) + if((FromEntry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 && FromEntry->KernelData != NULL) { GdiHdr = GDIBdyToHdr(FromEntry->KernelData);
_____
Modified: trunk/reactos/subsys/win32k/objects/region.c --- trunk/reactos/subsys/win32k/objects/region.c 2005-02-18 09:17:56 UTC (rev 13627) +++ trunk/reactos/subsys/win32k/objects/region.c 2005-02-18 12:54:17 UTC (rev 13628) @@ -707,45 +707,43 @@
HRGN FASTCALL REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpPt) { PROSRGNDATA objSrc, rgnDst; - HRGN hNewDst, hRet = NULL; - GDIMULTILOCK Lock[2] = {{hDst, 0, GDI_OBJECT_TYPE_REGION}, {hSrc, 0, GDI_OBJECT_TYPE_REGION}}; + HRGN hRet = NULL; + POINT pt = { 0, 0 };
if( !hDst ) { - if( !( hNewDst = RGNDATA_AllocRgn(1) ) ) + if( !( hDst = RGNDATA_AllocRgn(1) ) ) { return 0; } - Lock[0].hObj = hNewDst; }
- if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) ) - { - DPRINT1("GDIOBJ_LockMultipleObj() failed\n" ); - return 0; - } - rgnDst = Lock[0].pObj; - objSrc = Lock[1].pObj; - - if( objSrc && rgnDst ) + rgnDst = RGNDATA_LockRgn(hDst); + if(rgnDst == NULL) { - if(rgnDst) - { - POINT pt = { 0, 0 }; + return NULL; + } + + objSrc = RGNDATA_LockRgn(hSrc); + if(objSrc == NULL) + { + RGNDATA_UnlockRgn(hDst); + return NULL; + } + if(!lpPt) + lpPt = &pt;
- if(!lpPt) - lpPt = &pt; - - if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) == FALSE) - { // ve failed cleanup and return - hRet = NULL; - } - else{ // ve are fine. unlock the correct pointer and return correct handle - hRet = Lock[0].hObj; - } + if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) == FALSE) + { // ve failed cleanup and return + hRet = NULL; } + else{ // ve are fine. unlock the correct pointer and return correct handle + hRet = hDst; } - GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])); + + RGNDATA_UnlockRgn(hSrc); + RGNDATA_UnlockRgn(hDst); + return hRet; }
@@ -1957,21 +1955,12 @@ INT CombineMode) { INT result = ERROR; - GDIMULTILOCK Lock[3] = {{hDest, 0, GDI_OBJECT_TYPE_REGION}, {hSrc1, 0, GDI_OBJECT_TYPE_REGION}, {hSrc2, 0, GDI_OBJECT_TYPE_REGION}}; PROSRGNDATA destRgn, src1Rgn, src2Rgn; - - if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) ) - { - DPRINT1("GDIOBJ_LockMultipleObj() failed\n" ); - return ERROR; - } - - destRgn = (PROSRGNDATA) Lock[0].pObj; - src1Rgn = (PROSRGNDATA) Lock[1].pObj; - src2Rgn = (PROSRGNDATA) Lock[2].pObj; - + + destRgn = RGNDATA_LockRgn(hDest); if( destRgn ) { + src1Rgn = RGNDATA_LockRgn(hSrc1); if( src1Rgn ) { if (CombineMode == RGN_COPY) @@ -1982,7 +1971,8 @@ } else { - if( src2Rgn ) + src2Rgn = RGNDATA_LockRgn(hSrc2); + if( src2Rgn ) { switch (CombineMode) { @@ -1999,17 +1989,26 @@ REGION_SubtractRegion(destRgn, src1Rgn, src2Rgn); break; } + RGNDATA_UnlockRgn(hSrc2); result = destRgn->rdh.iType; } + else + { + DPRINT1("NtGdiCombineRgn requires hSrc2 != NULL for combine mode %d!\n", CombineMode); + } } + + RGNDATA_UnlockRgn(hSrc1); } + + RGNDATA_UnlockRgn(hDest); } else { DPRINT("NtGdiCombineRgn: hDest unavailable\n"); result = ERROR; } - GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])); + return result; }