github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/runtime/syscall_windows.go (about)

     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  
    11  type callbacks struct {
    12  	lock mutex
    13  	ctxt [cb_max]*wincallbackcontext
    14  	n    int
    15  }
    16  
    17  func (c *wincallbackcontext) isCleanstack() bool {
    18  	return c.cleanstack
    19  }
    20  
    21  func (c *wincallbackcontext) setCleanstack(cleanstack bool) {
    22  	c.cleanstack = cleanstack
    23  }
    24  
    25  var (
    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.
    38  func callbackasmAddr(i int) uintptr {
    39  	return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5)))
    40  }
    41  
    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")
    45  	}
    46  	ft := (*functype)(unsafe.Pointer(fn._type))
    47  	if ft.out.len != 1 {
    48  		panic("compileCallback: function must have one output parameter")
    49  	}
    50  	uintptrSize := unsafe.Sizeof(uintptr(0))
    51  	if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
    52  		panic("compileCallback: output parameter size is wrong")
    53  	}
    54  	argsize := uintptr(0)
    55  	for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
    56  		if (*t).size > uintptrSize {
    57  			panic("compileCallback: input parameter size is wrong")
    58  		}
    59  		argsize += uintptrSize
    60  	}
    61  
    62  	lock(&cbs.lock)
    63  	defer unlock(&cbs.lock)
    64  
    65  	n := cbs.n
    66  	for i := 0; i < n; i++ {
    67  		if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack {
    68  			return callbackasmAddr(i)
    69  		}
    70  	}
    71  	if n >= cb_max {
    72  		gothrow("too many callback functions")
    73  	}
    74  
    75  	c := new(wincallbackcontext)
    76  	c.gobody = fn.data
    77  	c.argsize = argsize
    78  	c.setCleanstack(cleanstack)
    79  	if cleanstack && argsize != 0 {
    80  		c.restorestack = argsize
    81  	} else {
    82  		c.restorestack = 0
    83  	}
    84  	cbs.ctxt[n] = c
    85  	cbs.n++
    86  
    87  	return callbackasmAddr(n)
    88  }
    89  
    90  //go:nosplit
    91  func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
    92  	var c libcall
    93  	c.fn = getLoadLibrary()
    94  	c.n = 1
    95  	c.args = uintptr(unsafe.Pointer(&filename))
    96  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
    97  	handle = c.r1
    98  	if handle == 0 {
    99  		err = c.err
   100  	}
   101  	return
   102  }
   103  
   104  //go:nosplit
   105  func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
   106  	var c libcall
   107  	c.fn = getGetProcAddress()
   108  	c.n = 2
   109  	c.args = uintptr(unsafe.Pointer(&handle))
   110  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
   111  	outhandle = c.r1
   112  	if outhandle == 0 {
   113  		err = c.err
   114  	}
   115  	return
   116  }
   117  
   118  //go:nosplit
   119  func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
   120  	var c libcall
   121  	c.fn = fn
   122  	c.n = nargs
   123  	c.args = uintptr(unsafe.Pointer(&a1))
   124  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
   125  	return c.r1, c.r2, c.err
   126  }
   127  
   128  //go:nosplit
   129  func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
   130  	var c libcall
   131  	c.fn = fn
   132  	c.n = nargs
   133  	c.args = uintptr(unsafe.Pointer(&a1))
   134  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
   135  	return c.r1, c.r2, c.err
   136  }
   137  
   138  //go:nosplit
   139  func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
   140  	var c libcall
   141  	c.fn = fn
   142  	c.n = nargs
   143  	c.args = uintptr(unsafe.Pointer(&a1))
   144  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
   145  	return c.r1, c.r2, c.err
   146  }
   147  
   148  //go:nosplit
   149  func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
   150  	var c libcall
   151  	c.fn = fn
   152  	c.n = nargs
   153  	c.args = uintptr(unsafe.Pointer(&a1))
   154  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
   155  	return c.r1, c.r2, c.err
   156  }
   157  
   158  //go:nosplit
   159  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) {
   160  	var c libcall
   161  	c.fn = fn
   162  	c.n = nargs
   163  	c.args = uintptr(unsafe.Pointer(&a1))
   164  	cgocall_errno(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&c))
   165  	return c.r1, c.r2, c.err
   166  }