~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/runtime/runtime.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
// license that can be found in the LICENSE file.
4
4
 
5
5
#include "runtime.h"
6
 
#include "stack.h"
 
6
#include "arch_GOARCH.h"
7
7
 
8
8
enum {
9
9
        maxround = sizeof(uintptr),
10
10
};
11
11
 
12
 
uint32  runtime·panicking;
13
 
void    (*runtime·destroylock)(Lock*);
14
 
 
15
12
/*
16
13
 * We assume that all architectures turn faults and the like
17
14
 * into apparent calls to runtime.sigpanic.  If we see a "call"
20
17
 */
21
18
void    runtime·sigpanic(void);
22
19
 
 
20
// The GOTRACEBACK environment variable controls the
 
21
// behavior of a Go program that is crashing and exiting.
 
22
//      GOTRACEBACK=0   suppress all tracebacks
 
23
//      GOTRACEBACK=1   default behavior - show tracebacks but exclude runtime frames
 
24
//      GOTRACEBACK=2   show tracebacks including runtime frames
 
25
//      GOTRACEBACK=crash   show tracebacks including runtime frames, then crash (core dump etc)
23
26
int32
24
 
runtime·gotraceback(void)
 
27
runtime·gotraceback(bool *crash)
25
28
{
26
29
        byte *p;
27
30
 
 
31
        if(crash != nil)
 
32
                *crash = false;
28
33
        p = runtime·getenv("GOTRACEBACK");
29
34
        if(p == nil || p[0] == '\0')
30
35
                return 1;       // default is on
 
36
        if(runtime·strcmp(p, (byte*)"crash") == 0) {
 
37
                if(crash != nil)
 
38
                        *crash = true;
 
39
                return 2;       // extra information
 
40
        }
31
41
        return runtime·atoi(p);
32
42
}
33
43
 
34
 
static Lock paniclk;
35
 
 
36
 
void
37
 
runtime·startpanic(void)
38
 
{
39
 
        if(m->dying) {
40
 
                runtime·printf("panic during panic\n");
41
 
                runtime·exit(3);
42
 
        }
43
 
        m->dying = 1;
44
 
        runtime·xadd(&runtime·panicking, 1);
45
 
        runtime·lock(&paniclk);
46
 
}
47
 
 
48
 
void
49
 
runtime·dopanic(int32 unused)
50
 
{
51
 
        static bool didothers;
52
 
 
53
 
        if(g->sig != 0)
54
 
                runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
55
 
                        g->sig, g->sigcode0, g->sigcode1, g->sigpc);
56
 
 
57
 
        if(runtime·gotraceback()){
58
 
                if(g != m->g0) {
59
 
                        runtime·printf("\n");
60
 
                        runtime·goroutineheader(g);
61
 
                        runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g);
62
 
                }
63
 
                if(!didothers) {
64
 
                        didothers = true;
65
 
                        runtime·tracebackothers(g);
66
 
                }
67
 
        }
68
 
        runtime·unlock(&paniclk);
69
 
        if(runtime·xadd(&runtime·panicking, -1) != 0) {
70
 
                // Some other m is panicking too.
71
 
                // Let it print what it needs to print.
72
 
                // Wait forever without chewing up cpu.
73
 
                // It will exit when it's done.
74
 
                static Lock deadlock;
75
 
                runtime·lock(&deadlock);
76
 
                runtime·lock(&deadlock);
77
 
        }
78
 
 
79
 
        runtime·exit(2);
80
 
}
81
 
 
82
 
void
83
 
runtime·panicindex(void)
84
 
{
85
 
        runtime·panicstring("index out of range");
86
 
}
87
 
 
88
 
void
89
 
runtime·panicslice(void)
90
 
{
91
 
        runtime·panicstring("slice bounds out of range");
92
 
}
93
 
 
94
 
void
95
 
runtime·throwreturn(void)
96
 
{
97
 
        // can only happen if compiler is broken
98
 
        runtime·throw("no return at end of a typed function - compiler is broken");
99
 
}
100
 
 
101
 
void
102
 
runtime·throwinit(void)
103
 
{
104
 
        // can only happen with linker skew
105
 
        runtime·throw("recursive call during initialization - linker skew");
106
 
}
107
 
 
108
 
void
109
 
runtime·throw(int8 *s)
110
 
{
111
 
        runtime·startpanic();
112
 
        runtime·printf("throw: %s\n", s);
113
 
        runtime·dopanic(0);
114
 
        *(int32*)0 = 0; // not reached
115
 
        runtime·exit(1);        // even more not reached
116
 
}
117
 
 
118
 
void
119
 
runtime·panicstring(int8 *s)
120
 
{
121
 
        Eface err;
122
 
 
123
 
        if(m->gcing) {
124
 
                runtime·printf("panic: %s\n", s);
125
 
                runtime·throw("panic during gc");
126
 
        }
127
 
        runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err);
128
 
        runtime·panic(err);
129
 
}
130
 
 
131
44
int32
132
 
runtime·mcmp(byte *s1, byte *s2, uint32 n)
 
