Skip to content

Commit 1207de4

Browse files
qmuntalprattmic
authored andcommitted
[release-branch.go1.23] runtime: reduce syscall.SyscallX stack usage
syscall.SyscallX consumes a lot of stack space, which is a problem because they are nosplit functions. They used to use less stack space, but CL 563315, that landed in Go 1.23, increased the stack usage by a lot. This CL reduces the stack usage back to the previous level. Fixes #69848 Updates #69813 Change-Id: Iddedd28b693c66a258da687389768055c493fc2e Reviewed-on: https://go-review.googlesource.com/c/go/+/618497 Reviewed-by: Cherry Mui <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> (cherry picked from commit fa7343a) Reviewed-on: https://go-review.googlesource.com/c/go/+/623516 Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Michael Pratt <[email protected]>
1 parent a0d15cb commit 1207de4

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

src/runtime/syscall_windows.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -454,43 +454,37 @@ func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uint
454454
//go:linkname syscall_Syscall syscall.Syscall
455455
//go:nosplit
456456
func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
457-
args := [...]uintptr{a1, a2, a3}
458-
return syscall_SyscallN(fn, args[:nargs]...)
457+
return syscall_syscalln(fn, nargs, a1, a2, a3)
459458
}
460459

461460
//go:linkname syscall_Syscall6 syscall.Syscall6
462461
//go:nosplit
463462
func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
464-
args := [...]uintptr{a1, a2, a3, a4, a5, a6}
465-
return syscall_SyscallN(fn, args[:nargs]...)
463+
return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6)
466464
}
467465

468466
//go:linkname syscall_Syscall9 syscall.Syscall9
469467
//go:nosplit
470468
func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
471-
args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9}
472-
return syscall_SyscallN(fn, args[:nargs]...)
469+
return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9)
473470
}
474471

475472
//go:linkname syscall_Syscall12 syscall.Syscall12
476473
//go:nosplit
477474
func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
478-
args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12}
479-
return syscall_SyscallN(fn, args[:nargs]...)
475+
return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
480476
}
481477

482478
//go:linkname syscall_Syscall15 syscall.Syscall15
483479
//go:nosplit
484480
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) {
485-
args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15}
486-
return syscall_SyscallN(fn, args[:nargs]...)
481+
return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
487482
}
488483

489484
//go:linkname syscall_Syscall18 syscall.Syscall18
490485
//go:nosplit
491486
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) {
492-
args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18}
493-
return syscall_SyscallN(fn, args[:nargs]...)
487+
return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18)
494488
}
495489

496490
// maxArgs should be divisible by 2, as Windows stack
@@ -503,7 +497,15 @@ const maxArgs = 42
503497
//go:linkname syscall_SyscallN syscall.SyscallN
504498
//go:nosplit
505499
func syscall_SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
506-
if len(args) > maxArgs {
500+
return syscall_syscalln(fn, uintptr(len(args)), args...)
501+
}
502+
503+
//go:nosplit
504+
func syscall_syscalln(fn, n uintptr, args ...uintptr) (r1, r2, err uintptr) {
505+
if n > uintptr(len(args)) {
506+
panic("syscall: n > len(args)") // should not be reachable from user code
507+
}
508+
if n > maxArgs {
507509
panic("runtime: SyscallN has too many arguments")
508510
}
509511

@@ -512,7 +514,7 @@ func syscall_SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
512514
// calls back into Go.
513515
c := &getg().m.winsyscall
514516
c.fn = fn
515-
c.n = uintptr(len(args))
517+
c.n = n
516518
if c.n != 0 {
517519
c.args = uintptr(noescape(unsafe.Pointer(&args[0])))
518520
}

src/runtime/syscall_windows_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,13 @@ func TestBigStackCallbackSyscall(t *testing.T) {
12121212
}
12131213
}
12141214

1215+
func TestSyscallStackUsage(t *testing.T) {
1216+
// Test that the stack usage of a syscall doesn't exceed the limit.
1217+
// See https://go.dev/issue/69813.
1218+
syscall.Syscall15(procSetEvent.Addr(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1219+
syscall.Syscall18(procSetEvent.Addr(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1220+
}
1221+
12151222
var (
12161223
modwinmm = syscall.NewLazyDLL("winmm.dll")
12171224
modkernel32 = syscall.NewLazyDLL("kernel32.dll")

0 commit comments

Comments
 (0)