1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 4 //go:build !cgo && (darwin || freebsd || linux || netbsd)
5 6 package fakecgo
7 8 import "unsafe"
9 10 // _cgo_thread_start is split into three parts in cgo since only one part is system dependent (keep it here for easier handling)
11 12 // _cgo_thread_start(ThreadStart *arg) (runtime/cgo/gcc_util.c)
13 // This get's called instead of the go code for creating new threads
14 // -> pthread_* stuff is used, so threads are setup correctly for C
15 // If this is missing, TLS is only setup correctly on thread 1!
16 // This function should be go:systemstack instead of go:nosplit (but that requires runtime)
17 //
18 //go:nosplit
19 //go:norace
20 func x_cgo_thread_start(arg *ThreadStart) {
21 var ts *ThreadStart
22 // Make our own copy that can persist after we return.
23 // _cgo_tsan_acquire();
24 ts = (*ThreadStart)(malloc(unsafe.Sizeof(*ts)))
25 // _cgo_tsan_release();
26 if ts == nil {
27 println("fakecgo: out of memory in thread_start")
28 abort()
29 }
30 // *ts = *arg would cause a writebarrier so copy using slices
31 s1 := unsafe.Slice((*uintptr)(unsafe.Pointer(ts)), unsafe.Sizeof(*ts)/8)
32 s2 := unsafe.Slice((*uintptr)(unsafe.Pointer(arg)), unsafe.Sizeof(*arg)/8)
33 for i := range s2 {
34 s1[i] = s2[i]
35 }
36 _cgo_sys_thread_start(ts) // OS-dependent half
37 }
38