diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
commit | 3e45412327a2654a77944249962b3652e6142299 (patch) | |
tree | bc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/runtime/plan9 | |
parent | c533680039762cacbc37db8dc7eed074c3e497be (diff) | |
download | golang-upstream/2011.01.12.tar.gz |
Imported Upstream version 2011.01.12upstream/2011.01.12
Diffstat (limited to 'src/pkg/runtime/plan9')
-rw-r--r-- | src/pkg/runtime/plan9/386/defs.h | 1 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/386/rt0.s | 32 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/386/signal.c | 16 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/386/sys.s | 76 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/mem.c | 49 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/os.h | 27 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/runtime_defs.go | 23 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/signals.h | 1 | ||||
-rw-r--r-- | src/pkg/runtime/plan9/thread.c | 140 |
9 files changed, 365 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..5df757613 --- /dev/null +++ b/src/pkg/runtime/plan9/386/defs.h @@ -0,0 +1 @@ +// nothing to see here 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..6bde09846 --- /dev/null +++ b/src/pkg/runtime/plan9/386/signal.c @@ -0,0 +1,16 @@ +// 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; +} diff --git a/src/pkg/runtime/plan9/386/sys.s b/src/pkg/runtime/plan9/386/sys.s new file mode 100644 index 000000000..867b8940f --- /dev/null +++ b/src/pkg/runtime/plan9/386/sys.s @@ -0,0 +1,76 @@ +// 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·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 0xdfffeff8, 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..651e6728e --- /dev/null +++ b/src/pkg/runtime/plan9/mem.c @@ -0,0 +1,49 @@ +// 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" + +extern byte end[]; +static byte *bloc = { end }; + +enum +{ + Round = 7 +}; + +void* +runtime·SysAlloc(uintptr ask) +{ + uintptr bl; + + // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c + bl = ((uintptr)bloc + Round) & ~Round; + if(runtime·brk_((void*)(bl + ask)) < 0) + return (void*)-1; + bloc = (byte*)bl + ask; + return (void*)bl; +} + +void +runtime·SysFree(void *v, uintptr n) +{ + // from tiny/mem.c + // Push pointer back if this is a free + // of the most recent SysAlloc. + n += (n + Round) & ~Round; + if(bloc == (byte*)v+n) + bloc -= n; +} + +void +runtime·SysUnused(void *v, uintptr n) +{ + USED(v, n); +} + +void +runtime·SysMemInit(void) +{ +} diff --git a/src/pkg/runtime/plan9/os.h b/src/pkg/runtime/plan9/os.h new file mode 100644 index 000000000..9444acc98 --- /dev/null +++ b/src/pkg/runtime/plan9/os.h @@ -0,0 +1,27 @@ +// 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*); + +/* 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) +}; +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/runtime_defs.go b/src/pkg/runtime/plan9/runtime_defs.go new file mode 100644 index 000000000..cf0b414a9 --- /dev/null +++ b/src/pkg/runtime/plan9/runtime_defs.go @@ -0,0 +1,23 @@ +// 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. + +// Go definitions of internal structures. Master is runtime.h + +package runtime + +type lock struct { + key uint32 + sema uint32 +} + +type usema struct { + u uint32 + k uint32 +} + + +type note struct { + wakeup int32 + sema usema +} 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..fa96552a9 --- /dev/null +++ b/src/pkg/runtime/plan9/thread.c @@ -0,0 +1,140 @@ +// 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) +{ +} + +void +runtime·exit(int32) +{ + runtime·exits(nil); +} + +void +runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) +{ + USED(m, g, stk, fn); + + 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, 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); +} + + +void +runtime·destroylock(Lock *l) +{ + // nothing +} + +// 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); +} + |