github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/mem_linux.go (about) 1 // Copyright 2010 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 "runtime/internal/atomic" 9 "unsafe" 10 ) 11 12 const ( 13 _EACCES = 13 14 _EINVAL = 22 15 ) 16 17 // Don't split the stack as this method may be invoked without a valid G, which 18 // prevents us from allocating more stack. 19 // 20 //go:nosplit 21 func sysAllocOS(n uintptr) unsafe.Pointer { 22 p, err := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0) 23 if err != 0 { 24 if err == _EACCES { 25 print("runtime: mmap: access denied\n") 26 exit(2) 27 } 28 if err == _EAGAIN { 29 print("runtime: mmap: too much locked memory (check 'ulimit -l').\n") 30 exit(2) 31 } 32 return nil 33 } 34 return p 35 } 36 37 var adviseUnused = uint32(_MADV_FREE) 38 39 func sysUnusedOS(v unsafe.Pointer, n uintptr) { 40 if uintptr(v)&(physPageSize-1) != 0 || n&(physPageSize-1) != 0 { 41 // madvise will round this to any physical page 42 // *covered* by this range, so an unaligned madvise 43 // will release more memory than intended. 44 throw("unaligned sysUnused") 45 } 46 47 var advise uint32 48 if debug.madvdontneed != 0 { 49 advise = _MADV_DONTNEED 50 } else { 51 advise = atomic.Load(&adviseUnused) 52 } 53 if errno := madvise(v, n, int32(advise)); advise == _MADV_FREE && errno != 0 { 54 // MADV_FREE was added in Linux 4.5. Fall back to MADV_DONTNEED if it is 55 // not supported. 56 atomic.Store(&adviseUnused, _MADV_DONTNEED) 57 madvise(v, n, _MADV_DONTNEED) 58 } 59 60 if debug.harddecommit > 0 { 61 p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) 62 if p != v || err != 0 { 63 throw("runtime: cannot disable permissions in address space") 64 } 65 } 66 } 67 68 func sysUsedOS(v unsafe.Pointer, n uintptr) { 69 if debug.harddecommit > 0 { 70 p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) 71 if err == _ENOMEM { 72 throw("runtime: out of memory") 73 } 74 if p != v || err != 0 { 75 throw("runtime: cannot remap pages in address space") 76 } 77 return 78 } 79 } 80 81 func sysHugePageOS(v unsafe.Pointer, n uintptr) { 82 if physHugePageSize != 0 { 83 // Round v up to a huge page boundary. 84 beg := alignUp(uintptr(v), physHugePageSize) 85 // Round v+n down to a huge page boundary. 86 end := alignDown(uintptr(v)+n, physHugePageSize) 87 88 if beg < end { 89 madvise(unsafe.Pointer(beg), end-beg, _MADV_HUGEPAGE) 90 } 91 } 92 } 93 94 func sysNoHugePageOS(v unsafe.Pointer, n uintptr) { 95 if uintptr(v)&(physPageSize-1) != 0 { 96 // The Linux implementation requires that the address 97 // addr be page-aligned, and allows length to be zero. 98 throw("unaligned sysNoHugePageOS") 99 } 100 madvise(v, n, _MADV_NOHUGEPAGE) 101 } 102 103 // Don't split the stack as this function may be invoked without a valid G, 104 // which prevents us from allocating more stack. 105 // 106 //go:nosplit 107 func sysFreeOS(v unsafe.Pointer, n uintptr) { 108 munmap(v, n) 109 } 110 111 func sysFaultOS(v unsafe.Pointer, n uintptr) { 112 mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE|_MAP_FIXED, -1, 0) 113 } 114 115 func sysReserveOS(v unsafe.Pointer, n uintptr) unsafe.Pointer { 116 p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0) 117 if err != 0 { 118 return nil 119 } 120 return p 121 } 122 123 func sysMapOS(v unsafe.Pointer, n uintptr) { 124 p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) 125 if err == _ENOMEM { 126 throw("runtime: out of memory") 127 } 128 if p != v || err != 0 { 129 print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n") 130 throw("runtime: cannot map pages in arena address space") 131 } 132 }