This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
run/locale.t: Add explanation for when tests fail
[perl5.git] / win32 / vmem.h
index cda6f81..d691635 100644 (file)
@@ -9,8 +9,8 @@
  * Options:
  *
  * Defining _USE_MSVCRT_MEM_ALLOC will cause all memory allocations
- * to be forwarded to MSVCRT.DLL. Defining _USE_LINKED_LIST as well will
- * track all allocations in a doubly linked list, so that the host can
+ * to be forwarded to the compiler's MSVCR*.DLL. Defining _USE_LINKED_LIST as
+ * well will track all allocations in a doubly linked list, so that the host can
  * free all memory allocated when it goes away.
  * If _USE_MSVCRT_MEM_ALLOC is not defined then Knuth's boundary tag algorithm
  * is used; defining _USE_BUDDY_BLOCKS will use Knuth's algorithm R
 #ifndef ___VMEM_H_INC___
 #define ___VMEM_H_INC___
 
-// #define _USE_MSVCRT_MEM_ALLOC
+#ifndef UNDER_CE
+#define _USE_MSVCRT_MEM_ALLOC
+#endif
+#define _USE_LINKED_LIST
 
 // #define _USE_BUDDY_BLOCKS
 
@@ -62,18 +65,17 @@ inline void MEMODSlx(char *str, long x)
 #endif
 
 /* 
- * Pass all memory requests throught to msvcrt.dll 
- * optionaly track by using a doubly linked header
+ * Pass all memory requests through to the compiler's msvcr*.dll.
+ * Optionaly track by using a doubly linked header.
  */
 
-typedef void (*LPFREE)(void *block);
-typedef void* (*LPMALLOC)(size_t size);
-typedef void* (*LPREALLOC)(void *block, size_t size);
 #ifdef _USE_LINKED_LIST
+class VMem;
 typedef struct _MemoryBlockHeader* PMEMORY_BLOCK_HEADER;
 typedef struct _MemoryBlockHeader {
     PMEMORY_BLOCK_HEADER    pNext;
     PMEMORY_BLOCK_HEADER    pPrev;
+    VMem *owner;
 } MEMORY_BLOCK_HEADER, *PMEMORY_BLOCK_HEADER;
 #endif
 
@@ -82,14 +84,14 @@ class VMem
 public:
     VMem();
     ~VMem();
-    virtual void* Malloc(size_t size);
-    virtual void* Realloc(void* pMem, size_t size);
-    virtual void Free(void* pMem);
-    virtual void GetLock(void);
-    virtual void FreeLock(void);
-    virtual int IsLocked(void);
-    virtual long Release(void);
-    virtual long AddRef(void);
+    void* Malloc(size_t size);
+    void* Realloc(void* pMem, size_t size);
+    void Free(void* pMem);
+    void GetLock(void);
+    void FreeLock(void);
+    int IsLocked(void);
+    long Release(void);
+    long AddRef(void);
 
     inline BOOL CreateOk(void)
     {
@@ -104,6 +106,7 @@ protected:
        m_Dummy.pNext = ptr;
        ptr->pPrev = &m_Dummy;
        ptr->pNext = next;
+        ptr->owner = this;
        next->pPrev = ptr;
     }
     void UnlinkBlock(PMEMORY_BLOCK_HEADER ptr)
@@ -115,29 +118,20 @@ protected:
     }
 
     MEMORY_BLOCK_HEADER        m_Dummy;
+    CRITICAL_SECTION   m_cs;           // access lock
 #endif
 
     long               m_lRefCount;    // number of current users
-    CRITICAL_SECTION   m_cs;           // access lock
-    HINSTANCE          m_hLib;
-    LPFREE             m_pfree;
-    LPMALLOC           m_pmalloc;
-    LPREALLOC          m_prealloc;
 };
 
 VMem::VMem()
 {
     m_lRefCount = 1;
-    InitializeCriticalSection(&m_cs);
 #ifdef _USE_LINKED_LIST
+    InitializeCriticalSection(&m_cs);
     m_Dummy.pNext = m_Dummy.pPrev =  &m_Dummy;
+    m_Dummy.owner = this;
 #endif
-    m_hLib = LoadLibrary("msvcrt.dll");
-    if (m_hLib) {
-       m_pfree = (LPFREE)GetProcAddress(m_hLib, "free");
-       m_pmalloc = (LPMALLOC)GetProcAddress(m_hLib, "malloc");
-       m_prealloc = (LPREALLOC)GetProcAddress(m_hLib, "realloc");
-    }
 }
 
 VMem::~VMem(void)
