summary refs log tree commit diff
path: root/Src/mem.c
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2014-06-24 18:50:50 +0100
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2014-06-24 18:50:50 +0100
commit920db696cb53122bec0c8a83087852e7e8c018f0 (patch)
tree36e6b31f8eea75fe72dd9132342bdfcf94338ab3 /Src/mem.c
parent0853bcfdd6a90fb4e6a9b7428d9b2a4975af717e (diff)
downloadzsh-920db696cb53122bec0c8a83087852e7e8c018f0.tar.gz
zsh-920db696cb53122bec0c8a83087852e7e8c018f0.tar.xz
zsh-920db696cb53122bec0c8a83087852e7e8c018f0.zip
32789: --enable-zsh-valgrind allows analysis of heap allocation
Diffstat (limited to 'Src/mem.c')
-rw-r--r--Src/mem.c99
1 files changed, 95 insertions, 4 deletions
diff --git a/Src/mem.c b/Src/mem.c
index f19817723..a8f0c37ce 100644
--- a/Src/mem.c
+++ b/Src/mem.c
@@ -226,6 +226,9 @@ old_heaps(Heap old)
 #else
 	zfree(h, HEAPSIZE);
 #endif
+#ifdef ZSH_VALGRIND
+	VALGRIND_DESTROY_MEMPOOL((char *)h);
+#endif
     }
     heaps = old;
 #ifdef ZSH_HEAP_DEBUG
@@ -347,6 +350,10 @@ freeheap(void)
 	hn = h->next;
 	if (h->sp) {
 #ifdef ZSH_MEM_DEBUG
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MAKE_MEM_UNDEFINED((char *)arena(h) + h->sp->used,
+					h->used - h->sp->used);
+#endif
 	    memset(arena(h) + h->sp->used, 0xff, h->used - h->sp->used);
 #endif
 	    h->used = h->sp->used;
@@ -369,12 +376,18 @@ freeheap(void)
 		h->heap_id = new_id;
 	    }
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used);
+#endif
 	} else {
 #ifdef USE_MMAP
 	    munmap((void *) h, h->size);
 #else
 	    zfree(h, HEAPSIZE);
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_DESTROY_MEMPOOL((char *)h);
+#endif
 	}
     }
     if (hl)
@@ -406,6 +419,10 @@ popheap(void)
 	if ((hs = h->sp)) {
 	    h->sp = hs->next;
 #ifdef ZSH_MEM_DEBUG
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MAKE_MEM_UNDEFINED((char *)arena(h) + hs->used,
+					h->used - hs->used);
+#endif
 	    memset(arena(h) + hs->used, 0xff, h->used - hs->used);
 #endif
 	    h->used = hs->used;
@@ -417,6 +434,9 @@ popheap(void)
 	    }
 	    h->heap_id = hs->heap_id;
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used);
+#endif
 	    if (!fheap && h->used < ARENA_SIZEOF(h))
 		fheap = h;
 	    zfree(hs, sizeof(*hs));
@@ -428,6 +448,9 @@ popheap(void)
 #else
 	    zfree(h, HEAPSIZE);
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_DESTROY_MEMPOOL((char *)h);
+#endif
 	}
     }
     if (hl)
@@ -499,6 +522,12 @@ zhalloc(size_t size)
 {
     Heap h;
     size_t n;
+#ifdef ZSH_VALGRIND
+    size_t req_size = size;
+
+    if (size == 0)
+	return NULL;
+#endif
 
     size = (size + H_ISIZE - 1) & ~(H_ISIZE - 1);
 
@@ -526,6 +555,9 @@ zhalloc(size_t size)
 			HEAPID_FMT ".\n", h->heap_id);
 	    }
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)ret, req_size);
+#endif
 	    return ret;
 	}
     }
@@ -564,6 +596,12 @@ zhalloc(size_t size)
 		    h->heap_id);
 	}
 #endif
+#ifdef ZSH_VALGRIND
+	VALGRIND_CREATE_MEMPOOL((char *)h, 0, 0);
+	VALGRIND_MAKE_MEM_NOACCESS((char *)arena(h),
+				   n - ((char *)arena(h)-(char *)h));
+	VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)arena(h), req_size);
+#endif
 
 	if (hp)
 	    hp->next = h;
