github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/mem_linux.c (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 #include "runtime.h" 6 #include "arch_GOARCH.h" 7 #include "defs_GOOS_GOARCH.h" 8 #include "os_GOOS.h" 9 #include "malloc.h" 10 11 enum 12 { 13 _PAGE_SIZE = 4096, 14 }; 15 16 static int32 17 addrspace_free(void *v, uintptr n) 18 { 19 int32 errval; 20 uintptr chunk; 21 uintptr off; 22 static byte vec[4096]; 23 24 for(off = 0; off < n; off += chunk) { 25 chunk = _PAGE_SIZE * sizeof vec; 26 if(chunk > (n - off)) 27 chunk = n - off; 28 errval = runtime·mincore((int8*)v + off, chunk, vec); 29 // errval is 0 if success, or -(error_code) if error. 30 if (errval == 0 || errval != -ENOMEM) 31 return 0; 32 } 33 return 1; 34 } 35 36 static void * 37 mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset) 38 { 39 void *p; 40 41 p = runtime·mmap(v, n, prot, flags, fd, offset); 42 if(p != v && addrspace_free(v, n)) { 43 // On some systems, mmap ignores v without 44 // MAP_FIXED, so retry if the address space is free. 45 if(p > (void*)4096) 46 runtime·munmap(p, n); 47 p = runtime·mmap(v, n, prot, flags|MAP_FIXED, fd, offset); 48 } 49 return p; 50 } 51 52 void* 53 runtime·SysAlloc(uintptr n) 54 { 55 void *p; 56 57 mstats.sys += n; 58 p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); 59 if(p < (void*)4096) { 60 if(p == (void*)EACCES) { 61 runtime·printf("runtime: mmap: access denied\n"); 62 runtime·printf("if you're running SELinux, enable execmem for this process.\n"); 63 runtime·exit(2); 64 } 65 if(p == (void*)EAGAIN) { 66 runtime·printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n"); 67 runtime·exit(2); 68 } 69 return nil; 70 } 71 return p; 72 } 73 74 void 75 runtime·SysUnused(void *v, uintptr n) 76 { 77 runtime·madvise(v, n, MADV_DONTNEED); 78 } 79 80 void 81 runtime·SysFree(void *v, uintptr n) 82 { 83 mstats.sys -= n; 84 runtime·munmap(v, n); 85 } 86 87 void* 88 runtime·SysReserve(void *v, uintptr n) 89 { 90 void *p; 91 92 // On 64-bit, people with ulimit -v set complain if we reserve too 93 // much address space. Instead, assume that the reservation is okay 94 // if we can reserve at least 64K and check the assumption in SysMap. 95 // Only user-mode Linux (UML) rejects these requests. 96 if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) { 97 p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 98 if (p != v) 99 return nil; 100 runtime·munmap(p, 64<<10); 101 return v; 102 } 103 104 p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 105 if((uintptr)p < 4096 || -(uintptr)p < 4096) 106 return nil; 107 return p; 108 } 109 110 void 111 runtime·SysMap(void *v, uintptr n) 112 { 113 void *p; 114 115 mstats.sys += n; 116 117 // On 64-bit, we don't actually have v reserved, so tread carefully. 118 if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) { 119 p = mmap_fixed(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); 120 if(p == (void*)ENOMEM) 121 runtime·throw("runtime: out of memory"); 122 if(p != v) { 123 runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p); 124 runtime·throw("runtime: address space conflict"); 125 } 126 return; 127 } 128 129 p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0); 130 if(p == (void*)ENOMEM) 131 runtime·throw("runtime: out of memory"); 132 if(p != v) 133 runtime·throw("runtime: cannot map pages in arena address space"); 134 }