]>
Commit | Line | Data |
---|---|---|
f8d9fa9e ILT |
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. | |
4 | ||
5 | package runtime | |
6 | ||
7 | import ( | |
8 | "unsafe" | |
9 | ) | |
10 | ||
c271e224 ILT |
11 | const _SIGPROF = 0 // dummy value for badsignal |
12 | ||
f8d9fa9e ILT |
13 | type callbacks struct { |
14 | lock mutex | |
15 | ctxt [cb_max]*wincallbackcontext | |
16 | n int | |
17 | } | |
18 | ||
19 | func (c *wincallbackcontext) isCleanstack() bool { | |
20 | return c.cleanstack | |
21 | } | |
22 | ||
23 | func (c *wincallbackcontext) setCleanstack(cleanstack bool) { | |
24 | c.cleanstack = cleanstack | |
25 | } | |
26 | ||
27 | var ( | |
28 | cbs callbacks | |
29 | cbctxts **wincallbackcontext = &cbs.ctxt[0] // to simplify access to cbs.ctxt in sys_windows_*.s | |
30 | ||
31 | callbackasm byte // type isn't really byte, it's code in runtime | |
32 | ) | |
33 | ||
34 | // callbackasmAddr returns address of runtime.callbackasm | |
35 | // function adjusted by i. | |
36 | // runtime.callbackasm is just a series of CALL instructions | |
37 | // (each is 5 bytes long), and we want callback to arrive at | |
38 | // correspondent call instruction instead of start of | |
39 | // runtime.callbackasm. | |
40 | func callbackasmAddr(i int) uintptr { | |
41 | return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5))) | |
42 | } | |
43 | ||
44 | func compileCallback(fn eface, cleanstack bool) (code uintptr) { | |
45 | if fn._type == nil || (fn._type.kind&kindMask) != kindFunc { | |
46 | panic("compilecallback: not a function") | |
47 | } | |
48 | ft := (*functype)(unsafe.Pointer(fn._type)) | |
49 | if len(ft.out) != 1 { | |
50 | panic("compilecallback: function must have one output parameter") | |
51 | } | |
52 | uintptrSize := unsafe.Sizeof(uintptr(0)) | |
53 | if t := (**_type)(unsafe.Pointer(&ft.out[0])); (*t).size != uintptrSize { | |
54 | panic("compilecallback: output parameter size is wrong") | |
55 | } | |
56 | argsize := uintptr(0) | |
c271e224 ILT |
57 | if len(ft.in) > 0 { |
58 | for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] { | |
59 | if (*t).size > uintptrSize { | |
60 | panic("compilecallback: input parameter size is wrong") | |
61 | } | |
62 | argsize += uintptrSize | |
f8d9fa9e | 63 | } |
f8d9fa9e ILT |
64 | } |
65 | ||
66 | lock(&cbs.lock) | |
67 | defer unlock(&cbs.lock) | |
68 | ||
69 | n := cbs.n | |
70 | for i := 0; i < n; i++ { | |
71 | if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack { | |
72 | return callbackasmAddr(i) | |
73 | } | |
74 | } | |
75 | if n >= cb_max { | |
76 | gothrow("too many callback functions") | |
77 | } | |
78 | ||
79 | c := new(wincallbackcontext) | |
80 | c.gobody = fn.data | |
81 | c.argsize = argsize | |
82 | c.setCleanstack(cleanstack) | |
83 | if cleanstack && argsize != 0 { | |
84 | c.restorestack = argsize | |
85 | } else { | |
86 | c.restorestack = 0 | |
87 | } | |
88 | cbs.ctxt[n] = c | |
89 | cbs.n++ | |
90 | ||
91 | return callbackasmAddr(n) | |
92 | } | |
93 | ||
94 | func getLoadLibrary() uintptr | |
95 | ||
96 | //go:nosplit | |
97 | func syscall_loadlibrary(filename *uint16) (handle, err uintptr) { | |
98 | var c libcall | |
99 | c.fn = getLoadLibrary() | |
100 | c.n = 1 | |
101 | c.args = uintptr(unsafe.Pointer(&filename)) | |
102 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
103 | handle = c.r1 | |
104 | if handle == 0 { | |
105 | err = c.err | |
106 | } | |
107 | return | |
108 | } | |
109 | ||
110 | func getGetProcAddress() uintptr | |
111 | ||
112 | //go:nosplit | |
113 | func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) { | |
114 | var c libcall | |
115 | c.fn = getGetProcAddress() | |
116 | c.n = 2 | |
117 | c.args = uintptr(unsafe.Pointer(&handle)) | |
118 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
119 | outhandle = c.r1 | |
120 | if outhandle == 0 { | |
121 | err = c.err | |
122 | } | |
123 | return | |
124 | } | |
125 | ||
126 | //go:nosplit | |
127 | func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) { | |
128 | var c libcall | |
129 | c.fn = fn | |
130 | c.n = nargs | |
131 | c.args = uintptr(unsafe.Pointer(&a1)) | |
132 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
133 | return c.r1, c.r2, c.err | |
134 | } | |
135 | ||
136 | //go:nosplit | |
137 | func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { | |
138 | var c libcall | |
139 | c.fn = fn | |
140 | c.n = nargs | |
141 | c.args = uintptr(unsafe.Pointer(&a1)) | |
142 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
143 | return c.r1, c.r2, c.err | |
144 | } | |
145 | ||
146 | //go:nosplit | |
147 | func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | |
148 | var c libcall | |
149 | c.fn = fn | |
150 | c.n = nargs | |
151 | c.args = uintptr(unsafe.Pointer(&a1)) | |
152 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
153 | return c.r1, c.r2, c.err | |
154 | } | |
155 | ||
156 | //go:nosplit | |
157 | func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) { | |
158 | var c libcall | |
159 | c.fn = fn | |
160 | c.n = nargs | |
161 | c.args = uintptr(unsafe.Pointer(&a1)) | |
162 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
163 | return c.r1, c.r2, c.err | |
164 | } | |
165 | ||
166 | //go:nosplit | |
167 | 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) { | |
168 | var c libcall | |
169 | c.fn = fn | |
170 | c.n = nargs | |
171 | c.args = uintptr(unsafe.Pointer(&a1)) | |
172 | cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c)) | |
173 | return c.r1, c.r2, c.err | |
174 | } |