diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
commit | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch) | |
tree | c0650497e988f47be9c6f2324fa692a52dea82e1 /src/pkg/runtime/plan9 | |
parent | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff) | |
download | golang-upstream/60.tar.gz |
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/pkg/runtime/plan9')
-rw-r--r-- | src/pkg/runtime/plan9/386/defs.h | 2 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/386/rt0.s | 32 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/386/signal.c | 24 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/386/sys.s | 82 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/mem.c | 67 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/os.h | 57 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/signals.h | 1 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/thread.c | 174 |
8 files changed, 439 insertions, 0 deletions
diff --git a/src/pkg/runtime/plan9/386/defs.h b/src/pkg/runtime/plan9/386/defs.h new file mode 100644 index 000000000..58fd9d94d --- /dev/null +++ b/src/pkg/runtime/plan9/386/defs.h @@ -0,0 +1,2 @@ +// nothing to see here +#define tos_pid 48 diff --git a/src/pkg/runtime/plan9/386/rt0.s b/src/pkg/runtime/plan9/386/rt0.s new file mode 100644 index 000000000..b56c8b325 --- /dev/null +++ b/src/pkg/runtime/plan9/386/rt0.s @@ -0,0 +1,32 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +TEXT _rt0_386_plan9(SB),7, $0 + MOVL AX, _tos(SB) + + // move arguments down to make room for + // m and g at top of stack, right before Tos. + MOVL SP, SI + SUBL $8, SP + MOVL SP, DI + + MOVL AX, CX + SUBL SI, CX + CLD + REP; MOVSB + + // adjust argv + SUBL SI, DI + MOVL newargc+0(SP), CX + LEAL newargv+4(SP), BP +argv_fix: + ADDL DI, 0(BP) + ADDL $4, BP + LOOP argv_fix + + JMP _rt0_386(SB) + +DATA runtime·isplan9(SB)/4, $1 +GLOBL runtime·isplan9(SB), $4 +GLOBL _tos(SB), $4 diff --git a/src/pkg/runtime/plan9/386/signal.c b/src/pkg/runtime/plan9/386/signal.c new file mode 100644 index 000000000..364fd1c41 --- /dev/null +++ b/src/pkg/runtime/plan9/386/signal.c @@ -0,0 +1,24 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" + +void +runtime·gettime(int64*, int32*) +{ +} + +String +runtime·signame(int32) +{ + return runtime·emptystring; +} + +void +runtime·resetcpuprofiler(int32 hz) +{ + // TODO: Enable profiling interrupts. + + m->profilehz = hz; +} diff --git a/src/pkg/runtime/plan9/386/sys.s b/src/pkg/runtime/plan9/386/sys.s new file mode 100644 index 000000000..1cb570b68 --- /dev/null +++ b/src/pkg/runtime/plan9/386/sys.s @@ -0,0 +1,82 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "defs.h" +#include "386/asm.h" + +// setldt(int entry, int address, int limit) +TEXT runtime·setldt(SB),7,$0 + RET + +TEXT runtime·open(SB),7,$0 + MOVL $14, AX + INT $64 + RET + +TEXT runtime·write(SB),7,$0 + MOVL $20, AX + INT $64 + RET + +TEXT runtime·exits(SB),7,$0 + MOVL $8, AX + INT $64 + RET + +TEXT runtime·brk_(SB),7,$0 + MOVL $24, AX + INT $64 + RET + +TEXT runtime·plan9_semacquire(SB),7,$0 + MOVL $37, AX + INT $64 + RET + +TEXT runtime·plan9_semrelease(SB),7,$0 + MOVL $38, AX + INT $64 + RET + +TEXT runtime·rfork(SB),7,$0 + MOVL $19, AX // rfork + INT $64 + + // In parent, return. + CMPL AX, $0 + JEQ 2(PC) + RET + + // In child on old stack. + MOVL mm+12(SP), BX // m + MOVL gg+16(SP), DX // g + MOVL fn+20(SP), SI // fn + + // set SP to be on the new child stack + MOVL stack+8(SP), CX + MOVL CX, SP + + // Initialize m, g. + get_tls(AX) + MOVL DX, g(AX) + MOVL BX, m(AX) + + // Initialize AX from _tos->pid + MOVL _tos(SB), AX + MOVL tos_pid(AX), AX + MOVL AX, m_procid(BX) // save pid as m->procid + + CALL runtime·stackcheck(SB) // smashes AX, CX + + MOVL 0(DX), DX // paranoia; check they are not nil + MOVL 0(BX), BX + + // more paranoia; check that stack splitting code works + PUSHAL + CALL runtime·emptyfunc(SB) + POPAL + + CALL SI // fn() + CALL runtime·exit(SB) + RET diff --git a/src/pkg/runtime/plan9/mem.c b/src/pkg/runtime/plan9/mem.c new file mode 100644 index 000000000..f795b2c01 --- /dev/null +++ b/src/pkg/runtime/plan9/mem.c @@ -0,0 +1,67 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" +#include "malloc.h" +#include "os.h" + +extern byte end[]; +static byte *bloc = { end }; +static Lock memlock; + +enum +{ + Round = 4095 +}; + +void* +runtime·SysAlloc(uintptr nbytes) +{ + uintptr bl; + + runtime·lock(&memlock); + mstats.sys += nbytes; + // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c + bl = ((uintptr)bloc + Round) & ~Round; + if(runtime·brk_((void*)(bl + nbytes)) < 0) { + runtime·unlock(&memlock); + return (void*)-1; + } + bloc = (byte*)bl + nbytes; + runtime·unlock(&memlock); + return (void*)bl; +} + +void +runtime·SysFree(void *v, uintptr nbytes) +{ + runtime·lock(&memlock); + mstats.sys -= nbytes; + // from tiny/mem.c + // Push pointer back if this is a free + // of the most recent SysAlloc. + nbytes += (nbytes + Round) & ~Round; + if(bloc == (byte*)v+nbytes) + bloc -= nbytes; + runtime·unlock(&memlock); +} + +void +runtime·SysUnused(void *v, uintptr nbytes) +{ + USED(v, nbytes); +} + +void +runtime·SysMap(void *v, uintptr nbytes) +{ + USED(v, nbytes); +} + +void* +runtime·SysReserve(void *v, uintptr nbytes) +{ + USED(v); + return runtime·SysAlloc(nbytes); +} diff --git a/src/pkg/runtime/plan9/os.h b/src/pkg/runtime/plan9/os.h new file mode 100644 index 000000000..b2f7357ec --- /dev/null +++ b/src/pkg/runtime/plan9/os.h @@ -0,0 +1,57 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +extern int32 runtime·write(int32 fd, void* buffer, int32 nbytes); +extern void runtime·exits(int8* msg); +extern int32 runtime·brk_(void*); + +/* open */ +enum +{ + OREAD = 0, + OWRITE = 1, + ORDWR = 2 +}; + +/* rfork */ +enum +{ + RFNAMEG = (1<<0), + RFENVG = (1<<1), + RFFDG = (1<<2), + RFNOTEG = (1<<3), + RFPROC = (1<<4), + RFMEM = (1<<5), + RFNOWAIT = (1<<6), + RFCNAMEG = (1<<10), + RFCENVG = (1<<11), + RFCFDG = (1<<12), + RFREND = (1<<13), + RFNOMNT = (1<<14) +}; + +typedef struct Tos Tos; +typedef intptr Plink; + +struct Tos { + struct /* Per process profiling */ + { + Plink *pp; /* known to be 0(ptr) */ + Plink *next; /* known to be 4(ptr) */ + Plink *last; + Plink *first; + uint32 pid; + uint32 what; + } prof; + uint64 cyclefreq; /* cycle clock frequency if there is one, 0 otherwise */ + int64 kcycles; /* cycles spent in kernel */ + int64 pcycles; /* cycles spent in process (kernel + user) */ + uint32 pid; /* might as well put the pid here */ + uint32 clock; + /* top of stack is here */ +}; + +extern int32 runtime·rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void)); +extern int32 runtime·plan9_semacquire(uint32 *addr, int32 block); +extern int32 runtime·plan9_semrelease(uint32 *addr, int32 count); diff --git a/src/pkg/runtime/plan9/signals.h b/src/pkg/runtime/plan9/signals.h new file mode 100644 index 000000000..5df757613 --- /dev/null +++ b/src/pkg/runtime/plan9/signals.h @@ -0,0 +1 @@ +// nothing to see here diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c new file mode 100644 index 000000000..776989242 --- /dev/null +++ b/src/pkg/runtime/plan9/thread.c @@ -0,0 +1,174 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" +#include "os.h" + +int8 *goos = "plan9"; + +void +runtime·minit(void) +{ +} + +void +runtime·osinit(void) +{ +} + +void +runtime·goenvs(void) +{ +} + +void +runtime·initsig(int32 queue) +{ +} + +extern Tos *_tos; +void +runtime·exit(int32) +{ + int32 fd; + 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; + } + p = buf; + runtime·memmove((void*)p, (void*)"/proc/", 6); + p += 6; + for(q--; q >= tmp;) + *p++ = *q--; + runtime·memmove((void*)p, (void*)"/notepg", 7); + + /* post interrupt note */ + fd = runtime·open(buf, OWRITE); + runtime·write(fd, "interrupt", 9); + runtime·exits(nil); +} + +void +runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) +{ + m->tls[0] = m->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); + } + + if (runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0 ) + runtime·throw("newosproc: rfork failed"); +} + +// Blocking locks. + +// Implement Locks, using semaphores. +// l->key is the number of threads who want the lock. +// In a race, one thread increments l->key from 0 to 1 +// and the others increment it from >0 to >1. The thread +// who does the 0->1 increment gets the lock, and the +// others wait on the semaphore. When the 0->1 thread +// releases the lock by decrementing l->key, l->key will +// be >0, so it will increment the semaphore to wake up +// one of the others. This is the same algorithm used +// in Plan 9's user-level locks. + +void +runtime·lock(Lock *l) +{ + if(m->locks < 0) + runtime·throw("lock count"); + m->locks++; + + if(runtime·xadd(&l->key, 1) == 1) + return; // changed from 0 -> 1; we hold lock + // otherwise wait in kernel + while(runtime·plan9_semacquire(&l->sema, 1) < 0) { + /* interrupted; try again */ + } +} + +void +runtime·unlock(Lock *l) +{ + m->locks--; + if(m->locks < 0) + runtime·throw("lock count"); + + if(runtime·xadd(&l->key, -1) == 0) + return; // changed from 1 -> 0: no contention + + runtime·plan9_semrelease(&l->sema, 1); +} + + +// User-level semaphore implementation: +// try to do the operations in user space on u, +// but when it's time to block, fall back on the kernel semaphore k. +// This is the same algorithm used in Plan 9. +void +runtime·usemacquire(Usema *s) +{ + if((int32)runtime·xadd(&s->u, -1) < 0) + while(runtime·plan9_semacquire(&s->k, 1) < 0) { + /* interrupted; try again */ + } +} + +void +runtime·usemrelease(Usema *s) +{ + if((int32)runtime·xadd(&s->u, 1) <= 0) + runtime·plan9_semrelease(&s->k, 1); +} + + +// Event notifications. +void +runtime·noteclear(Note *n) +{ + n->wakeup = 0; +} + +void +runtime·notesleep(Note *n) +{ + while(!n->wakeup) + runtime·usemacquire(&n->sema); +} + +void +runtime·notewakeup(Note *n) +{ + n->wakeup = 1; + runtime·usemrelease(&n->sema); +} + +void +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) +{ +} |