mirror of
https://github.com/golang/go
synced 2024-11-24 22:57:57 -07:00
8l, runtime: initial support for Plan 9
No multiple processes/locks, managed to compile and run a hello.go (with print not fmt). Also test/sieve.go seems to run until 439 and stops with a 'throw: all goroutines are asleep - deadlock!' - just like runtime/tiny. based on Russ's suggestions at: http://groups.google.com/group/comp.os.plan9/browse_thread/thread/cfda8b82535d2d68/243777a597ec1612 Build instructions: cd src/pkg/runtime make clean && GOOS=plan9 make install this will build and install the runtime. When linking with 8l, you should pass -s to suppress symbol generation in the a.out, otherwise the generated executable will not run. This is runtime only, the porting of the toolchain has already been done: http://code.google.com/p/go-plan9/source/browse in the plan9-quanstro branch. R=rsc CC=golang-dev https://golang.org/cl/2273041
This commit is contained in:
parent
6ac08ba638
commit
99a10eff16
@ -34,9 +34,10 @@ else ifeq ($(GOOS),freebsd)
|
|||||||
else ifeq ($(GOOS),linux)
|
else ifeq ($(GOOS),linux)
|
||||||
else ifeq ($(GOOS),nacl)
|
else ifeq ($(GOOS),nacl)
|
||||||
else ifeq ($(GOOS),tiny)
|
else ifeq ($(GOOS),tiny)
|
||||||
|
else ifeq ($(GOOS),plan9)
|
||||||
else ifeq ($(GOOS),windows)
|
else ifeq ($(GOOS),windows)
|
||||||
else
|
else
|
||||||
$(error Invalid $$GOOS '$(GOOS)'; must be darwin, freebsd, linux, nacl, tiny, or windows)
|
$(error Invalid $$GOOS '$(GOOS)'; must be darwin, freebsd, linux, nacl, tiny, plan9, or windows)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(GOHOSTARCH),)
|
ifeq ($(GOHOSTARCH),)
|
||||||
|
@ -441,6 +441,7 @@ asmb(void)
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
seek(cout, HEADR+textsize+segdata.filelen, 0);
|
seek(cout, HEADR+textsize+segdata.filelen, 0);
|
||||||
|
symo = HEADR+textsize+segdata.filelen;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -144,6 +144,9 @@ main(int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
if(strcmp(goos, "tiny") == 0)
|
if(strcmp(goos, "tiny") == 0)
|
||||||
HEADTYPE = 11;
|
HEADTYPE = 11;
|
||||||
|
else
|
||||||
|
if(strcmp(goos, "plan9") == 0)
|
||||||
|
HEADTYPE = 2;
|
||||||
else
|
else
|
||||||
print("goos is not known: %s\n", goos);
|
print("goos is not known: %s\n", goos);
|
||||||
}
|
}
|
||||||
|
@ -293,6 +293,14 @@ patch(void)
|
|||||||
p->from.offset = 0;
|
p->from.offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(HEADTYPE == 2) { // Plan 9
|
||||||
|
if(p->from.type == D_INDIR+D_GS
|
||||||
|
&& p->to.type >= D_AX && p->to.type <= D_DI) {
|
||||||
|
p->as = AMOVL;
|
||||||
|
p->from.type = D_ADDR+D_STATIC;
|
||||||
|
p->from.offset += 0xdfffefc0;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) {
|
if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) {
|
||||||
s = p->to.sym;
|
s = p->to.sym;
|
||||||
if(s) {
|
if(s) {
|
||||||
@ -418,7 +426,14 @@ dostkoff(void)
|
|||||||
p->from.offset = tlsoffset + 0;
|
p->from.offset = tlsoffset + 0;
|
||||||
p->to.type = D_CX;
|
p->to.type = D_CX;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 2: // Plan 9
|
||||||
|
p->as = AMOVL;
|
||||||
|
p->from.type = D_ADDR+D_STATIC;
|
||||||
|
p->from.offset = 0xdfffefc0;
|
||||||
|
p->to.type = D_CX;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
p->as = AMOVL;
|
p->as = AMOVL;
|
||||||
p->from.type = D_INDIR+D_GS;
|
p->from.type = D_INDIR+D_GS;
|
||||||
|
@ -26,6 +26,8 @@ TEXT _rt0_386(SB),7,$0
|
|||||||
CALL ldt0setup(SB)
|
CALL ldt0setup(SB)
|
||||||
|
|
||||||
// store through it, to make sure it works
|
// store through it, to make sure it works
|
||||||
|
CMPL isplan9(SB), $1
|
||||||
|
JEQ ok
|
||||||
get_tls(BX)
|
get_tls(BX)
|
||||||
MOVL $0x123, g(BX)
|
MOVL $0x123, g(BX)
|
||||||
MOVL tls0(SB), AX
|
MOVL tls0(SB), AX
|
||||||
@ -414,4 +416,4 @@ GLOBL m0(SB), $1024
|
|||||||
GLOBL g0(SB), $1024
|
GLOBL g0(SB), $1024
|
||||||
GLOBL tls0(SB), $32
|
GLOBL tls0(SB), $32
|
||||||
GLOBL initcgo(SB), $4
|
GLOBL initcgo(SB), $4
|
||||||
|
GLOBL isplan9(SB), $4
|
||||||
|
@ -24,6 +24,11 @@ case "$GOARCH" in
|
|||||||
echo '#define g(r) 0(r)'
|
echo '#define g(r) 0(r)'
|
||||||
echo '#define m(r) 4(r)'
|
echo '#define m(r) 4(r)'
|
||||||
;;
|
;;
|
||||||
|
plan9)
|
||||||
|
echo '#define get_tls(r)'
|
||||||
|
echo '#define g(r) 0xdfffefc0'
|
||||||
|
echo '#define m(r) 0xdfffefc4'
|
||||||
|
;;
|
||||||
linux)
|
linux)
|
||||||
# On Linux systems, what we call 0(GS) and 4(GS) for g and m
|
# On Linux systems, what we call 0(GS) and 4(GS) for g and m
|
||||||
# turn into %gs:-8 and %gs:-4 (using gcc syntax to denote
|
# turn into %gs:-8 and %gs:-4 (using gcc syntax to denote
|
||||||
|
1
src/pkg/runtime/plan9/386/defs.h
Normal file
1
src/pkg/runtime/plan9/386/defs.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
// nothing to see here
|
32
src/pkg/runtime/plan9/386/rt0.s
Normal file
32
src/pkg/runtime/plan9/386/rt0.s
Normal file
@ -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 isplan9+0(SB)/4, $1
|
||||||
|
GLOBL isplan9(SB), $4
|
||||||
|
GLOBL _tos(SB), $4
|
10
src/pkg/runtime/plan9/386/signal.c
Normal file
10
src/pkg/runtime/plan9/386/signal.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// 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
|
||||||
|
gettime(int64*, int32*)
|
||||||
|
{
|
||||||
|
}
|
76
src/pkg/runtime/plan9/386/sys.s
Normal file
76
src/pkg/runtime/plan9/386/sys.s
Normal file
@ -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 setldt(SB),7,$0
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT write(SB),7,$0
|
||||||
|
MOVL $20, AX
|
||||||
|
INT $64
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT exits(SB),7,$0
|
||||||
|
MOVL $8, AX
|
||||||
|
INT $64
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT brk_(SB),7,$0
|
||||||
|
MOVL $24, AX
|
||||||
|
INT $64
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT plan9_semacquire(SB),7,$0
|
||||||
|
MOVL $37, AX
|
||||||
|
INT $64
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT plan9_semrelease(SB),7,$0
|
||||||
|
MOVL $38, AX
|
||||||
|
INT $64
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT 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 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 emptyfunc(SB)
|
||||||
|
POPAL
|
||||||
|
|
||||||
|
CALL SI // fn()
|
||||||
|
CALL exit(SB)
|
||||||
|
RET
|
49
src/pkg/runtime/plan9/mem.c
Normal file
49
src/pkg/runtime/plan9/mem.c
Normal file
@ -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*
|
||||||
|
SysAlloc(uintptr ask)
|
||||||
|
{
|
||||||
|
uintptr bl;
|
||||||
|
|
||||||
|
// Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
|
||||||
|
bl = ((uintptr)bloc + Round) & ~Round;
|
||||||
|
if(brk_((void*)(bl + ask)) < 0)
|
||||||
|
return (void*)-1;
|
||||||
|
bloc = (byte*)bl + ask;
|
||||||
|
return (void*)bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
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
|
||||||
|
SysUnused(void *v, uintptr n)
|
||||||
|
{
|
||||||
|
USED(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SysMemInit(void)
|
||||||
|
{
|
||||||
|
}
|
27
src/pkg/runtime/plan9/os.h
Normal file
27
src/pkg/runtime/plan9/os.h
Normal file
@ -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 write(int32 fd, void* buffer, int32 nbytes);
|
||||||
|
extern void exits(int8* msg);
|
||||||
|
extern int32 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 rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void));
|
||||||
|
extern int32 plan9_semacquire(uint32 *addr, int32 block);
|
||||||
|
extern int32 plan9_semrelease(uint32 *addr, int32 count);
|
1
src/pkg/runtime/plan9/signals.h
Normal file
1
src/pkg/runtime/plan9/signals.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
// nothing to see here
|
135
src/pkg/runtime/plan9/thread.c
Normal file
135
src/pkg/runtime/plan9/thread.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 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
|
||||||
|
minit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
osinit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
initsig(int32 queue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
exit(int32)
|
||||||
|
{
|
||||||
|
exits(nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
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){
|
||||||
|
printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n",
|
||||||
|
stk, m, g, fn, rfork, m->id, m->tls[0], &m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfork(RFPROC | RFMEM, stk, m, g, fn) < 0 )
|
||||||
|
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
|
||||||
|
lock(Lock *l)
|
||||||
|
{
|
||||||
|
if(m->locks < 0)
|
||||||
|
throw("lock count");
|
||||||
|
m->locks++;
|
||||||
|
|
||||||
|
if(xadd(&l->key, 1) == 1)
|
||||||
|
return; // changed from 0 -> 1; we hold lock
|
||||||
|
// otherwise wait in kernel
|
||||||
|
while(plan9_semacquire(&l->sema, 1) < 0) {
|
||||||
|
/* interrupted; try again */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unlock(Lock *l)
|
||||||
|
{
|
||||||
|
m->locks--;
|
||||||
|
if(m->locks < 0)
|
||||||
|
throw("lock count");
|
||||||
|
|
||||||
|
if(xadd(&l->key, -1) == 0)
|
||||||
|
return; // changed from 1 -> 0: no contention
|
||||||
|
|
||||||
|
plan9_semrelease(&l->sema, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
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
|
||||||
|
usemacquire(Usema *s)
|
||||||
|
{
|
||||||
|
if((int32)xadd(&s->u, -1) < 0)
|
||||||
|
while(plan9_semacquire(&s->k, 1) < 0) {
|
||||||
|
/* interrupted; try again */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usemrelease(Usema *s)
|
||||||
|
{
|
||||||
|
if((int32)xadd(&s->u, 1) <= 0)
|
||||||
|
plan9_semrelease(&s->k, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Event notifications.
|
||||||
|
void
|
||||||
|
noteclear(Note *n)
|
||||||
|
{
|
||||||
|
n->wakeup = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notesleep(Note *n)
|
||||||
|
{
|
||||||
|
while(!n->wakeup)
|
||||||
|
usemacquire(&n->sema);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notewakeup(Note *n)
|
||||||
|
{
|
||||||
|
n->wakeup = 1;
|
||||||
|
usemrelease(&n->sema);
|
||||||
|
}
|
||||||
|
|
@ -147,15 +147,20 @@ args(int32 c, uint8 **v)
|
|||||||
argv = v;
|
argv = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int32 isplan9;
|
||||||
|
|
||||||
void
|
void
|
||||||
goargs(void)
|
goargs(void)
|
||||||
{
|
{
|
||||||
String *gargv;
|
String *gargv;
|
||||||
String *genvv;
|
String *genvv;
|
||||||
int32 i, envc;
|
int32 i, envc;
|
||||||
|
|
||||||
for(envc=0; argv[argc+1+envc] != 0; envc++)
|
if(isplan9)
|
||||||
;
|
envc=0;
|
||||||
|
else
|
||||||
|
for(envc=0; argv[argc+1+envc] != 0; envc++)
|
||||||
|
;
|
||||||
|
|
||||||
gargv = malloc(argc*sizeof gargv[0]);
|
gargv = malloc(argc*sizeof gargv[0]);
|
||||||
genvv = malloc(envc*sizeof genvv[0]);
|
genvv = malloc(envc*sizeof genvv[0]);
|
||||||
|
@ -76,7 +76,7 @@ typedef struct Complex128 Complex128;
|
|||||||
* segment register.
|
* segment register.
|
||||||
*
|
*
|
||||||
* amd64: allocated downwards from R15
|
* amd64: allocated downwards from R15
|
||||||
* x86: allocated upwards from 0(FS)
|
* x86: allocated upwards from 0(GS)
|
||||||
* arm: allocated downwards from R10
|
* arm: allocated downwards from R10
|
||||||
*
|
*
|
||||||
* every C file linked into a Go program must include runtime.h
|
* every C file linked into a Go program must include runtime.h
|
||||||
|
Loading…
Reference in New Issue
Block a user