summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/mcentral.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/mcentral.c')
-rw-r--r--src/pkg/runtime/mcentral.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/pkg/runtime/mcentral.c b/src/pkg/runtime/mcentral.c
index 9881812e3..7e33e01af 100644
--- a/src/pkg/runtime/mcentral.c
+++ b/src/pkg/runtime/mcentral.c
@@ -115,6 +115,7 @@ MCentral_Free(MCentral *c, void *v)
MSpan *s;
PageID page;
MLink *p, *next;
+ int32 size;
// Find span for v.
page = (uintptr)v >> PageShift;
@@ -136,15 +137,20 @@ MCentral_Free(MCentral *c, void *v)
// If s is completely freed, return it to the heap.
if(--s->ref == 0) {
+ size = class_to_size[c->sizeclass];
MSpanList_Remove(s);
- // Freed blocks are zeroed except for the link pointer.
- // Zero the link pointers so that the page is all zero.
+ // The second word of each freed block indicates
+ // whether it needs to be zeroed. The first word
+ // is the link pointer and must always be cleared.
for(p=s->freelist; p; p=next) {
next = p->next;
- p->next = nil;
+ if(size > sizeof(uintptr) && ((uintptr*)p)[1] != 0)
+ runtime_memclr((byte*)p, size);
+ else
+ p->next = nil;
}
s->freelist = nil;
- c->nfree -= (s->npages << PageShift) / class_to_size[c->sizeclass];
+ c->nfree -= (s->npages << PageShift) / size;
unlock(c);
MHeap_Free(&mheap, s);
lock(c);