=bmesh= merge from trunk at r36529
[blender.git] / intern / guardedalloc / intern / mallocn.c
index 55340d6011d9ea73954140761c6cc42c4b2c2361..0ce6a92359d6ad89aee59b12da7f5bcb5dc5504e 100644 (file)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
@@ -80,35 +80,6 @@ static void memcount_raise(const char *name)
 /* --------------------------------------------------------------------- */
 /* Data definition                                                       */
 /* --------------------------------------------------------------------- */
-/* all memory chunks are put in linked lists */
-typedef struct localLink
-{
-       struct localLink *next,*prev;
-} localLink;
-
-typedef struct localListBase 
-{
-       void *first, *last;
-} localListBase;
-
-       /* note: keep this struct aligned (e.g., irix/gcc) - Hos */
-typedef struct MemHead {
-       int tag1;
-       size_t len;
-       struct MemHead *next,*prev;
-       const char * name;
-       const char * nextname;
-       int tag2;
-       int mmap;       /* if true, memory was mmapped */
-#ifdef DEBUG_MEMCOUNTER
-       int _count;
-#endif
-} MemHead;
-
-typedef struct MemTail {
-       int tag3, pad;
-} MemTail;
-
 
 /* --------------------------------------------------------------------- */
 /* local functions                                                       */
@@ -133,6 +104,7 @@ static const char *check_memlist(MemHead *memh);
 #define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
 #define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
 #define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
+#define MEMTAG4 MAKE_ID('C', 'R', 'A', 'P')
 #define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
 
 #define MEMNEXT(x) ((MemHead *)(((char *) x) - ((char *) & (((MemHead *)0)->next))))
@@ -237,7 +209,7 @@ size_t MEM_allocN_len(void *vmemh)
                return 0;
 }
 
-void *MEM_dupallocN(void *vmemh)
+void *MEM_reallocN(void *vmemh, size_t len)
 {
        void *newp= NULL;
        
@@ -246,35 +218,35 @@ void *MEM_dupallocN(void *vmemh)
                memh--;
                
                if(memh->mmap)
-                       newp= MEM_mapallocN(memh->len, "dupli_mapalloc");
+                       newp= MEM_mapallocN(len, "dupli_mapalloc");
                else
-                       newp= MEM_mallocN(memh->len, "dupli_alloc");
+                       newp= MEM_mallocN(len, "dupli_alloc");
 
                if (newp == NULL) return NULL;
 
-               memcpy(newp, vmemh, memh->len);
+               memcpy(newp, vmemh, len<=memh->len ? len : memh->len);
        }
 
        return newp;
 }
 
-void *MEM_reallocN(void *vmemh, size_t len)
+
+void *MEM_dupallocN(void *vmemh)
 {
        void *newp= NULL;
-       
+
        if (vmemh) {
                MemHead *memh= vmemh;
                memh--;
 
-               newp= MEM_mallocN(len, memh->name);
-               if(newp) {
-                       if(len < memh->len)
-                               memcpy(newp, vmemh, len);
-                       else
-                               memcpy(newp, vmemh, memh->len);
-               }
+               if(memh->mmap)
+                       newp= MEM_mapallocN(memh->len, "dupli_mapalloc");
+               else
+                       newp= MEM_mallocN(memh->len, "dupli_alloc");
+
+               if (newp == NULL) return NULL;
 
-               MEM_freeN(vmemh);
+               memcpy(newp, vmemh, memh->len);
        }
 
        return newp;
@@ -293,6 +265,7 @@ static void make_memhead_header(MemHead *memh, size_t len, const char *str)
        
        memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
        memt->tag3 = MEMTAG3;
+       memt->tag4 = MEMTAG4;
        
        addtail(membase,&memh->next);
        if (memh->next) memh->nextname = MEMNEXT(memh->next)->name;
@@ -318,12 +291,6 @@ void *MEM_mallocN(size_t len, const char *str)
                mem_unlock_thread();
                if(malloc_debug_memset && len)
                        memset(memh+1, 255, len);
-
-#ifdef DEBUG_MEMCOUNTER
-               if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL)
-                       memcount_raise("MEM_mallocN");
-               memh->_count= _mallocn_count++;
-#endif
                return (++memh);
        }
        mem_unlock_thread();
@@ -344,11 +311,6 @@ void *MEM_callocN(size_t len, const char *str)
        if(memh) {
                make_memhead_header(memh, len, str);
                mem_unlock_thread();
-#ifdef DEBUG_MEMCOUNTER
-               if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL)
-                       memcount_raise("MEM_callocN");
-               memh->_count= _mallocn_count++;
-#endif
                return (++memh);
        }
        mem_unlock_thread();
