syscall_windows.go 4.4 KB

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