1
0
mirror of https://github.com/golang/go synced 2024-11-19 21:14:43 -07:00
go/src/pkg/runtime/mem_freebsd.c
John Graham-Cumming 314fd62434 runtime: implement runtime.SysUnused on FreeBSD
madvise was missing so implement it in assembler. This change
needs to be extended to the other BSD variantes (Net and Open)

Without this change the scavenger will attempt to pass memory back
to the operating system when it has become idle, but the memory is
not returned and for long running Go processes the total memory used
can grow until OOM occurs.

I have only been able to test the code on FreeBSD AMD64. The ARM
platforms needs testing.

R=golang-dev, mikioh.mikioh, dave, jgc, minux.ma
CC=golang-dev
https://golang.org/cl/6850081
2012-11-24 15:55:19 +11:00

78 lines
1.7 KiB
C

// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "arch_GOARCH.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
void*
runtime·SysAlloc(uintptr n)
{
void *v;
mstats.sys += n;
v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
if(v < (void*)4096)
return nil;
return v;
}
void
runtime·SysUnused(void *v, uintptr n)
{
runtime·madvise(v, n, MADV_FREE);
}
void
runtime·SysFree(void *v, uintptr n)
{
mstats.sys -= n;
runtime·munmap(v, n);
}
void*
runtime·SysReserve(void *v, uintptr n)
{
// On 64-bit, people with ulimit -v set complain if we reserve too
// much address space. Instead, assume that the reservation is okay
// and check the assumption in SysMap.
if(sizeof(void*) == 8)
return v;
return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
}
enum
{
ENOMEM = 12,
};
void
runtime·SysMap(void *v, uintptr n)
{
void *p;
mstats.sys += n;
// On 64-bit, we don't actually have v reserved, so tread carefully.
if(sizeof(void*) == 8) {
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
if(p == (void*)-ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v) {
runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
runtime·throw("runtime: address space conflict");
}
return;
}
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
if(p == (void*)-ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
}