@@ -146,20 +140,24 @@ VMem::~VMem(void)
     while (m_Dummy.pNext != &m_Dummy) {
        Free(m_Dummy.pNext+1);
     }
-#endif
-    if (m_hLib)
-       FreeLibrary(m_hLib);
     DeleteCriticalSection(&m_cs);
+#endif
 }
 
 void* VMem::Malloc(size_t size)
 {
 #ifdef _USE_LINKED_LIST
-    PMEMORY_BLOCK_HEADER ptr = (PMEMORY_BLOCK_HEADER)m_pmalloc(size+sizeof(MEMORY_BLOCK_HEADER));
+    GetLock();
+    PMEMORY_BLOCK_HEADER ptr = (PMEMORY_BLOCK_HEADER)malloc(size+sizeof(MEMORY_BLOCK_HEADER));
+    if (!ptr) {
+       FreeLock();
+       return NULL;
+    }
     LinkBlock(ptr);
+    FreeLock();
     return (ptr+1);
 #else
-    return m_pmalloc(size);
+    return malloc(size);
 #endif
 }
 
@@ -174,14 +172,20 @@ void* VMem::Realloc(void* pMem, size_t size)
        return NULL;
     }
 
+    GetLock();
     PMEMORY_BLOCK_HEADER ptr = (PMEMORY_BLOCK_HEADER)(((char*)pMem)-sizeof(MEMORY_BLOCK_HEADER));
     UnlinkBlock(ptr);
-    ptr = (PMEMORY_BLOCK_HEADER)m_prealloc(ptr, size+sizeof(MEMORY_BLOCK_HEADER));
+    ptr = (PMEMORY_BLOCK_HEADER)realloc(ptr, size+sizeof(MEMORY_BLOCK_HEADER));
+    if (!ptr) {
+       FreeLock();
+       return NULL;
+    }
     LinkBlock(ptr);
+    FreeLock();
 
     return (ptr+1);
 #else
-    return m_prealloc(pMem, size);
+    return realloc(pMem, size);
 #endif
 }
 
@@ -190,22 +194,42 @@ void VMem::Free(void* pMem)
 #ifdef _USE_LINKED_LIST
     if (pMem) {
        PMEMORY_BLOCK_HEADER ptr = (PMEMORY_BLOCK_HEADER)(((char*)pMem)-sizeof(MEMORY_BLOCK_HEADER));
+        if (ptr->owner != this) {
+           if (ptr->owner) {
+#if 1
+               int *nowhere = NULL;
+               Perl_warn_nocontext("Free to wrong pool %p not %p",this,ptr->owner);
+               *nowhere = 0; /* this segfault is deliberate, 
+                                so you can see the stack trace */
+#else
+                ptr->owner->Free(pMem);        
+#endif
+           }
+           return;
+        }
+       GetLock();
        UnlinkBlock(ptr);
-       m_pfree(ptr);
+       ptr->owner = NULL;
+       free(ptr);
+       FreeLock();
     }
-#else
-    m_pfree(pMem);
+#else /*_USE_LINKED_LIST*/
+    free(pMem);
 #endif
 }
 
 void VMem::GetLock(void)
 {
+#ifdef _USE_LINKED_LIST
     EnterCriticalSection(&m_cs);
+#endif
 }
 
 void VMem::FreeLock(void)
 {
+#ifdef _USE_LINKED_LIST
     LeaveCriticalSection(&m_cs);
+#endif
 }
 
 int VMem::IsLocked(void)
@@ -377,14 +401,14 @@ class VMem
 public:
     VMem();
     ~VMem();
-    virtual void* Malloc(size_t size);
-    virtual void* Realloc(void* pMem, size_t size);
-    virtual void Free(void* pMem);
-    virtual void GetLock(void);
-    virtual void FreeLock(void);
-    virtual int IsLocked(void);
-    virtual long Release(void);
-    virtual long AddRef(void);
+    void* Malloc(size_t size);
+    void* Realloc(void* pMem, size_t size);
+    void Free(void* pMem);
+    void GetLock(void);
+    void FreeLock(void);
+    int IsLocked(void);
+    long Release(void);
+    long AddRef(void);
 
     inline BOOL CreateOk(void)
     {
@@ -1009,7 +1033,7 @@ int VMem::HeapAdd(void* p, size_t size
            if(ptr == m_heaps[index].base + (int)m_heaps[index].len) {
                /*
                 * The new block is contiguous with a previously allocated heap area.  Add its
-                * length to that of the previous heap.  Merge it with the the dummy end-of-heap
+                * length to that of the previous heap.  Merge it with the dummy end-of-heap
                 * area marker of the previous heap.
                 */
                m_heaps[index].len += size;