diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-03-04 21:27:36 +0100 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2013-03-04 21:27:36 +0100 |
commit | 04b08da9af0c450d645ab7389d1467308cfc2db8 (patch) | |
tree | db247935fa4f2f94408edc3acd5d0d4f997aa0d8 /src/pkg/runtime/thread_plan9.c | |
parent | 917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff) | |
download | golang-upstream/1.1_hg20130304.tar.gz |
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'src/pkg/runtime/thread_plan9.c')
-rw-r--r-- | src/pkg/runtime/thread_plan9.c | 222 |
1 files changed, 143 insertions, 79 deletions
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/thread_plan9.c index 3b0dca69f..7f94623e7 100644 --- a/src/pkg/runtime/thread_plan9.c +++ b/src/pkg/runtime/thread_plan9.c @@ -7,12 +7,37 @@ #include "arch_GOARCH.h" int8 *goos = "plan9"; +extern SigTab runtime·sigtab[]; +int32 runtime·postnote(int32, int8*); + +// 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) +{ + // Initialize stack and goroutine for note handling. + mp->gsignal = runtime·malg(32*1024); + mp->notesig = (int8*)runtime·malloc(ERRMAX*sizeof(int8)); +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. void runtime·minit(void) { + // Mask all SSE floating-point exceptions + // when running on the 64-bit kernel. + runtime·setfpmasks(); +} + +// Called from dropm to undo the effect of an minit. +void +runtime·unminit(void) +{ } + static int32 getproccount(void) { @@ -36,10 +61,30 @@ getproccount(void) return ncpu > 0 ? ncpu : 1; } +static int32 +getpid(void) +{ + byte b[20], *c; + int32 fd; + + runtime·memclr(b, sizeof(b)); + fd = runtime·open((byte*)"#c/pid", 0); + if(fd >= 0) { + runtime·read(fd, b, sizeof(b)); + runtime·close(fd); + } + c = b; + while(*c == ' ' || *c == '\t') + c++; + return runtime·atoi(c); +} + void runtime·osinit(void) { runtime·ncpu = getproccount(); + m->procid = getpid(); + runtime·notify(runtime·sigtramp); } void @@ -52,6 +97,7 @@ runtime·initsig(void) { } +#pragma textflag 7 void runtime·osyield(void) { @@ -69,34 +115,6 @@ runtime·usleep(uint32 µs) runtime·sleep(ms); } -int64 -runtime·nanotime(void) -{ - static int32 fd = -1; - byte b[8]; - uint32 hi, lo; - - // As long as all goroutines share the same file - // descriptor table we can get away with using - // just a static fd. Without a lock the file can - // be opened twice but that's okay. - // - // Using /dev/bintime gives us a latency on the - // order of ten microseconds between two calls. - // - // The naïve implementation (without the cached - // file descriptor) is roughly four times slower - // in 9vx on a 2.16 GHz Intel Core 2 Duo. - - if(fd < 0 && (fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC)) < 0) - return 0; - if(runtime·pread(fd, b, sizeof b, 0) != sizeof b) - return 0; - hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3]; - lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]; - return (int64)hi<<32 | (int64)lo; -} - void time·now(int64 sec, int32 nsec) { @@ -109,48 +127,111 @@ time·now(int64 sec, int32 nsec) FLUSH(&nsec); } -extern Tos *_tos; void -runtime·exit(int32) +runtime·itoa(int32 n, byte *p, uint32 len) { - int32 fd; + byte *q, c; + uint32 i; + + if(len <= 1) + return; + + runtime·memclr(p, len); + q = p; + + if(n==0) { + *q++ = '0'; + USED(q); + return; + } + if(n < 0) { + *q++ = '-'; + p++; + n = -n; + } + for(i=0; n > 0 && i < len; i++) { + *q++ = '0' + (n%10); + n = n/10; + } + for(q--; q >= p; ) { + c = *p; + *p++ = *q; + *q-- = c; + } +} + +void +runtime·goexitsall(int8 *status) +{ + M *mp; + int32 pid; + + pid = getpid(); + for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink) + if(mp->procid != pid) + runtime·postnote(mp->procid, status); +} + +int32 +runtime·postnote(int32 pid, int8* msg) +{ + int32 fd, len; uint8 buf[128]; uint8 tmp[16]; uint8 *p, *q; - int32 pid; runtime·memclr(buf, sizeof buf); - runtime·memclr(tmp, sizeof tmp); - pid = _tos->pid; - /* build path string /proc/pid/notepg */ - for(q=tmp; pid > 0;) { - *q++ = '0' + (pid%10); - pid = pid/10; - } + /* build path string /proc/pid/note */ + q = tmp; p = buf; + runtime·itoa(pid, tmp, sizeof tmp); runtime·memmove((void*)p, (void*)"/proc/", 6); - p += 6; - for(q--; q >= tmp;) - *p++ = *q--; - runtime·memmove((void*)p, (void*)"/notepg", 7); + for(p += 6; *p++ = *q++; ); + p--; + runtime·memmove((void*)p, (void*)"/note", 5); - /* post interrupt note */ fd = runtime·open(buf, OWRITE); - runtime·write(fd, "interrupt", 9); - runtime·exits(nil); + if(fd < 0) + return -1; + + len = runtime·findnull((byte*)msg); + if(runtime·write(fd, msg, len) != len) { + runtime·close(fd); + return -1; + } + runtime·close(fd); + return 0; } void -runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) +runtime·exit(int32 e) { - m->tls[0] = m->id; // so 386 asm can find it + byte tmp[16]; + int8 *status; + + if(e == 0) + status = ""; + else { + /* build error string */ + runtime·itoa(e, tmp, sizeof tmp); + status = (int8*)tmp; + } + + runtime·goexitsall(status); + runtime·exits(status); +} + +void +runtime·newosproc(M *mp, void *stk) +{ + mp->tls[0] = mp->id; // so 386 asm can find it if(0){ - runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n", - stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m); + runtime·printf("newosproc stk=%p m=%p g=%p rfork=%p id=%d/%d ostk=%p\n", + stk, mp, mp->g0, runtime·rfork, mp->id, (int32)mp->tls[0], &mp); } - if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0) + if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, mp, mp->g0, runtime·mstart) < 0) runtime·throw("newosproc: rfork failed"); } @@ -167,36 +248,18 @@ runtime·semasleep(int64 ns) int32 ms; if(ns >= 0) { - // TODO: Plan 9 needs a new system call, tsemacquire. - // The kernel implementation is the same as semacquire - // except with a tsleep and check for timeout. - // It would be great if the implementation returned the - // value that was added to the semaphore, so that on - // timeout the return value would be 0, on success 1. - // Then the error string does not have to be parsed - // to detect timeout. - // - // If a negative time indicates no timeout, then - // semacquire can be implemented (in the kernel) - // as tsemacquire(p, v, -1). - runtime·throw("semasleep: timed sleep not implemented on Plan 9"); - - /* - if(ns < 0) - ms = -1; - else if(ns/1000 > 0x7fffffffll) + if(ns/1000000 > 0x7fffffffll) ms = 0x7fffffff; else - ms = ns/1000; - ret = runtime·plan9_tsemacquire(&m->waitsemacount, 1, ms); + ms = ns/1000000; + ret = runtime·plan9_tsemacquire(&m->waitsemacount, ms); if(ret == 1) return 0; // success return -1; // timeout or interrupted - */ } while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) { - /* interrupted; try again */ + /* interrupted; try again (c.f. lock_sema.c) */ } return 0; // success } @@ -213,15 +276,15 @@ os·sigpipe(void) runtime·throw("too many writes on closed pipe"); } -/* - * placeholder - once notes are implemented, - * a signal generating a panic must appear as - * a call to this function for correct handling by - * traceback. - */ void runtime·sigpanic(void) { + if(g->sigpc == 0) + runtime·panicstring("call of nil func value"); + runtime·panicstring(m->notesig); + + if(g->sig == 1 || g->sig == 2) + runtime·throw("fault"); } int32 @@ -266,4 +329,5 @@ void runtime·badsignal(void) { runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL); + runtime·exits(badsignal); } |