Index: /trunk/include/iprt/heap.h
===================================================================
--- /trunk/include/iprt/heap.h	(revision 287)
+++ /trunk/include/iprt/heap.h	(revision 288)
@@ -33,4 +33,7 @@
 /** Pointer to a handle to a simple heap. */
 typedef RTHEAPSIMPLE *PRTHEAPSIMPLE;
+
+/** NIL simple heap handle. */
+#define NIL_RTHEAPSIMPLE    ((RTHEAPSIMPLE)0)
 /* <<< types.h */
 
@@ -39,5 +42,5 @@
 /**
  * Initializes the heap.
- * 
+ *
  * @returns IPRT status code on success.
  * @param   pHeap       Where to store the heap anchor block on success.
@@ -49,11 +52,12 @@
 /**
  * Merge two simple heaps into one.
- * 
+ *
  * The requiremet is of course that they next two each other memory wise.
- * 
+ *
  * @returns IPRT status code on success.
  * @param   pHeap       Where to store the handle to the merged heap on success.
  * @param   Heap1       Handle to the first heap.
  * @param   Heap2       Handle to the second heap.
+ * @remark  This API isn't implemented yet.
  */
 RTDECL(int) RTHeapSimpleMerge(PRTHEAPSIMPLE pHeap, RTHEAPSIMPLE Heap1, RTHEAPSIMPLE Heap2);
@@ -61,8 +65,8 @@
 /**
  * Allocates memory from the specified simple heap.
- * 
+ *
  * @returns Pointer to the allocated memory block on success.
  * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.)
- * 
+ *
  * @param   Heap        The heap to allocate the memory on.
  * @param   cb          The requested heap block size.
@@ -74,8 +78,8 @@
 /**
  * Allocates zeroed memory from the specified simple heap.
- * 
+ *
  * @returns Pointer to the allocated memory block on success.
  * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.)
- * 
+ *
  * @param   Heap        The heap to allocate the memory on.
  * @param   cb          The requested heap block size.
@@ -86,6 +90,30 @@
 
 /**
+ * Reallocates / Allocates / Frees a heap block.
+ *
+ * @param   Heap        The heap. This is optional and will only be used for strict assertions.
+ * @param   pv          The heap block returned by RTHeapSimple. If NULL it behaves like RTHeapSimpleAlloc().
+ * @param   cbNew       The new size of the heap block. If NULL it behaves like RTHeapSimpleFree().
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(void *) RTHeapSimpleRealloc(RTHEAPSIMPLE Heap, void *pv, size_t cbNew, size_t cbAlignment);
+
+/**
+ * Reallocates / Allocates / Frees a heap block, zeroing any new bits.
+ *
+ * @param   Heap        The heap. This is optional and will only be used for strict assertions.
+ * @param   pv          The heap block returned by RTHeapSimple. If NULL it behaves like RTHeapSimpleAllocZ().
+ * @param   cbNew       The new size of the heap block. If NULL it behaves like RTHeapSimpleFree().
+ * @param   cbAlignment The requested heap block alignment. Pass 0 for default alignment.
+ *                      Must be a power of 2.
+ * @remark  This API isn't implemented yet.
+ */
+RTDECL(void *) RTHeapSimpleReallocZ(RTHEAPSIMPLE Heap, void *pv, size_t cbNew, size_t cbAlignment);
+
+/**
  * Frees memory allocated from a simple heap.
- * 
+ *
  * @param   Heap    The heap. This is optional and will only be used for strict assertions.
  * @param   pv      The heap block returned by RTHeapSimple
@@ -93,16 +121,59 @@
 RTDECL(void) RTHeapSimpleFree(RTHEAPSIMPLE Heap, void *pv);
 
-#ifdef DEBUG
 /**
- * Dumps the hypervisor heap to the (default) log.
- * 
+ * Gets the size of the specified heap block.
+ *
+ * @returns The actual size of the heap block.
+ * @returns 0 if \a pv is NULL or it doesn't point to a valid heap block. An invalid \a pv
+ *          can also cause traps or trigger assertions.
+ * @param   Heap    The heap. This is optional and will only be used for strict assertions.
+ * @param   pv      The heap block returned by RTHeapSimple
+ */
+RTDECL(size_t) RTHeapSimpleSize(RTHEAPSIMPLE Heap, void *pv);
+
+/**
+ * Gets the size of the heap.
+ *
+ * This size includes all the internal heap structures. So, even if the heap is
+ * empty the RTHeapSimpleGetFreeSize() will never reach the heap size returned
+ * by this function.
+ *
+ * @returns The heap size.
+ * @returns 0 if heap was safely detected as being bad.
+ * @param   Heap    The heap.
+ */
+RTDECL(size_t) RTHeapSimpleGetHeapSize(RTHEAPSIMPLE Heap);
+
+/**
+ * Returns the sum of all free heap blocks.
+ *
+ * This is the amount of memory you can theoretically allocate
+ * if you do allocations exactly matching the free blocks.
+ *
+ * @returns The size of the free blocks.
+ * @returns 0 if heap was safely detected as being bad.
+ * @param   Heap    The heap.
+ */
+RTDECL(size_t) RTHeapSimpleGetFreeSize(RTHEAPSIMPLE Heap);
+
+/**
+ * Printf like callbaclk function for RTHeapSimpleDump.
+ * @param   pszFormat   IPRT format string.
+ * @param   ...         Format arguments.
+ */
+typedef DECLCALLBACK(void) FNRTHEAPSIMPLEPRINTF(const char *pszFormat, ...);
+/** Pointer to a FNRTHEAPSIMPLEPRINTF function. */
+typedef FNRTHEAPSIMPLEPRINTF *PFNRTHEAPSIMPLEPRINTF;
+
+/**
+ * Dumps the hypervisor heap.
+ *
  * @param   Heap        The heap handle.
+ * @param   pfnPrintf   Printf like function that groks IPRT formatting.
  */
