1 // 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.
11 type callbacks
struct {
13 ctxt
[cb_max
]*wincallbackcontext
17 func (c
*wincallbackcontext
) isCleanstack() bool {
21 func (c
*wincallbackcontext
) setCleanstack(cleanstack
bool) {
22 c
.cleanstack
= cleanstack
27 cbctxts
**wincallbackcontext
= &cbs
.ctxt
[0] // to simplify access to cbs.ctxt in sys_windows_*.s
29 callbackasm
byte // type isn't really byte, it's code in runtime
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.
38 func callbackasmAddr(i
int) uintptr {
39 return uintptr(add(unsafe
.Pointer(&callbackasm
), uintptr(i
*5)))
42 func compileCallback(fn eface
, cleanstack
bool) (code
uintptr) {
43 if fn
._type
== nil ||
(fn
._type
.kind
&kindMask
) != kindFunc
{
44 panic("compilecallback: not a function")
46 ft
:= (*functype
)(unsafe
.Pointer(fn
._type
))
48 panic("compilecallback: function must have one output parameter")
50 uintptrSize
:= unsafe
.Sizeof(uintptr(0))
51 if t
:= (**_type
)(unsafe
.Pointer(&ft
.out
[0])); (*t
).size
!= uintptrSize
{
52 panic("compilecallback: output parameter size is wrong")
55 for _
, t
:= range (*[1024](*_type
))(unsafe
.Pointer(&ft
.in
[0]))[:len(ft
.in
)] {
56 if (*t
).size
> uintptrSize
{
57 panic("compilecallback: input parameter size is wrong")
59 argsize
+= uintptrSize
63 defer unlock(&cbs
.lock
)
66 for i
:= 0; i
< n
; i
++ {
67 if cbs
.ctxt
[i
].gobody
== fn
.data
&& cbs
.ctxt
[i
].isCleanstack() == cleanstack
{
68 return callbackasmAddr(i
)
72 gothrow("too many callback functions")
75 c
:= new(wincallbackcontext
)
78 c
.setCleanstack(cleanstack
)
79 if cleanstack
&& argsize
!= 0 {
80 c
.restorestack
= argsize
87 return callbackasmAddr(n
)
90 func getLoadLibrary() uintptr
93 func syscall_loadlibrary(filename
*uint16) (handle
, err
uintptr) {
95 c
.fn
= getLoadLibrary()
97 c
.args
= uintptr(unsafe
.Pointer(&filename
))
98 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
106 func getGetProcAddress() uintptr
109 func syscall_getprocaddress(handle
uintptr, procname
*byte) (outhandle
, err
uintptr) {
111 c
.fn
= getGetProcAddress()
113 c
.args
= uintptr(unsafe
.Pointer(&handle
))
114 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
123 func syscall_Syscall(fn
, nargs
, a1
, a2
, a3
uintptr) (r1
, r2
, err
uintptr) {
127 c
.args
= uintptr(unsafe
.Pointer(&a1
))
128 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
129 return c
.r1
, c
.r2
, c
.err
133 func syscall_Syscall6(fn
, nargs
, a1
, a2
, a3
, a4
, a5
, a6
uintptr) (r1
, r2
, err
uintptr) {
137 c
.args
= uintptr(unsafe
.Pointer(&a1
))
138 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
139 return c
.r1
, c
.r2
, c
.err
143 func syscall_Syscall9(fn
, nargs
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
uintptr) (r1
, r2
, err
uintptr) {
147 c
.args
= uintptr(unsafe
.Pointer(&a1
))
148 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
149 return c
.r1
, c
.r2
, c
.err
153 func syscall_Syscall12(fn
, nargs
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
, a11
, a12
uintptr) (r1
, r2
, err
uintptr) {
157 c
.args
= uintptr(unsafe
.Pointer(&a1
))
158 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
159 return c
.r1
, c
.r2
, c
.err
163 func syscall_Syscall15(fn
, nargs
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
, a11
, a12
, a13
, a14
, a15
uintptr) (r1
, r2
, err
uintptr) {
167 c
.args
= uintptr(unsafe
.Pointer(&a1
))
168 cgocall_errno(unsafe
.Pointer(funcPC(asmstdcall
)), unsafe
.Pointer(&c
))
169 return c
.r1
, c
.r2
, c
.err