Home | History | Annotate | Download | only in cgo
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 #include "libcgo.h"
      6 
      7 /* Stub for creating a new thread */
      8 void
      9 x_cgo_thread_start(ThreadStart *arg)
     10 {
     11 	ThreadStart *ts;
     12 
     13 	/* Make our own copy that can persist after we return. */
     14 	_cgo_tsan_acquire();
     15 	ts = malloc(sizeof *ts);
     16 	_cgo_tsan_release();
     17 	if(ts == nil) {
     18 		fprintf(stderr, "runtime/cgo: out of memory in thread_start\n");
     19 		abort();
     20 	}
     21 	*ts = *arg;
     22 
     23 	_cgo_sys_thread_start(ts);	/* OS-dependent half */
     24 }
     25 
     26 #ifndef CGO_TSAN
     27 void(* const _cgo_yield)() = NULL;
     28 #else
     29 
     30 #include <string.h>
     31 
     32 char x_cgo_yield_strncpy_src = 0;
     33 char x_cgo_yield_strncpy_dst = 0;
     34 size_t x_cgo_yield_strncpy_n = 0;
     35 
     36 /*
     37 Stub for allowing libc interceptors to execute.
     38 
     39 _cgo_yield is set to NULL if we do not expect libc interceptors to exist.
     40 */
     41 static void
     42 x_cgo_yield()
     43 {
     44 	/*
     45 	The libc function(s) we call here must form a no-op and include at least one
     46 	call that triggers TSAN to process pending asynchronous signals.
     47 
     48 	sleep(0) would be fine, but it's not portable C (so it would need more header
     49 	guards).
     50 	free(NULL) has a fast-path special case in TSAN, so it doesn't
     51 	trigger signal delivery.
     52 	free(malloc(0)) would work (triggering the interceptors in malloc), but
     53 	it also runs a bunch of user-supplied malloc hooks.
     54 
     55 	So we choose strncpy(_, _, 0): it requires an extra header,
     56 	but it's standard and should be very efficient.
     57 
     58 	GCC 7 has an unfortunate habit of optimizing out strncpy calls (see
     59 	https://golang.org/issue/21196), so the arguments here need to be global
     60 	variables with external linkage in order to ensure that the call traps all the
     61 	way down into libc.
     62 	*/
     63 	strncpy(&x_cgo_yield_strncpy_dst, &x_cgo_yield_strncpy_src,
     64 	        x_cgo_yield_strncpy_n);
     65 }
     66 
     67 void(* const _cgo_yield)() = &x_cgo_yield;
     68 
     69 #endif  /* GO_TSAN */
     70