go_util.go raw

   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