diff options
Diffstat (limited to 'src/pkg/runtime/thread_linux.c')
-rw-r--r-- | src/pkg/runtime/thread_linux.c | 79 |
1 files changed, 47 insertions, 32 deletions
diff --git a/src/pkg/runtime/thread_linux.c b/src/pkg/runtime/thread_linux.c index 858be7036..78ddef878 100644 --- a/src/pkg/runtime/thread_linux.c +++ b/src/pkg/runtime/thread_linux.c @@ -13,8 +13,8 @@ int32 runtime·open(uint8*, int32, int32); int32 runtime·close(int32); int32 runtime·read(int32, void*, int32); -static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 }; static Sigset sigset_none; +static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 }; // Linux futex. // @@ -80,33 +80,23 @@ runtime·futexwakeup(uint32 *addr, uint32 cnt) *(int32*)0x1006 = 0x1006; } +extern runtime·sched_getaffinity(uintptr pid, uintptr len, uintptr *buf); static int32 getproccount(void) { - int32 fd, rd, cnt, cpustrlen; - byte *cpustr, *pos, *bufpos; - byte buf[256]; + uintptr buf[16], t; + int32 r, cnt, i; - fd = runtime·open((byte*)"/proc/stat", O_RDONLY|O_CLOEXEC, 0); - if(fd == -1) - return 1; cnt = 0; - bufpos = buf; - cpustr = (byte*)"\ncpu"; - cpustrlen = runtime·findnull(cpustr); - for(;;) { - rd = runtime·read(fd, bufpos, sizeof(buf)-cpustrlen); - if(rd == -1) - break; - bufpos[rd] = 0; - for(pos=buf; pos=runtime·strstr(pos, cpustr); cnt++, pos++) { - } - if(rd < cpustrlen) - break; - runtime·memmove(buf, bufpos+rd-cpustrlen+1, cpustrlen-1); - bufpos = buf+cpustrlen-1; + r = runtime·sched_getaffinity(0, sizeof(buf), buf); + if(r > 0) + for(i = 0; i < r/sizeof(buf[0]); i++) { + t = buf[i]; + t = t - ((t >> 1) & 0x5555555555555555ULL); + t = (t & 0x3333333333333333ULL) + ((t >> 2) & 0x3333333333333333ULL); + cnt += (int32)((((t + (t >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56); } - runtime·close(fd); + return cnt ? cnt : 1; } @@ -134,7 +124,7 @@ enum }; void -runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) +runtime·newosproc(M *mp, void *stk) { int32 ret; int32 flags; @@ -150,16 +140,16 @@ runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) | CLONE_THREAD /* revisit - okay for now */ ; - m->tls[0] = m->id; // so 386 asm can find it + mp->tls[0] = mp->id; // so 386 asm can find it if(0){ - runtime·printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n", - stk, m, g, fn, runtime·clone, m->id, m->tls[0], &m); + runtime·printf("newosproc stk=%p m=%p g=%p clone=%p id=%d/%d ostk=%p\n", + stk, mp, mp->g0, runtime·clone, mp->id, (int32)mp->tls[0], &mp); } // Disable signals during clone, so that the new thread starts // with signals disabled. It will enable them in minit. runtime·rtsigprocmask(SIG_SETMASK, &sigset_all, &oset, sizeof oset); - ret = runtime·clone(flags, stk, m, g, fn); + ret = runtime·clone(flags, stk, mp, mp->g0, runtime·mstart); runtime·rtsigprocmask(SIG_SETMASK, &oset, nil, sizeof oset); if(ret < 0) { @@ -181,13 +171,28 @@ runtime·goenvs(void) } // Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +void +runtime·mpreinit(M *mp) +{ + mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. void runtime·minit(void) { // Initialize signal handling. - m->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K - runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024); - runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none); + runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024); + runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof(Sigset)); +} + +// Called from dropm to undo the effect of an minit. +void +runtime·unminit(void) +{ + runtime·signalstack(nil, 0); } void @@ -266,12 +271,22 @@ runtime·badcallback(void) runtime·write(2, badcallback, sizeof badcallback - 1); } -static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n"; +static int8 badsignal[] = "runtime: signal received on thread not created by Go: "; // This runs on a foreign stack, without an m or a g. No stack split. #pragma textflag 7 void -runtime·badsignal(void) +runtime·badsignal(int32 sig) { + if (sig == SIGPROF) { + return; // Ignore SIGPROFs intended for a non-Go thread. + } runtime·write(2, badsignal, sizeof badsignal - 1); + if (0 <= sig && sig < NSIG) { + // Call runtime·findnull dynamically to circumvent static stack size check. + static int32 (*findnull)(byte*) = runtime·findnull; + runtime·write(2, runtime·sigtab[sig].name, findnull((byte*)runtime·sigtab[sig].name)); + } + runtime·write(2, "\n", 1); + runtime·exit(1); } |