cgo: support errno value as second return parameter

Making this work on all targets was interesting but there's now a test
in place to make sure this works on all targets that have the CGo test
enabled (which is almost all targets).
This commit is contained in:
Ayke van Laethem
2024-11-06 14:57:56 +01:00
committed by Ayke
parent 548fba82e6
commit 6593cf22fa
23 changed files with 263 additions and 16 deletions
+13
View File
@@ -86,3 +86,16 @@ func AdjustTimeOffset(offset int64) {
// TODO: do this atomically?
timeOffset += offset
}
// Picolibc is not configured to define its own errno value, instead it calls
// __errno_location.
// TODO: a global works well enough for now (same as errno on Linux with
// -scheduler=tasks), but this should ideally be a thread-local variable stored
// in task.Task.
// Especially when we add multicore support for microcontrollers.
var errno int32
//export __errno_location
func libc_errno_location() *int32 {
return &errno
}
+6 -6
View File
@@ -151,7 +151,7 @@ func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1 = uintptr(result)
if result == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
err = uintptr(*libc_errno_location())
}
return
}
@@ -161,7 +161,7 @@ func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1 = call_syscallX(fn, a1, a2, a3)
if int64(r1) == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
err = uintptr(*libc_errno_location())
}
return
}
@@ -171,7 +171,7 @@ func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1 = call_syscallX(fn, a1, a2, a3)
if r1 == 0 {
// Syscall returns a pointer on success, or NULL on failure.
err = uintptr(*libc___error())
err = uintptr(*libc_errno_location())
}
return
}
@@ -182,7 +182,7 @@ func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
r1 = uintptr(result)
if result == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
err = uintptr(*libc_errno_location())
}
return
}
@@ -192,7 +192,7 @@ func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
r1 = call_syscall6X(fn, a1, a2, a3, a4, a5, a6)
if int64(r1) == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
err = uintptr(*libc_errno_location())
}
return
}
@@ -216,7 +216,7 @@ func libc_getpagesize() int32
// }
//
//export __error
func libc___error() *int32
func libc_errno_location() *int32
//export tinygo_syscall
func call_syscall(fn, a1, a2, a3 uintptr) int32
+3
View File
@@ -113,3 +113,6 @@ func syscall_Getpagesize() int {
_GetSystemInfo(unsafe.Pointer(&info))
return int(info.dwpagesize)
}
//export _errno
func libc_errno_location() *int32
+5
View File
@@ -127,3 +127,8 @@ func write(fd uintptr, p unsafe.Pointer, n int32) int32 {
func getAuxv() []uintptr {
return nil
}
// Called from cgo to obtain the errno value.
func cgo_errno() uintptr {
return uintptr(*libc_errno_location())
}
+6
View File
@@ -313,3 +313,9 @@ func hardwareRand() (n uint64, ok bool) {
// TODO: see whether there is a RNG and use it.
return 0, false
}
func libc_errno_location() *int32 {
// CGo is unavailable, so this function should be unreachable.
runtimePanic("runtime: no cgo errno")
return nil
}
+5
View File
@@ -112,3 +112,8 @@ func hardwareRand() (n uint64, ok bool) {
//
//export arc4random
func libc_arc4random() uint32
// int *__errno_location(void);
//
//export __errno_location
func libc_errno_location() *int32
@@ -51,3 +51,9 @@ func procUnpin() {
func hardwareRand() (n uint64, ok bool) {
return 0, false
}
func libc_errno_location() *int32 {
// CGo is unavailable, so this function should be unreachable.
runtimePanic("runtime: no cgo errno")
return nil
}
+6
View File
@@ -81,3 +81,9 @@ func procUnpin() {
func hardwareRand() (n uint64, ok bool) {
return random.GetRandomU64(), true
}
func libc_errno_location() *int32 {
// CGo is unavailable, so this function should be unreachable.
runtimePanic("runtime: no cgo errno")
return nil
}