Make the Global* memory API functions thread safe

Dmitry Timoshkov dmitry at baikal.ru
Tue May 20 05:47:08 CDT 2003


Hello,

this patch uncomments HeapLock/HeapUnlock calls in the Global*
family API functions. This change has passed some internal test
of installing and running a fairly non-trivial application suite
and not caused any dead locks or crashes.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Make the Global* memory API functions thread safe.

--- cvs/hq/wine/memory/global.c	Sun May 11 13:30:14 2003
+++ wine/memory/global.c	Tue May 20 19:21:13 2003
@@ -1104,28 +1104,35 @@ HGLOBAL WINAPI GlobalAlloc(
    }
    else  /* HANDLE */
    {
-      /* HeapLock(heap); */
+      RtlLockHeap(GetProcessHeap());
 
-      pintern=HeapAlloc(GetProcessHeap(), 0,  sizeof(GLOBAL32_INTERN));
-      if (!pintern) return 0;
-      if(size)
+      pintern = HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
+      if (pintern)
       {
-	 if (!(palloc=HeapAlloc(GetProcessHeap(), hpflags, size+HGLOBAL_STORAGE))) {
-	    HeapFree(GetProcessHeap(), 0, pintern);
-	    return 0;
-	 }
-	 *(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
-	 pintern->Pointer=(char *) palloc+HGLOBAL_STORAGE;
+          pintern->Magic = MAGIC_GLOBAL_USED;
+          pintern->Flags = flags >> 8;
+          pintern->LockCount = 0;
+
+          if (size)
+          {
+              palloc = HeapAlloc(GetProcessHeap(), hpflags, size+HGLOBAL_STORAGE);
+              if (!palloc)
+              {
+                  HeapFree(GetProcessHeap(), 0, pintern);
+                  pintern = NULL;
+              }
+              else
+              {
+                  *(HGLOBAL *)palloc = INTERN_TO_HANDLE(pintern);
+                  pintern->Pointer = (char *)palloc + HGLOBAL_STORAGE;
+              }
+          }
+          else
+              pintern->Pointer = NULL;
       }
-      else
-	 pintern->Pointer=NULL;
-      pintern->Magic=MAGIC_GLOBAL_USED;
-      pintern->Flags=flags>>8;
-      pintern->LockCount=0;
-
-      /* HeapUnlock(heap); */
 
-      return INTERN_TO_HANDLE(pintern);
+      RtlUnlockHeap(GetProcessHeap());
+      return pintern ? INTERN_TO_HANDLE(pintern) : 0;
    }
 }
 
@@ -1146,7 +1153,7 @@ LPVOID WINAPI GlobalLock(
     if (ISPOINTER(hmem))
         return IsBadReadPtr(hmem, 1) ? NULL : hmem;
 
-    /* HeapLock(GetProcessHeap()); */
+    RtlLockHeap(GetProcessHeap());
     __TRY
     {
         pintern = HANDLE_TO_INTERN(hmem);
@@ -1170,7 +1177,7 @@ LPVOID WINAPI GlobalLock(
         SetLastError(ERROR_INVALID_HANDLE);
     }
     __ENDTRY
-    /* HeapUnlock(GetProcessHeap()); */;
+    RtlUnlockHeap(GetProcessHeap());
     return palloc;
 }
 
@@ -1189,7 +1196,7 @@ BOOL WINAPI GlobalUnlock(
 
     if (ISPOINTER(hmem)) return FALSE;
 
-    /* HeapLock(GetProcessHeap()); */
+    RtlLockHeap(GetProcessHeap());
     __TRY
     {
         pintern=HANDLE_TO_INTERN(hmem);
@@ -1215,7 +1222,7 @@ BOOL WINAPI GlobalUnlock(
         locked=FALSE;
     }
     __ENDTRY
-    /* HeapUnlock(GetProcessHeap()); */
+    RtlUnlockHeap(GetProcessHeap());
     return locked;
 }
 
@@ -1241,6 +1248,7 @@ HGLOBAL WINAPI GlobalHandle(
         return 0;
     }
 
+    RtlLockHeap(GetProcessHeap());
     __TRY
     {
         handle = 0;
@@ -1271,9 +1279,10 @@ HGLOBAL WINAPI GlobalHandle(
     __EXCEPT(page_fault)
     {
         SetLastError( ERROR_INVALID_HANDLE );
-        return 0;
+        handle = 0;
     }
     __ENDTRY
+    RtlUnlockHeap(GetProcessHeap());
 
     return handle;
 }
@@ -1296,7 +1305,7 @@ HGLOBAL WINAPI GlobalReAlloc(
    DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
 
    hnew = 0;
-   /* HeapLock(heap); */
+   RtlLockHeap(GetProcessHeap());
    if(flags & GMEM_MODIFY) /* modify flags */
    {
       if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
@@ -1306,16 +1315,19 @@ HGLOBAL WINAPI GlobalReAlloc(
 	  */
          if (hmem == 0)
          {
-	     ERR("GlobalReAlloc32 with null handle!\n");
+             WARN("GlobalReAlloc with null handle!\n");
              SetLastError( ERROR_NOACCESS );
-    	     return 0;
+             hnew = 0;
+         }
+         else
+         {
+             size = HeapSize(GetProcessHeap(), 0, (LPVOID)hmem);
+             hnew = GlobalAlloc(flags, size);
+             palloc = GlobalLock(hnew);
+             memcpy(palloc, (LPVOID)hmem, size);
+             GlobalUnlock(hnew);
+             GlobalFree(hmem);
          }
-	 size=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
-	 hnew=GlobalAlloc( flags, size);
-	 palloc=GlobalLock(hnew);
-	 memcpy(palloc, (LPVOID) hmem, size);
-	 GlobalUnlock(hnew);
-	 GlobalFree(hmem);
       }
       else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
       {
@@ -1358,16 +1370,20 @@ HGLOBAL WINAPI GlobalReAlloc(
 	       if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
 				   (char *) pintern->Pointer-HGLOBAL_STORAGE,
 				   size+HGLOBAL_STORAGE)) == NULL)
-		   return 0; /* Block still valid */
-	       pintern->Pointer=(char *) palloc+HGLOBAL_STORAGE;
+                   hnew = 0; /* Block still valid */
+               else
+                   pintern->Pointer = (char *)palloc+HGLOBAL_STORAGE;
 	    }
 	    else
 	    {
 	        if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+HGLOBAL_STORAGE))
 		   == NULL)
-		    return 0;
-	       *(HGLOBAL *)palloc=hmem;
-	       pintern->Pointer=(char *) palloc+HGLOBAL_STORAGE;
+                    hnew = 0;
+                else
+                {
+                    *(HGLOBAL *)palloc = hmem;
+                    pintern->Pointer = (char *)palloc + HGLOBAL_STORAGE;
+                }
 	    }
 	 }
 	 else