45
runtime·mcmp(byte *s1, byte *s2, uintptr n)
133
46
{
134
 
        uint32 i;
 
47
        uintptr i;
135
48
        byte c1, c2;
136
49
 
137
50
        for(i=0; i<n; i++) {
155
68
        return nil;
156
69
}
157
70
 
158
 
uint32
159
 
runtime·rnd(uint32 n, uint32 m)
160
 
{
161
 
        uint32 r;
162
 
 
163
 
        if(m > maxround)
164
 
                m = maxround;
165
 
        r = n % m;
166
 
        if(r)
167
 
                n += m-r;
168
 
        return n;
169
 
}
170
 
 
171
71
static int32    argc;
172
72
static uint8**  argv;
173
73
 
174
74
Slice os·Args;
175
75
Slice syscall·envs;
176
76
 
 
77
void (*runtime·sysargs)(int32, uint8**);
 
78
 
177
79
void
178
80
runtime·args(int32 c, uint8 **v)
179
81
{
180
82
        argc = c;
181
83
        argv = v;
 
84
        if(runtime·sysargs != nil)
 
85
                runtime·sysargs(c, v);
182
86
}
183
87
 
184
88
int32 runtime·isplan9;
185
89
int32 runtime·iswindows;
186
90
 
 
91
// Information about what cpu features are available.
 
92
// Set on startup in asm_{x86/amd64}.s.
 
93
uint32 runtime·cpuid_ecx;
 
94
uint32 runtime·cpuid_edx;
 
95
 
187
96
void
188
97
runtime·goargs(void)
189
98
{
219
128
        syscall·envs.cap = n;
220
129
}
221
130
 
222
 
byte*
223
 
runtime·getenv(int8 *s)
224
 
{
225
 
        int32 i, j, len;
226
 
        byte *v, *bs;
227
 
        String* envv;
228
 
        int32 envc;
229
 
 
230
 
        bs = (byte*)s;
231
 
        len = runtime·findnull(bs);
232
 
        envv = (String*)syscall·envs.array;
233
 
        envc = syscall·envs.len;
234
 
        for(i=0; i<envc; i++){
235
 
                if(envv[i].len <= len)
236
 
                        continue;
237
 
                v = envv[i].str;
238
 
                for(j=0; j<len; j++)
239
 
                        if(bs[j] != v[j])
240
 
                                goto nomatch;
241
 
                if(v[len] != '=')
242
 
                        goto nomatch;
243
 
                return v+len+1;
244
 
        nomatch:;
245
 
        }
246
 
        return nil;
247
 
}
248
 
 
249
131
void
250
132
runtime·getgoroot(String out)
251
133
{
267
149
        return n;
268
150
}
269
151
 
 
152
static void
 
153
TestAtomic64(void)
 
154
{
 
155
        uint64 z64, x64;
 
156
 
 
157
        z64 = 42;
 
158
        x64 = 0;
 
159
        PREFETCH(&z64);
 
160
        if(runtime·cas64(&z64, &x64, 1))
 
161
                runtime·throw("cas64 failed");
 
162
        if(x64 != 42)
 
163
                runtime·throw("cas64 failed");
 
164
        if(!runtime·cas64(&z64, &x64, 1))
 
165
                runtime·throw("cas64 failed");
 
166
        if(x64 != 42 || z64 != 1)
 
167
                runtime·throw("cas64 failed");
 
168
        if(runtime·atomicload64(&z64) != 1)
 
169
                runtime·throw("load64 failed");
 
170
        runtime·atomicstore64(&z64, (1ull<<40)+1);
 
171
        if(runtime·atomicload64(&z64) != (1ull<<40)+1)
 
172
                runtime·throw("store64 failed");
 
173
        if(runtime·xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2)
 
174
                runtime·throw("xadd64 failed");
 
175
        if(runtime·atomicload64(&z64) != (2ull<<40)+2)
 
176
                runtime·throw("xadd64 failed");
 
177
        if(runtime·xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2)
 
178
                runtime·throw("xchg64 failed");
 
179
        if(runtime·atomicload64(&z64) != (3ull<<40)+3)
 
180
                runtime·throw("xchg64 failed");
 
181
}
 
182
 
270
183
void
271
184
runtime·check(void)
272
185
{
342
255
                runtime·throw("float32nan2");
343
256
        if(!(i != i1))
344
257
                runtime·throw("float32nan3");
 
258
 
 
259
        TestAtomic64();
345
260
}
346
261
 
347
262
void
348
 
runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
 
263
runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool retbool)
349
264
{
350
265
        Func *f, *g;
351
266
        uintptr pc;
382
297
}
383
298
 
384
299
void
385
 
runtime·Callers(int32 skip, Slice pc, int32 retn)
 
300
runtime·Callers(intgo skip, Slice pc, intgo retn)
386
301
{
387
302
        // runtime.callers uses pc.array==nil as a signal
388
303
        // to print a stack trace.  Pick off 0-length pc here
413
328
        m->fastrand = x;
414
329
        return x;
415
330
}
 
331
 
 
332
static Lock ticksLock;
 
333
static int64 ticks;
 
334
 
 
335
int64
 
336
runtime·tickspersecond(void)
 
337
{
 
338
        int64 res, t0, t1, c0, c1;
 
339
 
 
340
        res = (int64)runtime·atomicload64((uint64*)&ticks);
 
341
        if(res != 0)
 
342
                return ticks;
 
343
        runtime·lock(&ticksLock);
 
344
        res = ticks;
 
345
        if(res == 0) {
 
346
                t0 = runtime·nanotime();
 
347
                c0 = runtime·cputicks();
 
348
                runtime·usleep(100*1000);
 
349
                t1 = runtime·nanotime();
 
350
                c1 = runtime·cputicks();
 
351
                if(t1 == t0)
 
352
                        t1++;
 
353
                res = (c1-c0)*1000*1000*1000/(t1-t0);
 
354
                if(res == 0)
 
355
                        res++;
 
356
                runtime·atomicstore64((uint64*)&ticks, res);
 
357
        }
 
358
        runtime·unlock(&ticksLock);
 
359
        return res;
 
360
}
 
361
 
 
362
void
 
363
runtime∕pprof·runtime_cyclesPerSecond(int64 res)
 
364
{
 
365
        res = runtime·tickspersecond();
 
366
        FLUSH(&res);
 
367
}