Text file
src/runtime/cgo/gcc_libinit_windows.c
1 // Copyright 2015 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 #ifdef __CYGWIN__
6 #error "don't use the cygwin compiler to build native Windows programs; use MinGW instead"
7 #endif
8
9 #define WIN32_LEAN_AND_MEAN
10 #include <windows.h>
11
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 #include "libcgo.h"
16
17 #define IMAGE_GUARD_SECURITY_COOKIE_UNUSED 0x00000800
18 // With modern mingw, we can use the normal struct:
19 //
20 // const IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
21 // .Size = sizeof(_load_config_used),
22 // .GuardFlags = IMAGE_GUARD_SECURITY_COOKIE_UNUSED
23 // };
24 //
25 // But we support older toolchains, so instead, fix the offsets:
26 #ifdef _WIN64
27 const ULONGLONG _load_config_used[40] = {
28 sizeof(_load_config_used),
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 IMAGE_GUARD_SECURITY_COOKIE_UNUSED
31 };
32 #else
33 const DWORD _load_config_used[48] = {
34 sizeof(_load_config_used),
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 IMAGE_GUARD_SECURITY_COOKIE_UNUSED
37 };
38 #endif
39
40 static volatile LONG runtime_init_once_gate = 0;
41 static volatile LONG runtime_init_once_done = 0;
42
43 static CRITICAL_SECTION runtime_init_cs;
44
45 static HANDLE runtime_init_wait;
46 static int runtime_init_done;
47
48 // No pthreads on Windows, these are always zero.
49 uintptr_t x_cgo_pthread_key_created;
50 void (*x_crosscall2_ptr)(void (*fn)(void *), void *, int, size_t);
51
52 // Pre-initialize the runtime synchronization objects
53 void
54 _cgo_preinit_init() {
55 runtime_init_wait = CreateEvent(NULL, TRUE, FALSE, NULL);
56 if (runtime_init_wait == NULL) {
57 fprintf(stderr, "runtime: failed to create runtime initialization wait event.\n");
58 abort();
59 }
60
61 InitializeCriticalSection(&runtime_init_cs);
62 }
63
64 // Make sure that the preinit sequence has run.
65 void
66 _cgo_maybe_run_preinit() {
67 if (!InterlockedExchangeAdd(&runtime_init_once_done, 0)) {
68 if (InterlockedIncrement(&runtime_init_once_gate) == 1) {
69 _cgo_preinit_init();
70 InterlockedIncrement(&runtime_init_once_done);
71 } else {
72 // Decrement to avoid overflow.
73 InterlockedDecrement(&runtime_init_once_gate);
74 while(!InterlockedExchangeAdd(&runtime_init_once_done, 0)) {
75 Sleep(0);
76 }
77 }
78 }
79 }
80
81 int
82 _cgo_is_runtime_initialized() {
83 int status;
84
85 EnterCriticalSection(&runtime_init_cs);
86 status = runtime_init_done;
87 LeaveCriticalSection(&runtime_init_cs);
88 return status;
89 }
90
91 uintptr_t
92 _cgo_wait_runtime_init_done(void) {
93 void (*pfn)(struct cgoContextArg*);
94
95 _cgo_maybe_run_preinit();
96 while (!_cgo_is_runtime_initialized()) {
97 WaitForSingleObject(runtime_init_wait, INFINITE);
98 }
99 pfn = _cgo_get_context_function();
100 if (pfn != nil) {
101 struct cgoContextArg arg;
102
103 arg.Context = 0;
104 (*pfn)(&arg);
105 return arg.Context;
106 }
107 return 0;
108 }
109
110 void
111 x_cgo_notify_runtime_init_done(void* dummy) {
112 _cgo_maybe_run_preinit();
113
114 EnterCriticalSection(&runtime_init_cs);
115 runtime_init_done = 1;
116 LeaveCriticalSection(&runtime_init_cs);
117
118 if (!SetEvent(runtime_init_wait)) {
119 fprintf(stderr, "runtime: failed to signal runtime initialization complete.\n");
120 abort();
121 }
122 }
123
124 // The traceback function, used when tracing C calls.
125 static void (*cgo_traceback_function)(struct cgoTracebackArg*);
126
127 // The context function, used when tracing back C calls into Go.
128 static void (*cgo_context_function)(struct cgoContextArg*);
129
130 // The symbolizer function, used when symbolizing C frames.
131 static void (*cgo_symbolizer_function)(struct cgoSymbolizerArg*);
132
133 // Sets the traceback, context, and symbolizer functions. Called from
134 // runtime.SetCgoTraceback.
135 void x_cgo_set_traceback_functions(struct cgoSetTracebackFunctionsArg* arg) {
136 EnterCriticalSection(&runtime_init_cs);
137 cgo_traceback_function = arg->Traceback;
138 cgo_context_function = arg->Context;
139 cgo_symbolizer_function = arg->Symbolizer;
140 LeaveCriticalSection(&runtime_init_cs);
141 }
142
143 // Gets the traceback function to call to trace C calls.
144 void (*(_cgo_get_traceback_function(void)))(struct cgoTracebackArg*) {
145 void (*ret)(struct cgoTracebackArg*);
146
147 EnterCriticalSection(&runtime_init_cs);
148 ret = cgo_traceback_function;
149 LeaveCriticalSection(&runtime_init_cs);
150 return ret;
151 }
152
153 // Call the traceback function registered with x_cgo_set_traceback_functions.
154 //
155 // On other platforms, this coordinates with C/C++ TSAN. On Windows, there is
156 // no C/C++ TSAN.
157 void x_cgo_call_traceback_function(struct cgoTracebackArg* arg) {
158 void (*pfn)(struct cgoTracebackArg*);
159
160 pfn = _cgo_get_traceback_function();
161 if (pfn == nil) {
162 return;
163 }
164
165 (*pfn)(arg);
166 }
167
168 // Gets the context function to call to record the traceback context
169 // when calling a Go function from C code.
170 void (*(_cgo_get_context_function(void)))(struct cgoContextArg*) {
171 void (*ret)(struct cgoContextArg*);
172
173 EnterCriticalSection(&runtime_init_cs);
174 ret = cgo_context_function;
175 LeaveCriticalSection(&runtime_init_cs);
176 return ret;
177 }
178
179 // Gets the symbolizer function to call to symbolize C frames.
180 void (*(_cgo_get_symbolizer_function(void)))(struct cgoSymbolizerArg*) {
181 void (*ret)(struct cgoSymbolizerArg*);
182
183 EnterCriticalSection(&runtime_init_cs);
184 ret = cgo_symbolizer_function;
185 LeaveCriticalSection(&runtime_init_cs);
186 return ret;
187 }
188
189 // Call the symbolizer function registered with x_cgo_set_symbolizer_functions.
190 //
191 // On other platforms, this coordinates with C/C++ TSAN. On Windows, there is
192 // no C/C++ TSAN.
193 void x_cgo_call_symbolizer_function(struct cgoSymbolizerArg* arg) {
194 void (*pfn)(struct cgoSymbolizerArg*);
195
196 pfn = _cgo_get_symbolizer_function();
197 if (pfn == nil) {
198 return;
199 }
200
201 (*pfn)(arg);
202 }
203
View as plain text