/cp
[official-gcc.git] / libgo / runtime / runtime.c
blob1a7c3c7219c146a04d595afdf5bed9cc1dc3bcc5
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.
5 #include <signal.h>
6 #include <unistd.h>
8 #include "config.h"
10 #include "runtime.h"
11 #include "array.h"
12 #include "go-panic.h"
14 // The GOTRACEBACK environment variable controls the
15 // behavior of a Go program that is crashing and exiting.
16 // GOTRACEBACK=0 suppress all tracebacks
17 // GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames
18 // GOTRACEBACK=2 show tracebacks including runtime frames
19 // GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc)
20 int32
21 runtime_gotraceback(bool *crash)
23 const byte *p;
25 if(crash != nil)
26 *crash = false;
27 p = runtime_getenv("GOTRACEBACK");
28 if(p == nil || p[0] == '\0')
29 return 1; // default is on
30 if(runtime_strcmp((const char *)p, "crash") == 0) {
31 if(crash != nil)
32 *crash = true;
33 return 2; // extra information
35 return runtime_atoi(p);
38 static int32 argc;
39 static byte** argv;
41 extern Slice os_Args __asm__ (GOSYM_PREFIX "os.Args");
42 extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs");
44 void (*runtime_sysargs)(int32, uint8**);
46 void
47 runtime_args(int32 c, byte **v)
49 argc = c;
50 argv = v;
51 if(runtime_sysargs != nil)
52 runtime_sysargs(c, v);
55 byte*
56 runtime_progname()
58 return argc == 0 ? nil : argv[0];
61 void
62 runtime_goargs(void)
64 String *s;
65 int32 i;
67 // for windows implementation see "os" package
68 if(Windows)
69 return;
71 s = runtime_malloc(argc*sizeof s[0]);
72 for(i=0; i<argc; i++)
73 s[i] = runtime_gostringnocopy((const byte*)argv[i]);
74 os_Args.__values = (void*)s;
75 os_Args.__count = argc;
76 os_Args.__capacity = argc;
79 void
80 runtime_goenvs_unix(void)
82 String *s;
83 int32 i, n;
85 for(n=0; argv[argc+1+n] != 0; n++)
88 s = runtime_malloc(n*sizeof s[0]);
89 for(i=0; i<n; i++)
90 s[i] = runtime_gostringnocopy(argv[argc+1+i]);
91 syscall_Envs.__values = (void*)s;
92 syscall_Envs.__count = n;
93 syscall_Envs.__capacity = n;
96 int32
97 runtime_atoi(const byte *p)
99 int32 n;
101 n = 0;
102 while('0' <= *p && *p <= '9')
103 n = n*10 + *p++ - '0';
104 return n;
107 static struct root_list runtime_roots =
108 { nil,
109 { { &syscall_Envs, sizeof syscall_Envs },
110 { &os_Args, sizeof os_Args },
111 { nil, 0 } },
114 static void
115 TestAtomic64(void)
117 uint64 z64, x64;
119 z64 = 42;
120 x64 = 0;
121 PREFETCH(&z64);
122 if(runtime_cas64(&z64, x64, 1))
123 runtime_throw("cas64 failed");
124 if(x64 != 0)
125 runtime_throw("cas64 failed");
126 x64 = 42;
127 if(!runtime_cas64(&z64, x64, 1))
128 runtime_throw("cas64 failed");
129 if(x64 != 42 || z64 != 1)
130 runtime_throw("cas64 failed");
131 if(runtime_atomicload64(&z64) != 1)
132 runtime_throw("load64 failed");
133 runtime_atomicstore64(&z64, (1ull<<40)+1);
134 if(runtime_atomicload64(&z64) != (1ull<<40)+1)
135 runtime_throw("store64 failed");
136 if(runtime_xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2)
137 runtime_throw("xadd64 failed");
138 if(runtime_atomicload64(&z64) != (2ull<<40)+2)
139 runtime_throw("xadd64 failed");
140 if(runtime_xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2)
141 runtime_throw("xchg64 failed");
142 if(runtime_atomicload64(&z64) != (3ull<<40)+3)
143 runtime_throw("xchg64 failed");
146 void
147 runtime_check(void)
149 __go_register_gc_roots(&runtime_roots);
151 TestAtomic64();
154 uint32
155 runtime_fastrand1(void)
157 M *m;
158 uint32 x;
160 m = runtime_m();
161 x = m->fastrand;
162 x += x;
163 if(x & 0x80000000L)
164 x ^= 0x88888eefUL;
165 m->fastrand = x;
166 return x;
169 int64
170 runtime_cputicks(void)
172 #if defined(__386__) || defined(__x86_64__)
173 uint32 low, high;
174 asm("rdtsc" : "=a" (low), "=d" (high));
175 return (int64)(((uint64)high << 32) | (uint64)low);
176 #else
177 // FIXME: implement for other processors.
178 return 0;
179 #endif
182 bool
183 runtime_showframe(String s, bool current)
185 static int32 traceback = -1;
187 if(current && runtime_m()->throwing > 0)
188 return 1;
189 if(traceback < 0)
190 traceback = runtime_gotraceback(nil);
191 return traceback > 1 || (__builtin_memchr(s.str, '.', s.len) != nil && __builtin_memcmp(s.str, "runtime.", 7) != 0);
194 static Lock ticksLock;
195 static int64 ticks;
197 int64
198 runtime_tickspersecond(void)
200 int64 res, t0, t1, c0, c1;
202 res = (int64)runtime_atomicload64((uint64*)&ticks);
203 if(res != 0)
204 return ticks;
205 runtime_lock(&ticksLock);
206 res = ticks;
207 if(res == 0) {
208 t0 = runtime_nanotime();
209 c0 = runtime_cputicks();
210 runtime_usleep(100*1000);
211 t1 = runtime_nanotime();
212 c1 = runtime_cputicks();
213 if(t1 == t0)
214 t1++;
215 res = (c1-c0)*1000*1000*1000/(t1-t0);
216 if(res == 0)
217 res++;
218 runtime_atomicstore64((uint64*)&ticks, res);
220 runtime_unlock(&ticksLock);
221 return res;
224 int64 runtime_pprof_runtime_cyclesPerSecond(void)
225 __asm__ (GOSYM_PREFIX "runtime_pprof.runtime_cyclesPerSecond");
227 int64
228 runtime_pprof_runtime_cyclesPerSecond(void)
230 return runtime_tickspersecond();
233 // Called to initialize a new m (including the bootstrap m).
234 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
235 void
236 runtime_mpreinit(M *mp)
238 mp->gsignal = runtime_malg(32*1024, &mp->gsignalstack, &mp->gsignalstacksize); // OS X wants >=8K, Linux >=2K
241 // Called to initialize a new m (including the bootstrap m).
242 // Called on the new thread, can not allocate memory.
243 void
244 runtime_minit(void)
246 M* m;
247 sigset_t sigs;
249 // Initialize signal handling.
250 m = runtime_m();
251 runtime_signalstack(m->gsignalstack, m->gsignalstacksize);
252 if (sigemptyset(&sigs) != 0)
253 runtime_throw("sigemptyset");
254 pthread_sigmask(SIG_SETMASK, &sigs, nil);
257 // Called from dropm to undo the effect of an minit.
258 void
259 runtime_unminit(void)
261 runtime_signalstack(nil, 0);
265 void
266 runtime_signalstack(byte *p, int32 n)
268 stack_t st;
270 st.ss_sp = p;
271 st.ss_size = n;
272 st.ss_flags = 0;
273 if(p == nil)
274 st.ss_flags = SS_DISABLE;
275 if(sigaltstack(&st, nil) < 0)
276 *(int *)0xf1 = 0xf1;
279 DebugVars runtime_debug;
281 static struct {
282 const char* name;
283 int32* value;
284 } dbgvar[] = {
285 {"gctrace", &runtime_debug.gctrace},
286 {"schedtrace", &runtime_debug.schedtrace},
287 {"scheddetail", &runtime_debug.scheddetail},
290 void
291 runtime_parsedebugvars(void)
293 const byte *p;
294 intgo i, n;
296 p = runtime_getenv("GODEBUG");
297 if(p == nil)
298 return;
299 for(;;) {
300 for(i=0; i<(intgo)nelem(dbgvar); i++) {
301 n = runtime_findnull((const byte*)dbgvar[i].name);
302 if(runtime_mcmp(p, dbgvar[i].name, n) == 0 && p[n] == '=')
303 *dbgvar[i].value = runtime_atoi(p+n+1);
305 p = (const byte *)runtime_strstr((const char *)p, ",");
306 if(p == nil)
307 break;
308 p++;
312 // Poor mans 64-bit division.
313 // This is a very special function, do not use it if you are not sure what you are doing.
314 // int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
315 // Handles overflow in a time-specific manner.
316 int32
317 runtime_timediv(int64 v, int32 div, int32 *rem)
319 int32 res, bit;
321 if(v >= (int64)div*0x7fffffffLL) {
322 if(rem != nil)
323 *rem = 0;
324 return 0x7fffffff;
326 res = 0;
327 for(bit = 30; bit >= 0; bit--) {
328 if(v >= ((int64)div<<bit)) {
329 v = v - ((int64)div<<bit);
330 res += 1<<bit;
333 if(rem != nil)
334 *rem = v;
335 return res;
338 // Setting the max stack size doesn't really do anything for gccgo.
340 uintptr runtime_maxstacksize = 1<<20; // enough until runtime.main sets it for real
342 intgo runtime_debug_setMaxStack(intgo)
343 __asm__ (GOSYM_PREFIX "runtime_debug.setMaxStack");
345 intgo
346 runtime_debug_setMaxStack(intgo in)
348 intgo out;
350 out = runtime_maxstacksize;
351 runtime_maxstacksize = in;
352 return out;