-RTDECL(void) RTHeapSimpleDump(RTHEAPSIMPLE Heap);
-#endif
-
+RTDECL(void) RTHeapSimpleDump(RTHEAPSIMPLE Heap, PFNRTHEAPSIMPLEPRINTF pfnPrintf);
 
 __END_DECLS
 
-#endif 
+#endif
 
Index: /trunk/src/VBox/Runtime/testcase/tstHeapSimple.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstHeapSimple.cpp	(revision 287)
+++ /trunk/src/VBox/Runtime/testcase/tstHeapSimple.cpp	(revision 288)
@@ -68,33 +68,30 @@
     } aOps[] =
     {
-        {        16,          0,    NULL,  0 },
+        {        16,          0,    NULL,  0 },  // 0
         {        16,          4,    NULL,  1 },
         {        16,          8,    NULL,  2 },
         {        16,         16,    NULL,  5 },
         {        16,         32,    NULL,  4 },
-        {        32,          0,    NULL,  3 },
+        {        32,          0,    NULL,  3 },  // 5
         {        31,          0,    NULL,  6 },
         {      1024,          0,    NULL,  8 },
         {      1024,         32,    NULL, 10 },
         {      1024,         32,    NULL, 12 },
-        { PAGE_SIZE,  PAGE_SIZE,    NULL, 13 },
+        { PAGE_SIZE,  PAGE_SIZE,    NULL, 13 },  // 10
         {      1024,         32,    NULL,  9 },
         { PAGE_SIZE,         32,    NULL, 11 },
         { PAGE_SIZE,  PAGE_SIZE,    NULL, 14 },
         {        16,          0,    NULL, 15 },
-        {        9,           0,    NULL,  7 },
+        {        9,           0,    NULL,  7 },  // 15
         {        16,          0,    NULL,  7 },
         {        36,          0,    NULL,  7 },
         {        16,          0,    NULL,  7 },
         {     12344,          0,    NULL,  7 },
-        {        50,          0,    NULL,  7 },
+        {        50,          0,    NULL,  7 },  // 20
         {        16,          0,    NULL,  7 },
     };
     unsigned i;