@@ -1380,7 +1396,7 @@ HGLOBAL WINAPI GlobalReAlloc(
 	 }
       }
    }
-   /* HeapUnlock(heap); */
+   RtlUnlockHeap(GetProcessHeap());
    return hnew;
 }
 
@@ -1397,6 +1413,7 @@ HGLOBAL WINAPI GlobalFree(
     PGLOBAL32_INTERN pintern;
     HGLOBAL hreturned;
 
+    RtlLockHeap(GetProcessHeap());
     __TRY
     {
         hreturned = 0;
@@ -1406,7 +1423,6 @@ HGLOBAL WINAPI GlobalFree(
         }
         else  /* HANDLE */
         {
-            /* HeapLock(heap); */
             pintern=HANDLE_TO_INTERN(hmem);
 
             if(pintern->Magic==MAGIC_GLOBAL_USED)
@@ -1423,16 +1439,16 @@ HGLOBAL WINAPI GlobalFree(
                 if(!HeapFree(GetProcessHeap(), 0, pintern))
                     hreturned=hmem;
             }
-            /* HeapUnlock(heap); */
         }
     }
     __EXCEPT(page_fault)
     {
         ERR("page fault occurred ! Caused by bug ?\n");
         SetLastError( ERROR_INVALID_PARAMETER );
-        return hmem;
+        hreturned = hmem;
     }
     __ENDTRY
+    RtlUnlockHeap(GetProcessHeap());
     return hreturned;
 }
 
@@ -1457,23 +1473,26 @@ SIZE_T WINAPI GlobalSize(
    }
    else
    {
-      /* HeapLock(heap); */
+      RtlLockHeap(GetProcessHeap());
       pintern=HANDLE_TO_INTERN(hmem);
 
       if(pintern->Magic==MAGIC_GLOBAL_USED)
       {
-        if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
-            return 0;
-	 retval=HeapSize(GetProcessHeap(), 0,
+         if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
+             retval = 0;
+         else
+         {
+             retval = HeapSize(GetProcessHeap(), 0,
 	                 (char *)(pintern->Pointer) - HGLOBAL_STORAGE );
-         if (retval != (DWORD)-1) retval -= HGLOBAL_STORAGE;
+             if (retval != (DWORD)-1) retval -= HGLOBAL_STORAGE;
+         }
       }
       else
       {
 	 WARN("invalid handle\n");
 	 retval=0;
       }
-      /* HeapUnlock(heap); */
+      RtlUnlockHeap(GetProcessHeap());
    }
    /* HeapSize returns 0xffffffff on failure */
    if (retval == 0xffffffff) retval = 0;
@@ -1540,7 +1559,7 @@ UINT WINAPI GlobalFlags(
    }
    else
    {
-      /* HeapLock(GetProcessHeap()); */
+      RtlLockHeap(GetProcessHeap());
       pintern=HANDLE_TO_INTERN(hmem);
       if(pintern->Magic==MAGIC_GLOBAL_USED)
       {
@@ -1553,7 +1572,7 @@ UINT WINAPI GlobalFlags(
 	 WARN("Invalid handle: %p\n", hmem);
 	 retval=0;
       }
-      /* HeapUnlock(GetProcessHeap()); */
+      RtlUnlockHeap(GetProcessHeap());
    }
    return retval;
 }






More information about the wine-patches mailing list