@@ -387,11 +349,6 @@ void *MEM_mapallocN(size_t len, const char *str)
                mmap_in_use += len;
                peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
                mem_unlock_thread();
-#ifdef DEBUG_MEMCOUNTER
-               if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL)
-                       memcount_raise("MEM_mapallocN");
-               memh->_count= _mallocn_count++;
-#endif
                return (++memh);
        }
        else {
@@ -570,10 +527,8 @@ short MEM_testN(void *vmemh) {
        if (membl) membl = MEMNEXT(membl);
 
        while(membl) {
-               if (vmemh == membl+1) {
-                       mem_unlock_thread();
+               if (vmemh == membl+1)
                        return 1;
-               }
 
                if(membl->next)
                        membl= MEMNEXT(membl->next);
@@ -593,46 +548,67 @@ void MEM_printmemlist_pydict( void ) {
        MEM_printmemlist_internal(1);
 }
 
-short MEM_freeN(void *vmemh)           /* anders compileertie niet meer */
+#ifdef MEM_freeN
+#undef MEM_freeN
+#endif
+
+short MEM_freeN(void *vmemh)
+{
+       return _MEM_freeN(vmemh, "(called through C stub function)", -1);
+}
+
+short WMEM_freeN(void *vmemh)
+{
+       return _MEM_freeN(vmemh, "(called through C stub function)", -1);
+}
+
+/*special macro-wrapped MEM_freeN that keeps track of where MEM_freeN is called.*/
+short _MEM_freeN(void *vmemh, const char *file, int line)              /* anders compileertie niet meer */
 {
        short error = 0;
        MemTail *memt;
        MemHead *memh= vmemh;
        const char *name;
-
+       char str1[90];
+       
        if (memh == NULL){
-               MemorY_ErroR("free","attempt to free NULL pointer");
+               sprintf(str1, "Error in %s on line %d: attempt to free NULL pointer", file, line);
+               MemorY_ErroR("free", str1);
                /* print_error(err_stream, "%d\n", (memh+4000)->tag1); */
                return(-1);
        }
 
        if(sizeof(intptr_t)==8) {
                if (((intptr_t) memh) & 0x7) {
-                       MemorY_ErroR("free","attempt to free illegal pointer");
+                       sprintf(str1, "Error in %s on line %d: attempt to free illegal pointer", file, line);
+                       MemorY_ErroR("free", str1);
                        return(-1);
                }
        }
        else {
                if (((intptr_t) memh) & 0x3) {
-                       MemorY_ErroR("free","attempt to free illegal pointer");
+                       sprintf(str1, "Error in %s on line %d: attempt to free illegal pointer", file, line);
+                       MemorY_ErroR("free", str1);
                        return(-1);
                }
        }
        
        memh--;
        if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
-               MemorY_ErroR(memh->name,"double free");
+               sprintf(str1, "Error in %s on line %d: double free", file, line);
+               MemorY_ErroR(memh->name, str1);
                return(-1);
        }
 
        mem_lock_thread();
        if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) {
                memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len);
-               if (memt->tag3 == MEMTAG3){
+               if (memt->tag3 == MEMTAG3 && memt->tag4 == MEMTAG4){
                        
                        memh->tag1 = MEMFREE;
                        memh->tag2 = MEMFREE;
                        memt->tag3 = MEMFREE;
+                       memt->tag4 = MEMFREE;
                        /* after tags !!! */
                        rem_memblock(memh);
 
@@ -644,15 +620,20 @@ short MEM_freeN(void *vmemh)              /* anders compileertie niet meer */
                MemorY_ErroR(memh->name,"end corrupt");
                name = check_memlist(memh);
                if (name != NULL){
-                       if (name != memh->name) MemorY_ErroR(name,"is also corrupt");
+                       sprintf(str1, "Error in %s on line %d: %s is also corrupt", file, line, name);
+                       if (name != memh->name) MemorY_ErroR(name, str1);
                }
        } else{
                error = -1;
                name = check_memlist(memh);
-               if (name == NULL)
-                       MemorY_ErroR("free","pointer not in memlist");
-               else
-                       MemorY_ErroR(name,"error in header");
+
+               if (name == 0) {
+                       sprintf(str1, "Error in %s on line %d: pointer not in memlist", file, line);
+                       MemorY_ErroR("free", str1);
+               } else {
+                       sprintf(str1, "Error in %s on line %d: error in header", file, line);
+                       MemorY_ErroR(name, str1);
+               }
        }
 
        totblock--;