github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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, uint64 *stat) 54 { 55 void *p; 56 57 p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); 58 if(p < (void*)4096) { 59 if(p == (void*)EACCES) { 60 runtime·printf("runtime: mmap: access denied\n"); 61 runtime·printf("if you're running SELinux, enable execmem for this process.\n"); 62 runtime·exit(2); 63 } 64 if(p == (void*)EAGAIN) { 65 runtime·printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n"); 66 runtime·exit(2); 67 } 68 return nil; 69 } 70 runtime·xadd64(stat, n); 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·SysUsed(void *v, uintptr n) 82 { 83 USED(v); 84 USED(n); 85 } 86 87 void 88 runtime·SysFree(void *v, uintptr n, uint64 *stat) 89 { 90 runtime·xadd64(stat, -(uint64)n); 91 runtime·munmap(v, n); 92 } 93 94 void* 95 runtime·SysReserve(void *v, uintptr n) 96 { 97 void *p; 98 99 // On 64-bit, people with ulimit -v set complain if we reserve too 100 // much address space. Instead, assume that the reservation is okay 101 // if we can reserve at least 64K and check the assumption in SysMap. 102 // Only user-mode Linux (UML) rejects these requests. 103 if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) { 104 p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 105 if (p != v) { 106 if(p >= (void*)4096) 107 runtime·munmap(p, 64<<10); 108 return nil; 109 } 110 runtime·munmap(p, 64<<10); 111 return v; 112 } 113 114 p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); 115 if((uintptr)p < 4096) 116 return nil; 117 return p; 118 } 119 120 void 121 runtime·SysMap(void *v, uintptr n, uint64 *stat) 122 { 123 void *p; 124 125 runtime·xadd64(stat, n); 126 127 // On 64-bit, we don't actually have v reserved, so tread carefully. 128 if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) { 129 p = mmap_fixed(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); 130 if(p == (void*)ENOMEM) 131 runtime·throw("runtime: out of memory"); 132 if(p != v) { 133 runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p); 134 runtime·throw("runtime: address space conflict"); 135 } 136 return; 137 } 138 139 p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0); 140 if(p == (void*)ENOMEM) 141 runtime·throw("runtime: out of memory"); 142 if(p != v) 143 runtime·throw("runtime: cannot map pages in arena address space"); 144 }