syscall: add SyscallN

This CL adds a new syscall.SyscallN API.

The proposal discussion also suggests the API should not only for
Windows but other platforms. However, the existing API set already
contain differences between platforms, hence the CL only implements
the Windows platform.

Moreover, although the API offers variadic parameters, the permitted
parameters remains up to a limit, which is selected as 42, and arguably
large enough.

Fixes #46552

Change-Id: I66b49988a304d9fc178c7cd5de46d0b75e167a4f
Reviewed-on: https://go-review.googlesource.com/c/go/+/336550
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Changkun Ou 2021-07-22 17:50:42 +02:00 committed by Matthew Dempsky
parent 91e2e3b903
commit 0e598e7da4
6 changed files with 115 additions and 133 deletions

View file

@ -468,84 +468,69 @@ func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uint
//go:linkname syscall_Syscall syscall.Syscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
lockOSThread()
defer unlockOSThread()
c := &getg().m.syscall
c.fn = fn
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
return syscall_SyscallN(fn, a1, a2, a3)
}
//go:linkname syscall_Syscall6 syscall.Syscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
lockOSThread()
defer unlockOSThread()
c := &getg().m.syscall
c.fn = fn
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6)
}
//go:linkname syscall_Syscall9 syscall.Syscall9
//go:nosplit
//go:cgo_unsafe_args
func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
lockOSThread()
c := &getg().m.syscall
c.fn = fn
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
cgocall(asmstdcallAddr, unsafe.Pointer(c))
unlockOSThread()
return c.r1, c.r2, c.err
return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
}
//go:linkname syscall_Syscall12 syscall.Syscall12
//go:nosplit
//go:cgo_unsafe_args
func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
lockOSThread()
c := &getg().m.syscall
c.fn = fn
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
cgocall(asmstdcallAddr, unsafe.Pointer(c))
unlockOSThread()
return c.r1, c.r2, c.err
return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
}
//go:linkname syscall_Syscall15 syscall.Syscall15
//go:nosplit
//go:cgo_unsafe_args
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) {
lockOSThread()
c := &getg().m.syscall
c.fn = fn
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
cgocall(asmstdcallAddr, unsafe.Pointer(c))
unlockOSThread()
return c.r1, c.r2, c.err
return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
}
//go:linkname syscall_Syscall18 syscall.Syscall18
//go:nosplit
//go:cgo_unsafe_args
func syscall_Syscall18(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2, err uintptr) {
return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18)
}
// maxArgs should be divisible by 2, as Windows stack
// must be kept 16-byte aligned on syscall entry.
//
// Although it only permits maximum 42 parameters, it
// is arguably large enough.
const maxArgs = 42
//go:linkname syscall_SyscallN syscall.SyscallN
//go:nosplit
func syscall_SyscallN(trap uintptr, args ...uintptr) (r1, r2, err uintptr) {
nargs := len(args)
// asmstdcall expects it can access the first 4 arguments
// to load them into registers.
var tmp [4]uintptr
switch {
case nargs < 4:
copy(tmp[:], args)
args = tmp[:]
case nargs > maxArgs:
panic("runtime: SyscallN has too many arguments")
}
lockOSThread()
defer unlockOSThread()
c := &getg().m.syscall
c.fn = fn
c.n = nargs
c.args = uintptr(noescape(unsafe.Pointer(&a1)))
c.fn = trap
c.n = uintptr(nargs)
c.args = uintptr(noescape(unsafe.Pointer(&args[0])))
cgocall(asmstdcallAddr, unsafe.Pointer(c))
unlockOSThread()
return c.r1, c.r2, c.err
}