diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h index 20cf6fb96b0..36166543ee3 100644 --- a/src/pkg/runtime/malloc.h +++ b/src/pkg/runtime/malloc.h @@ -157,8 +157,9 @@ struct MLink // // SysUnused notifies the operating system that the contents // of the memory region are no longer needed and can be reused -// for other purposes. The program reserves the right to start -// accessing those pages in the future. +// for other purposes. +// SysUsed notifies the operating system that the contents +// of the memory region are needed again. // // SysFree returns it unconditionally; this is only used if // an out-of-memory error has been detected midway through @@ -174,6 +175,7 @@ struct MLink void* runtime·SysAlloc(uintptr nbytes); void runtime·SysFree(void *v, uintptr nbytes); void runtime·SysUnused(void *v, uintptr nbytes); +void runtime·SysUsed(void *v, uintptr nbytes); void runtime·SysMap(void *v, uintptr nbytes); void* runtime·SysReserve(void *v, uintptr nbytes); diff --git a/src/pkg/runtime/mem_darwin.c b/src/pkg/runtime/mem_darwin.c index 7aa607f8ee7..ef5674e3408 100644 --- a/src/pkg/runtime/mem_darwin.c +++ b/src/pkg/runtime/mem_darwin.c @@ -27,6 +27,13 @@ runtime·SysUnused(void *v, uintptr n) runtime·madvise(v, n, MADV_FREE); } +void +runtime·SysUsed(void *v, uintptr n) +{ + USED(v); + USED(n); +} + void runtime·SysFree(void *v, uintptr n) { diff --git a/src/pkg/runtime/mem_freebsd.c b/src/pkg/runtime/mem_freebsd.c index 805e74cffba..e47ea7a436d 100644 --- a/src/pkg/runtime/mem_freebsd.c +++ b/src/pkg/runtime/mem_freebsd.c @@ -31,6 +31,13 @@ runtime·SysUnused(void *v, uintptr n) runtime·madvise(v, n, MADV_FREE); } +void +runtime·SysUsed(void *v, uintptr n) +{ + USED(v); + USED(n); +} + void runtime·SysFree(void *v, uintptr n) { diff --git a/src/pkg/runtime/mem_linux.c b/src/pkg/runtime/mem_linux.c index bacd568d9e0..d96eb69e899 100644 --- a/src/pkg/runtime/mem_linux.c +++ b/src/pkg/runtime/mem_linux.c @@ -77,6 +77,13 @@ runtime·SysUnused(void *v, uintptr n) runtime·madvise(v, n, MADV_DONTNEED); } +void +runtime·SysUsed(void *v, uintptr n) +{ + USED(v); + USED(n); +} + void runtime·SysFree(void *v, uintptr n) { diff --git a/src/pkg/runtime/mem_netbsd.c b/src/pkg/runtime/mem_netbsd.c index e5bdac0ef65..8a7ef17e84f 100644 --- a/src/pkg/runtime/mem_netbsd.c +++ b/src/pkg/runtime/mem_netbsd.c @@ -31,6 +31,13 @@ runtime·SysUnused(void *v, uintptr n) runtime·madvise(v, n, MADV_FREE); } +void +runtime·SysUsed(void *v, uintptr n) +{ + USED(v); + USED(n); +} + void runtime·SysFree(void *v, uintptr n) { diff --git a/src/pkg/runtime/mem_openbsd.c b/src/pkg/runtime/mem_openbsd.c index e5bdac0ef65..8a7ef17e84f 100644 --- a/src/pkg/runtime/mem_openbsd.c +++ b/src/pkg/runtime/mem_openbsd.c @@ -31,6 +31,13 @@ runtime·SysUnused(void *v, uintptr n) runtime·madvise(v, n, MADV_FREE); } +void +runtime·SysUsed(void *v, uintptr n) +{ + USED(v); + USED(n); +} + void runtime·SysFree(void *v, uintptr n) { diff --git a/src/pkg/runtime/mem_plan9.c b/src/pkg/runtime/mem_plan9.c index 26ca367f11e..3aa16eb3a63 100644 --- a/src/pkg/runtime/mem_plan9.c +++ b/src/pkg/runtime/mem_plan9.c @@ -55,6 +55,12 @@ runtime·SysUnused(void *v, uintptr nbytes) USED(v, nbytes); } +void +runtime·SysUsed(void *v, uintptr n) +{ + USED(v, nbytes); +} + void runtime·SysMap(void *v, uintptr nbytes) { diff --git a/src/pkg/runtime/mem_windows.c b/src/pkg/runtime/mem_windows.c index 1a778b77527..0a1ea38d567 100644 --- a/src/pkg/runtime/mem_windows.c +++ b/src/pkg/runtime/mem_windows.c @@ -11,6 +11,7 @@ enum { MEM_COMMIT = 0x1000, MEM_RESERVE = 0x2000, + MEM_DECOMMIT = 0x4000, MEM_RELEASE = 0x8000, PAGE_READWRITE = 0x0004, @@ -31,8 +32,21 @@ runtime·SysAlloc(uintptr n) void runtime·SysUnused(void *v, uintptr n) { - USED(v); - USED(n); + uintptr r; + + r = runtime·stdcall(runtime·VirtualFree, 3, v, n, (uintptr)MEM_DECOMMIT); + if(r == 0) + runtime·throw("runtime: failed to decommit pages"); +} + +void +runtime·SysUsed(void *v, uintptr n) +{ + uintptr r; + + r = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE); + if(r != v) + runtime·throw("runtime: failed to commit pages"); } void diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c index c03b13bdfd8..d7713965cfc 100644 --- a/src/pkg/runtime/mheap.c +++ b/src/pkg/runtime/mheap.c @@ -156,6 +156,7 @@ HaveSpan: // is just a unique constant not seen elsewhere in the // runtime, as a clue in case it turns up unexpectedly in // memory or in a stack trace. + runtime·SysUsed((void*)(s->start<npages<start<npreleased = 0; @@ -350,8 +351,10 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) if(sizeof(void*) == 8) p -= (uintptr)h->arena_start >> PageShift; if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse) { - tp = (uintptr*)(t->start<npreleased == 0) { // cant't touch this otherwise + tp = (uintptr*)(t->start<start = t->start; s->npages += t->npages; s->npreleased = t->npreleased; // absorb released pages @@ -364,8 +367,10 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) mstats.mspan_sys = h->spanalloc.sys; } if((p+s->npages)*sizeof(h->spans[0]) < h->spans_mapped && (t = h->spans[p+s->npages]) != nil && t->state != MSpanInUse) { - tp = (uintptr*)(t->start<npreleased == 0) { // cant't touch this otherwise + tp = (uintptr*)(t->start<npages += t->npages; s->npreleased += t->npreleased; h->spans[p + s->npages - 1] = s; @@ -401,7 +406,7 @@ scavengelist(MSpan *list, uint64 now, uint64 limit) sumreleased = 0; for(s=list->next; s != list; s=s->next) { - if((now - s->unusedsince) > limit) { + if((now - s->unusedsince) > limit && s->npreleased != s->npages) { released = (s->npages - s->npreleased) << PageShift; mstats.heap_released += released; sumreleased += released;