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  }