OLD | NEW |
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 "stack.h" | 8 #include "stack.h" |
9 | 9 |
10 extern SigTab runtime·sigtab[]; | 10 extern SigTab runtime·sigtab[]; |
11 | 11 |
12 static Sigset sigset_all = ~(Sigset)0; | 12 static Sigset sigset_all = ~(Sigset)0; |
13 static Sigset sigset_none; | 13 static Sigset sigset_none; |
| 14 static Sigset sigset_prof = 1<<(SIGPROF-1); |
14 | 15 |
15 static void | 16 static void |
16 unimplemented(int8 *name) | 17 unimplemented(int8 *name) |
17 { | 18 { |
18 runtime·prints(name); | 19 runtime·prints(name); |
19 runtime·prints(" not implemented\n"); | 20 runtime·prints(" not implemented\n"); |
20 *(int32*)1231 = 1231; | 21 *(int32*)1231 = 1231; |
21 } | 22 } |
22 | 23 |
23 int32 | 24 int32 |
24 runtime·semasleep(int64 ns) | 25 runtime·semasleep(int64 ns) |
25 { | 26 { |
26 » return runtime·mach_semacquire(m->waitsema, ns); | 27 » int32 v; |
| 28 |
| 29 » if(m->profilehz > 0) |
| 30 » » runtime·setprof(false); |
| 31 » v = runtime·mach_semacquire(m->waitsema, ns); |
| 32 » if(m->profilehz > 0) |
| 33 » » runtime·setprof(true); |
| 34 » return v; |
27 } | 35 } |
28 | 36 |
29 void | 37 void |
30 runtime·semawakeup(M *mp) | 38 runtime·semawakeup(M *mp) |
31 { | 39 { |
32 runtime·mach_semrelease(mp->waitsema); | 40 runtime·mach_semrelease(mp->waitsema); |
33 } | 41 } |
34 | 42 |
35 uintptr | 43 uintptr |
36 runtime·semacreate(void) | 44 runtime·semacreate(void) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 | 85 |
78 m->tls[0] = m->id; // so 386 asm can find it | 86 m->tls[0] = m->id; // so 386 asm can find it |
79 if(0){ | 87 if(0){ |
80 runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%
p\n", | 88 runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%
p\n", |
81 stk, m, g, fn, m->id, m->tls[0], &m); | 89 stk, m, g, fn, m->id, m->tls[0], &m); |
82 } | 90 } |
83 | 91 |
84 runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset); | 92 runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset); |
85 errno = runtime·bsdthread_create(stk, m, g, fn); | 93 errno = runtime·bsdthread_create(stk, m, g, fn); |
86 runtime·sigprocmask(SIG_SETMASK, &oset, nil); | 94 runtime·sigprocmask(SIG_SETMASK, &oset, nil); |
87 » | 95 |
88 if(errno < 0) { | 96 if(errno < 0) { |
89 runtime·printf("runtime: failed to create new OS thread (have %d
already; errno=%d)\n", runtime·mcount(), -errno); | 97 runtime·printf("runtime: failed to create new OS thread (have %d
already; errno=%d)\n", runtime·mcount(), -errno); |
90 runtime·throw("runtime.newosproc"); | 98 runtime·throw("runtime.newosproc"); |
91 } | 99 } |
92 } | 100 } |
93 | 101 |
94 // Called to initialize a new m (including the bootstrap m). | 102 // Called to initialize a new m (including the bootstrap m). |
95 void | 103 void |
96 runtime·minit(void) | 104 runtime·minit(void) |
97 { | 105 { |
98 // Initialize signal handling. | 106 // Initialize signal handling. |
99 m->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K | 107 m->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K |
100 runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024); | 108 runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024); |
101 » runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil); | 109 |
| 110 » if(m->profilehz > 0) |
| 111 » » runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil); |
| 112 » else |
| 113 » » runtime·sigprocmask(SIG_SETMASK, &sigset_prof, nil); |
102 } | 114 } |
103 | 115 |
104 // Mach IPC, to get at semaphores | 116 // Mach IPC, to get at semaphores |
105 // Definitions are in /usr/include/mach on a Mac. | 117 // Definitions are in /usr/include/mach on a Mac. |
106 | 118 |
107 static void | 119 static void |
108 macherror(int32 r, int8 *fn) | 120 macherror(int32 r, int8 *fn) |
109 { | 121 { |
110 runtime·printf("mach error %s: %d\n", fn, r); | 122 runtime·printf("mach error %s: %d\n", fn, r); |
111 runtime·throw("mach error"); | 123 runtime·throw("mach error"); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 | 439 |
428 uintptr | 440 uintptr |
429 runtime·memlimit(void) | 441 runtime·memlimit(void) |
430 { | 442 { |
431 // NOTE(rsc): Could use getrlimit here, | 443 // NOTE(rsc): Could use getrlimit here, |
432 // like on FreeBSD or Linux, but Darwin doesn't enforce | 444 // like on FreeBSD or Linux, but Darwin doesn't enforce |
433 // ulimit -v, so it's unclear why we'd try to stay within | 445 // ulimit -v, so it's unclear why we'd try to stay within |
434 // the limit. | 446 // the limit. |
435 return 0; | 447 return 0; |
436 } | 448 } |
| 449 |
| 450 // NOTE(rsc): On OS X, when the CPU profiling timer expires, the SIGPROF |
| 451 // signal is not guaranteed to be sent to the thread that was executing to |
| 452 // cause it to expire. It can and often does go to a sleeping thread, which is |
| 453 // not interesting for our profile. This is filed Apple Bug Report #9177434, |
| 454 // copied to http://code.google.com/p/go/source/detail?r=35b716c94225. |
| 455 // To work around this bug, we disable receipt of the profiling signal on |
| 456 // a thread while in blocking system calls. This forces the kernel to deliver |
| 457 // the profiling signal to an executing thread. |
| 458 // |
| 459 // The workaround fails on OS X machines using a 64-bit Snow Leopard kernel. |
| 460 // In that configuration, the kernel appears to want to deliver SIGPROF to the |
| 461 // sleeping threads regardless of signal mask and, worse, does not deliver |
| 462 // the signal until the thread wakes up on its own. |
| 463 // |
| 464 // If necessary, we can switch to using ITIMER_REAL for OS X and handle |
| 465 // the kernel-generated SIGALRM by generating our own SIGALRMs to deliver |
| 466 // to all the running threads. SIGALRM does not appear to be affected by |
| 467 // the 64-bit Snow Leopard bug. However, as of this writing Mountain Lion |
| 468 // is in preview, making Snow Leopard two versions old, so it is unclear how |
| 469 // much effort we need to spend on one buggy kernel. |
| 470 |
| 471 // Control whether profiling signal can be delivered to this thread. |
| 472 void |
| 473 runtime·setprof(bool on) |
| 474 { |
| 475 if(on) |
| 476 runtime·sigprocmask(SIG_UNBLOCK, &sigset_prof, nil); |
| 477 else |
| 478 runtime·sigprocmask(SIG_BLOCK, &sigset_prof, nil); |
| 479 } |
OLD | NEW |