| 12345678910111213141516171819202122232425262728293031323334353637 |
- // SPDX-License-Identifier: Apache-2.0
- // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
- //go:build !cgo && (darwin || freebsd || linux)
- package fakecgo
- import "unsafe"
- // _cgo_thread_start is split into three parts in cgo since only one part is system dependent (keep it here for easier handling)
- // _cgo_thread_start(ThreadStart *arg) (runtime/cgo/gcc_util.c)
- // This get's called instead of the go code for creating new threads
- // -> pthread_* stuff is used, so threads are setup correctly for C
- // If this is missing, TLS is only setup correctly on thread 1!
- // This function should be go:systemstack instead of go:nosplit (but that requires runtime)
- //
- //go:nosplit
- //go:norace
- func x_cgo_thread_start(arg *ThreadStart) {
- var ts *ThreadStart
- // Make our own copy that can persist after we return.
- // _cgo_tsan_acquire();
- ts = (*ThreadStart)(malloc(unsafe.Sizeof(*ts)))
- // _cgo_tsan_release();
- if ts == nil {
- println("fakecgo: out of memory in thread_start")
- abort()
- }
- // *ts = *arg would cause a writebarrier so copy using slices
- s1 := unsafe.Slice((*uintptr)(unsafe.Pointer(ts)), unsafe.Sizeof(*ts)/8)
- s2 := unsafe.Slice((*uintptr)(unsafe.Pointer(arg)), unsafe.Sizeof(*arg)/8)
- for i := range s2 {
- s1[i] = s2[i]
- }
- _cgo_sys_thread_start(ts) // OS-dependent half
- }
|