~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 "runtime.h"
6
 
#include "defs_GOOS_GOARCH.h"
7
 
#include "os_GOOS.h"
8
 
#include "stack.h"
9
 
 
10
 
extern SigTab runtime·sigtab[];
11
 
 
12
 
int32 runtime·open(uint8*, int32, int32);
13
 
int32 runtime·close(int32);
14
 
int32 runtime·read(int32, void*, int32);
15
 
 
16
 
static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 };
17
 
static Sigset sigset_none;
18
 
 
19
 
// Linux futex.
20
 
//
21
 
//      futexsleep(uint32 *addr, uint32 val)
22
 
//      futexwakeup(uint32 *addr)
23
 
//
24
 
// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
25
 
// Futexwakeup wakes up threads sleeping on addr.
26
 
// Futexsleep is allowed to wake up spuriously.
27
 
 
28
 
enum
29
 
{
30
 
        FUTEX_WAIT = 0,
31
 
        FUTEX_WAKE = 1,
32
 
 
33
 
        EINTR = 4,
34
 
        EAGAIN = 11,
35
 
};
36
 
 
37
 
// Atomically,
38
 
//      if(*addr == val) sleep
39
 
// Might be woken up spuriously; that's allowed.
40
 
// Don't sleep longer than ns; ns < 0 means forever.
41
 
void
42
 
runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
43
 
{
44
 
        Timespec ts, *tsp;
45
 
 
46
 
        if(ns < 0)
47
 
                tsp = nil;
48
 
        else {
49
 
                ts.tv_sec = ns/1000000000LL;
50
 
                ts.tv_nsec = ns%1000000000LL;
51
 
                // Avoid overflow
52
 
                if(ts.tv_sec > 1<<30)
53
 
                        ts.tv_sec = 1<<30;
54
 
                tsp = &ts;
55
 
        }
56
 
 
57
 
        // Some Linux kernels have a bug where futex of
58
 
        // FUTEX_WAIT returns an internal error code
59
 
        // as an errno.  Libpthread ignores the return value
60
 
        // here, and so can we: as it says a few lines up,
61
 
        // spurious wakeups are allowed.
62
 
        runtime·futex(addr, FUTEX_WAIT, val, tsp, nil, 0);
63
 
}
64
 
 
65
 
// If any procs are sleeping on addr, wake up at most cnt.
66
 
void
67
 
runtime·futexwakeup(uint32 *addr, uint32 cnt)
68
 
{
69
 
        int64 ret;
70
 
 
71
 
        ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0);
72
 
 
73
 
        if(ret >= 0)
74
 
                return;
75
 
 
76
 
        // I don't know that futex wakeup can return
77
 
        // EAGAIN or EINTR, but if it does, it would be
78
 
        // safe to loop and call futex again.
79
 
        runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret);
80
 
        *(int32*)0x1006 = 0x1006;
81
 
}
82
 
 
83
 
static int32
84
 
getproccount(void)
85
 
{
86
 
        int32 fd, rd, cnt, cpustrlen;
87
 
        byte *cpustr, *pos, *bufpos;
88
 
        byte buf[256];
89
 
 
90
 
        fd = runtime·open((byte*)"/proc/stat", O_RDONLY|O_CLOEXEC, 0);
91
 
        if(fd == -1)
92
 
                return 1;
93
 
        cnt = 0;
94
 
        bufpos = buf;
95
 
        cpustr = (byte*)"\ncpu";
96
 
        cpustrlen = runtime·findnull(cpustr);
97
 
        for(;;) {
98
 
                rd = runtime·read(fd, bufpos, sizeof(buf)-cpustrlen);
99
 
                if(rd == -1)
100
 
                        break;
101
 
                bufpos[rd] = 0;
102
 
                for(pos=buf; pos=runtime·strstr(pos, cpustr); cnt++, pos++) {
103
 
                }
104
 
                if(rd < cpustrlen)
105
 
                        break;
106
 
                runtime·memmove(buf, bufpos+rd-cpustrlen+1, cpustrlen-1);
107
 
                bufpos = buf+cpustrlen-1;
108
 
        }
109
 
        runtime·close(fd);
110
 
        return cnt ? cnt : 1;
111
 
}
112
 
 
113
 
// Clone, the Linux rfork.
114
 
enum
115
 
{
116
 
        CLONE_VM = 0x100,
117
 
        CLONE_FS = 0x200,
118
 
        CLONE_FILES = 0x400,
119
 
        CLONE_SIGHAND = 0x800,
120
 
        CLONE_PTRACE = 0x2000,
121
 
        CLONE_VFORK = 0x4000,
122
 
        CLONE_PARENT = 0x8000,
123
 
        CLONE_THREAD = 0x10000,
124
 
        CLONE_NEWNS = 0x20000,
125
 
        CLONE_SYSVSEM = 0x40000,
126
 
        CLONE_SETTLS = 0x80000,
127
 
        CLONE_PARENT_SETTID = 0x100000,
128
 
        CLONE_CHILD_CLEARTID = 0x200000,
129
 
        CLONE_UNTRACED = 0x800000,
130
 
        CLONE_CHILD_SETTID = 0x1000000,
131
 
        CLONE_STOPPED = 0x2000000,
132
 
        CLONE_NEWUTS = 0x4000000,
133
 
        CLONE_NEWIPC = 0x8000000,
134
 
};
135
 
 
136
 
