summaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2014-11-13 14:53:13 +1100
committerAlex Brainman <alex.brainman@gmail.com>2014-11-13 14:53:13 +1100
commit6399eb54aaff5cc06643bcbbfa1b3dd24f743681 (patch)
tree4e0958e7915ea54c59612808d20f47f27f9fc7a5 /src/runtime
parent02a7c13f8e208ad8aabbed94522f4417e6f036e8 (diff)
downloadgo-6399eb54aaff5cc06643bcbbfa1b3dd24f743681.tar.gz
[dev.cc] runtime: convert mem_windows.c to Go
LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/175000043
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/mem_windows.c132
-rw-r--r--src/runtime/mem_windows.go119
2 files changed, 119 insertions, 132 deletions
diff --git a/src/runtime/mem_windows.c b/src/runtime/mem_windows.c
deleted file mode 100644
index 6ea992020..000000000
--- a/src/runtime/mem_windows.c
+++ /dev/null
@@ -1,132 +0,0 @@
-// 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 "os_GOOS.h"
-#include "defs_GOOS_GOARCH.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum {
- MEM_COMMIT = 0x1000,
- MEM_RESERVE = 0x2000,
- MEM_DECOMMIT = 0x4000,
- MEM_RELEASE = 0x8000,
-
- PAGE_READWRITE = 0x0004,
- PAGE_NOACCESS = 0x0001,
-};
-
-#pragma dynimport runtime·VirtualAlloc VirtualAlloc "kernel32.dll"
-#pragma dynimport runtime·VirtualFree VirtualFree "kernel32.dll"
-#pragma dynimport runtime·VirtualProtect VirtualProtect "kernel32.dll"
-extern void *runtime·VirtualAlloc;
-extern void *runtime·VirtualFree;
-extern void *runtime·VirtualProtect;
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
- runtime·xadd64(stat, n);
- return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
- void *r;
- uintptr small;
-
- r = runtime·stdcall3(runtime·VirtualFree, (uintptr)v, n, MEM_DECOMMIT);
- if(r != nil)
- return;
-
- // Decommit failed. Usual reason is that we've merged memory from two different
- // VirtualAlloc calls, and Windows will only let each VirtualFree handle pages from
- // a single VirtualAlloc. It is okay to specify a subset of the pages from a single alloc,
- // just not pages from multiple allocs. This is a rare case, arising only when we're
- // trying to give memory back to the operating system, which happens on a time
- // scale of minutes. It doesn't have to be terribly fast. Instead of extra bookkeeping
- // on all our VirtualAlloc calls, try freeing successively smaller pieces until
- // we manage to free something, and then repeat. This ends up being O(n log n)
- // in the worst case, but that's fast enough.
- while(n > 0) {
- small = n;
- while(small >= 4096 && runtime·stdcall3(runtime·VirtualFree, (uintptr)v, small, MEM_DECOMMIT) == nil)
- small = (small / 2) & ~(4096-1);
- if(small < 4096)
- runtime·throw("runtime: failed to decommit pages");
- v = (byte*)v + small;
- n -= small;
- }
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
- void *r;
- uintptr small;
-
- r = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
- if(r != v)
- runtime·throw("runtime: failed to commit pages");
-
- // Commit failed. See SysUnused.
- while(n > 0) {
- small = n;
- while(small >= 4096 && runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, small, MEM_COMMIT, PAGE_READWRITE) == nil)
- small = (small / 2) & ~(4096-1);
- if(small < 4096)
- runtime·throw("runtime: failed to decommit pages");
- v = (byte*)v + small;
- n -= small;
- }
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
- uintptr r;
-
- runtime·xadd64(stat, -(uint64)n);
- r = (uintptr)runtime·stdcall3(runtime·VirtualFree, (uintptr)v, 0, MEM_RELEASE);
- if(r == 0)
- runtime·throw("runtime: failed to release pages");
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
- // SysUnused makes the memory inaccessible and prevents its reuse
- runtime·SysUnused(v, n);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
- *reserved = true;
- // v is just a hint.
- // First try at v.
- v = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_RESERVE, PAGE_READWRITE);
- if(v != nil)
- return v;
-
- // Next let the kernel choose the address.
- return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_RESERVE, PAGE_READWRITE);
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
- void *p;
-
- USED(reserved);
-
- runtime·xadd64(stat, n);
- p = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
- if(p != v)
- runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_windows.go b/src/runtime/mem_windows.go
new file mode 100644
index 000000000..a1dcad013
--- /dev/null
+++ b/src/runtime/mem_windows.go
@@ -0,0 +1,119 @@
+// 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.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+const (
+ _MEM_COMMIT = 0x1000
+ _MEM_RESERVE = 0x2000
+ _MEM_DECOMMIT = 0x4000
+ _MEM_RELEASE = 0x8000
+
+ _PAGE_READWRITE = 0x0004
+ _PAGE_NOACCESS = 0x0001
+)
+
+//go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc "kernel32.dll"
+//go:cgo_import_dynamic runtime._VirtualFree VirtualFree "kernel32.dll"
+//go:cgo_import_dynamic runtime._VirtualProtect VirtualProtect "kernel32.dll"
+
+var (
+ _VirtualAlloc,
+ _VirtualFree,
+ _VirtualProtect stdFunction
+)
+
+//go:nosplit
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+ xadd64(stat, int64(n))
+ return unsafe.Pointer(stdcall4(_VirtualAlloc, 0, n, _MEM_COMMIT|_MEM_RESERVE, _PAGE_READWRITE))
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+ r := stdcall3(_VirtualFree, uintptr(v), n, _MEM_DECOMMIT)
+ if r != 0 {
+ return
+ }
+
+ // Decommit failed. Usual reason is that we've merged memory from two different
+ // VirtualAlloc calls, and Windows will only let each VirtualFree handle pages from
+ // a single VirtualAlloc. It is okay to specify a subset of the pages from a single alloc,
+ // just not pages from multiple allocs. This is a rare case, arising only when we're
+ // trying to give memory back to the operating system, which happens on a time
+ // scale of minutes. It doesn't have to be terribly fast. Instead of extra bookkeeping
+ // on all our VirtualAlloc calls, try freeing successively smaller pieces until
+ // we manage to free something, and then repeat. This ends up being O(n log n)
+ // in the worst case, but that's fast enough.
+ for n > 0 {
+ small := n
+ for small >= 4096 && stdcall3(_VirtualFree, uintptr(v), small, _MEM_DECOMMIT) == 0 {
+ small /= 2
+ small &^= 4096 - 1
+ }
+ if small < 4096 {
+ gothrow("runtime: failed to decommit pages")
+ }
+ v = add(v, small)
+ n -= small
+ }
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+ r := stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_COMMIT, _PAGE_READWRITE)
+ if r != uintptr(v) {
+ gothrow("runtime: failed to commit pages")
+ }
+
+ // Commit failed. See SysUnused.
+ for n > 0 {
+ small := n
+ for small >= 4096 && stdcall4(_VirtualAlloc, uintptr(v), small, _MEM_COMMIT, _PAGE_READWRITE) == 0 {
+ small /= 2
+ small &^= 4096 - 1
+ }
+ if small < 4096 {
+ gothrow("runtime: failed to decommit pages")
+ }
+ v = add(v, small)
+ n -= small
+ }
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+ xadd64(stat, -int64(n))
+ r := stdcall3(_VirtualFree, uintptr(v), 0, _MEM_RELEASE)
+ if r == 0 {
+ gothrow("runtime: failed to release pages")
+ }
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+ // SysUnused makes the memory inaccessible and prevents its reuse
+ sysUnused(v, n)
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+ *reserved = true
+ // v is just a hint.
+ // First try at v.
+ v = unsafe.Pointer(stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_RESERVE, _PAGE_READWRITE))
+ if v != nil {
+ return v
+ }
+
+ // Next let the kernel choose the address.
+ return unsafe.Pointer(stdcall4(_VirtualAlloc, 0, n, _MEM_RESERVE, _PAGE_READWRITE))
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+ xadd64(stat, int64(n))
+ p := stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_COMMIT, _PAGE_READWRITE)
+ if p != uintptr(v) {
+ gothrow("runtime: cannot map pages in arena address space")
+ }
+}