LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "defs_GOOS_GOARCH.h" | 6 #include "defs_GOOS_GOARCH.h" |
7 #include "os_GOOS.h" | 7 #include "os_GOOS.h" |
8 #include "signal_unix.h" | 8 #include "signal_unix.h" |
9 #include "stack.h" | 9 #include "stack.h" |
10 #include "../../cmd/ld/textflag.h" | 10 #include "textflag.h" |
11 | 11 |
12 extern SigTab runtime·sigtab[]; | 12 extern SigTab runtime·sigtab[]; |
13 | 13 |
14 static Sigset sigset_none; | 14 static Sigset sigset_none; |
15 static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 }; | 15 static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 }; |
16 | 16 |
17 // Linux futex. | 17 // Linux futex. |
18 // | 18 // |
19 // futexsleep(uint32 *addr, uint32 val) | 19 // futexsleep(uint32 *addr, uint32 val) |
20 // futexwakeup(uint32 *addr) | 20 // futexwakeup(uint32 *addr) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 #ifdef _64BIT | 61 #ifdef _64BIT |
62 ts.tv_sec = ns / 1000000000LL; | 62 ts.tv_sec = ns / 1000000000LL; |
63 ts.tv_nsec = ns % 1000000000LL; | 63 ts.tv_nsec = ns % 1000000000LL; |
64 #else | 64 #else |
65 ts.tv_nsec = 0; | 65 ts.tv_nsec = 0; |
66 ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec); | 66 ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec); |
67 #endif | 67 #endif |
68 runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0); | 68 runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0); |
69 } | 69 } |
70 | 70 |
| 71 static void badfutexwakeup(void); |
| 72 |
71 // If any procs are sleeping on addr, wake up at most cnt. | 73 // If any procs are sleeping on addr, wake up at most cnt. |
| 74 #pragma textflag NOSPLIT |
72 void | 75 void |
73 runtime·futexwakeup(uint32 *addr, uint32 cnt) | 76 runtime·futexwakeup(uint32 *addr, uint32 cnt) |
74 { | 77 { |
75 int64 ret; | 78 int64 ret; |
| 79 void (*fn)(void); |
76 | 80 |
77 ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0); | 81 ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0); |
78 | |
79 if(ret >= 0) | 82 if(ret >= 0) |
80 return; | 83 return; |
81 | 84 |
82 // I don't know that futex wakeup can return | 85 // I don't know that futex wakeup can return |
83 // EAGAIN or EINTR, but if it does, it would be | 86 // EAGAIN or EINTR, but if it does, it would be |
84 // safe to loop and call futex again. | 87 // safe to loop and call futex again. |
| 88 g->m->ptrarg[0] = addr; |
| 89 g->m->scalararg[0] = (int32)ret; // truncated but fine |
| 90 fn = badfutexwakeup; |
| 91 if(g == g->m->gsignal) |
| 92 fn(); |
| 93 else |
| 94 runtime·onM(&fn); |
| 95 *(int32*)0x1006 = 0x1006; |
| 96 } |
| 97 |
| 98 static void |
| 99 badfutexwakeup(void) |
| 100 { |
| 101 void *addr; |
| 102 int64 ret; |
| 103 ········ |
| 104 addr = g->m->ptrarg[0]; |
| 105 ret = (int32)g->m->scalararg[0]; |
85 runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret); | 106 runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret); |
86 *(int32*)0x1006 = 0x1006; | |
87 } | 107 } |
88 | 108 |
89 extern runtime·sched_getaffinity(uintptr pid, uintptr len, uintptr *buf); | 109 extern runtime·sched_getaffinity(uintptr pid, uintptr len, uintptr *buf); |
90 static int32 | 110 static int32 |
91 getproccount(void) | 111 getproccount(void) |
92 { | 112 { |
93 uintptr buf[16], t; | 113 uintptr buf[16], t; |
94 int32 r, n, i; | 114 int32 r, n, i; |
95 | 115 |
96 r = runtime·sched_getaffinity(0, sizeof(buf), buf); | 116 r = runtime·sched_getaffinity(0, sizeof(buf), buf); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 runtime·osinit(void) | 191 runtime·osinit(void) |
172 { | 192 { |
173 runtime·ncpu = getproccount(); | 193 runtime·ncpu = getproccount(); |
174 } | 194 } |
175 | 195 |
176 // Random bytes initialized at startup. These come | 196 // Random bytes initialized at startup. These come |
177 // from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c). | 197 // from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c). |
178 byte* runtime·startup_random_data; | 198 byte* runtime·startup_random_data; |
179 uint32 runtime·startup_random_data_len; | 199 uint32 runtime·startup_random_data_len; |
180 | 200 |
| 201 #pragma textflag NOSPLIT |
181 void | 202 void |
182 runtime·get_random_data(byte **rnd, int32 *rnd_len) | 203 runtime·get_random_data(byte **rnd, int32 *rnd_len) |
183 { | 204 { |
184 if(runtime·startup_random_data != nil) { | 205 if(runtime·startup_random_data != nil) { |
185 *rnd = runtime·startup_random_data; | 206 *rnd = runtime·startup_random_data; |
186 *rnd_len = runtime·startup_random_data_len; | 207 *rnd_len = runtime·startup_random_data_len; |
187 } else { | 208 } else { |
188 #pragma dataflag NOPTR | 209 #pragma dataflag NOPTR |
189 static byte urandom_data[HashRandomBytes]; | 210 static byte urandom_data[HashRandomBytes]; |
190 int32 fd; | 211 int32 fd; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 } | 285 } |
265 runtime·panicstring("floating point error"); | 286 runtime·panicstring("floating point error"); |
266 } | 287 } |
267 runtime·panicstring(runtime·sigtab[g->sig].name); | 288 runtime·panicstring(runtime·sigtab[g->sig].name); |
268 } | 289 } |
269 | 290 |
270 uintptr | 291 uintptr |
271 runtime·memlimit(void) | 292 runtime·memlimit(void) |
272 { | 293 { |
273 Rlimit rl; | 294 Rlimit rl; |
274 » extern byte text[], end[]; | 295 » extern byte runtime·text[], runtime·end[]; |
275 uintptr used; | 296 uintptr used; |
276 | 297 |
277 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) | 298 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) |
278 return 0; | 299 return 0; |
279 if(rl.rlim_cur >= 0x7fffffff) | 300 if(rl.rlim_cur >= 0x7fffffff) |
280 return 0; | 301 return 0; |
281 | 302 |
282 // Estimate our VM footprint excluding the heap. | 303 // Estimate our VM footprint excluding the heap. |
283 // Not an exact science: use size of binary plus | 304 // Not an exact science: use size of binary plus |
284 // some room for thread stacks. | 305 // some room for thread stacks. |
285 » used = end - text + (64<<20); | 306 » used = runtime·end - runtime·text + (64<<20); |
286 if(used >= rl.rlim_cur) | 307 if(used >= rl.rlim_cur) |
287 return 0; | 308 return 0; |
288 | 309 |
289 // If there's not at least 16 MB left, we're probably | 310 // If there's not at least 16 MB left, we're probably |
290 // not going to be able to do much. Treat as no limit. | 311 // not going to be able to do much. Treat as no limit. |
291 rl.rlim_cur -= used; | 312 rl.rlim_cur -= used; |
292 if(rl.rlim_cur < (16<<20)) | 313 if(rl.rlim_cur < (16<<20)) |
293 return 0; | 314 return 0; |
294 | 315 |
295 return rl.rlim_cur - used; | 316 return rl.rlim_cur - used; |
296 } | 317 } |
297 | 318 |
298 #ifdef GOARCH_386 | 319 #ifdef GOARCH_386 |
299 #define sa_handler k_sa_handler | 320 #define sa_handler k_sa_handler |
300 #endif | 321 #endif |
301 | 322 |
302 /* | 323 /* |
303 * This assembler routine takes the args from registers, puts them on the stack, | 324 * This assembler routine takes the args from registers, puts them on the stack, |
304 * and calls sighandler(). | 325 * and calls sighandler(). |
305 */ | 326 */ |
306 extern void runtime·sigtramp(void); | 327 extern void runtime·sigtramp(void); |
307 extern void runtime·sigreturn(void); // calls rt_sigreturn, only used with SA
_RESTORER | 328 extern void runtime·sigreturn(void); // calls rt_sigreturn, only used with SA
_RESTORER |
308 | 329 |
309 void | 330 void |
310 runtime·setsig(int32 i, GoSighandler *fn, bool restart) | 331 runtime·setsig(int32 i, GoSighandler *fn, bool restart) |
311 { | 332 { |
312 » Sigaction sa; | 333 » SigactionT sa; |
313 | 334 |
314 runtime·memclr((byte*)&sa, sizeof sa); | 335 runtime·memclr((byte*)&sa, sizeof sa); |
315 sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER; | 336 sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER; |
316 if(restart) | 337 if(restart) |
317 sa.sa_flags |= SA_RESTART; | 338 sa.sa_flags |= SA_RESTART; |
318 sa.sa_mask = ~0ULL; | 339 sa.sa_mask = ~0ULL; |
319 // Although Linux manpage says "sa_restorer element is obsolete and | 340 // Although Linux manpage says "sa_restorer element is obsolete and |
320 // should not be used". x86_64 kernel requires it. Only use it on | 341 // should not be used". x86_64 kernel requires it. Only use it on |
321 // x86. | 342 // x86. |
322 #ifdef GOARCH_386 | 343 #ifdef GOARCH_386 |
323 sa.sa_restorer = (void*)runtime·sigreturn; | 344 sa.sa_restorer = (void*)runtime·sigreturn; |
324 #endif | 345 #endif |
325 #ifdef GOARCH_amd64 | 346 #ifdef GOARCH_amd64 |
326 sa.sa_restorer = (void*)runtime·sigreturn; | 347 sa.sa_restorer = (void*)runtime·sigreturn; |
327 #endif | 348 #endif |
328 if(fn == runtime·sighandler) | 349 if(fn == runtime·sighandler) |
329 fn = (void*)runtime·sigtramp; | 350 fn = (void*)runtime·sigtramp; |
330 sa.sa_handler = fn; | 351 sa.sa_handler = fn; |
331 // Qemu rejects rt_sigaction of SIGRTMAX (64). | 352 // Qemu rejects rt_sigaction of SIGRTMAX (64). |
332 if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0 && i != 64
) | 353 if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0 && i != 64
) |
333 runtime·throw("rt_sigaction failure"); | 354 runtime·throw("rt_sigaction failure"); |
334 } | 355 } |
335 | 356 |
336 GoSighandler* | 357 GoSighandler* |
337 runtime·getsig(int32 i) | 358 runtime·getsig(int32 i) |
338 { | 359 { |
339 » Sigaction sa; | 360 » SigactionT sa; |
340 | 361 |
341 runtime·memclr((byte*)&sa, sizeof sa); | 362 runtime·memclr((byte*)&sa, sizeof sa); |
342 if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0) | 363 if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0) |
343 runtime·throw("rt_sigaction read failure"); | 364 runtime·throw("rt_sigaction read failure"); |
344 if((void*)sa.sa_handler == runtime·sigtramp) | 365 if((void*)sa.sa_handler == runtime·sigtramp) |
345 return runtime·sighandler; | 366 return runtime·sighandler; |
346 return (void*)sa.sa_handler; | 367 return (void*)sa.sa_handler; |
347 } | 368 } |
348 | 369 |
349 void | 370 void |
350 runtime·signalstack(byte *p, int32 n) | 371 runtime·signalstack(byte *p, int32 n) |
351 { | 372 { |
352 » Sigaltstack st; | 373 » SigaltstackT st; |
353 | 374 |
354 st.ss_sp = p; | 375 st.ss_sp = p; |
355 st.ss_size = n; | 376 st.ss_size = n; |
356 st.ss_flags = 0; | 377 st.ss_flags = 0; |
357 if(p == nil) | 378 if(p == nil) |
358 st.ss_flags = SS_DISABLE; | 379 st.ss_flags = SS_DISABLE; |
359 runtime·sigaltstack(&st, nil); | 380 runtime·sigaltstack(&st, nil); |
360 } | 381 } |
361 | 382 |
362 void | 383 void |
363 runtime·unblocksignals(void) | 384 runtime·unblocksignals(void) |
364 { | 385 { |
365 runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none
); | 386 runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none
); |
366 } | 387 } |
LEFT | RIGHT |