]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: mark SyscallN as noescape
authorqmuntal <quimmuntal@gmail.com>
Tue, 5 Nov 2024 15:01:45 +0000 (16:01 +0100)
committerQuim Muntal <quimmuntal@gmail.com>
Wed, 6 Nov 2024 16:35:17 +0000 (16:35 +0000)
syscall.SyscallN is implemented by runtime.syscall_syscalln, which makes
sure that the variadic argument doesn't escape.

There is no need to worry about the lifetime of the elements of the
variadic argument, as the compiler will keep them live until the
function returns.

Fixes #70197.

Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-longtest,gotip-windows-amd64-race
Change-Id: I12991f0be12062eea68f2b103fa0a794c1b527eb
Reviewed-on: https://go-review.googlesource.com/c/go/+/625297
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/syscall/dll_windows.go
src/syscall/syscall_windows_test.go

index 81134cb0bd27ffd0da8ef8cfdd827daa6d0b4afe..a7873e6ad8c93ef200979aa001c2cf1b3ebe8616 100644 (file)
@@ -42,6 +42,7 @@ func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
 // Deprecated: Use [SyscallN] instead.
 func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2 uintptr, err Errno)
 
+//go:noescape
 func SyscallN(trap uintptr, args ...uintptr) (r1, r2 uintptr, err Errno)
 func loadlibrary(filename *uint16) (handle uintptr, err Errno)
 func loadsystemlibrary(filename *uint16) (handle uintptr, err Errno)
index 8b5af9c501dc4553922521ccbc8ea60d6e7c6be3..63409daf044f06aabda9ba2cf953f7e4a0b381ef 100644 (file)
@@ -227,6 +227,53 @@ func TestGetStartupInfo(t *testing.T) {
        }
 }
 
+func TestSyscallAllocations(t *testing.T) {
+       testenv.SkipIfOptimizationOff(t)
+
+       t.Parallel()
+
+       // Test that syscall.SyscallN arguments do not escape.
+       // The function used (in this case GetVersion) doesn't matter
+       // as long as it is always available and doesn't panic.
+       h, err := syscall.LoadLibrary("kernel32.dll")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer syscall.FreeLibrary(h)
+       proc, err := syscall.GetProcAddress(h, "GetVersion")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       testAllocs := func(t *testing.T, name string, fn func() error) {
+               t.Run(name, func(t *testing.T) {
+                       n := int(testing.AllocsPerRun(10, func() {
+                               if err := fn(); err != nil {
+                                       t.Fatalf("%s: %v", name, err)
+                               }
+                       }))
+                       if n > 0 {
+                               t.Errorf("allocs = %d, want 0", n)
+                       }
+               })
+       }
+
+       testAllocs(t, "SyscallN", func() error {
+               r0, _, e1 := syscall.SyscallN(proc, 0, 0, 0)
+               if r0 == 0 {
+                       return syscall.Errno(e1)
+               }
+               return nil
+       })
+       testAllocs(t, "Syscall", func() error {
+               r0, _, e1 := syscall.Syscall(proc, 3, 0, 0, 0)
+               if r0 == 0 {
+                       return syscall.Errno(e1)
+               }
+               return nil
+       })
+}
+
 func FuzzUTF16FromString(f *testing.F) {
        f.Add("hi")           // ASCII
        f.Add("รข")            // latin1