Skip to content

Commit abf8e35

Browse files
committed
runtime: use MADV_FREE_REUSABLE on darwin
Currently on darwin we use MADV_FREE, which unfortunately doesn't result in a change in the process's RSS until pages actually get kicked out, which the OS is free to do lazily (e.g. until it finds itself under memory pressure). To remedy this, we instead use MADV_FREE_REUSABLE which has similar semantics, except that it also sets a reusable bit on each page so the process's RSS gets reported more accurately. The one caveat is for every time we call MADV_FREE_REUSABLE on a region we must call MADV_FREE_REUSE to keep the kernel's accounting updated. Also, because this change requires adding new constants that only exist on darwin, it splits mem_bsd.go into mem_bsd.go and mem_darwin.go. Fixes #29844. Change-Id: Idb6421698511138a430807bcbbd1516cd57557c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/159117 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Michael Knyszek <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 0c7cdb4 commit abf8e35

7 files changed

+102
-24
lines changed

src/runtime/defs_darwin.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ const (
4141
MAP_PRIVATE = C.MAP_PRIVATE
4242
MAP_FIXED = C.MAP_FIXED
4343

44-
MADV_DONTNEED = C.MADV_DONTNEED
45-
MADV_FREE = C.MADV_FREE
44+
MADV_DONTNEED = C.MADV_DONTNEED
45+
MADV_FREE = C.MADV_FREE
46+
MADV_FREE_REUSABLE = C.MADV_FREE_REUSABLE
47+
MADV_FREE_REUSE = C.MADV_FREE_REUSE
4648

4749
SA_SIGINFO = C.SA_SIGINFO
4850
SA_RESTART = C.SA_RESTART

src/runtime/defs_darwin_386.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ const (
1919
_MAP_PRIVATE = 0x2
2020
_MAP_FIXED = 0x10
2121

22-
_MADV_DONTNEED = 0x4
23-
_MADV_FREE = 0x5
22+
_MADV_DONTNEED = 0x4
23+
_MADV_FREE = 0x5
24+
_MADV_FREE_REUSABLE = 0x7
25+
_MADV_FREE_REUSE = 0x8
2426

2527
_SA_SIGINFO = 0x40
2628
_SA_RESTART = 0x2

src/runtime/defs_darwin_amd64.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ const (
1919
_MAP_PRIVATE = 0x2
2020
_MAP_FIXED = 0x10
2121

22-
_MADV_DONTNEED = 0x4
23-
_MADV_FREE = 0x5
22+
_MADV_DONTNEED = 0x4
23+
_MADV_FREE = 0x5
24+
_MADV_FREE_REUSABLE = 0x7
25+
_MADV_FREE_REUSE = 0x8
2426

2527
_SA_SIGINFO = 0x40
2628
_SA_RESTART = 0x2

src/runtime/defs_darwin_arm.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ const (
2121
_MAP_PRIVATE = 0x2
2222
_MAP_FIXED = 0x10
2323

24-
_MADV_DONTNEED = 0x4
25-
_MADV_FREE = 0x5
24+
_MADV_DONTNEED = 0x4
25+
_MADV_FREE = 0x5
26+
_MADV_FREE_REUSABLE = 0x7
27+
_MADV_FREE_REUSE = 0x8
2628

2729
_SA_SIGINFO = 0x40
2830
_SA_RESTART = 0x2

src/runtime/defs_darwin_arm64.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ const (
1919
_MAP_PRIVATE = 0x2
2020
_MAP_FIXED = 0x10
2121

22-
_MADV_DONTNEED = 0x4
23-
_MADV_FREE = 0x5
22+
_MADV_DONTNEED = 0x4
23+
_MADV_FREE = 0x5
24+
_MADV_FREE_REUSABLE = 0x7
25+
_MADV_FREE_REUSE = 0x8
2426

2527
_SA_SIGINFO = 0x40
2628
_SA_RESTART = 0x2

src/runtime/mem_bsd.go

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
5+
// +build dragonfly freebsd nacl netbsd openbsd solaris
66

77
package runtime
88

@@ -42,19 +42,7 @@ func sysFault(v unsafe.Pointer, n uintptr) {
4242
}
4343

4444
func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {
45-
flags := int32(_MAP_ANON | _MAP_PRIVATE)
46-
if raceenabled && GOOS == "darwin" {
47-
// Currently the race detector expects memory to live within a certain
48-
// range, and on Darwin 10.10 mmap is prone to ignoring hints, more so
49-
// than later versions and other BSDs (#26475). So, even though it's
50-
// potentially dangerous to MAP_FIXED, we do it in the race detection
51-
// case because it'll help maintain the race detector's invariants.
52-
//
53-
// TODO(mknyszek): Drop this once support for Darwin 10.10 is dropped,
54-
// and reconsider this when #24133 is addressed.
55-
flags |= _MAP_FIXED
56-
}
57-
p, err := mmap(v, n, _PROT_NONE, flags, -1, 0)
45+
p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
5846
if err != 0 {
5947
return nil
6048
}

src/runtime/mem_darwin.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package runtime
6+
7+
import (
8+
"unsafe"
9+
)
10+
11+
// Don't split the stack as this function may be invoked without a valid G,
12+
// which prevents us from allocating more stack.
13+
//go:nosplit
14+
func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
15+
v, err := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
16+
if err != 0 {
17+
return nil
18+
}
19+
mSysStatInc(sysStat, n)
20+
return v
21+
}
22+
23+
func sysUnused(v unsafe.Pointer, n uintptr) {
24+
// MADV_FREE_REUSABLE is like MADV_FREE except it also propagates
25+
// accounting information about the process to task_info.
26+
madvise(v, n, _MADV_FREE_REUSABLE)
27+
}
28+
29+
func sysUsed(v unsafe.Pointer, n uintptr) {
30+
// MADV_FREE_REUSE is necessary to keep the kernel's accounting
31+
// accurate. If called on any memory region that hasn't been
32+
// MADV_FREE_REUSABLE'd, it's a no-op.
33+
madvise(v, n, _MADV_FREE_REUSE)
34+
}
35+
36+
// Don't split the stack as this function may be invoked without a valid G,
37+
// which prevents us from allocating more stack.
38+
//go:nosplit
39+
func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) {
40+
mSysStatDec(sysStat, n)
41+
munmap(v, n)
42+
}
43+
44+
func sysFault(v unsafe.Pointer, n uintptr) {
45+
mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE|_MAP_FIXED, -1, 0)
46+
}
47+
48+
func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {
49+
flags := int32(_MAP_ANON | _MAP_PRIVATE)
50+
if raceenabled {
51+
// Currently the race detector expects memory to live within a certain
52+
// range, and on Darwin 10.10 mmap is prone to ignoring hints, moreso
53+
// than later versions and other BSDs (#26475). So, even though it's
54+
// potentially dangerous to MAP_FIXED, we do it in the race detection
55+
// case because it'll help maintain the race detector's invariants.
56+
//
57+
// TODO(mknyszek): Drop this once support for Darwin 10.10 is dropped,
58+
// and reconsider this when #24133 is addressed.
59+
flags |= _MAP_FIXED
60+
}
61+
p, err := mmap(v, n, _PROT_NONE, flags, -1, 0)
62+
if err != 0 {
63+
return nil
64+
}
65+
return p
66+
}
67+
68+
const _ENOMEM = 12
69+
70+
func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
71+
mSysStatInc(sysStat, n)
72+
73+
p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
74+
if err == _ENOMEM {
75+
throw("runtime: out of memory")
76+
}
77+
if p != v || err != 0 {
78+
throw("runtime: cannot map pages in arena address space")
79+
}
80+
}

0 commit comments

Comments
 (0)