...
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 */
8void
9x_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
27void(* const _cgo_yield)() = NULL;
28#else
29
30#include <string.h>
31
32char x_cgo_yield_strncpy_src = 0;
33char x_cgo_yield_strncpy_dst = 0;
34size_t x_cgo_yield_strncpy_n = 0;
35
36/*
37Stub for allowing libc interceptors to execute.
38
39_cgo_yield is set to NULL if we do not expect libc interceptors to exist.
40*/
41static void
42x_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
67void(* const _cgo_yield)() = &x_cgo_yield;
68
69#endif /* GO_TSAN */
View as plain text