9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] plan9 go output faults on 9vx but ok on cpu
@ 2011-01-11  7:54 Skip Tavakkolian
  2011-01-11 14:11 ` erik quanstrom
                   ` (2 more replies)
  0 siblings, 3 replies; 36+ messages in thread
From: Skip Tavakkolian @ 2011-01-11  7:54 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

hell-o.go is like hello.go but uses println. 8.hell-o works properly
on a plan9 cpu. but it faults when running on 9vx. i built vx32 --
including 9vx -- on a linux/x86-64 from sources in the last couple of
days.

% 8.hell-o
8.hell-o 270: suicide: sys: trap: page fault pc=0x000010bc

/dev/kprint reports:
270 8.hell-o: unhandled fault va=ffffffffdfffefc0 [218f7fc0] eip=10bc
cpu0: registers for 8.hell-o 270
FLAGS=0 TRAP=0 ECODE=0 PC=10BC USP=FFFFF00
  AX 00018D60  BX 0FFFFF8C  CX 00018DF8  DX 0001C608
  SI 0FFFFFA8  DI FFFFFFF8  BP 00000000

-Skip



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11  7:54 [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
@ 2011-01-11 14:11 ` erik quanstrom
  2011-01-11 15:06   ` Devon H. O'Dell
  2011-01-11 17:03   ` Charles Forsyth
  2011-01-11 16:25 ` ron minnich
  2011-01-11 17:03 ` Pavel Zholkover
  2 siblings, 2 replies; 36+ messages in thread
From: erik quanstrom @ 2011-01-11 14:11 UTC (permalink / raw)
  To: 9fans

On Tue Jan 11 02:55:42 EST 2011, skip.tavakkolian@gmail.com wrote:
> hell-o.go is like hello.go but uses println. 8.hell-o works properly
> on a plan9 cpu. but it faults when running on 9vx. i built vx32 --
> including 9vx -- on a linux/x86-64 from sources in the last couple of
> days.
>
> % 8.hell-o
> 8.hell-o 270: suicide: sys: trap: page fault pc=0x000010bc
>
> /dev/kprint reports:
> 270 8.hell-o: unhandled fault va=ffffffffdfffefc0 [218f7fc0] eip=10bc
> cpu0: registers for 8.hell-o 270
> FLAGS=0 TRAP=0 ECODE=0 PC=10BC USP=FFFFF00
>   AX 00018D60  BX 0FFFFF8C  CX 00018DF8  DX 0001C608
>   SI 0FFFFFA8  DI FFFFFFF8  BP 00000000

i'm a little confused.  i thought that 9vx had to be compiled
32-bit because it relies on the ancient segment registers.
whence the 64-bit va?  is it using pae?

- erik



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 14:11 ` erik quanstrom
@ 2011-01-11 15:06   ` Devon H. O'Dell
  2011-01-11 17:03   ` Charles Forsyth
  1 sibling, 0 replies; 36+ messages in thread
From: Devon H. O'Dell @ 2011-01-11 15:06 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

2011/1/11 erik quanstrom <quanstro@quanstro.net>:
> On Tue Jan 11 02:55:42 EST 2011, skip.tavakkolian@gmail.com wrote:
>> hell-o.go is like hello.go but uses println. 8.hell-o works properly
>> on a plan9 cpu. but it faults when running on 9vx. i built vx32 --
>> including 9vx -- on a linux/x86-64 from sources in the last couple of
>> days.
>>
>> % 8.hell-o
>> 8.hell-o 270: suicide: sys: trap: page fault pc=0x000010bc
>>
>> /dev/kprint reports:
>> 270 8.hell-o: unhandled fault va=ffffffffdfffefc0 [218f7fc0] eip=10bc
>> cpu0: registers for 8.hell-o 270
>> FLAGS=0 TRAP=0 ECODE=0 PC=10BC USP=FFFFF00
>>   AX 00018D60  BX 0FFFFF8C  CX 00018DF8  DX 0001C608
>>   SI 0FFFFFA8  DI FFFFFFF8  BP 00000000
>
> i'm a little confused.  i thought that 9vx had to be compiled
> 32-bit because it relies on the ancient segment registers.
> whence the 64-bit va?  is it using pae?

64-bit works on linux with some ldt emulation using tls, I believe. It
doesn't work on os x or freebsd.

--dho


> - erik
>
>



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11  7:54 [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
  2011-01-11 14:11 ` erik quanstrom
@ 2011-01-11 16:25 ` ron minnich
  2011-01-12  8:32   ` Skip Tavakkolian
  2011-01-11 17:03 ` Pavel Zholkover
  2 siblings, 1 reply; 36+ messages in thread
From: ron minnich @ 2011-01-11 16:25 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

can you do a ratrace for me?

ron



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11  7:54 [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
  2011-01-11 14:11 ` erik quanstrom
  2011-01-11 16:25 ` ron minnich
@ 2011-01-11 17:03 ` Pavel Zholkover
  2011-01-11 18:55   ` Anthony Martin
  2 siblings, 1 reply; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-11 17:03 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

I'm typing from my phone so I don't have go sources in front of me,
but 0xdfffefc0 looks like the address I used for per thread G and M
structs - just bellow struct Tos.

Andrey and I also tried running on a 32-bit 9vx with the same effect.

Is 9vx using a different memory layout than Plan 9?

On Tuesday, January 11, 2011, Skip Tavakkolian
<skip.tavakkolian@gmail.com> wrote:
> hell-o.go is like hello.go but uses println. 8.hell-o works properly
> on a plan9 cpu. but it faults when running on 9vx. i built vx32 --
> including 9vx -- on a linux/x86-64 from sources in the last couple of
> days.
>
> % 8.hell-o
> 8.hell-o 270: suicide: sys: trap: page fault pc=0x000010bc
>
> /dev/kprint reports:
> 270 8.hell-o: unhandled fault va=ffffffffdfffefc0 [218f7fc0] eip=10bc
> cpu0: registers for 8.hell-o 270
> FLAGS=0 TRAP=0 ECODE=0 PC=10BC USP=FFFFF00
>   AX 00018D60  BX 0FFFFF8C  CX 00018DF8  DX 0001C608
>   SI 0FFFFFA8  DI FFFFFFF8  BP 00000000
>
> -Skip
>
>



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 14:11 ` erik quanstrom
  2011-01-11 15:06   ` Devon H. O'Dell
@ 2011-01-11 17:03   ` Charles Forsyth
  2011-01-11 17:51     ` ron minnich
  1 sibling, 1 reply; 36+ messages in thread
From: Charles Forsyth @ 2011-01-11 17:03 UTC (permalink / raw)
  To: 9fans

i suspect go is using segment register(s) to implement extern register,
and that isn't expected (or perhaps even supported) by 9vx.
just a guess.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 17:03   ` Charles Forsyth
@ 2011-01-11 17:51     ` ron minnich
  2011-01-11 19:35       ` Pavel Zholkover
  2011-01-11 23:58       ` Charles Forsyth
  0 siblings, 2 replies; 36+ messages in thread
From: ron minnich @ 2011-01-11 17:51 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Tue, Jan 11, 2011 at 9:03 AM, Charles Forsyth <forsyth@terzarima.net> wrote:
> i suspect go is using segment register(s) to implement extern register,
> and that isn't expected (or perhaps even supported) by 9vx.
> just a guess.
>
>

I did not realize this was currently supported by Plan 9 ... maybe I
didn't get the memo?

ron



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 17:03 ` Pavel Zholkover
@ 2011-01-11 18:55   ` Anthony Martin
  2011-01-11 19:06     ` Anthony Martin
  2011-01-11 22:58     ` ron minnich
  0 siblings, 2 replies; 36+ messages in thread
From: Anthony Martin @ 2011-01-11 18:55 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

Pavel Zholkover <paulzhol@gmail.com> once said:
> I'm typing from my phone so I don't have go sources in front of me,
> but 0xdfffefc0 looks like the address I used for per thread G and M
> structs - just bellow struct Tos.
>
> Andrey and I also tried running on a 32-bit 9vx with the same effect.
>
> Is 9vx using a different memory layout than Plan 9?

The Tos structure is bigger on 64-bit 9vx so the references
to GS will need a different offset. You'll have to change
both src/8l/pass.c:/^patch and the runtime.

  Anthony



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 18:55   ` Anthony Martin
@ 2011-01-11 19:06     ` Anthony Martin
  2011-01-11 22:58     ` ron minnich
  1 sibling, 0 replies; 36+ messages in thread
From: Anthony Martin @ 2011-01-11 19:06 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

Anthony Martin <ality@pbrane.org> once said:
> The Tos structure is bigger on 64-bit 9vx so the references
> to GS will need a different offset. You'll have to change
> both src/8l/pass.c:/^patch and the runtime.

I forgot to mention that on 9vx, USTKTOP is at 0x10000000.

  Anthony



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 17:51     ` ron minnich
@ 2011-01-11 19:35       ` Pavel Zholkover
  2011-01-11 23:58       ` Charles Forsyth
  1 sibling, 0 replies; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-11 19:35 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

I did the runtime port a few month ago, now waiting for
http://codereview.appspot.com/3816043/ to get reviewed and
committed... there are still a bunch of things missing like linking
with symbols, os.ForkExec and environment variables at early runtime.

time package is also not ready, so I can't run the tests yet (I expect
there are a lot of bugs hidden inside :))

Pavel

On Tue, Jan 11, 2011 at 7:51 PM, ron minnich <rminnich@gmail.com> wrote:
> I did not realize this was currently supported by Plan 9 ... maybe I
> didn't get the memo?
>
> ron
>



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 18:55   ` Anthony Martin
  2011-01-11 19:06     ` Anthony Martin
@ 2011-01-11 22:58     ` ron minnich
  2011-01-12 22:31       ` Anthony Martin
  1 sibling, 1 reply; 36+ messages in thread
From: ron minnich @ 2011-01-11 22:58 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Tue, Jan 11, 2011 at 10:55 AM, Anthony Martin <ality@pbrane.org> wrote:
> Pavel Zholkover <paulzhol@gmail.com> once said:
>> I'm typing from my phone so I don't have go sources in front of me,
>> but 0xdfffefc0 looks like the address I used for per thread G and M
>> structs - just bellow struct Tos.
>>
>> Andrey and I also tried running on a 32-bit 9vx with the same effect.
>>
>> Is 9vx using a different memory layout than Plan 9?
>
> The Tos structure is bigger on 64-bit 9vx so the references
> to GS will need a different offset. You'll have to change
> both src/8l/pass.c:/^patch and the runtime.

are you saying change 8l so that it creates code that works on 9vx in
the special case that it runs on a 64-bit system? Then we're going to
need to make 8l aware of way too much stuff.

That strikes me as the wrong direction. I think what you want to do is
what my 9vx branch does: on 64- or 32- bit system, the TOS struct is
always correctly set up for a 32-bit 9vx binary.

If someone wants to send me a go binary I can test tomorrow on 64-bit
osx with my 9vx branch.

ron



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 17:51     ` ron minnich
  2011-01-11 19:35       ` Pavel Zholkover
@ 2011-01-11 23:58       ` Charles Forsyth
  1 sibling, 0 replies; 36+ messages in thread
From: Charles Forsyth @ 2011-01-11 23:58 UTC (permalink / raw)
  To: 9fans

>I did not realize this was currently supported by Plan 9 ... maybe I
>didn't get the memo?

go's 8c/8l convert extern register to references off a segment register,
although the implementation of extern register isn't general enough for plan 9 kernel use;
it's just enough for go. it sounds as though the current plan9/go implementation
instead changes its 8l to catch the GS references and convert them to references to known
locations on the per-process stack (which would also work for go).

i made a more accurate implementation of extern register in plan 9's own 8c/8l that
could for instance be used by kernels to make up and/or m extern register on x86,
but i'm not sure of its status.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 16:25 ` ron minnich
@ 2011-01-12  8:32   ` Skip Tavakkolian
  2011-01-12 16:12     ` andrey mirtchovski
  2011-01-13  5:54     ` ron minnich
  0 siblings, 2 replies; 36+ messages in thread
From: Skip Tavakkolian @ 2011-01-12  8:32 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Tue, Jan 11, 2011 at 8:25 AM, ron minnich <rminnich@gmail.com> wrote:
> can you do a ratrace for me?
>
> ron
>
>

i'll have to rebuild using the vx32 branch on your bitbucket. is it up
to date with the changes to compile on linux/x86-64?

here it is on acid:

% acid 8.hell-o
8.hell-o:386 plan 9 executable
/sys/lib/acid/port
/sys/lib/acid/386
no symbol information
acid: new()
299: exception 576	0x7045	MOVL	AX,0x18cfc
<stdin>:2: (error) main used but not set
acid: asm(*PC-32)
0x7025 0x00007025	CALLL	0x3b9a:0xca00ba3b
0x702c 0x0000702c	MULL	AX,DX
0x702e 0x0000702e	ADDL	CX,DX
0x7030 0x00007030	JMP	0x7002
0x7032 0x00007032	MOVL	DX,CX
0x7034 0x00007034	IMULL	CX,$0x3e8,CX
0x703a 0x0000703a	MOVL	$0x3e8,DX
0x703f 0x0000703f	MULL	AX,DX
0x7041 0x00007041	ADDL	CX,DX
0x7043 0x00007043	JMP	0x6fe2
0x7045 0x00007045	MOVL	AX,0x18cfc
0x704b 0x0000704b	MOVL	SP,SI
0x704d 0x0000704d	SUBL	$0x8,SP
0x7050 0x00007050	MOVL	SP,DI
0x7052 0x00007052	MOVL	AX,CX
0x7054 0x00007054	SUBL	SI,CX
0x7056 0x00007056	CLD
0x7057 0x00007057	REP MOVSB	(SI),(DI)
0x7059 0x00007059	SUBL	SI,DI
0x705b 0x0000705b	MOVL	0x0(SP),CX
0x705e 0x0000705e	LEAL	0x4(SP),BP
0x7062 0x00007062	ADDL	DI,0x0(BP)
0x7065 0x00007065	ADDL	$0x4,BP
0x7068 0x00007068	LOOP	0x7062
0x706a 0x0000706a	JMP	0x1092
0x706f 0x0000706f	MOVL	0xdfffefc0,CX
0x7075 0x00007075	CMPL	0x0(CX),SP
0x7077 0x00007077	JHI	0x7085
0x7079 0x00007079	XORL	DX,DX
0x707b 0x0000707b	MOVL	$0x8,AX
acid:



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-12  8:32   ` Skip Tavakkolian
@ 2011-01-12 16:12     ` andrey mirtchovski
  2011-01-12 22:03       ` ron minnich
  2011-01-13  5:54     ` ron minnich
  1 sibling, 1 reply; 36+ messages in thread
From: andrey mirtchovski @ 2011-01-12 16:12 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

slightly different on my mac, so i'll post it:

61: page fault	0x10bc	MOVL	CX,0xdfffefc0
acid: asm(*PC-32)
0x109c 0x0000109c	ADDB	AL,0x0(AX)
0x109e 0x0000109e	ADDB	AL,0x4489f0e4(BX)
0x10a4 0x000010a4	ANDB	$0x78,AL
0x10a6 0x000010a6	MOVL	BX,0x7c(SP)
0x10aa 0x000010aa	MOVL	0x15c70,AX
0x10b0 0x000010b0	TESTL	AX,AX
0x10b2 0x000010b2	JEQ	0x111b
0x10b4 0x000010b4	CALL*	AX
0x10b6 0x000010b6	LEAL	0x16a88,CX
0x10bc 0x000010bc	MOVL	CX,0xdfffefc0
0x10c2 0x000010c2	LEAL	0x16e88,AX
0x10c8 0x000010c8	MOVL	AX,0xdfffefc4
0x10ce 0x000010ce	MOVL	CX,0x0(AX)
0x10d0 0x000010d0	LEAL	0xffffe068(SP),AX
0x10d7 0x000010d7	MOVL	AX,0x0(CX)
0x10d9 0x000010d9	MOVL	SP,0x4(CX)
0x10dc 0x000010dc	CALL	0x12e8
0x10e1 0x000010e1	CLD
0x10e2 0x000010e2	CALL	0x6f97
0x10e7 0x000010e7	MOVL	0x78(SP),AX
0x10eb 0x000010eb	MOVL	AX,0x0(SP)
0x10ee 0x000010ee	MOVL	0x7c(SP),AX
0x10f2 0x000010f2	MOVL	AX,0x4(SP)
0x10f6 0x000010f6	CALL	0x6d1a
0x10fb 0x000010fb	CALL	0x816c
0x1100 0x00001100	CALL	0x5963
0x1105 0x00001105	PUSHL	$0x114f
0x110a 0x0000110a	PUSHL	$0x0
0x110c 0x0000110c	CALL	0x6772
0x1111 0x00001111	POPL	AX



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-12 16:12     ` andrey mirtchovski
@ 2011-01-12 22:03       ` ron minnich
  0 siblings, 0 replies; 36+ messages in thread
From: ron minnich @ 2011-01-12 22:03 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Wed, Jan 12, 2011 at 9:12 AM, andrey mirtchovski
<mirtchovski@gmail.com> wrote:
> slightly different on my mac, so i'll post it:
>
> 61: page fault  0x10bc  MOVL    CX,0xdfffefc0

eek. Yeah, I guess the guys are right, you're dying on access to stack?

which 9vx are you running? I'm on travel but will look at this tomorrow.

ron



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-11 22:58     ` ron minnich
@ 2011-01-12 22:31       ` Anthony Martin
  2011-01-12 22:36         ` erik quanstrom
  2011-01-12 23:29         ` Charles Forsyth
  0 siblings, 2 replies; 36+ messages in thread
From: Anthony Martin @ 2011-01-12 22:31 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

ron minnich <rminnich@gmail.com> once said:
> are you saying change 8l so that it creates code that works on 9vx in
> the special case that it runs on a 64-bit system? Then we're going to
> need to make 8l aware of way too much stuff.

I'm talking about Go's linker. In the Go runtime, the G and M
pointers need to be in a per-process storage area. On Plan 9,
this is the stack. Right now, the offset of the pointers is
hard-coded in the linker to be just before the Tos structure.
The problem is that the value that was chosen is not correct
when running on 9vx because the top of the stack is is at
0x10000000 instead of 0xdffff000 (as it is on native Plan 9).

I think that the Go 8l should not hard-code this value but,
instead, discover it somehow ... though I'm not sure how.

  Anthony



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-12 22:31       ` Anthony Martin
@ 2011-01-12 22:36         ` erik quanstrom
  2011-01-12 23:28           ` Pavel Zholkover
  2011-01-12 23:29         ` Charles Forsyth
  1 sibling, 1 reply; 36+ messages in thread
From: erik quanstrom @ 2011-01-12 22:36 UTC (permalink / raw)
  To: ality, 9fans

> I'm talking about Go's linker. In the Go runtime, the G and M
> pointers need to be in a per-process storage area. On Plan 9,
> this is the stack. Right now, the offset of the pointers is
> hard-coded in the linker to be just before the Tos structure.
> The problem is that the value that was chosen is not correct
> when running on 9vx because the top of the stack is is at
> 0x10000000 instead of 0xdffff000 (as it is on native Plan 9).
>
> I think that the Go 8l should not hard-code this value but,
> instead, discover it somehow ... though I'm not sure how.

main9.s sets _tos on entry.  why not just use _tos as
the c glue code does?

- erik



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-12 22:36         ` erik quanstrom
@ 2011-01-12 23:28           ` Pavel Zholkover
  0 siblings, 0 replies; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-12 23:28 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

> main9.s sets _tos on entry.  why not just use _tos as
> the c glue code does?
>
> - erik
>
>

I'm already setting _tos on entry:
http://code.google.com/p/go/source/browse/src/pkg/runtime/plan9/386/rt0.s
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.
...

the hard coded addresses are here:
http://code.google.com/p/go/source/browse/src/pkg/runtime/mkasmh.sh
case "$GOOS" in
...
        plan9)
                echo '#define   get_tls(r)'
                echo '#define   g(r)    0xdfffefc0'
                echo '#define   m(r)    0xdfffefc4'

which are easy enough to modify and here:
http://code.google.com/p/go/source/browse/src/cmd/8l/pass.c
^patch(void)
...
                        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;
                                }
                        }

^dostkoff(void)
...
                        case 2: // Plan 9
                                p->as = AMOVL;
                                p->from.type = D_ADDR+D_STATIC;
                                p->from.offset = 0xdfffefc0;
                                p->to.type = D_CX;
                                break;


I am not that familiar with the linker, but maybe calling Sym*
lookup("_tos") and adding some code to to add instructions for
calculating the offset would work.

It was just easier for me to start working on a kvm vm...



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-12 22:31       ` Anthony Martin
  2011-01-12 22:36         ` erik quanstrom
@ 2011-01-12 23:29         ` Charles Forsyth
  1 sibling, 0 replies; 36+ messages in thread
From: Charles Forsyth @ 2011-01-12 23:29 UTC (permalink / raw)
  To: 9fans

>0xdffff000 (as it is on native Plan 9).

of course, that too can change, but i know you know that,
and the current go implementation was just to get going.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-12  8:32   ` Skip Tavakkolian
  2011-01-12 16:12     ` andrey mirtchovski
@ 2011-01-13  5:54     ` ron minnich
  2011-01-14 17:32       ` Pavel Zholkover
  1 sibling, 1 reply; 36+ messages in thread
From: ron minnich @ 2011-01-13  5:54 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Wed, Jan 12, 2011 at 12:32 AM, Skip Tavakkolian
<skip.tavakkolian@gmail.com> wrote:
> On Tue, Jan 11, 2011 at 8:25 AM, ron minnich <rminnich@gmail.com> wrote:
>> can you do a ratrace for me?
>>
>> ron
>>
>>
>
> i'll have to rebuild using the vx32 branch on your bitbucket. is it up
> to date with the changes to compile on linux/x86-64?

yeah, I'm running that way today on my linux box.

ron



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-13  5:54     ` ron minnich
@ 2011-01-14 17:32       ` Pavel Zholkover
  2011-01-15  2:00         ` Anthony Martin
  2011-01-15  9:01         ` kokamoto
  0 siblings, 2 replies; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-14 17:32 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

[-- Attachment #1: Type: text/plain, Size: 997 bytes --]

Hi,

Attached a patch to get cross compiled go binaries to run on 9vx and
native Plan 9.

I tried the 9vx-0.12 binaries from http://swtch.com/9vx on a x86-64
linux, but they don't contain support for the CMPXCHG instruction.
After recompiling 9vx from rminnich branch, I can get hello.go to run
correctly both on 9vx and a Plan 9 terminal inside qemu-kvm with this
patch.

Unfortunately rfork seems to be broken (on the 9vx); The PUSHAL, POPAL
instructions are not supported so I had to comment out
PUSHAL
CALL	runtime·emptyfunc(SB)
POPAL
in src/runtime/plan9/386/sys.s, and then 9vx crashes:

% goroutines
9vx panic: kernel fault: signo=11 addr=0[ffffffffbf44a000] 1 eip=0
esp=7f37b5eecd70
aborting, to dump core.

I have no idea what is causing it to die, I've tried adding a bunch of
INT $3 to see how far in the flow I can get, but all I get this:

9vx panic: unknown trap/intr: 0x203
aborting, to dump core.

for an INT $3 just before
CALL	SI	// fn()

Pavel

[-- Attachment #2: golang_plan9_9vx.diff --]
[-- Type: text/x-patch, Size: 3739 bytes --]

diff -r ad4f2cbb85ef src/cmd/8l/obj.c
--- a/src/cmd/8l/obj.c	Thu Jan 13 20:05:08 2011 -0800
+++ b/src/cmd/8l/obj.c	Fri Jan 14 19:04:02 2011 +0200
@@ -185,6 +185,7 @@
 			INITRND = 0;
 		break;
 	case 2:	/* plan 9 */
+		tlsoffset = -8;
 		HEADR = 32L;
 		if(INITTEXT == -1)
 			INITTEXT = 4096+32;
diff -r ad4f2cbb85ef src/cmd/8l/pass.c
--- a/src/cmd/8l/pass.c	Thu Jan 13 20:05:08 2011 -0800
+++ b/src/cmd/8l/pass.c	Fri Jan 14 19:04:02 2011 +0200
@@ -243,6 +243,7 @@
 	Prog *p, *q;
 	Sym *s;
 	int32 vexit;
+	Sym *plan9_tos;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f mkfwd\n", cputime());
@@ -253,6 +254,10 @@
 	Bflush(&bso);
 	s = lookup("exit", 0);
 	vexit = s->value;
+	
+	if(HEADTYPE == 2)
+		plan9_tos = lookup("_tos", 0);
+	
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
 		for(p = cursym->text; p != P; p = p->link) {
 			if(HEADTYPE == 10) {	// Windows
@@ -296,9 +301,15 @@
 			if(HEADTYPE == 2) {	// Plan 9
 				if(p->from.type == D_INDIR+D_GS
 				&& p->to.type >= D_AX && p->to.type <= D_DI) {
+					q = appendp(p);
+					q->from = p->from;
+					q->from.type = D_INDIR + p->to.type;
+					q->to = p->to;
+					q->as = p->as;
 					p->as = AMOVL;
-					p->from.type = D_ADDR+D_STATIC;
-					p->from.offset += 0xdfffefc0;
+					p->from.type = D_EXTERN;
+					p->from.sym = plan9_tos;
+					p->from.offset = 0;
 				}
 			}
 			if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) {
@@ -382,6 +393,7 @@
 	int a;
 	Prog *pmorestack;
 	Sym *symmorestack;
+	Sym *plan9_tos;
 
 	pmorestack = P;
 	symmorestack = lookup("runtime.morestack", 0);
@@ -392,6 +404,9 @@
 		pmorestack = symmorestack->text;
 		symmorestack->text->from.scale |= NOSPLIT;
 	}
+	
+	if(HEADTYPE == 2)	
+		plan9_tos = lookup("_tos", 0);
 
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
 		if(cursym->text == nil || cursym->text->link == nil)
@@ -436,9 +451,15 @@
 			
 			case 2:	// Plan 9
 				p->as = AMOVL;
-				p->from.type = D_ADDR+D_STATIC;
-				p->from.offset = 0xdfffefc0;
+				p->from.type = D_EXTERN;
+				p->from.sym = plan9_tos;
 				p->to.type = D_CX;
+				
+				p = appendp(p);
+				p->as = AMOVL;
+				p->from.type = D_INDIR+D_CX;
+				p->from.offset = tlsoffset + 0;
+				p->to.type = D_CX;				
 				break;
 			
 			default:
diff -r ad4f2cbb85ef src/pkg/runtime/mkasmh.sh
--- a/src/pkg/runtime/mkasmh.sh	Thu Jan 13 20:05:08 2011 -0800
+++ b/src/pkg/runtime/mkasmh.sh	Fri Jan 14 19:04:02 2011 +0200
@@ -25,9 +25,9 @@
 		echo '#define	m(r)	4(r)'
 		;;
 	plan9)
-		echo '#define	get_tls(r)'
-		echo '#define	g(r)	0xdfffefc0'
-		echo '#define	m(r)	0xdfffefc4'
+		echo '#define	get_tls(r)	MOVL _tos(SB), r '
+		echo '#define	g(r)	-8(r)'
+		echo '#define	m(r)	-4(r)'
 		;;
 	linux)
 		# On Linux systems, what we call 0(GS) and 4(GS) for g and m
diff -r ad4f2cbb85ef src/pkg/runtime/plan9/386/defs.h
--- a/src/pkg/runtime/plan9/386/defs.h	Thu Jan 13 20:05:08 2011 -0800
+++ b/src/pkg/runtime/plan9/386/defs.h	Fri Jan 14 19:04:02 2011 +0200
@@ -1,1 +1,2 @@
 // nothing to see here
+#define tos_pid 48
diff -r ad4f2cbb85ef src/pkg/runtime/plan9/386/sys.s
--- a/src/pkg/runtime/plan9/386/sys.s	Thu Jan 13 20:05:08 2011 -0800
+++ b/src/pkg/runtime/plan9/386/sys.s	Fri Jan 14 19:04:02 2011 +0200
@@ -58,18 +58,19 @@
 	MOVL	BX, m(AX)
 
 	// Initialize AX from _tos->pid
-	MOVL	0xdfffeff8, AX
+	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
+//	PUSHAL
+//	CALL	runtime·emptyfunc(SB)
+//	POPAL
 	
 	CALL	SI	// fn()
 	CALL	runtime·exit(SB)

[-- Attachment #3: hello.go --]
[-- Type: application/octet-stream, Size: 59 bytes --]

package main

func main() {
        println("Hello Go!")
}

[-- Attachment #4: goroutines.go --]
[-- Type: application/octet-stream, Size: 225 bytes --]

package main

import "runtime"


func until(id int) {
	for i := 0; i < 10; i++ {
		println("id:", id, i)
        	runtime.Gosched()	
	}
        
}

func main() {
	runtime.GOMAXPROCS(2)
        go until(2)
        until(1)	
}

[-- Attachment #5: goroutines --]
[-- Type: application/octet-stream, Size: 122007 bytes --]

[-- Attachment #6: hello --]
[-- Type: application/octet-stream, Size: 96564 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-14 17:32       ` Pavel Zholkover
@ 2011-01-15  2:00         ` Anthony Martin
  2011-01-15  9:47           ` Pavel Zholkover
  2011-01-15  9:01         ` kokamoto
  1 sibling, 1 reply; 36+ messages in thread
From: Anthony Martin @ 2011-01-15  2:00 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

Pavel Zholkover <paulzhol@gmail.com> once said:
> I have no idea what is causing it to die, I've tried adding a bunch of
> INT $3 to see how far in the flow I can get, but all I get this:
>
> 9vx panic: unknown trap/intr: 0x203
> aborting, to dump core.
>
> for an INT $3 just before
> CALL	SI	// fn()

This happens because the linker outputs the two bytes
{ 0xCD, 0x03 } for an INT $3 instruction but libvx32
only sends a VXTRAP_BREAKPOINT to 9vx if it sees an
INT3 instruction (a single 0xCC byte). Try using a
'BYTE $0xCC' instead.

  Anthony



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-14 17:32       ` Pavel Zholkover
  2011-01-15  2:00         ` Anthony Martin
@ 2011-01-15  9:01         ` kokamoto
  2011-01-15  9:19           ` Pavel Zholkover
  2011-01-15  9:30           ` lucio
  1 sibling, 2 replies; 36+ messages in thread
From: kokamoto @ 2011-01-15  9:01 UTC (permalink / raw)
  To: 9fans

I'm a bit cinfusing...

There is a flag (GPOS=plan9) to ebnable plan9 os in the standard Go dsitribution.
How the patches you posted here now and before are related to that flag.
I suppose the original plan9 flag is for plan9port.
Am I correct?

That plan9 flag works for plan9port?
Then how I can use it on my linux box with plan9port.

Kenji




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15  9:01         ` kokamoto
@ 2011-01-15  9:19           ` Pavel Zholkover
  2011-01-15  9:30           ` lucio
  1 sibling, 0 replies; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-15  9:19 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Sat, Jan 15, 2011 at 11:01 AM,  <kokamoto@hera.eonet.ne.jp> wrote:
> I'm a bit cinfusing...
>
> There is a flag (GPOS=plan9) to ebnable plan9 os in the standard Go dsitribution.
> How the patches you posted here now and before are related to that flag.
> I suppose the original plan9 flag is for plan9port.
> Am I correct?
>
> That plan9 flag works for plan9port?
> Then how I can use it on my linux box with plan9port.
>
> Kenji
>

Setting GOOS=plan9 when using the main Go distribution (and linking
with symbols stripped 8l -s) will compile to native plan 9 binaries.
They assume a stack layout that is not correct when running on 9vx as
Anthony points out.

The patch I posted is to replace the hard coded values with relative
offsets from _tos, so the binaries will run both in 9vx and on a
native install of plan 9.

Previously I posted a patch for syscall and os Go packages against the
Go distribution to allow writing code that can actually do something
useful besides println.

I'm not sure what you mean by using these with plan9port...

Pavel



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15  9:01         ` kokamoto
  2011-01-15  9:19           ` Pavel Zholkover
@ 2011-01-15  9:30           ` lucio
  2011-01-15  9:58             ` Pavel Zholkover
  1 sibling, 1 reply; 36+ messages in thread
From: lucio @ 2011-01-15  9:30 UTC (permalink / raw)
  To: 9fans

> That plan9 flag works for plan9port?
> Then how I can use it on my linux box with plan9port.

I looked at connecting Go and p9p a few months back, before my
assignments in Cape Town put a halt to my efforts.  My conclusion at
the time was that it was a worthwhile objective that could be
accomplished, but not without a great deal of trouble.  Because of the
scope of the project, I estimated that the chances of getting upstream
approval for the changes, be they to p9p or to Go, would be minimal
despite Russ' involvement in both projects.

Merging p9p, Go and Plan 9 in a portable manner seems to me to be
really hard.  I would be extremely pleasantly surprised if somebody
had achieved even the smallest portion of such merging and had it
pulled up to the source projects.  Also, without carefully
documentation one runs a real risk of having to repeat and sometimes
rediscover many of the changes.  At least, that is the situation I am
confronted by at this very moment.

In a nutshell, I actually took a very recent release of Go and tried
to build a Plan 9 version:

	cd $GOROOT/src
	GOOS=plan9 ./make.bash

I was not surprised that it did not build correctly on my Ubuntu
workstation.  Fixing it did not seem a trivial task and a cursory web
search did not reveal any encouraging help.

Right now, I have a few days in which to resurrect work I did
initially that concluded with a "working" version of the Hello World
"C" program compiled and executed on Plan 9/386 using modifed Go
sources to compile and build the "C" development toolchain under Plan
9.  It is daunting how much effort I estimate I will need to do to get
that far, specially with a view to propagate the rather extensive
changes to the Go source release.  On the positive side, I had
invested no effort in the Go aspects of the project and I'm grateful
to those who have added the Go features for Plan 9 to the Go release.

My regret is that I am so far out of the loop, I don't even know where
the loop is :-(

++L




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15  2:00         ` Anthony Martin
@ 2011-01-15  9:47           ` Pavel Zholkover
  0 siblings, 0 replies; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-15  9:47 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Sat, Jan 15, 2011 at 4:00 AM, Anthony Martin <ality@pbrane.org> wrote:
> Pavel Zholkover <paulzhol@gmail.com> once said:
>> I have no idea what is causing it to die, I've tried adding a bunch of
>> INT $3 to see how far in the flow I can get, but all I get this:
>>
>> 9vx panic: unknown trap/intr: 0x203
>> aborting, to dump core.
>>
>> for an INT $3 just before
>> CALL  SI      // fn()
>
> This happens because the linker outputs the two bytes
> { 0xCD, 0x03 } for an INT $3 instruction but libvx32
> only sends a VXTRAP_BREAKPOINT to 9vx if it sees an
> INT3 instruction (a single 0xCC byte). Try using a
> 'BYTE $0xCC' instead.
>
>  Anthony

Thanks, that did the trick.

This is what I get when running goroutines on 9vx with a 0xCC
breakpoint compiled in:
% goroutines
goroutines 69: suicide: sys: breakpoint pc=0x00009e44
id: 1 0
id: 1 1
id: 1 2
id: 1 3
id: 1 4
id: 1 5
id: 1 6
id: 1 7
id: 1 8
id: 1 9
% acid 69
/proc/69/text:386 plan 9 executable
/sys/lib/acid/port
/sys/lib/acid/386
no symbol information
acid: regs()
PC      0x00009e44 0x9e44  ?file?:0
SP      0x000560e0 ECODE 0x00000000 EFLAG 0x00000000
CS      0x00000000 DS    0x00000000 SS  0x00000000
GS      0x00000000 FS    0x00000000 ES  0x00000000
TRAP    0x00000003 breakpoint
AX      0x0004c0c0 BX   0x0004c0c0 CX   0x0fffffc8 DX   0x00054100
DI      0x00056100 SI   0x000072f8 BP   0x00000000

acid: asm(*PC-32)
0x9e24 0x00009e24       ADDL    $0x1ed2c,AX
0x9e29 0x00009e29       MOVL    DX,0xfffffff8(AX)
0x9e2c 0x00009e2c       MOVL    BX,0xfffffffc(AX)
0x9e2f 0x00009e2f       MOVL    0x1ed2c,AX
0x9e35 0x00009e35       MOVL    0x30(AX),AX
0x9e38 0x00009e38       MOVL    AX,0x24(BX)
0x9e3b 0x00009e3b       CALL    0x1c10
0x9e40 0x00009e40       MOVL    0x0(DX),DX
0x9e42 0x00009e42       MOVL    0x0(BX),BX
0x9e44 0x00009e44       INT     3  <=== we stopped here,
runtime.rfork() in src/pkg/runtime/plan9/sys.s
0x9e45 0x00009e45       CALL*   SI
0x9e47 0x00009e47       CALL    0x9eac
0x9e4c 0x00009e4c       RET

0x72f8 is runtime.mstart as it should...

acid: asm(*SI)
0x72f8 0x000072f8       MOVL    0x1ed2c,CX
0x72fe 0x000072fe       MOVL    0xfffffff8(CX),CX
0x7301 0x00007301       CMPL    0x0(CX),SP
0x7303 0x00007303       JHI     0x730e
0x7305 0x00007305       XORL    DX,DX
0x7307 0x00007307       XORL    AX,AX
0x7309 0x00007309       CALL    0x1a75
0x730e 0x0000730e       SUBL    $0x8,SP
0x7311 0x00007311       MOVL    0x1ed2c,AX
0x7317 0x00007317       MOVL    0xfffffff8(AX),AX
0x731a 0x0000731a       MOVL    0x1ed2c,CX
0x7320 0x00007320       MOVL    0xfffffffc(CX),CX
0x7323 0x00007323       MOVL    0x0(CX),CX
0x7325 0x00007325       CMPL    CX,AX
0x7327 0x00007327       JEQ     0x7336
0x7329 0x00007329       MOVL    $0x1eb80,AX
0x732e 0x0000732e       MOVL    AX,0x0(SP)
0x7331 0x00007331       CALL    0x81ee
0x7336 0x00007336       MOVL    0x1ed2c,AX
0x733c 0x0000733c       MOVL    0xfffffffc(AX),AX
0x733f 0x0000733f       MOVL    0x94(AX),AX
0x7345 0x00007345       CMPL    AX,$0x0
0x7348 0x00007348       JNE     0x735e
0x734a 0x0000734a       CALL    0x2d75
0x734f 0x0000734f       MOVL    0x1ed2c,CX
0x7355 0x00007355       MOVL    0xfffffffc(CX),CX
0x7358 0x00007358       MOVL    AX,0x94(CX)
0x735e 0x0000735e       CALL    0x9e4d
0x7363 0x00007363       CALL    0x74c3
0x7368 0x00007368       ADDL    $0x8,SP

I can't tell from this why 9vx is dying on me and I don't know how to
use acid to debug a child process after rfork,
is there something like gdb's set follow-fork-mode child ?

Pavel



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15  9:30           ` lucio
@ 2011-01-15  9:58             ` Pavel Zholkover
  2011-01-15 10:29               ` lucio
  2011-01-15 10:40               ` lucio
  0 siblings, 2 replies; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-15  9:58 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

On Sat, Jan 15, 2011 at 11:30 AM,  <lucio@proxima.alt.za> wrote:
> In a nutshell, I actually took a very recent release of Go and tried
> to build a Plan 9 version:
>
>        cd $GOROOT/src
>        GOOS=plan9 ./make.bash
>
> I was not surprised that it did not build correctly on my Ubuntu
> workstation.  Fixing it did not seem a trivial task and a cursory web
> search did not reveal any encouraging help.

If you try applying http://codereview.appspot.com/3816043/ you can get
pretty far..
you need to
cd src/pkg
make clean
GOOS=plan9 make -k install

You'll get os, syscall, fmt and a bunch of other portable go libraries.

> Right now, I have a few days in which to resurrect work I did
> initially that concluded with a "working" version of the Hello World
> "C" program compiled and executed on Plan 9/386 using modifed Go
> sources to compile and build the "C" development toolchain under Plan
> 9.  It is daunting how much effort I estimate I will need to do to get
> that far, specially with a view to propagate the rather extensive
> changes to the Go source release.  On the positive side, I had
> invested no effort in the Go aspects of the project and I'm grateful
> to those who have added the Go features for Plan 9 to the Go release.
>

I think that you can produce a "C" hello world pretty easily if you
provide stubs for 8l (like morestack and etc.) and use GOOS=plan9 8l
-s to link you stuff together.

Pavel



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15  9:58             ` Pavel Zholkover
@ 2011-01-15 10:29               ` lucio
  2011-01-15 10:40               ` lucio
  1 sibling, 0 replies; 36+ messages in thread
From: lucio @ 2011-01-15 10:29 UTC (permalink / raw)
  To: 9fans

> I think that you can produce a "C" hello world pretty easily if you
> provide stubs for 8l (like morestack and etc.) and use GOOS=plan9 8l
> -s to link you stuff together.

Thank you, it's my intention to get as many of these poorly connected
pieces under my belt so I have a better view of the whole picture, so
I'll definitely try out your suggestions and possibly build them into
rc and/or sh scripts so they are not easily lost :-)

My primary objective was and remains to jack up the Plan 9 "C"
toolchain with newer features it failed to inherit from Inferno and
now Go, with my own emphasis on ELF capabilities.  There's one
significant hurdle to be surmounted, more a design issue than a
practical problem, namely that the Plan 9 multi-architecture ways
deserve better multi-platform capabilities: the classic approach lacks
equivalent convenience to be able to target Operating Systems other
than Plan 9.

That one can get the Go language and all its novelties and excitement
thrown in can only be considered a gift from (Google-) heaven.

In passing, there is no doubt that you have a much better
understanding of the issues surrounding this subject than I have.  I
hope you don't mind me asking for direction when I get lost.  I also
hope that others on this mailing list have sufficient interest in the
Go port to Plan 9 to bear with my occasional post.

++L




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15  9:58             ` Pavel Zholkover
  2011-01-15 10:29               ` lucio
@ 2011-01-15 10:40               ` lucio
  2011-01-15 11:25                 ` Pavel Zholkover
  1 sibling, 1 reply; 36+ messages in thread
From: lucio @ 2011-01-15 10:40 UTC (permalink / raw)
  To: 9fans

> If you try applying http://codereview.appspot.com/3816043/ you can get
> pretty far..

Could you provide more detailed instructions, please?  Mercurial seems
very helpful, but the learning curve can be quite steep.  I presume
this requires hg to be involved?

++L




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15 10:40               ` lucio
@ 2011-01-15 11:25                 ` Pavel Zholkover
  2011-01-16  1:51                   ` kokamoto
  0 siblings, 1 reply; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-15 11:25 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

[-- Attachment #1: Type: text/plain, Size: 536 bytes --]

On Sat, Jan 15, 2011 at 12:40 PM,  <lucio@proxima.alt.za> wrote:
>> If you try applying http://codereview.appspot.com/3816043/ you can get
>> pretty far..
>
> Could you provide more detailed instructions, please?  Mercurial seems
> very helpful, but the learning curve can be quite steep.  I presume
> this requires hg to be involved?
>
> ++L
>

There is some trouble using patch to apply the raw patches from the
Rietveld code review site as Skip found out,
So I've attached a diff without the hg history stuff.

Pavel

[-- Attachment #2: issue3816043_43001.diff --]
[-- Type: text/x-patch, Size: 87851 bytes --]

diff -r 09ab865d875c src/pkg/os/Makefile
--- a/src/pkg/os/Makefile	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/Makefile	Sat Jan 15 13:00:13 2011 +0200
@@ -19,24 +19,42 @@
 	types.go\
 
 GOFILES_freebsd=\
+	error_posix.go\
 	env_unix.go\
+	file_posix.go\
 	file_unix.go\
 	sys_bsd.go\
+	exec_unix.go
 
 GOFILES_darwin=\
+	error_posix.go\
 	env_unix.go\
+	file_posix.go\
 	file_unix.go\
 	sys_bsd.go\
+	exec_unix.go
 
 GOFILES_linux=\
+	error_posix.go\
 	env_unix.go\
+	file_posix.go\
 	file_unix.go\
 	sys_linux.go\
+	exec_unix.go
 
 GOFILES_windows=\
+	error_posix.go\
 	env_windows.go\
+	file_posix.go\
 	file_windows.go\
 	sys_windows.go\
+	exec_unix.go
+
+GOFILES_plan9=\
+	error_plan9.go\
+	env_plan9.go\
+	file_plan9.go\
+	sys_plan9.go\
 
 GOFILES+=$(GOFILES_$(GOOS))
 
diff -r 09ab865d875c src/pkg/os/dir_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/dir_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,273 @@
+// Copyright 2009 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.
+
+package os
+
+import (
+	"syscall"
+)
+
+const (
+	blockSize = 4096 // TODO(r): use statfs
+)
+
+type dirInfo int
+
+
+// Readdir reads the contents of the directory associated with file and
+// returns an array of up to count FileInfo structures, as would be returned
+// by Lstat, in directory order.  Subsequent calls on the same file will yield
+// further FileInfos.
+// A negative count means to read until EOF.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
+	size := count
+	if size < 0 {
+		size = 100
+	}
+
+	// ToDo: Investigate a bug in allocation/memory/slice append when more than one iteration of Read is done.
+	result := make([]FileInfo, 0, size)
+	buf := make([]byte, syscall.STATMAX /*448*/ )
+
+	var e Error = nil
+	for e == nil {
+		n, e := file.Read(buf)
+
+		if e != nil {
+			if e == EOF {
+				break
+			}
+
+			return []FileInfo{}, &PathError{"readdir", file.name, e}
+		}
+
+		if n < syscall.STATFIXLEN {
+			return []FileInfo{}, &PathError{"readdir", file.name, syscall.Etoosmall}
+		}
+
+		for i := 0; i < n; {
+			m, _ := gbit16(buf[i:])
+			m += 2
+
+			if m < syscall.STATFIXLEN {
+				return []FileInfo{}, &PathError{"readdir", file.name, syscall.Ebadstat}
+			}
+
+			d, e := UnmarshalDir(buf[i : i+int(m)])
+
+			if e != nil {
+				return []FileInfo{}, &PathError{"readdir", file.name, e}
+			}
+
+			var f FileInfo
+			fileInfoFromStat(&f, d)
+
+			result = append(result, f)
+
+			if count > 0 && len(result) >= count {
+				break
+			}
+
+			i += int(m)
+		}
+	}
+
+	if e != nil && e != EOF {
+		return []FileInfo{}, e
+	}
+
+	return result, nil
+}
+
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+	fi, e := file.Readdir(count)
+
+	if e != nil {
+		return []string{}, e
+	}
+
+	names = make([]string, len(fi))
+	err = nil
+
+	for i, _ := range fi {
+		names[i] = fi[i].Name
+	}
+
+	return
+}
+
+type Dir struct {
+	Type   uint16
+	Dev    uint32
+	Qid    Qid
+	Mode   uint32
+	Atime  uint32
+	Mtime  uint32
+	Length uint64
+	Name   string
+	Uid    string
+	Gid    string
+	Muid   string
+}
+
+type Qid struct {
+	Path uint64
+	Vers uint32
+	Type uint8
+}
+
+
+var nullDir = Dir{
+	^uint16(0),
+	^uint32(0),
+	Qid{^uint64(0), ^uint32(0), ^uint8(0)},
+	^uint32(0),
+	^uint32(0),
+	^uint32(0),
+	^uint64(0),
+	"",
+	"",
+	"",
+	"",
+}
+
+func pdir(b []byte, d *Dir) []byte {
+	n := len(b)
+	b = pbit16(b, 0) // length, filled in later	
+	b = pbit16(b, d.Type)
+	b = pbit32(b, d.Dev)
+	b = pqid(b, d.Qid)
+	b = pbit32(b, d.Mode)
+	b = pbit32(b, d.Atime)
+	b = pbit32(b, d.Mtime)
+	b = pbit64(b, d.Length)
+	b = pstring(b, d.Name)
+	b = pstring(b, d.Uid)
+	b = pstring(b, d.Gid)
+	b = pstring(b, d.Muid)
+	pbit16(b[0:n], uint16(len(b)-(n+2)))
+	return b
+}
+
+func UnmarshalDir(b []byte) (d *Dir, err Error) {
+	n := uint16(0)
+	n, b = gbit16(b)
+
+	if int(n) != len(b) {
+		return nil, syscall.Ebadstat
+	}
+
+	d = new(Dir)
+	d.Type, b = gbit16(b)
+	d.Dev, b = gbit32(b)
+	d.Qid, b = gqid(b)
+	d.Mode, b = gbit32(b)
+	d.Atime, b = gbit32(b)
+	d.Mtime, b = gbit32(b)
+	d.Length, b = gbit64(b)
+	d.Name, b = gstring(b)
+	d.Uid, b = gstring(b)
+	d.Gid, b = gstring(b)
+	d.Muid, b = gstring(b)
+
+	if len(b) != 0 {
+		return nil, syscall.Ebadstat
+	}
+
+	return d, nil
+}
+
+func gqid(b []byte) (Qid, []byte) {
+	var q Qid
+	q.Path, b = gbit64(b)
+	q.Vers, b = gbit32(b)
+	q.Type, b = gbit8(b)
+	return q, b
+}
+
+func pqid(b []byte, q Qid) []byte {
+	b = pbit64(b, q.Path)
+	b = pbit32(b, q.Vers)
+	b = pbit8(b, q.Type)
+	return b
+}
+
+func gbit8(b []byte) (uint8, []byte) {
+	return uint8(b[0]), b[1:]
+}
+
+func gbit16(b []byte) (uint16, []byte) {
+	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+func gbit32(b []byte) (uint32, []byte) {
+	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+func gbit64(b []byte) (uint64, []byte) {
+	lo, b := gbit32(b)
+	hi, b := gbit32(b)
+	return uint64(hi)<<32 | uint64(lo), b
+}
+
+func gstring(b []byte) (string, []byte) {
+	n, b := gbit16(b)
+	return string(b[0:n]), b[n:]
+}
+
+func pbit8(b []byte, x uint8) []byte {
+	n := len(b)
+	if n+1 > cap(b) {
+		nb := make([]byte, n, 100+2*cap(b))
+		copy(nb, b)
+		b = nb
+	}
+	b = b[0 : n+1]
+	b[n] = x
+	return b
+}
+
+func pbit16(b []byte, x uint16) []byte {
+	n := len(b)
+	if n+2 > cap(b) {
+		nb := make([]byte, n, 100+2*cap(b))
+		copy(nb, b)
+		b = nb
+	}
+	b = b[0 : n+2]
+	b[n] = byte(x)
+	b[n+1] = byte(x >> 8)
+	return b
+}
+
+func pbit32(b []byte, x uint32) []byte {
+	n := len(b)
+	if n+4 > cap(b) {
+		nb := make([]byte, n, 100+2*cap(b))
+		copy(nb, b)
+		b = nb
+	}
+	b = b[0 : n+4]
+	b[n] = byte(x)
+	b[n+1] = byte(x >> 8)
+	b[n+2] = byte(x >> 16)
+	b[n+3] = byte(x >> 24)
+	return b
+}
+
+func pbit64(b []byte, x uint64) []byte {
+	b = pbit32(b, uint32(x))
+	b = pbit32(b, uint32(x>>32))
+	return b
+}
+
+func pstring(b []byte, s string) []byte {
+	if len(s) >= 1<<16 {
+		panic(NewError("string too long"))
+	}
+	b = pbit16(b, uint16(len(s)))
+	b = append(b, []byte(s)...)
+	return b
+}
diff -r 09ab865d875c src/pkg/os/env_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/env_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,131 @@
+// 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.
+
+// Plan 9 environment variables.
+
+package os
+
+import (
+	"syscall"
+	"sync"
+)
+
+// ENOENV is the Error indicating that an environment variable does not exist.
+var ENOENV = NewError("no such environment variable")
+
+var env map[string]string
+var once sync.Once
+
+func copyenv() {
+	env = make(map[string]string)
+
+	f, e := Open("#e", O_RDONLY, 0)
+	if iserror(e) {
+		panic(e)
+	}
+
+	fi, e := f.Readdir(-1)
+	if iserror(e) {
+		f.Close()
+		panic(e)
+	}
+	f.Close()
+
+	buf := make([]byte, 4096)
+	for i, _ := range fi {
+		if f, e = Open("#e/"+fi[i].Name, O_RDONLY, 0); iserror(e) {
+			continue
+		}
+
+		if fi[i].Size > int64(cap(buf)) {
+			fi[i].Size = int64(cap(buf)) - 1
+		}
+
+		if fi[i].Size > 0 {
+			n, e := f.Read(buf[0:fi[i].Size])
+
+			if !iserror(e) {
+				buf[n] = 0
+				env[fi[i].Name] = string(buf[0:n])
+			}
+		} else {
+			env[fi[i].Name] = ""
+		}
+
+		f.Close()
+	}
+}
+
+// Getenverror retrieves the value of the environment variable named by the key.
+// It returns the value and an error, if any.
+func Getenverror(key string) (value string, err Error) {
+	once.Do(copyenv)
+
+	if len(key) == 0 {
+		return "", syscall.Enonexist
+	}
+	v, ok := env[key]
+	if !ok {
+		return "", ENOENV
+	}
+	return v, nil
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+	v, _ := Getenverror(key)
+	return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an Error, if any.
+func Setenv(key, value string) Error {
+	once.Do(copyenv)
+
+	if len(key) == 0 {
+		return syscall.Enonexist
+	}
+
+	f, e := Open("#e/"+key, O_WRONLY|O_CREAT, 0666)
+	if iserror(e) {
+		return e
+	}
+	defer f.Close()
+
+	_, e = f.Write(syscall.StringByteSlice(value))
+
+	env[key] = value
+	return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+	once.Do(copyenv) // prevent copyenv in Getenv/Setenv
+	env = make(map[string]string)
+
+	syscall.RawSyscall(syscall.SYS_RFORK, syscall.RFCENVG, 0, 0)
+}
+
+// Environ returns an array of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+	once.Do(copyenv)
+	a := make([]string, len(env))
+	i := 0
+	for k, v := range env {
+		// check i < len(a) for safety,
+		// in case env is changing underfoot.
+		if i < len(a) {
+			a[i] = k + "=" + v
+			i++
+		}
+	}
+	return a[0:i]
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+	return "/tmp"
+}
diff -r 09ab865d875c src/pkg/os/error.go
--- a/src/pkg/os/error.go	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/error.go	Sat Jan 15 13:00:13 2011 +0200
@@ -4,8 +4,6 @@
 
 package os
 
-import syscall "syscall"
-
 // An Error can represent any printable error condition.
 type Error interface {
 	String() string
@@ -26,61 +24,6 @@
 // NewError converts s to an ErrorString, which satisfies the Error interface.
 func NewError(s string) Error { return ErrorString(s) }
 
-// Errno is the Unix error number.  Names such as EINVAL are simple
-// wrappers to convert the error number into an Error.
-type Errno int64
-
-func (e Errno) String() string { return syscall.Errstr(int(e)) }
-
-func (e Errno) Temporary() bool {
-	return e == Errno(syscall.EINTR) || e.Timeout()
-}
-
-func (e Errno) Timeout() bool {
-	return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK)
-}
-
-// Commonly known Unix errors.
-var (
-	EPERM        Error = Errno(syscall.EPERM)
-	ENOENT       Error = Errno(syscall.ENOENT)
-	ESRCH        Error = Errno(syscall.ESRCH)
-	EINTR        Error = Errno(syscall.EINTR)
-	EIO          Error = Errno(syscall.EIO)
-	ENXIO        Error = Errno(syscall.ENXIO)
-	E2BIG        Error = Errno(syscall.E2BIG)
-	ENOEXEC      Error = Errno(syscall.ENOEXEC)
-	EBADF        Error = Errno(syscall.EBADF)
-	ECHILD       Error = Errno(syscall.ECHILD)
-	EDEADLK      Error = Errno(syscall.EDEADLK)
-	ENOMEM       Error = Errno(syscall.ENOMEM)
-	EACCES       Error = Errno(syscall.EACCES)
-	EFAULT       Error = Errno(syscall.EFAULT)
-	EBUSY        Error = Errno(syscall.EBUSY)
-	EEXIST       Error = Errno(syscall.EEXIST)
-	EXDEV        Error = Errno(syscall.EXDEV)
-	ENODEV       Error = Errno(syscall.ENODEV)
-	ENOTDIR      Error = Errno(syscall.ENOTDIR)
-	EISDIR       Error = Errno(syscall.EISDIR)
-	EINVAL       Error = Errno(syscall.EINVAL)
-	ENFILE       Error = Errno(syscall.ENFILE)
-	EMFILE       Error = Errno(syscall.EMFILE)
-	ENOTTY       Error = Errno(syscall.ENOTTY)
-	EFBIG        Error = Errno(syscall.EFBIG)
-	ENOSPC       Error = Errno(syscall.ENOSPC)
-	ESPIPE       Error = Errno(syscall.ESPIPE)
-	EROFS        Error = Errno(syscall.EROFS)
-	EMLINK       Error = Errno(syscall.EMLINK)
-	EPIPE        Error = Errno(syscall.EPIPE)
-	EAGAIN       Error = Errno(syscall.EAGAIN)
-	EDOM         Error = Errno(syscall.EDOM)
-	ERANGE       Error = Errno(syscall.ERANGE)
-	EADDRINUSE   Error = Errno(syscall.EADDRINUSE)
-	ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
-	ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
-	EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
-)
-
 // PathError records an error and the operation and file path that caused it.
 type PathError struct {
 	Op    string
@@ -89,25 +32,3 @@
 }
 
 func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
-	Syscall string
-	Errno   Errno
-}
-
-func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
-
-// Note: If the name of the function NewSyscallError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
-
-// NewSyscallError returns, as an Error, a new SyscallError
-// with the given system call name and error number.
-// As a convenience, if errno is 0, NewSyscallError returns nil.
-func NewSyscallError(syscall string, errno int) Error {
-	if errno == 0 {
-		return nil
-	}
-	return &SyscallError{syscall, Errno(errno)}
-}
diff -r 09ab865d875c src/pkg/os/error_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/error_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,48 @@
+// 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.
+
+package os
+
+import syscall "syscall"
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+	Syscall string
+	Err     string
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Err }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error number.
+// As a convenience, if errno is 0, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err syscall.Error) Error {
+	if err == nil {
+		return nil
+	}
+	return &SyscallError{syscall, err.String()}
+}
+
+var (
+	EINVAL       Error = syscall.Ebadarg
+	ENOTDIR      Error = syscall.Enotdir
+	ENOENT       Error = syscall.Enonexist
+	ENAMETOOLONG Error = NewError("file name too long")
+	EPIPE        = syscall.EPIPE
+
+	ERANGE Error = NewError("math result not representable")
+	EEXIST Error = syscall.Eexist
+
+	EPLAN9 Error = NewError("not supported by plan 9")
+)
+
+func iserror(err syscall.Error) bool {
+	return err != nil
+}
+
+func Errno(e syscall.Error) syscall.Error { return e }
diff -r 09ab865d875c src/pkg/os/error_posix.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/error_posix.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,88 @@
+// Copyright 2009 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.
+
+package os
+
+import syscall "syscall"
+
+// Errno is the Unix error number.  Names such as EINVAL are simple
+// wrappers to convert the error number into an Error.
+type Errno int64
+
+func (e Errno) String() string { return syscall.Errstr(int(e)) }
+
+func (e Errno) Temporary() bool {
+	return e == Errno(syscall.EINTR) || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+	return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK)
+}
+
+// Commonly known Unix errors.
+var (
+	EPERM        Error = Errno(syscall.EPERM)
+	ENOENT       Error = Errno(syscall.ENOENT)
+	ESRCH        Error = Errno(syscall.ESRCH)
+	EINTR        Error = Errno(syscall.EINTR)
+	EIO          Error = Errno(syscall.EIO)
+	ENXIO        Error = Errno(syscall.ENXIO)
+	E2BIG        Error = Errno(syscall.E2BIG)
+	ENOEXEC      Error = Errno(syscall.ENOEXEC)
+	EBADF        Error = Errno(syscall.EBADF)
+	ECHILD       Error = Errno(syscall.ECHILD)
+	EDEADLK      Error = Errno(syscall.EDEADLK)
+	ENOMEM       Error = Errno(syscall.ENOMEM)
+	EACCES       Error = Errno(syscall.EACCES)
+	EFAULT       Error = Errno(syscall.EFAULT)
+	EBUSY        Error = Errno(syscall.EBUSY)
+	EEXIST       Error = Errno(syscall.EEXIST)
+	EXDEV        Error = Errno(syscall.EXDEV)
+	ENODEV       Error = Errno(syscall.ENODEV)
+	ENOTDIR      Error = Errno(syscall.ENOTDIR)
+	EISDIR       Error = Errno(syscall.EISDIR)
+	EINVAL       Error = Errno(syscall.EINVAL)
+	ENFILE       Error = Errno(syscall.ENFILE)
+	EMFILE       Error = Errno(syscall.EMFILE)
+	ENOTTY       Error = Errno(syscall.ENOTTY)
+	EFBIG        Error = Errno(syscall.EFBIG)
+	ENOSPC       Error = Errno(syscall.ENOSPC)
+	ESPIPE       Error = Errno(syscall.ESPIPE)
+	EROFS        Error = Errno(syscall.EROFS)
+	EMLINK       Error = Errno(syscall.EMLINK)
+	EPIPE        Error = Errno(syscall.EPIPE)
+	EAGAIN       Error = Errno(syscall.EAGAIN)
+	EDOM         Error = Errno(syscall.EDOM)
+	ERANGE       Error = Errno(syscall.ERANGE)
+	EADDRINUSE   Error = Errno(syscall.EADDRINUSE)
+	ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
+	ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
+	EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
+)
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+	Syscall string
+	Errno   Errno
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error number.
+// As a convenience, if errno is 0, NewSyscallError returns nil.
+func NewSyscallError(syscall string, errno int) Error {
+	if errno == 0 {
+		return nil
+	}
+	return &SyscallError{syscall, Errno(errno)}
+}
+
+func iserror(errno int) bool {
+	return errno != 0
+}
diff -r 09ab865d875c src/pkg/os/exec.go
--- a/src/pkg/os/exec.go	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/exec.go	Sat Jan 15 13:00:13 2011 +0200
@@ -8,145 +8,6 @@
 	"syscall"
 )
 
-// ForkExec forks the current process and invokes Exec with the program, arguments,
-// and environment specified by name, argv, and envv.  It returns the process
-// id of the forked process and an Error, if any.  The fd array specifies the
-// file descriptors to be set up in the new process: fd[0] will be Unix file
-// descriptor 0 (standard input), fd[1] descriptor 1, and so on.  A nil entry
-// will cause the child to have no open file descriptor with that index.
-// If dir is not empty, the child chdirs into the directory before execing the program.
-func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
-	if envv == nil {
-		envv = Environ()
-	}
-	// Create array of integer (system) fds.
-	intfd := make([]int, len(fd))
-	for i, f := range fd {
-		if f == nil {
-			intfd[i] = -1
-		} else {
-			intfd[i] = f.Fd()
-		}
-	}
-
-	p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
-	if e != 0 {
-		return 0, &PathError{"fork/exec", name, Errno(e)}
-	}
-	return p, nil
-}
-
-// Exec replaces the current process with an execution of the
-// named binary, with arguments argv and environment envv.
-// If successful, Exec never returns.  If it fails, it returns an Error.
-// ForkExec is almost always a better way to execute a program.
-func Exec(name string, argv []string, envv []string) Error {
-	if envv == nil {
-		envv = Environ()
-	}
-	e := syscall.Exec(name, argv, envv)
-	if e != 0 {
-		return &PathError{"exec", name, Errno(e)}
-	}
-	return nil
-}
-
-// TODO(rsc): Should os implement its own syscall.WaitStatus
-// wrapper with the methods, or is exposing the underlying one enough?
-//
-// TODO(rsc): Certainly need to have Rusage struct,
-// since syscall one might have different field types across
-// different OS.
-
-// Waitmsg stores the information about an exited process as reported by Wait.
-type Waitmsg struct {
-	Pid                int             // The process's id.
-	syscall.WaitStatus                 // System-dependent status info.
-	Rusage             *syscall.Rusage // System-dependent resource usage info.
-}
-
-// Options for Wait.
-const (
-	WNOHANG   = syscall.WNOHANG  // Don't wait if no process has exited.
-	WSTOPPED  = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
-	WUNTRACED = WSTOPPED
-	WRUSAGE   = 1 << 20 // Record resource usage.
-)
-
-// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
-// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
-// the options
-
-// Wait waits for process pid to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
-// (WNOHANG etc.) affect the behavior of the Wait call.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
-	var status syscall.WaitStatus
-	var rusage *syscall.Rusage
-	if options&WRUSAGE != 0 {
-		rusage = new(syscall.Rusage)
-		options ^= WRUSAGE
-	}
-	pid1, e := syscall.Wait4(pid, &status, options, rusage)
-	if e != 0 {
-		return nil, NewSyscallError("wait", e)
-	}
-	w = new(Waitmsg)
-	w.Pid = pid1
-	w.WaitStatus = status
-	w.Rusage = rusage
-	return w, nil
-}
-
-// Convert i to decimal string.
-func itod(i int) string {
-	if i == 0 {
-		return "0"
-	}
-
-	u := uint64(i)
-	if i < 0 {
-		u = -u
-	}
-
-	// Assemble decimal in reverse order.
-	var b [32]byte
-	bp := len(b)
-	for ; u > 0; u /= 10 {
-		bp--
-		b[bp] = byte(u%10) + '0'
-	}
-
-	if i < 0 {
-		bp--
-		b[bp] = '-'
-	}
-
-	return string(b[bp:])
-}
-
-func (w Waitmsg) String() string {
-	// TODO(austin) Use signal names when possible?
-	res := ""
-	switch {
-	case w.Exited():
-		res = "exit status " + itod(w.ExitStatus())
-	case w.Signaled():
-		res = "signal " + itod(w.Signal())
-	case w.Stopped():
-		res = "stop signal " + itod(w.StopSignal())
-		if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
-			res += " (trap " + itod(w.TrapCause()) + ")"
-		}
-	case w.Continued():
-		res = "continued"
-	}
-	if w.CoreDump() {
-		res += " (core dumped)"
-	}
-	return res
-}
-
 // Getpid returns the process id of the caller.
 func Getpid() int { return syscall.Getpid() }
 
diff -r 09ab865d875c src/pkg/os/exec_unix.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/exec_unix.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,148 @@
+// Copyright 2009 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.
+
+package os
+
+import (
+	"syscall"
+)
+
+// ForkExec forks the current process and invokes Exec with the program, arguments,
+// and environment specified by name, argv, and envv.  It returns the process
+// id of the forked process and an Error, if any.  The fd array specifies the
+// file descriptors to be set up in the new process: fd[0] will be Unix file
+// descriptor 0 (standard input), fd[1] descriptor 1, and so on.  A nil entry
+// will cause the child to have no open file descriptor with that index.
+// If dir is not empty, the child chdirs into the directory before execing the program.
+func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
+	if envv == nil {
+		envv = Environ()
+	}
+	// Create array of integer (system) fds.
+	intfd := make([]int, len(fd))
+	for i, f := range fd {
+		if f == nil {
+			intfd[i] = -1
+		} else {
+			intfd[i] = f.Fd()
+		}
+	}
+
+	p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
+	if e != 0 {
+		return 0, &PathError{"fork/exec", name, Errno(e)}
+	}
+	return p, nil
+}
+
+// Exec replaces the current process with an execution of the
+// named binary, with arguments argv and environment envv.
+// If successful, Exec never returns.  If it fails, it returns an Error.
+// ForkExec is almost always a better way to execute a program.
+func Exec(name string, argv []string, envv []string) Error {
+	if envv == nil {
+		envv = Environ()
+	}
+	e := syscall.Exec(name, argv, envv)
+	if e != 0 {
+		return &PathError{"exec", name, Errno(e)}
+	}
+	return nil
+}
+
+// TODO(rsc): Should os implement its own syscall.WaitStatus
+// wrapper with the methods, or is exposing the underlying one enough?
+//
+// TODO(rsc): Certainly need to have Rusage struct,
+// since syscall one might have different field types across
+// different OS.
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg struct {
+	Pid                int             // The process's id.
+	syscall.WaitStatus                 // System-dependent status info.
+	Rusage             *syscall.Rusage // System-dependent resource usage info.
+}
+
+// Options for Wait.
+const (
+	WNOHANG   = syscall.WNOHANG  // Don't wait if no process has exited.
+	WSTOPPED  = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
+	WUNTRACED = WSTOPPED
+	WRUSAGE   = 1 << 20 // Record resource usage.
+)
+
+// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
+// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
+// the options
+
+// Wait waits for process pid to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+	var status syscall.WaitStatus
+	var rusage *syscall.Rusage
+	if options&WRUSAGE != 0 {
+		rusage = new(syscall.Rusage)
+		options ^= WRUSAGE
+	}
+	pid1, e := syscall.Wait4(pid, &status, options, rusage)
+	if e != 0 {
+		return nil, NewSyscallError("wait", e)
+	}
+	w = new(Waitmsg)
+	w.Pid = pid1
+	w.WaitStatus = status
+	w.Rusage = rusage
+	return w, nil
+}
+
+// Convert i to decimal string.
+func itod(i int) string {
+	if i == 0 {
+		return "0"
+	}
+
+	u := uint64(i)
+	if i < 0 {
+		u = -u
+	}
+
+	// Assemble decimal in reverse order.
+	var b [32]byte
+	bp := len(b)
+	for ; u > 0; u /= 10 {
+		bp--
+		b[bp] = byte(u%10) + '0'
+	}
+
+	if i < 0 {
+		bp--
+		b[bp] = '-'
+	}
+
+	return string(b[bp:])
+}
+
+func (w Waitmsg) String() string {
+	// TODO(austin) Use signal names when possible?
+	res := ""
+	switch {
+	case w.Exited():
+		res = "exit status " + itod(w.ExitStatus())
+	case w.Signaled():
+		res = "signal " + itod(w.Signal())
+	case w.Stopped():
+		res = "stop signal " + itod(w.StopSignal())
+		if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
+			res += " (trap " + itod(w.TrapCause()) + ")"
+		}
+	case w.Continued():
+		res = "continued"
+	}
+	if w.CoreDump() {
+		res += " (core dumped)"
+	}
+	return res
+}
diff -r 09ab865d875c src/pkg/os/file.go
--- a/src/pkg/os/file.go	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/file.go	Sat Jan 15 13:00:13 2011 +0200
@@ -83,10 +83,10 @@
 	if n < 0 {
 		n = 0
 	}