void
137
 
runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
138
 
{
139
 
        int32 ret;
140
 
        int32 flags;
141
 
        Sigset oset;
142
 
 
143
 
        /*
144
 
         * note: strace gets confused if we use CLONE_PTRACE here.
145
 
         */
146
 
        flags = CLONE_VM        /* share memory */
147
 
                | CLONE_FS      /* share cwd, etc */
148
 
                | CLONE_FILES   /* share fd table */
149
 
                | CLONE_SIGHAND /* share sig handler table */
150
 
                | CLONE_THREAD  /* revisit - okay for now */
151
 
                ;
152
 
 
153
 
        m->tls[0] = m->id;      // so 386 asm can find it
154
 
        if(0){
155
 
                runtime·printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n",
156
 
                        stk, m, g, fn, runtime·clone, m->id, m->tls[0], &m);
157
 
        }
158
 
 
159
 
        // Disable signals during clone, so that the new thread starts
160
 
        // with signals disabled.  It will enable them in minit.
161
 
        runtime·rtsigprocmask(SIG_SETMASK, &sigset_all, &oset, sizeof oset);
162
 
        ret = runtime·clone(flags, stk, m, g, fn);
163
 
        runtime·rtsigprocmask(SIG_SETMASK, &oset, nil, sizeof oset);
164
 
 
165
 
        if(ret < 0) {
166
 
                runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -ret);
167
 
                runtime·throw("runtime.newosproc");
168
 
        }
169
 
}
170
 
 
171
 
void
172
 
runtime·osinit(void)
173
 
{
174
 
        runtime·ncpu = getproccount();
175
 
}
176
 
 
177
 
void
178
 
runtime·goenvs(void)
179
 
{
180
 
        runtime·goenvs_unix();
181
 
}
182
 
 
183
 
// Called to initialize a new m (including the bootstrap m).
184
 
void
185
 
runtime·minit(void)
186
 
{
187
 
        // Initialize signal handling.
188
 
        m->gsignal = runtime·malg(32*1024);     // OS X wants >=8K, Linux >=2K
189
 
        runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
190
 
        runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none);
191
 
}
192
 
 
193
 
void
194
 
runtime·sigpanic(void)
195
 
{
196
 
        switch(g->sig) {
197
 
        case SIGBUS:
198
 
                if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
199
 
                        if(g->sigpc == 0)
200
 
                                runtime·panicstring("call of nil func value");
201
 
                        }
202
 
                        runtime·panicstring("invalid memory address or nil pointer dereference");
203
 
                runtime·printf("unexpected fault address %p\n", g->sigcode1);
204
 
                runtime·throw("fault");
205
 
        case SIGSEGV:
206
 
                if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
207
 
                        if(g->sigpc == 0)
208
 
                                runtime·panicstring("call of nil func value");
209
 
                        runtime·panicstring("invalid memory address or nil pointer dereference");
210
 
                }
211
 
                runtime·printf("unexpected fault address %p\n", g->sigcode1);
212
 
                runtime·throw("fault");
213
 
        case SIGFPE:
214
 
                switch(g->sigcode0) {
215
 
                case FPE_INTDIV:
216
 
                        runtime·panicstring("integer divide by zero");
217
 
                case FPE_INTOVF:
218
 
                        runtime·panicstring("integer overflow");
219
 
                }
220
 
                runtime·panicstring("floating point error");
221
 
        }
222
 
        runtime·panicstring(runtime·sigtab[g->sig].name);
223
 
}
224
 
 
225
 
uintptr
226
 
runtime·memlimit(void)
227
 
{
228
 
        Rlimit rl;
229
 
        extern byte text[], end[];
230
 
        uintptr used;
231
 
 
232
 
        if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
233
 
                return 0;
234
 
        if(rl.rlim_cur >= 0x7fffffff)
235
 
                return 0;
236
 
 
237
 
        // Estimate our VM footprint excluding the heap.
238
 
        // Not an exact science: use size of binary plus
239
 
        // some room for thread stacks.
240
 
        used = end - text + (64<<20);
241
 
        if(used >= rl.rlim_cur)
242
 
                return 0;
243
 
 
244
 
        // If there's not at least 16 MB left, we're probably
245
 
        // not going to be able to do much.  Treat as no limit.
246
 
        rl.rlim_cur -= used;
247
 
        if(rl.rlim_cur < (16<<20))
248
 
                return 0;
249
 
 
250
 
        return rl.rlim_cur - used;
251
 
}
252
 
 
253
 
void
254
 
runtime·setprof(bool on)
255
 
{
256
 
        USED(on);
257
 
}
258
 
 
259
 
static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
260
 
 
261
 
// This runs on a foreign stack, without an m or a g.  No stack split.
262
 
#pragma textflag 7
263
 
void
264
 
runtime·badcallback(void)
265
 
{
266
 
        runtime·write(2, badcallback, sizeof badcallback - 1);
267
 
}
268
 
 
269
 
static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
270
 
 
271
 
// This runs on a foreign stack, without an m or a g.  No stack split.
272
 
#pragma textflag 7
273
 
void
274
 
runtime·badsignal(void)
275
 
{
276
 
        runtime·write(2, badsignal, sizeof badsignal - 1);
277
 
}