]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] runtime: convert mem_windows.c to Go
authorAlex Brainman <alex.brainman@gmail.com>
Thu, 13 Nov 2014 03:53:13 +0000 (14:53 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Thu, 13 Nov 2014 03:53:13 +0000 (14:53 +1100)
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/175000043

src/runtime/mem_windows.c [deleted file]
src/runtime/mem_windows.go [new file with mode: 0644]

diff --git a/src/runtime/mem_windows.c b/src/runtime/mem_windows.c
deleted file mode 100644 (file)
index 6ea9920..0000000
+++ /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 (file)
index 0000000..a1dcad0
--- /dev/null
@@ -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")
+       }
+}