summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/plan9
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
committerOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
commit5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch)
treec0650497e988f47be9c6f2324fa692a52dea82e1 /src/pkg/runtime/plan9
parent80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff)
downloadgolang-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.h2
-rw-r--r--src/pkg/runtime/plan9/386/rt0.s32
-rw-r--r--src/pkg/runtime/plan9/386/signal.c24
-rw-r--r--src/pkg/runtime/plan9/386/sys.s82
-rw-r--r--src/pkg/runtime/plan9/mem.c67
-rw-r--r--src/pkg/runtime/plan9/os.h57
-rw-r--r--src/pkg/runtime/plan9/signals.h1
-rw-r--r--src/pkg/runtime/plan9/thread.c174
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)
+{
+}