diff options
author | Peter Stephenson <p.w.stephenson@ntlworld.com> | 2014-06-24 18:50:50 +0100 |
---|---|---|
committer | Peter Stephenson <p.w.stephenson@ntlworld.com> | 2014-06-24 18:50:50 +0100 |
commit | 920db696cb53122bec0c8a83087852e7e8c018f0 (patch) | |
tree | 36e6b31f8eea75fe72dd9132342bdfcf94338ab3 /Src/mem.c | |
parent | 0853bcfdd6a90fb4e6a9b7428d9b2a4975af717e (diff) | |
download | zsh-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.c | 99 |
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; } |