Allocate memory for the handle table from paged pool!
[reactos.git] / reactos / subsys / win32k / objects / gdiobj.c
index 0627c3e..149680d 100644 (file)
@@ -19,7 +19,7 @@
 /*
  * GDIOBJ.C - GDI object manipulation routines
  *
- * $Id: gdiobj.c,v 1.69 2004/07/03 13:55:36 navaraf Exp $
+ * $Id: gdiobj.c,v 1.73 2004/10/02 16:48:12 navaraf Exp $
  *
  */
 #include <w32k.h>
@@ -178,6 +178,7 @@ static HGDIOBJ StockObjects[NB_STOCK_OBJECTS];
 static PGDI_HANDLE_TABLE  HandleTable = 0;
 static FAST_MUTEX  HandleTableMutex;
 static FAST_MUTEX  RefCountHandling;
+static LARGE_INTEGER  ShortDelay;
 
 /*!
  * Allocate GDI object table.
@@ -193,9 +194,7 @@ GDIOBJ_iAllocHandleTable (WORD Size)
   
   MemSize = sizeof(GDI_HANDLE_TABLE) + sizeof(PGDIOBJ) * Size;
 
-  /* prevent APC delivery for the *FastMutexUnsafe calls */
-  const KIRQL PrevIrql = KfRaiseIrql(APC_LEVEL);
-  ExAcquireFastMutexUnsafe (&HandleTableMutex);
+  ExAcquireFastMutex(&HandleTableMutex);
   handleTable = ExAllocatePoolWithTag(PagedPool, MemSize, TAG_GDIHNDTBLE);
   ASSERT( handleTable );
   memset (handleTable, 0, MemSize);
@@ -210,8 +209,7 @@ GDIOBJ_iAllocHandleTable (WORD Size)
   if (NULL == handleTable->LookasideLists)
     {
       ExFreePool(handleTable);
-      ExReleaseFastMutexUnsafe (&HandleTableMutex);
-      KfLowerIrql(PrevIrql);
+      ExReleaseFastMutex(&HandleTableMutex);
       return NULL;
     }
   for (ObjType = 0; ObjType < OBJTYPE_COUNT; ObjType++)
@@ -219,8 +217,7 @@ GDIOBJ_iAllocHandleTable (WORD Size)
       ExInitializePagedLookasideList(handleTable->LookasideLists + ObjType, NULL, NULL, 0,
                                      ObjSizes[ObjType].Size + sizeof(GDIOBJHDR), TAG_GDIOBJ, 0);
     }
-  ExReleaseFastMutexUnsafe (&HandleTableMutex);
-  KfLowerIrql(PrevIrql);
+  ExReleaseFastMutex(&HandleTableMutex);
 
   return handleTable;
 }
@@ -344,7 +341,13 @@ GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
   newObject->Magic = GDI_TYPE_TO_MAGIC(ObjectType);
   newObject->lockfile = NULL;
   newObject->lockline = 0;
+#ifdef GDIOBJ_USE_FASTMUTEX
   ExInitializeFastMutex(&newObject->Lock);
+  newObject->RecursiveLockCount = 0;
+#else
+  newObject->LockTid = 0;
+  newObject->LockCount = 0;
+#endif
   HandleTable->Handles[Index] = newObject;
 #if GDI_COUNT_OBJECTS
   HandleTable->HandlesCount++;
@@ -550,6 +553,8 @@ InitGdiObjectHandleTable (VOID)
   ExInitializeFastMutex (&HandleTableMutex);
   ExInitializeFastMutex (&RefCountHandling);
 
+  ShortDelay.QuadPart = -100;
+
   HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT);
   DPRINT("HandleTable: %x\n", HandleTable );
 
