Index: /trunk/src/VBox/Runtime/common/alloc/memcache.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/alloc/memcache.cpp	(revision 55251)
+++ /trunk/src/VBox/Runtime/common/alloc/memcache.cpp	(revision 55252)
@@ -87,5 +87,5 @@
     /** Bitmap tracking which blocks that has been thru the constructor. */
     void volatile              *pbmCtor;
-    /** Pointer to the object array.. */
+    /** Pointer to the object array. */
     uint8_t                    *pbObjects;
     /** The number of objects on this page.  */
@@ -150,4 +150,9 @@
 
 
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void rtMemCacheFreeList(RTMEMCACHEINT *pThis, PRTMEMCACHEFREEOBJ pHead);
+
 
 RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects,
@@ -221,4 +226,5 @@
     pThis->pFreeTop         = NULL;
 
+#if 1 /* should be fixed now, enable shortly... */
     /** @todo
      * Here is a puzzler (or maybe I'm just blind), the free list code breaks
@@ -235,4 +241,5 @@
      * now. */
     pThis->fUseFreeList = false;
+#endif
 
     *phMemCache = pThis;
@@ -382,19 +389,19 @@
     if (pObj)
     {
-        do
-        {
-            PRTMEMCACHEFREEOBJ pNext = ASMAtomicUoReadPtrT(&pObj->pNext, PRTMEMCACHEFREEOBJ);
-            PRTMEMCACHEFREEOBJ pObjOld;
-            if (ASMAtomicCmpXchgExPtr(&pThis->pFreeTop, pNext, pObj, &pObjOld))
+        pObj = ASMAtomicXchgPtrT(&pThis->pFreeTop, NULL, PRTMEMCACHEFREEOBJ);
+        if (pObj)
+        {
+            if (pObj->pNext)
             {
-                Assert(pObjOld == pObj);
-                Assert(pNext != pObjOld);
-                pObj->pNext = NULL;
-                *ppvObj = pObj;
-                return VINF_SUCCESS;
+                Assert(pObj->pNext != pObj);
+                PRTMEMCACHEFREEOBJ pAllocRace = ASMAtomicXchgPtrT(&pThis->pFreeTop, pObj->pNext, PRTMEMCACHEFREEOBJ);
+                if (pAllocRace)
+                    rtMemCacheFreeList(pThis, pAllocRace);
             }
-            pObj = pObjOld;
-            ASMNopPause();
-        } while (pObj);
+
+            pObj->pNext = NULL;
+            *ppvObj = pObj;
+            return VINF_SUCCESS;
+        }
     }
 
@@ -502,4 +509,56 @@
 
 
+
+/**
+ * Really frees one object.
+ *
+ * @param   pThis               The memory cache.
+ * @param   pvObj               The memory object to free.
+ */
+static void rtMemCacheFreeOne(RTMEMCACHEINT *pThis, void *pvObj)
+{
+    /* Note: Do *NOT* attempt to poison the object! */
+
+    /*
+     * Find the cache page.  The page structure is at the start of the page.
+     */
+    PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK);
+    Assert(pPage->pCache == pThis);
+    Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage);
+
+    /*
+     * Clear the bitmap bit and update the two object counter. Order matters!
+     */
+    uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects;
+    uintptr_t iObj   = offObj / pThis->cbObject;
+    Assert(iObj * pThis->cbObject == offObj);
+    Assert(iObj < pThis->cPerPage);
+    AssertReturnVoid(ASMAtomicBitTestAndClear(pPage->pbmAlloc, iObj));
+
+    ASMAtomicIncS32(&pPage->cFree);
+    ASMAtomicIncS32(&pThis->cFree);
+}
+
+
+/**
+ * Really frees a list of 'freed' object.
+ *
+ * @param   pThis               The memory cache.
+ * @param   pHead               The head of the list.
+ */
+static void rtMemCacheFreeList(RTMEMCACHEINT *pThis, PRTMEMCACHEFREEOBJ pHead)
+{
+    while (pHead)
+    {
+        PRTMEMCACHEFREEOBJ pFreeMe = pHead;
+        pHead = pHead->pNext;
+        pFreeMe->pNext = NULL;
+        ASMCompilerBarrier();
+        rtMemCacheFreeOne(pThis, pFreeMe);
+    }
+}
+
+
+
 RTDECL(void) RTMemCacheFree(RTMEMCACHE hMemCache, void *pvObj)
 {
@@ -514,5 +573,7 @@
     Assert(RT_ALIGN_P(pvObj, pThis->cbAlignment) == pvObj);
 
-    if (pThis->fUseFreeList)
+    if (!pThis->fUseFreeList)
+        rtMemCacheFreeOne(pThis, pvObj);
+    else
     {
 # ifdef RT_STRICT
@@ -532,38 +593,9 @@
          */
         PRTMEMCACHEFREEOBJ pObj = (PRTMEMCACHEFREEOBJ)pvObj;
-        PRTMEMCACHEFREEOBJ pNext = ASMAtomicUoReadPtrT(&pThis->pFreeTop, PRTMEMCACHEFREEOBJ);
-        PRTMEMCACHEFREEOBJ pFreeTopOld;
-        pObj->pNext = pNext;
-        while (!ASMAtomicCmpXchgExPtr(&pThis->pFreeTop, pObj, pNext, &pFreeTopOld))
-        {
-            pNext = pFreeTopOld;
-            Assert(pNext != pObj);
-            pObj->pNext = pNext;
-            ASMNopPause();
-        }
-    }
-    else
-    {
-        /* Note: Do *NOT* attempt to poison the object! */
-
-        /*
-         * Find the cache page.  The page structure is at the start of the page.
-         */
-        PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK);
-        Assert(pPage->pCache == pThis);
-        Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage);
-
-        /*
-         * Clear the bitmap bit and update the two object counter. Order matters!
-         */
-        uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects;
-        uintptr_t iObj   = offObj / pThis->cbObject;
-        Assert(iObj * pThis->cbObject == offObj);
-        Assert(iObj < pThis->cPerPage);
-        AssertReturnVoid(ASMAtomicBitTestAndClear(pPage->pbmAlloc, iObj));
-
-        ASMAtomicIncS32(&pPage->cFree);
-        ASMAtomicIncS32(&pThis->cFree);
-    }
-}
-
+        pObj->pNext = ASMAtomicXchgPtrT(&pThis->pFreeTop, NULL, PRTMEMCACHEFREEOBJ);
+        PRTMEMCACHEFREEOBJ pFreeRace = ASMAtomicXchgPtrT(&pThis->pFreeTop, pObj, PRTMEMCACHEFREEOBJ);
+        if (pFreeRace)
+            rtMemCacheFreeList(pThis, pFreeRace);
+    }
+}
+
