* [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).