Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"math"
"reflect"
"runtime"
"sync"
"unsafe"

"github.com/ebitengine/purego/internal/strings"
Expand All @@ -21,6 +22,10 @@ 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) {
Expand Down Expand Up @@ -318,12 +323,13 @@ 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 = &syscallArgs{}
syscall = thePool.Get().(*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
}
Expand All @@ -340,7 +346,10 @@ func RegisterFunc(fptr any, cfn uintptr) {
// We take the address and then dereference it to trick go vet from creating a possible miss-use of unsafe.Pointer
v.SetPointer(*(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1)))
case reflect.Pointer:
v = reflect.NewAt(outType, unsafe.Pointer(&syscall.a1)).Elem()
// Copy syscall.a1 into a local variable to prevent v
// from holding a pointer to the pooled syscallArgs field.
a1 := syscall.a1
v = reflect.NewAt(outType, unsafe.Pointer(&a1)).Elem()
case reflect.Func:
// wrap this C function in a nicely typed Go function
v = reflect.New(outType)
Expand Down
4 changes: 3 additions & 1 deletion syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ type syscallArgs struct {
}

func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
s := &syscallArgs{
s := thePool.Get().(*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],
Expand Down Expand Up @@ -78,5 +79,6 @@ 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
}
4 changes: 3 additions & 1 deletion syscall_32bit.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ type syscallArgs struct {
}

func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
s := &syscallArgs{
s := thePool.Get().(*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],
Expand Down Expand Up @@ -80,5 +81,6 @@ 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
}
4 changes: 3 additions & 1 deletion syscall_ppc64le.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ type syscallArgs struct {
}

func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
s := &syscallArgs{
s := thePool.Get().(*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],
Expand Down Expand Up @@ -66,5 +67,6 @@ 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
}
Loading