fakecgo: C functions require nosplit (#295)
* fakecgo: C functions require nosplit fakecgo runs on systemstack so we shouldn't ever split the stack. Fixes #287
- commit
- a32290b73c0334609816e2b780b0afa13bcb0345
- author
- TotallyGamerJet · · 2025-01-06 14:47 UTC
- committer
- GitHub · · 2025-01-06 14:47 UTC
- parent
- ca651c3
- signature
- GPG Unverified
B5690EEEBB952194The key is unknown
5 files · +33 -5
M .github/workflows/test.yml +1 -1
| @@ -96,7 +96,7 @@ jobs: | |||
| 96 | 96 | # Compile without optimization to check potential stack overflow. | |
| 97 | 97 | # The option '-gcflags=all=-N -l' is often used at Visual Studio Code. | |
| 98 | 98 | # See also https://go.googlesource.com/vscode-go/+/HEAD/docs/debugging.md#launch. | |
| 99 | - | # TODO: CGO_ENABLED=0 might cause SEGV. Fix this issue. | |
| 99 | + | env CGO_ENABLED=0 go test "-gcflags=all=-N -l" -v ./... | |
| 100 | 100 | env CGO_ENABLED=1 go test "-gcflags=all=-N -l" -v ./... | |
| 101 | 101 | ||
| 102 | 102 | - name: go test (Linux arm64) | |
| @@ -96,7 +96,7 @@ jobs: | |||||
| 96 | # Compile without optimization to check potential stack overflow. | 96 | # Compile without optimization to check potential stack overflow. | ||
| 97 | # The option '-gcflags=all=-N -l' is often used at Visual Studio Code. | 97 | # The option '-gcflags=all=-N -l' is often used at Visual Studio Code. | ||
| 98 | # See also https://go.googlesource.com/vscode-go/+/HEAD/docs/debugging.md#launch. | 98 | # See also https://go.googlesource.com/vscode-go/+/HEAD/docs/debugging.md#launch. | ||
| 99 | - | # TODO: CGO_ENABLED=0 might cause SEGV. Fix this issue. | 99 | + | env CGO_ENABLED=0 go test "-gcflags=all=-N -l" -v ./... |
| 100 | env CGO_ENABLED=1 go test "-gcflags=all=-N -l" -v ./... | 100 | env CGO_ENABLED=1 go test "-gcflags=all=-N -l" -v ./... | ||
| 101 | 101 | ||||
| 102 | - name: go test (Linux arm64) | 102 | - name: go test (Linux arm64) | ||
M internal/fakecgo/gen.go +1 -0
| @@ -36,6 +36,7 @@ func setg_trampoline(setg uintptr, G uintptr) | |||
| 36 | 36 | func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr | |
| 37 | 37 | ||
| 38 | 38 | {{ range . -}} | |
| 39 | + | //go:nosplit | |
| 39 | 40 | func {{.Name}}( | |
| 40 | 41 | {{- range .Args -}} | |
| 41 | 42 | {{- if .Name -}} | |
| @@ -36,6 +36,7 @@ func setg_trampoline(setg uintptr, G uintptr) | |||||
| 36 | func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr | 36 | func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr | ||
| 37 | 37 | ||||
| 38 | {{ range . -}} | 38 | {{ range . -}} | ||
| 39 | + | //go:nosplit | |||
| 39 | func {{.Name}}( | 40 | func {{.Name}}( | ||
| 40 | {{- range .Args -}} | 41 | {{- range .Args -}} | ||
| 41 | {{- if .Name -}} | 42 | {{- if .Name -}} | ||
M internal/fakecgo/go_libinit.go +6 -3
| @@ -50,9 +50,11 @@ func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe | |||
| 50 | 50 | var err int | |
| 51 | 51 | ||
| 52 | 52 | for tries = 0; tries < 20; tries++ { | |
| 53 | - | err = int(pthread_create(thread, attr, pfn, unsafe.Pointer(arg))) | |
| 53 | + | // inlined this call because it ran out of stack when inlining was disabled | |
| 54 | + | err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0)) | |
| 54 | 55 | if err == 0 { | |
| 55 | - | pthread_detach(*thread) | |
| 56 | + | // inlined this call because it ran out of stack when inlining was disabled | |
| 57 | + | call5(pthread_detachABI0, uintptr(*thread), 0, 0, 0, 0) | |
| 56 | 58 | return 0 | |
| 57 | 59 | } | |
| 58 | 60 | if err != int(syscall.EAGAIN) { | |
| @@ -60,7 +62,8 @@ func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe | |||
| 60 | 62 | } | |
| 61 | 63 | ts.Sec = 0 | |
| 62 | 64 | ts.Nsec = (tries + 1) * 1000 * 1000 // Milliseconds. | |
| 63 | - | nanosleep(&ts, nil) | |
| 65 | + | // inlined this call because it ran out of stack when inlining was disabled | |
| 66 | + | call5(nanosleepABI0, uintptr(unsafe.Pointer(&ts)), 0, 0, 0, 0) | |
| 64 | 67 | } | |
| 65 | 68 | return int(syscall.EAGAIN) | |
| 66 | 69 | } | |
| @@ -50,9 +50,11 @@ func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe | |||||
| 50 | var err int | 50 | var err int | ||
| 51 | 51 | ||||
| 52 | for tries = 0; tries < 20; tries++ { | 52 | for tries = 0; tries < 20; tries++ { | ||
| 53 | - | err = int(pthread_create(thread, attr, pfn, unsafe.Pointer(arg))) | 53 | + | // inlined this call because it ran out of stack when inlining was disabled |
| 54 | + | err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0)) | |||
| 54 | if err == 0 { | 55 | if err == 0 { | ||
| 55 | - | pthread_detach(*thread) | 56 | + | // inlined this call because it ran out of stack when inlining was disabled |
| 57 | + | call5(pthread_detachABI0, uintptr(*thread), 0, 0, 0, 0) | |||
| 56 | return 0 | 58 | return 0 | ||
| 57 | } | 59 | } | ||
| 58 | if err != int(syscall.EAGAIN) { | 60 | if err != int(syscall.EAGAIN) { | ||
| @@ -60,7 +62,8 @@ func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe | |||||
| 60 | } | 62 | } | ||
| 61 | ts.Sec = 0 | 63 | ts.Sec = 0 | ||
| 62 | ts.Nsec = (tries + 1) * 1000 * 1000 // Milliseconds. | 64 | ts.Nsec = (tries + 1) * 1000 * 1000 // Milliseconds. | ||
| 63 | - | nanosleep(&ts, nil) | 65 | + | // inlined this call because it ran out of stack when inlining was disabled |
| 66 | + | call5(nanosleepABI0, uintptr(unsafe.Pointer(&ts)), 0, 0, 0, 0) | |||
| 64 | } | 67 | } | ||
| 65 | return int(syscall.EAGAIN) | 68 | return int(syscall.EAGAIN) | ||
| 66 | } | 69 | } | ||
M internal/fakecgo/libcgo.go +5 -1
| @@ -6,7 +6,11 @@ | |||
| 6 | 6 | package fakecgo | |
| 7 | 7 | ||
| 8 | 8 | type ( | |
| 9 | - | size_t uintptr | |
| 9 | + | size_t uintptr | |
| 10 | + | // Sources: | |
| 11 | + | // Darwin (32 bytes) - https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74 | |
| 12 | + | // FreeBSD (32 bytes) - https://github.com/DoctorWkt/xv6-freebsd/blob/d2a294c2a984baed27676068b15ed9a29b06ab6f/include/signal.h#L98C9-L98C21 | |
| 13 | + | // Linux (128 bytes) - https://github.com/torvalds/linux/blob/ab75170520d4964f3acf8bb1f91d34cbc650688e/arch/x86/include/asm/signal.h#L25 | |
| 10 | 14 | sigset_t [128]byte | |
| 11 | 15 | pthread_attr_t [64]byte | |
| 12 | 16 | pthread_t int | |
| @@ -6,7 +6,11 @@ | |||||
| 6 | package fakecgo | 6 | package fakecgo | ||
| 7 | 7 | ||||
| 8 | type ( | 8 | type ( | ||
| 9 | - | size_t uintptr | 9 | + | size_t uintptr |
| 10 | + | // Sources: | |||
| 11 | + | // Darwin (32 bytes) - https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74 | |||
| 12 | + | // FreeBSD (32 bytes) - https://github.com/DoctorWkt/xv6-freebsd/blob/d2a294c2a984baed27676068b15ed9a29b06ab6f/include/signal.h#L98C9-L98C21 | |||
| 13 | + | // Linux (128 bytes) - https://github.com/torvalds/linux/blob/ab75170520d4964f3acf8bb1f91d34cbc650688e/arch/x86/include/asm/signal.h#L25 | |||
| 10 | sigset_t [128]byte | 14 | sigset_t [128]byte | ||
| 11 | pthread_attr_t [64]byte | 15 | pthread_attr_t [64]byte | ||
| 12 | pthread_t int | 16 | pthread_t int | ||
M internal/fakecgo/symbols.go +20 -0
| @@ -18,84 +18,104 @@ func setg_trampoline(setg uintptr, G uintptr) | |||
| 18 | 18 | // call5 takes fn the C function and 5 arguments and calls the function with those arguments | |
| 19 | 19 | func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr | |
| 20 | 20 | ||
| 21 | + | //go:nosplit | |
| 21 | 22 | func malloc(size uintptr) unsafe.Pointer { | |
| 22 | 23 | ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0) | |
| 23 | 24 | // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer | |
| 24 | 25 | return *(*unsafe.Pointer)(unsafe.Pointer(&ret)) | |
| 25 | 26 | } | |
| 26 | 27 | ||
| 28 | + | //go:nosplit | |
| 27 | 29 | func free(ptr unsafe.Pointer) { | |
| 28 | 30 | call5(freeABI0, uintptr(ptr), 0, 0, 0, 0) | |
| 29 | 31 | } | |
| 30 | 32 | ||
| 33 | + | //go:nosplit | |
| 31 | 34 | func setenv(name *byte, value *byte, overwrite int32) int32 { | |
| 32 | 35 | return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0)) | |
| 33 | 36 | } | |
| 34 | 37 | ||
| 38 | + | //go:nosplit | |
| 35 | 39 | func unsetenv(name *byte) int32 { | |
| 36 | 40 | return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0)) | |
| 37 | 41 | } | |
| 38 | 42 | ||
| 43 | + | //go:nosplit | |
| 39 | 44 | func sigfillset(set *sigset_t) int32 { | |
| 40 | 45 | return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0)) | |
| 41 | 46 | } | |
| 42 | 47 | ||
| 48 | + | //go:nosplit | |
| 43 | 49 | func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 { | |
| 44 | 50 | return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0)) | |
| 45 | 51 | } | |
| 46 | 52 | ||
| 53 | + | //go:nosplit | |
| 47 | 54 | func abort() { | |
| 48 | 55 | call5(abortABI0, 0, 0, 0, 0, 0) | |
| 49 | 56 | } | |
| 50 | 57 | ||
| 58 | + | //go:nosplit | |
| 51 | 59 | func pthread_attr_init(attr *pthread_attr_t) int32 { | |
| 52 | 60 | return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | |
| 53 | 61 | } | |
| 54 | 62 | ||
| 63 | + | //go:nosplit | |
| 55 | 64 | func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 { | |
| 56 | 65 | return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0)) | |
| 57 | 66 | } | |
| 58 | 67 | ||
| 68 | + | //go:nosplit | |
| 59 | 69 | func pthread_detach(thread pthread_t) int32 { | |
| 60 | 70 | return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0)) | |
| 61 | 71 | } | |
| 62 | 72 | ||
| 73 | + | //go:nosplit | |
| 63 | 74 | func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 { | |
| 64 | 75 | return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0)) | |
| 65 | 76 | } | |
| 66 | 77 | ||
| 78 | + | //go:nosplit | |
| 67 | 79 | func pthread_self() pthread_t { | |
| 68 | 80 | return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0)) | |
| 69 | 81 | } | |
| 70 | 82 | ||
| 83 | + | //go:nosplit | |
| 71 | 84 | func pthread_get_stacksize_np(thread pthread_t) size_t { | |
| 72 | 85 | return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0)) | |
| 73 | 86 | } | |
| 74 | 87 | ||
| 88 | + | //go:nosplit | |
| 75 | 89 | func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { | |
| 76 | 90 | return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0)) | |
| 77 | 91 | } | |
| 78 | 92 | ||
| 93 | + | //go:nosplit | |
| 79 | 94 | func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 { | |
| 80 | 95 | return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0)) | |
| 81 | 96 | } | |
| 82 | 97 | ||
| 98 | + | //go:nosplit | |
| 83 | 99 | func pthread_attr_destroy(attr *pthread_attr_t) int32 { | |
| 84 | 100 | return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | |
| 85 | 101 | } | |
| 86 | 102 | ||
| 103 | + | //go:nosplit | |
| 87 | 104 | func pthread_mutex_lock(mutex *pthread_mutex_t) int32 { | |
| 88 | 105 | return int32(call5(pthread_mutex_lockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) | |
| 89 | 106 | } | |
| 90 | 107 | ||
| 108 | + | //go:nosplit | |
| 91 | 109 | func pthread_mutex_unlock(mutex *pthread_mutex_t) int32 { | |
| 92 | 110 | return int32(call5(pthread_mutex_unlockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) | |
| 93 | 111 | } | |
| 94 | 112 | ||
| 113 | + | //go:nosplit | |
| 95 | 114 | func pthread_cond_broadcast(cond *pthread_cond_t) int32 { | |
| 96 | 115 | return int32(call5(pthread_cond_broadcastABI0, uintptr(unsafe.Pointer(cond)), 0, 0, 0, 0)) | |
| 97 | 116 | } | |
| 98 | 117 | ||
| 118 | + | //go:nosplit | |
| 99 | 119 | func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 { | |
| 100 | 120 | return int32(call5(pthread_setspecificABI0, uintptr(key), uintptr(value), 0, 0, 0)) | |
| 101 | 121 | } | |
| @@ -18,84 +18,104 @@ func setg_trampoline(setg uintptr, G uintptr) | |||||
| 18 | // call5 takes fn the C function and 5 arguments and calls the function with those arguments | 18 | // call5 takes fn the C function and 5 arguments and calls the function with those arguments | ||
| 19 | func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr | 19 | func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr | ||
| 20 | 20 | ||||
| 21 | + | //go:nosplit | |||
| 21 | func malloc(size uintptr) unsafe.Pointer { | 22 | func malloc(size uintptr) unsafe.Pointer { | ||
| 22 | ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0) | 23 | ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0) | ||
| 23 | // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer | 24 | // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer | ||
| 24 | return *(*unsafe.Pointer)(unsafe.Pointer(&ret)) | 25 | return *(*unsafe.Pointer)(unsafe.Pointer(&ret)) | ||
| 25 | } | 26 | } | ||
| 26 | 27 | ||||
| 28 | + | //go:nosplit | |||
| 27 | func free(ptr unsafe.Pointer) { | 29 | func free(ptr unsafe.Pointer) { | ||
| 28 | call5(freeABI0, uintptr(ptr), 0, 0, 0, 0) | 30 | call5(freeABI0, uintptr(ptr), 0, 0, 0, 0) | ||
| 29 | } | 31 | } | ||
| 30 | 32 | ||||
| 33 | + | //go:nosplit | |||
| 31 | func setenv(name *byte, value *byte, overwrite int32) int32 { | 34 | func setenv(name *byte, value *byte, overwrite int32) int32 { | ||
| 32 | return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0)) | 35 | return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0)) | ||
| 33 | } | 36 | } | ||
| 34 | 37 | ||||
| 38 | + | //go:nosplit | |||
| 35 | func unsetenv(name *byte) int32 { | 39 | func unsetenv(name *byte) int32 { | ||
| 36 | return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0)) | 40 | return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0)) | ||
| 37 | } | 41 | } | ||
| 38 | 42 | ||||
| 43 | + | //go:nosplit | |||
| 39 | func sigfillset(set *sigset_t) int32 { | 44 | func sigfillset(set *sigset_t) int32 { | ||
| 40 | return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0)) | 45 | return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0)) | ||
| 41 | } | 46 | } | ||
| 42 | 47 | ||||
| 48 | + | //go:nosplit | |||
| 43 | func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 { | 49 | func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 { | ||
| 44 | return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0)) | 50 | return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0)) | ||
| 45 | } | 51 | } | ||
| 46 | 52 | ||||
| 53 | + | //go:nosplit | |||
| 47 | func abort() { | 54 | func abort() { | ||
| 48 | call5(abortABI0, 0, 0, 0, 0, 0) | 55 | call5(abortABI0, 0, 0, 0, 0, 0) | ||
| 49 | } | 56 | } | ||
| 50 | 57 | ||||
| 58 | + | //go:nosplit | |||
| 51 | func pthread_attr_init(attr *pthread_attr_t) int32 { | 59 | func pthread_attr_init(attr *pthread_attr_t) int32 { | ||
| 52 | return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | 60 | return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | ||
| 53 | } | 61 | } | ||
| 54 | 62 | ||||
| 63 | + | //go:nosplit | |||
| 55 | func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 { | 64 | func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 { | ||
| 56 | return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0)) | 65 | return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0)) | ||
| 57 | } | 66 | } | ||
| 58 | 67 | ||||
| 68 | + | //go:nosplit | |||
| 59 | func pthread_detach(thread pthread_t) int32 { | 69 | func pthread_detach(thread pthread_t) int32 { | ||
| 60 | return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0)) | 70 | return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0)) | ||
| 61 | } | 71 | } | ||
| 62 | 72 | ||||
| 73 | + | //go:nosplit | |||
| 63 | func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 { | 74 | func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 { | ||
| 64 | return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0)) | 75 | return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0)) | ||
| 65 | } | 76 | } | ||
| 66 | 77 | ||||
| 78 | + | //go:nosplit | |||
| 67 | func pthread_self() pthread_t { | 79 | func pthread_self() pthread_t { | ||
| 68 | return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0)) | 80 | return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0)) | ||
| 69 | } | 81 | } | ||
| 70 | 82 | ||||
| 83 | + | //go:nosplit | |||
| 71 | func pthread_get_stacksize_np(thread pthread_t) size_t { | 84 | func pthread_get_stacksize_np(thread pthread_t) size_t { | ||
| 72 | return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0)) | 85 | return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0)) | ||
| 73 | } | 86 | } | ||
| 74 | 87 | ||||
| 88 | + | //go:nosplit | |||
| 75 | func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { | 89 | func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { | ||
| 76 | return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0)) | 90 | return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0)) | ||
| 77 | } | 91 | } | ||
| 78 | 92 | ||||
| 93 | + | //go:nosplit | |||
| 79 | func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 { | 94 | func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 { | ||
| 80 | return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0)) | 95 | return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0)) | ||
| 81 | } | 96 | } | ||
| 82 | 97 | ||||
| 98 | + | //go:nosplit | |||
| 83 | func pthread_attr_destroy(attr *pthread_attr_t) int32 { | 99 | func pthread_attr_destroy(attr *pthread_attr_t) int32 { | ||
| 84 | return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | 100 | return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) | ||
| 85 | } | 101 | } | ||
| 86 | 102 | ||||
| 103 | + | //go:nosplit | |||
| 87 | func pthread_mutex_lock(mutex *pthread_mutex_t) int32 { | 104 | func pthread_mutex_lock(mutex *pthread_mutex_t) int32 { | ||
| 88 | return int32(call5(pthread_mutex_lockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) | 105 | return int32(call5(pthread_mutex_lockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) | ||
| 89 | } | 106 | } | ||
| 90 | 107 | ||||
| 108 | + | //go:nosplit | |||
| 91 | func pthread_mutex_unlock(mutex *pthread_mutex_t) int32 { | 109 | func pthread_mutex_unlock(mutex *pthread_mutex_t) int32 { | ||
| 92 | return int32(call5(pthread_mutex_unlockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) | 110 | return int32(call5(pthread_mutex_unlockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) | ||
| 93 | } | 111 | } | ||
| 94 | 112 | ||||
| 113 | + | //go:nosplit | |||
| 95 | func pthread_cond_broadcast(cond *pthread_cond_t) int32 { | 114 | func pthread_cond_broadcast(cond *pthread_cond_t) int32 { | ||
| 96 | return int32(call5(pthread_cond_broadcastABI0, uintptr(unsafe.Pointer(cond)), 0, 0, 0, 0)) | 115 | return int32(call5(pthread_cond_broadcastABI0, uintptr(unsafe.Pointer(cond)), 0, 0, 0, 0)) | ||
| 97 | } | 116 | } | ||
| 98 | 117 | ||||
| 118 | + | //go:nosplit | |||
| 99 | func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 { | 119 | func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 { | ||
| 100 | return int32(call5(pthread_setspecificABI0, uintptr(key), uintptr(value), 0, 0, 0)) | 120 | return int32(call5(pthread_setspecificABI0, uintptr(key), uintptr(value), 0, 0, 0)) | ||
| 101 | } | 121 | } | ||