-#ifdef DEBUG
-    RTHeapSimpleDump(Heap);
-#endif
-//    size_t cbBefore = RTHeapSimpleGetFreeSize(Heap);
-    size_t cbBefore = 0;
+    RTHeapSimpleDump(Heap, (PFNRTHEAPSIMPLEPRINTF)RTPrintf);
+    size_t cbBefore = RTHeapSimpleGetFreeSize(Heap);
     static char szFill[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
@@ -119,32 +116,31 @@
     for (i = 0; i < ELEMENTS(aOps); i++)
     {
-        if (    !aOps[i].pvAlloc
-            ||  aOps[i].uAlignment == PAGE_SIZE)
+        if (!aOps[i].pvAlloc)
             continue;
-        //size_t cbBeforeSub = RTHeapSimpleGetFreeSize(Heap);
+        //RTPrintf("debug: i=%d pv=%#x cb=%#zx align=%#zx cbReal=%#zx\n", i, aOps[i].pvAlloc,
+        //         aOps[i].cb, aOps[i].uAlignment, RTHeapSimpleSize(Heap, aOps[i].pvAlloc));
+        size_t cbBeforeSub = RTHeapSimpleGetFreeSize(Heap);
         RTHeapSimpleFree(Heap, aOps[i].pvAlloc);
+        size_t cbAfterSubFree = RTHeapSimpleGetFreeSize(Heap);
 
-        //RTPrintf("debug: i=%d cbBeforeSub=%d now=%d\n", i, cbBeforeSub, RTHeapSimpleGetFreeSize(Heap));
         void *pv;
         pv = RTHeapSimpleAlloc(Heap, aOps[i].cb, aOps[i].uAlignment);
-        if (pv)
+        if (!pv)
         {
             RTPrintf("Failure: RTHeapSimpleAlloc(%p, %#x, %#x,) -> NULL i=%d\n", (void *)Heap, aOps[i].cb, aOps[i].uAlignment, i);
             return 1;
         }
+        //RTPrintf("debug: i=%d pv=%p cbReal=%#zx cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx \n", i, pv, RTHeapSimpleSize(Heap, pv),
+        //         cbBeforeSub, cbAfterSubFree, RTHeapSimpleGetFreeSize(Heap));
         if (pv != aOps[i].pvAlloc)
+            RTPrintf("Warning: Free+Alloc returned different address. new=%p old=%p i=%d\n", pv, aOps[i].pvAlloc, i);
+        aOps[i].pvAlloc = pv;
+        size_t cbAfterSubAlloc = RTHeapSimpleGetFreeSize(Heap);
+        if (cbBeforeSub != cbAfterSubAlloc)
         {
-            RTPrintf("Failure: Free+Alloc returned different address. new=%p old=%p i=%d (doesn't work with delayed free)\n", pv, aOps[i].pvAlloc, i);
-            //return 1;
+            RTPrintf("Warning: cbBeforeSub=%#zx cbAfterSubFree=%#zx cbAfterSubAlloc=%#zx. i=%d\n",
+                     cbBeforeSub, cbAfterSubFree, cbAfterSubAlloc, i);
+            //return 1; - won't work correctly until we start creating free block instead of donating memory on alignment.
         }
-        aOps[i].pvAlloc = pv;
-        #if 0 /* won't work :/ */
-        size_t cbAfterSub = RTHeapSimpleGetFreeSize(Heap);
-        if (cbBeforeSub != cbAfterSub)
-        {
-            RTPrintf("Failure: cbBeforeSub=%d cbAfterSub=%d. i=%d\n", cbBeforeSub, cbAfterSub, i);
-            return 1;
-        }
-        #endif
     }
 
@@ -160,8 +156,5 @@
                 continue;
             //RTPrintf("j=%d i=%d free=%d cb=%d pv=%p\n", j, i, RTHeapSimpleGetFreeSize(Heap), aOps[j].cb, aOps[j].pvAlloc);
-            if (aOps[j].uAlignment == PAGE_SIZE)
-                cbBefore -= aOps[j].cb;
-            else
-                RTHeapSimpleFree(Heap, aOps[j].pvAlloc);
+            RTHeapSimpleFree(Heap, aOps[j].pvAlloc);
             aOps[j].pvAlloc = NULL;
             cFreed++;
@@ -169,18 +162,14 @@
     }
     Assert(cFreed == RT_ELEMENTS(aOps));
-    //RTPrintf("i=done free=%d\n", RTHeapSimpleGetFreeSize(Heap));
+    RTPrintf("i=done free=%d\n", RTHeapSimpleGetFreeSize(Heap));
 
-#if 0
     /* check that we're back at the right amount of free memory. */
-    //size_t cbAfter = RTHeapSimpleGetFreeSize(Heap);
+    size_t cbAfter = RTHeapSimpleGetFreeSize(Heap);
     if (cbBefore != cbAfter)
     {
         RTPrintf("Warning: Either we've split out an alignment chunk at the start, or we've got\n"
                  "         an alloc/free accounting bug: cbBefore=%d cbAfter=%d\n", cbBefore, cbAfter);
-#ifdef DEBUG
-        RTHeapSimpleDump(Heap);
-#endif
+        RTHeapSimpleDump(Heap, (PFNRTHEAPSIMPLEPRINTF)RTPrintf);
     }
-#endif 
 
     RTPrintf("tstHeapSimple: Success\n");
