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  }