go_util.go 1.3 KB

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