blob: 8e069cdb15f82a014f969eeda8120d9e4b5d743d [file] [log] [blame]
Brent Austinba3052e2015-04-21 16:08:23 -07001// Copyright 2014 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
5package runtime
6
7import (
8 "unsafe"
9)
10
Brent Austinba3052e2015-04-21 16:08:23 -070011type callbacks struct {
12 lock mutex
13 ctxt [cb_max]*wincallbackcontext
14 n int
15}
16
17func (c *wincallbackcontext) isCleanstack() bool {
18 return c.cleanstack
19}
20
21func (c *wincallbackcontext) setCleanstack(cleanstack bool) {
22 c.cleanstack = cleanstack
23}
24
25var (
26 cbs callbacks
27 cbctxts **wincallbackcontext = &cbs.ctxt[0] // to simplify access to cbs.ctxt in sys_windows_*.s
28
29 callbackasm byte // type isn't really byte, it's code in runtime
30)
31
32// callbackasmAddr returns address of runtime.callbackasm
33// function adjusted by i.
34// runtime.callbackasm is just a series of CALL instructions
35// (each is 5 bytes long), and we want callback to arrive at
36// correspondent call instruction instead of start of
37// runtime.callbackasm.
38func callbackasmAddr(i int) uintptr {
39 return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5)))
40}
41
Anton Carvere342c612015-10-15 19:13:47 +010042//go:linkname compileCallback syscall.compileCallback
Brent Austinba3052e2015-04-21 16:08:23 -070043func compileCallback(fn eface, cleanstack bool) (code uintptr) {
44 if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
Anton Carvere342c612015-10-15 19:13:47 +010045 panic("compileCallback: not a function")
Brent Austinba3052e2015-04-21 16:08:23 -070046 }
47 ft := (*functype)(unsafe.Pointer(fn._type))
Anton Carvere342c612015-10-15 19:13:47 +010048 if ft.out.len != 1 {
49 panic("compileCallback: function must have one output parameter")
Brent Austinba3052e2015-04-21 16:08:23 -070050 }
51 uintptrSize := unsafe.Sizeof(uintptr(0))
Anton Carvere342c612015-10-15 19:13:47 +010052 if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
53 panic("compileCallback: output parameter size is wrong")
Brent Austinba3052e2015-04-21 16:08:23 -070054 }
55 argsize := uintptr(0)
Anton Carvere342c612015-10-15 19:13:47 +010056 for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
57 if (*t).size > uintptrSize {
58 panic("compileCallback: input parameter size is wrong")
Brent Austinba3052e2015-04-21 16:08:23 -070059 }
Anton Carvere342c612015-10-15 19:13:47 +010060 argsize += uintptrSize
Brent Austinba3052e2015-04-21 16:08:23 -070061 }
62
63 lock(&cbs.lock)
64 defer unlock(&cbs.lock)
65
66 n := cbs.n
67 for i := 0; i < n; i++ {
68 if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack {
69 return callbackasmAddr(i)
70 }
71 }
72 if n >= cb_max {
Anton Carvere342c612015-10-15 19:13:47 +010073 throw("too many callback functions")
Brent Austinba3052e2015-04-21 16:08:23 -070074 }
75
76 c := new(wincallbackcontext)
77 c.gobody = fn.data
78 c.argsize = argsize
79 c.setCleanstack(cleanstack)
80 if cleanstack && argsize != 0 {
81 c.restorestack = argsize
82 } else {
83 c.restorestack = 0
84 }
85 cbs.ctxt[n] = c
86 cbs.n++
87
88 return callbackasmAddr(n)
89}
90
Anton Carvere342c612015-10-15 19:13:47 +010091//go:linkname syscall_loadlibrary syscall.loadlibrary
Brent Austinba3052e2015-04-21 16:08:23 -070092//go:nosplit
93func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +010094 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -070095 c.fn = getLoadLibrary()
96 c.n = 1
Anton Carvere342c612015-10-15 19:13:47 +010097 c.args = uintptr(noescape(unsafe.Pointer(&filename)))
98 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -070099 handle = c.r1
100 if handle == 0 {
101 err = c.err
102 }
103 return
104}
105
Anton Carvere342c612015-10-15 19:13:47 +0100106//go:linkname syscall_getprocaddress syscall.getprocaddress
Brent Austinba3052e2015-04-21 16:08:23 -0700107//go:nosplit
108func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +0100109 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700110 c.fn = getGetProcAddress()
111 c.n = 2
Anton Carvere342c612015-10-15 19:13:47 +0100112 c.args = uintptr(noescape(unsafe.Pointer(&handle)))
113 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -0700114 outhandle = c.r1
115 if outhandle == 0 {
116 err = c.err
117 }
118 return
119}
120
Anton Carvere342c612015-10-15 19:13:47 +0100121//go:linkname syscall_Syscall syscall.Syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700122//go:nosplit
123func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +0100124 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700125 c.fn = fn
126 c.n = nargs
Anton Carvere342c612015-10-15 19:13:47 +0100127 c.args = uintptr(noescape(unsafe.Pointer(&a1)))
128 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -0700129 return c.r1, c.r2, c.err
130}
131
Anton Carvere342c612015-10-15 19:13:47 +0100132//go:linkname syscall_Syscall6 syscall.Syscall6
Brent Austinba3052e2015-04-21 16:08:23 -0700133//go:nosplit
134func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +0100135 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700136 c.fn = fn
137 c.n = nargs
Anton Carvere342c612015-10-15 19:13:47 +0100138 c.args = uintptr(noescape(unsafe.Pointer(&a1)))
139 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -0700140 return c.r1, c.r2, c.err
141}
142
Anton Carvere342c612015-10-15 19:13:47 +0100143//go:linkname syscall_Syscall9 syscall.Syscall9
Brent Austinba3052e2015-04-21 16:08:23 -0700144//go:nosplit
145func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +0100146 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700147 c.fn = fn
148 c.n = nargs
Anton Carvere342c612015-10-15 19:13:47 +0100149 c.args = uintptr(noescape(unsafe.Pointer(&a1)))
150 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -0700151 return c.r1, c.r2, c.err
152}
153
Anton Carvere342c612015-10-15 19:13:47 +0100154//go:linkname syscall_Syscall12 syscall.Syscall12
Brent Austinba3052e2015-04-21 16:08:23 -0700155//go:nosplit
156func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +0100157 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700158 c.fn = fn
159 c.n = nargs
Anton Carvere342c612015-10-15 19:13:47 +0100160 c.args = uintptr(noescape(unsafe.Pointer(&a1)))
161 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -0700162 return c.r1, c.r2, c.err
163}
164
Anton Carvere342c612015-10-15 19:13:47 +0100165//go:linkname syscall_Syscall15 syscall.Syscall15
Brent Austinba3052e2015-04-21 16:08:23 -0700166//go:nosplit
167func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
Anton Carvere342c612015-10-15 19:13:47 +0100168 c := &getg().m.syscall
Brent Austinba3052e2015-04-21 16:08:23 -0700169 c.fn = fn
170 c.n = nargs
Anton Carvere342c612015-10-15 19:13:47 +0100171 c.args = uintptr(noescape(unsafe.Pointer(&a1)))
172 cgocall(asmstdcallAddr, unsafe.Pointer(c))
Brent Austinba3052e2015-04-21 16:08:23 -0700173 return c.r1, c.r2, c.err
174}