aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/syscall_windows.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-09-08 00:08:51 -0400
committerRuss Cox <rsc@golang.org>2014-09-08 00:08:51 -0400
commitc007ce824d9a4fccb148f9204e04c23ed2984b71 (patch)
tree7dcac257114ef5c446be5b7b68c27dea230b7c09 /src/runtime/syscall_windows.go
parent220a6de47eced55956eb8af8d643d4f5b67fd634 (diff)
downloadgo-c007ce824d9a4fccb148f9204e04c23ed2984b71.tar.gz
go-c007ce824d9a4fccb148f9204e04c23ed2984b71.zip
build: move package sources from src/pkg to src
Preparation was in CL 134570043. This CL contains only the effect of 'hg mv src/pkg/* src'. For more about the move, see golang.org/s/go14nopkg.
Diffstat (limited to 'src/runtime/syscall_windows.go')
-rw-r--r--src/runtime/syscall_windows.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
new file mode 100644
index 0000000000..0592c57e1d
--- /dev/null
+++ b/src/runtime/syscall_windows.go
@@ -0,0 +1,88 @@
+// Copyright 2014 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"
+)
+
+type callbacks struct {
+ lock mutex
+ ctxt [cb_max]*wincallbackcontext
+ n int
+}
+
+func (c *wincallbackcontext) isCleanstack() bool {
+ return c.cleanstack
+}
+
+func (c *wincallbackcontext) setCleanstack(cleanstack bool) {
+ c.cleanstack = cleanstack
+}
+
+var (
+ cbs callbacks
+ cbctxts **wincallbackcontext = &cbs.ctxt[0] // to simplify access to cbs.ctxt in sys_windows_*.s
+
+ callbackasm byte // type isn't really byte, it's code in runtime
+)
+
+// callbackasmAddr returns address of runtime.callbackasm
+// function adjusted by i.
+// runtime.callbackasm is just a series of CALL instructions
+// (each is 5 bytes long), and we want callback to arrive at
+// correspondent call instruction instead of start of
+// runtime.callbackasm.
+func callbackasmAddr(i int) uintptr {
+ return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5)))
+}
+
+func compileCallback(fn eface, cleanstack bool) (code uintptr) {
+ if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
+ panic("compilecallback: not a function")
+ }
+ ft := (*functype)(unsafe.Pointer(fn._type))
+ if len(ft.out) != 1 {
+ panic("compilecallback: function must have one output parameter")
+ }
+ uintptrSize := unsafe.Sizeof(uintptr(0))
+ if t := (**_type)(unsafe.Pointer(&ft.out[0])); (*t).size != uintptrSize {
+ panic("compilecallback: output parameter size is wrong")
+ }
+ argsize := uintptr(0)
+ for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
+ if (*t).size != uintptrSize {
+ panic("compilecallback: input parameter size is wrong")
+ }
+ argsize += uintptrSize
+ }
+
+ lock(&cbs.lock)
+ defer unlock(&cbs.lock)
+
+ n := cbs.n
+ for i := 0; i < n; i++ {
+ if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack {
+ return callbackasmAddr(i)
+ }
+ }
+ if n >= cb_max {
+ gothrow("too many callback functions")
+ }
+
+ c := new(wincallbackcontext)
+ c.gobody = fn.data
+ c.argsize = argsize
+ c.setCleanstack(cleanstack)
+ if cleanstack && argsize != 0 {
+ c.restorestack = argsize
+ } else {
+ c.restorestack = 0
+ }
+ cbs.ctxt[n] = c
+ cbs.n++
+
+ return callbackasmAddr(n)
+}