var adviseUnused = uint32(_MADV_FREE)
+const madviseUnsupported = 0
+
func sysUnusedOS(v unsafe.Pointer, n uintptr) {
if uintptr(v)&(physPageSize-1) != 0 || n&(physPageSize-1) != 0 {
// madvise will round this to any physical page
throw("unaligned sysUnused")
}
- var advise uint32
- if debug.madvdontneed != 0 {
+ advise := atomic.Load(&adviseUnused)
+ if debug.madvdontneed != 0 && advise != madviseUnsupported {
advise = _MADV_DONTNEED
- } else {
- advise = atomic.Load(&adviseUnused)
}
- if errno := madvise(v, n, int32(advise)); advise == _MADV_FREE && errno != 0 {
- // MADV_FREE was added in Linux 4.5. Fall back to MADV_DONTNEED if it is
- // not supported.
+ switch advise {
+ case _MADV_FREE:
+ if madvise(v, n, _MADV_FREE) == 0 {
+ break
+ }
atomic.Store(&adviseUnused, _MADV_DONTNEED)
- madvise(v, n, _MADV_DONTNEED)
+ fallthrough
+ case _MADV_DONTNEED:
+ // MADV_FREE was added in Linux 4.5. Fall back on MADV_DONTNEED if it's
+ // not supported.
+ if madvise(v, n, _MADV_DONTNEED) == 0 {
+ break
+ }
+ atomic.Store(&adviseUnused, madviseUnsupported)
+ fallthrough
+ case madviseUnsupported:
+ // Since Linux 3.18, support for madvise is optional.
+ // Fall back on mmap if it's not supported.
+ // _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE will unmap all the
+ // pages in the old mapping, and remap the memory region.
+ mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
}
if debug.harddecommit > 0 {