@@ -676,6 +681,9 @@ PGDIOBJ FASTCALL
 GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
 {
   PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+#ifndef GDIOBJ_USE_FASTMUTEX
+  DWORD CurrentTid = (DWORD)PsGetCurrentThreadId();
+#endif
 
   DPRINT("(%s:%i) GDIOBJ_LockObjDbg(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
   if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
@@ -704,21 +712,48 @@ GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
       return NULL;
     }
 
-#ifdef NDEBUG
-  ExAcquireFastMutex(&ObjHdr->Lock);
+#ifdef GDIOBJ_USE_FASTMUTEX
+  if (ObjHdr->Lock.Owner == KeGetCurrentThread())
+    {
+      ObjHdr->RecursiveLockCount++;
+    }
+  else
+    {
+#ifdef NDEBUG    
+      ExAcquireFastMutex(&ObjHdr->Lock);
 #else /* NDEBUG */
-  if (! ExTryToAcquireFastMutex(&ObjHdr->Lock))
+      if (! ExTryToAcquireFastMutex(&ObjHdr->Lock))
+        {
+          DPRINT1("Caution! GDIOBJ_LockObj trying to lock object 0x%x second time\n", hObj);
+          DPRINT1("  called from: %s:%i (thread %x)\n", file, line, KeGetCurrentThread());
+          if (NULL != ObjHdr->lockfile)
+            {
+              DPRINT1("  previously locked from: %s:%i (thread %x)\n", ObjHdr->lockfile, ObjHdr->lockline, ObjHdr->Lock.Owner);
+            }
+          ExAcquireFastMutex(&ObjHdr->Lock);
+          DPRINT1("  Disregard previous message about object 0x%x, it's ok\n", hObj);
+        }
+#endif /* NDEBUG */
+      ObjHdr->RecursiveLockCount++;
+    }
+#else
+  if (ObjHdr->LockTid == CurrentTid)
+    {
+      InterlockedIncrement(&ObjHdr->LockCount);
+    }
+  else
     {
-      DPRINT1("Caution! GDIOBJ_LockObj trying to lock object 0x%x second time\n", hObj);
-      DPRINT1("  called from: %s:%i (thread %x)\n", file, line, KeGetCurrentThread());
-      if (NULL != ObjHdr->lockfile)
+      for (;;)
         {
-          DPRINT1("  previously locked from: %s:%i (thread %x)\n", ObjHdr->lockfile, ObjHdr->lockline, ObjHdr->Lock.Owner);
+          if (InterlockedCompareExchange(&ObjHdr->LockTid, CurrentTid, 0) == CurrentTid)
+            {
+              InterlockedIncrement(&ObjHdr->LockCount);
+              break;
+            }
+          /* FIXME: KeDelayExecutionThread(KernelMode, FALSE, &ShortDelay); */
         }
-      ExAcquireFastMutex(&ObjHdr->Lock);
-      DPRINT1("  Disregard previous message about object 0x%x, it's ok\n", hObj);
     }
-#endif /* NDEBUG */
+#endif
 
   ExAcquireFastMutex(&RefCountHandling);
   ObjHdr->dwCount++;
@@ -771,6 +806,9 @@ PGDIOBJ FASTCALL
 GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ObjectType)
 {
   PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+#ifndef GDIOBJ_USE_FASTMUTEX
+  DWORD CurrentTid = (DWORD)PsGetCurrentThreadId();
+#endif
 
   DPRINT("GDIOBJ_LockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
   if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
@@ -780,7 +818,34 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ObjectType)
       return NULL;
     }
 
-  ExAcquireFastMutex(&ObjHdr->Lock);
+#ifdef GDIOBJ_USE_FASTMUTEX
+  if (ObjHdr->Lock.Owner == KeGetCurrentThread())
+    {
+      ObjHdr->RecursiveLockCount++;
+    }
+  else
+    {
+      ExAcquireFastMutex(&ObjHdr->Lock);
+      ObjHdr->RecursiveLockCount++;
+    }
+#else
+  if (ObjHdr->LockTid == CurrentTid)
+    {
+      InterlockedIncrement(&ObjHdr->LockCount);
+    }
+  else
+    {
+      for (;;)
+        {
+          if (InterlockedCompareExchange(&ObjHdr->LockTid, CurrentTid, 0) == CurrentTid)
+            {
+              InterlockedIncrement(&ObjHdr->LockCount);
+              break;
+            }
+          /* FIXME: KeDelayExecutionThread(KernelMode, FALSE, &ShortDelay); */
+        }
+    }
+#endif
 
   ExAcquireFastMutex(&RefCountHandling);
   ObjHdr->dwCount++;
@@ -813,7 +878,15 @@ GDIOBJ_UnlockObj(HGDIOBJ hObj, DWORD ObjectType)
     return FALSE;
   }
 
-  ExReleaseFastMutex(&ObjHdr->Lock);
+#ifdef GDIOBJ_USE_FASTMUTEX
+  if (--ObjHdr->RecursiveLockCount == 0)
+    ExReleaseFastMutex(&ObjHdr->Lock);
+#else
+  if (InterlockedDecrement(&ObjHdr->LockCount) == 0)
+    {
+      InterlockedExchange(&ObjHdr->LockTid, 0);
+    }
+#endif
 
   ExAcquireFastMutex(&RefCountHandling);
   if (0 == (ObjHdr->dwCount & ~0x80000000))