OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / runtime.c
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 <unistd.h>
6
7 #include "runtime.h"
8 #include "array.h"
9 #include "go-panic.h"
10 #include "go-string.h"
11
12 uint32  runtime_panicking;
13
14 int32
15 runtime_gotraceback(void)
16 {
17         const byte *p;
18
19         p = runtime_getenv("GOTRACEBACK");
20         if(p == nil || p[0] == '\0')
21                 return 1;       // default is on
22         return runtime_atoi(p);
23 }
24
25 static Lock paniclk;
26
27 void
28 runtime_startpanic(void)
29 {
30         M *m;
31
32         m = runtime_m();
33         if(m->dying) {
34                 runtime_printf("panic during panic\n");
35                 runtime_exit(3);
36         }
37         m->dying = 1;
38         runtime_xadd(&runtime_panicking, 1);
39         runtime_lock(&paniclk);
40 }
41
42 void
43 runtime_dopanic(int32 unused __attribute__ ((unused)))
44 {
45         G* g;
46         static bool didothers;
47
48         g = runtime_g();
49         if(g->sig != 0)
50                 runtime_printf("[signal %x code=%p addr=%p]\n",
51                         g->sig, (void*)(g->sigcode0), (void*)(g->sigcode1));
52
53         if(runtime_gotraceback()){
54                 if(g != runtime_m()->g0) {
55                         runtime_printf("\n");
56                         runtime_goroutineheader(g);
57                         runtime_traceback();
58                         runtime_goroutinetrailer(g);
59                 }
60                 if(!didothers) {
61                         didothers = true;
62                         runtime_tracebackothers(g);
63                 }
64         }
65
66         runtime_unlock(&paniclk);
67         if(runtime_xadd(&runtime_panicking, -1) != 0) {
68                 // Some other m is panicking too.
69                 // Let it print what it needs to print.
70                 // Wait forever without chewing up cpu.
71                 // It will exit when it's done.
72                 static Lock deadlock;
73                 runtime_lock(&deadlock);
74                 runtime_lock(&deadlock);
75         }
76
77         runtime_exit(2);
78 }
79
80 void
81 runtime_throw(const char *s)
82 {
83         runtime_startpanic();
84         runtime_printf("throw: %s\n", s);
85         runtime_dopanic(0);
86         *(int32*)0 = 0; // not reached
87         runtime_exit(1);        // even more not reached
88 }
89
90 void
91 runtime_panicstring(const char *s)
92 {
93         Eface err;
94
95         if(runtime_m()->gcing) {
96                 runtime_printf("panic: %s\n", s);
97                 runtime_throw("panic during gc");
98         }
99         runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err);
100         runtime_panic(err);
101 }
102
103 static int32    argc;
104 static byte**   argv;
105
106 extern Slice os_Args asm ("os.Args");
107 extern Slice syscall_Envs asm ("syscall.Envs");
108
109 void (*runtime_sysargs)(int32, uint8**);
110
111 void
112 runtime_args(int32 c, byte **v)
113 {
114         argc = c;
115         argv = v;
116         if(runtime_sysargs != nil)
117                 runtime_sysargs(c, v);
118 }
119
120 void
121 runtime_goargs(void)
122 {
123         String *s;
124         int32 i;
125
126         // for windows implementation see "os" package
127         if(Windows)
128                 return;
129
130         s = runtime_malloc(argc*sizeof s[0]);
131         for(i=0; i<argc; i++)
132                 s[i] = runtime_gostringnocopy((const byte*)argv[i]);
133         os_Args.__values = (void*)s;
134         os_Args.__count = argc;
135         os_Args.__capacity = argc;
136 }
137
138 void
139 runtime_goenvs_unix(void)
140 {
141         String *s;
142         int32 i, n;
143
144         for(n=0; argv[argc+1+n] != 0; n++)
145                 ;
146
147         s = runtime_malloc(n*sizeof s[0]);
148         for(i=0; i<n; i++)
149                 s[i] = runtime_gostringnocopy(argv[argc+1+i]);
150         syscall_Envs.__values = (void*)s;
151         syscall_Envs.__count = n;
152         syscall_Envs.__capacity = n;
153 }
154
155 const byte*
156 runtime_getenv(const char *s)
157 {
158         int32 i, j, len;
159         const byte *v, *bs;
160         String* envv;
161         int32 envc;
162
163         bs = (const byte*)s;
164         len = runtime_findnull(bs);
165         envv = (String*)syscall_Envs.__values;
166         envc = syscall_Envs.__count;
167         for(i=0; i<envc; i++){
168                 if(envv[i].__length <= len)
169                         continue;
170                 v = (const byte*)envv[i].__data;
171                 for(j=0; j<len; j++)
172                         if(bs[j] != v[j])
173                                 goto nomatch;
174                 if(v[len] != '=')
175                         goto nomatch;
176                 return v+len+1;
177         nomatch:;
178         }
179         return nil;
180 }
181
182 int32
183 runtime_atoi(const byte *p)
184 {
185         int32 n;
186
187         n = 0;
188         while('0' <= *p && *p <= '9')
189                 n = n*10 + *p++ - '0';
190         return n;
191 }
192
193 uint32
194 runtime_fastrand1(void)
195 {
196         M *m;
197         uint32 x;
198
199         m = runtime_m();
200         x = m->fastrand;
201         x += x;
202         if(x & 0x80000000L)
203                 x ^= 0x88888eefUL;
204         m->fastrand = x;
205         return x;
206 }
207
208 static struct root_list runtime_roots =
209 { nil,
210   { { &syscall_Envs, sizeof syscall_Envs },
211     { &os_Args, sizeof os_Args },
212     { nil, 0 } },
213 };
214
215 void
216 runtime_check(void)
217 {
218         __go_register_gc_roots(&runtime_roots);
219 }
220
221 int64
222 runtime_cputicks(void)
223 {
224 #if defined(__386__) || defined(__x86_64__)
225   uint32 low, high;
226   asm("rdtsc" : "=a" (low), "=d" (high));
227   return (int64)(((uint64)high << 32) | (uint64)low);
228 #else
229   // FIXME: implement for other processors.
230   return 0;
231 #endif
232 }
233
234 bool
235 runtime_showframe(const unsigned char *s)
236 {
237         static int32 traceback = -1;
238         
239         if(traceback < 0)
240                 traceback = runtime_gotraceback();
241         return traceback > 1 || (s != nil && __builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0);
242 }
243
244 bool
245 runtime_isInf(float64 f, int32 sign)
246 {
247         if(!__builtin_isinf(f))
248                 return false;
249         if(sign == 0)
250                 return true;
251         if(sign > 0)
252                 return f > 0;
253         return f < 0;
254 }