-	if n == 0 && e == 0 {
+	if n == 0 && !iserror(e) {
 		return 0, EOF
 	}
-	if e != 0 {
+	if iserror(e) {
 		err = &PathError{"read", file.name, Errno(e)}
 	}
 	return n, err
@@ -102,10 +102,10 @@
 	}
 	for len(b) > 0 {
 		m, e := syscall.Pread(file.fd, b, off)
-		if m == 0 && e == 0 {
+		if m == 0 && !iserror(e) {
 			return n, EOF
 		}
-		if e != 0 {
+		if iserror(e) {
 			err = &PathError{"read", file.name, Errno(e)}
 			break
 		}
@@ -127,15 +127,10 @@
 	if n < 0 {
 		n = 0
 	}
-	if e == syscall.EPIPE {
-		file.nepipe++
-		if file.nepipe >= 10 {
-			Exit(syscall.EPIPE)
-		}
-	} else {
-		file.nepipe = 0
-	}
-	if e != 0 {
+
+	epipecheck(file, e)
+
+	if iserror(e) {
 		err = &PathError{"write", file.name, Errno(e)}
 	}
 	return n, err
@@ -150,7 +145,7 @@
 	}
 	for len(b) > 0 {
 		m, e := syscall.Pwrite(file.fd, b, off)
-		if e != 0 {
+		if iserror(e) {
 			err = &PathError{"write", file.name, Errno(e)}
 			break
 		}
@@ -167,10 +162,10 @@
 // It returns the new offset and an Error, if any.
 func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
 	r, e := syscall.Seek(file.fd, offset, whence)
-	if e == 0 && file.dirinfo != nil && r != 0 {
+	if !iserror(e) && file.dirinfo != nil && r != 0 {
 		e = syscall.EISDIR
 	}
-	if e != 0 {
+	if iserror(e) {
 		return 0, &PathError{"seek", file.name, Errno(e)}
 	}
 	return r, nil
@@ -187,71 +182,19 @@
 	return file.Write(b)
 }
 
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
-	var p [2]int
-
-	// See ../syscall/exec.go for description of lock.
-	syscall.ForkLock.RLock()
-	e := syscall.Pipe(p[0:])
-	if e != 0 {
-		syscall.ForkLock.RUnlock()
-		return nil, nil, NewSyscallError("pipe", e)
-	}
-	syscall.CloseOnExec(p[0])
-	syscall.CloseOnExec(p[1])
-	syscall.ForkLock.RUnlock()
-
-	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
-}
-
 // Mkdir creates a new directory with the specified name and permission bits.
 // It returns an error, if any.
 func Mkdir(name string, perm uint32) Error {
 	e := syscall.Mkdir(name, perm)
-	if e != 0 {
+	if iserror(e) {
 		return &PathError{"mkdir", name, Errno(e)}
 	}
 	return nil
 }
 
-// Stat returns a FileInfo structure describing the named file and an error, if any.
-// If name names a valid symbolic link, the returned FileInfo describes
-// the file pointed at by the link and has fi.FollowedSymlink set to true.
-// If name names an invalid symbolic link, the returned FileInfo describes
-// the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
-	var lstat, stat syscall.Stat_t
-	e := syscall.Lstat(name, &lstat)
-	if e != 0 {
-		return nil, &PathError{"stat", name, Errno(e)}
-	}
-	statp := &lstat
-	if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
-		e := syscall.Stat(name, &stat)
-		if e == 0 {
-			statp = &stat
-		}
-	}
-	return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
-}
-
-// Lstat returns the FileInfo structure describing the named file and an
-// error, if any.  If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link.  Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
-	var stat syscall.Stat_t
-	e := syscall.Lstat(name, &stat)
-	if e != 0 {
-		return nil, &PathError{"lstat", name, Errno(e)}
-	}
-	return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
-}
-
 // Chdir changes the current working directory to the named directory.
 func Chdir(dir string) Error {
-	if e := syscall.Chdir(dir); e != 0 {
+	if e := syscall.Chdir(dir); iserror(e) {
 		return &PathError{"chdir", dir, Errno(e)}
 	}
 	return nil
@@ -260,179 +203,8 @@
 // Chdir changes the current working directory to the file,
 // which must be a directory.
 func (f *File) Chdir() Error {
-	if e := syscall.Fchdir(f.fd); e != 0 {
+	if e := syscall.Fchdir(f.fd); iserror(e) {
 		return &PathError{"chdir", f.name, Errno(e)}
 	}
 	return nil
 }
-
-// Remove removes the named file or directory.
-func Remove(name string) Error {
-	// System call interface forces us to know
-	// whether name is a file or directory.
-	// Try both: it is cheaper on average than
-	// doing a Stat plus the right one.
-	e := syscall.Unlink(name)
-	if e == 0 {
-		return nil
-	}
-	e1 := syscall.Rmdir(name)
-	if e1 == 0 {
-		return nil
-	}
-
-	// Both failed: figure out which error to return.
-	// OS X and Linux differ on whether unlink(dir)
-	// returns EISDIR, so can't use that.  However,
-	// both agree that rmdir(file) returns ENOTDIR,
-	// so we can use that to decide which error is real.
-	// Rmdir might also return ENOTDIR if given a bad
-	// file path, like /etc/passwd/foo, but in that case,
-	// both errors will be ENOTDIR, so it's okay to
-	// use the error from unlink.
-	// For windows syscall.ENOTDIR is set
-	// to syscall.ERROR_DIRECTORY, hopefully it should
-	// do the trick.
-	if e1 != syscall.ENOTDIR {
-		e = e1
-	}
-	return &PathError{"remove", name, Errno(e)}
-}
-
-// LinkError records an error during a link or symlink or rename
-// system call and the paths that caused it.
-type LinkError struct {
-	Op    string
-	Old   string
-	New   string
-	Error Error
-}
-
-func (e *LinkError) String() string {
-	return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
-}
-
-// Link creates a hard link.
-func Link(oldname, newname string) Error {
-	e := syscall.Link(oldname, newname)
-	if e != 0 {
-		return &LinkError{"link", oldname, newname, Errno(e)}
-	}
-	return nil
-}
-
-// Symlink creates a symbolic link.
-func Symlink(oldname, newname string) Error {
-	e := syscall.Symlink(oldname, newname)
-	if e != 0 {
-		return &LinkError{"symlink", oldname, newname, Errno(e)}
-	}
-	return nil
-}
-
-// Readlink reads the contents of a symbolic link: the destination of
-// the link.  It returns the contents and an Error, if any.
-func Readlink(name string) (string, Error) {
-	for len := 128; ; len *= 2 {
-		b := make([]byte, len)
-		n, e := syscall.Readlink(name, b)
-		if e != 0 {
-			return "", &PathError{"readlink", name, Errno(e)}
-		}
-		if n < len {
-			return string(b[0:n]), nil
-		}
-	}
-	// Silence 6g.
-	return "", nil
-}
-
-// Rename renames a file.
-func Rename(oldname, newname string) Error {
-	e := syscall.Rename(oldname, newname)
-	if e != 0 {
-		return &LinkError{"rename", oldname, newname, Errno(e)}
-	}
-	return nil
-}
-
-// Chmod changes the mode of the named file to mode.
-// If the file is a symbolic link, it changes the mode of the link's target.
-func Chmod(name string, mode uint32) Error {
-	if e := syscall.Chmod(name, mode); e != 0 {
-		return &PathError{"chmod", name, Errno(e)}
-	}
-	return nil
-}
-
-// Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) Error {
-	if e := syscall.Fchmod(f.fd, mode); e != 0 {
-		return &PathError{"chmod", f.name, Errno(e)}
-	}
-	return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link's target.
-func Chown(name string, uid, gid int) Error {
-	if e := syscall.Chown(name, uid, gid); e != 0 {
-		return &PathError{"chown", name, Errno(e)}
-	}
-	return nil
-}
-
-// Lchown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link itself.
-func Lchown(name string, uid, gid int) Error {
-	if e := syscall.Lchown(name, uid, gid); e != 0 {
-		return &PathError{"lchown", name, Errno(e)}
-	}
-	return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-func (f *File) Chown(uid, gid int) Error {
-	if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
-		return &PathError{"chown", f.name, Errno(e)}
-	}
-	return nil
-}
-
-// Truncate changes the size of the file.
-// It does not change the I/O offset.
-func (f *File) Truncate(size int64) Error {
-	if e := syscall.Ftruncate(f.fd, size); e != 0 {
-		return &PathError{"truncate", f.name, Errno(e)}
-	}
-	return nil
-}
-
-// Sync commits the current contents of the file to stable storage.
-// Typically, this means flushing the file system's in-memory copy
-// of recently written data to disk.
-func (file *File) Sync() (err Error) {
-	if file == nil {
-		return EINVAL
-	}
-	if e := syscall.Fsync(file.fd); e != 0 {
-		return NewSyscallError("fsync", e)
-	}
-	return nil
-}
-
-// Chtimes changes the access and modification times of the named
-// file, similar to the Unix utime() or utimes() functions.
-//
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
-	var utimes [2]syscall.Timeval
-	utimes[0] = syscall.NsecToTimeval(atime_ns)
-	utimes[1] = syscall.NsecToTimeval(mtime_ns)
-	if e := syscall.Utimes(name, utimes[0:]); e != 0 {
-		return &PathError{"chtimes", name, Errno(e)}
-	}
-	return nil
-}
diff -r 09ab865d875c src/pkg/os/file_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/file_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,204 @@
+// Copyright 20010 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.
+
+package os
+
+import (
+	"runtime"
+	"syscall"
+)
+
+func epipecheck(file *File, e syscall.Error) {
+}
+
+
+// DevNull is the name of the operating system's ``null device.''
+// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
+const DevNull = "#c/null"
+
+// Open opens the named file with specified flag (O_RDONLY etc.) and perm.
+// If successful, methods on the returned File can be used for I/O.
+// It returns the File and an Error, if any.
+func Open(name string, flag int, perm uint32) (file *File, err Error) {
+	var fd int
+	var e syscall.Error
+
+	if flag&O_CREAT == O_CREAT {
+		fd, e = syscall.Create(name, flag & ^O_CREAT, perm)
+	} else {
+		fd, e = syscall.Open(name, flag)
+	}
+
+	if e != nil {
+		return nil, &PathError{"open", name, e}
+	}
+
+	return NewFile(fd, name), nil
+}
+
+// Close closes the File, rendering it unusable for I/O.
+// It returns an Error, if any.
+func (file *File) Close() Error {
+	if file == nil || file.fd < 0 {
+		return syscall.Ebadfd
+	}
+	var err Error
+	if e := syscall.Close(file.fd); e != nil {
+		err = &PathError{"close", file.name, e}
+	}
+	file.fd = -1 // so it can't be closed again
+
+	// no need for a finalizer anymore
+	runtime.SetFinalizer(file, nil)
+	return err
+}
+
+// Stat returns the FileInfo structure describing file.
+// It returns the FileInfo and an error, if any.
+func (file *File) Stat() (fi *FileInfo, err Error) {
+	return dirstat(file)
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+	d := nullDir
+
+	d.Length = uint64(size)
+
+	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+		return &PathError{"truncate", f.name, e}
+	}
+	return nil
+}
+
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (f *File) Sync() (err Error) {
+	if f == nil {
+		return EINVAL
+	}
+
+	d := nullDir
+
+	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+		return NewSyscallError("fsync", e)
+	}
+
+	return nil
+}
+
+// Truncate changes the size of the named file.
+// If the file is a symbolic link, it changes the size of the link's target.
+func Truncate(name string, size int64) Error {
+	d := nullDir
+
+	d.Length = uint64(size)
+
+	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+		return &PathError{"truncate", name, e}
+	}
+	return nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+	if e := syscall.Remove(name); iserror(e) {
+		return &PathError{"remove", name, e}
+	}
+	return nil
+}
+
+func Rename(oldname, newname string) Error {
+	d := nullDir
+
+	d.Name = newname
+
+	if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) {
+		return &PathError{"rename", oldname, e}
+	}
+	return nil
+}
+
+func Chmod(name string, mode uint32) Error {
+	d := nullDir
+
+	d.Mode = mode & 0777
+
+	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+		return &PathError{"chmod", name, e}
+	}
+	return nil
+}
+
+func ChownPlan9(name, uid, gid string) Error {
+	d := nullDir
+
+	d.Uid = uid
+	d.Gid = gid
+
+	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+		return &PathError{"chown_plan9", name, e}
+	}
+	return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+	d := nullDir
+
+	d.Atime = uint32(atime_ns / 1e9)
+	d.Mtime = uint32(mtime_ns / 1e9)
+
+	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+		return &PathError{"chtimes", name, e}
+	}
+	return nil
+}
+
+func Pipe() (r *File, w *File, err Error) {
+	var p [2]int
+
+	if e := syscall.Pipe(p[0:]); iserror(e) {
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+
+	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+
+// not supported on Plan 9
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+	return EPLAN9
+}
+
+func Symlink(oldname, newname string) Error {
+	return EPLAN9
+}
+
+func Readlink(name string) (string, Error) {
+	return "", EPLAN9
+}
+
+func Chown(name string, uid, gid int) Error {
+	return EPLAN9
+}
+
+func Lchown(name string, uid, gid int) Error {
+	return EPLAN9
+}
+
+// Chown changes the numeric uid and gid of the named file.
+func (f *File) Chown(uid, gid int) Error {
+	return EPLAN9
+}
diff -r 09ab865d875c src/pkg/os/file_posix.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/file_posix.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,246 @@
+// Copyright 2009 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.
+
+// The os package provides a platform-independent interface to operating
+// system functionality.  The design is Unix-like.
+package os
+
+import (
+	"syscall"
+)
+
+func epipecheck(file *File, e int) {
+	if e == syscall.EPIPE {
+		file.nepipe++
+		if file.nepipe >= 10 {
+			Exit(syscall.EPIPE)
+		}
+	} else {
+		file.nepipe = 0
+	}
+}
+
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err Error) {
+	var p [2]int
+
+	// See ../syscall/exec.go for description of lock.
+	syscall.ForkLock.RLock()
+	e := syscall.Pipe(p[0:])
+	if iserror(e) {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+	syscall.CloseOnExec(p[0])
+	syscall.CloseOnExec(p[1])
+	syscall.ForkLock.RUnlock()
+
+	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+// If name names a valid symbolic link, the returned FileInfo describes
+// the file pointed at by the link and has fi.FollowedSymlink set to true.
+// If name names an invalid symbolic link, the returned FileInfo describes
+// the link itself and has fi.FollowedSymlink set to false.
+func Stat(name string) (fi *FileInfo, err Error) {
+	var lstat, stat syscall.Stat_t
+	e := syscall.Lstat(name, &lstat)
+	if iserror(e) {
+		return nil, &PathError{"stat", name, Errno(e)}
+	}
+	statp := &lstat
+	if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
+		e := syscall.Stat(name, &stat)
+		if !iserror(e) {
+			statp = &stat
+		}
+	}
+	return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any.  If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link.  Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+	var stat syscall.Stat_t
+	e := syscall.Lstat(name, &stat)
+	if iserror(e) {
+		return nil, &PathError{"lstat", name, Errno(e)}
+	}
+	return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+	// System call interface forces us to know
+	// whether name is a file or directory.
+	// Try both: it is cheaper on average than
+	// doing a Stat plus the right one.
+	e := syscall.Unlink(name)
+	if !iserror(e) {
+		return nil
+	}
+	e1 := syscall.Rmdir(name)
+	if !iserror(e1) {
+		return nil
+	}
+
+	// Both failed: figure out which error to return.
+	// OS X and Linux differ on whether unlink(dir)
+	// returns EISDIR, so can't use that.  However,
+	// both agree that rmdir(file) returns ENOTDIR,
+	// so we can use that to decide which error is real.
+	// Rmdir might also return ENOTDIR if given a bad
+	// file path, like /etc/passwd/foo, but in that case,
+	// both errors will be ENOTDIR, so it's okay to
+	// use the error from unlink.
+	// For windows syscall.ENOTDIR is set
+	// to syscall.ERROR_DIRECTORY, hopefully it should
+	// do the trick.
+	if e1 != syscall.ENOTDIR {
+		e = e1
+	}
+	return &PathError{"remove", name, Errno(e)}
+}
+
+// LinkError records an error during a link or symlink or rename
+// system call and the paths that caused it.
+type LinkError struct {
+	Op    string
+	Old   string
+	New   string
+	Error Error
+}
+
+func (e *LinkError) String() string {
+	return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+}
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+	e := syscall.Link(oldname, newname)
+	if iserror(e) {
+		return &LinkError{"link", oldname, newname, Errno(e)}
+	}
+	return nil
+}
+
+// Symlink creates a symbolic link.
+func Symlink(oldname, newname string) Error {
+	e := syscall.Symlink(oldname, newname)
+	if iserror(e) {
+		return &LinkError{"symlink", oldname, newname, Errno(e)}
+	}
+	return nil
+}
+
+// Readlink reads the contents of a symbolic link: the destination of
+// the link.  It returns the contents and an Error, if any.
+func Readlink(name string) (string, Error) {
+	for len := 128; ; len *= 2 {
+		b := make([]byte, len)
+		n, e := syscall.Readlink(name, b)
+		if iserror(e) {
+			return "", &PathError{"readlink", name, Errno(e)}
+		}
+		if n < len {
+			return string(b[0:n]), nil
+		}
+	}
+	// Silence 6g.
+	return "", nil
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+	e := syscall.Rename(oldname, newname)
+	if iserror(e) {
+		return &LinkError{"rename", oldname, newname, Errno(e)}
+	}
+	return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
+func Chmod(name string, mode uint32) Error {
+	if e := syscall.Chmod(name, mode); iserror(e) {
+		return &PathError{"chmod", name, Errno(e)}
+	}
+	return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+	if e := syscall.Fchmod(f.fd, mode); iserror(e) {
+		return &PathError{"chmod", f.name, Errno(e)}
+	}
+	return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+func Chown(name string, uid, gid int) Error {
+	if e := syscall.Chown(name, uid, gid); iserror(e) {
+		return &PathError{"chown", name, Errno(e)}
+	}
+	return nil
+}
+
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+func Lchown(name string, uid, gid int) Error {
+	if e := syscall.Lchown(name, uid, gid); iserror(e) {
+		return &PathError{"lchown", name, Errno(e)}
+	}
+	return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+func (f *File) Chown(uid, gid int) Error {
+	if e := syscall.Fchown(f.fd, uid, gid); iserror(e) {
+		return &PathError{"chown", f.name, Errno(e)}
+	}
+	return nil
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+	if e := syscall.Ftruncate(f.fd, size); iserror(e) {
+		return &PathError{"truncate", f.name, Errno(e)}
+	}
+	return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (file *File) Sync() (err Error) {
+	if file == nil {
+		return EINVAL
+	}
+	if e := syscall.Fsync(file.fd); iserror(e) {
+		return NewSyscallError("fsync", e)
+	}
+	return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+	var utimes [2]syscall.Timeval
+	utimes[0] = syscall.NsecToTimeval(atime_ns)
+	utimes[1] = syscall.NsecToTimeval(mtime_ns)
+	if e := syscall.Utimes(name, utimes[0:]); iserror(e) {
+		return &PathError{"chtimes", name, Errno(e)}
+	}
+	return nil
+}
diff -r 09ab865d875c src/pkg/os/proc.go
--- a/src/pkg/os/proc.go	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/proc.go	Sat Jan 15 13:00:13 2011 +0200
@@ -26,8 +26,8 @@
 
 // Getgroups returns a list of the numeric ids of groups that the caller belongs to.
 func Getgroups() ([]int, Error) {
-	gids, errno := syscall.Getgroups()
-	return gids, NewSyscallError("getgroups", errno)
+	gids, e := syscall.Getgroups()
+	return gids, NewSyscallError("getgroups", e)
 }
 
 // Exit causes the current program to exit with the given status code.
diff -r 09ab865d875c src/pkg/os/stat_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/stat_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,81 @@
+// 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.
+
+package os
+
+import "syscall"
+
+func fileInfoFromStat(fi *FileInfo, d *Dir) *FileInfo {
+	fi.Dev = uint64(d.Qid.Vers) | uint64(d.Qid.Type<<32)
+	fi.Ino = d.Qid.Path
+
+	fi.Mode = uint32(d.Mode) & 0777
+	if (d.Mode & syscall.DMDIR) == syscall.DMDIR {
+		fi.Mode |= syscall.S_IFDIR
+	} else {
+		fi.Mode |= syscall.S_IFREG
+	}
+
+	fi.Size = int64(d.Length)
+	fi.Atime_ns = 1e9 * int64(d.Atime)
+	fi.Mtime_ns = 1e9 * int64(d.Mtime)
+	fi.Name = d.Name
+	fi.FollowedSymlink = false
+	return fi
+}
+
+// arg is an open *File or a path string. 
+func dirstat(arg interface{}) (fi *FileInfo, err Error) {
+	var name string
+	nd := syscall.STATFIXLEN + 16*4
+
+	for i := 0; i < 2; i++ { /* should work by the second try */
+		buf := make([]byte, nd)
+
+		var n int
+		var e syscall.Error
+
+		switch syscall_arg := arg.(type) {
+		case *File:
+			name = syscall_arg.name
+			n, e = syscall.Fstat(syscall_arg.fd, buf)
+		case string:
+			name = syscall_arg
+			n, e = syscall.Stat(name, buf)
+		}
+
+		if e != nil {
+			return nil, &PathError{"stat", name, e}
+		}
+
+		if n < syscall.STATFIXLEN {
+			return nil, &PathError{"stat", name, syscall.Etoosmall}
+		}
+
+		ntmp, _ := gbit16(buf)
+		nd = int(ntmp)
+
+		if nd <= n {
+			d, e := UnmarshalDir(buf[:n])
+
+			if e != nil {
+				return nil, &PathError{"stat", name, e}
+			}
+
+			return fileInfoFromStat(new(FileInfo), d), nil
+		}
+	}
+
+	return nil, &PathError{"stat", name, syscall.Ebadstat}
+}
+
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+func Stat(name string) (fi *FileInfo, err Error) {
+	return dirstat(name)
+}
+
+func Lstat(name string) (fi *FileInfo, err Error) {
+	return dirstat(name)
+}
diff -r 09ab865d875c src/pkg/os/sys_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/sys_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,27 @@
+// Copyright 2009 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.
+
+// Plan 9-specific
+
+package os
+
+
+func Hostname() (name string, err Error) {
+	f, err := Open("#e/sysname", O_RDONLY, 0)
+	if err != nil {
+		return "", err
+	}
+	defer f.Close()
+
+	var buf [512]byte // Enough for a DNS name.
+	n, err := f.Read(buf[0:])
+	if err != nil {
+		return "", err
+	}
+
+	if n > 0 && buf[n-1] == '\n' {
+		n--
+	}
+	return string(buf[0:n]), nil
+}
diff -r 09ab865d875c src/pkg/os/time.go
--- a/src/pkg/os/time.go	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/time.go	Sat Jan 15 13:00:13 2011 +0200
@@ -13,8 +13,8 @@
 // time is the Unix epoch.
 func Time() (sec int64, nsec int64, err Error) {
 	var tv syscall.Timeval
-	if errno := syscall.Gettimeofday(&tv); errno != 0 {
-		return 0, 0, NewSyscallError("gettimeofday", errno)
+	if e := syscall.Gettimeofday(&tv); iserror(e) {
+		return 0, 0, NewSyscallError("gettimeofday", e)
 	}
 	return int64(tv.Sec), int64(tv.Usec) * 1000, err
 }
diff -r 09ab865d875c src/pkg/runtime/plan9/386/rt0.s
--- a/src/pkg/runtime/plan9/386/rt0.s	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/runtime/plan9/386/rt0.s	Sat Jan 15 13:00:13 2011 +0200
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 TEXT _rt0_386_plan9(SB),7, $0
-	MOVL	AX, _tos(SB)
+	MOVL	AX, syscall路_tos(SB)
 	
 	// move arguments down to make room for
 	// m and g at top of stack, right before Tos.
@@ -29,4 +29,4 @@
 
 DATA  runtime路isplan9(SB)/4, $1
 GLOBL runtime路isplan9(SB), $4
-GLOBL _tos(SB), $4
+GLOBL syscall路_tos(SB), $4
diff -r 09ab865d875c src/pkg/syscall/Makefile
--- a/src/pkg/syscall/Makefile	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/syscall/Makefile	Sat Jan 15 13:00:13 2011 +0200
@@ -32,6 +32,8 @@
 
 GOFILES_windows=\
 	exec_windows.go
+	
+GOFILES_plan9=
 
 OFILES=\
 	asm_$(GOOS)_$(GOARCH).$O\
diff -r 09ab865d875c src/pkg/syscall/asm_plan9_386.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/asm_plan9_386.s	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,176 @@
+// Copyright 2009 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.
+
+//
+// System call support for 386, Plan 9
+//
+
+// func Syscall(trap int32, a1, a2, a3 int32) (r1, r2, err uintptr);
+// func SyscallErrstr(trap uintptr, a1, a2, a3 uintptr) (r uintptr, err string);
+// func Syscall6(trap int32, a1, a2, a3, a4, a5, a6 int32) (r1, r2, err uintptr);
+// func SyscallErrstr6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r uintptr, err string);
+// Trap # in AX, args on stack above caller pc.
+
+TEXT	路Syscall(SB),7,$0
+	CALL	runtime路entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$64
+	MOVL	AX, r1+20(SP)
+	MOVL	$0, r2+24(SP)
+	MOVL	$0, err+28(SP)		
+	CALL	runtime路exitsyscall(SB)
+	RET
+
+
+TEXT	路Syscall6(SB),7,$0
+	CALL	runtime路entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$64
+	MOVL	AX, r1+32(SP)
+	MOVL	$0, r2+36(SP)
+	MOVL	$0, err+40(SP)		
+	CALL	runtime路exitsyscall(SB)
+	RET
+
+TEXT	路SyscallErrstr(SB),7,$0
+	CALL	runtime路entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$64
+	MOVL	AX, r+20(SP)
+	CMPL	AX, $-1
+	JNE	ok3
+
+	SUBL	$8, SP
+	CALL	syscall路errstr(SB)
+	MOVL	SP, SI
+	ADDL	$8, SP
+	JMP	copyresult3
+	
+ok3:
+	LEAL	runtime路emptystring(SB), SI	
+	
+copyresult3:
+	LEAL	err+24(SP), DI
+
+	CLD
+	MOVSL
+	MOVSL
+
+	CALL	runtime路exitsyscall(SB)
+	RET
+
+
+TEXT	路SyscallErrstr6(SB),7,$0
+	CALL	runtime路entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$64
+	MOVL	AX, r+32(SP)
+	CMPL	AX, $-1
+	JNE	ok4
+	
+	SUBL	$8, SP
+	CALL	syscall路errstr(SB)
+	MOVL	SP, SI
+	ADDL	$8, SP
+	JMP	copyresult4
+	
+ok4:
+	LEAL	runtime路emptystring(SB), SI
+	
+copyresult4:
+	LEAL	err+36(SP), DI
+
+	CLD
+	MOVSL
+	MOVSL
+
+	CALL	runtime路exitsyscall(SB)
+	RET
+
+
+TEXT 路RawSyscall(SB),7,$0
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$64
+	MOVL	AX, r1+20(SP)
+	MOVL	$0, r2+24(SP)
+	MOVL	$0, err+28(SP)
+	RET
+
+
+#define SYS_SEEK 39	/* from zsysnum_plan9_386.go */
+
+//func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+TEXT 路seek(SB),7,$0
+	CALL	runtime路entersyscall(SB)
+	
+	LEAL	newoffset+24(SP), AX
+	MOVL	AX, placeholder+4(SP)
+	
+	MOVL	$SYS_SEEK, AX	// syscall entry
+	INT	$64
+	
+	CMPL	AX, $-1
+	JNE	ok6
+	MOVL	AX, 24(SP)	// newoffset low
+	MOVL	AX, 28(SP)	// newoffset high
+	
+	SUBL	$8, SP
+	CALL	syscall路errstr(SB)
+	MOVL	SP, SI
+	ADDL	$8, SP	
+	JMP	copyresult6
+	
+ok6:
+	LEAL	runtime路emptystring(SB), SI
+	
+copyresult6:
+	LEAL	err+32(SP), DI
+
+	CLD
+	MOVSL
+	MOVSL
+
+	CALL	runtime路exitsyscall(SB)
+	RET
diff -r 09ab865d875c src/pkg/syscall/mkall.sh
--- a/src/pkg/syscall/mkall.sh	Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/syscall/mkall.sh	Sat Jan 15 13:00:13 2011 +0200
@@ -154,6 +154,12 @@
 	mktypes=
 	mkerrors="./mkerrors_windows.sh -f -m32"
 	;;
+plan9_386)
+	mkerrors=
+	mksyscall="./mksyscall_plan9.sh -l32"
+	mksysnum="./mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h"
+	mktypes="godefs -gsyscall -f -m32"
+	;;
 *)
 	echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
 	exit 1
diff -r 09ab865d875c src/pkg/syscall/mksyscall_plan9.awk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/mksyscall_plan9.awk	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,205 @@
+function parse_line(line) {
+
+	inargs_begin = match(line, /\(([^()]*)\)/)
+	
+	if(inargs_begin == 0)
+		return 0
+
+	fname = substr(line, 1, inargs_begin-1)
+	sub(/func[ \t]+/, "", fname)
+
+	inargs_tmp = substr(line, inargs_begin+1, RLENGTH-2)
+	outargs_tmp = substr(line, inargs_begin+RLENGTH, length(line))
+	
+	outargs_begin = match(outargs_tmp, /\(([^()]*)\)/)
+	if(outargs_begin == 0)
+		outargs_tmp = ""
+	else
+		outargs_tmp = substr(outargs_tmp, outargs_begin+1, RLENGTH-2)
+	
+	parse_arg_types(inargs_tmp, inargs, inarg_types)
+	parse_arg_types(outargs_tmp, outargs, outarg_types)
+	
+	return 1
+}
+
+function parse_arg_types(args_str, args, arg_types) {
+	arg_index = 1
+
+	delete args_tmp
+	delete args
+	delete arg_types
+	
+	split(args_str, args_tmp, /[ \t]*,[ \t]*/)
+	for(i=1; i <= length(args_tmp); i++) {
+		argname = args_tmp[i]	
+
+		type_begin = match(args_tmp[i], /[ \t]+/)
+		if (type_begin == 0) {
+			arg_types[argname] = ""
+		} else {
+			argname = substr(args_tmp[i], 1, type_begin-1)
+			type =  substr(args_tmp[i], type_begin+RLENGTH, length(args_tmp[i]))
+			sub(/^[ \t]+/, "", type)
+			sub(/[ \t]+$/, "", type)			
+			arg_types[argname] = type
+			
+			for (j = arg_index; j > 0; j--) {
+				if (arg_types[args[j]] != "")
+					break
+					
+				arg_types[args[j]] = arg_types[argname]
+			}		
+		}
+		
+		sub(/^[ \t]+/, "", argname)
+		sub(/[ \t]+$/, "", argname)
+		
+		if (argname == "")
+			continue
+		
+		args[arg_index++] = argname
+	}
+} 
+
+BEGIN {
+	printf("// %s\n", cmdline)
+	print "// MACHINE GENERATED BY THE COMMAND ABOVE DO NOT EDIT\n"
+	print "package syscall\n"
+	print "import \"unsafe\"\n"
+}
+
+
+/^\/\/sys[ \t]+/ {
+
+	print "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT\n\n"
+
+	sub(/^\/\/sys[ \t]+/, "func ", $0)
+	printf("%s {\n", $0)
+
+	if (!parse_line($0))
+		next
+
+	# Prepare arguments to Syscall.
+	delete syscall_args
+	syscall_arg_index = 1
+	ptrindex = 0
+
+	for (i=1; i <= length(inargs); i++) {
+		name = inargs[i]
+		type = inarg_types[name]
+		
+		if (type ~ /^\*/) {
+			syscall_args[syscall_arg_index++] = sprintf("uintptr(unsafe.Pointer(%s))", name)
+		} else if (type == "string") {
+			syscall_args[syscall_arg_index++] = sprintf("uintptr(unsafe.Pointer(StringBytePtr(%s)))", name)
+		} else if (type ~ /\[\](.*)/) {
+			# Convert slice into pointer, length.
+			# Have to be careful not to take address of &a[0] if len == 0:
+			# pass nil in that case.
+			
+			printf("\tvar _p%d unsafe.Pointer\n", ptrindex)
+			printf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}\n", name, ptrindex, name)
+			
+			syscall_args[syscall_arg_index++] = sprintf("uintptr(_p%d)", ptrindex)
+			syscall_args[syscall_arg_index++] = sprintf("uintptr(len(%s))", name)
+			ptrindex++
+		} else if (type == "int64" && _32bit != "") {
+			if (_32bit == "big-endian") {
+				syscall_args[syscall_arg_index++] = sprintf("uintptr(%s>>32)", name)
+				syscall_args[syscall_arg_index++] = sprintf("uintptr(%s)", name)
+			} else {
+				syscall_args[syscall_arg_index++] = sprintf("uintptr(%s)", name)
+				syscall_args[syscall_arg_index++] = sprintf("uintptr(%s>>32)", name)
+			}
+		} else {
+			syscall_args[syscall_arg_index++] = sprintf("uintptr(%s)", name)
+		}		
+	}
+	
+	# Determine which form to use; pad args with zeros.
+	asm = "Syscall"
+	
+	errstr = 0
+	if ("err" in outarg_types && outarg_types["err"] == "Error") {
+		asm = asm "Errstr"
+		errstr = 1
+	}
+
+	if (syscall_arg_index <= 4) {
+		for (; syscall_arg_index <= 3; syscall_arg_index++)
+			syscall_args[syscall_arg_index] = "0"
+	} else if (syscall_arg_index <= 7) {
+		asm = asm "6"
+		for (; syscall_arg_index <= 6; syscall_arg_index++)
+			syscall_args[syscall_arg_index] = "0"
+	} else {
+		print "too many arguments to system call\n"
+		exit 1
+	}
+
+	syscall_ret = ""
+	
+	if (length(outargs) > 0) {		
+		if (errstr) {
+			syscall_ret = syscall_ret "r0,e"
+		} else {
+#			if(outarg_types[outargs[1]] == "int64" && _32bit != "") {
+#			# 64-bit number in r1:r0 or r0:r1.
+#				syscall_ret = "r0,r1,_"
+#			} else {
+				syscall_ret = "r0,_,_"
+#			}
+		}
+	}
+	
+	sysname = "SYS_" toupper(fname)
+
+	# Actuall call.
+	if (syscall_ret == "")
+		printf("\t%s(%s", asm, sysname)
+	else
+		printf("\t%s := %s(%s", syscall_ret, asm, sysname)
+	
+	for (i=1; i <= length(syscall_args); i++) {
+		printf(", %s", syscall_args[i])
+	}
+
+	print ")\n"
+	
+	# set Return values.
+	for (i=1; i <= length(outargs); i++) {
+		name = outargs[i]
+		type = outarg_types[name]
+		
+		# Should be the last output variable.
+		if (name == "err" && type == "Error")
+			break
+	
+		if(type == "int64" && _32bit != "") {
+			print "system call returning 64 bit value\n"
+			exit 1			
+#			# 64-bit number in r1:r0 or r0:r1.
+#			if(_32bit == "big-endian") {
+#				printf("\t%s = int64(r0)<<32 | int64(r1)", name);
+#			} else {
+#				printf("\t%s = int64(r1)<<32 | int64(r0)", name);
+#			}
+#			break
+		} else if (type == "bool") {
+			printf("\t%s = r%d != 0\n", name, i-1)
+		} else {
+			printf("\t%s = %s(r%d)\n", name, type, i-1)
+		}
+	}	
+
+	if (errstr) {
+		print "\terr = nil"
+		print "\tif int(r0) == -1 {"
+		print "\t\terr = NewError(e)"
+		print "\t}"
+	}
+
+	print "\treturn\n}"
+	
+}
diff -r 09ab865d875c src/pkg/syscall/mksyscall_plan9.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/mksyscall_plan9.sh	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,32 @@
+#!/bin/sh
+# 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.
+
+# This program reads a file containing function prototypes
+# (like syscall_plan9.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+#	* The parameter lists must give a name for each argument.
+#	  This includes return parameters.
+#	* If the return parameter is an error string,
+#	  as returned by errstr. It must be named err, of type Error
+#	  and be the last return parameter.
+
+cmdline="mksyscall_plan9.sh $@" 
+_32bit=""
+
+if [ "$1" == '-b32' ]; then
+	_32bit="big-endian"
+elif [ "$1" == '-l32' ]; then
+	_32bit="little-endian"
+fi
+
+awk -v _32bit="${_32bit}" -v cmdline="${cmdline}" -f mksyscall_plan9.awk "$2"
+
+#if($ARGV[0] =~ /^-/) {
+#	print STDERR "usage: mksyscall.sh [-b32 | -l32] [file ...]\n";
+#	exit 1;
+#}
+
+
diff -r 09ab865d875c src/pkg/syscall/mksysnum_plan9.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/mksysnum_plan9.sh	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Copyright 2009 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.# Copyright 2009 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.
+
+COMMAND="mksysnum_plan9.sh $@"
+
+cat <<EOF
+// $COMMAND
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const(
+EOF
+
+cat $1 | sed -r 's/^#define[ \t]([A-Z0-9_]+)[ \t]+([0-9]+)/\tSYS_\1=\2/g' | grep -v SYS__
+
+cat <<EOF
+)
+EOF
diff -r 09ab865d875c src/pkg/syscall/syscall_plan9.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/syscall_plan9.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,368 @@
+// 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.
+
+// Plan 9 system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import "unsafe"
+
+const OS = "plan9"
+
+const ImplementsGetwd = true
+
+// shamelessly copied from os.error.
+// An Error can represent any printable error condition.
+type Error interface {
+	String() string
+}
+
+// A helper type that can be embedded or wrapped to simplify satisfying
+// Error.
+type ErrorString string
+
+func (e ErrorString) String() string { return string(e) }
+
+// NewError converts s to an ErrorString, which satisfies the Error interface.
+func NewError(s string) Error { return ErrorString(s) }
+
+var (
+	Stdin  = 0
+	Stdout = 1
+	Stderr = 2
+)
+
+func SyscallErrstr(trap, a1, a2, a3 uintptr) (r uintptr, err string)
+func SyscallErrstr6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r uintptr, err string)
+
+// Plan 9 errors
+var (
+	Enoerror    Error = NewError("no error")
+	Emount      Error = NewError("inconsistent mount")
+	Eunmount    Error = NewError("not mounted")
+	Eismtpt     Error = NewError("is a mount point")
+	Eunion      Error = NewError("not in union")
+	Emountrpc   Error = NewError("mount rpc error")
+	Eshutdown   Error = NewError("device shut down")
+	Enocreate   Error = NewError("mounted directory forbids creation")
+	Enonexist   Error = NewError("file does not exist")
+	Eexist      Error = NewError("file already exists")
+	Ebadsharp   Error = NewError("unknown device in # filename")
+	Enotdir     Error = NewError("not a directory")
+	Eisdir      Error = NewError("file is a directory")
+	Ebadchar    Error = NewError("bad character in file name")
+	Efilename   Error = NewError("file name syntax")
+	Eperm       Error = NewError("permission denied")
+	Ebadusefd   Error = NewError("inappropriate use of fd")
+	Ebadarg     Error = NewError("bad arg in system call")
+	Einuse      Error = NewError("device or object already in use")
+	Eio         Error = NewError("i/o error")
+	Etoobig     Error = NewError("read or write too large")
+	Etoosmall   Error = NewError("read or write too small")
+	Enoport     Error = NewError("network port not available")
+	Ehungup     Error = NewError("i/o on hungup channel")
+	Ebadctl     Error = NewError("bad process or channel control request")
+	Enodev      Error = NewError("no free devices")
+	Eprocdied   Error = NewError("process exited")
+	Enochild    Error = NewError("no living children")
+	Eioload     Error = NewError("i/o error in demand load")
+	Enovmem     Error = NewError("virtual memory allocation failed")
+	Ebadfd      Error = NewError("fd out of range or not open")
+	Enofd       Error = NewError("no free file descriptors")
+	Eisstream   Error = NewError("seek on a stream")
+	Ebadexec    Error = NewError("exec header invalid")
+	Etimedout   Error = NewError("connection timed out")
+	Econrefused Error = NewError("connection refused")
+	Econinuse   Error = NewError("connection in use")
+	Eintr       Error = NewError("interrupted")
+	Enomem      Error = NewError("kernel allocate failed")
+	Enoswap     Error = NewError("swap space full")
+	Esoverlap   Error = NewError("segments overlap")
+	Emouseset   Error = NewError("mouse type already set")
+	Eshort      Error = NewError("i/o count too small")
+	Egreg       Error = NewError("jmk added reentrancy for threads")
+	Ebadspec    Error = NewError("bad attach specifier")
+	Enoreg      Error = NewError("process has no saved registers")
+	Enoattach   Error = NewError("mount/attach disallowed")
+	Eshortstat  Error = NewError("stat buffer too small")
+	Ebadstat    Error = NewError("malformed stat buffer")
+	Enegoff     Error = NewError("negative i/o offset")
+	Ecmdargs    Error = NewError("wrong #args in control message")
+	Ebadip      Error = NewError("bad ip address syntax")
+	Edirseek    Error = NewError("seek in directory")
+)
+
+var (
+	EISDIR Error = Eisdir
+	EPIPE  Error = Eio
+)
+
+func atoi(buf []byte) int {
+	res := 0
+
+	for i := 0; i < len(buf); i++ {
+		res *= 10
+		res += int(buf[i] - '0')
+	}
+
+	return res
+}
+
+func findnull(s []byte) int {
+	l := 0
+	for ; (l < len(s)) && (s[l] != 0); l++ {
+	}
+
+	return l
+}
+
+
+/*
+ * Wrapped
+ */
+
+func Getpagesize() int { return 4096 }
+
+//sys	exits(msg *byte)
+func Exits(msg *string) {
+	if msg == nil {
+		exits(nil)
+	}
+
+	exits(StringBytePtr(*msg))
+}
+
+func Exit(code int) {
+	if code == 0 {
+		Exits(nil)
+	}
+
+	msg := str(code)
+	Exits(&msg)
+}
+
+var _tos *Tos // provided by runtime rt0.s
+func Getpid() (pid int) {
+	return int(_tos.Pid)
+}
+
+func Getppid() (ppid int) {
+	var b [12]byte
+
+	fd, e := Open("#c/ppid", O_RDONLY)
+	if e != nil {
+		return -1
+	}
+	defer Close(fd)
+
+	n, e := Pread(fd, b[:], 0)
+
+	m := 0
+	for ; m < n && b[m] == ' '; m++ {
+	}
+
+	return atoi(b[m : n-1])
+}
+
+
+func Read(fd int, p []byte) (n int, err Error) {
+	return Pread(fd, p, -1)
+}
+
+func Write(fd int, p []byte) (n int, err Error) {
+	return Pwrite(fd, p, -1)
+}
+
+func Getwd() (wd string, err Error) {
+	fd, e := Open(".", O_RDONLY)
+
+	if e != nil {
+		return "", e
+	}
+	defer Close(fd)
+
+	return Fd2path(fd)
+}
+
+//sys	fd2path(fd int, buf []byte) (err Error)
+func Fd2path(fd int) (path string, err Error) {
+	var buf [512]byte
+
+	e := fd2path(fd, buf[:])
+	if e != nil {
+		return "", e
+	}
+
+	buf[len(buf)-1] = 0
+	return string(buf[:findnull(buf[:])]), nil
+}
+
+//sys	pipe(p *[2]_C_int) (err Error)
+func Pipe(p []int) (err Error) {
+	if len(p) != 2 {
+		return NewError("bad arg in system call")
+	}
+	var pp [2]_C_int
+	err = pipe(&pp)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+
+//sys	sleep(millisecs int32) (err Error)
+func Sleep(nsec int64) (err Error) {
+	return sleep(int32((nsec + 999) / 1e6))
+}
+
+// Underlying system call writes to newoffset via pointer.
+// Implemented in assembly to avoid allocation.
+func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err Error) {
+	newoffset, e := seek(0, fd, offset, whence)
+
+	err = nil
+	if newoffset == -1 {
+		err = NewError(e)
+	}
+	return
+}
+
+func Mkdir(path string, mode uint32) (err Error) {
+	fd, err := Create(path, O_RDONLY, DMDIR|mode)
+
+	if fd != -1 {
+		Close(fd)
+	}
+
+	return
+}
+
+type Waitmsg struct {
+	Pid  int
+	Time [3]uint32
+	Msg  string
+}
+
+//sys	await(s []byte) (n int, err Error)
+func Await(msg *Waitmsg) (err Error) {
+	var s [512]byte
+
+	end, err := await(s[:])
+
+	if err != nil || msg == nil {
+		return
+	}
+
+	sep := make([]int, 0, 7)
+
+	for i := 0; i < end; i++ {
+		if s[i] == ' ' {
+			sep = append(sep, i)
+		}
+	}
+	sep = append(sep, end)
+
+	msg.Pid = atoi(s[0:sep[0]])
+
+	for i := 0; i < 3; i++ {
+		msg.Time[i] = uint32(atoi(s[sep[i]+1 : sep[i+1]]))
+	}
+
+	msg.Msg = string(s[sep[3]+2 : sep[len(sep)-1]-1])
+
+	return
+}
+
+func Fchdir(fd int) (err Error) {
+	path, err := Fd2path(fd)
+
+	if err != nil {
+		return
+	}
+
+	return Chdir(path)
+}
+
+type Timeval struct {
+	Sec  int32
+	Usec int32
+}
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+	nsec += 999 // round up to microsecond
+	tv.Usec = int32(nsec % 1e9 / 1e3)
+	tv.Sec = int32(nsec / 1e9)
+	return
+}
+
+func Gettimeofday(tv *Timeval) (err Error) {
+	var b [8]byte
+	var nsec int64
+
+	fd, e := Open("#c/bintime", O_RDONLY)
+	if e != nil {
+		return e
+	}
+	defer Close(fd)
+
+	_, e = Pread(fd, b[:], 0)
+
+	if e != nil {
+		return e
+	}
+
+	nsec = int64(b[0])<<56 |
+		int64(b[1])<<48 |
+		int64(b[2])<<40 |
+		int64(b[3])<<32 |
+		int64(b[4])<<24 |
+		int64(b[5])<<16 |
+		int64(b[6])<<8 |
+		int64(b[7])
+
+	*tv = NsecToTimeval(nsec)
+
+	return e
+}
+
+func errstr() string {
+	err_buffer := make([]byte, ERRMAX)
+
+	RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&err_buffer[0])), uintptr(len(err_buffer)), 0)
+
+	err_buffer[len(err_buffer)-1] = 0
+	return string(err_buffer[:findnull(err_buffer)])
+}
+
+func Getegid() (egid int) { return -1 }
+func Geteuid() (euid int) { return -1 }
+func Getgid() (gid int)   { return -1 }
+func Getuid() (uid int)   { return -1 }
+
+func Getgroups() (gids []int, err Error) {
+	return make([]int, 0), nil
+}
+
+//sys	Dup(oldfd int, newfd int) (fd int, err Error)
+//sys	Open(path string, mode int) (fd int, err Error)
+//sys	Create(path string, mode int, perm uint32) (fd int, err Error)
+//sys	Remove(path string) (err Error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err Error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err Error)
+//sys	Close(fd int) (err Error)
+//sys	Chdir(path string) (err Error)
+//sys	Bind(name, old string, flag int) (err Error)
+//sys	Mount(fd, afd int, old string, flag int, aname string) (err Error)
+//sys	Unmount(name, old string) (err Error)
+//sys	Stat(path string, edir []byte) (n int, err Error)
+//sys	Fstat(fd int, edir []byte) (n int, err Error)
+//sys	Wstat(path string, edir []byte) (err Error)
+//sys	Fwstat(fd int, edir []byte) (err Error)
diff -r 09ab865d875c src/pkg/syscall/syscall_plan9_386.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/syscall_plan9_386.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,5 @@
+// Copyright 2009 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.
+
+package syscall
diff -r 09ab865d875c src/pkg/syscall/types_plan9.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/types_plan9.c	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,116 @@
+// Copyright 2009 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.
+
+/*
+Input to godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+typedef long long vlong;
+typedef unsigned long long uvlong;
+
+typedef int $_C_int;
+
+enum {
+	OREAD   = 0,       /* open for read */
+	OWRITE  = 1,       /* write */
+	ORDWR   = 2,       /* read and write */
+	
+	$O_RDONLY   = OREAD,
+	$O_WRONLY   = OWRITE,
+	$O_RDWR     = ORDWR,
+	
+	OEXEC   = 3,       /* execute, == read but check execute permission */
+	OTRUNC  = 16,      /* or'ed in (except for exec), truncate file first */
+	OCEXEC  = 32,      /* or'ed in, close on exec */
+	
+	$O_CLOEXEC  = OCEXEC,
+	
+	ORCLOSE = 64,      /* or'ed in, remove on close */
+	OEXCL   = 0x1000,  /* or'ed in, exclusive use (create only) */
+	$O_EXCL = OEXCL,
+	
+	$STATMAX = 65535U,
+	$ERRMAX = 128,
+	
+	$MORDER		= 0x0003,	/* mask for bits defining order of mounting */
+	$MREPL		= 0x0000,	/* mount replaces object */
+	$MBEFORE	= 0x0001,	/* mount goes before others in union directory */
+	$MAFTER		= 0x0002,	/* mount goes after others in union directory */
+	$MCREATE	= 0x0004,	/* permit creation in mounted directory */
+	$MCACHE		= 0x0010,	/* cache some data */
+	$MMASK		= 0x0017,	/* all bits on */
+	
+	$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),
+	
+/* bits in Qid.type */
+	$QTDIR = 0x80,		/* type bit for directories */
+	$QTAPPEND = 0x40,		/* type bit for append only files */
+	$QTEXCL = 0x20,		/* type bit for exclusive use files */
+	$QTMOUNT = 0x10,		/* type bit for mounted channel */
+	$QTAUTH = 0x08,		/* type bit for authentication file */
+	$QTTMP = 0x04,		/* type bit for not-backed-up file */
+	$QTFILE = 0x00,		/* plain file */
+	
+	
+	/* bits in Dir.mode */
+	$DMDIR = 0x80000000,	/* mode bit for directories */
+	$DMAPPEND = 0x40000000,	/* mode bit for append only files */
+	$DMEXCL = 0x20000000,	/* mode bit for exclusive use files */
+	$DMMOUNT = 0x10000000,	/* mode bit for mounted channel */
+	$DMAUTH = 0x08000000,	/* mode bit for authentication file */
+	$DMTMP = 0x04000000,	/* mode bit for non-backed-up files */
+	$DMREAD = 0x4,		/* mode bit for read permission */
+	$DMWRITE = 0x2,		/* mode bit for write permission */
+	$DMEXEC = 0x1,		/* mode bit for execute permission */
+	
+	BIT8SZ = 1,
+	BIT16SZ = 2,
+	BIT32SZ = 4,
+	BIT64SZ = 8,
+	QIDSZ = (BIT8SZ+BIT32SZ+BIT64SZ),
+
+	/* STATFIXLEN includes leading 16-bit count */
+	/* The count, however, excludes itself; total size is BIT16SZ+count */
+	$STATFIXLEN = (BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ),	/* amount of fixed length data in a stat buffer */
+	
+};
+
+
+struct Prof			/* Per process profiling */
+{
+	struct Plink	*pp;	/* known to be 0(ptr) */
+	struct Plink	*next;	/* known to be 4(ptr) */
+	struct Plink	*last;
+	struct Plink	*first;
+	ulong		pid;
+	ulong		what;
+};
+
+struct Tos {
+	struct Prof	prof;
+	uvlong		cyclefreq;	/* cycle clock frequency if there is one, 0 otherwise */
+	vlong		kcycles;	/* cycles spent in kernel */
+	vlong		pcycles;	/* cycles spent in process (kernel + user) */
+	ulong		pid;		/* might as well put the pid here */
+	ulong		clock;
+	/* top of stack is here */
+};
+
+typedef struct Prof $Prof;
+typedef struct Tos $Tos;
diff -r 09ab865d875c src/pkg/syscall/zerrors_plan9_386.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/zerrors_plan9_386.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,25 @@
+package syscall
+
+// Constants
+const (
+	// Invented values to support what package os expects.
+	O_CREAT    = 0x02000
+	O_NOCTTY   = 0x00000
+	O_TRUNC    = 0x00000
+	O_NONBLOCK = 0x00000
+	O_APPEND   = 0x00000
+	O_SYNC     = 0x00000
+	O_ASYNC    = 0x00000
+
+
+	S_IFMT   = 0x1f000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+)
+
+// Error table
diff -r 09ab865d875c src/pkg/syscall/zsyscall_plan9_386.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/zsyscall_plan9_386.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,283 @@
+// mksyscall_plan9.sh -l32 syscall_plan9.go syscall_plan9_386.go
+// MACHINE GENERATED BY THE COMMAND ABOVE DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func exits(msg *byte) {
+	Syscall(SYS_EXITS, uintptr(unsafe.Pointer(msg)), 0, 0)
+
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func fd2path(fd int, buf []byte) (err Error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	}
+	r0, e := SyscallErrstr(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func pipe(p *[2]_C_int) (err Error) {
+	r0, e := SyscallErrstr(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func sleep(millisecs int32) (err Error) {
+	r0, e := SyscallErrstr(SYS_SLEEP, uintptr(millisecs), 0, 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func await(s []byte) (n int, err Error) {
+	var _p0 unsafe.Pointer
+	if len(s) > 0 {
+		_p0 = unsafe.Pointer(&s[0])
+	}
+	r0, e := SyscallErrstr(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+
+	n = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Dup(oldfd int, newfd int) (fd int, err Error) {
+	r0, e := SyscallErrstr(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+
+	fd = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Open(path string, mode int) (fd int, err Error) {
+	r0, e := SyscallErrstr(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+
+	fd = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Create(path string, mode int, perm uint32) (fd int, err Error) {
+	r0, e := SyscallErrstr(SYS_CREATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+
+	fd = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Remove(path string) (err Error) {
+	r0, e := SyscallErrstr(SYS_REMOVE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Pread(fd int, p []byte, offset int64) (n int, err Error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	}
+	r0, e := SyscallErrstr6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+
+	n = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err Error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	}
+	r0, e := SyscallErrstr6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+
+	n = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Close(fd int) (err Error) {
+	r0, e := SyscallErrstr(SYS_CLOSE, uintptr(fd), 0, 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Chdir(path string) (err Error) {
+	r0, e := SyscallErrstr(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Bind(name, old string, flag int) (err Error) {
+	r0, e := SyscallErrstr(SYS_BIND, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag))
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Mount(fd, afd int, old string, flag int, aname string) (err Error) {
+	r0, e := SyscallErrstr6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag), uintptr(unsafe.Pointer(StringBytePtr(aname))), 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Unmount(name, old string) (err Error) {
+	r0, e := SyscallErrstr(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), 0)
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Stat(path string, edir []byte) (n int, err Error) {
+	var _p0 unsafe.Pointer
+	if len(edir) > 0 {
+		_p0 = unsafe.Pointer(&edir[0])
+	}
+	r0, e := SyscallErrstr(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
+
+	n = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Fstat(fd int, edir []byte) (n int, err Error) {
+	var _p0 unsafe.Pointer
+	if len(edir) > 0 {
+		_p0 = unsafe.Pointer(&edir[0])
+	}
+	r0, e := SyscallErrstr(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+
+	n = int(r0)
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Wstat(path string, edir []byte) (err Error) {
+	var _p0 unsafe.Pointer
+	if len(edir) > 0 {
+		_p0 = unsafe.Pointer(&edir[0])
+	}
+	r0, e := SyscallErrstr(SYS_WSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Fwstat(fd int, edir []byte) (err Error) {
+	var _p0 unsafe.Pointer
+	if len(edir) > 0 {
+		_p0 = unsafe.Pointer(&edir[0])
+	}
+	r0, e := SyscallErrstr(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+
+	err = nil
+	if int(r0) == -1 {
+		err = NewError(e)
+	}
+	return
+}
diff -r 09ab865d875c src/pkg/syscall/zsysnum_plan9_386.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/zsysnum_plan9_386.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,47 @@
+// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	SYS_SYSR1      = 0
+	SYS_BIND       = 2
+	SYS_CHDIR      = 3
+	SYS_CLOSE      = 4
+	SYS_DUP        = 5
+	SYS_ALARM      = 6
+	SYS_EXEC       = 7
+	SYS_EXITS      = 8
+	SYS_FAUTH      = 10
+	SYS_SEGBRK     = 12
+	SYS_OPEN       = 14
+	SYS_OSEEK      = 16
+	SYS_SLEEP      = 17
+	SYS_RFORK      = 19
+	SYS_PIPE       = 21
+	SYS_CREATE     = 22
+	SYS_FD2PATH    = 23
+	SYS_BRK_       = 24
+	SYS_REMOVE     = 25
+	SYS_NOTIFY     = 28
+	SYS_NOTED      = 29
+	SYS_SEGATTACH  = 30
+	SYS_SEGDETACH  = 31
+	SYS_SEGFREE    = 32
+	SYS_SEGFLUSH   = 33
+	SYS_RENDEZVOUS = 34
+	SYS_UNMOUNT    = 35
+	SYS_SEMACQUIRE = 37
+	SYS_SEMRELEASE = 38
+	SYS_SEEK       = 39
+	SYS_FVERSION   = 40
+	SYS_ERRSTR     = 41
+	SYS_STAT       = 42
+	SYS_FSTAT      = 43
+	SYS_WSTAT      = 44
+	SYS_FWSTAT     = 45
+	SYS_MOUNT      = 46
+	SYS_AWAIT      = 47
+	SYS_PREAD      = 50
+	SYS_PWRITE     = 51
+)
diff -r 09ab865d875c src/pkg/syscall/ztypes_plan9_386.go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/ztypes_plan9_386.go	Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,74 @@
+// godefs -gsyscall -f -m32 types_plan9.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+package syscall
+
+// Constants
+const (
+	O_RDONLY   = 0
+	O_WRONLY   = 0x1
+	O_RDWR     = 0x2
+	O_CLOEXEC  = 0x20
+	O_EXCL     = 0x1000
+	STATMAX    = 0xffff
+	ERRMAX     = 0x80
+	MORDER     = 0x3
+	MREPL      = 0
+	MBEFORE    = 0x1
+	MAFTER     = 0x2
+	MCREATE    = 0x4
+	MCACHE     = 0x10
+	MMASK      = 0x17
+	RFNAMEG    = 0x1
+	RFENVG     = 0x2
+	RFFDG      = 0x4
+	RFNOTEG    = 0x8
+	RFPROC     = 0x10
+	RFMEM      = 0x20
+	RFNOWAIT   = 0x40
+	RFCNAMEG   = 0x400
+	RFCENVG    = 0x800
+	RFCFDG     = 0x1000
+	RFREND     = 0x2000
+	RFNOMNT    = 0x4000
+	QTDIR      = 0x80
+	QTAPPEND   = 0x40
+	QTEXCL     = 0x20
+	QTMOUNT    = 0x10
+	QTAUTH     = 0x8
+	QTTMP      = 0x4
+	QTFILE     = 0
+	DMDIR      = 0x80000000
+	DMAPPEND   = 0x40000000
+	DMEXCL     = 0x20000000
+	DMMOUNT    = 0x10000000
+	DMAUTH     = 0x8000000
+	DMTMP      = 0x4000000
+	DMREAD     = 0x4
+	DMWRITE    = 0x2
+	DMEXEC     = 0x1
+	STATFIXLEN = 0x31
+)
+
+// Types
+
+type _C_int int32
+
+type Prof struct {
+	Pp    *[0]byte /* sPlink */
+	Next  *[0]byte /* sPlink */
+	Last  *[0]byte /* sPlink */
+	First *[0]byte /* sPlink */
+	Pid   uint32
+	What  uint32
+}
+
+type Tos struct {
+	Prof      Prof
+	Cyclefreq uint64
+	Kcycles   int64
+	Pcycles   int64
+	Pid       uint32
+	Clock     uint32
+}

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-15 11:25                 ` Pavel Zholkover
@ 2011-01-16  1:51                   ` kokamoto
  2011-01-16  2:04                     ` kokamoto
  2011-01-16  2:06                     ` [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
  0 siblings, 2 replies; 36+ messages in thread
From: kokamoto @ 2011-01-16  1:51 UTC (permalink / raw)
  To: 9fans

> On Sat, Jan 15, 2011 at 12:40 PM,  <lucio@proxima.alt.za> wrote:
>>> If you try applying http://codereview.appspot.com/3816043/ you can get
>>> pretty far..

Your new patch here made me success to make patch.
Previous one had problem to patch file_posix.go etc.

By the way, now I got the real procedure to get it work, I think.

First, compile Go tree as GOOS=linux (not plan9).
Second, go to src/pkg/syscall, and
	GOOS=plan9 make -k install.
Third, then go to src/pkg/os, and
	GOOS=plan9 make -k install.

However, even if I could make a binary for Plan 9, I have to compile it
on linux machine, and move the binary to Plan 9.
Am I right?

I tried GOOS=plan9 from top level of the go tree, but it failed somewhere
where I didn't dig into more.

Kenji




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-16  1:51                   ` kokamoto
@ 2011-01-16  2:04                     ` kokamoto
  2011-01-16  6:21                       ` kokamoto
  2011-01-16  2:06                     ` [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
  1 sibling, 1 reply; 36+ messages in thread
From: kokamoto @ 2011-01-16  2:04 UTC (permalink / raw)
  To: 9fans

oups! I got
hello: exec header invalid

Kenji




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-16  1:51                   ` kokamoto
  2011-01-16  2:04                     ` kokamoto
@ 2011-01-16  2:06                     ` Skip Tavakkolian
  1 sibling, 0 replies; 36+ messages in thread
From: Skip Tavakkolian @ 2011-01-16  2:06 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs; +Cc: 9fans

Yes. Drawterm is convenient for executing programs exported in /mnt/term

On Jan 15, 2011, at 5:51 PM, kokamoto wrote:

> However, even if I could make a binary for Plan 9, I have to compile it
> on linux machine, and move the binary to Plan 9.
> Am I right?



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-16  2:04                     ` kokamoto
@ 2011-01-16  6:21                       ` kokamoto
  2011-01-17 12:03                         ` kokamoto
  2011-01-17 15:20                         ` [9fans] how to make hardware work? sergey.kish
  0 siblings, 2 replies; 36+ messages in thread
From: kokamoto @ 2011-01-16  6:21 UTC (permalink / raw)
  To: 9fans

Ok, now I got the right procedure to run hello.go.

1) do the patch posted here most recently
2) make sure GOOS=plan9 etc
3) at the top of the source tree, that should be $GOROOT/src
4) ./make.bash
   it stops at src/pkg/exec.  Don't mind it
5) 8g hello.go
6) 8l -s -o hello hello.8
7) copy the hello to somewhere in the real Plan 9 file tree
7) cd at the above directory
8) ./hello

Kenji




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
  2011-01-16  6:21                       ` kokamoto
@ 2011-01-17 12:03                         ` kokamoto
  2011-01-17 15:20                         ` [9fans] how to make hardware work? sergey.kish
  1 sibling, 0 replies; 36+ messages in thread
From: kokamoto @ 2011-01-17 12:03 UTC (permalink / raw)
  To: 9fans

> Ok, now I got the right procedure to run hello.go.

and the lists of fail of compile packages ($GOROOT/src/pk) are:

asn1, crypto/ocsp, crypto/x509, crypto/tls, debug, expvar,
go/printer, http, log, net, os/inotify, rpc, smtp, syslog,
tabwriter, testing, testing/iotest, time, websocket ☺

Kenji




^ permalink raw reply	[flat|nested] 36+ messages in thread

* [9fans] how to make hardware work?
  2011-01-16  6:21                       ` kokamoto
  2011-01-17 12:03                         ` kokamoto
@ 2011-01-17 15:20                         ` sergey.kish
  1 sibling, 0 replies; 36+ messages in thread
From: sergey.kish @ 2011-01-17 15:20 UTC (permalink / raw)
  To: 9fans

I've installed Plan 9 on my netbook. There are several things I can't
leave without - internet and music.

My system information collected in Linux and Plan 9, usb/ether output
https://gist.github.com/782904

Ethernet works ok, how to make PPP over USB?  I've found ppp(8),
usb/ether and cinap_lenrek/usbether, zwansch/usbuart in contrib.

    term% usb/ether -D
    usb/ether: fsioproc pid 471
    <- Tversion tag 65535 msize 8216 version '9P2000'
    -> Rversion tag 65535 msize 8192 version '9P2000'
    <- Tauth tag 4 afid 219 uname sergeykish aname
    -> Rerror tag 4 ename permission denied
    <- Tattach tag 4 fid 219 afid -1 uname sergeykish aname
    -> Rattach tag 4 qid (0000000000000000 0 d)
    usb/ether: startdevs: opening #0 [2]
    usb/ether: [2]: can't open endpoint [2]: '[2]' file does not exist
    usb/ether: no device found

I have no idea what to do.
There is no /dev/audio, cat '#A' says hardware isn't soundblaster.

Not so important issues:

* There is no plugged usb disk (which I use to boot)
* I'd like to have wifi
* and accelerated graphics (it is hard to get poulsbo working even on
Linux)

How to make it work? Is there tutorials, books? Ruby, Python,
JavaScript and Sh are my primary languages today. Used to program
windows applications on C++ (shame on me).




^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2011-01-17 15:20 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-11  7:54 [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
2011-01-11 14:11 ` erik quanstrom
2011-01-11 15:06   ` Devon H. O'Dell
2011-01-11 17:03   ` Charles Forsyth
2011-01-11 17:51     ` ron minnich
2011-01-11 19:35       ` Pavel Zholkover
2011-01-11 23:58       ` Charles Forsyth
2011-01-11 16:25 ` ron minnich
2011-01-12  8:32   ` Skip Tavakkolian
2011-01-12 16:12     ` andrey mirtchovski
2011-01-12 22:03       ` ron minnich
2011-01-13  5:54     ` ron minnich
2011-01-14 17:32       ` Pavel Zholkover
2011-01-15  2:00         ` Anthony Martin
2011-01-15  9:47           ` Pavel Zholkover
2011-01-15  9:01         ` kokamoto
2011-01-15  9:19           ` Pavel Zholkover
2011-01-15  9:30           ` lucio
2011-01-15  9:58             ` Pavel Zholkover
2011-01-15 10:29               ` lucio
2011-01-15 10:40               ` lucio
2011-01-15 11:25                 ` Pavel Zholkover
2011-01-16  1:51                   ` kokamoto
2011-01-16  2:04                     ` kokamoto
2011-01-16  6:21                       ` kokamoto
2011-01-17 12:03                         ` kokamoto
2011-01-17 15:20                         ` [9fans] how to make hardware work? sergey.kish
2011-01-16  2:06                     ` [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
2011-01-11 17:03 ` Pavel Zholkover
2011-01-11 18:55   ` Anthony Martin
2011-01-11 19:06     ` Anthony Martin
2011-01-11 22:58     ` ron minnich
2011-01-12 22:31       ` Anthony Martin
2011-01-12 22:36         ` erik quanstrom
2011-01-12 23:28           ` Pavel Zholkover
2011-01-12 23:29         ` Charles Forsyth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).