summaryrefslogtreecommitdiffstats
path: root/libgo/runtime
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-25 04:28:48 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-25 04:28:48 +0000
commit0102c4b77f669b203fc196114a02226c5f93f96e (patch)
tree2d74bb623091af0ae7f23a44fd44fff2edcb0c2d /libgo/runtime
parentd124bef37aa1891f556e93a77411f0136c526439 (diff)
downloadppe42-gcc-0102c4b77f669b203fc196114a02226c5f93f96e.tar.gz
ppe42-gcc-0102c4b77f669b203fc196114a02226c5f93f96e.zip
PR go/60931
runtime: Fix garbage collector issue with non 4kB system page size The go garbage collector tracks memory in terms of 4kB pages. Most of the code checks getpagesize() at runtime and does the right thing. On a 64kB ppc64 box I see SEGVs in long running processes which has been diagnosed as a bug in scavengelist. scavengelist does a madvise(MADV_DONTNEED) without rounding the arguments to the system page size. A strace of one of the failures shows the problem: madvise(0xc211030000, 4096, MADV_DONTNEED) = 0 The kernel rounds the length up to 64kB and we mark 60kB of valid data as no longer needed. Round start up to a system page and end down before calling madvise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_9-branch@209776 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/mheap.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index fee493c1367..1b8ab791606 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -387,7 +387,7 @@ forcegchelper(void *vnote)
static uintptr
scavengelist(MSpan *list, uint64 now, uint64 limit)
{
- uintptr released, sumreleased;
+ uintptr released, sumreleased, start, end, pagesize;
MSpan *s;
if(runtime_MSpanList_IsEmpty(list))
@@ -400,7 +400,17 @@ scavengelist(MSpan *list, uint64 now, uint64 limit)
mstats.heap_released += released;
sumreleased += released;
s->npreleased = s->npages;
- runtime_SysUnused((void*)(s->start << PageShift), s->npages << PageShift);
+
+ start = s->start << PageShift;
+ end = start + (s->npages << PageShift);
+
+ // Round start up and end down to ensure we
+ // are acting on entire pages.
+ pagesize = getpagesize();
+ start = ROUND(start, pagesize);
+ end &= ~(pagesize - 1);
+ if(end > start)
+ runtime_SysUnused((void*)start, end - start);
}
}
return sumreleased;
OpenPOWER on IntegriCloud