@@ -589,13 +627,21 @@ hrealloc(char *p, size_t old, size_t new)
 {
     Heap h, ph;
 
+#ifdef ZSH_VALGRIND
+    size_t new_req = new;
+#endif
+
     old = (old + H_ISIZE - 1) & ~(H_ISIZE - 1);
     new = (new + H_ISIZE - 1) & ~(H_ISIZE - 1);
 
     if (old == new)
 	return p;
     if (!old && !p)
+#ifdef ZSH_VALGRIND
+	return zhalloc(new_req);
+#else
 	return zhalloc(new);
+#endif
 
     /* find the heap with p */
 
@@ -618,14 +664,33 @@ hrealloc(char *p, size_t old, size_t new)
      */
     if (p + old < arena(h) + h->used) {
 	if (new > old) {
+#ifdef ZSH_VALGRIND
+	    char *ptr = (char *) zhalloc(new_req);
+#else
 	    char *ptr = (char *) zhalloc(new);
+#endif
 	    memcpy(ptr, p, old);
 #ifdef ZSH_MEM_DEBUG
 	    memset(p, 0xff, old);
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
+	    /*
+	     * zhalloc() marked h,ptr,new as an allocation so we don't
+	     * need to do that here.
+	     */
+#endif
 	    unqueue_signals();
 	    return ptr;
 	} else {
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
+	    if (p) {
+		VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p,
+				       new_req);
+		VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
+	    }
+#endif
 	    unqueue_signals();
 	    return new ? p : NULL;
 	}
@@ -660,10 +725,14 @@ hrealloc(char *p, size_t old, size_t new)
 #else
 	    zfree(h, HEAPSIZE);
 #endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_DESTROY_MEMPOOL((char *)h);
+#endif
 	    unqueue_signals();
 	    return NULL;
 	}
 	if (new > ARENA_SIZEOF(h)) {
+	    Heap hnew;
 	    /*
 	     * Not enough memory in this heap.  Allocate a new
 	     * one of sufficient size.
@@ -685,17 +754,23 @@ hrealloc(char *p, size_t old, size_t new)
 		 * a mmap'd segment be extended, so simply allocate
 		 * a new one and copy.
 		 */
-		Heap hnew;
-
 		hnew = mmap_heap_alloc(&n);
 		/* Copy the entire heap, header (with next pointer) included */
 		memcpy(hnew, h, h->size);
 		munmap((void *)h, h->size);
-		h = hnew;
 	    }
 #else
-	    h = (Heap) realloc(h, n);
+	    hnew = (Heap) realloc(h, n);
+#endif
+#ifdef ZSH_VALGRIND
+	    VALGRIND_MEMPOOL_FREE((char *)h, p);
+	    VALGRIND_DESTROY_MEMPOOL((char *)h);
+	    VALGRIND_CREATE_MEMPOOL((char *)hnew, 0, 0);
+	    VALGRIND_MEMPOOL_ALLOC((char *)hnew, (char *)arena(hnew),
+				   new_req);
+	    VALGRIND_MAKE_MEM_DEFINED((char *)hnew, (char *)arena(hnew));
 #endif
+	    h = hnew;
 
 	    h->size = n;
 	    if (ph)
@@ -703,6 +778,13 @@ hrealloc(char *p, size_t old, size_t new)
 	    else
 		heaps = h;
 	}
+#ifdef ZSH_VALGRIND
+	else {
+	    VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
+	    VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p, new_req);
+	    VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
+	}
+#endif
 	h->used = new;
 #ifdef ZSH_HEAP_DEBUG
 	h->heap_id = heap_id;
@@ -716,6 +798,11 @@ hrealloc(char *p, size_t old, size_t new)
     if (h->used + (new - old) <= ARENA_SIZEOF(h)) {
 	h->used += new - old;
 	unqueue_signals();
+#ifdef ZSH_VALGRIND
+	VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
+	VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p, new_req);
+	VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
+#endif
 	return p;
     } else {
 	char *t = zhalloc(new);
@@ -724,6 +811,10 @@ hrealloc(char *p, size_t old, size_t new)
 #ifdef ZSH_MEM_DEBUG
 	memset(p, 0xff, old);
 #endif
+#ifdef ZSH_VALGRIND
+	VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
+	/* t already marked as allocated by zhalloc() */
+#endif
 	unqueue_signals();
 	return t;
     }