diff --git a/func.go b/func.go index c6d1150f..5ce5103a 100644 --- a/func.go +++ b/func.go @@ -10,7 +10,6 @@ import ( "math" "reflect" "runtime" - "sync" "unsafe" "github.com/ebitengine/purego/internal/strings" @@ -22,10 +21,6 @@ const ( align8ByteSize = 8 // 8-byte alignment boundary ) -var thePool = sync.Pool{New: func() any { - return new(syscallArgs) -}} - // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name). // It panics if it can't find the name symbol. func RegisterLibFunc(fptr any, handle uintptr, name string) { @@ -323,13 +318,12 @@ func RegisterFunc(fptr any, cfn uintptr) { var syscall *syscallArgs if runtime.GOOS == "windows" && runtime.GOARCH != "arm64" { // Windows amd64, 386, and arm use syscall.SyscallN. - syscall = thePool.Get().(*syscallArgs) + syscall = &syscallArgs{} syscall.a1, syscall.a2, _ = syscall_syscallN(cfn, sysargs[:numStack]...) syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support } else { syscall = syscall_SyscallN(cfn, sysargs[:], floats[:], arm64_r8) } - defer thePool.Put(syscall) if ty.NumOut() == 0 { return nil } diff --git a/func_test.go b/func_test.go index cf7ebc04..d87eac8a 100644 --- a/func_test.go +++ b/func_test.go @@ -11,6 +11,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" "testing" "unsafe" @@ -35,6 +36,40 @@ func getSystemLibrary() (string, error) { } } +func TestRegisterFunc_ConcurrentPointerReturn(t *testing.T) { + library, err := getSystemLibrary() + if err != nil { + t.Fatalf("couldn't get system library: %s", err) + } + libc, err := load.OpenLibrary(library) + if err != nil { + t.Fatalf("failed to dlopen: %s", err) + } + + var alloc func(uint64) *byte + var free func(*byte) + purego.RegisterLibFunc(&alloc, libc, "malloc") + purego.RegisterLibFunc(&free, libc, "free") + + var wg sync.WaitGroup + + for i := 0; i < runtime.NumCPU(); i++ { + wg.Add(1) + go func(id int) { + defer wg.Done() + for j := 0; j < 400_000; j++ { + ptr := alloc(5) + if ptr == nil { + continue + } + free(ptr) + } + }(i) + } + + wg.Wait() +} + func TestRegisterFunc(t *testing.T) { library, err := getSystemLibrary() if err != nil { diff --git a/syscall.go b/syscall.go index 32f4a3d9..06068231 100644 --- a/syscall.go +++ b/syscall.go @@ -22,8 +22,7 @@ type syscallArgs struct { } func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs { - s := thePool.Get().(*syscallArgs) - *s = syscallArgs{ + s := &syscallArgs{ fn: fn, a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3], a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7], @@ -79,6 +78,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { var floats [maxArgs]uintptr copy(floats[:], tmp[:]) s := syscall_SyscallN(fn, tmp[:], floats[:], 0) - defer thePool.Put(s) return s.a1, s.a2, s.a3 } diff --git a/syscall_32bit.go b/syscall_32bit.go index c0641110..d6667da5 100644 --- a/syscall_32bit.go +++ b/syscall_32bit.go @@ -22,8 +22,7 @@ type syscallArgs struct { } func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs { - s := thePool.Get().(*syscallArgs) - *s = syscallArgs{ + s := &syscallArgs{ fn: fn, a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3], a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7], @@ -81,6 +80,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { var floats [16]uintptr copy(floats[:], tmp[:16]) s := syscall_SyscallN(fn, tmp[:], floats[:], 0) - defer thePool.Put(s) return s.a1, s.a2, s.a3 } diff --git a/syscall_ppc64le.go b/syscall_ppc64le.go index a133be3a..a8e94a2c 100644 --- a/syscall_ppc64le.go +++ b/syscall_ppc64le.go @@ -20,8 +20,7 @@ type syscallArgs struct { } func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs { - s := thePool.Get().(*syscallArgs) - *s = syscallArgs{ + s := &syscallArgs{ fn: fn, a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3], a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7], @@ -67,6 +66,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { var floats [maxArgs]uintptr copy(floats[:], tmp[:]) s := syscall_SyscallN(fn, tmp[:], floats[:], 0) - defer thePool.Put(s) return s.a1, s.a2, s.a3 }