summaryrefslogtreecommitdiff
path: root/src/lib/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/runtime')
-rw-r--r--src/lib/runtime/386/asm.s217
-rw-r--r--src/lib/runtime/386/closure.c104
-rw-r--r--src/lib/runtime/386/traceback.c148
-rwxr-xr-xsrc/lib/runtime/386/vlop.s48
-rwxr-xr-xsrc/lib/runtime/386/vlrt.c815
-rw-r--r--src/lib/runtime/Makefile125
-rw-r--r--src/lib/runtime/amd64/asm.s207
-rw-r--r--src/lib/runtime/amd64/closure.c121
-rw-r--r--src/lib/runtime/amd64/traceback.c146
-rw-r--r--src/lib/runtime/arm/asm.s83
-rw-r--r--src/lib/runtime/arm/closure.c4
-rw-r--r--src/lib/runtime/arm/traceback.s0
-rw-r--r--src/lib/runtime/array.c175
-rw-r--r--src/lib/runtime/cgo2c.c602
-rw-r--r--src/lib/runtime/chan.c1024
-rw-r--r--src/lib/runtime/darwin/386/defs.h229
-rwxr-xr-xsrc/lib/runtime/darwin/386/rt0.s8
-rw-r--r--src/lib/runtime/darwin/386/signal.c103
-rw-r--r--src/lib/runtime/darwin/386/sys.s278
-rw-r--r--src/lib/runtime/darwin/amd64/defs.h244
-rw-r--r--src/lib/runtime/darwin/amd64/rt0.s9
-rw-r--r--src/lib/runtime/darwin/amd64/signal.c111
-rw-r--r--src/lib/runtime/darwin/amd64/sys.s263
-rw-r--r--src/lib/runtime/darwin/defs.c104
-rw-r--r--src/lib/runtime/darwin/os.h24
-rw-r--r--src/lib/runtime/darwin/signals.h48
-rw-r--r--src/lib/runtime/darwin/thread.c441
-rw-r--r--src/lib/runtime/extern.go28
-rw-r--r--src/lib/runtime/float.c173
-rw-r--r--src/lib/runtime/float_go.cgo52
-rw-r--r--src/lib/runtime/hashmap.c954
-rw-r--r--src/lib/runtime/hashmap.h161
-rw-r--r--src/lib/runtime/iface.c906
-rwxr-xr-xsrc/lib/runtime/linux/386/defs.h136
-rwxr-xr-xsrc/lib/runtime/linux/386/rt0.s8
-rw-r--r--src/lib/runtime/linux/386/signal.c102
-rwxr-xr-xsrc/lib/runtime/linux/386/sys.s222
-rw-r--r--src/lib/runtime/linux/amd64/defs.h175
-rw-r--r--src/lib/runtime/linux/amd64/rt0.s9
-rw-r--r--src/lib/runtime/linux/amd64/signal.c112
-rw-r--r--src/lib/runtime/linux/amd64/sys.s193
-rw-r--r--src/lib/runtime/linux/arm/defs.h27
-rw-r--r--src/lib/runtime/linux/arm/rt0.s6
-rw-r--r--src/lib/runtime/linux/arm/signal.c4
-rw-r--r--src/lib/runtime/linux/arm/sys.s15
-rw-r--r--src/lib/runtime/linux/defs.c40
-rw-r--r--src/lib/runtime/linux/defs1.c25
-rw-r--r--src/lib/runtime/linux/defs2.c51
-rw-r--r--src/lib/runtime/linux/defs_arm.c54
-rw-r--r--src/lib/runtime/linux/os.h10
-rw-r--r--src/lib/runtime/linux/signals.h48
-rw-r--r--src/lib/runtime/linux/thread.c282
-rw-r--r--src/lib/runtime/malloc.c308
-rw-r--r--src/lib/runtime/malloc.h308
-rw-r--r--src/lib/runtime/malloc_go.cgo28
-rw-r--r--src/lib/runtime/mcache.c105
-rw-r--r--src/lib/runtime/mcentral.c192
-rw-r--r--src/lib/runtime/mem.c75
-rw-r--r--src/lib/runtime/mfixalloc.c56
-rw-r--r--src/lib/runtime/mgc0.c231
-rw-r--r--src/lib/runtime/mheap.c333
-rw-r--r--src/lib/runtime/mheapmap32.c96
-rw-r--r--src/lib/runtime/mheapmap32.h76
-rw-r--r--src/lib/runtime/mheapmap64.c117
-rw-r--r--src/lib/runtime/mheapmap64.h96
-rw-r--r--src/lib/runtime/msize.c165
-rw-r--r--src/lib/runtime/print.c268
-rw-r--r--src/lib/runtime/proc.c858
-rw-r--r--src/lib/runtime/rune.c238
-rw-r--r--src/lib/runtime/runtime.c462
-rw-r--r--src/lib/runtime/runtime.h464
-rw-r--r--src/lib/runtime/sema.c176
-rw-r--r--src/lib/runtime/sema_go.cgo15
-rw-r--r--src/lib/runtime/string.c263
-rw-r--r--src/lib/runtime/symtab.c377
75 files changed, 0 insertions, 14781 deletions
diff --git a/src/lib/runtime/386/asm.s b/src/lib/runtime/386/asm.s
deleted file mode 100644
index 5d3c4261a..000000000
--- a/src/lib/runtime/386/asm.s
+++ /dev/null
@@ -1,217 +0,0 @@
-// 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.
-
-TEXT _rt0_386(SB),7,$0
- // copy arguments forward on an even stack
- MOVL 0(SP), AX // argc
- LEAL 4(SP), BX // argv
- SUBL $128, SP // plenty of scratch
- ANDL $~7, SP
- MOVL AX, 120(SP) // save argc, argv away
- MOVL BX, 124(SP)
-
-/*
- // write "go386\n"
- PUSHL $6
- PUSHL $hello(SB)
- PUSHL $1
- CALL sys·write(SB)
- POPL AX
- POPL AX
- POPL AX
-*/
-
- CALL ldt0setup(SB)
-
- // set up %fs to refer to that ldt entry
- MOVL $(7*8+7), AX
- MOVW AX, FS
-
- // store through it, to make sure it works
- MOVL $0x123, 0(FS)
- MOVL tls0(SB), AX
- CMPL AX, $0x123
- JEQ ok
- MOVL AX, 0
-ok:
-
- // set up m and g "registers"
- // g is 0(FS), m is 4(FS)
- LEAL g0(SB), CX
- MOVL CX, 0(FS)
- LEAL m0(SB), AX
- MOVL AX, 4(FS)
-
- // save m->g0 = g0
- MOVL CX, 0(AX)
-
- // create istack out of the OS stack
- LEAL (-8192+104)(SP), AX // TODO: 104?
- MOVL AX, 0(CX) // 8(g) is stack limit (w 104b guard)
- MOVL SP, 4(CX) // 12(g) is base
- CALL emptyfunc(SB) // fault if stack check is wrong
-
- // convention is D is always cleared
- CLD
-
- CALL check(SB)
-
- // saved argc, argv
- MOVL 120(SP), AX
- MOVL AX, 0(SP)
- MOVL 124(SP), AX
- MOVL AX, 4(SP)
- CALL args(SB)
- CALL osinit(SB)
- CALL schedinit(SB)
-
- // create a new goroutine to start program
- PUSHL $mainstart(SB) // entry
- PUSHL $8 // arg size
- CALL sys·newproc(SB)
- POPL AX
- POPL AX
-
- // start this M
- CALL mstart(SB)
-
- INT $3
- RET
-
-TEXT mainstart(SB),7,$0
- CALL main·init(SB)
- CALL initdone(SB)
- CALL main·main(SB)
- PUSHL $0
- CALL exit(SB)
- POPL AX
- INT $3
- RET
-
-TEXT breakpoint(SB),7,$0
- BYTE $0xcc
- RET
-
-// go-routine
-TEXT gogo(SB), 7, $0
- MOVL 4(SP), AX // gobuf
- MOVL 0(AX), SP // restore SP
- MOVL 4(AX), AX
- MOVL AX, 0(SP) // put PC on the stack
- MOVL $1, AX
- RET
-
-TEXT gosave(SB), 7, $0
- MOVL 4(SP), AX // gobuf
- MOVL SP, 0(AX) // save SP
- MOVL 0(SP), BX
- MOVL BX, 4(AX) // save PC
- MOVL $0, AX // return 0
- RET
-
-// support for morestack
-
-// return point when leaving new stack.
-// save AX, jmp to lesstack to switch back
-TEXT retfromnewstack(SB),7,$0
- MOVL 4(FS), BX // m
- MOVL AX, 12(BX) // save AX in m->cret
- JMP lessstack(SB)
-
-// gogo, returning 2nd arg instead of 1
-TEXT gogoret(SB), 7, $0
- MOVL 8(SP), AX // return 2nd arg
- MOVL 4(SP), BX // gobuf
- MOVL 0(BX), SP // restore SP
- MOVL 4(BX), BX
- MOVL BX, 0(SP) // put PC on the stack
- RET
-
-TEXT setspgoto(SB), 7, $0
- MOVL 4(SP), AX // SP
- MOVL 8(SP), BX // fn to call
- MOVL 12(SP), CX // fn to return
- MOVL AX, SP
- PUSHL CX
- JMP BX
- POPL AX // not reached
- RET
-
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// }else
-// return 0;
-TEXT cas(SB), 7, $0
- MOVL 4(SP), BX
- MOVL 8(SP), AX
- MOVL 12(SP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- JZ 3(PC)
- MOVL $0, AX
- RET
- MOVL $1, AX
- RET
-
-// void jmpdefer(fn, sp);
-// called from deferreturn.
-// 1. pop the caller
-// 2. sub 5 bytes from the callers return
-// 3. jmp to the argument
-TEXT jmpdefer(SB), 7, $0
- MOVL 4(SP), AX // fn
- MOVL 8(SP), BX // caller sp
- LEAL -4(BX), SP // caller sp after CALL
- SUBL $5, (SP) // return to CALL again
- JMP AX // but first run the deferred function
-
-TEXT sys·memclr(SB),7,$0
- MOVL 4(SP), DI // arg 1 addr
- MOVL 8(SP), CX // arg 2 count
- ADDL $3, CX
- SHRL $2, CX
- MOVL $0, AX
- CLD
- REP
- STOSL
- RET
-
-TEXT sys·getcallerpc+0(SB),7,$0
- MOVL x+0(FP),AX // addr of first arg
- MOVL -4(AX),AX // get calling pc
- RET
-
-TEXT sys·setcallerpc+0(SB),7,$0
- MOVL x+0(FP),AX // addr of first arg
- MOVL x+4(FP), BX
- MOVL BX, -4(AX) // set calling pc
- RET
-
-TEXT ldt0setup(SB),7,$16
- // set up ldt 7 to point at tls0
- // ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
- MOVL $7, 0(SP)
- LEAL tls0(SB), AX
- MOVL AX, 4(SP)
- MOVL $32, 8(SP) // sizeof(tls array)
- CALL setldt(SB)
- RET
-
-GLOBL m0+0(SB), $1024
-GLOBL g0+0(SB), $1024
-
-GLOBL tls0+0(SB), $32
-
-TEXT emptyfunc(SB),0,$0
- RET
-
-TEXT abort(SB),7,$0
- INT $0x3
-
-DATA hello+0(SB)/8, $"go386\n\z\z"
-GLOBL hello+0(SB), $8
-
diff --git a/src/lib/runtime/386/closure.c b/src/lib/runtime/386/closure.c
deleted file mode 100644
index 6ccbe3b8b..000000000
--- a/src/lib/runtime/386/closure.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-#pragma textflag 7
-// func closure(siz int32,
-// fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
-// arg0, arg1, arg2 *ptr) (func(xxx) yyy)
-void
-sys·closure(int32 siz, byte *fn, byte *arg0)
-{
- byte *p, *q, **ret;
- int32 i, n;
- int32 pcrel;
-
- if(siz < 0 || siz%4 != 0)
- throw("bad closure size");
-
- ret = (byte**)((byte*)&arg0 + siz);
-
- if(siz > 100) {
- // TODO(rsc): implement stack growth preamble?
- throw("closure too big");
- }
-
- // compute size of new fn.
- // must match code laid out below.
- n = 6+5+2+1; // SUBL MOVL MOVL CLD
- if(siz <= 4*4)
- n += 1*siz/4; // MOVSL MOVSL...
- else
- n += 6+2; // MOVL REP MOVSL
- n += 5; // CALL
- n += 6+1; // ADDL RET
-
- // store args aligned after code, so gc can find them.
- n += siz;
- if(n%4)
- n += 4 - n%4;
-
- p = mal(n);
- *ret = p;
- q = p + n - siz;
- mcpy(q, (byte*)&arg0, siz);
-
- // SUBL $siz, SP
- *p++ = 0x81;
- *p++ = 0xec;
- *(uint32*)p = siz;
- p += 4;
-
- // MOVL $q, SI
- *p++ = 0xbe;
- *(byte**)p = q;
- p += 4;
-
- // MOVL SP, DI
- *p++ = 0x89;
- *p++ = 0xe7;
-
- // CLD
- *p++ = 0xfc;
-
- if(siz <= 4*4) {
- for(i=0; i<siz; i+=4) {
- // MOVSL
- *p++ = 0xa5;
- }
- } else {
- // MOVL $(siz/4), CX [32-bit immediate siz/4]
- *p++ = 0xc7;
- *p++ = 0xc1;
- *(uint32*)p = siz/4;
- p += 4;
-
- // REP; MOVSL
- *p++ = 0xf3;
- *p++ = 0xa5;
- }
-
- // call fn
- pcrel = fn - (p+5);
- // direct call with pc-relative offset
- // CALL fn
- *p++ = 0xe8;
- *(int32*)p = pcrel;
- p += 4;
-
- // ADDL $siz, SP
- *p++ = 0x81;
- *p++ = 0xc4;
- *(uint32*)p = siz;
- p += 4;
-
- // RET
- *p++ = 0xc3;
-
- if(p > q)
- throw("bad math in sys.closure");
-}
-
-
diff --git a/src/lib/runtime/386/traceback.c b/src/lib/runtime/386/traceback.c
deleted file mode 100644
index 05724d9ac..000000000
--- a/src/lib/runtime/386/traceback.c
+++ /dev/null
@@ -1,148 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-// TODO(rsc): Move this into portable code, with calls to a
-// machine-dependent isclosure() function.
-
-void
-traceback(byte *pc0, byte *sp, G *g)
-{
- Stktop *stk;
- uintptr pc;
- int32 i, n;
- Func *f;
- byte *p;
-
- pc = (uintptr)pc0;
-
- // If the PC is zero, it's likely a nil function call.
- // Start in the caller's frame.
- if(pc == 0) {
- pc = *(uintptr*)sp;
- sp += sizeof(uintptr);
- }
-
- stk = (Stktop*)g->stackbase;
- for(n=0; n<100; n++) {
- while(pc == (uintptr)retfromnewstack) {
- // pop to earlier stack block
- sp = stk->oldsp;
- stk = (Stktop*)stk->oldbase;
- pc = *(uintptr*)(sp+sizeof(uintptr));
- sp += 2*sizeof(uintptr); // two irrelevant calls on stack: morestack plus its call
- }
- f = findfunc(pc);
- if(f == nil) {
- // dangerous, but poke around to see if it is a closure
- p = (byte*)pc;
- // ADDL $xxx, SP; RET
- if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
- sp += *(uint32*)(p+2) + 8;
- pc = *(uintptr*)(sp - 8);
- if(pc <= 0x1000)
- return;
- continue;
- }
- printf("%p unknown pc\n", pc);
- return;
- }
- if(f->frame < sizeof(uintptr)) // assembly funcs say 0 but lie
- sp += sizeof(uintptr);
- else
- sp += f->frame;
-
- // print this frame
- // main+0xf /home/rsc/go/src/runtime/x.go:23
- // main(0x1, 0x2, 0x3)
- printf("%S", f->name);
- if(pc > f->entry)
- printf("+%p", (uintptr)(pc - f->entry));
- printf(" %S:%d\n", f->src, funcline(f, pc-1)); // -1 to get to CALL instr.
- printf("\t%S(", f->name);
- for(i = 0; i < f->args; i++) {
- if(i != 0)
- prints(", ");
- sys·printhex(((uint32*)sp)[i]);
- if(i >= 4) {
- prints(", ...");
- break;
- }
- }
- prints(")\n");
-
- pc = *(uintptr*)(sp-sizeof(uintptr));
- if(pc <= 0x1000)
- return;
- }
- prints("...\n");
-}
-
-// func caller(n int) (pc uintptr, file string, line int, ok bool)
-void
-runtime·Caller(int32 n, uintptr retpc, String retfile, int32 retline, bool retbool)
-{
- uintptr pc;
- byte *sp;
- byte *p;
- Stktop *stk;
- Func *f;
-
- // our caller's pc, sp.
- sp = (byte*)&n;
- pc = *((uintptr*)sp - 1);
- if((f = findfunc(pc)) == nil) {
- error:
- retpc = 0;
- retline = 0;
- retfile = emptystring;
- retbool = false;
- FLUSH(&retpc);
- FLUSH(&retfile);
- FLUSH(&retline);
- FLUSH(&retbool);
- return;
- }
-
- // now unwind n levels
- stk = (Stktop*)g->stackbase;
- while(n-- > 0) {
- while(pc == (uintptr)retfromnewstack) {
- sp = stk->oldsp;
- stk = (Stktop*)stk->oldbase;
- pc = *((uintptr*)sp + 1);
- sp += 2*sizeof(uintptr);
- }
-
- if(f->frame < sizeof(uintptr)) // assembly functions lie
- sp += sizeof(uintptr);
- else
- sp += f->frame;
-
- loop:
- pc = *((uintptr*)sp - 1);
- if(pc <= 0x1000 || (f = findfunc(pc)) == nil) {
- // dangerous, but let's try this.
- // see if it is a closure.
- p = (byte*)pc;
- // ADDL $xxx, SP; RET
- if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
- sp += *(uint32*)(p+2) + sizeof(uintptr);
- goto loop;
- }
- goto error;
- }
- }
-
- retpc = pc;
- retfile = f->src;
- retline = funcline(f, pc-1);
- retbool = true;
- FLUSH(&retpc);
- FLUSH(&retfile);
- FLUSH(&retline);
- FLUSH(&retbool);
-}
-
diff --git a/src/lib/runtime/386/vlop.s b/src/lib/runtime/386/vlop.s
deleted file mode 100755
index 803276ce2..000000000
--- a/src/lib/runtime/386/vlop.s
+++ /dev/null
@@ -1,48 +0,0 @@
-// Inferno's libkern/vlop-386.s
-// http://code.google.com/p/inferno-os/source/browse/libkern/vlop-386.s
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
-// Portions Copyright 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * C runtime for 64-bit divide.
- */
-
-TEXT _mul64by32(SB), 7, $0
- MOVL r+0(FP), CX
- MOVL a+4(FP), AX
- MULL b+12(FP)
- MOVL AX, 0(CX)
- MOVL DX, BX
- MOVL a+8(FP), AX
- MULL b+12(FP)
- ADDL AX, BX
- MOVL BX, 4(CX)
- RET
-
-TEXT _div64by32(SB), 7, $0
- MOVL r+12(FP), CX
- MOVL a+0(FP), AX
- MOVL a+4(FP), DX
- DIVL b+8(FP)
- MOVL DX, 0(CX)
- RET
diff --git a/src/lib/runtime/386/vlrt.c b/src/lib/runtime/386/vlrt.c
deleted file mode 100755
index 093cca70d..000000000
--- a/src/lib/runtime/386/vlrt.c
+++ /dev/null
@@ -1,815 +0,0 @@
-// Inferno's libkern/vlrt-386.c
-// http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-386.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
-// Portions Copyright 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * C runtime for 64-bit divide, others.
- *
- * TODO(rsc): The simple functions are dregs--8c knows how
- * to generate the code directly now. Find and remove.
- */
-
-typedef unsigned long ulong;
-typedef unsigned int uint;
-typedef unsigned short ushort;
-typedef unsigned char uchar;
-typedef signed char schar;
-
-#define SIGN(n) (1UL<<(n-1))
-
-typedef struct Vlong Vlong;
-struct Vlong
-{
- union
- {
- long long v;
- struct
- {
- ulong lo;
- ulong hi;
- };
- struct
- {
- ushort lols;
- ushort loms;
- ushort hils;
- ushort hims;
- };
- };
-};
-
-void abort(void);
-
-void
-_d2v(Vlong *y, double d)
-{
- union { double d; struct Vlong; } x;
- ulong xhi, xlo, ylo, yhi;
- int sh;
-
- x.d = d;
-
- xhi = (x.hi & 0xfffff) | 0x100000;
- xlo = x.lo;
- sh = 1075 - ((x.hi >> 20) & 0x7ff);
-
- ylo = 0;
- yhi = 0;
- if(sh >= 0) {
- /* v = (hi||lo) >> sh */
- if(sh < 32) {
- if(sh == 0) {
- ylo = xlo;
- yhi = xhi;
- } else {
- ylo = (xlo >> sh) | (xhi << (32-sh));
- yhi = xhi >> sh;
- }
- } else {
- if(sh == 32) {
- ylo = xhi;
- } else
- if(sh < 64) {
- ylo = xhi >> (sh-32);
- }
- }
- } else {
- /* v = (hi||lo) << -sh */
- sh = -sh;
- if(sh <= 10) {
- ylo = xlo << sh;
- yhi = (xhi << sh) | (xlo >> (32-sh));
- } else {
- /* overflow */
- yhi = d; /* causes something awful */
- }
- }
- if(x.hi & SIGN(32)) {
- if(ylo != 0) {
- ylo = -ylo;
- yhi = ~yhi;
- } else
- yhi = -yhi;
- }
-
- y->hi = yhi;
- y->lo = ylo;
-}
-
-void
-_f2v(Vlong *y, float f)
-{
-
- _d2v(y, f);
-}
-
-double
-_v2d(Vlong x)
-{
- if(x.hi & SIGN(32)) {
- if(x.lo) {
- x.lo = -x.lo;
- x.hi = ~x.hi;
- } else
- x.hi = -x.hi;
- return -((long)x.hi*4294967296. + x.lo);
- }
- return (long)x.hi*4294967296. + x.lo;
-}
-
-float
-_v2f(Vlong x)
-{
- return _v2d(x);
-}
-
-ulong _div64by32(Vlong, ulong, ulong*);
-void _mul64by32(Vlong*, Vlong, ulong);
-
-static void
-slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
-{
- ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
- int i;
-
- numhi = num.hi;
- numlo = num.lo;
- denhi = den.hi;
- denlo = den.lo;
-
- /*
- * get a divide by zero
- */
- if(denlo==0 && denhi==0) {
- numlo = numlo / denlo;
- }
-
- /*
- * set up the divisor and find the number of iterations needed
- */
- if(numhi >= SIGN(32)) {
- quohi = SIGN(32);
- quolo = 0;
- } else {
- quohi = numhi;
- quolo = numlo;
- }
- i = 0;
- while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
- denhi = (denhi<<1) | (denlo>>31);
- denlo <<= 1;
- i++;
- }
-
- quohi = 0;
- quolo = 0;
- for(; i >= 0; i--) {
- quohi = (quohi<<1) | (quolo>>31);
- quolo <<= 1;
- if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
- t = numlo;
- numlo -= denlo;
- if(numlo > t)
- numhi--;
- numhi -= denhi;
- quolo |= 1;
- }
- denlo = (denlo>>1) | (denhi<<31);
- denhi >>= 1;
- }
-
- if(q) {
- q->lo = quolo;
- q->hi = quohi;
- }
- if(r) {
- r->lo = numlo;
- r->hi = numhi;
- }
-}
-
-static void
-dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
-{
- ulong n;
- Vlong x, q, r;
-
- if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){
- if(qp) {
- qp->hi = 0;
- qp->lo = 0;
- }
- if(rp) {
- rp->hi = num.hi;
- rp->lo = num.lo;
- }
- return;
- }
-
- if(den.hi != 0){
- q.hi = 0;
- n = num.hi/den.hi;
- _mul64by32(&x, den, n);
- if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
- slowdodiv(num, den, &q, &r);
- else {
- q.lo = n;
- r.v = num.v - x.v;
- }
- } else {
- if(num.hi >= den.lo){
- q.hi = n = num.hi/den.lo;
- num.hi -= den.lo*n;
- } else {
- q.hi = 0;
- }
- q.lo = _div64by32(num, den.lo, &r.lo);
- r.hi = 0;
- }
- if(qp) {
- qp->lo = q.lo;
- qp->hi = q.hi;
- }
- if(rp) {
- rp->lo = r.lo;
- rp->hi = r.hi;
- }
-}
-
-void
-_divvu(Vlong *q, Vlong n, Vlong d)
-{
-
- if(n.hi == 0 && d.hi == 0) {
- q->hi = 0;
- q->lo = n.lo / d.lo;
- return;
- }
- dodiv(n, d, q, 0);
-}
-
-void
-sys·uint64div(Vlong n, Vlong d, Vlong q)
-{
- _divvu(&q, n, d);
-}
-
-void
-_modvu(Vlong *r, Vlong n, Vlong d)
-{
-
- if(n.hi == 0 && d.hi == 0) {
- r->hi = 0;
- r->lo = n.lo % d.lo;
- return;
- }
- dodiv(n, d, 0, r);
-}
-
-void
-sys·uint64mod(Vlong n, Vlong d, Vlong q)
-{
- _modvu(&q, n, d);
-}
-
-static void
-vneg(Vlong *v)
-{
-
- if(v->lo == 0) {
- v->hi = -v->hi;
- return;
- }
- v->lo = -v->lo;
- v->hi = ~v->hi;
-}
-
-void
-_divv(Vlong *q, Vlong n, Vlong d)
-{
- long nneg, dneg;
-
- if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
- if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
- // special case: 32-bit -0x80000000 / -1 causes divide error,
- // but it's okay in this 64-bit context.
- q->lo = 0x80000000;
- q->hi = 0;
- return;
- }
- q->lo = (long)n.lo / (long)d.lo;
- q->hi = ((long)q->lo) >> 31;
- return;
- }
- nneg = n.hi >> 31;
- if(nneg)
- vneg(&n);
- dneg = d.hi >> 31;
- if(dneg)
- vneg(&d);
- dodiv(n, d, q, 0);
- if(nneg != dneg)
- vneg(q);
-}
-
-void
-sys·int64div(Vlong n, Vlong d, Vlong q)
-{
- _divv(&q, n, d);
-}
-
-void
-_modv(Vlong *r, Vlong n, Vlong d)
-{
- long nneg, dneg;
-
- if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
- if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
- // special case: 32-bit -0x80000000 % -1 causes divide error,
- // but it's okay in this 64-bit context.
- r->lo = 0;
- r->hi = 0;
- return;
- }
- r->lo = (long)n.lo % (long)d.lo;
- r->hi = ((long)r->lo) >> 31;
- return;
- }
- nneg = n.hi >> 31;
- if(nneg)
- vneg(&n);
- dneg = d.hi >> 31;
- if(dneg)
- vneg(&d);
- dodiv(n, d, 0, r);
- if(nneg)
- vneg(r);
-}
-
-void
-sys·int64mod(Vlong n, Vlong d, Vlong q)
-{
- _modv(&q, n, d);
-}
-
-void
-_rshav(Vlong *r, Vlong a, int b)
-{
- long t;
-
- t = a.hi;
- if(b >= 32) {
- r->hi = t>>31;
- if(b >= 64) {
- /* this is illegal re C standard */
- r->lo = t>>31;
- return;
- }
- r->lo = t >> (b-32);
- return;
- }
- if(b <= 0) {
- r->hi = t;
- r->lo = a.lo;
- return;
- }
- r->hi = t >> b;
- r->lo = (t << (32-b)) | (a.lo >> b);
-}
-
-void
-_rshlv(Vlong *r, Vlong a, int b)
-{
- ulong t;
-
- t = a.hi;
- if(b >= 32) {
- r->hi = 0;
- if(b >= 64) {
- /* this is illegal re C standard */
- r->lo = 0;
- return;
- }
- r->lo = t >> (b-32);
- return;
- }
- if(b <= 0) {
- r->hi = t;
- r->lo = a.lo;
- return;
- }
- r->hi = t >> b;
- r->lo = (t << (32-b)) | (a.lo >> b);
-}
-
-void
-_lshv(Vlong *r, Vlong a, int b)
-{
- ulong t;
-
- t = a.lo;
- if(b >= 32) {
- r->lo = 0;
- if(b >= 64) {
- /* this is illegal re C standard */
- r->hi = 0;
- return;
- }
- r->hi = t << (b-32);
- return;
- }
- if(b <= 0) {
- r->lo = t;
- r->hi = a.hi;
- return;
- }
- r->lo = t << b;
- r->hi = (t >> (32-b)) | (a.hi << b);
-}
-
-void
-_andv(Vlong *r, Vlong a, Vlong b)
-{
- r->hi = a.hi & b.hi;
- r->lo = a.lo & b.lo;
-}
-
-void
-_orv(Vlong *r, Vlong a, Vlong b)
-{
- r->hi = a.hi | b.hi;
- r->lo = a.lo | b.lo;
-}
-
-void
-_xorv(Vlong *r, Vlong a, Vlong b)
-{
- r->hi = a.hi ^ b.hi;
- r->lo = a.lo ^ b.lo;
-}
-
-void
-_vpp(Vlong *l, Vlong *r)
-{
-
- l->hi = r->hi;
- l->lo = r->lo;
- r->lo++;
- if(r->lo == 0)
- r->hi++;
-}
-
-void
-_vmm(Vlong *l, Vlong *r)
-{
-
- l->hi = r->hi;
- l->lo = r->lo;
- if(r->lo == 0)
- r->hi--;
- r->lo--;
-}
-
-void
-_ppv(Vlong *l, Vlong *r)
-{
-
- r->lo++;
- if(r->lo == 0)
- r->hi++;
- l->hi = r->hi;
- l->lo = r->lo;
-}
-
-void
-_mmv(Vlong *l, Vlong *r)
-{
-
- if(r->lo == 0)
- r->hi--;
- r->lo--;
- l->hi = r->hi;
- l->lo = r->lo;
-}
-
-void
-_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
-{
- Vlong t, u;
-
- u.lo = 0;
- u.hi = 0;
- switch(type) {
- default:
- abort();
- break;
-
- case 1: /* schar */
- t.lo = *(schar*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(schar*)lv = u.lo;
- break;
-
- case 2: /* uchar */
- t.lo = *(uchar*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(uchar*)lv = u.lo;
- break;
-
- case 3: /* short */
- t.lo = *(short*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(short*)lv = u.lo;
- break;
-
- case 4: /* ushort */
- t.lo = *(ushort*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(ushort*)lv = u.lo;
- break;
-
- case 9: /* int */
- t.lo = *(int*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(int*)lv = u.lo;
- break;
-
- case 10: /* uint */
- t.lo = *(uint*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(uint*)lv = u.lo;
- break;
-
- case 5: /* long */
- t.lo = *(long*)lv;
- t.hi = t.lo >> 31;
- fn(&u, t, rv);
- *(long*)lv = u.lo;
- break;
-
- case 6: /* ulong */
- t.lo = *(ulong*)lv;
- t.hi = 0;
- fn(&u, t, rv);
- *(ulong*)lv = u.lo;
- break;
-
- case 7: /* vlong */
- case 8: /* uvlong */
- fn(&u, *(Vlong*)lv, rv);
- *(Vlong*)lv = u;
- break;
- }
- *ret = u;
-}
-
-void
-_p2v(Vlong *ret, void *p)
-{
- long t;
-
- t = (ulong)p;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_sl2v(Vlong *ret, long sl)
-{
- long t;
-
- t = sl;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_ul2v(Vlong *ret, ulong ul)
-{
- long t;
-
- t = ul;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_si2v(Vlong *ret, int si)
-{
- long t;
-
- t = si;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_ui2v(Vlong *ret, uint ui)
-{
- long t;
-
- t = ui;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_sh2v(Vlong *ret, long sh)
-{
- long t;
-
- t = (sh << 16) >> 16;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_uh2v(Vlong *ret, ulong ul)
-{
- long t;
-
- t = ul & 0xffff;
- ret->lo = t;
- ret->hi = 0;
-}
-
-void
-_sc2v(Vlong *ret, long uc)
-{
- long t;
-
- t = (uc << 24) >> 24;
- ret->lo = t;
- ret->hi = t >> 31;
-}
-
-void
-_uc2v(Vlong *ret, ulong ul)
-{
- long t;
-
- t = ul & 0xff;
- ret->lo = t;
- ret->hi = 0;
-}
-
-long
-_v2sc(Vlong rv)
-{
- long t;
-
- t = rv.lo & 0xff;
- return (t << 24) >> 24;
-}
-
-long
-_v2uc(Vlong rv)
-{
-
- return rv.lo & 0xff;
-}
-
-long
-_v2sh(Vlong rv)
-{
- long t;
-
- t = rv.lo & 0xffff;
- return (t << 16) >> 16;
-}
-
-long
-_v2uh(Vlong rv)
-{
-
- return rv.lo & 0xffff;
-}
-
-long
-_v2sl(Vlong rv)
-{
-
- return rv.lo;
-}
-
-long
-_v2ul(Vlong rv)
-{
-
- return rv.lo;
-}
-
-long
-_v2si(Vlong rv)
-{
-
- return rv.lo;
-}
-
-long
-_v2ui(Vlong rv)
-{
-
- return rv.lo;
-}
-
-int
-_testv(Vlong rv)
-{
- return rv.lo || rv.hi;
-}
-
-int
-_eqv(Vlong lv, Vlong rv)
-{
- return lv.lo == rv.lo && lv.hi == rv.hi;
-}
-
-int
-_nev(Vlong lv, Vlong rv)
-{
- return lv.lo != rv.lo || lv.hi != rv.hi;
-}
-
-int
-_ltv(Vlong lv, Vlong rv)
-{
- return (long)lv.hi < (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo < rv.lo);
-}
-
-int
-_lev(Vlong lv, Vlong rv)
-{
- return (long)lv.hi < (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo <= rv.lo);
-}
-
-int
-_gtv(Vlong lv, Vlong rv)
-{
- return (long)lv.hi > (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo > rv.lo);
-}
-
-int
-_gev(Vlong lv, Vlong rv)
-{
- return (long)lv.hi > (long)rv.hi ||
- (lv.hi == rv.hi && lv.lo >= rv.lo);
-}
-
-int
-_lov(Vlong lv, Vlong rv)
-{
- return lv.hi < rv.hi ||
- (lv.hi == rv.hi && lv.lo < rv.lo);
-}
-
-int
-_lsv(Vlong lv, Vlong rv)
-{
- return lv.hi < rv.hi ||
- (lv.hi == rv.hi && lv.lo <= rv.lo);
-}
-
-int
-_hiv(Vlong lv, Vlong rv)
-{
- return lv.hi > rv.hi ||
- (lv.hi == rv.hi && lv.lo > rv.lo);
-}
-
-int
-_hsv(Vlong lv, Vlong rv)
-{
- return lv.hi > rv.hi ||
- (lv.hi == rv.hi && lv.lo >= rv.lo);
-}
diff --git a/src/lib/runtime/Makefile b/src/lib/runtime/Makefile
deleted file mode 100644
index 5a5ace9c5..000000000
--- a/src/lib/runtime/Makefile
+++ /dev/null
@@ -1,125 +0,0 @@
-# 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.
-
-# Set SIZE to 32 or 64.
-SIZE_386=32
-SIZE_amd64=64
-SIZE_arm=32
-SIZE=$(SIZE_$(GOARCH))
-
-# Setup CFLAGS. Add -D_64BIT on 64-bit platforms (sorry).
-CFLAGS_64=-D_64BIT
-CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF $(CFLAGS_$(SIZE))
-
-# Set O to right letter.
-O_386=8
-O_amd64=6
-O_arm=5
-O=$(O_$(GOARCH))
-
-# Tools
-CC=$(O)c
-GC=$(O)g
-AS=$(O)a
-AR=gopack
-
-LIB=runtime.a
-
-# 386-specific object files
-OFILES_386=\
- vlop.$O\
- vlrt.$O\
-
-OFILES=\
- array.$O\
- asm.$O\
- chan.$O\
- closure.$O\
- extern.$O\
- float.$O\
- float_go.$O\
- hashmap.$O\
- iface.$O\
- malloc.$O\
- malloc_go.$O\
- mcache.$O\
- mcentral.$O\
- mem.$O\
- mfixalloc.$O\
- mgc0.$O\
- mheap.$O\
- mheapmap$(SIZE).$O\
- msize.$O\
- print.$O\
- proc.$O\
- rune.$O\
- runtime.$O\
- rt0.$O\
- sema.$O\
- sema_go.$O\
- signal.$O\
- string.$O\
- symtab.$O\
- sys.$O\
- thread.$O\
- traceback.$O\
- $(OFILES_$(GOARCH))\
-
-HFILES=\
- runtime.h\
- hashmap.h\
- malloc.h\
- $(GOOS)/os.h\
- $(GOOS)/$(GOARCH)/defs.h\
-
-install: $(LIB) runtime.acid
- test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)
- cp $(LIB) $(GOROOT)/pkg/$(GOOS)_$(GOARCH)/$(LIB)
- cp runtime.acid $(GOROOT)/acid/runtime.acid
-
-$(LIB): $(OFILES)
- $(AR) grc $(LIB) $(OFILES)
-
-$(OFILES): $(HFILES)
-
-nuke:
- rm -f *.[568] *.a $(GOROOT)/lib/$(LIB)
-
-clean:
- rm -f *.[568] *.a runtime.acid cgo2c
-
-%.$O: %.go
- $(GC) $<
-
-%.$O: %.c
- $(CC) $(CFLAGS) $<
-
-%.$O: $(GOARCH)/%.c
- $(CC) $(CFLAGS) $<
-
-%.$O: $(GOOS)/%.c
- $(CC) $(CFLAGS) $<
-
-%.$O: $(GOOS)/$(GOARCH)/%.c
- $(CC) $(CFLAGS) $<
-
-%.$O: $(GOARCH)/%.s
- $(AS) $<
-
-%.$O: $(GOOS)/$(GOARCH)/%.s
- $(AS) $<
-
-cgo2c: cgo2c.c
- quietgcc -o $@ $<
-
-%.c: %.cgo cgo2c
- ./cgo2c $< > $@.tmp
- mv -f $@.tmp $@
-
-runtime.acid: runtime.h proc.c
- $(CC) -a proc.c >runtime.acid
-
-chan.acid: runtime.h chan.c
- $(CC) -a chan.c >chan.acid
-
diff --git a/src/lib/runtime/amd64/asm.s b/src/lib/runtime/amd64/asm.s
deleted file mode 100644
index 6fc01bbc9..000000000
--- a/src/lib/runtime/amd64/asm.s
+++ /dev/null
@@ -1,207 +0,0 @@
-// 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.
-
-
-TEXT _rt0_amd64(SB),7,$-8
-
- // copy arguments forward on an even stack
-
- MOVQ 0(SP), AX // argc
- LEAQ 8(SP), BX // argv
- SUBQ $(4*8+7), SP // 2args 2auto
- ANDQ $~7, SP
- MOVQ AX, 16(SP)
- MOVQ BX, 24(SP)
-
- // set the per-goroutine and per-mach registers
-
- LEAQ m0(SB), R14 // dedicated m. register
- LEAQ g0(SB), R15 // dedicated g. register
- MOVQ R15, 0(R14) // m has pointer to its g0
-
- // create istack out of the given (operating system) stack
-
- LEAQ (-8192+104)(SP), AX
- MOVQ AX, 0(R15) // 0(R15) is stack limit (w 104b guard)
- MOVQ SP, 8(R15) // 8(R15) is base
-
- CLD // convention is D is always left cleared
- CALL check(SB)
-
- MOVL 16(SP), AX // copy argc
- MOVL AX, 0(SP)
- MOVQ 24(SP), AX // copy argv
- MOVQ AX, 8(SP)
- CALL args(SB)
- CALL osinit(SB)
- CALL schedinit(SB)
-
- // create a new goroutine to start program
- PUSHQ $mainstart(SB) // entry
- PUSHQ $16 // arg size
- CALL sys·newproc(SB)
- POPQ AX
- POPQ AX
-
- // start this M
- CALL mstart(SB)
-
- CALL notok(SB) // never returns
- RET
-
-TEXT mainstart(SB),7,$0
- CALL main·init(SB)
- CALL initdone(SB)
- CALL main·main(SB)
- PUSHQ $0
- CALL exit(SB)
- POPQ AX
- CALL notok(SB)
- RET
-
-TEXT breakpoint(SB),7,$0
- BYTE $0xcc
- RET
-
-/*
- * go-routine
- */
-TEXT gogo(SB), 7, $0
- MOVQ 8(SP), AX // gobuf
- MOVQ 0(AX), SP // restore SP
- MOVQ 8(AX), AX
- MOVQ AX, 0(SP) // put PC on the stack
- MOVL $1, AX // return 1
- RET
-
-TEXT gosave(SB), 7, $0
- MOVQ 8(SP), AX // gobuf
- MOVQ SP, 0(AX) // save SP
- MOVQ 0(SP), BX
- MOVQ BX, 8(AX) // save PC
- MOVL $0, AX // return 0
- RET
-
-/*
- * support for morestack
- */
-
-// morestack trampolines
-TEXT sys·morestack00+0(SB),7,$0
- MOVQ $0, AX
- MOVQ AX, 8(R14)
- MOVQ $sys·morestack+0(SB), AX
- JMP AX
-
-TEXT sys·morestack01+0(SB),7,$0
- SHLQ $32, AX
- MOVQ AX, 8(R14)
- MOVQ $sys·morestack+0(SB), AX
- JMP AX
-
-TEXT sys·morestack10+0(SB),7,$0
- MOVLQZX AX, AX
- MOVQ AX, 8(R14)
- MOVQ $sys·morestack+0(SB), AX
- JMP AX
-
-TEXT sys·morestack11+0(SB),7,$0
- MOVQ AX, 8(R14)
- MOVQ $sys·morestack+0(SB), AX
- JMP AX
-
-TEXT sys·morestackx(SB),7,$0
- POPQ AX
- SHLQ $35, AX
- MOVQ AX, 8(R14)
- MOVQ $sys·morestack(SB), AX
- JMP AX
-
-// subcases of morestack01
-// with const of 8,16,...48
-TEXT sys·morestack8(SB),7,$0
- PUSHQ $1
- MOVQ $sys·morestackx(SB), AX
- JMP AX
-
-TEXT sys·morestack16(SB),7,$0
- PUSHQ $2
- MOVQ $sys·morestackx(SB), AX
- JMP AX
-
-TEXT sys·morestack24(SB),7,$0
- PUSHQ $3
- MOVQ $sys·morestackx(SB), AX
- JMP AX
-
-TEXT sys·morestack32(SB),7,$0
- PUSHQ $4
- MOVQ $sys·morestackx(SB), AX
- JMP AX
-
-TEXT sys·morestack40(SB),7,$0
- PUSHQ $5
- MOVQ $sys·morestackx(SB), AX
- JMP AX
-
-TEXT sys·morestack48(SB),7,$0
- PUSHQ $6
- MOVQ $sys·morestackx(SB), AX
- JMP AX
-
-// return point when leaving new stack. save AX, jmp to lessstack to switch back
-TEXT retfromnewstack(SB), 7, $0
- MOVQ AX, 16(R14) // save AX in m->cret
- MOVQ $lessstack(SB), AX
- JMP AX
-
-// gogo, returning 2nd arg instead of 1
-TEXT gogoret(SB), 7, $0
- MOVQ 16(SP), AX // return 2nd arg
- MOVQ 8(SP), BX // gobuf
- MOVQ 0(BX), SP // restore SP
- MOVQ 8(BX), BX
- MOVQ BX, 0(SP) // put PC on the stack
- RET
-
-TEXT setspgoto(SB), 7, $0
- MOVQ 8(SP), AX // SP
- MOVQ 16(SP), BX // fn to call
- MOVQ 24(SP), CX // fn to return
- MOVQ AX, SP
- PUSHQ CX
- JMP BX
- POPQ AX // not reached
- RET
-
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-// if(*val == old){
-// *val = new;
-// return 1;
-// } else
-// return 0;
-TEXT cas(SB), 7, $0
- MOVQ 8(SP), BX
- MOVL 16(SP), AX
- MOVL 20(SP), CX
- LOCK
- CMPXCHGL CX, 0(BX)
- JZ 3(PC)
- MOVL $0, AX
- RET
- MOVL $1, AX
- RET
-
-// void jmpdefer(fn, sp);
-// called from deferreturn.
-// 1. pop the caller
-// 2. sub 5 bytes from the callers return
-// 3. jmp to the argument
-TEXT jmpdefer(SB), 7, $0
- MOVQ 8(SP), AX // fn
- MOVQ 16(SP), BX // caller sp
- LEAQ -8(BX), SP // caller sp after CALL
- SUBQ $5, (SP) // return to CALL again
- JMP AX // but first run the deferred function
diff --git a/src/lib/runtime/amd64/closure.c b/src/lib/runtime/amd64/closure.c
deleted file mode 100644
index 5717d3c5e..000000000
--- a/src/lib/runtime/amd64/closure.c
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-#pragma textflag 7
-// func closure(siz int32,
-// fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
-// arg0, arg1, arg2 *ptr) (func(xxx) yyy)
-void
-sys·closure(int32 siz, byte *fn, byte *arg0)
-{
- byte *p, *q, **ret;
- int32 i, n;
- int64 pcrel;
-
- if(siz < 0 || siz%8 != 0)
- throw("bad closure size");
-
- ret = (byte**)((byte*)&arg0 + siz);
-
- if(siz > 100) {
- // TODO(rsc): implement stack growth preamble?
- throw("closure too big");
- }
-
- // compute size of new fn.
- // must match code laid out below.
- n = 7+10+3; // SUBQ MOVQ MOVQ
- if(siz <= 4*8)
- n += 2*siz/8; // MOVSQ MOVSQ...
- else
- n += 7+3; // MOVQ REP MOVSQ
- n += 12; // CALL worst case; sometimes only 5
- n += 7+1; // ADDQ RET
-
- // store args aligned after code, so gc can find them.
- n += siz;
- if(n%8)
- n += 8 - n%8;
-
- p = mal(n);
- *ret = p;
- q = p + n - siz;
- mcpy(q, (byte*)&arg0, siz);
-
- // SUBQ $siz, SP
- *p++ = 0x48;
- *p++ = 0x81;
- *p++ = 0xec;
- *(uint32*)p = siz;
- p += 4;
-
- // MOVQ $q, SI
- *p++ = 0x48;
- *p++ = 0xbe;
- *(byte**)p = q;
- p += 8;
-
- // MOVQ SP, DI
- *p++ = 0x48;
- *p++ = 0x89;
- *p++ = 0xe7;
-
- if(siz <= 4*8) {
- for(i=0; i<siz; i+=8) {
- // MOVSQ
- *p++ = 0x48;
- *p++ = 0xa5;
- }
- } else {
- // MOVQ $(siz/8), CX [32-bit immediate siz/8]
- *p++ = 0x48;
- *p++ = 0xc7;
- *p++ = 0xc1;
- *(uint32*)p = siz/8;
- p += 4;
-
- // REP; MOVSQ
- *p++ = 0xf3;
- *p++ = 0x48;
- *p++ = 0xa5;
- }
-
-
- // call fn
- pcrel = fn - (p+5);
- if((int32)pcrel == pcrel) {
- // can use direct call with pc-relative offset
- // CALL fn
- *p++ = 0xe8;
- *(int32*)p = pcrel;
- p += 4;
- } else {
- // MOVQ $fn, CX [64-bit immediate fn]
- *p++ = 0x48;
- *p++ = 0xb9;
- *(byte**)p = fn;
- p += 8;
-
- // CALL *CX
- *p++ = 0xff;
- *p++ = 0xd1;
- }
-
- // ADDQ $siz, SP
- *p++ = 0x48;
- *p++ = 0x81;
- *p++ = 0xc4;
- *(uint32*)p = siz;
- p += 4;
-
- // RET
- *p++ = 0xc3;
-
- if(p > q)
- throw("bad math in sys.closure");
-}
-
-
diff --git a/src/lib/runtime/amd64/traceback.c b/src/lib/runtime/amd64/traceback.c
deleted file mode 100644
index 16d7bed72..000000000
--- a/src/lib/runtime/amd64/traceback.c
+++ /dev/null
@@ -1,146 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-void
-traceback(byte *pc0, byte *sp, G *g)
-{
- Stktop *stk;
- uint64 pc;
- int32 i, n;
- Func *f;
- byte *p;
-
- pc = (uint64)pc0;
-
- // If the PC is zero, it's likely a nil function call.
- // Start in the caller's frame.
- if(pc == 0) {
- pc = *(uint64*)sp;
- sp += 8;
- }
-
- stk = (Stktop*)g->stackbase;
- for(n=0; n<100; n++) {
- while(pc == (uint64)retfromnewstack) {
- // pop to earlier stack block
- sp = stk->oldsp;
- stk = (Stktop*)stk->oldbase;
- pc = *(uint64*)(sp+8);
- sp += 16; // two irrelevant calls on stack: morestack plus its call
- }
- f = findfunc(pc);
- if(f == nil) {
- // dangerous, but poke around to see if it is a closure
- p = (byte*)pc;
- // ADDQ $xxx, SP; RET
- if(p[0] == 0x48 && p[1] == 0x81 && p[2] == 0xc4 && p[7] == 0xc3) {
- sp += *(uint32*)(p+3) + 8;
- pc = *(uint64*)(sp - 8);
- if(pc <= 0x1000)
- return;
- continue;
- }
- printf("%p unknown pc\n", pc);
- return;
- }
- if(f->frame < 8) // assembly funcs say 0 but lie
- sp += 8;
- else
- sp += f->frame;
-
- // print this frame
- // main+0xf /home/rsc/go/src/runtime/x.go:23
- // main(0x1, 0x2, 0x3)
- printf("%S", f->name);
- if(pc > f->entry)
- printf("+%X", pc - f->entry);
- printf(" %S:%d\n", f->src, funcline(f, pc-1)); // -1 to get to CALL instr.
- printf("\t%S(", f->name);
- for(i = 0; i < f->args; i++) {
- if(i != 0)
- prints(", ");
- sys·printhex(((uint32*)sp)[i]);
- if(i >= 4) {
- prints(", ...");
- break;
- }
- }
- prints(")\n");
-
- pc = *(uint64*)(sp-8);
- if(pc <= 0x1000)
- return;
- }
- prints("...\n");
-}
-
-// func caller(n int) (pc uint64, file string, line int, ok bool)
-void
-runtime·Caller(int32 n, uint64 retpc, String retfile, int32 retline, bool retbool)
-{
- uint64 pc;
- byte *sp;
- byte *p;
- Stktop *stk;
- Func *f;
-
- // our caller's pc, sp.
- sp = (byte*)&n;
- pc = *(uint64*)(sp-8);
- if((f = findfunc(pc)) == nil) {
- error:
- retpc = 0;
- retline = 0;
- retfile = emptystring;
- retbool = false;
- FLUSH(&retpc);
- FLUSH(&retfile);
- FLUSH(&retline);
- FLUSH(&retbool);
- return;
- }
-
- // now unwind n levels
- stk = (Stktop*)g->stackbase;
- while(n-- > 0) {
- while(pc == (uint64)retfromnewstack) {
- sp = stk->oldsp;
- stk = (Stktop*)stk->oldbase;
- pc = *(uint64*)(sp+8);
- sp += 16;
- }
-
- if(f->frame < 8) // assembly functions lie
- sp += 8;
- else
- sp += f->frame;
-
- loop:
- pc = *(uint64*)(sp-8);
- if(pc <= 0x1000 || (f = findfunc(pc)) == nil) {
- // dangerous, but let's try this.
- // see if it is a closure.
- p = (byte*)pc;
- // ADDQ $xxx, SP; RET
- if(p[0] == 0x48 && p[1] == 0x81 && p[2] == 0xc4 && p[7] == 0xc3) {
- sp += *(uint32*)(p+3) + 8;
- goto loop;
- }
- goto error;
- }
- }
-
- retpc = pc;
- retfile = f->src;
- retline = funcline(f, pc-1);
- retbool = true;
- FLUSH(&retpc);
- FLUSH(&retfile);
- FLUSH(&retline);
- FLUSH(&retbool);
-}
-
-
diff --git a/src/lib/runtime/arm/asm.s b/src/lib/runtime/arm/asm.s
deleted file mode 100644
index 232ab4ddf..000000000
--- a/src/lib/runtime/arm/asm.s
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.
-
-TEXT _rt0_arm(SB),7,$0
- // copy arguments forward on an even stack
- // MOVW $0(SP), R0
- // MOVL 0(SP), R1 // argc
-// LEAL 4(SP), R1 // argv
-// SUBL $128, SP // plenty of scratch
-// ANDL $~7, SP
-// MOVL AX, 120(SP) // save argc, argv away
-// MOVL BX, 124(SP)
-
-
-// // write "go386\n"
-// PUSHL $6
-// PUSHL $hello(SB)
-// PUSHL $1
-// CALL sys·write(SB)
-// POPL AX
-// POPL AX
-// POPL AX
-
-
-// CALL ldt0setup(SB)
-
- // set up %fs to refer to that ldt entry
-// MOVL $(7*8+7), AX
-// MOVW AX, FS
-
-// // store through it, to make sure it works
-// MOVL $0x123, 0(FS)
-// MOVL tls0(SB), AX
-// CMPL AX, $0x123
-// JEQ ok
-// MOVL AX, 0
-// ok:
-
-// // set up m and g "registers"
-// // g is 0(FS), m is 4(FS)
-// LEAL g0(SB), CX
-// MOVL CX, 0(FS)
-// LEAL m0(SB), AX
-// MOVL AX, 4(FS)
-
-// // save m->g0 = g0
-// MOVL CX, 0(AX)
-
-// // create istack out of the OS stack
-// LEAL (-8192+104)(SP), AX // TODO: 104?
-// MOVL AX, 0(CX) // 8(g) is stack limit (w 104b guard)
-// MOVL SP, 4(CX) // 12(g) is base
-// CALL emptyfunc(SB) // fault if stack check is wrong
-
-// // convention is D is always cleared
-// CLD
-
-// CALL check(SB)
-
-// // saved argc, argv
-// MOVL 120(SP), AX
-// MOVL AX, 0(SP)
-// MOVL 124(SP), AX
-// MOVL AX, 4(SP)
-// CALL args(SB)
-// CALL osinit(SB)
-// CALL schedinit(SB)
-
-// // create a new goroutine to start program
-// PUSHL $mainstart(SB) // entry
-// PUSHL $8 // arg size
-// CALL sys·newproc(SB)
-// POPL AX
-// POPL AX
-
-// // start this M
-// CALL mstart(SB)
-
- BL main�main(SB)
- MOVW $99, R0
- SWI $0x00900001
-
diff --git a/src/lib/runtime/arm/closure.c b/src/lib/runtime/arm/closure.c
deleted file mode 100644
index 024018d5a..000000000
--- a/src/lib/runtime/arm/closure.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// 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.
-
diff --git a/src/lib/runtime/arm/traceback.s b/src/lib/runtime/arm/traceback.s
deleted file mode 100644
index e69de29bb..000000000
--- a/src/lib/runtime/arm/traceback.s
+++ /dev/null
diff --git a/src/lib/runtime/array.c b/src/lib/runtime/array.c
deleted file mode 100644
index bbd57b03e..000000000
--- a/src/lib/runtime/array.c
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-static int32 debug = 0;
-
-// newarray(nel int, cap int, width int) (ary []any);
-void
-sys·newarray(uint32 nel, uint32 cap, uint32 width, Array ret)
-{
- uint64 size;
-
- if(cap < nel)
- cap = nel;
- size = cap*width;
-
- ret.nel = nel;
- ret.cap = cap;
- ret.array = mal(size);
-
- FLUSH(&ret);
-
- if(debug) {
- prints("newarray: nel=");
- sys·printint(nel);
- prints("; cap=");
- sys·printint(cap);
- prints("; width=");
- sys·printint(width);
- prints("; ret=");
- sys·printarray(ret);
- prints("\n");
- }
-}
-
-static void
-throwslice(uint32 lb, uint32 hb, uint32 n)
-{
- prints("slice[");
- sys·printint(lb);
- prints(":");
- sys·printint(hb);
- prints("] of [");
- sys·printint(n);
- prints("] array\n");
- throw("array slice");
-}
-
-// arraysliced(old []any, lb int, hb int, width int) (ary []any);
-void
-sys·arraysliced(Array old, uint32 lb, uint32 hb, uint32 width, Array ret)
-{
-
- if(hb > old.cap || lb > hb) {
- if(debug) {
- prints("sys·arraysliced: old=");
- sys·printarray(old);
- prints("; lb=");
- sys·printint(lb);
- prints("; hb=");
- sys·printint(hb);
- prints("; width=");
- sys·printint(width);
- prints("\n");
-
- prints("oldarray: nel=");
- sys·printint(old.nel);
- prints("; cap=");
- sys·printint(old.cap);
- prints("\n");
- }
- throwslice(lb, hb, old.cap);
- }
-
- // new array is inside old array
- ret.nel = hb-lb;
- ret.cap = old.cap - lb;
- ret.array = old.array + lb*width;
-
- FLUSH(&ret);
-
- if(debug) {
- prints("sys·arraysliced: old=");
- sys·printarray(old);
- prints("; lb=");
- sys·printint(lb);
- prints("; hb=");
- sys·printint(hb);
- prints("; width=");
- sys·printint(width);
- prints("; ret=");
- sys·printarray(ret);
- prints("\n");
- }
-}
-
-// arrayslices(old *any, nel int, lb int, hb int, width int) (ary []any);
-void
-sys·arrayslices(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Array ret)
-{
-
- if(hb > nel || lb > hb) {
- if(debug) {
- prints("sys·arrayslices: old=");
- sys·printpointer(old);
- prints("; nel=");
- sys·printint(nel);
- prints("; lb=");
- sys·printint(lb);
- prints("; hb=");
- sys·printint(hb);
- prints("; width=");
- sys·printint(width);
- prints("\n");
- }
- throwslice(lb, hb, nel);
- }
-
- // new array is inside old array
- ret.nel = hb-lb;
- ret.cap = nel-lb;
- ret.array = old + lb*width;
-
- FLUSH(&ret);
-
- if(debug) {
- prints("sys·arrayslices: old=");
- sys·printpointer(old);
- prints("; nel=");
- sys·printint(nel);
- prints("; lb=");
- sys·printint(lb);
- prints("; hb=");
- sys·printint(hb);
- prints("; width=");
- sys·printint(width);
- prints("; ret=");
- sys·printarray(ret);
- prints("\n");
- }
-}
-
-// arrays2d(old *any, nel int) (ary []any)
-void
-sys·arrays2d(byte* old, uint32 nel, Array ret)
-{
-
- // new dope to old array
- ret.nel = nel;
- ret.cap = nel;
- ret.array = old;
-
- FLUSH(&ret);
-
- if(debug) {
- prints("sys·arrays2d: old=");
- sys·printpointer(old);
- prints("; ret=");
- sys·printarray(ret);
- prints("\n");
- }
-}
-
-void
-sys·printarray(Array a)
-{
- prints("[");
- sys·printint(a.nel);
- prints("/");
- sys·printint(a.cap);
- prints("]");
- sys·printpointer(a.array);
-}
diff --git a/src/lib/runtime/cgo2c.c b/src/lib/runtime/cgo2c.c
deleted file mode 100644
index 3905f7e6d..000000000
--- a/src/lib/runtime/cgo2c.c
+++ /dev/null
@@ -1,602 +0,0 @@
-// 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.
-
-/* Translate a .cgo file into a .c file. A .cgo file is a combination
- of a limited form of Go with C. */
-
-/*
- package PACKAGENAME
- {# line}
- func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{
- C code with proper brace nesting
- \}
-*/
-
-/* We generate C code which implements the function such that it can
- be called from Go and executes the C code. */
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-/* Whether we're emitting for gcc */
-static int gcc;
-
-/* File and line number */
-static const char *file;
-static unsigned int lineno;
-
-/* List of names and types. */
-struct params {
- struct params *next;
- char *name;
- char *type;
-};
-
-/* Unexpected EOF. */
-static void
-bad_eof(void)
-{
- fprintf(stderr, "%s:%u: unexpected EOF\n", file, lineno);
- exit(1);
-}
-
-/* Out of memory. */
-static void
-bad_mem(void)
-{
- fprintf(stderr, "%s:%u: out of memory\n", file, lineno);
- exit(1);
-}
-
-/* Allocate memory without fail. */
-static void *
-xmalloc(unsigned int size)
-{
- void *ret = malloc(size);
- if (ret == NULL)
- bad_mem();
- return ret;
-}
-
-/* Reallocate memory without fail. */
-static void*
-xrealloc(void *buf, unsigned int size)
-{
- void *ret = realloc(buf, size);
- if (ret == NULL)
- bad_mem();
- return ret;
-}
-
-/* Free a list of parameters. */
-static void
-free_params(struct params *p)
-{
- while (p != NULL) {
- struct params *next;
-
- next = p->next;
- free(p->name);
- free(p->type);
- free(p);
- p = next;
- }
-}
-
-/* Read a character, tracking lineno. */
-static int
-getchar_update_lineno(void)
-{
- int c;
-
- c = getchar();
- if (c == '\n')
- ++lineno;
- return c;
-}
-
-/* Read a character, giving an error on EOF, tracking lineno. */
-static int
-getchar_no_eof(void)
-{
- int c;
-
- c = getchar_update_lineno();
- if (c == EOF)
- bad_eof();
- return c;
-}
-
-/* Read a character, skipping comments. */
-static int
-getchar_skipping_comments(void)
-{
- int c;
-
- while (1) {
- c = getchar_update_lineno();
- if (c != '/')
- return c;
-
- c = getchar();
- if (c == '/') {
- do {
- c = getchar_update_lineno();
- } while (c != EOF && c != '\n');
- return c;
- } else if (c == '*') {
- while (1) {
- c = getchar_update_lineno();
- if (c == EOF)
- return EOF;
- if (c == '*') {
- do {
- c = getchar_update_lineno();
- } while (c == '*');
- if (c == '/')
- break;
- }
- }
- } else {
- ungetc(c, stdin);
- return '/';
- }
- }
-}
-
-/* Read and return a token. Tokens are delimited by whitespace or by
- [(),{}]. The latter are all returned as single characters. */
-static char *
-read_token(void)
-{
- int c;
- char *buf;
- unsigned int alc, off;
- const char* delims = "(),{}";
-
- while (1) {
- c = getchar_skipping_comments();
- if (c == EOF)
- return NULL;
- if (!isspace(c))
- break;
- }
- alc = 16;
- buf = xmalloc(alc + 1);
- off = 0;
- if (strchr(delims, c) != NULL) {
- buf[off] = c;
- ++off;
- } else {
- while (1) {
- if (off >= alc) {
- alc *= 2;
- buf = xrealloc(buf, alc + 1);
- }
- buf[off] = c;
- ++off;
- c = getchar_skipping_comments();
- if (c == EOF)
- break;
- if (isspace(c) || strchr(delims, c) != NULL) {
- ungetc(c, stdin);
- break;
- }
- }
- }
- buf[off] = '\0';
- return buf;
-}
-
-/* Read a token, giving an error on EOF. */
-static char *
-read_token_no_eof(void)
-{
- char *token = read_token();
- if (token == NULL)
- bad_eof();
- return token;
-}
-
-/* Read the package clause, and return the package name. */
-static char *
-read_package(void)
-{
- char *token;
-
- token = read_token_no_eof();
- if (strcmp(token, "package") != 0) {
- fprintf(stderr,
- "%s:%u: expected \"package\", got \"%s\"\n",
- file, lineno, token);
- exit(1);
- }
- return read_token_no_eof();
-}
-
-/* Read and copy preprocessor lines. */
-static void
-read_preprocessor_lines(void)
-{
- while (1) {
- int c;
-
- do {
- c = getchar_skipping_comments();
- } while (isspace(c));
- if (c != '#') {
- ungetc(c, stdin);
- return;
- }
- putchar(c);
- do {
- c = getchar_update_lineno();
- putchar(c);
- } while (c != '\n');
- }
-}
-
-/* Read a type in Go syntax and return a type in C syntax. We only
- permit basic types and pointers. */
-static char *
-read_type(void)
-{
- char *p, *op, *q;
- int pointer_count;
- unsigned int len;
-
- p = read_token_no_eof();
- if (*p != '*')
- return p;
- op = p;
- pointer_count = 0;
- while (*p == '*') {
- ++pointer_count;
- ++p;
- }
- len = strlen(p);
- q = xmalloc(len + pointer_count + 1);
- memcpy(q, p, len);
- while (pointer_count > 0) {
- q[len] = '*';
- ++len;
- --pointer_count;
- }
- q[len] = '\0';
- free(op);
- return q;
-}
-
-/* Read a list of parameters. Each parameter is a name and a type.
- The list ends with a ')'. We have already read the '('. */
-static struct params *
-read_params(void)
-{
- char *token;
- struct params *ret, **pp;
-
- ret = NULL;
- pp = &ret;
- token = read_token_no_eof();
- if (strcmp(token, ")") != 0) {
- while (1) {
- *pp = xmalloc(sizeof(struct params));
- (*pp)->name = token;
- (*pp)->type = read_type();
- pp = &(*pp)->next;
- *pp = NULL;
-
- token = read_token_no_eof();
- if (strcmp(token, ",") != 0)
- break;
- token = read_token_no_eof();
- }
- }
- if (strcmp(token, ")") != 0) {
- fprintf(stderr, "%s:%u: expected '('\n",
- file, lineno);
- exit(1);
- }
- return ret;
-}
-
-/* Read a function header. This reads up to and including the initial
- '{' character. Returns 1 if it read a header, 0 at EOF. */
-static int
-read_func_header(char **name, struct params **params, struct params **rets)
-{
- char *token;
-
- token = read_token();
- if (token == NULL)
- return 0;
- if (strcmp(token, "func") != 0) {
- fprintf(stderr, "%s:%u: expected \"func\"\n",
- file, lineno);
- exit(1);
- }
- *name = read_token_no_eof();
-
- token = read_token();
- if (token == NULL || strcmp(token, "(") != 0) {
- fprintf(stderr, "%s:%u: expected \"(\"\n",
- file, lineno);
- exit(1);
- }
- *params = read_params();
-
- token = read_token();
- if (token == NULL || strcmp(token, "(") != 0)
- *rets = NULL;
- else {
- *rets = read_params();
- token = read_token();
- }
- if (token == NULL || strcmp(token, "{") != 0) {
- fprintf(stderr, "%s:%u: expected \"{\"\n",
- file, lineno);
- exit(1);
- }
- return 1;
-}
-
-/* Write out parameters. */
-static void
-write_params(struct params *params, int *first)
-{
- struct params *p;
-
- for (p = params; p != NULL; p = p->next) {
- if (*first)
- *first = 0;
- else
- printf(", ");
- printf("%s %s", p->type, p->name);
- }
-}
-
-/* Write a 6g function header. */
-static void
-write_6g_func_header(char *package, char *name, struct params *params,
- struct params *rets)
-{
- int first;
-
- printf("void\n%s·%s(", package, name);
- first = 1;
- write_params(params, &first);
- write_params(rets, &first);
- printf(")\n{\n");
-}
-
-/* Write a 6g function trailer. */
-static void
-write_6g_func_trailer(struct params *rets)
-{
- struct params *p;
-
- for (p = rets; p != NULL; p = p->next)
- printf("\tFLUSH(&%s);\n", p->name);
- printf("}\n");
-}
-
-/* Define the gcc function return type if necessary. */
-static void
-define_gcc_return_type(char *package, char *name, struct params *rets)
-{
- struct params *p;
-
- if (rets == NULL || rets->next == NULL)
- return;
- printf("struct %s_%s_ret {\n", package, name);
- for (p = rets; p != NULL; p = p->next)
- printf(" %s %s;\n", p->type, p->name);
- printf("};\n");
-}
-
-/* Write out the gcc function return type. */
-static void
-write_gcc_return_type(char *package, char *name, struct params *rets)
-{
- if (rets == NULL)
- printf("void");
- else if (rets->next == NULL)
- printf("%s", rets->type);
- else
- printf("struct %s_%s_ret", package, name);
-}
-
-/* Write out a gcc function header. */
-static void
-write_gcc_func_header(char *package, char *name, struct params *params,
- struct params *rets)
-{
- int first;
- struct params *p;
-
- define_gcc_return_type(package, name, rets);
- write_gcc_return_type(package, name, rets);
- printf(" %s_%s(", package, name);
- first = 1;
- write_params(params, &first);
- printf(") asm (\"%s.%s\");\n", package, name);
- write_gcc_return_type(package, name, rets);
- printf(" %s_%s(", package, name);
- first = 1;
- write_params(params, &first);
- printf(")\n{\n");
- for (p = rets; p != NULL; p = p->next)
- printf(" %s %s;\n", p->type, p->name);
-}
-
-/* Write out a gcc function trailer. */
-static void
-write_gcc_func_trailer(char *package, char *name, struct params *rets)
-{
- if (rets == NULL)
- ;
- else if (rets->next == NULL)
- printf("return %s;\n", rets->name);
- else {
- struct params *p;
-
- printf(" {\n struct %s_%s_ret __ret;\n", package, name);
- for (p = rets; p != NULL; p = p->next)
- printf(" __ret.%s = %s;\n", p->name, p->name);
- printf(" return __ret;\n }\n");
- }
- printf("}\n");
-}
-
-/* Write out a function header. */
-static void
-write_func_header(char *package, char *name,
- struct params *params, struct params *rets)
-{
- if (gcc)
- write_gcc_func_header(package, name, params, rets);
- else
- write_6g_func_header(package, name, params, rets);
- printf("#line %d \"%s\"\n", lineno, file);
-}
-
-/* Write out a function trailer. */
-static void
-write_func_trailer(char *package, char *name,
- struct params *rets)
-{
- if (gcc)
- write_gcc_func_trailer(package, name, rets);
- else
- write_6g_func_trailer(rets);
-}
-
-/* Read and write the body of the function, ending in an unnested }
- (which is read but not written). */
-static void
-copy_body(void)
-{
- int nesting = 0;
- while (1) {
- int c;
-
- c = getchar_no_eof();
- if (c == '}' && nesting == 0)
- return;
- putchar(c);
- switch (c) {
- default:
- break;
- case '{':
- ++nesting;
- break;
- case '}':
- --nesting;
- break;
- case '/':
- c = getchar_update_lineno();
- putchar(c);
- if (c == '/') {
- do {
- c = getchar_no_eof();
- putchar(c);
- } while (c != '\n');
- } else if (c == '*') {
- while (1) {
- c = getchar_no_eof();
- putchar(c);
- if (c == '*') {
- do {
- c = getchar_no_eof();
- putchar(c);
- } while (c == '*');
- if (c == '/')
- break;
- }
- }
- }
- break;
- case '"':
- case '\'':
- {
- int delim = c;
- do {
- c = getchar_no_eof();
- putchar(c);
- if (c == '\\') {
- c = getchar_no_eof();
- putchar(c);
- c = '\0';
- }
- } while (c != delim);
- }
- break;
- }
- }
-}
-
-/* Process the entire file. */
-static void
-process_file(void)
-{
- char *package, *name;
- struct params *params, *rets;
-
- package = read_package();
- read_preprocessor_lines();
- while (read_func_header(&name, &params, &rets)) {
- write_func_header(package, name, params, rets);
- copy_body();
- write_func_trailer(package, name, rets);
- free(name);
- free_params(params);
- free_params(rets);
- }
- free(package);
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "Usage: cgo2c [--6g | --gc] [file]\n");
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- while(argc > 1 && argv[1][0] == '-') {
- if(strcmp(argv[1], "-") == 0)
- break;
- if(strcmp(argv[1], "--6g") == 0)
- gcc = 0;
- else if(strcmp(argv[1], "--gcc") == 0)
- gcc = 1;
- else
- usage();
- argc--;
- argv++;
- }
-
- if(argc <= 1 || strcmp(argv[1], "-") == 0) {
- file = "<stdin>";
- process_file();
- return 0;
- }
-
- if(argc > 2)
- usage();
-
- file = argv[1];
- if(freopen(file, "r", stdin) == 0) {
- fprintf(stderr, "open %s: %s\n", file, strerror(errno));
- exit(1);
- }
- process_file();
- return 0;
-}
diff --git a/src/lib/runtime/chan.c b/src/lib/runtime/chan.c
deleted file mode 100644
index be65bcbc1..000000000
--- a/src/lib/runtime/chan.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-static int32 debug = 0;
-static Lock chanlock;
-
-enum
-{
- Wclosed = 0x0001, // writer has closed
- Rclosed = 0x0002, // reader has seen close
- Eincr = 0x0004, // increment errors
- Emax = 0x0800, // error limit before throw
-};
-
-typedef struct Hchan Hchan;
-typedef struct Link Link;
-typedef struct WaitQ WaitQ;
-typedef struct SudoG SudoG;
-typedef struct Select Select;
-typedef struct Scase Scase;
-
-struct SudoG
-{
- G* g; // g and selgen constitute
- int32 selgen; // a weak pointer to g
- int16 offset; // offset of case number
- int8 isfree; // offset of case number
- SudoG* link;
- byte elem[8]; // synch data element (+ more)
-};
-
-struct WaitQ
-{
- SudoG* first;
- SudoG* last;
-};
-
-struct Hchan
-{
- uint16 elemsize;
- uint16 closed; // Wclosed Rclosed errorcount
- uint32 dataqsiz; // size of the circular q
- uint32 qcount; // total data in the q
- Alg* elemalg; // interface for element type
- Link* senddataq; // pointer for sender
- Link* recvdataq; // pointer for receiver
- WaitQ recvq; // list of recv waiters
- WaitQ sendq; // list of send waiters
- SudoG* free; // freelist
-};
-
-struct Link
-{
- Link* link; // asynch queue circular linked list
- byte elem[8]; // asynch queue data element (+ more)
-};
-
-struct Scase
-{
- Hchan* chan; // chan
- byte* pc; // return pc
- uint16 send; // 0-recv 1-send 2-default
- uint16 so; // vararg of selected bool
- union {
- byte elem[8]; // element (send)
- byte* elemp; // pointer to element (recv)
- } u;
-};
-
-struct Select
-{
- uint16 tcase; // total count of scase[]
- uint16 ncase; // currently filled scase[]
- Select* link; // for freelist
- Scase* scase[1]; // one per case
-};
-
-static Select* selfree[20];
-
-static SudoG* dequeue(WaitQ*, Hchan*);
-static void enqueue(WaitQ*, SudoG*);
-static SudoG* allocsg(Hchan*);
-static void freesg(Hchan*, SudoG*);
-static uint32 gcd(uint32, uint32);
-static uint32 fastrand1(void);
-static uint32 fastrand2(void);
-
-// newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
-void
-sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
- Hchan* ret)
-{
- Hchan *c;
- int32 i;
-
- if(elemalg >= nelem(algarray)) {
- printf("chan(alg=%d)\n", elemalg);
- throw("sys·newchan: unsupported elem type");
- }
-
- c = mal(sizeof(*c));
-
- c->elemsize = elemsize;
- c->elemalg = &algarray[elemalg];
-
- if(hint > 0) {
- Link *d, *b, *e;
-
- // make a circular q
- b = nil;
- e = nil;
- for(i=0; i<hint; i++) {
- d = mal(sizeof(*d) + c->elemsize - sizeof(d->elem));
- if(e == nil)
- e = d;
- d->link = b;
- b = d;
- }
- e->link = b;
- c->recvdataq = b;
- c->senddataq = b;
- c->qcount = 0;
- c->dataqsiz = hint;
- }
-
- ret = c;
- FLUSH(&ret);
-
- if(debug) {
- prints("newchan: chan=");
- sys·printpointer(c);
- prints("; elemsize=");
- sys·printint(elemsize);
- prints("; elemalg=");
- sys·printint(elemalg);
- prints("; dataqsiz=");
- sys·printint(c->dataqsiz);
- prints("\n");
- }
-}
-
-static void
-incerr(Hchan* c)
-{
- c->closed += Eincr;
- if(c->closed & Emax) {
- unlock(&chanlock);
- throw("too many operations on a closed channel");
- }
-}
-
-/*
- * generic single channel send/recv
- * if the bool pointer is nil,
- * then the full exchange will
- * occur. if pres is not nil,
- * then the protocol will not
- * sleep but return if it could
- * not complete
- */
-void
-sendchan(Hchan *c, byte *ep, bool *pres)
-{
- SudoG *sg;
- G* gp;
-
- if(debug) {
- prints("chansend: chan=");
- sys·printpointer(c);
- prints("; elem=");
- c->elemalg->print(c->elemsize, ep);
- prints("\n");
- }
-
- lock(&chanlock);
-loop:
- if(c->closed & Wclosed)
- goto closed;
-
- if(c->dataqsiz > 0)
- goto asynch;
-
- sg = dequeue(&c->recvq, c);
- if(sg != nil) {
- if(ep != nil)
- c->elemalg->copy(c->elemsize, sg->elem, ep);
-
- gp = sg->g;
- gp->param = sg;
- unlock(&chanlock);
- ready(gp);
-
- if(pres != nil)
- *pres = true;
- return;
- }
-
- if(pres != nil) {
- unlock(&chanlock);
- *pres = false;
- return;
- }
-
- sg = allocsg(c);
- if(ep != nil)
- c->elemalg->copy(c->elemsize, sg->elem, ep);
- g->param = nil;
- g->status = Gwaiting;
- enqueue(&c->sendq, sg);
- unlock(&chanlock);
- gosched();
-
- lock(&chanlock);
- sg = g->param;
- if(sg == nil)
- goto loop;
- freesg(c, sg);
- unlock(&chanlock);
- if(pres != nil)
- *pres = true;
- return;
-
-asynch:
- if(c->closed & Wclosed)
- goto closed;
-
- if(c->qcount >= c->dataqsiz) {
- if(pres != nil) {
- unlock(&chanlock);
- *pres = false;
- return;
- }
- sg = allocsg(c);
- g->status = Gwaiting;
- enqueue(&c->sendq, sg);
- unlock(&chanlock);
- gosched();
-
- lock(&chanlock);
- goto asynch;
- }
- if(ep != nil)
- c->elemalg->copy(c->elemsize, c->senddataq->elem, ep);
- c->senddataq = c->senddataq->link;
- c->qcount++;
-
- sg = dequeue(&c->recvq, c);
- if(sg != nil) {
- gp = sg->g;
- freesg(c, sg);
- unlock(&chanlock);
- ready(gp);
- } else
- unlock(&chanlock);
- if(pres != nil)
- *pres = true;
- return;
-
-closed:
- incerr(c);
- if(pres != nil)
- *pres = true;
- unlock(&chanlock);
-}
-
-static void
-chanrecv(Hchan* c, byte *ep, bool* pres)
-{
- SudoG *sg;
- G *gp;
-
- if(debug) {
- prints("chanrecv: chan=");
- sys·printpointer(c);
- prints("\n");
- }
-
- lock(&chanlock);
-loop:
- if(c->dataqsiz > 0)
- goto asynch;
-
- if(c->closed & Wclosed)
- goto closed;
-
- sg = dequeue(&c->sendq, c);
- if(sg != nil) {
- c->elemalg->copy(c->elemsize, ep, sg->elem);
-
- gp = sg->g;
- gp->param = sg;
- unlock(&chanlock);
- ready(gp);
-
- if(pres != nil)
- *pres = true;
- return;
- }
-
- if(pres != nil) {
- unlock(&chanlock);
- *pres = false;
- return;
- }
-
- sg = allocsg(c);
- g->param = nil;
- g->status = Gwaiting;
- enqueue(&c->recvq, sg);
- unlock(&chanlock);
- gosched();
-
- lock(&chanlock);
- sg = g->param;
- if(sg == nil)
- goto loop;
-
- c->elemalg->copy(c->elemsize, ep, sg->elem);
- freesg(c, sg);
- unlock(&chanlock);
- if(pres != nil)
- *pres = true;
- return;
-
-asynch:
- if(c->qcount <= 0) {
- if(c->closed & Wclosed)
- goto closed;
-
- if(pres != nil) {
- unlock(&chanlock);
- *pres = false;
- return;
- }
- sg = allocsg(c);
- g->status = Gwaiting;
- enqueue(&c->recvq, sg);
- unlock(&chanlock);
- gosched();
-
- lock(&chanlock);
- goto asynch;
- }
- c->elemalg->copy(c->elemsize, ep, c->recvdataq->elem);
- c->recvdataq = c->recvdataq->link;
- c->qcount--;
- sg = dequeue(&c->sendq, c);
- if(sg != nil) {
- gp = sg->g;
- freesg(c, sg);
- unlock(&chanlock);
- ready(gp);
- if(pres != nil)
- *pres = true;
- return;
- }
-
- unlock(&chanlock);
- if(pres != nil)
- *pres = true;
- return;
-
-closed:
- c->elemalg->copy(c->elemsize, ep, nil);
- c->closed |= Rclosed;
- incerr(c);
- if(pres != nil)
- *pres = true;
- unlock(&chanlock);
-}
-
-// chansend1(hchan *chan any, elem any);
-void
-sys·chansend1(Hchan* c, ...)
-{
- int32 o;
- byte *ae;
-
- o = rnd(sizeof(c), c->elemsize);
- ae = (byte*)&c + o;
- sendchan(c, ae, nil);
-}
-
-// chansend2(hchan *chan any, elem any) (pres bool);
-void
-sys·chansend2(Hchan* c, ...)
-{
- int32 o;
- byte *ae, *ap;
-
- o = rnd(sizeof(c), c->elemsize);
- ae = (byte*)&c + o;
- o = rnd(o+c->elemsize, 1);
- ap = (byte*)&c + o;
-
- sendchan(c, ae, ap);
-}
-
-// chanrecv1(hchan *chan any) (elem any);
-void
-sys·chanrecv1(Hchan* c, ...)
-{
- int32 o;
- byte *ae;
-
- o = rnd(sizeof(c), c->elemsize);
- ae = (byte*)&c + o;
-
- chanrecv(c, ae, nil);
-}
-
-// chanrecv2(hchan *chan any) (elem any, pres bool);
-void
-sys·chanrecv2(Hchan* c, ...)
-{
- int32 o;
- byte *ae, *ap;
-
- o = rnd(sizeof(c), c->elemsize);
- ae = (byte*)&c + o;
- o = rnd(o+c->elemsize, 1);
- ap = (byte*)&c + o;
-
- chanrecv(c, ae, ap);
-}
-
-// chanrecv3(hchan *chan any, elem *any) (pres bool);
-void
-sys·chanrecv3(Hchan* c, byte* ep, byte pres)
-{
- chanrecv(c, ep, &pres);
-}
-
-// newselect(size uint32) (sel *byte);
-void
-sys·newselect(int32 size, Select *sel)
-{
- int32 n;
-
- n = 0;
- if(size > 1)
- n = size-1;
-
- lock(&chanlock);
- sel = nil;
- if(size >= 1 && size < nelem(selfree)) {
- sel = selfree[size];
- if(sel != nil)
- selfree[size] = sel->link;
- }
- unlock(&chanlock);
- if(sel == nil)
- sel = mal(sizeof(*sel) + n*sizeof(sel->scase[0]));
-
- sel->tcase = size;
- sel->ncase = 0;
- FLUSH(&sel);
- if(debug) {
- prints("newselect s=");
- sys·printpointer(sel);
- prints(" size=");
- sys·printint(size);
- prints("\n");
- }
-}
-
-// selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
-void
-sys·selectsend(Select *sel, Hchan *c, ...)
-{
- int32 i, eo;
- Scase *cas;
- byte *ae;
-
- // nil cases do not compete
- if(c == nil)
- return;
-
- i = sel->ncase;
- if(i >= sel->tcase)
- throw("selectsend: too many cases");
- sel->ncase = i+1;
- cas = sel->scase[i];
- if(cas == nil) {
- cas = mal(sizeof *cas + c->elemsize - sizeof(cas->u.elem));
- sel->scase[i] = cas;
- }
-
- cas->pc = sys·getcallerpc(&sel);
- cas->chan = c;
-
- eo = rnd(sizeof(sel), sizeof(c));
- eo = rnd(eo+sizeof(c), c->elemsize);
- cas->so = rnd(eo+c->elemsize, 1);
- cas->send = 1;
-
- ae = (byte*)&sel + eo;
- c->elemalg->copy(c->elemsize, cas->u.elem, ae);
-
- if(debug) {
- prints("selectsend s=");
- sys·printpointer(sel);
- prints(" pc=");
- sys·printpointer(cas->pc);
- prints(" chan=");
- sys·printpointer(cas->chan);
- prints(" po=");
- sys·printint(cas->so);
- prints(" send=");
- sys·printint(cas->send);
- prints("\n");
- }
-}
-
-// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
-void
-sys·selectrecv(Select *sel, Hchan *c, ...)
-{
- int32 i, eo;
- Scase *cas;
-
- // nil cases do not compete
- if(c == nil)
- return;
-
- i = sel->ncase;
- if(i >= sel->tcase)
- throw("selectrecv: too many cases");
- sel->ncase = i+1;
- cas = sel->scase[i];
- if(cas == nil) {
- cas = mal(sizeof *cas);
- sel->scase[i] = cas;
- }
- cas->pc = sys·getcallerpc(&sel);
- cas->chan = c;
-
- eo = rnd(sizeof(sel), sizeof(c));
- eo = rnd(eo+sizeof(c), sizeof(byte*));
- cas->so = rnd(eo+sizeof(byte*), 1);
- cas->send = 0;
- cas->u.elemp = *(byte**)((byte*)&sel + eo);
-
- if(debug) {
- prints("selectrecv s=");
- sys·printpointer(sel);
- prints(" pc=");
- sys·printpointer(cas->pc);
- prints(" chan=");
- sys·printpointer(cas->chan);
- prints(" so=");
- sys·printint(cas->so);
- prints(" send=");
- sys·printint(cas->send);
- prints("\n");
- }
-}
-
-
-// selectdefaul(sel *byte) (selected bool);
-void
-sys·selectdefault(Select *sel, ...)
-{
- int32 i;
- Scase *cas;
-
- i = sel->ncase;
- if(i >= sel->tcase)
- throw("selectdefault: too many cases");
- sel->ncase = i+1;
- cas = sel->scase[i];
- if(cas == nil) {
- cas = mal(sizeof *cas);
- sel->scase[i] = cas;
- }
- cas->pc = sys·getcallerpc(&sel);
- cas->chan = nil;
-
- cas->so = rnd(sizeof(sel), 1);
- cas->send = 2;
- cas->u.elemp = nil;
-
- if(debug) {
- prints("selectdefault s=");
- sys·printpointer(sel);
- prints(" pc=");
- sys·printpointer(cas->pc);
- prints(" so=");
- sys·printint(cas->so);
- prints(" send=");
- sys·printint(cas->send);
- prints("\n");
- }
-}
-
-// selectgo(sel *byte);
-void
-sys·selectgo(Select *sel)
-{
- uint32 p, o, i;
- Scase *cas, *dfl;
- Hchan *c;
- SudoG *sg;
- G *gp;
- byte *as;
-
- if(debug) {
- prints("selectgo: sel=");
- sys·printpointer(sel);
- prints("\n");
- }
-
- if(sel->ncase < 2) {
- if(sel->ncase < 1)
- throw("selectgo: no cases");
- // make special case of one.
- }
-
- // select a (relative) prime
- for(i=0;; i++) {
- p = fastrand1();
- if(gcd(p, sel->ncase) == 1)
- break;
- if(i > 1000) {
- throw("selectgo: failed to select prime");
- }
- }
-
- // select an initial offset
- o = fastrand2();
-
- p %= sel->ncase;
- o %= sel->ncase;
-
- lock(&chanlock);
-
-loop:
- // pass 1 - look for something already waiting
- dfl = nil;
- for(i=0; i<sel->ncase; i++) {
- cas = sel->scase[o];
-
- if(cas->send == 2) { // default
- dfl = cas;
- goto next1;
- }
-
- c = cas->chan;
- if(c->dataqsiz > 0) {
- if(cas->send) {
- if(c->closed & Wclosed)
- goto sclose;
- if(c->qcount < c->dataqsiz)
- goto asyns;
- goto next1;
- }
- if(c->qcount > 0)
- goto asynr;
- if(c->closed & Wclosed)
- goto rclose;
- goto next1;
- }
-
- if(cas->send) {
- if(c->closed & Wclosed)
- goto sclose;
- sg = dequeue(&c->recvq, c);
- if(sg != nil)
- goto gots;
- goto next1;
- }
- sg = dequeue(&c->sendq, c);
- if(sg != nil)
- goto gotr;
- if(c->closed & Wclosed)
- goto rclose;
-
- next1:
- o += p;
- if(o >= sel->ncase)
- o -= sel->ncase;
- }
-
- if(dfl != nil) {
- cas = dfl;
- goto retc;
- }
-
-
- // pass 2 - enqueue on all chans
- for(i=0; i<sel->ncase; i++) {
- cas = sel->scase[o];
- c = cas->chan;
-
- if(c->dataqsiz > 0) {
- if(cas->send) {
- if(c->qcount < c->dataqsiz) {
- prints("selectgo: pass 2 async send\n");
- goto asyns;
- }
- sg = allocsg(c);
- sg->offset = o;
- enqueue(&c->sendq, sg);
- goto next2;
- }
- if(c->qcount > 0) {
- prints("selectgo: pass 2 async recv\n");
- goto asynr;
- }
- sg = allocsg(c);
- sg->offset = o;
- enqueue(&c->recvq, sg);
- goto next2;
- }
-
- if(cas->send) {
- sg = dequeue(&c->recvq, c);
- if(sg != nil) {
- prints("selectgo: pass 2 sync send\n");
- g->selgen++;
- goto gots;
- }
- sg = allocsg(c);
- sg->offset = o;
- c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
- enqueue(&c->sendq, sg);
- goto next2;
- }
- sg = dequeue(&c->sendq, c);
- if(sg != nil) {
- prints("selectgo: pass 2 sync recv\n");
- g->selgen++;
- goto gotr;
- }
- sg = allocsg(c);
- sg->offset = o;
- enqueue(&c->recvq, sg);
-
- next2:
- o += p;
- if(o >= sel->ncase)
- o -= sel->ncase;
- }
-
- g->param = nil;
- g->status = Gwaiting;
- unlock(&chanlock);
- gosched();
-
- lock(&chanlock);
- sg = g->param;
- if(sg == nil)
- goto loop;
-
- o = sg->offset;
- cas = sel->scase[o];
- c = cas->chan;
-
- if(c->dataqsiz > 0) {
-// prints("shouldnt happen\n");
- goto loop;
- }
-
- if(debug) {
- prints("wait-return: sel=");
- sys·printpointer(sel);
- prints(" c=");
- sys·printpointer(c);
- prints(" cas=");
- sys·printpointer(cas);
- prints(" send=");
- sys·printint(cas->send);
- prints(" o=");
- sys·printint(o);
- prints("\n");
- }
-
- if(!cas->send) {
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
- }
-
- freesg(c, sg);
- goto retc;
-
-asynr:
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, c->recvdataq->elem);
- c->recvdataq = c->recvdataq->link;
- c->qcount--;
- sg = dequeue(&c->sendq, c);
- if(sg != nil) {
- gp = sg->g;
- freesg(c, sg);
- ready(gp);
- }
- goto retc;
-
-asyns:
- if(cas->u.elem != nil)
- c->elemalg->copy(c->elemsize, c->senddataq->elem, cas->u.elem);
- c->senddataq = c->senddataq->link;
- c->qcount++;
- sg = dequeue(&c->recvq, c);
- if(sg != nil) {
- gp = sg->g;
- freesg(c, sg);
- ready(gp);
- }
- goto retc;
-
-gotr:
- // recv path to wakeup the sender (sg)
- if(debug) {
- prints("gotr: sel=");
- sys·printpointer(sel);
- prints(" c=");
- sys·printpointer(c);
- prints(" o=");
- sys·printint(o);
- prints("\n");
- }
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
- gp = sg->g;
- gp->param = sg;
- ready(gp);
- goto retc;
-
-rclose:
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, nil);
- c->closed |= Rclosed;
- incerr(c);
- goto retc;
-
-gots:
- // send path to wakeup the receiver (sg)
- if(debug) {
- prints("gots: sel=");
- sys·printpointer(sel);
- prints(" c=");
- sys·printpointer(c);
- prints(" o=");
- sys·printint(o);
- prints("\n");
- }
- if(c->closed & Wclosed)
- goto sclose;
- c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
- gp = sg->g;
- gp->param = sg;
- ready(gp);
- goto retc;
-
-sclose:
- incerr(c);
- goto retc;
-
-retc:
- if(sel->ncase >= 1 && sel->ncase < nelem(selfree)) {
- sel->link = selfree[sel->ncase];
- selfree[sel->ncase] = sel;
- }
- unlock(&chanlock);
-
- sys·setcallerpc(&sel, cas->pc);
- as = (byte*)&sel + cas->so;
- *as = true;
-}
-
-// closechan(sel *byte);
-void
-sys·closechan(Hchan *c)
-{
- SudoG *sg;
- G* gp;
-
- lock(&chanlock);
- incerr(c);
- c->closed |= Wclosed;
-
- // release all readers
- for(;;) {
- sg = dequeue(&c->recvq, c);
- if(sg == nil)
- break;
- gp = sg->g;
- gp->param = nil;
- freesg(c, sg);
- ready(gp);
- }
-
- // release all writers
- for(;;) {
- sg = dequeue(&c->sendq, c);
- if(sg == nil)
- break;
- gp = sg->g;
- gp->param = nil;
- freesg(c, sg);
- ready(gp);
- }
-
- unlock(&chanlock);
-}
-
-// closedchan(sel *byte) bool;
-void
-sys·closedchan(Hchan *c, bool closed)
-{
- // test Rclosed
- closed = 0;
- if(c->closed & Rclosed)
- closed = 1;
- FLUSH(&closed);
-}
-
-static SudoG*
-dequeue(WaitQ *q, Hchan *c)
-{
- SudoG *sgp;
-
-loop:
- sgp = q->first;
- if(sgp == nil)
- return nil;
- q->first = sgp->link;
-
- // if sgp is stale, ignore it
- if(sgp->selgen != sgp->g->selgen) {
- //prints("INVALID PSEUDOG POINTER\n");
- freesg(c, sgp);
- goto loop;
- }
-
- // invalidate any others
- sgp->g->selgen++;
- return sgp;
-}
-
-static void
-enqueue(WaitQ *q, SudoG *sgp)
-{
- sgp->link = nil;
- if(q->first == nil) {
- q->first = sgp;
- q->last = sgp;
- return;
- }
- q->last->link = sgp;
- q->last = sgp;
-}
-
-static SudoG*
-allocsg(Hchan *c)
-{
- SudoG* sg;
-
- sg = c->free;
- if(sg != nil) {
- c->free = sg->link;
- } else
- sg = mal(sizeof(*sg) + c->elemsize - sizeof(sg->elem));
- sg->selgen = g->selgen;
- sg->g = g;
- sg->offset = 0;
- sg->isfree = 0;
-
- return sg;
-}
-
-static void
-freesg(Hchan *c, SudoG *sg)
-{
- if(sg != nil) {
- if(sg->isfree)
- throw("chan.freesg: already free");
- sg->isfree = 1;
- sg->link = c->free;
- c->free = sg;
- }
-}
-
-static uint32
-gcd(uint32 u, uint32 v)
-{
- for(;;) {
- if(u > v) {
- if(v == 0)
- return u;
- u = u%v;
- continue;
- }
- if(u == 0)
- return v;
- v = v%u;
- }
-}
-
-static uint32
-fastrand1(void)
-{
- static uint32 x = 0x49f6428aUL;
-
- x += x;
- if(x & 0x80000000L)
- x ^= 0x88888eefUL;
- return x;
-}
-
-static uint32
-fastrand2(void)
-{
- static uint32 x = 0x49f6428aUL;
-
- x += x;
- if(x & 0x80000000L)
- x ^= 0xfafd871bUL;
- return x;
-}
diff --git a/src/lib/runtime/darwin/386/defs.h b/src/lib/runtime/darwin/386/defs.h
deleted file mode 100644
index b66a5d8b4..000000000
--- a/src/lib/runtime/darwin/386/defs.h
+++ /dev/null
@@ -1,229 +0,0 @@
-// godefs -f -m32 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
- PROT_NONE = 0,
- PROT_READ = 0x1,
- PROT_WRITE = 0x2,
- PROT_EXEC = 0x4,
- MAP_ANON = 0x1000,
- MAP_PRIVATE = 0x2,
- MACH_MSG_TYPE_MOVE_RECEIVE = 0x10,
- MACH_MSG_TYPE_MOVE_SEND = 0x11,
- MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12,
- MACH_MSG_TYPE_COPY_SEND = 0x13,
- MACH_MSG_TYPE_MAKE_SEND = 0x14,
- MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15,
- MACH_MSG_TYPE_COPY_RECEIVE = 0x16,
- MACH_MSG_PORT_DESCRIPTOR = 0,
- MACH_MSG_OOL_DESCRIPTOR = 0x1,
- MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2,
- MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3,
- MACH_MSGH_BITS_COMPLEX = 0x80000000,
- MACH_SEND_MSG = 0x1,
- MACH_RCV_MSG = 0x2,
- MACH_RCV_LARGE = 0x4,
- MACH_SEND_TIMEOUT = 0x10,
- MACH_SEND_INTERRUPT = 0x40,
- MACH_SEND_CANCEL = 0x80,
- MACH_SEND_ALWAYS = 0x10000,
- MACH_SEND_TRAILER = 0x20000,
- MACH_RCV_TIMEOUT = 0x100,
- MACH_RCV_NOTIFY = 0x200,
- MACH_RCV_INTERRUPT = 0x400,
- MACH_RCV_OVERWRITE = 0x1000,
- NDR_PROTOCOL_2_0 = 0,
- NDR_INT_BIG_ENDIAN = 0,
- NDR_INT_LITTLE_ENDIAN = 0x1,
- NDR_FLOAT_IEEE = 0,
- NDR_CHAR_ASCII = 0,
- SA_SIGINFO = 0x40,
- SA_RESTART = 0x2,
- SA_ONSTACK = 0x1,
- SA_USERTRAMP = 0x100,
- SA_64REGSET = 0x200,
-};
-
-// Types
-#pragma pack on
-
-typedef struct MachBody MachBody;
-struct MachBody {
- uint32 msgh_descriptor_count;
-};
-
-typedef struct MachHeader MachHeader;
-struct MachHeader {
- uint32 msgh_bits;
- uint32 msgh_size;
- uint32 msgh_remote_port;
- uint32 msgh_local_port;
- uint32 msgh_reserved;
- int32 msgh_id;
-};
-
-typedef struct MachNDR MachNDR;
-struct MachNDR {
- uint8 mig_vers;
- uint8 if_vers;
- uint8 reserved1;
- uint8 mig_encoding;
- uint8 int_rep;
- uint8 char_rep;
- uint8 float_rep;
- uint8 reserved2;
-};
-
-typedef struct MachPort MachPort;
-struct MachPort {
- uint32 name;
- uint32 pad1;
- uint16 pad2;
- uint8 disposition;
- uint8 type;
-};
-
-typedef struct StackT StackT;
-struct StackT {
- void *ss_sp;
- uint32 ss_size;
- int32 ss_flags;
-};
-
-typedef union Sighandler Sighandler;
-union Sighandler {
- void *__sa_handler;
- void *__sa_sigaction;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
- Sighandler __sigaction_u;
- void *sa_tramp;
- uint32 sa_mask;
- int32 sa_flags;
-};
-
-typedef union Sigval Sigval;
-union Sigval {
- int32 sival_int;
- void *sival_ptr;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
- int32 si_signo;
- int32 si_errno;
- int32 si_code;
- int32 si_pid;
- uint32 si_uid;
- int32 si_status;
- void *si_addr;
- Sigval si_value;
- int32 si_band;
- uint32 __pad[7];
-};
-
-typedef struct FPControl FPControl;
-struct FPControl {
- byte pad0[2];
-};
-
-typedef struct FPStatus FPStatus;
-struct FPStatus {
- byte pad0[2];
-};
-
-typedef struct RegMMST RegMMST;
-struct RegMMST {
- int8 mmst_reg[10];
- int8 mmst_rsrv[6];
-};
-
-typedef struct RegXMM RegXMM;
-struct RegXMM {
- int8 xmm_reg[16];
-};
-
-typedef struct Regs Regs;
-struct Regs {
- uint32 eax;
- uint32 ebx;
- uint32 ecx;
- uint32 edx;
- uint32 edi;
- uint32 esi;
- uint32 ebp;
- uint32 esp;
- uint32 ss;
- uint32 eflags;
- uint32 eip;
- uint32 cs;
- uint32 ds;
- uint32 es;
- uint32 fs;
- uint32 gs;
-};
-
-typedef struct FloatState FloatState;
-struct FloatState {
- int32 fpu_reserved[2];
- FPControl fpu_fcw;
- FPStatus fpu_fsw;
- uint8 fpu_ftw;
- uint8 fpu_rsrv1;
- uint16 fpu_fop;
- uint32 fpu_ip;
- uint16 fpu_cs;
- uint16 fpu_rsrv2;
- uint32 fpu_dp;
- uint16 fpu_ds;
- uint16 fpu_rsrv3;
- uint32 fpu_mxcsr;
- uint32 fpu_mxcsrmask;
- RegMMST fpu_stmm0;
- RegMMST fpu_stmm1;
- RegMMST fpu_stmm2;
- RegMMST fpu_stmm3;
- RegMMST fpu_stmm4;
- RegMMST fpu_stmm5;
- RegMMST fpu_stmm6;
- RegMMST fpu_stmm7;
- RegXMM fpu_xmm0;
- RegXMM fpu_xmm1;
- RegXMM fpu_xmm2;
- RegXMM fpu_xmm3;
- RegXMM fpu_xmm4;
- RegXMM fpu_xmm5;
- RegXMM fpu_xmm6;
- RegXMM fpu_xmm7;
- int8 fpu_rsrv4[224];
- int32 fpu_reserved1;
-};
-
-typedef struct ExceptionState ExceptionState;
-struct ExceptionState {
- uint32 trapno;
- uint32 err;
- uint32 faultvaddr;
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
- ExceptionState es;
- Regs ss;
- FloatState fs;
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
- int32 uc_onstack;
- uint32 uc_sigmask;
- StackT uc_stack;
- Ucontext *uc_link;
- uint32 uc_mcsize;
- Mcontext *uc_mcontext;
-};
-#pragma pack off
diff --git a/src/lib/runtime/darwin/386/rt0.s b/src/lib/runtime/darwin/386/rt0.s
deleted file mode 100755
index 5b52e912c..000000000
--- a/src/lib/runtime/darwin/386/rt0.s
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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.
-
-// Darwin and Linux use the same linkage to main
-
-TEXT _rt0_386_darwin(SB),7,$0
- JMP _rt0_386(SB)
diff --git a/src/lib/runtime/darwin/386/signal.c b/src/lib/runtime/darwin/386/signal.c
deleted file mode 100644
index 3a63c4b38..000000000
--- a/src/lib/runtime/darwin/386/signal.c
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "signals.h"
-
-void
-dumpregs(Regs *r)
-{
- printf("eax %x\n", r->eax);
- printf("ebx %x\n", r->ebx);
- printf("ecx %x\n", r->ecx);
- printf("edx %x\n", r->edx);
- printf("edi %x\n", r->edi);
- printf("esi %x\n", r->esi);
- printf("ebp %x\n", r->ebp);
- printf("esp %x\n", r->esp);
- printf("eip %x\n", r->eip);
- printf("eflags %x\n", r->eflags);
- printf("cs %x\n", r->cs);
- printf("fs %x\n", r->fs);
- printf("gs %x\n", r->gs);
-}
-
-void
-sighandler(int32 sig, Siginfo *info, void *context)
-{
- Ucontext *uc;
- Mcontext *mc;
- Regs *r;
-
- if(panicking) // traceback already printed
- exit(2);
- panicking = 1;
-
- if(sig < 0 || sig >= NSIG){
- printf("Signal %d\n", sig);
- }else{
- printf("%s\n", sigtab[sig].name);
- }
-
- uc = context;
- mc = uc->uc_mcontext;
- r = &mc->ss;
-
- printf("Faulting address: %p\n", info->si_addr);
- printf("pc: %x\n", r->eip);
- printf("\n");
-
- if(gotraceback()){
- traceback((void*)r->eip, (void*)r->esp, m->curg);
- tracebackothers(m->curg);
- dumpregs(r);
- }
-
- breakpoint();
- exit(2);
-}
-
-void
-sigignore(int32, Siginfo*, void*)
-{
-}
-
-void
-signalstack(byte *p, int32 n)
-{
- StackT st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- sigaltstack(&st, nil);
-}
-
-void
-initsig(void)
-{
- int32 i;
- static Sigaction sa;
-
- sa.sa_flags |= SA_SIGINFO|SA_ONSTACK;
- sa.sa_mask = 0; // 0xFFFFFFFFU;
- sa.sa_tramp = sigtramp; // sigtramp's job is to call into real handler
- for(i = 0; i<NSIG; i++) {
- if(sigtab[i].flags) {
- if(sigtab[i].flags & SigCatch) {
- sa.__sigaction_u.__sa_sigaction = sighandler;
- } else {
- sa.__sigaction_u.__sa_sigaction = sigignore;
- }
- if(sigtab[i].flags & SigRestart)
- sa.sa_flags |= SA_RESTART;
- else
- sa.sa_flags &= ~SA_RESTART;
- sigaction(i, &sa, nil);
- }
- }
-}
-
diff --git a/src/lib/runtime/darwin/386/sys.s b/src/lib/runtime/darwin/386/sys.s
deleted file mode 100644
index bbcb622d5..000000000
--- a/src/lib/runtime/darwin/386/sys.s
+++ /dev/null
@@ -1,278 +0,0 @@
-// 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 calls and other sys.stuff for 386, Darwin
-// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
-// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
-
-TEXT notok(SB),7,$0
- MOVL $0xf1, 0xf1
- RET
-
-// Exit the entire program (like C exit)
-TEXT exit(SB),7,$0
- MOVL $1, AX
- INT $0x80
- CALL notok(SB)
- RET
-
-// Exit this OS thread (like pthread_exit, which eventually
-// calls __bsdthread_terminate).
-TEXT exit1(SB),7,$0
- MOVL $361, AX
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-TEXT sys·write(SB),7,$0
- MOVL $4, AX
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-TEXT sys·mmap(SB),7,$0
- MOVL $197, AX
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-TEXT sigaction(SB),7,$0
- MOVL $46, AX
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-// Sigtramp's job is to call the actual signal handler.
-// It is called with the following arguments on the stack:
-// 0(FP) "return address" - ignored
-// 4(FP) actual handler
-// 8(FP) siginfo style - ignored
-// 12(FP) signal number
-// 16(FP) siginfo
-// 20(FP) context
-TEXT sigtramp(SB),7,$40
- MOVL 4(FS), BP // m
- MOVL 28(BP), BP // m->gsignal
- MOVL BP, 0(FS) // g = m->gsignal
-
- MOVL handler+4(FP), DI
- MOVL signo+12(FP), AX
- MOVL siginfo+16(FP), BX
- MOVL context+20(FP), CX
-
- MOVL AX, 0(SP)
- MOVL BX, 4(SP)
- MOVL CX, 8(SP)
- CALL DI
-
- MOVL context+20(FP), CX
- MOVL style+8(FP), BX
-
- MOVL $0, 0(SP) // "caller PC" - ignored
- MOVL CX, 4(SP)
- MOVL BX, 8(SP)
- MOVL $184, AX // sigreturn(ucontext, infostyle)
- INT $0x80
- CALL notok(SB)
- RET
-
-TEXT sigaltstack(SB),7,$0
- MOVL $53, AX
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
-// System call args are: func arg stack pthread flags.
-TEXT bsdthread_create(SB),7,$32
- MOVL $360, AX
- // 0(SP) is where the caller PC would be; kernel skips it
- MOVL func+12(FP), BX
- MOVL BX, 4(SP) // func
- MOVL m+4(FP), BX
- MOVL BX, 8(SP) // arg
- MOVL stk+0(FP), BX
- MOVL BX, 12(SP) // stack
- MOVL g+8(FP), BX
- MOVL BX, 16(SP) // pthread
- MOVL $0x1000000, 20(SP) // flags = PTHREAD_START_CUSTOM
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-// The thread that bsdthread_create creates starts executing here,
-// because we registered this function using bsdthread_register
-// at startup.
-// AX = "pthread" (= g)
-// BX = mach thread port
-// CX = "func" (= fn)
-// DX = "arg" (= m)
-// DI = stack top
-// SI = flags (= 0x1000000)
-// SP = stack - C_32_STK_ALIGN
-TEXT bsdthread_start(SB),7,$0
- // set up ldt 7+id to point at m->tls.
- // m->tls is at m+40. newosproc left
- // the m->id in tls[0].
- LEAL 40(DX), BP
- MOVL 0(BP), DI
- ADDL $7, DI // m0 is LDT#7. count up.
- // setldt(tls#, &tls, sizeof tls)
- PUSHAL // save registers
- PUSHL $32 // sizeof tls
- PUSHL BP // &tls
- PUSHL DI // tls #
- CALL setldt(SB)
- POPL AX
- POPL AX
- POPL AX
- POPAL
- SHLL $3, DI // segment# is ldt*8 + 7.
- ADDL $7, DI
- MOVW DI, FS
-
- // Now segment is established. Initialize m, g.
- MOVL AX, 0(FS) // g
- MOVL DX, 4(FS) // m
- MOVL BX, 20(DX) // m->procid = thread port (for debuggers)
- CALL CX // fn()
- CALL exit1(SB)
- RET
-
-// void bsdthread_register(void)
-// registers callbacks for threadstart (see bsdthread_create above
-// and wqthread and pthsize (not used). returns 0 on success.
-TEXT bsdthread_register(SB),7,$40
- MOVL $366, AX
- // 0(SP) is where kernel expects caller PC; ignored
- MOVL $bsdthread_start(SB), 4(SP) // threadstart
- MOVL $0, 8(SP) // wqthread, not used by us
- MOVL $0, 12(SP) // pthsize, not used by us
- MOVL $0, 16(SP) // paranoia
- MOVL $0, 20(SP)
- MOVL $0, 24(SP)
- INT $0x80
- JAE 2(PC)
- CALL notok(SB)
- RET
-
-// Invoke Mach system call.
-// Assumes system call number in AX,
-// caller PC on stack, caller's caller PC next,
-// and then the system call arguments.
-//
-// Can be used for BSD too, but we don't,
-// because if you use this interface the BSD
-// system call numbers need an extra field
-// in the high 16 bits that seems to be the
-// argument count in bytes but is not always.
-// INT $0x80 works fine for those.
-TEXT sysenter(SB),7,$0
- POPL DX
- MOVL SP, CX
- BYTE $0x0F; BYTE $0x34; // SYSENTER
- // returns to DX with SP set to CX
-
-TEXT mach_msg_trap(SB),7,$0
- MOVL $-31, AX
- CALL sysenter(SB)
- RET
-
-TEXT mach_reply_port(SB),7,$0
- MOVL $-26, AX
- CALL sysenter(SB)
- RET
-
-TEXT mach_task_self(SB),7,$0
- MOVL $-28, AX
- CALL sysenter(SB)
- RET
-
-// Mach provides trap versions of the semaphore ops,
-// instead of requiring the use of RPC.
-
-// uint32 mach_semaphore_wait(uint32)
-TEXT mach_semaphore_wait(SB),7,$0
- MOVL $-36, AX
- CALL sysenter(SB)
- RET
-
-// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
-TEXT mach_semaphore_timedwait(SB),7,$0
- MOVL $-38, AX
- CALL sysenter(SB)
- RET
-
-// uint32 mach_semaphore_signal(uint32)
-TEXT mach_semaphore_signal(SB),7,$0
- MOVL $-33, AX
- CALL sysenter(SB)
- RET
-
-// uint32 mach_semaphore_signal_all(uint32)
-TEXT mach_semaphore_signal_all(SB),7,$0
- MOVL $-34, AX
- CALL sysenter(SB)
- RET
-
-/*
-descriptor entry format for system call
-is the native machine format, ugly as it is:
-
- 2-byte limit
- 3-byte base
- 1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
- 1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
- 0x0F=4 more bits of limit
- 1 byte: 8 more bits of base
-
-int i386_get_ldt(int, union ldt_entry *, int);
-int i386_set_ldt(int, const union ldt_entry *, int);
-
-*/
-
-// setldt(int entry, int address, int limit)
-TEXT setldt(SB),7,$32
- // set up data_desc
- LEAL 16(SP), AX // struct data_desc
- MOVL $0, 0(AX)
- MOVL $0, 4(AX)
-
- MOVL address+4(FP), BX // aka base
- MOVW BX, 2(AX)
- SHRL $16, BX
- MOVB BX, 4(AX)
- SHRL $8, BX
- MOVB BX, 7(AX)
-
- MOVL limit+8(FP), BX
- MOVW BX, 0(AX)
- SHRL $16, BX
- ANDL $0x0F, BX
- ORL $0x40, BX // 32-bit operand size
- MOVB BX, 6(AX)
-
- MOVL $0xF2, 5(AX) // r/w data descriptor, dpl=3, present
-
- // call i386_set_ldt(entry, desc, 1)
- MOVL entry+0(FP), BX
- MOVL BX, 0(SP)
- MOVL AX, 4(SP)
- MOVL $1, 8(SP)
- CALL i386_set_ldt(SB)
- RET
-
-TEXT i386_set_ldt(SB),7,$0
- MOVL $5, AX
- INT $0x82 // sic
- JAE 2(PC)
- CALL notok(SB)
- RET
-
diff --git a/src/lib/runtime/darwin/amd64/defs.h b/src/lib/runtime/darwin/amd64/defs.h
deleted file mode 100644
index 1076e4c10..000000000
--- a/src/lib/runtime/darwin/amd64/defs.h
+++ /dev/null
@@ -1,244 +0,0 @@
-// godefs -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
- PROT_NONE = 0,
- PROT_READ = 0x1,
- PROT_WRITE = 0x2,
- PROT_EXEC = 0x4,
- MAP_ANON = 0x1000,
- MAP_PRIVATE = 0x2,
- MACH_MSG_TYPE_MOVE_RECEIVE = 0x10,
- MACH_MSG_TYPE_MOVE_SEND = 0x11,
- MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12,
- MACH_MSG_TYPE_COPY_SEND = 0x13,
- MACH_MSG_TYPE_MAKE_SEND = 0x14,
- MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15,
- MACH_MSG_TYPE_COPY_RECEIVE = 0x16,
- MACH_MSG_PORT_DESCRIPTOR = 0,
- MACH_MSG_OOL_DESCRIPTOR = 0x1,
- MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2,
- MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3,
- MACH_MSGH_BITS_COMPLEX = 0x80000000,
- MACH_SEND_MSG = 0x1,
- MACH_RCV_MSG = 0x2,
- MACH_RCV_LARGE = 0x4,
- MACH_SEND_TIMEOUT = 0x10,
- MACH_SEND_INTERRUPT = 0x40,
- MACH_SEND_CANCEL = 0x80,
- MACH_SEND_ALWAYS = 0x10000,
- MACH_SEND_TRAILER = 0x20000,
- MACH_RCV_TIMEOUT = 0x100,
- MACH_RCV_NOTIFY = 0x200,
- MACH_RCV_INTERRUPT = 0x400,
- MACH_RCV_OVERWRITE = 0x1000,
- NDR_PROTOCOL_2_0 = 0,
- NDR_INT_BIG_ENDIAN = 0,
- NDR_INT_LITTLE_ENDIAN = 0x1,
- NDR_FLOAT_IEEE = 0,
- NDR_CHAR_ASCII = 0,
- SA_SIGINFO = 0x40,
- SA_RESTART = 0x2,
- SA_ONSTACK = 0x1,
- SA_USERTRAMP = 0x100,
- SA_64REGSET = 0x200,
-};
-
-// Types
-#pragma pack on
-
-typedef struct MachBody MachBody;
-struct MachBody {
- uint32 msgh_descriptor_count;
-};
-
-typedef struct MachHeader MachHeader;
-struct MachHeader {
- uint32 msgh_bits;
- uint32 msgh_size;
- uint32 msgh_remote_port;
- uint32 msgh_local_port;
- uint32 msgh_reserved;
- int32 msgh_id;
-};
-
-typedef struct MachNDR MachNDR;
-struct MachNDR {
- uint8 mig_vers;
- uint8 if_vers;
- uint8 reserved1;
- uint8 mig_encoding;
- uint8 int_rep;
- uint8 char_rep;
- uint8 float_rep;
- uint8 reserved2;
-};
-
-typedef struct MachPort MachPort;
-struct MachPort {
- uint32 name;
- uint32 pad1;
- uint16 pad2;
- uint8 disposition;
- uint8 type;
-};
-
-typedef struct StackT StackT;
-struct StackT {
- void *ss_sp;
- uint64 ss_size;
- int32 ss_flags;
- byte pad0[4];
-};
-
-typedef union Sighandler Sighandler;
-union Sighandler {
- void *__sa_handler;
- void *__sa_sigaction;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
- Sighandler __sigaction_u;
- void *sa_tramp;
- uint32 sa_mask;
- int32 sa_flags;
-};
-
-typedef union Sigval Sigval;
-union Sigval {
- int32 sival_int;
- void *sival_ptr;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
- int32 si_signo;
- int32 si_errno;
- int32 si_code;
- int32 si_pid;
- uint32 si_uid;
- int32 si_status;
- void *si_addr;
- Sigval si_value;
- int64 si_band;
- uint64 __pad[7];
-};
-
-typedef struct FPControl FPControl;
-struct FPControl {
- byte pad0[2];
-};
-
-typedef struct FPStatus FPStatus;
-struct FPStatus {
- byte pad0[2];
-};
-
-typedef struct RegMMST RegMMST;
-struct RegMMST {
- int8 mmst_reg[10];
- int8 mmst_rsrv[6];
-};
-
-typedef struct RegXMM RegXMM;
-struct RegXMM {
- int8 xmm_reg[16];
-};
-
-typedef struct Regs Regs;
-struct Regs {
- uint64 rax;
- uint64 rbx;
- uint64 rcx;
- uint64 rdx;
- uint64 rdi;
- uint64 rsi;
- uint64 rbp;
- uint64 rsp;
- uint64 r8;
- uint64 r9;
- uint64 r10;
- uint64 r11;
- uint64 r12;
- uint64 r13;
- uint64 r14;
- uint64 r15;
- uint64 rip;
- uint64 rflags;
- uint64 cs;
- uint64 fs;
- uint64 gs;
-};
-
-typedef struct FloatState FloatState;
-struct FloatState {
- int32 fpu_reserved[2];
- FPControl fpu_fcw;
- FPStatus fpu_fsw;
- uint8 fpu_ftw;
- uint8 fpu_rsrv1;
- uint16 fpu_fop;
- uint32 fpu_ip;
- uint16 fpu_cs;
- uint16 fpu_rsrv2;
- uint32 fpu_dp;
- uint16 fpu_ds;
- uint16 fpu_rsrv3;
- uint32 fpu_mxcsr;
- uint32 fpu_mxcsrmask;
- RegMMST fpu_stmm0;
- RegMMST fpu_stmm1;
- RegMMST fpu_stmm2;
- RegMMST fpu_stmm3;
- RegMMST fpu_stmm4;
- RegMMST fpu_stmm5;
- RegMMST fpu_stmm6;
- RegMMST fpu_stmm7;
- RegXMM fpu_xmm0;
- RegXMM fpu_xmm1;
- RegXMM fpu_xmm2;
- RegXMM fpu_xmm3;
- RegXMM fpu_xmm4;
- RegXMM fpu_xmm5;
- RegXMM fpu_xmm6;
- RegXMM fpu_xmm7;
- RegXMM fpu_xmm8;
- RegXMM fpu_xmm9;
- RegXMM fpu_xmm10;
- RegXMM fpu_xmm11;
- RegXMM fpu_xmm12;
- RegXMM fpu_xmm13;
- RegXMM fpu_xmm14;
- RegXMM fpu_xmm15;
- int8 fpu_rsrv4[96];
- int32 fpu_reserved1;
-};
-
-typedef struct ExceptionState ExceptionState;
-struct ExceptionState {
- uint32 trapno;
- uint32 err;
- uint64 faultvaddr;
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
- ExceptionState es;
- Regs ss;
- FloatState fs;
- byte pad0[4];
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
- int32 uc_onstack;
- uint32 uc_sigmask;
- StackT uc_stack;
- Ucontext *uc_link;
- uint64 uc_mcsize;
- Mcontext *uc_mcontext;
-};
-#pragma pack off
diff --git a/src/lib/runtime/darwin/amd64/rt0.s b/src/lib/runtime/darwin/amd64/rt0.s
deleted file mode 100644
index 0a0011781..000000000
--- a/src/lib/runtime/darwin/amd64/rt0.s
+++ /dev/null
@@ -1,9 +0,0 @@
-// 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.
-
-// Darwin and Linux use the same linkage to main
-
-TEXT _rt0_amd64_darwin(SB),7,$-8
- MOVQ $_rt0_amd64(SB), AX
- JMP AX
diff --git a/src/lib/runtime/darwin/amd64/signal.c b/src/lib/runtime/darwin/amd64/signal.c
deleted file mode 100644
index 45e5e8d47..000000000
--- a/src/lib/runtime/darwin/amd64/signal.c
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "signals.h"
-
-void
-dumpregs(Regs *r)
-{
- printf("rax %X\n", r->rax);
- printf("rbx %X\n", r->rbx);
- printf("rcx %X\n", r->rcx);
- printf("rdx %X\n", r->rdx);
- printf("rdi %X\n", r->rdi);
- printf("rsi %X\n", r->rsi);
- printf("rbp %X\n", r->rbp);
- printf("rsp %X\n", r->rsp);
- printf("r8 %X\n", r->r8 );
- printf("r9 %X\n", r->r9 );
- printf("r10 %X\n", r->r10);
- printf("r11 %X\n", r->r11);
- printf("r12 %X\n", r->r12);
- printf("r13 %X\n", r->r13);
- printf("r14 %X\n", r->r14);
- printf("r15 %X\n", r->r15);
- printf("rip %X\n", r->rip);
- printf("rflags %X\n", r->rflags);
- printf("cs %X\n", r->cs);
- printf("fs %X\n", r->fs);
- printf("gs %X\n", r->gs);
-}
-
-void
-sighandler(int32 sig, Siginfo *info, void *context)
-{
- Ucontext *uc;
- Mcontext *mc;
- Regs *r;
-
- if(panicking) // traceback already printed
- exit(2);
- panicking = 1;
-
- if(sig < 0 || sig >= NSIG){
- printf("Signal %d\n", sig);
- }else{
- printf("%s\n", sigtab[sig].name);
- }
-
- uc = context;
- mc = uc->uc_mcontext;
- r = &mc->ss;
-
- printf("Faulting address: %p\n", info->si_addr);
- printf("pc: %X\n", r->rip);
- printf("\n");
-
- if(gotraceback()){
- traceback((void*)r->rip, (void*)r->rsp, (void*)r->r15);
- tracebackothers((void*)r->r15);
- dumpregs(r);
- }
-
- breakpoint();
- exit(2);
-}
-
-void
-sigignore(int32, Siginfo*, void*)
-{
-}
-
-void
-signalstack(byte *p, int32 n)
-{
- StackT st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- sigaltstack(&st, nil);
-}
-
-void
-initsig(void)
-{
- int32 i;
- static Sigaction sa;
-
- sa.sa_flags |= SA_SIGINFO|SA_ONSTACK;
- sa.sa_mask = 0; // 0xFFFFFFFFU;
- sa.sa_tramp = sigtramp; // sigtramp's job is to call into real handler
- for(i = 0; i<NSIG; i++) {
- if(sigtab[i].flags) {
- if(sigtab[i].flags & SigCatch) {
- sa.__sigaction_u.__sa_sigaction = sighandler;
- } else {
- sa.__sigaction_u.__sa_sigaction = sigignore;
- }
- if(sigtab[i].flags & SigRestart)
- sa.sa_flags |= SA_RESTART;
- else
- sa.sa_flags &= ~SA_RESTART;
- sigaction(i, &sa, nil);
- }
- }
-}
-
diff --git a/src/lib/runtime/darwin/amd64/sys.s b/src/lib/runtime/darwin/amd64/sys.s
deleted file mode 100644
index b46c823ae..000000000
--- a/src/lib/runtime/darwin/amd64/sys.s
+++ /dev/null
@@ -1,263 +0,0 @@
-// 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 calls and other sys.stuff for AMD64, Darwin
-// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
-// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
-//
-
-// Exit the entire program (like C exit)
-TEXT exit(SB),7,$-8
- MOVL 8(SP), DI // arg 1 exit status
- MOVL $(0x2000000+1), AX // syscall entry
- SYSCALL
- CALL notok(SB)
- RET
-
-// Exit this OS thread (like pthread_exit, which eventually
-// calls __bsdthread_terminate).
-TEXT exit1(SB),7,$-8
- MOVL 8(SP), DI // arg 1 exit status
- MOVL $(0x2000000+361), AX // syscall entry
- SYSCALL
- CALL notok(SB)
- RET
-
-TEXT sys·write(SB),7,$-8
- MOVL 8(SP), DI // arg 1 fid
- MOVQ 16(SP), SI // arg 2 buf
- MOVL 24(SP), DX // arg 3 count
- MOVL $(0x2000000+4), AX // syscall entry
- SYSCALL
- JCC 2(PC)
- CALL notok(SB)
- RET
-
-TEXT open(SB),7,$-8
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVQ $0, R10
- MOVL $(0x2000000+5), AX // syscall entry
- SYSCALL
- RET
-
-TEXT close(SB),7,$-8
- MOVL 8(SP), DI
- MOVL $(0x2000000+6), AX // syscall entry
- SYSCALL
- RET
-
-TEXT fstat(SB),7,$-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL $(0x2000000+339), AX // syscall entry; really fstat64
- SYSCALL
- RET
-
-TEXT read(SB),7,$-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL $(0x2000000+3), AX // syscall entry
- SYSCALL
- RET
-
-TEXT write(SB),7,$-8
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL $(0x2000000+4), AX // syscall entry
- SYSCALL
- RET
-
-TEXT sigaction(SB),7,$-8
- MOVL 8(SP), DI // arg 1 sig
- MOVQ 16(SP), SI // arg 2 act
- MOVQ 24(SP), DX // arg 3 oact
- MOVQ 24(SP), CX // arg 3 oact
- MOVQ 24(SP), R10 // arg 3 oact
- MOVL $(0x2000000+46), AX // syscall entry
- SYSCALL
- JCC 2(PC)
- CALL notok(SB)
- RET
-
-TEXT sigtramp(SB),7,$40
- MOVQ 32(R14), R15 // g = m->gsignal
- MOVL DX,0(SP)
- MOVQ CX,8(SP)
- MOVQ R8,16(SP)
- MOVQ R8, 24(SP) // save ucontext
- MOVQ SI, 32(SP) // save infostyle
- CALL DI
- MOVL $(0x2000000+184), AX // sigreturn(ucontext, infostyle)
- MOVQ 24(SP), DI // saved ucontext
- MOVQ 32(SP), SI // saved infostyle
- SYSCALL
- INT $3 // not reached
-
-TEXT sys·mmap(SB),7,$-8
- MOVQ 8(SP), DI // arg 1 addr
- MOVL 16(SP), SI // arg 2 len
- MOVL 20(SP), DX // arg 3 prot
- MOVL 24(SP), R10 // arg 4 flags
- MOVL 28(SP), R8 // arg 5 fid
- MOVL 32(SP), R9 // arg 6 offset
- MOVL $(0x2000000+197), AX // syscall entry
- SYSCALL
- JCC 2(PC)
- CALL notok(SB)
- RET
-
-TEXT notok(SB),7,$-8
- MOVL $0xf1, BP
- MOVQ BP, (BP)
- RET
-
-TEXT sys·memclr(SB),7,$-8
- MOVQ 8(SP), DI // arg 1 addr
- MOVL 16(SP), CX // arg 2 count
- ADDL $7, CX
- SHRL $3, CX
- MOVQ $0, AX
- CLD
- REP
- STOSQ
- RET
-
-TEXT sys·getcallerpc+0(SB),7,$0
- MOVQ x+0(FP),AX // addr of first arg
- MOVQ -8(AX),AX // get calling pc
- RET
-
-TEXT sys·setcallerpc+0(SB),7,$0
- MOVQ x+0(FP),AX // addr of first arg
- MOVQ x+8(FP), BX
- MOVQ BX, -8(AX) // set calling pc
- RET
-
-TEXT sigaltstack(SB),7,$-8
- MOVQ new+8(SP), DI
- MOVQ old+16(SP), SI
- MOVQ $(0x2000000+53), AX
- SYSCALL
- JCC 2(PC)
- CALL notok(SB)
- RET
-
-// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
-TEXT bsdthread_create(SB),7,$-8
- // Set up arguments to bsdthread_create system call.
- // The ones in quotes pass through to the thread callback
- // uninterpreted, so we can put whatever we want there.
- MOVQ fn+32(SP), DI // "func"
- MOVQ m+16(SP), SI // "arg"
- MOVQ stk+8(SP), DX // stack
- MOVQ g+24(SP), R10 // "pthread"
-// TODO(rsc): why do we get away with 0 flags here but not on 386?
- MOVQ $0, R8 // flags
- MOVQ $(0x2000000+360), AX // bsdthread_create
- SYSCALL
- JCC 2(PC)
- CALL notok(SB)
- RET
-
-// The thread that bsdthread_create creates starts executing here,
-// because we registered this function using bsdthread_register
-// at startup.
-// DI = "pthread" (= g)
-// SI = mach thread port
-// DX = "func" (= fn)
-// CX = "arg" (= m)
-// R8 = stack
-// R9 = flags (= 0)
-// SP = stack - C_64_REDZONE_LEN (= stack - 128)
-TEXT bsdthread_start(SB),7,$-8
- MOVQ CX, R14 // m
- MOVQ DI, R15 // g
- MOVQ SI, 24(R14) // thread port is m->procid
- CALL DX // fn
- CALL exit1(SB)
- RET
-
-// void bsdthread_register(void)
-// registers callbacks for threadstart (see bsdthread_create above
-// and wqthread and pthsize (not used). returns 0 on success.
-TEXT bsdthread_register(SB),7,$-8
- MOVQ $bsdthread_start(SB), DI // threadstart
- MOVQ $0, SI // wqthread, not used by us
- MOVQ $0, DX // pthsize, not used by us
- MOVQ $(0x2000000+366), AX // bsdthread_register
- SYSCALL
- JCC 2(PC)
- CALL notok(SB)
- RET
-
-// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
-
-// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
-TEXT mach_msg_trap(SB),7,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVL 24(SP), R10
- MOVL 28(SP), R8
- MOVL 32(SP), R9
- MOVL 36(SP), R11
- PUSHQ R11 // seventh arg, on stack
- MOVL $(0x1000000+31), AX // mach_msg_trap
- SYSCALL
- POPQ R11
- RET
-
-TEXT mach_task_self(SB),7,$0
- MOVL $(0x1000000+28), AX // task_self_trap
- SYSCALL
- RET
-
-TEXT mach_thread_self(SB),7,$0
- MOVL $(0x1000000+27), AX // thread_self_trap
- SYSCALL
- RET
-
-TEXT mach_reply_port(SB),7,$0
- MOVL $(0x1000000+26), AX // mach_reply_port
- SYSCALL
- RET
-
-// Mach provides trap versions of the semaphore ops,
-// instead of requiring the use of RPC.
-
-// uint32 mach_semaphore_wait(uint32)
-TEXT mach_semaphore_wait(SB),7,$0
- MOVL 8(SP), DI
- MOVL $(0x1000000+36), AX // semaphore_wait_trap
- SYSCALL
- RET
-
-// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
-TEXT mach_semaphore_timedwait(SB),7,$0
- MOVL 8(SP), DI
- MOVL 12(SP), SI
- MOVL 16(SP), DX
- MOVL $(0x1000000+38), AX // semaphore_timedwait_trap
- SYSCALL
- RET
-
-// uint32 mach_semaphore_signal(uint32)
-TEXT mach_semaphore_signal(SB),7,$0
- MOVL 8(SP), DI
- MOVL $(0x1000000+33), AX // semaphore_signal_trap
- SYSCALL
- RET
-
-// uint32 mach_semaphore_signal_all(uint32)
-TEXT mach_semaphore_signal_all(SB),7,$0
- MOVL 8(SP), DI
- MOVL $(0x1000000+34), AX // semaphore_signal_all_trap
- SYSCALL
- RET
-
diff --git a/src/lib/runtime/darwin/defs.c b/src/lib/runtime/darwin/defs.c
deleted file mode 100644
index 1ed662957..000000000
--- a/src/lib/runtime/darwin/defs.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// 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.
- *
- godefs -f -m64 defs.c >amd64/defs.h
- godefs defs.c >386/defs.h
- */
-
-#define __DARWIN_UNIX03 0
-
-#include <mach/mach.h>
-#include <mach/message.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <sys/mman.h>
-
-enum {
- $PROT_NONE = PROT_NONE,
- $PROT_READ = PROT_READ,
- $PROT_WRITE = PROT_WRITE,
- $PROT_EXEC = PROT_EXEC,
-
- $MAP_ANON = MAP_ANON,
- $MAP_PRIVATE = MAP_PRIVATE,
-
- $MACH_MSG_TYPE_MOVE_RECEIVE = MACH_MSG_TYPE_MOVE_RECEIVE,
- $MACH_MSG_TYPE_MOVE_SEND = MACH_MSG_TYPE_MOVE_SEND,
- $MACH_MSG_TYPE_MOVE_SEND_ONCE = MACH_MSG_TYPE_MOVE_SEND_ONCE,
- $MACH_MSG_TYPE_COPY_SEND = MACH_MSG_TYPE_COPY_SEND,
- $MACH_MSG_TYPE_MAKE_SEND = MACH_MSG_TYPE_MAKE_SEND,
- $MACH_MSG_TYPE_MAKE_SEND_ONCE = MACH_MSG_TYPE_MAKE_SEND_ONCE,
- $MACH_MSG_TYPE_COPY_RECEIVE = MACH_MSG_TYPE_COPY_RECEIVE,
-
- $MACH_MSG_PORT_DESCRIPTOR = MACH_MSG_PORT_DESCRIPTOR,
- $MACH_MSG_OOL_DESCRIPTOR = MACH_MSG_OOL_DESCRIPTOR,
- $MACH_MSG_OOL_PORTS_DESCRIPTOR = MACH_MSG_OOL_PORTS_DESCRIPTOR,
- $MACH_MSG_OOL_VOLATILE_DESCRIPTOR = MACH_MSG_OOL_VOLATILE_DESCRIPTOR,
-
- $MACH_MSGH_BITS_COMPLEX = MACH_MSGH_BITS_COMPLEX,
-
- $MACH_SEND_MSG = MACH_SEND_MSG,
- $MACH_RCV_MSG = MACH_RCV_MSG,
- $MACH_RCV_LARGE = MACH_RCV_LARGE,
-
- $MACH_SEND_TIMEOUT = MACH_SEND_TIMEOUT,
- $MACH_SEND_INTERRUPT = MACH_SEND_INTERRUPT,
- $MACH_SEND_CANCEL = MACH_SEND_CANCEL,
- $MACH_SEND_ALWAYS = MACH_SEND_ALWAYS,
- $MACH_SEND_TRAILER = MACH_SEND_TRAILER,
- $MACH_RCV_TIMEOUT = MACH_RCV_TIMEOUT,
- $MACH_RCV_NOTIFY = MACH_RCV_NOTIFY,
- $MACH_RCV_INTERRUPT = MACH_RCV_INTERRUPT,
- $MACH_RCV_OVERWRITE = MACH_RCV_OVERWRITE,
-
- $NDR_PROTOCOL_2_0 = NDR_PROTOCOL_2_0,
- $NDR_INT_BIG_ENDIAN = NDR_INT_BIG_ENDIAN,
- $NDR_INT_LITTLE_ENDIAN = NDR_INT_LITTLE_ENDIAN,
- $NDR_FLOAT_IEEE = NDR_FLOAT_IEEE,
- $NDR_CHAR_ASCII = NDR_CHAR_ASCII,
-
- $SA_SIGINFO = SA_SIGINFO,
- $SA_RESTART = SA_RESTART,
- $SA_ONSTACK = SA_ONSTACK,
- $SA_USERTRAMP = SA_USERTRAMP,
- $SA_64REGSET = SA_64REGSET,
-};
-
-typedef mach_msg_body_t $MachBody;
-typedef mach_msg_header_t $MachHeader;
-typedef NDR_record_t $MachNDR;
-typedef mach_msg_port_descriptor_t $MachPort;
-
-typedef stack_t $StackT;
-typedef union __sigaction_u $Sighandler;
-
-typedef struct __sigaction $Sigaction; // used in syscalls
-// typedef struct sigaction $Sigaction; // used by the C library
-typedef union sigval $Sigval;
-typedef siginfo_t $Siginfo;
-
-typedef struct fp_control $FPControl;
-typedef struct fp_status $FPStatus;
-typedef struct mmst_reg $RegMMST;
-typedef struct xmm_reg $RegXMM;
-
-#ifdef __LP64__
-// amd64
-typedef x86_thread_state64_t $Regs;
-typedef x86_float_state64_t $FloatState;
-typedef x86_exception_state64_t $ExceptionState;
-typedef struct mcontext64 $Mcontext;
-#else
-// 386
-typedef x86_thread_state32_t $Regs;
-typedef x86_float_state32_t $FloatState;
-typedef x86_exception_state32_t $ExceptionState;
-typedef struct mcontext32 $Mcontext;
-#endif
-
-typedef ucontext_t $Ucontext;
diff --git a/src/lib/runtime/darwin/os.h b/src/lib/runtime/darwin/os.h
deleted file mode 100644
index 2a3ca87bd..000000000
--- a/src/lib/runtime/darwin/os.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-void bsdthread_create(void*, M*, G*, void(*)(void));
-void bsdthread_register(void);
-int32 mach_msg_trap(MachHeader*, int32, uint32, uint32, uint32, uint32, uint32);
-uint32 mach_reply_port(void);
-void mach_semacquire(uint32);
-uint32 mach_semcreate(void);
-void mach_semdestroy(uint32);
-void mach_semrelease(uint32);
-void mach_semreset(uint32);
-uint32 mach_task_self(void);
-uint32 mach_task_self(void);
-uint32 mach_thread_self(void);
-uint32 mach_thread_self(void);
-
-struct Sigaction;
-void sigaction(int64, struct Sigaction*, struct Sigaction*);
-
-struct StackT;
-void sigaltstack(struct StackT*, struct StackT*);
-void sigtramp(void);
diff --git a/src/lib/runtime/darwin/signals.h b/src/lib/runtime/darwin/signals.h
deleted file mode 100644
index 4051dc4dc..000000000
--- a/src/lib/runtime/darwin/signals.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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.
-
-
-#define C SigCatch
-#define I SigIgnore
-#define R SigRestart
-
-static SigTab sigtab[] = {
- /* 0 */ 0, "SIGNONE: no trap",
- /* 1 */ 0, "SIGHUP: terminal line hangup",
- /* 2 */ 0, "SIGINT: interrupt",
- /* 3 */ C, "SIGQUIT: quit",
- /* 4 */ C, "SIGILL: illegal instruction",
- /* 5 */ C, "SIGTRAP: trace trap", /* used by panic and array out of bounds, etc. */
- /* 6 */ C, "SIGABRT: abort",
- /* 7 */ C, "SIGEMT: emulate instruction executed",
- /* 8 */ C, "SIGFPE: floating-point exception",
- /* 9 */ 0, "SIGKILL: kill",
- /* 10 */ C, "SIGBUS: bus error",
- /* 11 */ C, "SIGSEGV: segmentation violation",
- /* 12 */ C, "SIGSYS: bad system call",
- /* 13 */ I, "SIGPIPE: write to broken pipe",
- /* 14 */ 0, "SIGALRM: alarm clock",
- /* 15 */ 0, "SIGTERM: termination",
- /* 16 */ 0, "SIGURG: urgent condition on socket",
- /* 17 */ 0, "SIGSTOP: stop",
- /* 18 */ 0, "SIGTSTP: keyboard stop",
- /* 19 */ 0, "SIGCONT: continue after stop",
- /* 20 */ I+R, "SIGCHLD: child status has changed",
- /* 21 */ 0, "SIGTTIN: background read from tty",
- /* 22 */ 0, "SIGTTOU: background write to tty",
- /* 23 */ 0, "SIGIO: i/o now possible",
- /* 24 */ 0, "SIGXCPU: cpu limit exceeded",
- /* 25 */ 0, "SIGXFSZ: file size limit exceeded",
- /* 26 */ 0, "SIGVTALRM: virtual alarm clock",
- /* 27 */ 0, "SIGPROF: profiling alarm clock",
- /* 28 */ I+R, "SIGWINCH: window size change",
- /* 29 */ 0, "SIGINFO: status request from keyboard",
- /* 30 */ 0, "SIGUSR1: user-defined signal 1",
- /* 31 */ 0, "SIGUSR2: user-defined signal 2",
-};
-#undef C
-#undef I
-#undef R
-
-#define NSIG 32
diff --git a/src/lib/runtime/darwin/thread.c b/src/lib/runtime/darwin/thread.c
deleted file mode 100644
index 3a982471a..000000000
--- a/src/lib/runtime/darwin/thread.c
+++ /dev/null
@@ -1,441 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-
-static void
-unimplemented(int8 *name)
-{
- prints(name);
- prints(" not implemented\n");
- *(int32*)1231 = 1231;
-}
-
-// Thread-safe allocation of a semaphore.
-// Psema points at a kernel semaphore key.
-// It starts out zero, meaning no semaphore.
-// Fill it in, being careful of others calling initsema
-// simultaneously.
-static void
-initsema(uint32 *psema)
-{
- uint32 sema;
-
- if(*psema != 0) // already have one
- return;
-
- sema = mach_semcreate();
- if(!cas(psema, 0, sema)){
- // Someone else filled it in. Use theirs.
- mach_semdestroy(sema);
- return;
- }
-}
-
-
-// Atomic add and return new value.
-static uint32
-xadd(uint32 volatile *val, int32 delta)
-{
- uint32 oval, nval;
-
- for(;;){
- oval = *val;
- nval = oval + delta;
- if(cas(val, oval, nval))
- return nval;
- }
-}
-
-
-// Blocking locks.
-
-// Implement Locks, using semaphores.
-// l->key is the number of threads who want the lock.
-// In a race, one thread increments l->key from 0 to 1
-// and the others increment it from >0 to >1. The thread
-// who does the 0->1 increment gets the lock, and the
-// others wait on the semaphore. When the 0->1 thread
-// releases the lock by decrementing l->key, l->key will
-// be >0, so it will increment the semaphore to wake up
-// one of the others. This is the same algorithm used
-// in Plan 9's user-level locks.
-//
-// Note that semaphores are never destroyed (the kernel
-// will clean up when the process exits). We assume for now
-// that Locks are only used for long-lived structures like M and G.
-
-void
-lock(Lock *l)
-{
- if(m->locks < 0)
- throw("lock count");
- m->locks++;
-
- // Allocate semaphore if needed.
- if(l->sema == 0)
- initsema(&l->sema);
-
- if(xadd(&l->key, 1) > 1) // someone else has it; wait
- mach_semacquire(l->sema);
-}
-
-void
-unlock(Lock *l)
-{
- m->locks--;
- if(m->locks < 0)
- throw("lock count");
-
- if(xadd(&l->key, -1) > 0) // someone else is waiting
- mach_semrelease(l->sema);
-}
-
-
-// User-level semaphore implementation:
-// try to do the operations in user space on u,
-// but when it's time to block, fall back on the kernel semaphore k.
-// This is the same algorithm used in Plan 9.
-void
-usemacquire(Usema *s)
-{
- if((int32)xadd(&s->u, -1) < 0)
- mach_semacquire(s->k);
-}
-
-void
-usemrelease(Usema *s)
-{
- if((int32)xadd(&s->u, 1) <= 0)
- mach_semrelease(s->k);
-}
-
-
-// Event notifications.
-void
-noteclear(Note *n)
-{
- n->wakeup = 0;
-}
-
-void
-notesleep(Note *n)
-{
- if(n->sema.k == 0)
- initsema(&n->sema.k);
- while(!n->wakeup)
- usemacquire(&n->sema);
-}
-
-void
-notewakeup(Note *n)
-{
- if(n->sema.k == 0)
- initsema(&n->sema.k);
- n->wakeup = 1;
- usemrelease(&n->sema);
-}
-
-
-// BSD interface for threading.
-void
-osinit(void)
-{
- // Register our thread-creation callback (see {amd64,386}/sys.s).
- bsdthread_register();
-}
-
-void
-newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
- // printf("newosproc m=%p g=%p stk=%p fn=%p\n", m, g, stk, fn);
- m->tls[0] = m->id; // so 386 asm can find it
- bsdthread_create(stk, m, g, fn);
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-minit(void)
-{
- // Initialize signal handling.
- m->gsignal = malg(32*1024); // OS X wants >=8K, Linux >=2K
- signalstack(m->gsignal->stackguard, 32*1024);
-}
-
-// Mach IPC, to get at semaphores
-// Definitions are in /usr/include/mach on a Mac.
-
-static void
-macherror(int32 r, int8 *fn)
-{
- printf("mach error %s: %d\n", fn, r);
- throw("mach error");
-}
-
-enum
-{
- DebugMach = 0
-};
-
-static MachNDR zerondr;
-
-#define MACH_MSGH_BITS(a, b) ((a) | ((b)<<8))
-
-static int32
-mach_msg(MachHeader *h,
- int32 op,
- uint32 send_size,
- uint32 rcv_size,
- uint32 rcv_name,
- uint32 timeout,
- uint32 notify)
-{
- // TODO: Loop on interrupt.
- return mach_msg_trap(h, op, send_size, rcv_size, rcv_name, timeout, notify);
-}
-
-// Mach RPC (MIG)
-
-enum
-{
- MinMachMsg = 48,
- Reply = 100,
-};
-
-#pragma pack on
-typedef struct CodeMsg CodeMsg;
-struct CodeMsg
-{
- MachHeader h;
- MachNDR NDR;
- int32 code;
-};
-#pragma pack off
-
-static int32
-machcall(MachHeader *h, int32 maxsize, int32 rxsize)
-{
- uint32 *p;
- int32 i, ret, id;
- uint32 port;
- CodeMsg *c;
-
- if((port = m->machport) == 0){
- port = mach_reply_port();
- m->machport = port;
- }
-
- h->msgh_bits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
- h->msgh_local_port = port;
- h->msgh_reserved = 0;
- id = h->msgh_id;
-
- if(DebugMach){
- p = (uint32*)h;
- prints("send:\t");
- for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
- prints(" ");
- sys·printpointer((void*)p[i]);
- if(i%8 == 7)
- prints("\n\t");
- }
- if(i%8)
- prints("\n");
- }
-
- ret = mach_msg(h, MACH_SEND_MSG|MACH_RCV_MSG,
- h->msgh_size, maxsize, port, 0, 0);
- if(ret != 0){
- if(DebugMach){
- prints("mach_msg error ");
- sys·printint(ret);
- prints("\n");
- }
- return ret;
- }
-
- if(DebugMach){
- p = (uint32*)h;
- prints("recv:\t");
- for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
- prints(" ");
- sys·printpointer((void*)p[i]);
- if(i%8 == 7)
- prints("\n\t");
- }
- if(i%8)
- prints("\n");
- }
-
- if(h->msgh_id != id+Reply){
- if(DebugMach){
- prints("mach_msg reply id mismatch ");
- sys·printint(h->msgh_id);
- prints(" != ");
- sys·printint(id+Reply);
- prints("\n");
- }
- return -303; // MIG_REPLY_MISMATCH
- }
-
- // Look for a response giving the return value.
- // Any call can send this back with an error,
- // and some calls only have return values so they
- // send it back on success too. I don't quite see how
- // you know it's one of these and not the full response
- // format, so just look if the message is right.
- c = (CodeMsg*)h;
- if(h->msgh_size == sizeof(CodeMsg)
- && !(h->msgh_bits & MACH_MSGH_BITS_COMPLEX)){
- if(DebugMach){
- prints("mig result ");
- sys·printint(c->code);
- prints("\n");
- }
- return c->code;
- }
-
- if(h->msgh_size != rxsize){
- if(DebugMach){
- prints("mach_msg reply size mismatch ");
- sys·printint(h->msgh_size);
- prints(" != ");
- sys·printint(rxsize);
- prints("\n");
- }
- return -307; // MIG_ARRAY_TOO_LARGE
- }
-
- return 0;
-}
-
-
-// Semaphores!
-
-enum
-{
- Tmach_semcreate = 3418,
- Rmach_semcreate = Tmach_semcreate + Reply,
-
- Tmach_semdestroy = 3419,
- Rmach_semdestroy = Tmach_semdestroy + Reply,
-
- // Mach calls that get interrupted by Unix signals
- // return this error code. We retry them.
- KERN_ABORTED = 14,
-};
-
-typedef struct Tmach_semcreateMsg Tmach_semcreateMsg;
-typedef struct Rmach_semcreateMsg Rmach_semcreateMsg;
-typedef struct Tmach_semdestroyMsg Tmach_semdestroyMsg;
-// Rmach_semdestroyMsg = CodeMsg
-
-#pragma pack on
-struct Tmach_semcreateMsg
-{
- MachHeader h;
- MachNDR ndr;
- int32 policy;
- int32 value;
-};
-
-struct Rmach_semcreateMsg
-{
- MachHeader h;
- MachBody body;
- MachPort semaphore;
-};
-
-struct Tmach_semdestroyMsg
-{
- MachHeader h;
- MachBody body;
- MachPort semaphore;
-};
-#pragma pack off
-
-uint32
-mach_semcreate(void)
-{
- union {
- Tmach_semcreateMsg tx;
- Rmach_semcreateMsg rx;
- uint8 pad[MinMachMsg];
- } m;
- int32 r;
-
- m.tx.h.msgh_bits = 0;
- m.tx.h.msgh_size = sizeof(m.tx);
- m.tx.h.msgh_remote_port = mach_task_self();
- m.tx.h.msgh_id = Tmach_semcreate;
- m.tx.ndr = zerondr;
-
- m.tx.policy = 0; // 0 = SYNC_POLICY_FIFO
- m.tx.value = 0;
-
- while((r = machcall(&m.tx.h, sizeof m, sizeof(m.rx))) != 0){
- if(r == KERN_ABORTED) // interrupted
- continue;
- macherror(r, "semaphore_create");
- }
- if(m.rx.body.msgh_descriptor_count != 1)
- unimplemented("mach_semcreate desc count");
- return m.rx.semaphore.name;
-}
-
-void
-mach_semdestroy(uint32 sem)
-{
- union {
- Tmach_semdestroyMsg tx;
- uint8 pad[MinMachMsg];
- } m;
- int32 r;
-
- m.tx.h.msgh_bits = MACH_MSGH_BITS_COMPLEX;
- m.tx.h.msgh_size = sizeof(m.tx);
- m.tx.h.msgh_remote_port = mach_task_self();
- m.tx.h.msgh_id = Tmach_semdestroy;
- m.tx.body.msgh_descriptor_count = 1;
- m.tx.semaphore.name = sem;
- m.tx.semaphore.disposition = MACH_MSG_TYPE_MOVE_SEND;
- m.tx.semaphore.type = 0;
-
- while((r = machcall(&m.tx.h, sizeof m, 0)) != 0){
- macherror(r, "semaphore_destroy");
- }
-}
-
-// The other calls have simple system call traps in sys.s
-int32 mach_semaphore_wait(uint32 sema);
-int32 mach_semaphore_timedwait(uint32 sema, uint32 sec, uint32 nsec);
-int32 mach_semaphore_signal(uint32 sema);
-int32 mach_semaphore_signal_all(uint32 sema);
-
-void
-mach_semacquire(uint32 sem)
-{
- int32 r;
-
- while((r = mach_semaphore_wait(sem)) != 0) {
- if(r == KERN_ABORTED) // interrupted
- continue;
- macherror(r, "semaphore_wait");
- }
-}
-
-void
-mach_semrelease(uint32 sem)
-{
- int32 r;
-
- while((r = mach_semaphore_signal(sem)) != 0) {
- if(r == KERN_ABORTED) // interrupted
- continue;
- macherror(r, "semaphore_signal");
- }
-}
-
diff --git a/src/lib/runtime/extern.go b/src/lib/runtime/extern.go
deleted file mode 100644
index 6fb5756d6..000000000
--- a/src/lib/runtime/extern.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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 runtime package contains operations that interact with Go's runtime system,
- such as functions to control goroutines.
- */
-package runtime
-
-// These functions are implemented in the base runtime library, ../../runtime/.
-
-// Gosched yields the processor, allowing other goroutines to run. It does not
-// suspend the current goroutine, so execution resumes automatically.
-func Gosched()
-
-// Goexit terminates the goroutine that calls it. No other goroutine is affected.
-func Goexit()
-
-// Breakpoint() executes a breakpoint trap.
-func Breakpoint()
-
-// Caller reports file and line number information about function invocations on
-// the calling goroutine's stack. The argument is the number of stack frames to
-// ascend, with 1 identifying the the caller of Caller. The return values report the
-// program counter, file name, and line number within the file of the corresponding
-// call. The boolean ok is false if it was not possible to recover the information.
-func Caller(n int) (pc uintptr, file string, line int, ok bool)
diff --git a/src/lib/runtime/float.c b/src/lib/runtime/float.c
deleted file mode 100644
index 5122f359a..000000000
--- a/src/lib/runtime/float.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-static uint64 uvnan = 0x7FF0000000000001ULL;
-static uint64 uvinf = 0x7FF0000000000000ULL;
-static uint64 uvneginf = 0xFFF0000000000000ULL;
-
-uint32
-float32tobits(float32 f)
-{
- // The obvious cast-and-pointer code is technically
- // not valid, and gcc miscompiles it. Use a union instead.
- union {
- float32 f;
- uint32 i;
- } u;
- u.f = f;
- return u.i;
-}
-
-uint64
-float64tobits(float64 f)
-{
- // The obvious cast-and-pointer code is technically
- // not valid, and gcc miscompiles it. Use a union instead.
- union {
- float64 f;
- uint64 i;
- } u;
- u.f = f;
- return u.i;
-}
-
-float64
-float64frombits(uint64 i)
-{
- // The obvious cast-and-pointer code is technically
- // not valid, and gcc miscompiles it. Use a union instead.
- union {
- float64 f;
- uint64 i;
- } u;
- u.i = i;
- return u.f;
-}
-
-float32
-float32frombits(uint32 i)
-{
- // The obvious cast-and-pointer code is technically
- // not valid, and gcc miscompiles it. Use a union instead.
- union {
- float32 f;
- uint32 i;
- } u;
- u.i = i;
- return u.f;
-}
-
-bool
-isInf(float64 f, int32 sign)
-{
- uint64 x;
-
- x = float64tobits(f);
- if(sign == 0)
- return x == uvinf || x == uvneginf;
- if(sign > 0)
- return x == uvinf;
- return x == uvneginf;
-}
-
-float64
-NaN(void)
-{
- return float64frombits(uvnan);
-}
-
-bool
-isNaN(float64 f)
-{
- uint64 x;
-
- x = float64tobits(f);
- return ((uint32)(x>>52) & 0x7FF) == 0x7FF && !isInf(f, 0);
-}
-
-float64
-Inf(int32 sign)
-{
- if(sign >= 0)
- return float64frombits(uvinf);
- else
- return float64frombits(uvneginf);
-}
-
-enum
-{
- MASK = 0x7ffL,
- SHIFT = 64-11-1,
- BIAS = 1022L,
-};
-
-float64
-frexp(float64 d, int32 *ep)
-{
- uint64 x;
-
- if(d == 0) {
- *ep = 0;
- return 0;
- }
- x = float64tobits(d);
- *ep = (int32)((x >> SHIFT) & MASK) - BIAS;
- x &= ~((uint64)MASK << SHIFT);
- x |= (uint64)BIAS << SHIFT;
- return float64frombits(x);
-}
-
-float64
-ldexp(float64 d, int32 e)
-{
- uint64 x;
-
- if(d == 0)
- return 0;
- x = float64tobits(d);
- e += (int32)(x >> SHIFT) & MASK;
- if(e <= 0)
- return 0; /* underflow */
- if(e >= MASK){ /* overflow */
- if(d < 0)
- return Inf(-1);
- return Inf(1);
- }
- x &= ~((uint64)MASK << SHIFT);
- x |= (uint64)e << SHIFT;
- return float64frombits(x);
-}
-
-float64
-modf(float64 d, float64 *ip)
-{
- float64 dd;
- uint64 x;
- int32 e;
-
- if(d < 1) {
- if(d < 0) {
- d = modf(-d, ip);
- *ip = -*ip;
- return -d;
- }
- *ip = 0;
- return d;
- }
-
- x = float64tobits(d);
- e = (int32)((x >> SHIFT) & MASK) - BIAS;
-
- /*
- * Keep the top 11+e bits; clear the rest.
- */
- if(e <= 64-11)
- x &= ~(((uint64)1 << (64LL-11LL-e))-1);
- dd = float64frombits(x);
- *ip = dd;
- return d - dd;
-}
-
diff --git a/src/lib/runtime/float_go.cgo b/src/lib/runtime/float_go.cgo
deleted file mode 100644
index 518d55950..000000000
--- a/src/lib/runtime/float_go.cgo
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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 math
-
-#include "runtime.h"
-
-func Frexp(f float64) (frac float64, exp int32) {
- frac = frexp(f, &exp);
-}
-
-func Ldexp(frac float64, exp int32) (f float64) {
- f = ldexp(frac, exp);
-}
-
-func Modf(f float64) (integer float64, frac float64) {
- frac = modf(f, &integer);
-}
-
-func IsInf(f float64, sign int32) (is bool) {
- is = isInf(f, sign);
-}
-
-func IsNaN(f float64) (is bool) {
- is = isNaN(f);
-}
-
-func Inf(sign int32) (f float64) {
- f = Inf(sign);
-}
-
-func NaN() (f float64) {
- f = NaN();
-}
-
-func Float32bits(f float32) (b uint32) {
- b = float32tobits(f);
-}
-
-func Float64bits(f float64) (b uint64) {
- b = float64tobits(f);
-}
-
-func Float32frombits(b uint32) (f float32) {
- f = float32frombits(b);
-}
-
-func Float64frombits(b uint64) (f float64) {
- f = float64frombits(b);
-}
-
diff --git a/src/lib/runtime/hashmap.c b/src/lib/runtime/hashmap.c
deleted file mode 100644
index b3022ca14..000000000
--- a/src/lib/runtime/hashmap.c
+++ /dev/null
@@ -1,954 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "hashmap.h"
-
-/* Return a pointer to the struct/union of type "type"
- whose "field" field is addressed by pointer "p". */
-
-
-struct hash { /* a hash table; initialize with hash_init() */
- uint32 count; /* elements in table - must be first */
-
- uint8 datasize; /* amount of data to store in entry */
- uint8 max_power; /* max power of 2 to create sub-tables */
- uint8 max_probes; /* max entries to probe before rehashing */
- int32 changes; /* inc'ed whenever a subtable is created/grown */
- hash_hash_t (*data_hash) (uint32, void *a); /* return hash of *a */
- uint32 (*data_eq) (uint32, void *a, void *b); /* return whether *a == *b */
- void (*data_del) (uint32, void *arg, void *data); /* invoked on deletion */
- struct hash_subtable *st; /* first-level table */
-
- uint32 keysize;
- uint32 valsize;
- uint32 datavo;
- uint32 ko;
- uint32 vo;
- uint32 po;
- Alg* keyalg;
- Alg* valalg;
-};
-
-struct hash_entry {
- hash_hash_t hash; /* hash value of data */
- byte data[1]; /* user data has "datasize" bytes */
-};
-
-struct hash_subtable {
- uint8 power; /* bits used to index this table */
- uint8 used; /* bits in hash used before reaching this table */
- uint8 datasize; /* bytes of client data in an entry */
- uint8 max_probes; /* max number of probes when searching */
- int16 limit_bytes; /* max_probes * (datasize+sizeof (hash_hash_t)) */
- struct hash_entry *end; /* points just past end of entry[] */
- struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsize bytes */
-};
-
-#define HASH_DATA_EQ(h,x,y) ((*h->data_eq) (h->keysize, (x), (y)))
-
-#define HASH_REHASH 0x2 /* an internal flag */
-/* the number of bits used is stored in the flags word too */
-#define HASH_USED(x) ((x) >> 2)
-#define HASH_MAKE_USED(x) ((x) << 2)
-
-#define HASH_LOW 6
-#define HASH_ONE (((hash_hash_t)1) << HASH_LOW)
-#define HASH_MASK (HASH_ONE - 1)
-#define HASH_ADJUST(x) (((x) < HASH_ONE) << HASH_LOW)
-
-#define HASH_BITS (sizeof (hash_hash_t) * 8)
-
-#define HASH_SUBHASH HASH_MASK
-#define HASH_NIL 0
-#define HASH_NIL_MEMSET 0
-
-#define HASH_OFFSET(base, byte_offset) \
- ((struct hash_entry *) (((byte *) (base)) + (byte_offset)))
-
-
-/* return a hash layer with 2**power empty entries */
-static struct hash_subtable *
-hash_subtable_new (struct hash *h, int32 power, int32 used)
-{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- int32 bytes = elemsize << power;
- struct hash_subtable *st;
- int32 limit_bytes = h->max_probes * elemsize;
- int32 max_probes = h->max_probes;
-
- if (bytes < limit_bytes) {
- limit_bytes = bytes;
- max_probes = 1 << power;
- }
- bytes += limit_bytes - elemsize;
- st = malloc (offsetof (struct hash_subtable, entry[0]) + bytes);
- st->power = power;
- st->used = used;
- st->datasize = h->datasize;
- st->max_probes = max_probes;
- st->limit_bytes = limit_bytes;
- st->end = HASH_OFFSET (st->entry, bytes);
- memset (st->entry, HASH_NIL_MEMSET, bytes);
- return (st);
-}
-
-static void
-init_sizes (int64 hint, int32 *init_power, int32 *max_power)
-{
- int32 log = 0;
- int32 i;
-
- for (i = 32; i != 0; i >>= 1) {
- if ((hint >> (log + i)) != 0) {
- log += i;
- }
- }
- log += 1 + (((hint << 3) >> log) >= 11); /* round up for utilization */
- if (log <= 14) {
- *init_power = log;
- } else {
- *init_power = 12;
- }
- *max_power = 12;
-}
-
-static void
-hash_init (struct hash *h,
- int32 datasize,
- hash_hash_t (*data_hash) (uint32, void *),
- uint32 (*data_eq) (uint32, void *, void *),
- void (*data_del) (uint32, void *, void *),
- int64 hint)
-{
- int32 init_power;
- int32 max_power;
-
- if(datasize < sizeof (void *))
- datasize = sizeof (void *);
- datasize = rnd(datasize, sizeof (void *));
- init_sizes (hint, &init_power, &max_power);
- h->datasize = datasize;
- h->max_power = max_power;
- h->max_probes = 15;
- assert (h->datasize == datasize);
- assert (h->max_power == max_power);
- assert (sizeof (void *) <= h->datasize || h->max_power == 255);
- h->count = 0;
- h->changes = 0;
- h->data_hash = data_hash;
- h->data_eq = data_eq;
- h->data_del = data_del;
- h->st = hash_subtable_new (h, init_power, 0);
-}
-
-static void
-hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
-{
- int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
- struct hash_entry *src_e = HASH_OFFSET (dst_e, n * elemsize);
- struct hash_entry *end_e = st->end;
- int32 shift = HASH_BITS - (st->power + st->used);
- int32 index_mask = (((hash_hash_t)1) << st->power) - 1;
- int32 dst_i = (((byte *) dst_e) - ((byte *) st->entry)) / elemsize;
- int32 src_i = dst_i + n;
- hash_hash_t hash;
- int32 skip;
- int32 bytes;
-
- while (dst_e != src_e) {
- if (src_e != end_e) {
- struct hash_entry *cp_e = src_e;
- int32 save_dst_i = dst_i;
- while (cp_e != end_e && (hash = cp_e->hash) != HASH_NIL &&
- ((hash >> shift) & index_mask) <= dst_i) {
- cp_e = HASH_OFFSET (cp_e, elemsize);
- dst_i++;
- }
- bytes = ((byte *) cp_e) - (byte *) src_e;
- memmove (dst_e, src_e, bytes);
- dst_e = HASH_OFFSET (dst_e, bytes);
- src_e = cp_e;
- src_i += dst_i - save_dst_i;
- if (src_e != end_e && (hash = src_e->hash) != HASH_NIL) {
- skip = ((hash >> shift) & index_mask) - dst_i;
- } else {
- skip = src_i - dst_i;
- }
- } else {
- skip = src_i - dst_i;
- }
- bytes = skip * elemsize;
- memset (dst_e, HASH_NIL_MEMSET, bytes);
- dst_e = HASH_OFFSET (dst_e, bytes);
- dst_i += skip;
- }
-}
-
-static int32
-hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
- struct hash *h, void *data, void **pres);
-
-static void
-hash_conv (struct hash *h,
- struct hash_subtable *st, int32 flags,
- hash_hash_t hash,
- struct hash_entry *e)
-{
- int32 new_flags = (flags + HASH_MAKE_USED (st->power)) | HASH_REHASH;
- int32 shift = HASH_BITS - HASH_USED (new_flags);
- hash_hash_t prefix_mask = (-(hash_hash_t)1) << shift;
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- void *dummy_result;
- struct hash_entry *de;
- int32 index_mask = (1 << st->power) - 1;
- hash_hash_t e_hash;
- struct hash_entry *pe = HASH_OFFSET (e, -elemsize);
-
- while (e != st->entry && (e_hash = pe->hash) != HASH_NIL && (e_hash & HASH_MASK) != HASH_SUBHASH) {
- e = pe;
- pe = HASH_OFFSET (pe, -elemsize);
- }
-
- de = e;
- while (e != st->end &&
- (e_hash = e->hash) != HASH_NIL &&
- (e_hash & HASH_MASK) != HASH_SUBHASH) {
- struct hash_entry *target_e = HASH_OFFSET (st->entry, ((e_hash >> shift) & index_mask) * elemsize);
- struct hash_entry *ne = HASH_OFFSET (e, elemsize);
- hash_hash_t current = e_hash & prefix_mask;
- if (de < target_e) {
- memset (de, HASH_NIL_MEMSET, ((byte *) target_e) - (byte *) de);
- de = target_e;
- }
- if ((hash & prefix_mask) == current ||
- (ne != st->end && (e_hash = ne->hash) != HASH_NIL &&
- (e_hash & prefix_mask) == current)) {
- struct hash_subtable *new_st = hash_subtable_new (h, 1, HASH_USED (new_flags));
- int32 rc = hash_insert_internal (&new_st, new_flags, e->hash, h, e->data, &dummy_result);
- assert (rc == 0);
- memcpy(dummy_result, e->data, h->datasize);
- e = ne;
- while (e != st->end && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
- assert ((e_hash & HASH_MASK) != HASH_SUBHASH);
- rc = hash_insert_internal (&new_st, new_flags, e_hash, h, e->data, &dummy_result);
- assert (rc == 0);
- memcpy(dummy_result, e->data, h->datasize);
- e = HASH_OFFSET (e, elemsize);
- }
- memset (de->data, HASH_NIL_MEMSET, h->datasize);
- *(struct hash_subtable **)de->data = new_st;
- de->hash = current | HASH_SUBHASH;
- } else {
- if (e != de) {
- memcpy (de, e, elemsize);
- }
- e = HASH_OFFSET (e, elemsize);
- }
- de = HASH_OFFSET (de, elemsize);
- }
- if (e != de) {
- hash_remove_n (st, de, (((byte *) e) - (byte *) de) / elemsize);
- }
-}
-
-static void
-hash_grow (struct hash *h, struct hash_subtable **pst, int32 flags)
-{
- struct hash_subtable *old_st = *pst;
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- *pst = hash_subtable_new (h, old_st->power + 1, HASH_USED (flags));
- struct hash_entry *end_e = old_st->end;
- struct hash_entry *e;
- void *dummy_result;
- int32 used = 0;
-
- flags |= HASH_REHASH;
- for (e = old_st->entry; e != end_e; e = HASH_OFFSET (e, elemsize)) {
- hash_hash_t hash = e->hash;
- if (hash != HASH_NIL) {
- int32 rc = hash_insert_internal (pst, flags, e->hash, h, e->data, &dummy_result);
- assert (rc == 0);
- memcpy(dummy_result, e->data, h->datasize);
- used++;
- }
- }
- free (old_st);
-}
-
-int32
-hash_lookup (struct hash *h, void *data, void **pres)
-{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK;
- struct hash_subtable *st = h->st;
- int32 used = 0;
- hash_hash_t e_hash;
- struct hash_entry *e;
- struct hash_entry *end_e;
-
- hash += HASH_ADJUST (hash);
- for (;;) {
- int32 shift = HASH_BITS - (st->power + used);
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (hash >> shift) & index_mask; /* i is the natural position of hash */
-
- e = HASH_OFFSET (st->entry, i * elemsize); /* e points to element i */
- e_hash = e->hash;
- if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable */
- break;
- }
- used += st->power;
- st = *(struct hash_subtable **)e->data;
- }
- end_e = HASH_OFFSET (e, st->limit_bytes);
- while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
- e = HASH_OFFSET (e, elemsize);
- }
- while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
- if (HASH_DATA_EQ (h, data, e->data)) { /* a match */
- *pres = e->data;
- return (1);
- }
- e = HASH_OFFSET (e, elemsize);
- }
- USED(e_hash);
- *pres = 0;
- return (0);
-}
-
-int32
-hash_remove (struct hash *h, void *data, void *arg)
-{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK;
- struct hash_subtable *st = h->st;
- int32 used = 0;
- hash_hash_t e_hash;
- struct hash_entry *e;
- struct hash_entry *end_e;
-
- hash += HASH_ADJUST (hash);
- for (;;) {
- int32 shift = HASH_BITS - (st->power + used);
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (hash >> shift) & index_mask; /* i is the natural position of hash */
-
- e = HASH_OFFSET (st->entry, i * elemsize); /* e points to element i */
- e_hash = e->hash;
- if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable */
- break;
- }
- used += st->power;
- st = *(struct hash_subtable **)e->data;
- }
- end_e = HASH_OFFSET (e, st->limit_bytes);
- while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
- e = HASH_OFFSET (e, elemsize);
- }
- while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
- if (HASH_DATA_EQ (h, data, e->data)) { /* a match */
- (*h->data_del) (h->keysize, arg, e->data);
- hash_remove_n (st, e, 1);
- h->count--;
- return (1);
- }
- e = HASH_OFFSET (e, elemsize);
- }
- USED(e_hash);
- return (0);
-}
-
-static int32
-hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
- struct hash *h, void *data, void **pres)
-{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
-
- if ((flags & HASH_REHASH) == 0) {
- hash += HASH_ADJUST (hash);
- hash &= ~HASH_MASK;
- }
- for (;;) {
- struct hash_subtable *st = *pst;
- int32 shift = HASH_BITS - (st->power + HASH_USED (flags));
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (hash >> shift) & index_mask; /* i is the natural position of hash */
- struct hash_entry *start_e =
- HASH_OFFSET (st->entry, i * elemsize); /* start_e is the pointer to element i */
- struct hash_entry *e = start_e; /* e is going to range over [start_e, end_e) */
- struct hash_entry *end_e;
- hash_hash_t e_hash = e->hash;
-
- if ((e_hash & HASH_MASK) == HASH_SUBHASH) { /* a subtable */
- pst = (struct hash_subtable **) e->data;
- flags += HASH_MAKE_USED (st->power);
- continue;
- }
- end_e = HASH_OFFSET (start_e, st->limit_bytes);
- while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
- e = HASH_OFFSET (e, elemsize);
- i++;
- }
- if (e != end_e && e_hash != HASH_NIL) {
- /* ins_e ranges over the elements that may match */
- struct hash_entry *ins_e = e;
- int32 ins_i = i;
- hash_hash_t ins_e_hash;
- while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) {
- if (HASH_DATA_EQ (h, data, ins_e->data)) { /* a match */
- *pres = ins_e->data;
- return (1);
- }
- assert (e_hash != hash || (flags & HASH_REHASH) == 0);
- hash += (e_hash == hash); /* adjust hash if it collides */
- ins_e = HASH_OFFSET (ins_e, elemsize);
- ins_i++;
- if (e_hash <= hash) { /* set e to insertion point */
- e = ins_e;
- i = ins_i;
- }
- }
- /* set ins_e to the insertion point for the new element */
- ins_e = e;
- ins_i = i;
- ins_e_hash = 0;
- /* move ins_e to point at the end of the contiguous block, but
- stop if any element can't be moved by one up */
- while (ins_e != st->end && (ins_e_hash = ins_e->hash) != HASH_NIL &&
- ins_i + 1 - ((ins_e_hash >> shift) & index_mask) < st->max_probes &&
- (ins_e_hash & HASH_MASK) != HASH_SUBHASH) {
- ins_e = HASH_OFFSET (ins_e, elemsize);
- ins_i++;
- }
- if (e == end_e || ins_e == st->end || ins_e_hash != HASH_NIL) {
- e = end_e; /* can't insert; must grow or convert to subtable */
- } else { /* make space for element */
- memmove (HASH_OFFSET (e, elemsize), e, ((byte *) ins_e) - (byte *) e);
- }
- }
- if (e != end_e) {
- e->hash = hash;
- *pres = e->data;
- return (0);
- }
- h->changes++;
- if (st->power < h->max_power) {
- hash_grow (h, pst, flags);
- } else {
- hash_conv (h, st, flags, hash, start_e);
- }
- }
-}
-
-int32
-hash_insert (struct hash *h, void *data, void **pres)
-{
- int32 rc = hash_insert_internal (&h->st, 0, (*h->data_hash) (h->keysize, data), h, data, pres);
-
- h->count += (rc == 0); /* increment count if element didn't previously exist */
- return (rc);
-}
-
-uint32
-hash_count (struct hash *h)
-{
- return (h->count);
-}
-
-static void
-iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
-{
- int32 elemsize = it->elemsize;
- hash_hash_t last_hash = it->last_hash;
- struct hash_entry *e;
- hash_hash_t e_hash;
- struct hash_iter_sub *sub = &it->subtable_state[it->i];
- struct hash_entry *end;
-
- for (;;) {
- int32 shift = HASH_BITS - (st->power + used);
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (last_hash >> shift) & index_mask;
-
- end = st->end;
- e = HASH_OFFSET (st->entry, i * elemsize);
- sub->start = st->entry;
- sub->end = end;
-
- if ((e->hash & HASH_MASK) != HASH_SUBHASH) {
- break;
- }
- sub->e = HASH_OFFSET (e, elemsize);
- sub = &it->subtable_state[++(it->i)];
- used += st->power;
- st = *(struct hash_subtable **)e->data;
- }
- while (e != end && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
- e = HASH_OFFSET (e, elemsize);
- }
- sub->e = e;
-}
-
-void *
-hash_next (struct hash_iter *it)
-{
- int32 elemsize = it->elemsize;
- struct hash_iter_sub *sub = &it->subtable_state[it->i];
- struct hash_entry *e = sub->e;
- struct hash_entry *end = sub->end;
- hash_hash_t e_hash = 0;
-
- if (it->changes != it->h->changes) { /* hash table's structure changed; recompute */
- it->changes = it->h->changes;
- it->i = 0;
- iter_restart (it, it->h->st, 0);
- sub = &it->subtable_state[it->i];
- e = sub->e;
- end = sub->end;
- }
- if (e != sub->start && it->last_hash != HASH_OFFSET (e, -elemsize)->hash) {
- struct hash_entry *start = HASH_OFFSET (e, -(elemsize * it->h->max_probes));
- struct hash_entry *pe = HASH_OFFSET (e, -elemsize);
- hash_hash_t last_hash = it->last_hash;
- if (start < sub->start) {
- start = sub->start;
- }
- while (e != start && ((e_hash = pe->hash) == HASH_NIL || last_hash < e_hash)) {
- e = pe;
- pe = HASH_OFFSET (pe, -elemsize);
- }
- while (e != end && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
- e = HASH_OFFSET (e, elemsize);
- }
- }
-
- for (;;) {
- while (e != end && (e_hash = e->hash) == HASH_NIL) {
- e = HASH_OFFSET (e, elemsize);
- }
- if (e == end) {
- if (it->i == 0) {
- it->last_hash = HASH_OFFSET (e, -elemsize)->hash;
- sub->e = e;
- return (0);
- } else {
- it->i--;
- sub = &it->subtable_state[it->i];
- e = sub->e;
- end = sub->end;
- }
- } else if ((e_hash & HASH_MASK) != HASH_SUBHASH) {
- it->last_hash = e->hash;
- sub->e = HASH_OFFSET (e, elemsize);
- return (e->data);
- } else {
- struct hash_subtable *st =
- *(struct hash_subtable **)e->data;
- sub->e = HASH_OFFSET (e, elemsize);
- it->i++;
- assert (it->i < sizeof (it->subtable_state) /
- sizeof (it->subtable_state[0]));
- sub = &it->subtable_state[it->i];
- sub->e = e = st->entry;
- sub->start = st->entry;
- sub->end = end = st->end;
- }
- }
-}
-
-void
-hash_iter_init (struct hash *h, struct hash_iter *it)
-{
- it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- it->changes = h->changes;
- it->i = 0;
- it->h = h;
- it->last_hash = 0;
- it->subtable_state[0].e = h->st->entry;
- it->subtable_state[0].start = h->st->entry;
- it->subtable_state[0].end = h->st->end;
-}
-
-static void
-clean_st (struct hash_subtable *st, int32 *slots, int32 *used)
-{
- int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
- struct hash_entry *e = st->entry;
- struct hash_entry *end = st->end;
- int32 lslots = (((byte *) end) - (byte *) e) / elemsize;
- int32 lused = 0;
-
- while (e != end) {
- hash_hash_t hash = e->hash;
- if ((hash & HASH_MASK) == HASH_SUBHASH) {
- clean_st (*(struct hash_subtable **)e->data, slots, used);
- } else {
- lused += (hash != HASH_NIL);
- }
- e = HASH_OFFSET (e, elemsize);
- }
- free (st);
- *slots += lslots;
- *used += lused;
-}
-
-void
-hash_destroy (struct hash *h)
-{
- int32 slots = 0;
- int32 used = 0;
-
- clean_st (h->st, &slots, &used);
- free (h);
-}
-
-static void
-hash_visit_internal (struct hash_subtable *st,
- int32 used, int32 level,
- void (*data_visit) (void *arg, int32 level, void *data),
- void *arg)
-{
- int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
- struct hash_entry *e = st->entry;
- int32 shift = HASH_BITS - (used + st->power);
- int32 i = 0;
-
- while (e != st->end) {
- int32 index = ((e->hash >> (shift - 1)) >> 1) & ((1 << st->power) - 1);
- if ((e->hash & HASH_MASK) == HASH_SUBHASH) {
- (*data_visit) (arg, level, e->data);
- hash_visit_internal (*(struct hash_subtable **)e->data,
- used + st->power, level + 1, data_visit, arg);
- } else {
- (*data_visit) (arg, level, e->data);
- }
- if (e->hash != HASH_NIL) {
- assert (i < index + st->max_probes);
- assert (index <= i);
- }
- e = HASH_OFFSET (e, elemsize);
- i++;
- }
-}
-
-void
-hash_visit (struct hash *h, void (*data_visit) (void *arg, int32 level, void *data), void *arg)
-{
- hash_visit_internal (h->st, 0, 0, data_visit, arg);
-}
-
-//
-/// interfaces to go runtime
-//
-
-static void
-donothing(uint32 s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
-}
-
-typedef struct hash Hmap;
-static int32 debug = 0;
-
-// newmap(keysize uint32, valsize uint32,
-// keyalg uint32, valalg uint32,
-// hint uint32) (hmap *map[any]any);
-void
-sys·newmap(uint32 keysize, uint32 valsize,
- uint32 keyalg, uint32 valalg, uint32 hint,
- Hmap* ret)
-{
- Hmap *h;
-
- if(keyalg >= nelem(algarray) || algarray[keyalg].hash == nohash) {
- printf("map(keyalg=%d)\n", keyalg);
- throw("sys·newmap: unsupported map key type");
- }
-
- if(valalg >= nelem(algarray)) {
- printf("map(valalg=%d)\n", valalg);
- throw("sys·newmap: unsupported map value type");
- }
-
- h = mal(sizeof(*h));
-
- // align value inside data so that mark-sweep gc can find it.
- // might remove in the future and just assume datavo == keysize.
- h->datavo = keysize;
- if(valsize >= sizeof(void*))
- h->datavo = rnd(keysize, sizeof(void*));
-
- hash_init(h, h->datavo+valsize,
- algarray[keyalg].hash,
- algarray[keyalg].equal,
- donothing,
- hint);
-
- h->keysize = keysize;
- h->valsize = valsize;
- h->keyalg = &algarray[keyalg];
- h->valalg = &algarray[valalg];
-
- // these calculations are compiler dependent.
- // figure out offsets of map call arguments.
- h->ko = rnd(sizeof(h), keysize);
- h->vo = rnd(h->ko+keysize, valsize);
- h->po = rnd(h->vo+valsize, 1);
-
- ret = h;
- FLUSH(&ret);
-
- if(debug) {
- prints("newmap: map=");
- sys·printpointer(h);
- prints("; keysize=");
- sys·printint(keysize);
- prints("; valsize=");
- sys·printint(valsize);
- prints("; keyalg=");
- sys·printint(keyalg);
- prints("; valalg=");
- sys·printint(valalg);
- prints("; ko=");
- sys·printint(h->ko);
- prints("; vo=");
- sys·printint(h->vo);
- prints("; po=");
- sys·printint(h->po);
- prints("\n");
- }
-}
-
-// mapaccess1(hmap *map[any]any, key any) (val any);
-void
-sys·mapaccess1(Hmap *h, ...)
-{
- byte *ak, *av;
- byte *res;
- int32 hit;
-
- ak = (byte*)&h + h->ko;
- av = (byte*)&h + h->vo;
-
- res = nil;
- hit = hash_lookup(h, ak, (void**)&res);
- if(!hit)
- throw("sys·mapaccess1: key not in map");
- h->valalg->copy(h->valsize, av, res+h->datavo);
-
- if(debug) {
- prints("sys·mapaccess1: map=");
- sys·printpointer(h);
- prints("; key=");
- h->keyalg->print(h->keysize, ak);
- prints("; val=");
- h->valalg->print(h->valsize, av);
- prints("; hit=");
- sys·printint(hit);
- prints("; res=");
- sys·printpointer(res);
- prints("\n");
- }
-}
-
-// mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
-void
-sys·mapaccess2(Hmap *h, ...)
-{
- byte *ak, *av, *ap;
- byte *res;
- int32 hit;
-
- ak = (byte*)&h + h->ko;
- av = (byte*)&h + h->vo;
- ap = (byte*)&h + h->po;
-
- res = nil;
- hit = hash_lookup(h, ak, (void**)&res);
- if(!hit) {
- *ap = false;
- h->valalg->copy(h->valsize, av, nil);
- } else {
- *ap = true;
- h->valalg->copy(h->valsize, av, res+h->datavo);
- }
-
- if(debug) {
- prints("sys·mapaccess2: map=");
- sys·printpointer(h);
- prints("; key=");
- h->keyalg->print(h->keysize, ak);
- prints("; val=");
- h->valalg->print(h->valsize, av);
- prints("; hit=");
- sys·printint(hit);
- prints("; res=");
- sys·printpointer(res);
- prints("; pres=");
- sys·printbool(*ap);
- prints("\n");
- }
-}
-
-static void
-mapassign(Hmap *h, byte *ak, byte *av)
-{
- byte *res;
- int32 hit;
-
- res = nil;
- hit = hash_insert(h, ak, (void**)&res);
- h->keyalg->copy(h->keysize, res, ak);
- h->valalg->copy(h->valsize, res+h->datavo, av);
-
- if(debug) {
- prints("mapassign: map=");
- sys·printpointer(h);
- prints("; key=");
- h->keyalg->print(h->keysize, ak);
- prints("; val=");
- h->valalg->print(h->valsize, av);
- prints("; hit=");
- sys·printint(hit);
- prints("; res=");
- sys·printpointer(res);
- prints("\n");
- }
-}
-
-// mapassign1(hmap *map[any]any, key any, val any);
-void
-sys·mapassign1(Hmap *h, ...)
-{
- byte *ak, *av;
-
- ak = (byte*)&h + h->ko;
- av = (byte*)&h + h->vo;
-
- mapassign(h, ak, av);
-}
-
-// mapassign2(hmap *map[any]any, key any, val any, pres bool);
-void
-sys·mapassign2(Hmap *h, ...)
-{
- byte *ak, *av, *ap;
- byte *res;
- int32 hit;
-
- ak = (byte*)&h + h->ko;
- av = (byte*)&h + h->vo;
- ap = (byte*)&h + h->po;
-
- if(*ap == true) {
- // assign
- mapassign(h, ak, av);
- return;
- }
-
- // delete
- hit = hash_remove(h, ak, (void**)&res);
-
- if(debug) {
- prints("mapassign2: map=");
- sys·printpointer(h);
- prints("; key=");
- h->keyalg->print(h->keysize, ak);
- prints("; hit=");
- sys·printint(hit);
- prints("; res=");
- sys·printpointer(res);
- prints("\n");
- }
-}
-
-// mapiterinit(hmap *map[any]any, hiter *any);
-void
-sys·mapiterinit(Hmap *h, struct hash_iter *it)
-{
- if(h == nil) {
- it->data = nil;
- return;
- }
- hash_iter_init(h, it);
- it->data = hash_next(it);
- if(debug) {
- prints("sys·mapiterinit: map=");
- sys·printpointer(h);
- prints("; iter=");
- sys·printpointer(it);
- prints("; data=");
- sys·printpointer(it->data);
- prints("\n");
- }
-}
-
-// mapiternext(hiter *any);
-void
-sys·mapiternext(struct hash_iter *it)
-{
- it->data = hash_next(it);
- if(debug) {
- prints("sys·mapiternext: iter=");
- sys·printpointer(it);
- prints("; data=");
- sys·printpointer(it->data);
- prints("\n");
- }
-}
-
-// mapiter1(hiter *any) (key any);
-void
-sys·mapiter1(struct hash_iter *it, ...)
-{
- Hmap *h;
- byte *ak, *res;
-
- h = it->h;
- ak = (byte*)&it + h->ko;
-
- res = it->data;
- if(res == nil)
- throw("sys·mapiter2: key:val nil pointer");
-
- h->keyalg->copy(h->keysize, ak, res);
-
- if(debug) {
- prints("mapiter2: iter=");
- sys·printpointer(it);
- prints("; map=");
- sys·printpointer(h);
- prints("\n");
- }
-}
-
-// mapiter2(hiter *any) (key any, val any);
-void
-sys·mapiter2(struct hash_iter *it, ...)
-{
- Hmap *h;
- byte *ak, *av, *res;
-
- h = it->h;
- ak = (byte*)&it + h->ko;
- av = (byte*)&it + h->vo;
-
- res = it->data;
- if(res == nil)
- throw("sys·mapiter2: key:val nil pointer");
-
- h->keyalg->copy(h->keysize, ak, res);
- h->valalg->copy(h->valsize, av, res+h->datavo);
-
- if(debug) {
- prints("mapiter2: iter=");
- sys·printpointer(it);
- prints("; map=");
- sys·printpointer(h);
- prints("\n");
- }
-}
diff --git a/src/lib/runtime/hashmap.h b/src/lib/runtime/hashmap.h
deleted file mode 100644
index ff93e9ee3..000000000
--- a/src/lib/runtime/hashmap.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// 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.
-
-
-/* A hash table.
- Example, hashing nul-terminated char*s:
- hash_hash_t str_hash (void *v) {
- char *s;
- hash_hash_t hash = 0;
- for (s = *(char **)v; *s != 0; s++) {
- hash = (hash ^ *s) * 2654435769U;
- }
- return (hash);
- }
- int str_eq (void *a, void *b) {
- return (strcmp (*(char **)a, *(char **)b) == 0);
- }
- void str_del (void *arg, void *data) {
- *(char **)arg = *(char **)data;
- }
-
- struct hash *h = hash_new (sizeof (char *), &str_hash, &str_eq, &str_del, 3, 12, 15);
- ... 3=> 2**3 entries initial size
- ... 12=> 2**12 entries before sprouting sub-tables
- ... 15=> number of adjacent probes to attempt before growing
-
- Example lookup:
- char *key = "foobar";
- char **result_ptr;
- if (hash_lookup (h, &key, (void **) &result_ptr)) {
- printf ("found in table: %s\n", *result_ptr);
- } else {
- printf ("not found in table\n");
- }
-
- Example insertion:
- char *key = strdup ("foobar");
- char **result_ptr;
- if (hash_lookup (h, &key, (void **) &result_ptr)) {
- printf ("found in table: %s\n", *result_ptr);
- printf ("to overwrite, do *result_ptr = key\n");
- } else {
- printf ("not found in table; inserted as %s\n", *result_ptr);
- assert (*result_ptr == key);
- }
-
- Example deletion:
- char *key = "foobar";
- char *result;
- if (hash_remove (h, &key, &result)) {
- printf ("key found and deleted from table\n");
- printf ("called str_del (&result, data) to copy data to result: %s\n", result);
- } else {
- printf ("not found in table\n");
- }
-
- Example iteration over the elements of *h:
- char **data;
- struct hash_iter it;
- hash_iter_init (h, &it);
- for (data = hash_next (&it); data != 0; data = hash_next (&it)) {
- printf ("%s\n", *data);
- }
- */
-
-#define malloc mal
-#define free(a) USED(a)
-#define offsetof(s,m) (uint32)(&(((s*)0)->m))
-#define memset(a,b,c) sys·memclr((byte*)(a), (uint32)(c))
-#define memmove(a,b,c) mmov((byte*)(a),(byte*)(b),(uint32)(c))
-#define memcpy(a,b,c) mcpy((byte*)(a),(byte*)(b),(uint32)(c))
-#define assert(a) if(!(a)) throw("assert")
-
-struct hash; /* opaque */
-struct hash_subtable; /* opaque */
-struct hash_entry; /* opaque */
-
-typedef uintptr uintptr_t;
-typedef uintptr_t hash_hash_t;
-
-struct hash_iter {
- uint8* data; /* returned from next */
- int32 elemsize; /* size of elements in table */
- int32 changes; /* number of changes observed last time */
- int32 i; /* stack pointer in subtable_state */
- hash_hash_t last_hash; /* last hash value returned */
- struct hash *h; /* the hash table */
- struct hash_iter_sub {
- struct hash_entry *e; /* pointer into subtable */
- struct hash_entry *start; /* start of subtable */
- struct hash_entry *end; /* end of subtable */
- } subtable_state[4]; /* Should be large enough unless the hashing is
- so bad that many distinct data values hash
- to the same hash value. */
-};
-
-/* Return a hashtable h 2**init_power empty entries, each with
- "datasize" data bytes.
- (*data_hash)(a) should return the hash value of data element *a.
- (*data_eq)(a,b) should return whether the data at "a" and the data at "b"
- are equal.
- (*data_del)(arg, a) will be invoked when data element *a is about to be removed
- from the table. "arg" is the argument passed to "hash_remove()".
-
- Growing is accomplished by resizing if the current tables size is less than
- a threshold, and by adding subtables otherwise. hint should be set
- the expected maximum size of the table.
- "datasize" should be in [sizeof (void*), ..., 255]. If you need a
- bigger "datasize", store a pointer to another piece of memory. */
-
-//struct hash *hash_new (int32 datasize,
-// hash_hash_t (*data_hash) (void *),
-// int32 (*data_eq) (void *, void *),
-// void (*data_del) (void *, void *),
-// int64 hint);
-
-/* Lookup *data in *h. If the data is found, return 1 and place a pointer to
- the found element in *pres. Otherwise return 0 and place 0 in *pres. */
-int32 hash_lookup (struct hash *h, void *data, void **pres);
-
-/* Lookup *data in *h. If the data is found, execute (*data_del) (arg, p)
- where p points to the data in the table, then remove it from *h and return
- 1. Otherwise return 0. */
-int32 hash_remove (struct hash *h, void *data, void *arg);
-
-/* Lookup *data in *h. If the data is found, return 1, and place a pointer
- to the found element in *pres. Otherwise, return 0, allocate a region
- for the data to be inserted, and place a pointer to the inserted element
- in *pres; it is the caller's responsibility to copy the data to be
- inserted to the pointer returned in *pres in this case.
-
- If using garbage collection, it is the caller's responsibility to
- add references for **pres if HASH_ADDED is returned. */
-int32 hash_insert (struct hash *h, void *data, void **pres);
-
-/* Return the number of elements in the table. */
-uint32 hash_count (struct hash *h);
-
-/* The following call is useful only if not using garbage collection on the
- table.
- Remove all sub-tables associated with *h.
- This undoes the effects of hash_init().
- If other memory pointed to by user data must be freed, the caller is
- responsible for doiing do by iterating over *h first; see
- hash_iter_init()/hash_next(). */
-void hash_destroy (struct hash *h);
-
-/*----- iteration -----*/
-
-/* Initialize *it from *h. */
-void hash_iter_init (struct hash *h, struct hash_iter *it);
-
-/* Return the next used entry in the table which which *it was initialized. */
-void *hash_next (struct hash_iter *it);
-
-/*---- test interface ----*/
-/* Call (*data_visit) (arg, level, data) for every data entry in the table,
- whether used or not. "level" is the subtable level, 0 means first level. */
-/* TESTING ONLY: DO NOT USE THIS ROUTINE IN NORMAL CODE */
-void hash_visit (struct hash *h, void (*data_visit) (void *arg, int32 level, void *data), void *arg);
diff --git a/src/lib/runtime/iface.c b/src/lib/runtime/iface.c
deleted file mode 100644
index 6c933b1b2..000000000
--- a/src/lib/runtime/iface.c
+++ /dev/null
@@ -1,906 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-int32 iface_debug = 0;
-
-typedef struct Sigt Sigt;
-typedef struct Sigi Sigi;
-typedef struct Itype Itype;
-
-/*
- * the layout of Iface, Sigt and Sigi are known to the compiler
- */
-struct Sigt
-{
- byte* name; // name of basic type
- Sigt* link; // for linking into hash tables
- uint32 thash; // hash of type
- uint32 mhash; // hash of methods
- uint16 width; // width of base type in bytes
- uint16 alg; // algorithm
- // note: on amd64 there is a 32-bit pad here.
- struct {
- byte* fname;
- uint32 fhash; // hash of type
- uint32 offset; // offset of substruct
- void (*fun)(void);
- } meth[1]; // one or more - last name is nil
-};
-
-struct Sigi
-{
- byte* name;
- uint32 hash;
- uint32 size; // number of methods
- struct {
- byte* fname;
- uint32 fhash;
- uint32 perm; // location of fun in Sigt
- } meth[1]; // [size+1] - last name is nil
-};
-
-struct Itype
-{
- Sigi* sigi;
- Sigt* sigt;
- Itype* link;
- int32 bad;
- int32 unused;
- void (*fun[])(void);
-};
-
-static Iface niliface;
-static Eface nileface;
-
-static Itype* hash[1009];
-static Lock ifacelock;
-
-Sigi sigi·empty[2] = { (byte*)"interface { }" };
-
-static void
-printsigi(Sigi *si)
-{
- int32 i;
- byte *name;
-
- sys·printpointer(si);
- prints("{");
- prints((int8*)si->name);
- prints(":");
- for(i=0;; i++) {
- name = si->meth[i].fname;
- if(name == nil)
- break;
- prints("[");
- sys·printint(i);
- prints("]\"");
- prints((int8*)name);
- prints("\"");
- sys·printint(si->meth[i].fhash%999);
- prints("/");
- sys·printint(si->meth[i].perm);
- }
- prints("}");
-}
-
-static void
-printsigt(Sigt *st)
-{
- int32 i;
- byte *name;
-
- sys·printpointer(st);
- prints("{");
- prints((int8*)st->name);
- prints(":");
- sys·printint(st->thash%999); // type hash
- prints(",");
- sys·printint(st->mhash%999); // method hash
- prints(",");
- sys·printint(st->width); // width
- prints(",");
- sys·printint(st->alg); // algorithm
- for(i=0;; i++) {
- name = st->meth[i].fname;
- if(name == nil)
- break;
- prints("[");
- sys·printint(i);
- prints("]\"");
- prints((int8*)name);
- prints("\"");
- sys·printint(st->meth[i].fhash%999);
- prints("/");
- sys·printint(st->meth[i].offset);
- prints("/");
- sys·printpointer(st->meth[i].fun);
- }
- prints("}");
-}
-
-static void
-printiface(Iface i)
-{
- prints("(");
- sys·printpointer(i.type);
- prints(",");
- sys·printpointer(i.data);
- prints(")");
-}
-
-static void
-printeface(Eface e)
-{
- prints("(");
- sys·printpointer(e.type);
- prints(",");
- sys·printpointer(e.data);
- prints(")");
-}
-
-static Itype*
-itype(Sigi *si, Sigt *st, int32 canfail)
-{
- int32 locked;
- int32 nt, ni;
- uint32 ihash, h;
- byte *sname, *iname;
- Itype *m;
-
- if(si->size == 0)
- throw("internal error - misuse of itype");
-
- // easy case
- if(st->meth[0].fname == nil) {
- if(canfail)
- return nil;
- iname = si->meth[0].fname;
- goto throw1;
- }
-
- // compiler has provided some good hash codes for us.
- h = 0;
- if(si)
- h += si->hash;
- if(st) {
- h += st->thash;
- h += st->mhash;
- }
-
- h %= nelem(hash);
-
- // look twice - once without lock, once with.
- // common case will be no lock contention.
- for(locked=0; locked<2; locked++) {
- if(locked)
- lock(&ifacelock);
- for(m=hash[h]; m!=nil; m=m->link) {
- if(m->sigi == si && m->sigt == st) {
- if(m->bad) {
- m = nil;
- if(!canfail) {
- // this can only happen if the conversion
- // was already done once using the , ok form
- // and we have a cached negative result.
- // the cached result doesn't record which
- // interface function was missing, so jump
- // down to the interface check, which will
- // give a better error.
- goto throw;
- }
- }
- if(locked)
- unlock(&ifacelock);
- return m;
- }
- }
- }
-
- ni = si->size;
- m = malloc(sizeof(*m) + ni*sizeof(m->fun[0]));
- m->sigi = si;
- m->sigt = st;
-
-throw:
- nt = 0;
- for(ni=0;; ni++) {
- iname = si->meth[ni].fname;
- if(iname == nil)
- break;
-
- // pick up next name from
- // interface signature
- ihash = si->meth[ni].fhash;
-
- for(;; nt++) {
- // pick up and compare next name
- // from structure signature
- sname = st->meth[nt].fname;
- if(sname == nil) {
- if(!canfail) {
- throw1:
- printf("cannot convert type %s to interface %s: missing method %s\n",
- st->name, si->name, iname);
- if(iface_debug) {
- prints("interface");
- printsigi(si);
- prints("\ntype");
- printsigt(st);
- prints("\n");
- }
- throw("interface conversion");
- return nil; // not reached
- }
- m->bad = 1;
- m->link = hash[h];
- hash[h] = m;
- if(locked)
- unlock(&ifacelock);
- return nil;
- }
- if(ihash == st->meth[nt].fhash && strcmp(sname, iname) == 0)
- break;
- }
- m->fun[si->meth[ni].perm] = st->meth[nt].fun;
- }
- m->link = hash[h];
- hash[h] = m;
- if(locked)
- unlock(&ifacelock);
-
- return m;
-}
-
-static void
-copyin(Sigt *st, void *src, void **dst)
-{
- int32 wid, alg;
- void *p;
-
- wid = st->width;
- alg = st->alg;
-
- if(wid <= sizeof(*dst))
- algarray[alg].copy(wid, dst, src);
- else {
- p = mal(wid);
- algarray[alg].copy(wid, p, src);
- *dst = p;
- }
-}
-
-static void
-copyout(Sigt *st, void **src, void *dst)
-{
- int32 wid, alg;
-
- wid = st->width;
- alg = st->alg;
-
- if(wid <= sizeof(*src))
- algarray[alg].copy(wid, dst, src);
- else
- algarray[alg].copy(wid, dst, *src);
-}
-
-// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
-#pragma textflag 7
-void
-sys·ifaceT2I(Sigi *si, Sigt *st, ...)
-{
- byte *elem;
- Iface *ret;
- int32 wid;
-
- elem = (byte*)(&st+1);
- wid = st->width;
- ret = (Iface*)(elem + rnd(wid, sizeof(uintptr)));
-
- ret->type = itype(si, st, 0);
- copyin(st, elem, &ret->data);
-}
-
-// ifaceT2E(sigt *byte, elem any) (ret any);
-#pragma textflag 7
-void
-sys·ifaceT2E(Sigt *st, ...)
-{
- byte *elem;
- Eface *ret;
- int32 wid;
-
- elem = (byte*)(&st+1);
- wid = st->width;
- ret = (Eface*)(elem + rnd(wid, sizeof(uintptr)));
-
- ret->type = st;
- copyin(st, elem, &ret->data);
-}
-
-// ifaceI2T(sigt *byte, iface any) (ret any);
-#pragma textflag 7
-void
-sys·ifaceI2T(Sigt *st, Iface i, ...)
-{
- Itype *im;
- byte *ret;
-
- ret = (byte*)(&i+1);
-
- im = i.type;
- if(im == nil) {
- printf("interface is nil, not %s\n", st->name);
- throw("interface conversion");
- }
- if(im->sigt != st) {
- printf("%s is %s, not %s\n", im->sigi->name, im->sigt->name, st->name);
- throw("interface conversion");
- }
- copyout(st, &i.data, ret);
-}
-
-// ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
-#pragma textflag 7
-void
-sys·ifaceI2T2(Sigt *st, Iface i, ...)
-{
- byte *ret;
- bool *ok;
- Itype *im;
- int32 wid;
-
- ret = (byte*)(&i+1);
- wid = st->width;
- ok = (bool*)(ret+rnd(wid, 1));
-
- im = i.type;
- if(im == nil || im->sigt != st) {
- *ok = false;
- sys·memclr(ret, wid);
- return;
- }
-
- *ok = true;
- copyout(st, &i.data, ret);
-}
-
-// ifaceE2T(sigt *byte, iface any) (ret any);
-#pragma textflag 7
-void
-sys·ifaceE2T(Sigt *st, Eface e, ...)
-{
- Sigt *t;
- byte *ret;
-
- ret = (byte*)(&e+1);
-
- t = e.type;
- if(t == nil) {
- printf("interface is nil, not %s\n", st->name);
- throw("interface conversion");
- }
- if(t != st) {
- printf("interface is %s, not %s\n", t->name, st->name);
- throw("interface conversion");
- }
- copyout(st, &e.data, ret);
-}
-
-// ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
-#pragma textflag 7
-void
-sys·ifaceE2T2(Sigt *st, Eface e, ...)
-{
- byte *ret;
- bool *ok;
- Sigt *t;
- int32 wid;
-
- ret = (byte*)(&e+1);
- wid = st->width;
- ok = (bool*)(ret+rnd(wid, 1));
-
- t = e.type;
- if(t != st) {
- *ok = false;
- sys·memclr(ret, wid);
- return;
- }
-
- *ok = true;
- copyout(st, &e.data, ret);
-}
-
-// ifaceI2E(sigi *byte, iface any) (ret any);
-// TODO(rsc): Move to back end, throw away function.
-void
-sys·ifaceI2E(Iface i, Eface ret)
-{
- Itype *im;
-
- ret.data = i.data;
- im = i.type;
- if(im == nil)
- ret.type = nil;
- else
- ret.type = im->sigt;
- FLUSH(&ret);
-}
-
-// ifaceI2I(sigi *byte, iface any) (ret any);
-// called only for implicit (no type assertion) conversions
-void
-sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
-{
- Itype *im;
-
- im = i.type;
- if(im == nil) {
- // If incoming interface is uninitialized (zeroed)
- // make the outgoing interface zeroed as well.
- ret = niliface;
- } else {
- ret = i;
- if(im->sigi != si)
- ret.type = itype(si, im->sigt, 0);
- }
-
- FLUSH(&ret);
-}
-
-// ifaceI2Ix(sigi *byte, iface any) (ret any);
-// called only for explicit conversions (with type assertion).
-void
-sys·ifaceI2Ix(Sigi *si, Iface i, Iface ret)
-{
- Itype *im;
-
- im = i.type;
- if(im == nil) {
- // explicit conversions require non-nil interface value.
- printf("interface is nil, not %s\n", si->name);
- throw("interface conversion");
- } else {
- ret = i;
- if(im->sigi != si)
- ret.type = itype(si, im->sigt, 0);
- }
-
- FLUSH(&ret);
-}
-
-// ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
-void
-sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
-{
- Itype *im;
-
- im = i.type;
- if(im == nil) {
- // If incoming interface is nil, the conversion fails.
- ret = niliface;
- ok = false;
- } else {
- ret = i;
- ok = true;
- if(im->sigi != si) {
- ret.type = itype(si, im->sigt, 1);
- if(ret.type == nil) {
- ret = niliface;
- ok = false;
- }
- }
- }
-
- FLUSH(&ret);
- FLUSH(&ok);
-}
-
-// ifaceE2I(sigi *byte, iface any) (ret any);
-// Called only for explicit conversions (with type assertion).
-void
-sys·ifaceE2I(Sigi *si, Eface e, Iface ret)
-{
- Sigt *t;
-
- t = e.type;
- if(t == nil) {
- // explicit conversions require non-nil interface value.
- printf("interface is nil, not %s\n", si->name);
- throw("interface conversion");
- } else {
- ret.data = e.data;
- ret.type = itype(si, t, 0);
- }
- FLUSH(&ret);
-}
-
-// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
-void
-sys·ifaceE2I2(Sigi *si, Eface e, Iface ret, bool ok)
-{
- Sigt *t;
-
- t = e.type;
- ok = true;
- if(t == nil) {
- // If incoming interface is nil, the conversion fails.
- ret = niliface;
- ok = false;
- } else {
- ret.data = e.data;
- ret.type = itype(si, t, 1);
- if(ret.type == nil) {
- ret = niliface;
- ok = false;
- }
- }
- FLUSH(&ret);
- FLUSH(&ok);
-}
-
-static uintptr
-ifacehash1(void *data, Sigt *sigt)
-{
- int32 alg, wid;
-
- if(sigt == nil)
- return 0;
-
- alg = sigt->alg;
- wid = sigt->width;
- if(algarray[alg].hash == nohash) {
- // calling nohash will throw too,
- // but we can print a better error.
- printf("hash of unhashable type %s\n", sigt->name);
- if(alg == AFAKE)
- throw("fake interface hash");
- throw("interface hash");
- }
- if(wid <= sizeof(data))
- return algarray[alg].hash(wid, &data);
- return algarray[alg].hash(wid, data);
-}
-
-uintptr
-ifacehash(Iface a)
-{
- if(a.type == nil)
- return 0;
- return ifacehash1(a.data, a.type->sigt);
-}
-
-uintptr
-efacehash(Eface a)
-{
- return ifacehash1(a.data, a.type);
-}
-
-static bool
-ifaceeq1(void *data1, void *data2, Sigt *sigt)
-{
- int32 alg, wid;
-
- alg = sigt->alg;
- wid = sigt->width;
-
- if(algarray[alg].equal == noequal) {
- // calling noequal will throw too,
- // but we can print a better error.
- printf("comparing uncomparable type %s\n", sigt->name);
- if(alg == AFAKE)
- throw("fake interface compare");
- throw("interface compare");
- }
-
- if(wid <= sizeof(data1))
- return algarray[alg].equal(wid, &data1, &data2);
- return algarray[alg].equal(wid, data1, data2);
-}
-
-bool
-ifaceeq(Iface i1, Iface i2)
-{
- if(i1.type != i2.type)
- return false;
- if(i1.type == nil)
- return true;
- return ifaceeq1(i1.data, i2.data, i1.type->sigt);
-}
-
-bool
-efaceeq(Eface e1, Eface e2)
-{
- if(e1.type != e2.type)
- return false;
- if(e1.type == nil)
- return true;
- return ifaceeq1(e1.data, e2.data, e1.type);
-}
-
-// ifaceeq(i1 any, i2 any) (ret bool);
-void
-sys·ifaceeq(Iface i1, Iface i2, bool ret)
-{
- ret = ifaceeq(i1, i2);
- FLUSH(&ret);
-}
-
-// efaceeq(i1 any, i2 any) (ret bool)
-void
-sys·efaceeq(Eface e1, Eface e2, bool ret)
-{
- ret = efaceeq(e1, e2);
- FLUSH(&ret);
-}
-
-// ifacethash(i1 any) (ret uint32);
-void
-sys·ifacethash(Iface i1, uint32 ret)
-{
- Itype *im;
- Sigt *st;
-
- ret = 0;
- im = i1.type;
- if(im != nil) {
- st = im->sigt;
- if(st != nil)
- ret = st->thash;
- }
- FLUSH(&ret);
-}
-
-// efacethash(e1 any) (ret uint32)
-void
-sys·efacethash(Eface e1, uint32 ret)
-{
- Sigt *st;
-
- ret = 0;
- st = e1.type;
- if(st != nil)
- ret = st->thash;
- FLUSH(&ret);
-}
-
-void
-sys·printiface(Iface i)
-{
- printiface(i);
-}
-
-void
-sys·printeface(Eface e)
-{
- printeface(e);
-}
-
-void
-unsafe·Reflect(Eface i, uint64 retit, String rettype, bool retindir)
-{
- int32 wid;
-
- if(i.type == nil) {
- retit = 0;
- rettype = emptystring;
- retindir = false;
- } else {
- retit = (uint64)i.data;
- rettype = gostring(i.type->name);
- wid = i.type->width;
- retindir = wid > sizeof(i.data);
- }
- FLUSH(&retit);
- FLUSH(&rettype);
- FLUSH(&retindir);
-}
-
-extern Sigt *gotypesigs[];
-extern int32 ngotypesigs;
-
-
-// The reflection library can ask to unreflect on a type
-// that has never been used, so we don't have a signature for it.
-// For concreteness, suppose a program does
-//
-// type T struct{ x []int }
-// var t T;
-// v := reflect.NewValue(v);
-// vv := v.Field(0);
-// if s, ok := vv.Interface().(string) {
-// print("first field is string");
-// }
-//
-// vv.Interface() returns the result of sys.Unreflect with
-// a typestring of "[]int". If []int is not used with interfaces
-// in the rest of the program, there will be no signature in gotypesigs
-// for "[]int", so we have to invent one. The requirements
-// on the fake signature are:
-//
-// (1) any interface conversion using the signature will fail
-// (2) calling unsafe.Reflect() returns the args to unreflect
-// (3) the right algorithm type is used, for == and map insertion
-//
-// (1) is ensured by the fact that we allocate a new Sigt,
-// so it will necessarily be != any Sigt in gotypesigs.
-// (2) is ensured by storing the type string in the signature
-// and setting the width to force the correct value of the bool indir.
-// (3) is ensured by sniffing the type string.
-//
-// Note that (1) is correct behavior: if the program had tested
-// for .([]int) instead of .(string) above, then there would be a
-// signature with type string "[]int" in gotypesigs, and unreflect
-// wouldn't call fakesigt.
-
-static Sigt* fake[1009];
-static int32 nfake;
-
-enum
-{
- SizeofInt = 4,
- SizeofFloat = 4,
-};
-
-// Table of prefixes of names of comparable types.
-static struct {
- int8 *s;
- int8 n;
- int8 alg;
- int8 w;
-} cmp[] =
-{
- // basic types
- "int", 3+1, AMEM, SizeofInt, // +1 is NUL
- "uint", 4+1, AMEM, SizeofInt,
- "int8", 4+1, AMEM, 1,
- "uint8", 5+1, AMEM, 1,
- "int16", 5+1, AMEM, 2,
- "uint16", 6+1, AMEM, 2,
- "int32", 5+1, AMEM, 4,
- "uint32", 6+1, AMEM, 4,
- "int64", 5+1, AMEM, 8,
- "uint64", 6+1, AMEM, 8,
- "uintptr", 7+1, AMEM, sizeof(uintptr),
- "float", 5+1, AMEM, SizeofFloat,
- "float32", 7+1, AMEM, 4,
- "float64", 7+1, AMEM, 8,
- "bool", 4+1, AMEM, sizeof(bool),
-
- // string compare is special
- "string", 6+1, ASTRING, sizeof(String),
-
- // generic types, identified by prefix
- "*", 1, AMEM, sizeof(uintptr),
- "chan ", 5, AMEM, sizeof(uintptr),
- "func(", 5, AMEM, sizeof(uintptr),
- "map[", 4, AMEM, sizeof(uintptr),
-};
-
-static Sigt*
-fakesigt(String type, bool indir)
-{
- Sigt *sigt;
- uint32 h;
- int32 i, locked;
-
- h = 0;
- for(i=0; i<type.len; i++)
- h = h*37 + type.str[i];
- h += indir;
- h %= nelem(fake);
-
- for(locked=0; locked<2; locked++) {
- if(locked)
- lock(&ifacelock);
- for(sigt = fake[h]; sigt != nil; sigt = sigt->link) {
- // don't need to compare indir.
- // same type string but different indir will have
- // different hashes.
- if(mcmp(sigt->name, type.str, type.len) == 0)
- if(sigt->name[type.len] == '\0') {
- if(locked)
- unlock(&ifacelock);
- return sigt;
- }
- }
- }
-
- sigt = malloc(sizeof(*sigt));
- sigt->name = malloc(type.len + 1);
- mcpy(sigt->name, type.str, type.len);
-
- sigt->alg = AFAKE;
- sigt->width = 1; // small width
- if(indir)
- sigt->width = 2*sizeof(niliface.data); // big width
-
- // AFAKE is like ANOEQ; check whether the type
- // should have a more capable algorithm.
- for(i=0; i<nelem(cmp); i++) {
- if(mcmp((byte*)sigt->name, (byte*)cmp[i].s, cmp[i].n) == 0) {
- sigt->alg = cmp[i].alg;
- sigt->width = cmp[i].w;
- break;
- }
- }
-
- sigt->link = fake[h];
- fake[h] = sigt;
-
- unlock(&ifacelock);
- return sigt;
-}
-
-static int32
-cmpstringchars(String a, uint8 *b)
-{
- int32 i;
- byte c1, c2;
-
- for(i=0;; i++) {
- c1 = 0;
- if(i < a.len)
- c1 = a.str[i];
- c2 = b[i];
- if(c1 < c2)
- return -1;
- if(c1 > c2)
- return +1;
- if(c1 == 0)
- return 0;
- }
-}
-
-static Sigt*
-findtype(String type, bool indir)
-{
- int32 i, lo, hi, m;
-
- lo = 0;
- hi = ngotypesigs;
- while(lo < hi) {
- m = lo + (hi - lo)/2;
- i = cmpstringchars(type, gotypesigs[m]->name);
- if(i == 0)
- return gotypesigs[m];
- if(i < 0)
- hi = m;
- else
- lo = m+1;
- }
- return fakesigt(type, indir);
-}
-
-
-void
-unsafe·Unreflect(uint64 it, String type, bool indir, Eface ret)
-{
- Sigt *sigt;
-
- ret = nileface;
-
- if(cmpstring(type, emptystring) == 0)
- goto out;
-
- if(type.len > 10 && mcmp(type.str, (byte*)"interface ", 10) == 0) {
- printf("unsafe.Unreflect: cannot put %S in interface\n", type);
- throw("unsafe.Unreflect");
- }
-
- // if we think the type should be indirect
- // and caller does not, play it safe, return nil.
- sigt = findtype(type, indir);
- if(indir != (sigt->width > sizeof(ret.data)))
- goto out;
-
- ret.type = sigt;
- ret.data = (void*)it;
-
-out:
- FLUSH(&ret);
-}
-
diff --git a/src/lib/runtime/linux/386/defs.h b/src/lib/runtime/linux/386/defs.h
deleted file mode 100755
index 112fc7b09..000000000
--- a/src/lib/runtime/linux/386/defs.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// godefs -f -m32 -f -I/home/rsc/pub/linux-2.6/arch/x86/include -f -I/home/rsc/pub/linux-2.6/include defs2.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
- PROT_NONE = 0,
- PROT_READ = 0x1,
- PROT_WRITE = 0x2,
- PROT_EXEC = 0x4,
- MAP_ANON = 0x20,
- MAP_PRIVATE = 0x2,
- SA_RESTART = 0x10000000,
- SA_ONSTACK = 0x8000000,
- SA_RESTORER = 0x4000000,
- SA_SIGINFO = 0x4,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Fpreg Fpreg;
-struct Fpreg {
- uint16 significand[4];
- uint16 exponent;
-};
-
-typedef struct Fpxreg Fpxreg;
-struct Fpxreg {
- uint16 significand[4];
- uint16 exponent;
- uint16 padding[3];
-};
-
-typedef struct Xmmreg Xmmreg;
-struct Xmmreg {
- uint32 element[4];
-};
-
-typedef struct Fpstate Fpstate;
-struct Fpstate {
- uint32 cw;
- uint32 sw;
- uint32 tag;
- uint32 ipoff;
- uint32 cssel;
- uint32 dataoff;
- uint32 datasel;
- Fpreg _st[8];
- uint16 status;
- uint16 magic;
- uint32 _fxsr_env[6];
- uint32 mxcsr;
- uint32 reserved;
- Fpxreg _fxsr_st[8];
- Xmmreg _xmm[8];
- uint32 padding1[44];
- byte _anon_[48];
-};
-
-typedef struct Timespec Timespec;
-struct Timespec {
- int32 tv_sec;
- int32 tv_nsec;
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
- int32 tv_sec;
- int32 tv_usec;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
- byte _u[4];
- uint32 sa_mask;
- uint32 sa_flags;
- void *sa_restorer;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
- int32 si_signo;
- int32 si_errno;
- int32 si_code;
- byte _sifields[116];
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
- void *ss_sp;
- int32 ss_flags;
- uint32 ss_size;
-};
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
- uint16 gs;
- uint16 __gsh;
- uint16 fs;
- uint16 __fsh;
- uint16 es;
- uint16 __esh;
- uint16 ds;
- uint16 __dsh;
- uint32 edi;
- uint32 esi;
- uint32 ebp;
- uint32 esp;
- uint32 ebx;
- uint32 edx;
- uint32 ecx;
- uint32 eax;
- uint32 trapno;
- uint32 err;
- uint32 eip;
- uint16 cs;
- uint16 __csh;
- uint32 eflags;
- uint32 esp_at_signal;
- uint16 ss;
- uint16 __ssh;
- Fpstate *fpstate;
- uint32 oldmask;
- uint32 cr2;
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
- uint32 uc_flags;
- Ucontext *uc_link;
- Sigaltstack uc_stack;
- Sigcontext uc_mcontext;
- uint32 uc_sigmask;
-};
-#pragma pack off
diff --git a/src/lib/runtime/linux/386/rt0.s b/src/lib/runtime/linux/386/rt0.s
deleted file mode 100755
index 7717c37e8..000000000
--- a/src/lib/runtime/linux/386/rt0.s
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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.
-
-// Darwin and Linux use the same linkage to main
-
-TEXT _rt0_386_linux(SB),7,$0
- JMP _rt0_386(SB)
diff --git a/src/lib/runtime/linux/386/signal.c b/src/lib/runtime/linux/386/signal.c
deleted file mode 100644
index 7dfca6bb4..000000000
--- a/src/lib/runtime/linux/386/signal.c
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-void
-dumpregs(Sigcontext *r)
-{
- printf("eax %X\n", r->eax);
- printf("ebx %X\n", r->ebx);
- printf("ecx %X\n", r->ecx);
- printf("edx %X\n", r->edx);
- printf("edi %X\n", r->edi);
- printf("esi %X\n", r->esi);
- printf("ebp %X\n", r->ebp);
- printf("esp %X\n", r->esp);
- printf("eip %X\n", r->eip);
- printf("eflags %X\n", r->eflags);
- printf("cs %X\n", r->cs);
- printf("fs %X\n", r->fs);
- printf("gs %X\n", r->gs);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void sigtramp(void);
-extern void sigignore(void); // just returns
-extern void sigreturn(void); // calls sigreturn
-
-void
-sighandler(int32 sig, Siginfo* info, void* context)
-{
- Ucontext *uc;
- Sigcontext *sc;
-
- if(panicking) // traceback already printed
- exit(2);
- panicking = 1;
-
- uc = context;
- sc = &uc->uc_mcontext;
-
- if(sig < 0 || sig >= NSIG)
- printf("Signal %d\n", sig);
- else
- printf("%s\n", sigtab[sig].name);
-
- printf("Faulting address: %p\n", *(void**)info->_sifields);
- printf("pc=%X\n", sc->eip);
- printf("\n");
-
- if(gotraceback()){
- traceback((void*)sc->eip, (void*)sc->esp, m->curg);
- tracebackothers(m->curg);
- dumpregs(sc);
- }
-
- breakpoint();
- exit(2);
-}
-
-void
-signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- sigaltstack(&st, nil);
-}
-
-void
-initsig(void)
-{
- static Sigaction sa;
-
- int32 i;
- sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
- sa.sa_mask = 0xFFFFFFFFFFFFFFFFULL;
- sa.sa_restorer = (void*)sigreturn;
- for(i = 0; i<NSIG; i++) {
- if(sigtab[i].flags) {
- if(sigtab[i].flags & SigCatch)
- *(void**)sa._u = (void*)sigtramp; // handler
- else
- *(void**)sa._u = (void*)sigignore; // handler
- if(sigtab[i].flags & SigRestart)
- sa.sa_flags |= SA_RESTART;
- else
- sa.sa_flags &= ~SA_RESTART;
- rt_sigaction(i, &sa, nil, 8);
- }
- }
-}
-
diff --git a/src/lib/runtime/linux/386/sys.s b/src/lib/runtime/linux/386/sys.s
deleted file mode 100755
index 419973a5c..000000000
--- a/src/lib/runtime/linux/386/sys.s
+++ /dev/null
@@ -1,222 +0,0 @@
-// 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 calls and other sys.stuff for 386, Linux
-//
-
-TEXT syscall(SB),7,$0
- MOVL 4(SP), AX // syscall number
- MOVL 8(SP), BX // arg1
- MOVL 12(SP), CX // arg2
- MOVL 16(SP), DX // arg3
- MOVL 20(SP), SI // arg4
- MOVL 24(SP), DI // arg5
- MOVL 28(SP), BP // arg6
- INT $0x80
- CMPL AX, $0xfffff001
- JLS 2(PC)
- INT $3 // not reached
- RET
-
-TEXT exit(SB),7,$0
- MOVL $252, AX // syscall number
- MOVL 4(SP), BX
- INT $0x80
- INT $3 // not reached
- RET
-
-TEXT exit1(SB),7,$0
- MOVL $1, AX // exit - exit the current os thread
- MOVL 4(SP), BX
- INT $0x80
- INT $3 // not reached
- RET
-
-TEXT write(SB),7,$0
- MOVL $4, AX // syscall - write
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- INT $0x80
- RET
-
-TEXT getpid(SB),7,$0
- MOVL $20, AX
- INT $0x80
- RET
-
-TEXT kill(SB),7,$0
- MOVL $37, AX
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- INT $0x80
- RET
-
-TEXT sys·write(SB),7,$0
- MOVL $4, AX // syscall - write
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- INT $0x80
- RET
-
-TEXT rt_sigaction(SB),7,$0
- MOVL $174, AX // syscall - rt_sigaction
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
- INT $0x80
- RET
-
-TEXT sigtramp(SB),7,$0
- MOVL 4(FS), BP // m
- MOVL 20(BP), AX // m->gsignal
- MOVL AX, 0(FS) // g = m->gsignal
- JMP sighandler(SB)
-
-TEXT sigignore(SB),7,$0
- RET
-
-TEXT sigreturn(SB),7,$0
- MOVL 4(FS), BP // m
- MOVL 32(BP), BP // m->curg
- MOVL BP, 0(FS) // g = m->curg
- MOVL $173, AX // rt_sigreturn
- INT $0x80
- INT $3 // not reached
- RET
-
-TEXT sys·mmap(SB),7,$0
- MOVL $192, AX // mmap2
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
- MOVL 20(SP), DI
- MOVL 24(SP), BP
- SHRL $12, BP
- INT $0x80
- CMPL AX, $0xfffff001
- JLS 2(PC)
- INT $3
- RET
-
-// int64 futex(int32 *uaddr, int32 op, int32 val,
-// struct timespec *timeout, int32 *uaddr2, int32 val2);
-TEXT futex(SB),7,$0
- MOVL $240, AX // futex
- MOVL 4(SP), BX
- MOVL 8(SP), CX
- MOVL 12(SP), DX
- MOVL 16(SP), SI
- MOVL 20(SP), DI
- MOVL 24(SP), BP
- INT $0x80
- RET
-
-// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT clone(SB),7,$0
- MOVL $120, AX // clone
- MOVL flags+4(SP), BX
- MOVL stack+8(SP), CX
-
- // Copy m, g, fn off parent stack for use by child.
- SUBL $12, CX
- MOVL m+12(SP), DX
- MOVL DX, 0(CX)
- MOVL g+16(SP), DX
- MOVL DX, 4(CX)
- MOVL fn+20(SP), DX
- MOVL DX, 8(CX)
-
- MOVL $120, AX
- INT $0x80
-
- // In parent, return.
- CMPL AX, $0
- JEQ 2(PC)
- RET
-
- // In child, set up new stack, etc.
- MOVL 0(CX), BX // m
- MOVL 12(AX), AX // fs (= m->cret)
- MOVW AX, FS
- MOVL 8(CX), DX // fn
- ADDL $12, CX
- MOVL CX, SP
-
- // fn is now on top of stack.
-
- // initialize m->procid to Linux tid
- MOVL $224, AX
- INT $0x80
- MOVL AX, 20(BX)
-
- // call fn
- CALL DX
-
- // It shouldn't return; if it does, exit.
- MOVL $111, DI
- MOVL $1, AX
- INT $0x80
- JMP -3(PC) // keep exiting
-
-TEXT sigaltstack(SB),7,$-8
- MOVL $186, AX // sigaltstack
- MOVL new+4(SP), BX
- MOVL old+8(SP), CX
- INT $0x80
- CMPL AX, $0xfffff001
- JLS 2(PC)
- INT $3
- RET
-
-// // fake the per-goroutine and per-mach registers
-// LEAL m0(SB),
-
-// TODO(rsc): move to linux.s
-// <asm-i386/ldt.h>
-// struct user_desc {
-// unsigned int entry_number;
-// unsigned long base_addr;
-// unsigned int limit;
-// unsigned int seg_32bit:1;
-// unsigned int contents:2;
-// unsigned int read_exec_only:1;
-// unsigned int limit_in_pages:1;
-// unsigned int seg_not_present:1;
-// unsigned int useable:1;
-// };
-#define SEG_32BIT 0x01
-// contents are the 2 bits 0x02 and 0x04.
-#define CONTENTS_DATA 0x00
-#define CONTENTS_STACK 0x02
-#define CONTENTS_CODE 0x04
-#define READ_EXEC_ONLY 0x08
-#define LIMIT_IN_PAGES 0x10
-#define SEG_NOT_PRESENT 0x20
-#define USEABLE 0x40
-
-// setldt(int entry, int address, int limit)
-TEXT setldt(SB),7,$32
- // set up user_desc
- LEAL 16(SP), AX // struct user_desc
- MOVL entry+0(FP), BX // entry
- MOVL BX, 0(AX)
- MOVL address+4(FP), BX // base address
- MOVL BX, 4(AX)
- MOVL limit+8(FP), BX // limit
- MOVL BX, 8(AX)
- MOVL $(SEG_32BIT|USEABLE|CONTENTS_DATA), 12(AX) // flag bits
-
- // call modify_ldt
- MOVL $123, 0(SP) // syscall - modify_ldt
- MOVL $1, 4(SP) // func = 1 (write)
- MOVL AX, 8(SP) // user_desc
- MOVL $16, 12(SP) // sizeof(user_desc)
- CALL syscall(SB)
- RET
-
diff --git a/src/lib/runtime/linux/amd64/defs.h b/src/lib/runtime/linux/amd64/defs.h
deleted file mode 100644
index 43b047523..000000000
--- a/src/lib/runtime/linux/amd64/defs.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// godefs -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
- PROT_NONE = 0,
- PROT_READ = 0x1,
- PROT_WRITE = 0x2,
- PROT_EXEC = 0x4,
- MAP_ANON = 0x20,
- MAP_PRIVATE = 0x2,
- SA_RESTART = 0x10000000,
- SA_ONSTACK = 0x8000000,
- SA_RESTORER = 0x4000000,
- SA_SIGINFO = 0x4,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Timespec Timespec;
-struct Timespec {
- int64 tv_sec;
- int64 tv_nsec;
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
- int64 tv_sec;
- int64 tv_usec;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
- void *sa_handler;
- uint64 sa_flags;
- void *sa_restorer;
- uint64 sa_mask;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
- int32 si_signo;
- int32 si_errno;
- int32 si_code;
- byte pad0[4];
- byte _sifields[112];
-};
-#pragma pack off
-// godefs -f -m64 defs1.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-
-// Types
-#pragma pack on
-
-typedef struct Usigset Usigset;
-struct Usigset {
- uint64 __val[16];
-};
-
-typedef struct Fpxreg Fpxreg;
-struct Fpxreg {
- uint16 significand[4];
- uint16 exponent;
- uint16 padding[3];
-};
-
-typedef struct Xmmreg Xmmreg;
-struct Xmmreg {
- uint32 element[4];
-};
-
-typedef struct Fpstate Fpstate;
-struct Fpstate {
- uint16 cwd;
- uint16 swd;
- uint16 ftw;
- uint16 fop;
- uint64 rip;
- uint64 rdp;
- uint32 mxcsr;
- uint32 mxcr_mask;
- Fpxreg _st[8];
- Xmmreg _xmm[16];
- uint32 padding[24];
-};
-
-typedef struct Fpxreg1 Fpxreg1;
-struct Fpxreg1 {
- uint16 significand[4];
- uint16 exponent;
- uint16 padding[3];
-};
-
-typedef struct Xmmreg1 Xmmreg1;
-struct Xmmreg1 {
- uint32 element[4];
-};
-
-typedef struct Fpstate1 Fpstate1;
-struct Fpstate1 {
- uint16 cwd;
- uint16 swd;
- uint16 ftw;
- uint16 fop;
- uint64 rip;
- uint64 rdp;
- uint32 mxcsr;
- uint32 mxcr_mask;
- Fpxreg1 _st[8];
- Xmmreg1 _xmm[16];
- uint32 padding[24];
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
- void *ss_sp;
- int32 ss_flags;
- byte pad0[4];
- uint64 ss_size;
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
- int64 gregs[23];
- Fpstate *fpregs;
- uint64 __reserved1[8];
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
- uint64 uc_flags;
- Ucontext *uc_link;
- Sigaltstack uc_stack;
- Mcontext uc_mcontext;
- Usigset uc_sigmask;
- Fpstate __fpregs_mem;
-};
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
- uint64 r8;
- uint64 r9;
- uint64 r10;
- uint64 r11;
- uint64 r12;
- uint64 r13;
- uint64 r14;
- uint64 r15;
- uint64 rdi;
- uint64 rsi;
- uint64 rbp;
- uint64 rbx;
- uint64 rdx;
- uint64 rax;
- uint64 rcx;
- uint64 rsp;
- uint64 rip;
- uint64 eflags;
- uint16 cs;
- uint16 gs;
- uint16 fs;
- uint16 __pad0;
- uint64 err;
- uint64 trapno;
- uint64 oldmask;
- uint64 cr2;
- Fpstate1 *fpstate;
- uint64 __reserved1[8];
-};
-#pragma pack off
diff --git a/src/lib/runtime/linux/amd64/rt0.s b/src/lib/runtime/linux/amd64/rt0.s
deleted file mode 100644
index 55be5bcee..000000000
--- a/src/lib/runtime/linux/amd64/rt0.s
+++ /dev/null
@@ -1,9 +0,0 @@
-// 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.
-
-// Darwin and Linux use the same linkage to main
-
-TEXT _rt0_amd64_linux(SB),7,$-8
- MOVQ $_rt0_amd64(SB), AX
- JMP AX
diff --git a/src/lib/runtime/linux/amd64/signal.c b/src/lib/runtime/linux/amd64/signal.c
deleted file mode 100644
index 55215176d..000000000
--- a/src/lib/runtime/linux/amd64/signal.c
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-void
-dumpregs(Sigcontext *r)
-{
- printf("rax %X\n", r->rax);
- printf("rbx %X\n", r->rbx);
- printf("rcx %X\n", r->rcx);
- printf("rdx %X\n", r->rdx);
- printf("rdi %X\n", r->rdi);
- printf("rsi %X\n", r->rsi);
- printf("rbp %X\n", r->rbp);
- printf("rsp %X\n", r->rsp);
- printf("r8 %X\n", r->r8 );
- printf("r9 %X\n", r->r9 );
- printf("r10 %X\n", r->r10);
- printf("r11 %X\n", r->r11);
- printf("r12 %X\n", r->r12);
- printf("r13 %X\n", r->r13);
- printf("r14 %X\n", r->r14);
- printf("r15 %X\n", r->r15);
- printf("rip %X\n", r->rip);
- printf("rflags %X\n", r->eflags);
- printf("cs %X\n", (uint64)r->cs);
- printf("fs %X\n", (uint64)r->fs);
- printf("gs %X\n", (uint64)r->gs);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void sigtramp(void);
-extern void sigignore(void); // just returns
-extern void sigreturn(void); // calls sigreturn
-
-void
-sighandler(int32 sig, Siginfo* info, void* context)
-{
- Ucontext *uc;
- Mcontext *mc;
- Sigcontext *sc;
-
- if(panicking) // traceback already printed
- exit(2);
- panicking = 1;
-
- uc = context;
- mc = &uc->uc_mcontext;
- sc = (Sigcontext*)mc; // same layout, more conveient names
-
- if(sig < 0 || sig >= NSIG)
- printf("Signal %d\n", sig);
- else
- printf("%s\n", sigtab[sig].name);
-
- printf("Faulting address: %p\n", *(void**)info->_sifields);
- printf("PC=%X\n", sc->rip);
- printf("\n");
-
- if(gotraceback()){
- traceback((void*)sc->rip, (void*)sc->rsp, (void*)sc->r15);
- tracebackothers((void*)sc->r15);
- dumpregs(sc);
- }
-
- breakpoint();
- exit(2);
-}
-
-void
-signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- sigaltstack(&st, nil);
-}
-
-void
-initsig(void)
-{
- static Sigaction sa;
-
- int32 i;
- sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
- sa.sa_mask = 0xFFFFFFFFFFFFFFFFULL;
- sa.sa_restorer = (void*)sigreturn;
- for(i = 0; i<NSIG; i++) {
- if(sigtab[i].flags) {
- if(sigtab[i].flags & SigCatch)
- sa.sa_handler = (void*)sigtramp;
- else
- sa.sa_handler = (void*)sigignore;
- if(sigtab[i].flags & SigRestart)
- sa.sa_flags |= SA_RESTART;
- else
- sa.sa_flags &= ~SA_RESTART;
- rt_sigaction(i, &sa, nil, 8);
- }
- }
-}
-
diff --git a/src/lib/runtime/linux/amd64/sys.s b/src/lib/runtime/linux/amd64/sys.s
deleted file mode 100644
index f90c704fa..000000000
--- a/src/lib/runtime/linux/amd64/sys.s
+++ /dev/null
@@ -1,193 +0,0 @@
-// 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 calls and other sys.stuff for AMD64, Linux
-//
-
-TEXT exit(SB),7,$0-8
- MOVL 8(SP), DI
- MOVL $231, AX // exitgroup - force all os threads to exi
- SYSCALL
- RET
-
-TEXT exit1(SB),7,$0-8
- MOVL 8(SP), DI
- MOVL $60, AX // exit - exit the current os thread
- SYSCALL
- RET
-
-TEXT open(SB),7,$0-16
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVL $2, AX // syscall entry
- SYSCALL
- RET
-
-TEXT close(SB),7,$0-8
- MOVL 8(SP), DI
- MOVL $3, AX // syscall entry
- SYSCALL
- RET
-
-TEXT fstat(SB),7,$0-16
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL $5, AX // syscall entry
- SYSCALL
- RET
-
-TEXT read(SB),7,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL $0, AX // syscall entry
- SYSCALL
- RET
-
-TEXT write(SB),7,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL $1, AX // syscall entry
- SYSCALL
- RET
-
-TEXT sys·write(SB),7,$0-24
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVL 24(SP), DX
- MOVL $1, AX // syscall entry
- SYSCALL
- RET
-
-TEXT rt_sigaction(SB),7,$0-32
- MOVL 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ 24(SP), DX
- MOVQ 32(SP), R10
- MOVL $13, AX // syscall entry
- SYSCALL
- RET
-
-TEXT sigtramp(SB),7,$24-16
- MOVQ 32(R14), R15 // g = m->gsignal
- MOVQ DI,0(SP)
- MOVQ SI,8(SP)
- MOVQ DX,16(SP)
- CALL sighandler(SB)
- RET
-
-TEXT sigignore(SB),7,$0
- RET
-
-TEXT sigreturn(SB),7,$0
- MOVL $15, AX // rt_sigreturn
- SYSCALL
- INT $3 // not reached
-
-TEXT sys·mmap(SB),7,$0-32
- MOVQ 8(SP), DI
- MOVQ $0, SI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVL 24(SP), R10
- MOVL 28(SP), R8
- MOVL 32(SP), R9
-
- MOVL $9, AX // syscall entry
- SYSCALL
- CMPQ AX, $0xfffffffffffff001
- JLS 2(PC)
- CALL notok(SB)
- RET
-
-TEXT notok(SB),7,$0
- MOVQ $0xf1, BP
- MOVQ BP, (BP)
- RET
-
-TEXT sys·memclr(SB),7,$0-16
- MOVQ 8(SP), DI // arg 1 addr
- MOVL 16(SP), CX // arg 2 count (cannot be zero)
- ADDL $7, CX
- SHRL $3, CX
- MOVQ $0, AX
- CLD
- REP
- STOSQ
- RET
-
-TEXT sys·getcallerpc+0(SB),7,$0
- MOVQ x+0(FP),AX // addr of first arg
- MOVQ -8(AX),AX // get calling pc
- RET
-
-TEXT sys·setcallerpc+0(SB),7,$0
- MOVQ x+0(FP),AX // addr of first arg
- MOVQ x+8(FP), BX
- MOVQ BX, -8(AX) // set calling pc
- RET
-
-// int64 futex(int32 *uaddr, int32 op, int32 val,
-// struct timespec *timeout, int32 *uaddr2, int32 val2);
-TEXT futex(SB),7,$0
- MOVQ 8(SP), DI
- MOVL 16(SP), SI
- MOVL 20(SP), DX
- MOVQ 24(SP), R10
- MOVQ 32(SP), R8
- MOVL 40(SP), R9
- MOVL $202, AX
- SYSCALL
- RET
-
-// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT clone(SB),7,$0
- MOVL flags+8(SP), DI
- MOVQ stack+16(SP), SI
-
- // Copy m, g, fn off parent stack for use by child.
- // Careful: Linux system call clobbers CX and R11.
- MOVQ m+24(SP), R8
- MOVQ g+32(SP), R9
- MOVQ fn+40(SP), R12
-
- MOVL $56, AX
- SYSCALL
-
- // In parent, return.
- CMPQ AX, $0
- JEQ 2(PC)
- RET
-
- // In child, set up new stack
- MOVQ SI, SP
- MOVQ R8, R14 // m
- MOVQ R9, R15 // g
-
- // Initialize m->procid to Linux tid
- MOVL $186, AX // gettid
- SYSCALL
- MOVQ AX, 24(R14)
-
- // Call fn
- CALL R12
-
- // It shouldn't return. If it does, exi
- MOVL $111, DI
- MOVL $60, AX
- SYSCALL
- JMP -3(PC) // keep exiting
-
-TEXT sigaltstack(SB),7,$-8
- MOVQ new+8(SP), DI
- MOVQ old+16(SP), SI
- MOVQ $131, AX
- SYSCALL
- CMPQ AX, $0xfffffffffffff001
- JLS 2(PC)
- CALL notok(SB)
- RET
diff --git a/src/lib/runtime/linux/arm/defs.h b/src/lib/runtime/linux/arm/defs.h
deleted file mode 100644
index caad66989..000000000
--- a/src/lib/runtime/linux/arm/defs.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// godefs -carm-gcc -f -I/usr/local/google/src/linux-2.6.28/arch/arm/include -f -I/usr/local/google/src/linux-2.6.28/include defs_arm.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
- PROT_NONE = 0,
- PROT_READ = 0x1,
- PROT_WRITE = 0x2,
- PROT_EXEC = 0x4,
- MAP_ANON = 0x20,
- MAP_PRIVATE = 0x2,
- SA_RESTART = 0x10000000,
- SA_ONSTACK = 0x8000000,
- SA_RESTORER = 0x4000000,
- SA_SIGINFO = 0x4,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Timespec Timespec;
-struct Timespec {
- int32 tv_sec;
- int32 tv_nsec;
-};
-#pragma pack off
diff --git a/src/lib/runtime/linux/arm/rt0.s b/src/lib/runtime/linux/arm/rt0.s
deleted file mode 100644
index 024547ddd..000000000
--- a/src/lib/runtime/linux/arm/rt0.s
+++ /dev/null
@@ -1,6 +0,0 @@
-// 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.
-
-TEXT _rt0_arm_linux(SB),7,$0
- B _rt0_arm(SB)
diff --git a/src/lib/runtime/linux/arm/signal.c b/src/lib/runtime/linux/arm/signal.c
deleted file mode 100644
index 024018d5a..000000000
--- a/src/lib/runtime/linux/arm/signal.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// 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.
-
diff --git a/src/lib/runtime/linux/arm/sys.s b/src/lib/runtime/linux/arm/sys.s
deleted file mode 100644
index f5db32305..000000000
--- a/src/lib/runtime/linux/arm/sys.s
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 calls and other sys.stuff for arm, Linux
-//
-
-TEXT write(SB),7,$0
- MOVW 4(SP), R0
- MOVW 8(SP), R1
- MOVW 12(SP), R2
- SWI $0x00900004 // syscall write
- RET
-
diff --git a/src/lib/runtime/linux/defs.c b/src/lib/runtime/linux/defs.c
deleted file mode 100644
index 35fa02953..000000000
--- a/src/lib/runtime/linux/defs.c
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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
- godefs -f -m64 defs.c >amd64/defs.h
- godefs -f -m64 defs1.c >>amd64/defs.h
- */
-
-// Linux glibc and Linux kernel define different and conflicting
-// definitions for struct sigaction, struct timespec, etc.
-// We want the kernel ones, which are in the asm/* headers.
-// But then we'd get conflicts when we include the system
-// headers for things like ucontext_t, so that happens in
-// a separate file, defs1.c.
-
-#include <asm/signal.h>
-#include <asm/siginfo.h>
-#include <asm/mman.h>
-
-enum {
- $PROT_NONE = PROT_NONE,
- $PROT_READ = PROT_READ,
- $PROT_WRITE = PROT_WRITE,
- $PROT_EXEC = PROT_EXEC,
-
- $MAP_ANON = MAP_ANONYMOUS,
- $MAP_PRIVATE = MAP_PRIVATE,
-
- $SA_RESTART = SA_RESTART,
- $SA_ONSTACK = SA_ONSTACK,
- $SA_RESTORER = SA_RESTORER,
- $SA_SIGINFO = SA_SIGINFO,
-};
-
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-typedef struct sigaction $Sigaction;
-typedef siginfo_t $Siginfo;
diff --git a/src/lib/runtime/linux/defs1.c b/src/lib/runtime/linux/defs1.c
deleted file mode 100644
index 0fe3506ad..000000000
--- a/src/lib/runtime/linux/defs1.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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
- godefs -f -m64 defs.c >amd64/defs.h
- godefs -f -m64 defs1.c >>amd64/defs.h
- */
-
-#include <ucontext.h>
-
-typedef __sigset_t $Usigset;
-typedef struct _libc_fpxreg $Fpxreg;
-typedef struct _libc_xmmreg $Xmmreg;
-typedef struct _libc_fpstate $Fpstate;
-typedef struct _libc_fpreg $Fpreg;
-typedef struct _fpxreg $Fpxreg1;
-typedef struct _xmmreg $Xmmreg1;
-typedef struct _fpstate $Fpstate1;
-typedef struct _fpreg $Fpreg1;
-typedef struct sigaltstack $Sigaltstack;
-typedef mcontext_t $Mcontext;
-typedef ucontext_t $Ucontext;
-typedef struct sigcontext $Sigcontext;
diff --git a/src/lib/runtime/linux/defs2.c b/src/lib/runtime/linux/defs2.c
deleted file mode 100644
index aa0331a37..000000000
--- a/src/lib/runtime/linux/defs2.c
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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
- godefs -f -m32 -f -I/home/rsc/pub/linux-2.6/arch/x86/include -f -I/home/rsc/pub/linux-2.6/include defs2.c >386/defs.h
-
- * The asm header tricks we have to use for Linux on amd64
- * (see defs.c and defs1.c) don't work here, so this is yet another
- * file. Sigh.
- */
-
-#include <asm/signal.h>
-#include <asm/mman.h>
-#include <asm/sigframe.h>
-#include <asm/ucontext.h>
-
-/*
-#include <sys/signal.h>
-#include <sys/mman.h>
-#include <ucontext.h>
-*/
-
-enum {
- $PROT_NONE = PROT_NONE,
- $PROT_READ = PROT_READ,
- $PROT_WRITE = PROT_WRITE,
- $PROT_EXEC = PROT_EXEC,
-
- $MAP_ANON = MAP_ANONYMOUS,
- $MAP_PRIVATE = MAP_PRIVATE,
-
- $SA_RESTART = SA_RESTART,
- $SA_ONSTACK = SA_ONSTACK,
- $SA_RESTORER = SA_RESTORER,
- $SA_SIGINFO = SA_SIGINFO,
-};
-
-typedef struct _fpreg $Fpreg;
-typedef struct _fpxreg $Fpxreg;
-typedef struct _xmmreg $Xmmreg;
-typedef struct _fpstate $Fpstate;
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-typedef struct sigaction $Sigaction;
-typedef siginfo_t $Siginfo;
-typedef struct sigaltstack $Sigaltstack;
-typedef struct sigcontext $Sigcontext;
-typedef struct ucontext $Ucontext;
-
diff --git a/src/lib/runtime/linux/defs_arm.c b/src/lib/runtime/linux/defs_arm.c
deleted file mode 100644
index eaec05154..000000000
--- a/src/lib/runtime/linux/defs_arm.c
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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
- godefs -carm-gcc -f -I/usr/local/google/src/linux-2.6.28/arch/arm/include -f
- -I/usr/local/google/src/linux-2.6.28/include defs_arm.c >arm/defs.h
-
- * Another input file for ARM defs.h
- */
-
-#include <asm/signal.h>
-#include <asm/mman.h>
-#include <asm/sigcontext.h>
-#include <asm/ucontext.h>
-
-/*
-#include <sys/signal.h>
-#include <sys/mman.h>
-#include <ucontext.h>
-*/
-
-#include <time.h>
-
-enum {
- $PROT_NONE = PROT_NONE,
- $PROT_READ = PROT_READ,
- $PROT_WRITE = PROT_WRITE,
- $PROT_EXEC = PROT_EXEC,
-
- $MAP_ANON = MAP_ANONYMOUS,
- $MAP_PRIVATE = MAP_PRIVATE,
-
- $SA_RESTART = SA_RESTART,
- $SA_ONSTACK = SA_ONSTACK,
- $SA_RESTORER = SA_RESTORER,
- $SA_SIGINFO = SA_SIGINFO
-};
-
-
-
-
-//typedef struct _fpreg $Fpreg;
-//typedef struct _fpxreg $Fpxreg;
-//typedef struct _xmmreg $Xmmreg;
-//typedef struct _fpstate $Fpstate;
-typedef struct timespec $Timespec;
-//typedef struct timeval $Timeval;
-// typedef struct sigaction $Sigaction;
-// typedef siginfo_t $Siginfo;
-// typedef struct sigaltstack $Sigaltstack;
-// typedef struct sigcontext $Sigcontext;
-// typedef struct ucontext $Ucontext;
diff --git a/src/lib/runtime/linux/os.h b/src/lib/runtime/linux/os.h
deleted file mode 100644
index c61619367..000000000
--- a/src/lib/runtime/linux/os.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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.
-
-// Linux-specific system calls
-int64 futex(uint32*, int32, uint32, Timespec*, uint32*, uint32);
-int64 clone(int32, void*, M*, G*, void(*)(void));
-
-struct Sigaction;
-void rt_sigaction(int64, struct Sigaction*, void*, uint64);
diff --git a/src/lib/runtime/linux/signals.h b/src/lib/runtime/linux/signals.h
deleted file mode 100644
index 1fb49c513..000000000
--- a/src/lib/runtime/linux/signals.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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.
-
-
-#define C SigCatch
-#define I SigIgnore
-#define R SigRestart
-
-static SigTab sigtab[] = {
- /* 0 */ 0, "SIGNONE: no trap",
- /* 1 */ 0, "SIGHUP: terminal line hangup",
- /* 2 */ 0, "SIGINT: interrupt",
- /* 3 */ C, "SIGQUIT: quit",
- /* 4 */ C, "SIGILL: illegal instruction",
- /* 5 */ C, "SIGTRAP: trace trap",
- /* 6 */ C, "SIGABRT: abort",
- /* 7 */ C, "SIGBUS: bus error",
- /* 8 */ C, "SIGFPE: floating-point exception",
- /* 9 */ 0, "SIGKILL: kill",
- /* 10 */ 0, "SIGUSR1: user-defined signal 1",
- /* 11 */ C, "SIGSEGV: segmentation violation",
- /* 12 */ 0, "SIGUSR2: user-defined signal 2",
- /* 13 */ I, "SIGPIPE: write to broken pipe",
- /* 14 */ 0, "SIGALRM: alarm clock",
- /* 15 */ 0, "SIGTERM: termination",
- /* 16 */ 0, "SIGSTKFLT: stack fault",
- /* 17 */ I+R, "SIGCHLD: child status has changed",
- /* 18 */ 0, "SIGCONT: continue",
- /* 19 */ 0, "SIGSTOP: stop, unblockable",
- /* 20 */ 0, "SIGTSTP: keyboard stop",
- /* 21 */ 0, "SIGTTIN: background read from tty",
- /* 22 */ 0, "SIGTTOU: background write to tty",
- /* 23 */ 0, "SIGURG: urgent condition on socket",
- /* 24 */ 0, "SIGXCPU: cpu limit exceeded",
- /* 25 */ 0, "SIGXFSZ: file size limit exceeded",
- /* 26 */ 0, "SIGVTALRM: virtual alarm clock",
- /* 27 */ 0, "SIGPROF: profiling alarm clock",
- /* 28 */ I+R, "SIGWINCH: window size change",
- /* 29 */ 0, "SIGIO: i/o now possible",
- /* 30 */ 0, "SIGPWR: power failure restart",
- /* 31 */ C, "SIGSYS: bad system call",
-};
-#undef C
-#undef I
-#undef R
-
-#define NSIG 32
diff --git a/src/lib/runtime/linux/thread.c b/src/lib/runtime/linux/thread.c
deleted file mode 100644
index cc9ba161b..000000000
--- a/src/lib/runtime/linux/thread.c
+++ /dev/null
@@ -1,282 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-// Linux futex.
-//
-// futexsleep(uint32 *addr, uint32 val)
-// futexwakeup(uint32 *addr)
-//
-// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
-// Futexwakeup wakes up one thread sleeping on addr.
-// Futexsleep is allowed to wake up spuriously.
-
-enum
-{
- FUTEX_WAIT = 0,
- FUTEX_WAKE = 1,
-
- EINTR = 4,
- EAGAIN = 11,
-};
-
-// TODO(rsc): I tried using 1<<40 here but futex woke up (-ETIMEDOUT).
-// I wonder if the timespec that gets to the kernel
-// actually has two 32-bit numbers in it, so that
-// a 64-bit 1<<40 ends up being 0 seconds,
-// 1<<8 nanoseconds.
-static Timespec longtime =
-{
- 1<<30, // 34 years
- 0
-};
-
-// Atomically,
-// if(*addr == val) sleep
-// Might be woken up spuriously; that's allowed.
-static void
-futexsleep(uint32 *addr, uint32 val)
-{
- int64 ret;
-
- ret = futex(addr, FUTEX_WAIT, val, &longtime, nil, 0);
- if(ret >= 0 || ret == -EAGAIN || ret == -EINTR)
- return;
-
- prints("futexsleep addr=");
- sys·printpointer(addr);
- prints(" val=");
- sys·printint(val);
- prints(" returned ");
- sys·printint(ret);
- prints("\n");
- *(int32*)0x1005 = 0x1005;
-}
-
-// If any procs are sleeping on addr, wake up at least one.
-static void
-futexwakeup(uint32 *addr)
-{
- int64 ret;
-
- ret = futex(addr, FUTEX_WAKE, 1, nil, nil, 0);
-
- if(ret >= 0)
- return;
-
- // I don't know that futex wakeup can return
- // EAGAIN or EINTR, but if it does, it would be
- // safe to loop and call futex again.
-
- prints("futexwakeup addr=");
- sys·printpointer(addr);
- prints(" returned ");
- sys·printint(ret);
- prints("\n");
- *(int32*)0x1006 = 0x1006;
-}
-
-
-// Lock and unlock.
-//
-// The lock state is a single 32-bit word that holds
-// a 31-bit count of threads waiting for the lock
-// and a single bit (the low bit) saying whether the lock is held.
-// The uncontended case runs entirely in user space.
-// When contention is detected, we defer to the kernel (futex).
-//
-// A reminder: compare-and-swap cas(addr, old, new) does
-// if(*addr == old) { *addr = new; return 1; }
-// else return 0;
-// but atomically.
-
-static void
-futexlock(Lock *l)
-{
- uint32 v;
-
-again:
- v = l->key;
- if((v&1) == 0){
- if(cas(&l->key, v, v|1)){
- // Lock wasn't held; we grabbed it.
- return;
- }
- goto again;
- }
-
- // Lock was held; try to add ourselves to the waiter count.
- if(!cas(&l->key, v, v+2))
- goto again;
-
- // We're accounted for, now sleep in the kernel.
- //
- // We avoid the obvious lock/unlock race because
- // the kernel won't put us to sleep if l->key has
- // changed underfoot and is no longer v+2.
- //
- // We only really care that (v&1) == 1 (the lock is held),
- // and in fact there is a futex variant that could
- // accomodate that check, but let's not get carried away.)
- futexsleep(&l->key, v+2);
-
- // We're awake: remove ourselves from the count.
- for(;;){
- v = l->key;
- if(v < 2)
- throw("bad lock key");
- if(cas(&l->key, v, v-2))
- break;
- }
-
- // Try for the lock again.
- goto again;
-}
-
-static void
-futexunlock(Lock *l)
-{
- uint32 v;
-
- // Atomically get value and clear lock bit.
-again:
- v = l->key;
- if((v&1) == 0)
- throw("unlock of unlocked lock");
- if(!cas(&l->key, v, v&~1))
- goto again;
-
- // If there were waiters, wake one.
- if(v & ~1)
- futexwakeup(&l->key);
-}
-
-void
-lock(Lock *l)
-{
- if(m->locks < 0)
- throw("lock count");
- m->locks++;
- futexlock(l);
-}
-
-void
-unlock(Lock *l)
-{
- m->locks--;
- if(m->locks < 0)
- throw("lock count");
- futexunlock(l);
-}
-
-
-// One-time notifications.
-//
-// Since the lock/unlock implementation already
-// takes care of sleeping in the kernel, we just reuse it.
-// (But it's a weird use, so it gets its own interface.)
-//
-// We use a lock to represent the event:
-// unlocked == event has happened.
-// Thus the lock starts out locked, and to wait for the
-// event you try to lock the lock. To signal the event,
-// you unlock the lock.
-
-void
-noteclear(Note *n)
-{
- n->lock.key = 0; // memset(n, 0, sizeof *n)
- futexlock(&n->lock);
-}
-
-void
-notewakeup(Note *n)
-{
- futexunlock(&n->lock);
-}
-
-void
-notesleep(Note *n)
-{
- futexlock(&n->lock);
- futexunlock(&n->lock); // Let other sleepers find out too.
-}
-
-
-// Clone, the Linux rfork.
-enum
-{
- CLONE_VM = 0x100,
- CLONE_FS = 0x200,
- CLONE_FILES = 0x400,
- CLONE_SIGHAND = 0x800,
- CLONE_PTRACE = 0x2000,
- CLONE_VFORK = 0x4000,
- CLONE_PARENT = 0x8000,
- CLONE_THREAD = 0x10000,
- CLONE_NEWNS = 0x20000,
- CLONE_SYSVSEM = 0x40000,
- CLONE_SETTLS = 0x80000,
- CLONE_PARENT_SETTID = 0x100000,
- CLONE_CHILD_CLEARTID = 0x200000,
- CLONE_UNTRACED = 0x800000,
- CLONE_CHILD_SETTID = 0x1000000,
- CLONE_STOPPED = 0x2000000,
- CLONE_NEWUTS = 0x4000000,
- CLONE_NEWIPC = 0x8000000,
-};
-
-void
-newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
- int64 ret;
- int32 flags;
-
- /*
- * note: strace gets confused if we use CLONE_PTRACE here.
- */
- flags = CLONE_PARENT /* getppid doesn't change in child */
- | CLONE_VM /* share memory */
- | CLONE_FS /* share cwd, etc */
- | CLONE_FILES /* share fd table */
- | CLONE_SIGHAND /* share sig handler table */
- | CLONE_THREAD /* revisit - okay for now */
- ;
-
- if(0){
- prints("newosproc stk=");
- sys·printpointer(stk);
- prints(" m=");
- sys·printpointer(m);
- prints(" g=");
- sys·printpointer(g);
- prints(" fn=");
- sys·printpointer(fn);
- prints(" clone=");
- sys·printpointer(clone);
- prints("\n");
- }
-
- ret = clone(flags, stk, m, g, fn);
- if(ret < 0)
- *(int32*)123 = 123;
-}
-
-void
-osinit(void)
-{
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-minit(void)
-{
- // Initialize signal handling.
- m->gsignal = malg(32*1024); // OS X wants >=8K, Linux >=2K
- signalstack(m->gsignal->stackguard, 32*1024);
-}
diff --git a/src/lib/runtime/malloc.c b/src/lib/runtime/malloc.c
deleted file mode 100644
index 81cdfb300..000000000
--- a/src/lib/runtime/malloc.c
+++ /dev/null
@@ -1,308 +0,0 @@
-// 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.
-
-// See malloc.h for overview.
-//
-// TODO(rsc): double-check stats.
-// TODO(rsc): solve "stack overflow during malloc" problem.
-
-#include "runtime.h"
-#include "malloc.h"
-#include "defs.h"
-
-MHeap mheap;
-MStats mstats;
-
-// Allocate an object of at least size bytes.
-// Small objects are allocated from the per-thread cache's free lists.
-// Large objects (> 32 kB) are allocated straight from the heap.
-void*
-malloc(uintptr size)
-{
- int32 sizeclass;
- MCache *c;
- uintptr npages;
- MSpan *s;
- void *v;
- uint32 *ref;
-
- if(m->mallocing)
- throw("malloc/free - deadlock");
- m->mallocing = 1;
-
- if(size == 0)
- size = 1;
-
- if(size <= MaxSmallSize) {
- // Allocate from mcache free lists.
- sizeclass = SizeToClass(size);
- size = class_to_size[sizeclass];
- c = m->mcache;
- v = MCache_Alloc(c, sizeclass, size);
- if(v == nil)
- throw("out of memory");
- mstats.alloc += size;
- } else {
- // TODO(rsc): Report tracebacks for very large allocations.
-
- // Allocate directly from heap.
- npages = size >> PageShift;
- if((size & PageMask) != 0)
- npages++;
- s = MHeap_Alloc(&mheap, npages, 0);
- if(s == nil)
- throw("out of memory");
- mstats.alloc += npages<<PageShift;
- v = (void*)(s->start << PageShift);
- }
-
- // setup for mark sweep
- if(!mlookup(v, nil, nil, &ref)) {
- printf("malloc %D; mlookup failed\n", (uint64)size);
- throw("malloc mlookup");
- }
- *ref = RefNone;
-
- m->mallocing = 0;
- return v;
-}
-
-void*
-mallocgc(uintptr size)
-{
- void *v;
-
- v = malloc(size);
- if(mstats.inuse_pages > mstats.next_gc)
- gc(0);
- return v;
-}
-
-// Free the object whose base pointer is v.
-void
-free(void *v)
-{
- int32 sizeclass, size;
- uintptr page, tmp;
- MSpan *s;
- MCache *c;
- uint32 *ref;
-
- if(v == nil)
- return;
-
- if(m->mallocing)
- throw("malloc/free - deadlock");
- m->mallocing = 1;
-
- if(!mlookup(v, nil, nil, &ref))
- throw("free mlookup");
- *ref = RefFree;
-
- // Find size class for v.
- page = (uintptr)v >> PageShift;
- sizeclass = MHeapMapCache_GET(&mheap.mapcache, page, tmp);
- if(sizeclass == 0) {
- // Missed in cache.
- s = MHeap_Lookup(&mheap, page);
- if(s == nil)
- throw("free - invalid pointer");
- sizeclass = s->sizeclass;
- if(sizeclass == 0) {
- // Large object.
- mstats.alloc -= s->npages<<PageShift;
- sys_memclr(v, s->npages<<PageShift);
- MHeap_Free(&mheap, s);
- goto out;
- }
- MHeapMapCache_SET(&mheap.mapcache, page, sizeclass);
- }
-
- // Small object.
- c = m->mcache;
- size = class_to_size[sizeclass];
- sys_memclr(v, size);
- mstats.alloc -= size;
- MCache_Free(c, v, sizeclass, size);
-
-out:
- m->mallocing = 0;
-}
-
-int32
-mlookup(void *v, byte **base, uintptr *size, uint32 **ref)
-{
- uintptr n, nobj, i;
- byte *p;
- MSpan *s;
-
- s = MHeap_LookupMaybe(&mheap, (uintptr)v>>PageShift);
- if(s == nil) {
- if(base)
- *base = nil;
- if(size)
- *size = 0;
- if(ref)
- *ref = 0;
- return 0;
- }
-
- p = (byte*)((uintptr)s->start<<PageShift);
- if(s->sizeclass == 0) {
- // Large object.
- if(base)
- *base = p;
- if(size)
- *size = s->npages<<PageShift;
- if(ref)
- *ref = &s->gcref0;
- return 1;
- }
-
- if((byte*)v >= (byte*)s->gcref) {
- // pointers into the gc ref counts
- // do not count as pointers.
- return 0;
- }
-
- n = class_to_size[s->sizeclass];
- i = ((byte*)v - p)/n;
- if(base)
- *base = p + i*n;
- if(size)
- *size = n;
- nobj = (s->npages << PageShift) / (n + RefcountOverhead);
- if((byte*)s->gcref < p || (byte*)(s->gcref+nobj) > p+(s->npages<<PageShift)) {
- printf("odd span state=%d span=%p base=%p sizeclass=%d n=%D size=%D npages=%D\n",
- s->state, s, p, s->sizeclass, (uint64)nobj, (uint64)n, (uint64)s->npages);
- printf("s->base sizeclass %d v=%p base=%p gcref=%p blocksize=%D nobj=%D size=%D end=%p end=%p\n",
- s->sizeclass, v, p, s->gcref, (uint64)s->npages<<PageShift,
- (uint64)nobj, (uint64)n, s->gcref + nobj, p+(s->npages<<PageShift));
- throw("bad gcref");
- }
- if(ref)
- *ref = &s->gcref[i];
-
- return 1;
-}
-
-MCache*
-allocmcache(void)
-{
- return FixAlloc_Alloc(&mheap.cachealloc);
-}
-
-void
-mallocinit(void)
-{
- InitSizes();
- MHeap_Init(&mheap, SysAlloc);
- m->mcache = allocmcache();
-
- // See if it works.
- free(malloc(1));
-}
-
-void*
-SysAlloc(uintptr n)
-{
- mstats.sys += n;
- return sys_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-}
-
-void
-SysUnused(void *v, uintptr n)
-{
- USED(v);
- USED(n);
- // TODO(rsc): call madvise MADV_DONTNEED
-}
-
-void
-SysFree(void *v, uintptr n)
-{
- USED(v);
- USED(n);
- // TODO(rsc): call munmap
-}
-
-// Runtime stubs.
-
-extern void *oldmal(uint32);
-
-void*
-mal(uint32 n)
-{
-//return oldmal(n);
- void *v;
-
- v = mallocgc(n);
-
- if(0) {
- byte *p;
- uint32 i;
- p = v;
- for(i=0; i<n; i++) {
- if(p[i] != 0) {
- printf("mal %d => %p: byte %d is non-zero\n", n, v, i);
- throw("mal");
- }
- }
- }
-
-//printf("mal %d %p\n", n, v); // |checkmal to check for overlapping returns.
- return v;
-}
-
-// Stack allocator uses malloc/free most of the time,
-// but if we're in the middle of malloc and need stack,
-// we have to do something else to avoid deadlock.
-// In that case, we fall back on a fixed-size free-list
-// allocator, assuming that inside malloc all the stack
-// frames are small, so that all the stack allocations
-// will be a single size, the minimum (right now, 5k).
-struct {
- Lock;
- FixAlloc;
-} stacks;
-
-void*
-stackalloc(uint32 n)
-{
- void *v;
- uint32 *ref;
-
-//return oldmal(n);
- if(m->mallocing) {
- lock(&stacks);
- if(stacks.size == 0)
- FixAlloc_Init(&stacks, n, SysAlloc, nil, nil);
- if(stacks.size != n) {
- printf("stackalloc: in malloc, size=%D want %d", (uint64)stacks.size, n);
- throw("stackalloc");
- }
- v = FixAlloc_Alloc(&stacks);
- unlock(&stacks);
- return v;
- }
- v = malloc(n);
- if(!mlookup(v, nil, nil, &ref))
- throw("stackalloc mlookup");
- *ref = RefStack;
- return v;
-}
-
-void
-stackfree(void *v)
-{
-//return;
-
- if(m->mallocing) {
- lock(&stacks);
- FixAlloc_Free(&stacks, v);
- unlock(&stacks);
- return;
- }
- free(v);
-}
diff --git a/src/lib/runtime/malloc.h b/src/lib/runtime/malloc.h
deleted file mode 100644
index 9b3d6b811..000000000
--- a/src/lib/runtime/malloc.h
+++ /dev/null
@@ -1,308 +0,0 @@
-// 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.
-
-// Memory allocator, based on tcmalloc.
-// http://goog-perftools.sourceforge.net/doc/tcmalloc.html
-
-// The main allocator works in runs of pages.
-// Small allocation sizes (up to and including 32 kB) are
-// rounded to one of about 100 size classes, each of which
-// has its own free list of objects of exactly that size.
-// Any free page of memory can be split into a set of objects
-// of one size class, which are then managed using free list
-// allocators.
-//
-// The allocator's data structures are:
-//
-// FixAlloc: a free-list allocator for fixed-size objects,
-// used to manage storage used by the allocator.
-// MHeap: the malloc heap, managed at page (4096-byte) granularity.
-// MSpan: a run of pages managed by the MHeap.
-// MHeapMap: a mapping from page IDs to MSpans.
-// MHeapMapCache: a small cache of MHeapMap mapping page IDs
-// to size classes for pages used for small objects.
-// MCentral: a shared free list for a given size class.
-// MCache: a per-thread (in Go, per-M) cache for small objects.
-// MStats: allocation statistics.
-//
-// Allocating a small object proceeds up a hierarchy of caches:
-//
-// 1. Round the size up to one of the small size classes
-// and look in the corresponding MCache free list.
-// If the list is not empty, allocate an object from it.
-// This can all be done without acquiring a lock.
-//
-// 2. If the MCache free list is empty, replenish it by
-// taking a bunch of objects from the MCentral free list.
-// Moving a bunch amortizes the cost of acquiring the MCentral lock.
-//
-// 3. If the MCentral free list is empty, replenish it by
-// allocating a run of pages from the MHeap and then
-// chopping that memory into a objects of the given size.
-// Allocating many objects amortizes the cost of locking
-// the heap.
-//
-// 4. If the MHeap is empty or has no page runs large enough,
-// allocate a new group of pages (at least 1MB) from the
-// operating system. Allocating a large run of pages
-// amortizes the cost of talking to the operating system.
-//
-// Freeing a small object proceeds up the same hierarchy:
-//
-// 1. Look up the size class for the object and add it to
-// the MCache free list.
-//
-// 2. If the MCache free list is too long or the MCache has
-// too much memory, return some to the MCentral free lists.
-//
-// 3. If all the objects in a given span have returned to
-// the MCentral list, return that span to the page heap.
-//
-// 4. If the heap has too much memory, return some to the
-// operating system.
-//
-// TODO(rsc): Step 4 is not implemented.
-//
-// Allocating and freeing a large object uses the page heap
-// directly, bypassing the MCache and MCentral free lists.
-//
-// This C code was written with an eye toward translating to Go
-// in the future. Methods have the form Type_Method(Type *t, ...).
-
-
-typedef struct FixAlloc FixAlloc;
-typedef struct MCentral MCentral;
-typedef struct MHeap MHeap;
-typedef struct MHeapMap MHeapMap;
-typedef struct MHeapMapCache MHeapMapCache;
-typedef struct MSpan MSpan;
-typedef struct MStats MStats;
-typedef struct MLink MLink;
-
-enum
-{
- PageShift = 12,
- PageSize = 1<<PageShift,
- PageMask = PageSize - 1,
-};
-typedef uintptr PageID; // address >> PageShift
-
-enum
-{
- // Tunable constants.
- NumSizeClasses = 67, // Number of size classes (must match msize.c)
- MaxSmallSize = 32<<10,
-
- FixAllocChunk = 128<<10, // Chunk size for FixAlloc
- MaxMCacheListLen = 256, // Maximum objects on MCacheList
- MaxMCacheSize = 2<<20, // Maximum bytes in one MCache
- MaxMHeapList = 1<<(20 - PageShift), // Maximum page length for fixed-size list in MHeap.
- HeapAllocChunk = 1<<20, // Chunk size for heap growth
-};
-
-#ifdef _64BIT
-#include "mheapmap64.h"
-#else
-#include "mheapmap32.h"
-#endif
-
-// A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).)
-struct MLink
-{
- MLink *next;
-};
-
-// SysAlloc obtains a large chunk of memory from the operating system,
-// typically on the order of a hundred kilobytes or a megabyte.
-//
-// SysUnused notifies the operating system that the contents
-// of the memory region are no longer needed and can be reused
-// for other purposes. The program reserves the right to start
-// accessing those pages in the future.
-//
-// SysFree returns it unconditionally; this is only used if
-// an out-of-memory error has been detected midway through
-// an allocation. It is okay if SysFree is a no-op.
-
-void* SysAlloc(uintptr nbytes);
-void SysFree(void *v, uintptr nbytes);
-void SysUnused(void *v, uintptr nbytes);
-
-
-// FixAlloc is a simple free-list allocator for fixed size objects.
-// Malloc uses a FixAlloc wrapped around SysAlloc to manages its
-// MCache and MSpan objects.
-//
-// Memory returned by FixAlloc_Alloc is not zeroed.
-// The caller is responsible for locking around FixAlloc calls.
-// Callers can keep state in the object but the first word is
-// smashed by freeing and reallocating.
-struct FixAlloc
-{
- uintptr size;
- void *(*alloc)(uintptr);
- void (*first)(void *arg, byte *p); // called first time p is returned
- void *arg;
- MLink *list;
- byte *chunk;
- uint32 nchunk;
-};
-
-void FixAlloc_Init(FixAlloc *f, uintptr size, void *(*alloc)(uintptr), void (*first)(void*, byte*), void *arg);
-void* FixAlloc_Alloc(FixAlloc *f);
-void FixAlloc_Free(FixAlloc *f, void *p);
-
-
-// Statistics.
-// Shared with Go: if you edit this structure, also edit ../lib/malloc.go.
-struct MStats
-{
- uint64 alloc;
- uint64 sys;
- uint64 stacks;
- uint64 inuse_pages; // protected by mheap.Lock
- uint64 next_gc; // protected by mheap.Lock
- bool enablegc;
-};
-extern MStats mstats;
-
-
-// Size classes. Computed and initialized by InitSizes.
-//
-// SizeToClass(0 <= n <= MaxSmallSize) returns the size class,
-// 1 <= sizeclass < NumSizeClasses, for n.
-// Size class 0 is reserved to mean "not small".
-//
-// class_to_size[i] = largest size in class i
-// class_to_allocnpages[i] = number of pages to allocate when
-// making new objects in class i
-// class_to_transfercount[i] = number of objects to move when
-// taking a bunch of objects out of the central lists
-// and putting them in the thread free list.
-
-int32 SizeToClass(int32);
-extern int32 class_to_size[NumSizeClasses];
-extern int32 class_to_allocnpages[NumSizeClasses];
-extern int32 class_to_transfercount[NumSizeClasses];
-extern void InitSizes(void);
-
-
-// Per-thread (in Go, per-M) cache for small objects.
-// No locking needed because it is per-thread (per-M).
-typedef struct MCacheList MCacheList;
-struct MCacheList
-{
- MLink *list;
- uint32 nlist;
- uint32 nlistmin;
-};
-
-struct MCache
-{
- MCacheList list[NumSizeClasses];
- uint64 size;
-};
-
-void* MCache_Alloc(MCache *c, int32 sizeclass, uintptr size);
-void MCache_Free(MCache *c, void *p, int32 sizeclass, uintptr size);
-
-
-// An MSpan is a run of pages.
-enum
-{
- MSpanInUse = 0,
- MSpanFree,
- MSpanListHead,
- MSpanDead,
-};
-struct MSpan
-{
- MSpan *next; // in a span linked list
- MSpan *prev; // in a span linked list
- MSpan *allnext; // in the list of all spans
- PageID start; // starting page number
- uintptr npages; // number of pages in span
- MLink *freelist; // list of free objects
- uint32 ref; // number of allocated objects in this span
- uint32 sizeclass; // size class
- uint32 state; // MSpanInUse etc
- union {
- uint32 *gcref; // sizeclass > 0
- uint32 gcref0; // sizeclass == 0
- };
-};
-
-void MSpan_Init(MSpan *span, PageID start, uintptr npages);
-
-// Every MSpan is in one doubly-linked list,
-// either one of the MHeap's free lists or one of the
-// MCentral's span lists. We use empty MSpan structures as list heads.
-void MSpanList_Init(MSpan *list);
-bool MSpanList_IsEmpty(MSpan *list);
-void MSpanList_Insert(MSpan *list, MSpan *span);
-void MSpanList_Remove(MSpan *span); // from whatever list it is in
-
-
-// Central list of free objects of a given size.
-struct MCentral
-{
- Lock;
- int32 sizeclass;
- MSpan nonempty;
- MSpan empty;
- int32 nfree;
-};
-
-void MCentral_Init(MCentral *c, int32 sizeclass);
-int32 MCentral_AllocList(MCentral *c, int32 n, MLink **first);
-void MCentral_FreeList(MCentral *c, int32 n, MLink *first);
-
-// Main malloc heap.
-// The heap itself is the "free[]" and "large" arrays,
-// but all the other global data is here too.
-struct MHeap
-{
- Lock;
- MSpan free[MaxMHeapList]; // free lists of given length
- MSpan large; // free lists length >= MaxMHeapList
- MSpan *allspans;
-
- // span lookup
- MHeapMap map;
- MHeapMapCache mapcache;
-
- // central free lists for small size classes.
- // the union makes sure that the MCentrals are
- // spaced 64 bytes apart, so that each MCentral.Lock
- // gets its own cache line.
- union {
- MCentral;
- byte pad[64];
- } central[NumSizeClasses];
-
- FixAlloc spanalloc; // allocator for Span*
- FixAlloc cachealloc; // allocator for MCache*
-};
-extern MHeap mheap;
-
-void MHeap_Init(MHeap *h, void *(*allocator)(uintptr));
-MSpan* MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass);
-void MHeap_Free(MHeap *h, MSpan *s);
-MSpan* MHeap_Lookup(MHeap *h, PageID p);
-MSpan* MHeap_LookupMaybe(MHeap *h, PageID p);
-
-int32 mlookup(void *v, byte **base, uintptr *size, uint32 **ref);
-void gc(int32 force);
-
-enum
-{
- RefcountOverhead = 4, // one uint32 per object
-
- RefFree = 0, // must be zero
- RefManual, // manual allocation - don't free
- RefStack, // stack segment - don't free and don't scan for pointers
- RefNone, // no references
- RefSome, // some references
-};
-
diff --git a/src/lib/runtime/malloc_go.cgo b/src/lib/runtime/malloc_go.cgo
deleted file mode 100644
index 6dcdaece2..000000000
--- a/src/lib/runtime/malloc_go.cgo
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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 malloc
-#include "runtime.h"
-#include "malloc.h"
-
-func Alloc(n uintptr) (p *byte) {
- p = malloc(n);
-}
-
-func Free(p *byte) {
- free(p);
-}
-
-func Lookup(p *byte) (base *byte, size uintptr) {
- mlookup(p, &base, &size, nil);
-}
-
-func GetStats() (s *MStats) {
- s = &mstats;
-}
-
-func GC() {
- gc(1);
-}
-
diff --git a/src/lib/runtime/mcache.c b/src/lib/runtime/mcache.c
deleted file mode 100644
index ae2594023..000000000
--- a/src/lib/runtime/mcache.c
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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.
-
-// Per-thread (in Go, per-M) malloc cache for small objects.
-//
-// See malloc.h for an overview.
-
-#include "runtime.h"
-#include "malloc.h"
-
-void*
-MCache_Alloc(MCache *c, int32 sizeclass, uintptr size)
-{
- MCacheList *l;
- MLink *first, *v;
- int32 n;
-
- // Allocate from list.
- l = &c->list[sizeclass];
- if(l->list == nil) {
- // Replenish using central lists.
- n = MCentral_AllocList(&mheap.central[sizeclass],
- class_to_transfercount[sizeclass], &first);
- l->list = first;
- l->nlist = n;
- c->size += n*size;
- }
- v = l->list;
- l->list = v->next;
- l->nlist--;
- if(l->nlist < l->nlistmin)
- l->nlistmin = l->nlist;
- c->size -= size;
-
- // v is zeroed except for the link pointer
- // that we used above; zero that.
- v->next = nil;
- return v;
-}
-
-// Take n elements off l and return them to the central free list.
-static void
-ReleaseN(MCache *c, MCacheList *l, int32 n, int32 sizeclass)
-{
- MLink *first, **lp;
- int32 i;
-
- // Cut off first n elements.
- first = l->list;
- lp = &l->list;
- for(i=0; i<n; i++)
- lp = &(*lp)->next;
- l->list = *lp;
- *lp = nil;
- l->nlist -= n;
- if(l->nlist < l->nlistmin)
- l->nlistmin = l->nlist;
- c->size -= n*class_to_size[sizeclass];
-
- // Return them to central free list.
- MCentral_FreeList(&mheap.central[sizeclass], n, first);
-}
-
-void
-MCache_Free(MCache *c, void *v, int32 sizeclass, uintptr size)
-{
- int32 i, n;
- MCacheList *l;
- MLink *p;
-
- // Put back on list.
- l = &c->list[sizeclass];
- p = v;
- p->next = l->list;
- l->list = p;
- l->nlist++;
- c->size += size;
-
- if(l->nlist >= MaxMCacheListLen) {
- // Release a chunk back.
- ReleaseN(c, l, class_to_transfercount[sizeclass], sizeclass);
- }
-
- if(c->size >= MaxMCacheSize) {
- // Scavenge.
- for(i=0; i<NumSizeClasses; i++) {
- l = &c->list[i];
- n = l->nlistmin;
-
- // n is the minimum number of elements we've seen on
- // the list since the last scavenge. If n > 0, it means that
- // we could have gotten by with n fewer elements
- // without needing to consult the central free list.
- // Move toward that situation by releasing n/2 of them.
- if(n > 0) {
- if(n > 1)
- n /= 2;
- ReleaseN(c, l, n, i);
- }
- l->nlistmin = l->nlist;
- }
- }
-}
-
diff --git a/src/lib/runtime/mcentral.c b/src/lib/runtime/mcentral.c
deleted file mode 100644
index 5c9f720c0..000000000
--- a/src/lib/runtime/mcentral.c
+++ /dev/null
@@ -1,192 +0,0 @@
-// 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.
-
-// Central free lists.
-//
-// See malloc.h for an overview.
-//
-// The MCentral doesn't actually contain the list of free objects; the MSpan does.
-// Each MCentral is two lists of MSpans: those with free objects (c->nonempty)
-// and those that are completely allocated (c->empty).
-//
-// TODO(rsc): tcmalloc uses a "transfer cache" to split the list
-// into sections of class_to_transfercount[sizeclass] objects
-// so that it is faster to move those lists between MCaches and MCentrals.
-
-#include "runtime.h"
-#include "malloc.h"
-
-static bool MCentral_Grow(MCentral *c);
-static void* MCentral_Alloc(MCentral *c);
-static void MCentral_Free(MCentral *c, void *v);
-
-// Initialize a single central free list.
-void
-MCentral_Init(MCentral *c, int32 sizeclass)
-{
- c->sizeclass = sizeclass;
- MSpanList_Init(&c->nonempty);
- MSpanList_Init(&c->empty);
-}
-
-// Allocate up to n objects from the central free list.
-// Return the number of objects allocated.
-// The objects are linked together by their first words.
-// On return, *pstart points at the first object and *pend at the last.
-int32
-MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
-{
- MLink *first, *last, *v;
- int32 i;
-
-
- lock(c);
- // Replenish central list if empty.
- if(MSpanList_IsEmpty(&c->nonempty)) {
- if(!MCentral_Grow(c)) {
- unlock(c);
- *pfirst = nil;
- return 0;
- }
- }
-
- // Copy from list, up to n.
- // First one is guaranteed to work, because we just grew the list.
- first = MCentral_Alloc(c);
- last = first;
- for(i=1; i<n && (v = MCentral_Alloc(c)) != nil; i++) {
- last->next = v;
- last = v;
- }
- last->next = nil;
- c->nfree -= i;
-
- unlock(c);
- *pfirst = first;
- return i;
-}
-
-// Helper: allocate one object from the central free list.
-static void*
-MCentral_Alloc(MCentral *c)
-{
- MSpan *s;
- MLink *v;
-
- if(MSpanList_IsEmpty(&c->nonempty))
- return nil;
- s = c->nonempty.next;
- s->ref++;
- v = s->freelist;
- s->freelist = v->next;
- if(s->freelist == nil) {
- MSpanList_Remove(s);
- MSpanList_Insert(&c->empty, s);
- }
- return v;
-}
-
-// Free n objects back into the central free list.
-// Return the number of objects allocated.
-// The objects are linked together by their first words.
-// On return, *pstart points at the first object and *pend at the last.
-void
-MCentral_FreeList(MCentral *c, int32 n, MLink *start)
-{
- MLink *v, *next;
-
- // Assume next == nil marks end of list.
- // n and end would be useful if we implemented
- // the transfer cache optimization in the TODO above.
- USED(n);
-
- lock(c);
- for(v=start; v; v=next) {
- next = v->next;
- MCentral_Free(c, v);
- }
- unlock(c);
-}
-
-// Helper: free one object back into the central free list.
-static void
-MCentral_Free(MCentral *c, void *v)
-{
- MSpan *s;
- PageID page;
- MLink *p, *next;
-
- // Find span for v.
- page = (uintptr)v >> PageShift;
- s = MHeap_Lookup(&mheap, page);
- if(s == nil || s->ref == 0)
- throw("invalid free");
-
- // Move to nonempty if necessary.
- if(s->freelist == nil) {
- MSpanList_Remove(s);
- MSpanList_Insert(&c->nonempty, s);
- }
-
- // Add v back to s's free list.
- p = v;
- p->next = s->freelist;
- s->freelist = p;
- c->nfree++;
-
- // If s is completely freed, return it to the heap.
- if(--s->ref == 0) {
- MSpanList_Remove(s);
- // Freed blocks are zeroed except for the link pointer.
- // Zero the link pointers so that the page is all zero.
- for(p=s->freelist; p; p=next) {
- next = p->next;
- p->next = nil;
- }
- s->freelist = nil;
- c->nfree -= (s->npages << PageShift) / class_to_size[c->sizeclass];
- unlock(c);
- MHeap_Free(&mheap, s);
- lock(c);
- }
-}
-
-// Fetch a new span from the heap and
-// carve into objects for the free list.
-static bool
-MCentral_Grow(MCentral *c)
-{
- int32 i, n, npages, size;
- MLink **tailp, *v;
- byte *p;
- MSpan *s;
-
- unlock(c);
- npages = class_to_allocnpages[c->sizeclass];
- s = MHeap_Alloc(&mheap, npages, c->sizeclass);
- if(s == nil) {
- // TODO(rsc): Log out of memory
- lock(c);
- return false;
- }
-
- // Carve span into sequence of blocks.
- tailp = &s->freelist;
- p = (byte*)(s->start << PageShift);
- size = class_to_size[c->sizeclass];
- n = (npages << PageShift) / (size + RefcountOverhead);
- s->gcref = (uint32*)(p + size*n);
- for(i=0; i<n; i++) {
- v = (MLink*)p;
- *tailp = v;
- tailp = &v->next;
- p += size;
- }
- *tailp = nil;
-
- lock(c);
- c->nfree += n;
- MSpanList_Insert(&c->nonempty, s);
- return true;
-}
diff --git a/src/lib/runtime/mem.c b/src/lib/runtime/mem.c
deleted file mode 100644
index 7ed299eb0..000000000
--- a/src/lib/runtime/mem.c
+++ /dev/null
@@ -1,75 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "defs.h"
-
-// Stubs for memory management.
-// In a separate file so they can be overridden during testing of gc.
-
-enum
-{
- NHUNK = 20<<20,
-};
-
-// Convenient wrapper around mmap.
-static void*
-brk(uint32 n)
-{
- byte *v;
-
- v = sys_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
- m->mem.nmmap += n;
- return v;
-}
-
-// Allocate n bytes of memory. Note that this gets used
-// to allocate new stack segments, so at each call to a function
-// you have to ask yourself "would it be okay to call mal recursively
-// right here?" The answer is yes unless we're in the middle of
-// editing the malloc state in m->mem.
-void*
-oldmal(uint32 n)
-{
- byte* v;
-
- // round to keep everything 64-bit aligned
- n = rnd(n, 8);
-
- // be careful. calling any function might invoke
- // mal to allocate more stack.
- if(n > NHUNK) {
- v = brk(n);
- } else {
- // allocate a new hunk if this one is too small
- if(n > m->mem.nhunk) {
- // here we're in the middle of editing m->mem
- // (we're about to overwrite m->mem.hunk),
- // so we can't call brk - it might call mal to grow the
- // stack, and the recursive call would allocate a new
- // hunk, and then once brk returned we'd immediately
- // overwrite that hunk with our own.
- // (the net result would be a memory leak, not a crash.)
- // so we have to call sys_mmap directly - it is written
- // in assembly and tagged not to grow the stack.
- m->mem.hunk =
- sys_mmap(nil, NHUNK, PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_ANON|MAP_PRIVATE, 0, 0);
- m->mem.nhunk = NHUNK;
- m->mem.nmmap += NHUNK;
- }
- v = m->mem.hunk;
- m->mem.hunk += n;
- m->mem.nhunk -= n;
- }
- m->mem.nmal += n;
- return v;
-}
-
-void
-sys_mal(uint32 n, uint8 *ret)
-{
- ret = mal(n);
- FLUSH(&ret);
-}
diff --git a/src/lib/runtime/mfixalloc.c b/src/lib/runtime/mfixalloc.c
deleted file mode 100644
index dd4f3f251..000000000
--- a/src/lib/runtime/mfixalloc.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-// Fixed-size object allocator. Returned memory is not zeroed.
-//
-// See malloc.h for overview.
-
-#include "runtime.h"
-#include "malloc.h"
-
-// Initialize f to allocate objects of the given size,
-// using the allocator to obtain chunks of memory.
-void
-FixAlloc_Init(FixAlloc *f, uintptr size, void *(*alloc)(uintptr), void (*first)(void*, byte*), void *arg)
-{
- f->size = size;
- f->alloc = alloc;
- f->first = first;
- f->arg = arg;
- f->list = nil;
- f->chunk = nil;
- f->nchunk = 0;
-}
-
-void*
-FixAlloc_Alloc(FixAlloc *f)
-{
- void *v;
-
- if(f->list) {
- v = f->list;
- f->list = *(void**)f->list;
- return v;
- }
- if(f->nchunk < f->size) {
- f->chunk = f->alloc(FixAllocChunk);
- if(f->chunk == nil)
- throw("out of memory (FixAlloc)");
- f->nchunk = FixAllocChunk;
- }
- v = f->chunk;
- if(f->first)
- f->first(f->arg, v);
- f->chunk += f->size;
- f->nchunk -= f->size;
- return v;
-}
-
-void
-FixAlloc_Free(FixAlloc *f, void *p)
-{
- *(void**)p = f->list;
- f->list = p;
-}
-
diff --git a/src/lib/runtime/mgc0.c b/src/lib/runtime/mgc0.c
deleted file mode 100644
index d58d6ce44..000000000
--- a/src/lib/runtime/mgc0.c
+++ /dev/null
@@ -1,231 +0,0 @@
-// 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.
-
-// Garbage collector -- step 0.
-//
-// Stop the world, mark and sweep garbage collector.
-// NOT INTENDED FOR PRODUCTION USE.
-//
-// A mark and sweep collector provides a way to exercise
-// and test the memory allocator and the stack walking machinery
-// without also needing to get reference counting
-// exactly right.
-
-#include "runtime.h"
-#include "malloc.h"
-
-enum {
- Debug = 0
-};
-
-extern byte etext[];
-extern byte end[];
-
-enum {
- PtrSize = sizeof(void*)
-};
-
-static void
-scanblock(int32 depth, byte *b, int64 n)
-{
- int32 off;
- void *obj;
- uintptr size;
- uint32 *ref;
- void **vp;
- int64 i;
-
- if(Debug)
- printf("%d scanblock %p %D\n", depth, b, n);
- off = (uint32)(uintptr)b & (PtrSize-1);
- if(off) {
- b += PtrSize - off;
- n -= PtrSize - off;
- }
-
- vp = (void**)b;
- n /= PtrSize;
- for(i=0; i<n; i++) {
- if(mlookup(vp[i], &obj, &size, &ref)) {
- if(*ref == RefFree || *ref == RefStack)
- continue;
- if(*ref == RefNone) {
- if(Debug)
- printf("%d found at %p: ", depth, &vp[i]);
- *ref = RefSome;
- scanblock(depth+1, obj, size);
- }
- }
- }
-}
-
-static void
-scanstack(G *g)
-{
- Stktop *stk;
- byte *sp;
-
- sp = g->sched.SP;
- stk = (Stktop*)g->stackbase;
- while(stk) {
- scanblock(0, sp, (byte*)stk - sp);
- sp = stk->oldsp;
- stk = (Stktop*)stk->oldbase;
- }
-}
-
-static void
-mark(void)
-{
- G *gp;
-
- // mark data+bss
- scanblock(0, etext, end - etext);
-
- // mark stacks
- for(gp=allg; gp!=nil; gp=gp->alllink) {
- switch(gp->status){
- default:
- printf("unexpected G.status %d\n", gp->status);
- throw("mark - bad status");
- case Gdead:
- break;
- case Grunning:
- if(gp != g)
- throw("mark - world not stopped");
- scanstack(gp);
- break;
- case Grunnable:
- case Gsyscall:
- case Gwaiting:
- scanstack(gp);
- break;
- }
- }
-}
-
-static void
-sweepspan(MSpan *s)
-{
- int32 i, n, npages, size;
- byte *p;
-
- if(s->state != MSpanInUse)
- return;
-
- p = (byte*)(s->start << PageShift);
- if(s->sizeclass == 0) {
- // Large block.
- switch(s->gcref0) {
- default:
- throw("bad 'ref count'");
- case RefFree:
- case RefManual:
- case RefStack:
- break;
- case RefNone:
- if(Debug)
- printf("free %D at %p\n", (uint64)s->npages<<PageShift, p);
- free(p);
- break;
- case RefSome:
- s->gcref0 = RefNone; // set up for next mark phase
- break;
- }
- return;
- }
-
- // Chunk full of small blocks.
- // Must match computation in MCentral_Grow.
- size = class_to_size[s->sizeclass];
- npages = class_to_allocnpages[s->sizeclass];
- n = (npages << PageShift) / (size + RefcountOverhead);
- for(i=0; i<n; i++) {
- switch(s->gcref[i]) {
- default:
- throw("bad 'ref count'");
- case RefFree:
- case RefManual:
- case RefStack:
- break;
- case RefNone:
- if(Debug)
- printf("free %d at %p\n", size, p+i*size);
- free(p + i*size);
- break;
- case RefSome:
- s->gcref[i] = RefNone; // set up for next mark phase
- break;
- }
- }
-}
-
-static void
-sweep(void)
-{
- MSpan *s;
-
- // Sweep all the spans.
- for(s = mheap.allspans; s != nil; s = s->allnext)
- sweepspan(s);
-}
-
-// Semaphore, not Lock, so that the goroutine
-// reschedules when there is contention rather
-// than spinning.
-static uint32 gcsema = 1;
-
-// Initialized from $GOGC. GOGC=off means no gc.
-//
-// Next gc is after we've allocated an extra amount of
-// memory proportional to the amount already in use.
-// If gcpercent=100 and we're using 4M, we'll gc again
-// when we get to 8M. This keeps the gc cost in linear
-// proportion to the allocation cost. Adjusting gcpercent
-// just changes the linear constant (and also the amount of
-// extra memory used).
-static int32 gcpercent = -2;
-
-void
-gc(int32 force)
-{
- byte *p;
-
- // The gc is turned off (via enablegc) until
- // the bootstrap has completed.
- // Also, malloc gets called in the guts
- // of a number of libraries that might be
- // holding locks. To avoid priority inversion
- // problems, don't bother trying to run gc
- // while holding a lock. The next mallocgc
- // without a lock will do the gc instead.
- if(!mstats.enablegc || m->locks > 0 || panicking)
- return;
-
- if(gcpercent == -2) { // first time through
- p = getenv("GOGC");
- if(p == nil || p[0] == '\0')
- gcpercent = 100;
- else if(strcmp(p, (byte*)"off") == 0)
- gcpercent = -1;
- else
- gcpercent = atoi(p);
- }
- if(gcpercent < 0)
- return;
-
- semacquire(&gcsema);
- gosave(&g->sched); // update g's stack pointer for scanstack
- stoptheworld();
- if(mheap.Lock.key != 0)
- throw("mheap locked during gc");
- if(force || mstats.inuse_pages >= mstats.next_gc) {
- mark();
- sweep();
- mstats.next_gc = mstats.inuse_pages+mstats.inuse_pages*gcpercent/100;
- }
- starttheworld();
- gosave(&g->sched); // update g's stack pointer for debugging
- semrelease(&gcsema);
-}
diff --git a/src/lib/runtime/mheap.c b/src/lib/runtime/mheap.c
deleted file mode 100644
index d0cf2237b..000000000
--- a/src/lib/runtime/mheap.c
+++ /dev/null
@@ -1,333 +0,0 @@
-// 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.
-
-// Page heap.
-//
-// See malloc.h for overview.
-//
-// When a MSpan is in the heap free list, state == MSpanFree
-// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span.
-//
-// When a MSpan is allocated, state == MSpanInUse
-// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
-
-#include "runtime.h"
-#include "malloc.h"
-
-static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
-static bool MHeap_Grow(MHeap*, uintptr);
-static void MHeap_FreeLocked(MHeap*, MSpan*);
-static MSpan *MHeap_AllocLarge(MHeap*, uintptr);
-static MSpan *BestFit(MSpan*, uintptr, MSpan*);
-
-static void
-RecordSpan(void *vh, byte *p)
-{
- MHeap *h;
- MSpan *s;
-
- h = vh;
- s = (MSpan*)p;
- s->allnext = h->allspans;
- h->allspans = s;
-}
-
-// Initialize the heap; fetch memory using alloc.
-void
-MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
-{
- uint32 i;
-
- FixAlloc_Init(&h->spanalloc, sizeof(MSpan), alloc, RecordSpan, h);
- FixAlloc_Init(&h->cachealloc, sizeof(MCache), alloc, nil, nil);
- MHeapMap_Init(&h->map, alloc);
- // h->mapcache needs no init
- for(i=0; i<nelem(h->free); i++)
- MSpanList_Init(&h->free[i]);
- MSpanList_Init(&h->large);
- for(i=0; i<nelem(h->central); i++)
- MCentral_Init(&h->central[i], i);
-}
-
-// Allocate a new span of npage pages from the heap
-// and record its size class in the HeapMap and HeapMapCache.
-MSpan*
-MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass)
-{
- MSpan *s;
-
- lock(h);
- s = MHeap_AllocLocked(h, npage, sizeclass);
- if(s != nil)
- mstats.inuse_pages += npage;
- unlock(h);
- return s;
-}
-
-static MSpan*
-MHeap_AllocLocked(MHeap *h, uintptr npage, int32 sizeclass)
-{
- uintptr n;
- MSpan *s, *t;
-
- // Try in fixed-size lists up to max.
- for(n=npage; n < nelem(h->free); n++) {
- if(!MSpanList_IsEmpty(&h->free[n])) {
- s = h->free[n].next;
- goto HaveSpan;
- }
- }
-
- // Best fit in list of large spans.
- if((s = MHeap_AllocLarge(h, npage)) == nil) {
- if(!MHeap_Grow(h, npage))
- return nil;
- if((s = MHeap_AllocLarge(h, npage)) == nil)
- return nil;
- }
-
-HaveSpan:
- // Mark span in use.
- if(s->state != MSpanFree)
- throw("MHeap_AllocLocked - MSpan not free");
- if(s->npages < npage)
- throw("MHeap_AllocLocked - bad npages");
- MSpanList_Remove(s);
- s->state = MSpanInUse;
-
- if(s->npages > npage) {
- // Trim extra and put it back in the heap.
- t = FixAlloc_Alloc(&h->spanalloc);
- MSpan_Init(t, s->start + npage, s->npages - npage);
- s->npages = npage;
- MHeapMap_Set(&h->map, t->start - 1, s);
- MHeapMap_Set(&h->map, t->start, t);
- MHeapMap_Set(&h->map, t->start + t->npages - 1, t);
- t->state = MSpanInUse;
- MHeap_FreeLocked(h, t);
- }
-
- // If span is being used for small objects, cache size class.
- // No matter what, cache span info, because gc needs to be
- // able to map interior pointer to containing span.
- s->sizeclass = sizeclass;
- for(n=0; n<npage; n++)
- MHeapMap_Set(&h->map, s->start+n, s);
- if(sizeclass == 0) {
- uintptr tmp;
-
- // If there are entries for this span, invalidate them,
- // but don't blow out cache entries about other spans.
- for(n=0; n<npage; n++)
- if(MHeapMapCache_GET(&h->mapcache, s->start+n, tmp) != 0)
- MHeapMapCache_SET(&h->mapcache, s->start+n, 0);
- } else {
- // Save cache entries for this span.
- // If there's a size class, there aren't that many pages.
- for(n=0; n<npage; n++)
- MHeapMapCache_SET(&h->mapcache, s->start+n, sizeclass);
- }
-
- return s;
-}
-
-// Allocate a span of exactly npage pages from the list of large spans.
-static MSpan*
-MHeap_AllocLarge(MHeap *h, uintptr npage)
-{
- return BestFit(&h->large, npage, nil);
-}
-
-// Search list for smallest span with >= npage pages.
-// If there are multiple smallest spans, take the one
-// with the earliest starting address.
-static MSpan*
-BestFit(MSpan *list, uintptr npage, MSpan *best)
-{
- MSpan *s;
-
- for(s=list->next; s != list; s=s->next) {
- if(s->npages < npage)
- continue;
- if(best == nil
- || s->npages < best->npages
- || (s->npages == best->npages && s->start < best->start))
- best = s;
- }
- return best;
-}
-
-// Try to add at least npage pages of memory to the heap,
-// returning whether it worked.
-static bool
-MHeap_Grow(MHeap *h, uintptr npage)
-{
- uintptr ask;
- void *v;
- MSpan *s;
-
- // Ask for a big chunk, to reduce the number of mappings
- // the operating system needs to track; also amortizes
- // the overhead of an operating system mapping.
- ask = npage<<PageShift;
- if(ask < HeapAllocChunk)
- ask = HeapAllocChunk;
-
- v = SysAlloc(ask);
- if(v == nil) {
- if(ask > (npage<<PageShift)) {
- ask = npage<<PageShift;
- v = SysAlloc(ask);
- }
- if(v == nil)
- return false;
- }
-
- // NOTE(rsc): In tcmalloc, if we've accumulated enough
- // system allocations, the heap map gets entirely allocated
- // in 32-bit mode. (In 64-bit mode that's not practical.)
-
- if(!MHeapMap_Preallocate(&h->map, ((uintptr)v>>PageShift) - 1, (ask>>PageShift) + 2)) {
- SysFree(v, ask);
- return false;
- }
-
- // Create a fake "in use" span and free it, so that the
- // right coalescing happens.
- s = FixAlloc_Alloc(&h->spanalloc);
- MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift);
- MHeapMap_Set(&h->map, s->start, s);
- MHeapMap_Set(&h->map, s->start + s->npages - 1, s);
- s->state = MSpanInUse;
- MHeap_FreeLocked(h, s);
- return true;
-}
-
-// Look up the span at the given page number.
-// Page number is guaranteed to be in map
-// and is guaranteed to be start or end of span.
-MSpan*
-MHeap_Lookup(MHeap *h, PageID p)
-{
- return MHeapMap_Get(&h->map, p);
-}
-
-// Look up the span at the given page number.
-// Page number is *not* guaranteed to be in map
-// and may be anywhere in the span.
-// Map entries for the middle of a span are only
-// valid for allocated spans. Free spans may have
-// other garbage in their middles, so we have to
-// check for that.
-MSpan*
-MHeap_LookupMaybe(MHeap *h, PageID p)
-{
- MSpan *s;
-
- s = MHeapMap_GetMaybe(&h->map, p);
- if(s == nil || p < s->start || p - s->start >= s->npages)
- return nil;
- if(s->state != MSpanInUse)
- return nil;
- return s;
-}
-
-// Free the span back into the heap.
-void
-MHeap_Free(MHeap *h, MSpan *s)
-{
- lock(h);
- mstats.inuse_pages -= s->npages;
- MHeap_FreeLocked(h, s);
- unlock(h);
-}
-
-static void
-MHeap_FreeLocked(MHeap *h, MSpan *s)
-{
- MSpan *t;
-
- if(s->state != MSpanInUse || s->ref != 0) {
- printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref);
- throw("MHeap_FreeLocked - invalid free");
- }
- s->state = MSpanFree;
- MSpanList_Remove(s);
-
- // Coalesce with earlier, later spans.
- if((t = MHeapMap_Get(&h->map, s->start - 1)) != nil && t->state != MSpanInUse) {
- s->start = t->start;
- s->npages += t->npages;
- MHeapMap_Set(&h->map, s->start, s);
- MSpanList_Remove(t);
- t->state = MSpanDead;
- FixAlloc_Free(&h->spanalloc, t);
- }
- if((t = MHeapMap_Get(&h->map, s->start + s->npages)) != nil && t->state != MSpanInUse) {
- s->npages += t->npages;
- MHeapMap_Set(&h->map, s->start + s->npages - 1, s);
- MSpanList_Remove(t);
- t->state = MSpanDead;
- FixAlloc_Free(&h->spanalloc, t);
- }
-
- // Insert s into appropriate list.
- if(s->npages < nelem(h->free))
- MSpanList_Insert(&h->free[s->npages], s);
- else
- MSpanList_Insert(&h->large, s);
-
- // TODO(rsc): IncrementalScavenge() to return memory to OS.
-}
-
-// Initialize a new span with the given start and npages.
-void
-MSpan_Init(MSpan *span, PageID start, uintptr npages)
-{
- span->next = nil;
- span->prev = nil;
- span->start = start;
- span->npages = npages;
- span->freelist = nil;
- span->ref = 0;
- span->sizeclass = 0;
- span->state = 0;
-}
-
-// Initialize an empty doubly-linked list.
-void
-MSpanList_Init(MSpan *list)
-{
- list->state = MSpanListHead;
- list->next = list;
- list->prev = list;
-}
-
-void
-MSpanList_Remove(MSpan *span)
-{
- if(span->prev == nil && span->next == nil)
- return;
- span->prev->next = span->next;
- span->next->prev = span->prev;
- span->prev = nil;
- span->next = nil;
-}
-
-bool
-MSpanList_IsEmpty(MSpan *list)
-{
- return list->next == list;
-}
-
-void
-MSpanList_Insert(MSpan *list, MSpan *span)
-{
- if(span->next != nil || span->prev != nil)
- throw("MSpanList_Insert");
- span->next = list->next;
- span->prev = list;
- span->next->prev = span;
- span->prev->next = span;
-}
diff --git a/src/lib/runtime/mheapmap32.c b/src/lib/runtime/mheapmap32.c
deleted file mode 100644
index 420ca2d83..000000000
--- a/src/lib/runtime/mheapmap32.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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.
-
-// Heap map, 32-bit version
-// See malloc.h and mheap.c for overview.
-
-#include "runtime.h"
-#include "malloc.h"
-
-// 3-level radix tree mapping page ids to Span*.
-void
-MHeapMap_Init(MHeapMap *m, void *(*allocator)(size_t))
-{
- m->allocator = allocator;
-}
-
-MSpan*
-MHeapMap_Get(MHeapMap *m, PageID k)
-{
- int32 i1, i2;
-
- i2 = k & MHeapMap_Level2Mask;
- k >>= MHeapMap_Level2Bits;
- i1 = k & MHeapMap_Level1Mask;
- k >>= MHeapMap_Level1Bits;
- if(k != 0)
- throw("MHeapMap_Get");
-
- return m->p[i1]->s[i2];
-}
-
-MSpan*
-MHeapMap_GetMaybe(MHeapMap *m, PageID k)
-{
- int32 i1, i2;
- MHeapMapNode2 *p2;
-
- i2 = k & MHeapMap_Level2Mask;
- k >>= MHeapMap_Level2Bits;
- i1 = k & MHeapMap_Level1Mask;
- k >>= MHeapMap_Level1Bits;
- if(k != 0)
- throw("MHeapMap_Get");
-
- p2 = m->p[i1];
- if(p2 == nil)
- return nil;
- return p2->s[i2];
-}
-
-void
-MHeapMap_Set(MHeapMap *m, PageID k, MSpan *s)
-{
- int32 i1, i2;
-
- i2 = k & MHeapMap_Level2Mask;
- k >>= MHeapMap_Level2Bits;
- i1 = k & MHeapMap_Level1Mask;
- k >>= MHeapMap_Level1Bits;
- if(k != 0)
- throw("MHeapMap_Set");
-
- m->p[i1]->s[i2] = s;
-}
-
-// Allocate the storage required for entries [k, k+1, ..., k+len-1]
-// so that Get and Set calls need not check for nil pointers.
-bool
-MHeapMap_Preallocate(MHeapMap *m, PageID k, uintptr len)
-{
- uintptr end;
- int32 i1;
- MHeapMapNode2 *p2;
-
- end = k+len;
- while(k < end) {
- if((k >> MHeapMap_TotalBits) != 0)
- return false;
- i1 = (k >> MHeapMap_Level2Bits) & MHeapMap_Level1Mask;
-
- // first-level pointer
- if(m->p[i1] == nil) {
- p2 = m->allocator(sizeof *p2);
- if(p2 == nil)
- return false;
- sys_memclr((byte*)p2, sizeof *p2);
- m->p[i1] = p2;
- }
-
- // advance key past this leaf node
- k = ((k >> MHeapMap_Level2Bits) + 1) << MHeapMap_Level2Bits;
- }
- return true;
-}
-
diff --git a/src/lib/runtime/mheapmap32.h b/src/lib/runtime/mheapmap32.h
deleted file mode 100644
index 0a16ccd10..000000000
--- a/src/lib/runtime/mheapmap32.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
-
-// Free(v) must be able to determine the MSpan containing v.
-// The MHeapMap is a 2-level radix tree mapping page numbers to MSpans.
-
-typedef struct MHeapMapNode2 MHeapMapNode2;
-
-enum
-{
- // 32 bit address - 12 bit page size = 20 bits to map
- MHeapMap_Level1Bits = 10,
- MHeapMap_Level2Bits = 10,
-
- MHeapMap_TotalBits =
- MHeapMap_Level1Bits +
- MHeapMap_Level2Bits,
-
- MHeapMap_Level1Mask = (1<<MHeapMap_Level1Bits) - 1,
- MHeapMap_Level2Mask = (1<<MHeapMap_Level2Bits) - 1,
-};
-
-struct MHeapMap
-{
- void *(*allocator)(uintptr);
- MHeapMapNode2 *p[1<<MHeapMap_Level1Bits];
-};
-
-struct MHeapMapNode2
-{
- MSpan *s[1<<MHeapMap_Level2Bits];
-};
-
-void MHeapMap_Init(MHeapMap *m, void *(*allocator)(uintptr));
-bool MHeapMap_Preallocate(MHeapMap *m, PageID k, uintptr npages);
-MSpan* MHeapMap_Get(MHeapMap *m, PageID k);
-MSpan* MHeapMap_GetMaybe(MHeapMap *m, PageID k);
-void MHeapMap_Set(MHeapMap *m, PageID k, MSpan *v);
-
-
-// Much of the time, free(v) needs to know only the size class for v,
-// not which span it came from. The MHeapMap finds the size class
-// by looking up the span.
-//
-// An MHeapMapCache is a simple direct-mapped cache translating
-// page numbers to size classes. It avoids the expensive MHeapMap
-// lookup for hot pages.
-//
-// The cache entries are 32 bits, with the page number in the low part
-// and the value at the top.
-//
-// NOTE(rsc): On a machine with 32-bit addresses (= 20-bit page numbers),
-// we can use a 16-bit cache entry by not storing the redundant 12 bits
-// of the key that are used as the entry index. For now, keep it simple.
-enum
-{
- MHeapMapCache_HashBits = 12
-};
-
-struct MHeapMapCache
-{
- uint32 array[1<<MHeapMapCache_HashBits];
-};
-
-// All macros for speed (sorry).
-#define HMASK ((1<<MHeapMapCache_HashBits)-1)
-#define KBITS MHeapMap_TotalBits
-#define KMASK ((1LL<<KBITS)-1)
-
-#define MHeapMapCache_SET(cache, key, value) \
- ((cache)->array[(key) & HMASK] = (key) | ((uintptr)(value) << KBITS))
-
-#define MHeapMapCache_GET(cache, key, tmp) \
- (tmp = (cache)->array[(key) & HMASK], \
- (tmp & KMASK) == (key) ? (tmp >> KBITS) : 0)
diff --git a/src/lib/runtime/mheapmap64.c b/src/lib/runtime/mheapmap64.c
deleted file mode 100644
index 1886ba529..000000000
--- a/src/lib/runtime/mheapmap64.c
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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.
-
-// Heap map, 64-bit version
-// See malloc.h and mheap.c for overview.
-
-#include "runtime.h"
-#include "malloc.h"
-
-// 3-level radix tree mapping page ids to Span*.
-void
-MHeapMap_Init(MHeapMap *m, void *(*allocator)(size_t))
-{
- m->allocator = allocator;
-}
-
-MSpan*
-MHeapMap_Get(MHeapMap *m, PageID k)
-{
- int32 i1, i2, i3;
-
- i3 = k & MHeapMap_Level3Mask;
- k >>= MHeapMap_Level3Bits;
- i2 = k & MHeapMap_Level2Mask;
- k >>= MHeapMap_Level2Bits;
- i1 = k & MHeapMap_Level1Mask;
- k >>= MHeapMap_Level1Bits;
- if(k != 0)
- throw("MHeapMap_Get");
-
- return m->p[i1]->p[i2]->s[i3];
-}
-
-MSpan*
-MHeapMap_GetMaybe(MHeapMap *m, PageID k)
-{
- int32 i1, i2, i3;
- MHeapMapNode2 *p2;
- MHeapMapNode3 *p3;
-
- i3 = k & MHeapMap_Level3Mask;
- k >>= MHeapMap_Level3Bits;
- i2 = k & MHeapMap_Level2Mask;
- k >>= MHeapMap_Level2Bits;
- i1 = k & MHeapMap_Level1Mask;
- k >>= MHeapMap_Level1Bits;
- if(k != 0)
- throw("MHeapMap_Get");
-
- p2 = m->p[i1];
- if(p2 == nil)
- return nil;
- p3 = p2->p[i2];
- if(p3 == nil)
- return nil;
- return p3->s[i3];
-}
-
-void
-MHeapMap_Set(MHeapMap *m, PageID k, MSpan *s)
-{
- int32 i1, i2, i3;
-
- i3 = k & MHeapMap_Level3Mask;
- k >>= MHeapMap_Level3Bits;
- i2 = k & MHeapMap_Level2Mask;
- k >>= MHeapMap_Level2Bits;
- i1 = k & MHeapMap_Level1Mask;
- k >>= MHeapMap_Level1Bits;
- if(k != 0)
- throw("MHeapMap_Set");
-
- m->p[i1]->p[i2]->s[i3] = s;
-}
-
-// Allocate the storage required for entries [k, k+1, ..., k+len-1]
-// so that Get and Set calls need not check for nil pointers.
-bool
-MHeapMap_Preallocate(MHeapMap *m, PageID k, uintptr len)
-{
- uintptr end;
- int32 i1, i2;
- MHeapMapNode2 *p2;
- MHeapMapNode3 *p3;
-
- end = k+len;
- while(k < end) {
- if((k >> MHeapMap_TotalBits) != 0)
- return false;
- i2 = (k >> MHeapMap_Level3Bits) & MHeapMap_Level2Mask;
- i1 = (k >> (MHeapMap_Level3Bits + MHeapMap_Level2Bits)) & MHeapMap_Level1Mask;
-
- // first-level pointer
- if((p2 = m->p[i1]) == nil) {
- p2 = m->allocator(sizeof *p2);
- if(p2 == nil)
- return false;
- sys_memclr((byte*)p2, sizeof *p2);
- m->p[i1] = p2;
- }
-
- // second-level pointer
- if(p2->p[i2] == nil) {
- p3 = m->allocator(sizeof *p3);
- if(p3 == nil)
- return false;
- sys_memclr((byte*)p3, sizeof *p3);
- p2->p[i2] = p3;
- }
-
- // advance key past this leaf node
- k = ((k >> MHeapMap_Level3Bits) + 1) << MHeapMap_Level3Bits;
- }
- return true;
-}
-
diff --git a/src/lib/runtime/mheapmap64.h b/src/lib/runtime/mheapmap64.h
deleted file mode 100644
index 127b773f7..000000000
--- a/src/lib/runtime/mheapmap64.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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.
-
-// Free(v) must be able to determine the MSpan containing v.
-// The MHeapMap is a 3-level radix tree mapping page numbers to MSpans.
-//
-// NOTE(rsc): On a 32-bit platform (= 20-bit page numbers),
-// we can swap in a 2-level radix tree.
-//
-// NOTE(rsc): We use a 3-level tree because tcmalloc does, but
-// having only three levels requires approximately 1 MB per node
-// in the tree, making the minimum map footprint 3 MB.
-// Using a 4-level tree would cut the minimum footprint to 256 kB.
-// On the other hand, it's just virtual address space: most of
-// the memory is never going to be touched, thus never paged in.
-
-typedef struct MHeapMapNode2 MHeapMapNode2;
-typedef struct MHeapMapNode3 MHeapMapNode3;
-
-enum
-{
- // 64 bit address - 12 bit page size = 52 bits to map
- MHeapMap_Level1Bits = 18,
- MHeapMap_Level2Bits = 18,
- MHeapMap_Level3Bits = 16,
-
- MHeapMap_TotalBits =
- MHeapMap_Level1Bits +
- MHeapMap_Level2Bits +
- MHeapMap_Level3Bits,
-
- MHeapMap_Level1Mask = (1<<MHeapMap_Level1Bits) - 1,
- MHeapMap_Level2Mask = (1<<MHeapMap_Level2Bits) - 1,
- MHeapMap_Level3Mask = (1<<MHeapMap_Level3Bits) - 1,
-};
-
-struct MHeapMap
-{
- void *(*allocator)(uintptr);
- MHeapMapNode2 *p[1<<MHeapMap_Level1Bits];
-};
-
-struct MHeapMapNode2
-{
- MHeapMapNode3 *p[1<<MHeapMap_Level2Bits];
-};
-
-struct MHeapMapNode3
-{
- MSpan *s[1<<MHeapMap_Level3Bits];
-};
-
-void MHeapMap_Init(MHeapMap *m, void *(*allocator)(uintptr));
-bool MHeapMap_Preallocate(MHeapMap *m, PageID k, uintptr npages);
-MSpan* MHeapMap_Get(MHeapMap *m, PageID k);
-MSpan* MHeapMap_GetMaybe(MHeapMap *m, PageID k);
-void MHeapMap_Set(MHeapMap *m, PageID k, MSpan *v);
-
-
-// Much of the time, free(v) needs to know only the size class for v,
-// not which span it came from. The MHeapMap finds the size class
-// by looking up the span.
-//
-// An MHeapMapCache is a simple direct-mapped cache translating
-// page numbers to size classes. It avoids the expensive MHeapMap
-// lookup for hot pages.
-//
-// The cache entries are 64 bits, with the page number in the low part
-// and the value at the top.
-//
-// NOTE(rsc): On a machine with 32-bit addresses (= 20-bit page numbers),
-// we can use a 16-bit cache entry by not storing the redundant 12 bits
-// of the key that are used as the entry index. Here in 64-bit land,
-// that trick won't work unless the hash table has 2^28 entries.
-enum
-{
- MHeapMapCache_HashBits = 12
-};
-
-struct MHeapMapCache
-{
- uintptr array[1<<MHeapMapCache_HashBits];
-};
-
-// All macros for speed (sorry).
-#define HMASK ((1<<MHeapMapCache_HashBits)-1)
-#define KBITS MHeapMap_TotalBits
-#define KMASK ((1LL<<KBITS)-1)
-
-#define MHeapMapCache_SET(cache, key, value) \
- ((cache)->array[(key) & HMASK] = (key) | ((uintptr)(value) << KBITS))
-
-#define MHeapMapCache_GET(cache, key, tmp) \
- (tmp = (cache)->array[(key) & HMASK], \
- (tmp & KMASK) == (key) ? (tmp >> KBITS) : 0)
diff --git a/src/lib/runtime/msize.c b/src/lib/runtime/msize.c
deleted file mode 100644
index 25e22637d..000000000
--- a/src/lib/runtime/msize.c
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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.
-
-// Malloc small size classes.
-//
-// See malloc.h for overview.
-//
-// The size classes are chosen so that rounding an allocation
-// request up to the next size class wastes at most 12.5% (1.125x).
-//
-// Each size class has its own page count that gets allocated
-// and chopped up when new objects of the size class are needed.
-// That page count is chosen so that chopping up the run of
-// pages into objects of the given size wastes at most 12.5% (1.125x)
-// of the memory. It is not necessary that the cutoff here be
-// the same as above.
-//
-// The two sources of waste multiply, so the worst possible case
-// for the above constraints would be that allocations of some
-// size might have a 26.6% (1.266x) overhead.
-// In practice, only one of the wastes comes into play for a
-// given size (sizes < 512 waste mainly on the round-up,
-// sizes > 512 waste mainly on the page chopping).
-//
-// TODO(rsc): Compute max waste for any given size.
-
-#include "runtime.h"
-#include "malloc.h"
-
-int32 class_to_size[NumSizeClasses];
-int32 class_to_allocnpages[NumSizeClasses];
-int32 class_to_transfercount[NumSizeClasses];
-
-// The SizeToClass lookup is implemented using two arrays,
-// one mapping sizes <= 1024 to their class and one mapping
-// sizes >= 1024 and <= MaxSmallSize to their class.
-// All objects are 8-aligned, so the first array is indexed by
-// the size divided by 8 (rounded up). Objects >= 1024 bytes
-// are 128-aligned, so the second array is indexed by the
-// size divided by 128 (rounded up). The arrays are filled in
-// by InitSizes.
-
-static int32 size_to_class8[1024/8 + 1];
-static int32 size_to_class128[(MaxSmallSize-1024)/128 + 1];
-
-int32
-SizeToClass(int32 size)
-{
- if(size > MaxSmallSize)
- throw("SizeToClass - invalid size");
- if(size > 1024-8)
- return size_to_class128[(size-1024+127) >> 7];
- return size_to_class8[(size+7)>>3];
-}
-
-void
-InitSizes(void)
-{
- int32 align, sizeclass, size, osize, nextsize, n;
- uint32 i;
- uintptr allocsize, npages;
-
- // Initialize the class_to_size table (and choose class sizes in the process).
- class_to_size[0] = 0;
- sizeclass = 1; // 0 means no class
- align = 8;
- for(size = align; size <= MaxSmallSize; size += align) {
- if((size&(size-1)) == 0) { // bump alignment once in a while
- if(size >= 2048)
- align = 256;
- else if(size >= 128)
- align = size / 8;
- else if(size >= 16)
- align = 16; // required for x86 SSE instructions, if we want to use them
- }
- if((align&(align-1)) != 0)
- throw("InitSizes - bug");
-
- // Make the allocnpages big enough that
- // the leftover is less than 1/8 of the total,
- // so wasted space is at most 12.5%.
- allocsize = PageSize;
- osize = size + RefcountOverhead;
- while(allocsize%osize > (allocsize/8))
- allocsize += PageSize;
- npages = allocsize >> PageShift;
-
- // If the previous sizeclass chose the same
- // allocation size and fit the same number of
- // objects into the page, we might as well
- // use just this size instead of having two
- // different sizes.
- if(sizeclass > 1
- && npages == class_to_allocnpages[sizeclass-1]
- && allocsize/osize == allocsize/(class_to_size[sizeclass-1]+RefcountOverhead)) {
- class_to_size[sizeclass-1] = size;
- continue;
- }
-
- class_to_allocnpages[sizeclass] = npages;
- class_to_size[sizeclass] = size;
- sizeclass++;
- }
- if(sizeclass != NumSizeClasses) {
- printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses);
- throw("InitSizes - bad NumSizeClasses");
- }
-
- // Initialize the size_to_class tables.
- nextsize = 0;
- for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
- for(; nextsize < 1024 && nextsize <= class_to_size[sizeclass]; nextsize+=8)
- size_to_class8[nextsize/8] = sizeclass;
- if(nextsize >= 1024)
- for(; nextsize <= class_to_size[sizeclass]; nextsize += 128)
- size_to_class128[(nextsize-1024)/128] = sizeclass;
- }
-
- // Double-check SizeToClass.
- if(0) {
- for(n=0; n < MaxSmallSize; n++) {
- sizeclass = SizeToClass(n);
- if(sizeclass < 1 || sizeclass >= NumSizeClasses || class_to_size[sizeclass] < n) {
- printf("size=%d sizeclass=%d class_to_size=%d\n", n, sizeclass, class_to_size[sizeclass]);
- printf("incorrect SizeToClass");
- goto dump;
- }
- if(sizeclass > 1 && class_to_size[sizeclass-1] >= n) {
- printf("size=%d sizeclass=%d class_to_size=%d\n", n, sizeclass, class_to_size[sizeclass]);
- printf("SizeToClass too big");
- goto dump;
- }
- }
- }
-
- // Initialize the class_to_transfercount table.
- for(sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
- n = 64*1024 / class_to_size[sizeclass];
- if(n < 2)
- n = 2;
- if(n > 32)
- n = 32;
- class_to_transfercount[sizeclass] = n;
- }
- return;
-
-dump:
- if(1){
- printf("NumSizeClasses=%d\n", NumSizeClasses);
- printf("class_to_size:");
- for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++)
- printf(" %d", class_to_size[sizeclass]);
- printf("\n\n");
- printf("size_to_class8:");
- for(i=0; i<nelem(size_to_class8); i++)
- printf(" %d=>%d(%d)\n", i*8, size_to_class8[i], class_to_size[size_to_class8[i]]);
- printf("\n");
- printf("size_to_class128:");
- for(i=0; i<nelem(size_to_class128); i++)
- printf(" %d=>%d(%d)\n", i*128, size_to_class128[i], class_to_size[size_to_class128[i]]);
- printf("\n");
- }
- throw("InitSizes failed");
-}
diff --git a/src/lib/runtime/print.c b/src/lib/runtime/print.c
deleted file mode 100644
index 5295e338d..000000000
--- a/src/lib/runtime/print.c
+++ /dev/null
@@ -1,268 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-
-void
-dump(byte *p, int32 n)
-{
- int32 i;
-
- for(i=0; i<n; i++) {
- sys·printpointer((byte*)(p[i]>>4));
- sys·printpointer((byte*)(p[i]&0xf));
- if((i&15) == 15)
- prints("\n");
- else
- prints(" ");
- }
- if(n & 15)
- prints("\n");
-}
-
-void
-prints(int8 *s)
-{
- sys·write(1, s, findnull((byte*)s));
-}
-
-// Very simple printf. Only for debugging prints.
-// Do not add to this without checking with Rob.
-void
-printf(int8 *s, ...)
-{
- int8 *p, *lp;
- byte *arg, *narg;
-
- lp = p = s;
- arg = (byte*)(&s+1);
- for(; *p; p++) {
- if(*p != '%')
- continue;
- if(p > lp)
- sys·write(1, lp, p-lp);
- p++;
- narg = nil;
- switch(*p) {
- case 'd': // 32-bit
- case 'x':
- narg = arg + 4;
- break;
- case 'D': // 64-bit
- case 'X':
- if(sizeof(uintptr) == 8 && ((uint32)(uint64)arg)&4)
- arg += 4;
- narg = arg + 8;
- break;
- case 'p': // pointer-sized
- case 's':
- if(sizeof(uintptr) == 8 && ((uint32)(uint64)arg)&4)
- arg += 4;
- narg = arg + sizeof(uintptr);
- break;
- case 'S': // pointer-aligned but bigger
- if(sizeof(uintptr) == 8 && ((uint32)(uint64)arg)&4)
- arg += 4;
- narg = arg + sizeof(String);
- break;
- }
- switch(*p) {
- case 'd':
- sys·printint(*(int32*)arg);
- break;
- case 'D':
- sys·printint(*(int64*)arg);
- break;
- case 'x':
- sys·printhex(*(int32*)arg);
- break;
- case 'X':
- sys·printhex(*(int64*)arg);
- break;
- case 'p':
- sys·printpointer(*(void**)arg);
- break;
- case 's':
- prints(*(int8**)arg);
- break;
- case 'S':
- sys·printstring(*(String*)arg);
- break;
- }
- arg = narg;
- lp = p+1;
- }
- if(p > lp)
- sys·write(1, lp, p-lp);
-}
-
-
-void
-sys·printpc(void *p)
-{
- prints("PC=");
- sys·printhex((uint64)sys·getcallerpc(p));
-}
-
-void
-sys·printbool(bool v)
-{
- if(v) {
- sys·write(1, (byte*)"true", 4);
- return;
- }
- sys·write(1, (byte*)"false", 5);
-}
-
-void
-sys·printfloat(float64 v)
-{
- byte buf[20];
- int32 e, s, i, n;
- float64 h;
-
- if(isNaN(v)) {
- sys·write(1, "NaN", 3);
- return;
- }
- if(isInf(v, 0)) {
- sys·write(1, "+Inf", 4);
- return;
- }
- if(isInf(v, -1)) {
- sys·write(1, "+Inf", 4);
- return;
- }
-
-
- n = 7; // digits printed
- e = 0; // exp
- s = 0; // sign
- if(v != 0) {
- // sign
- if(v < 0) {
- v = -v;
- s = 1;
- }
-
- // normalize
- while(v >= 10) {
- e++;
- v /= 10;
- }
- while(v < 1) {
- e--;
- v *= 10;
- }
-
- // round
- h = 5;
- for(i=0; i<n; i++)
- h /= 10;
- v += h;
- if(v >= 10) {
- e++;
- v /= 10;
- }
- }
-
- // format +d.dddd+edd
- buf[0] = '+';
- if(s)
- buf[0] = '-';
- for(i=0; i<n; i++) {
- s = v;
- buf[i+2] = s+'0';
- v -= s;
- v *= 10.;
- }
- buf[1] = buf[2];
- buf[2] = '.';
-
- buf[n+2] = 'e';
- buf[n+3] = '+';
- if(e < 0) {
- e = -e;
- buf[n+3] = '-';
- }
-
- buf[n+4] = (e/100) + '0';
- buf[n+5] = (e/10)%10 + '0';
- buf[n+6] = (e%10) + '0';
- sys·write(1, buf, n+7);
-}
-
-void
-sys·printuint(uint64 v)
-{
- byte buf[100];
- int32 i;
-
- for(i=nelem(buf)-1; i>0; i--) {
- buf[i] = v%10 + '0';
- if(v < 10)
- break;
- v = v/10;
- }
- sys·write(1, buf+i, nelem(buf)-i);
-}
-
-void
-sys·printint(int64 v)
-{
- if(v < 0) {
- sys·write(1, "-", 1);
- v = -v;
- }
- sys·printuint(v);
-}
-
-void
-sys·printhex(uint64 v)
-{
- static int8 *dig = "0123456789abcdef";
- byte buf[100];
- int32 i;
-
- i=nelem(buf);
- for(; v>0; v/=16)
- buf[--i] = dig[v%16];
- if(i == nelem(buf))
- buf[--i] = '0';
- buf[--i] = 'x';
- buf[--i] = '0';
- sys·write(1, buf+i, nelem(buf)-i);
-}
-
-void
-sys·printpointer(void *p)
-{
- sys·printhex((uint64)p);
-}
-
-void
-sys·printstring(String v)
-{
- extern int32 maxstring;
-
- if(v.len > maxstring) {
- sys·write(1, "[invalid string]", 16);
- return;
- }
- if(v.len > 0)
- sys·write(1, v.str, v.len);
-}
-
-void
-sys·printsp(void)
-{
- sys·write(1, " ", 1);
-}
-
-void
-sys·printnl(void)
-{
- sys·write(1, "\n", 1);
-}
diff --git a/src/lib/runtime/proc.c b/src/lib/runtime/proc.c
deleted file mode 100644
index 1d065e6d2..000000000
--- a/src/lib/runtime/proc.c
+++ /dev/null
@@ -1,858 +0,0 @@
-// 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.
-
-#include "runtime.h"
-#include "malloc.h"
-
-typedef struct Sched Sched;
-
-M m0;
-G g0; // idle goroutine for m0
-
-static int32 debug = 0;
-static Lock debuglock;
-
-// Go scheduler
-//
-// The go scheduler's job is to match ready-to-run goroutines (`g's)
-// with waiting-for-work schedulers (`m's). If there are ready gs
-// and no waiting ms, ready() will start a new m running in a new
-// OS thread, so that all ready gs can run simultaneously, up to a limit.
-// For now, ms never go away.
-//
-// The default maximum number of ms is one: go runs single-threaded.
-// This is because some locking details have to be worked ou
-// (select in particular is not locked properly) and because the low-level
-// code hasn't been written yet for OS X. Setting the environmen
-// variable $gomaxprocs changes sched.mmax for now.
-//
-// Even a program that can run without deadlock in a single process
-// might use more ms if given the chance. For example, the prime
-// sieve will use as many ms as there are primes (up to sched.mmax),
-// allowing different stages of the pipeline to execute in parallel.
-// We could revisit this choice, only kicking off new ms for blocking
-// system calls, but that would limit the amount of parallel computation
-// that go would try to do.
-//
-// In general, one could imagine all sorts of refinements to the
-// scheduler, but the goal now is just to get something working on
-// Linux and OS X.
-
-struct Sched {
- Lock;
-
- G *gfree; // available gs (status == Gdead)
-
- G *ghead; // gs waiting to run
- G *gtail;
- int32 gwait; // number of gs waiting to run
- int32 gcount; // number of gs that are alive
-
- M *mhead; // ms waiting for work
- int32 mwait; // number of ms waiting for work
- int32 mcount; // number of ms that have been created
- int32 mcpu; // number of ms executing on cpu
- int32 mcpumax; // max number of ms allowed on cpu
- int32 gomaxprocs;
- int32 msyscall; // number of ms in system calls
-
- int32 predawn; // running initialization, don't run new gs.
-
- Note stopped; // one g can wait here for ms to stop
- int32 waitstop; // after setting this flag
-};
-
-Sched sched;
-
-// Scheduling helpers. Sched must be locked.
-static void gput(G*); // put/get on ghead/gtail
-static G* gget(void);
-static void mput(M*); // put/get on mhead
-static M* mget(void);
-static void gfput(G*); // put/get on gfree
-static G* gfget(void);
-static void matchmg(void); // match ms to gs
-static void readylocked(G*); // ready, but sched is locked
-
-// Scheduler loop.
-static void scheduler(void);
-
-// The bootstrap sequence is:
-//
-// call osinit
-// call schedinit
-// make & queue new G
-// call mstart
-//
-// The new G does:
-//
-// call main·init_function
-// call initdone
-// call main·main
-void
-schedinit(void)
-{
- int32 n;
- byte *p;
-
- mallocinit();
- goargs();
-
- // Allocate internal symbol table representation now,
- // so that we don't need to call malloc when we crash.
- findfunc(0);
-
- sched.gomaxprocs = 1;
- p = getenv("GOMAXPROCS");
- if(p != nil && (n = atoi(p)) != 0)
- sched.gomaxprocs = n;
- sched.mcpumax = sched.gomaxprocs;
- sched.mcount = 1;
- sched.predawn = 1;
-}
-
-// Called after main·init_function; main·main will be called on return.
-void
-initdone(void)
-{
- // Let's go.
- sched.predawn = 0;
- mstats.enablegc = 1;
-
- // If main·init_function started other goroutines,
- // kick off new ms to handle them, like ready
- // would have, had it not been pre-dawn.
- lock(&sched);
- matchmg();
- unlock(&sched);
-}
-
-void
-goexit(void)
-{
- if(debug > 1){
- lock(&debuglock);
- printf("goexit goid=%d\n", g->goid);
- unlock(&debuglock);
- }
- g->status = Gmoribund;
- gosched();
-}
-
-void
-tracebackothers(G *me)
-{
- G *g;
-
- for(g = allg; g != nil; g = g->alllink) {
- if(g == me || g->status == Gdead)
- continue;
- printf("\ngoroutine %d:\n", g->goid);
- traceback(g->sched.PC, g->sched.SP+sizeof(uintptr), g); // gogo adjusts SP by one word
- }
-}
-
-// Put on `g' queue. Sched must be locked.
-static void
-gput(G *g)
-{
- g->schedlink = nil;
- if(sched.ghead == nil)
- sched.ghead = g;
- else
- sched.gtail->schedlink = g;
- sched.gtail = g;
- sched.gwait++;
-}
-
-// Get from `g' queue. Sched must be locked.
-static G*
-gget(void)
-{
- G *g;
-
- g = sched.ghead;
- if(g){
- sched.ghead = g->schedlink;
- if(sched.ghead == nil)
- sched.gtail = nil;
- sched.gwait--;
- }
- return g;
-}
-
-// Put on `m' list. Sched must be locked.
-static void
-mput(M *m)
-{
- m->schedlink = sched.mhead;
- sched.mhead = m;
- sched.mwait++;
-}
-
-// Get from `m' list. Sched must be locked.
-static M*
-mget(void)
-{
- M *m;
-
- m = sched.mhead;
- if(m){
- sched.mhead = m->schedlink;
- sched.mwait--;
- }
- return m;
-}
-
-// Put on gfree list. Sched must be locked.
-static void
-gfput(G *g)
-{
- g->schedlink = sched.gfree;
- sched.gfree = g;
-}
-
-// Get from gfree list. Sched must be locked.
-static G*
-gfget(void)
-{
- G *g;
-
- g = sched.gfree;
- if(g)
- sched.gfree = g->schedlink;
- return g;
-}
-
-// Mark g ready to run.
-void
-ready(G *g)
-{
- lock(&sched);
- readylocked(g);
- unlock(&sched);
-}
-
-// Mark g ready to run. Sched is already locked.
-// G might be running already and about to stop.
-// The sched lock protects g->status from changing underfoot.
-static void
-readylocked(G *g)
-{
- if(g->m){
- // Running on another machine.
- // Ready it when it stops.
- g->readyonstop = 1;
- return;
- }
-
- // Mark runnable.
- if(g->status == Grunnable || g->status == Grunning)
- throw("bad g->status in ready");
- g->status = Grunnable;
-
- gput(g);
- if(!sched.predawn)
- matchmg();
-}
-
-// Get the next goroutine that m should run.
-// Sched must be locked on entry, is unlocked on exit.
-// Makes sure that at most $GOMAXPROCS gs are
-// running on cpus (not in system calls) at any given time.
-static G*
-nextgandunlock(void)
-{
- G *gp;
-
- // On startup, each m is assigned a nextg and
- // has already been accounted for in mcpu.
- if(m->nextg != nil) {
- gp = m->nextg;
- m->nextg = nil;
- unlock(&sched);
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d nextg found g%d\n", m->id, gp->goid);
- unlock(&debuglock);
- }
- return gp;
- }
-
- // Otherwise, look for work.
- if(sched.mcpu < sched.mcpumax && (gp=gget()) != nil) {
- sched.mcpu++;
- unlock(&sched);
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d nextg got g%d\n", m->id, gp->goid);
- unlock(&debuglock);
- }
- return gp;
- }
-
- // Otherwise, sleep.
- mput(m);
- if(sched.mcpu == 0 && sched.msyscall == 0)
- throw("all goroutines are asleep - deadlock!");
- m->nextg = nil;
- noteclear(&m->havenextg);
- if(sched.waitstop && sched.mcpu <= sched.mcpumax) {
- sched.waitstop = 0;
- notewakeup(&sched.stopped);
- }
- unlock(&sched);
-
- notesleep(&m->havenextg);
- if((gp = m->nextg) == nil)
- throw("bad m->nextg in nextgoroutine");
- m->nextg = nil;
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d nextg woke g%d\n", m->id, gp->goid);
- unlock(&debuglock);
- }
- return gp;
-}
-
-// TODO(rsc): Remove. This is only temporary,
-// for the mark and sweep collector.
-void
-stoptheworld(void)
-{
- lock(&sched);
- sched.mcpumax = 1;
- while(sched.mcpu > 1) {
- noteclear(&sched.stopped);
- sched.waitstop = 1;
- unlock(&sched);
- notesleep(&sched.stopped);
- lock(&sched);
- }
- unlock(&sched);
-}
-
-// TODO(rsc): Remove. This is only temporary,
-// for the mark and sweep collector.
-void
-starttheworld(void)
-{
- lock(&sched);
- sched.mcpumax = sched.gomaxprocs;
- matchmg();
- unlock(&sched);
-}
-
-// Called to start an M.
-void
-mstart(void)
-{
- if(m->mcache == nil)
- m->mcache = allocmcache();
- minit();
- scheduler();
-}
-
-// Kick of new ms as needed (up to mcpumax).
-// There are already `other' other cpus that will
-// start looking for goroutines shortly.
-// Sched is locked.
-static void
-matchmg(void)
-{
- M *m;
- G *g;
-
- if(debug > 1 && sched.ghead != nil) {
- lock(&debuglock);
- printf("matchmg mcpu=%d mcpumax=%d gwait=%d\n", sched.mcpu, sched.mcpumax, sched.gwait);
- unlock(&debuglock);
- }
-
- while(sched.mcpu < sched.mcpumax && (g = gget()) != nil){
- sched.mcpu++;
- if((m = mget()) != nil){
- if(debug > 1) {
- lock(&debuglock);
- printf("wakeup m%d g%d\n", m->id, g->goid);
- unlock(&debuglock);
- }
- m->nextg = g;
- notewakeup(&m->havenextg);
- }else{
- m = malloc(sizeof(M));
- m->g0 = malg(8192);
- m->nextg = g;
- m->id = sched.mcount++;
- if(debug) {
- lock(&debuglock);
- printf("alloc m%d g%d\n", m->id, g->goid);
- unlock(&debuglock);
- }
- newosproc(m, m->g0, m->g0->stackbase, mstart);
- }
- }
-}
-
-// Scheduler loop: find g to run, run it, repeat.
-static void
-scheduler(void)
-{
- G* gp;
-
- lock(&sched);
- if(gosave(&m->sched)){
- // Jumped here via gosave/gogo, so didn't
- // execute lock(&sched) above.
- lock(&sched);
-
- if(sched.predawn)
- throw("init sleeping");
-
- // Just finished running m->curg.
- gp = m->curg;
- gp->m = nil;
- sched.mcpu--;
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d sched g%d status %d\n", m->id, gp->goid, gp->status);
- unlock(&debuglock);
- }
- switch(gp->status){
- case Grunnable:
- case Gdead:
- // Shouldn't have been running!
- throw("bad gp->status in sched");
- case Grunning:
- gp->status = Grunnable;
- gput(gp);
- break;
- case Gmoribund:
- gp->status = Gdead;
- if(--sched.gcount == 0)
- exit(0);
- break;
- }
- if(gp->readyonstop){
- gp->readyonstop = 0;
- readylocked(gp);
- }
- }
-
- // Find (or wait for) g to run. Unlocks sched.
- gp = nextgandunlock();
- gp->readyonstop = 0;
- gp->status = Grunning;
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d run g%d at %p\n", m->id, gp->goid, gp->sched.PC);
- traceback(gp->sched.PC, gp->sched.SP+8, gp);
- unlock(&debuglock);
- }
- m->curg = gp;
- gp->m = m;
- g = gp;
- gogo(&gp->sched);
-}
-
-// Enter scheduler. If g->status is Grunning,
-// re-queues g and runs everyone else who is waiting
-// before running g again. If g->status is Gmoribund,
-// kills off g.
-void
-gosched(void)
-{
- if(g == m->g0)
- throw("gosched of g0");
- if(gosave(&g->sched) == 0){
- g = m->g0;
- gogo(&m->sched);
- }
-}
-
-// The goroutine g is about to enter a system call.
-// Record that it's not using the cpu anymore.
-// This is called only from the go syscall library, not
-// from the low-level system calls used by the runtime.
-// The "arguments" are syscall.Syscall's stack frame
-void
-sys·entersyscall(uint64 callerpc, int64 trap)
-{
- USED(callerpc);
-
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d g%d enter syscall %D\n", m->id, g->goid, trap);
- unlock(&debuglock);
- }
- lock(&sched);
- g->status = Gsyscall;
- sched.mcpu--;
- sched.msyscall++;
- if(sched.gwait != 0)
- matchmg();
- if(sched.waitstop && sched.mcpu <= sched.mcpumax) {
- sched.waitstop = 0;
- notewakeup(&sched.stopped);
- }
- unlock(&sched);
- // leave SP around for gc and traceback
- gosave(&g->sched);
-}
-
-// The goroutine g exited its system call.
-// Arrange for it to run on a cpu again.
-// This is called only from the go syscall library, not
-// from the low-level system calls used by the runtime.
-void
-sys·exitsyscall(void)
-{
- if(debug > 1) {
- lock(&debuglock);
- printf("m%d g%d exit syscall mcpu=%d mcpumax=%d\n", m->id, g->goid, sched.mcpu, sched.mcpumax);
- unlock(&debuglock);
- }
-
- lock(&sched);
- g->status = Grunning;
- sched.msyscall--;
- sched.mcpu++;
- // Fast path - if there's room for this m, we're done.
- if(sched.mcpu <= sched.mcpumax) {
- unlock(&sched);
- return;
- }
- unlock(&sched);
-
- // Slow path - all the cpus are taken.
- // The scheduler will ready g and put this m to sleep.
- // When the scheduler takes g awa from m,
- // it will undo the sched.mcpu++ above.
- gosched();
-}
-
-/*
- * stack layout parameters.
- * known to linkers.
- *
- * g->stackguard is set to point StackGuard bytes
- * above the bottom of the stack. each function
- * compares its stack pointer against g->stackguard
- * to check for overflow. to cut one instruction from
- * the check sequence for functions with tiny frames,
- * the stack is allowed to protrude StackSmall bytes
- * below the stack guard. functions with large frames
- * don't bother with the check and always call morestack.
- * the sequences are:
- *
- * guard = g->stackguard
- * frame = function's stack frame size
- * argsize = size of function arguments (call + return)
- *
- * stack frame size <= StackSmall:
- * CMPQ guard, SP
- * JHI 3(PC)
- * MOVQ m->morearg, $(argsize << 32)
- * CALL sys.morestack(SB)
- *
- * stack frame size > StackSmall but < StackBig
- * LEAQ (frame-StackSmall)(SP), R0
- * CMPQ guard, R0
- * JHI 3(PC)
- * MOVQ m->morearg, $(argsize << 32)
- * CALL sys.morestack(SB)
- *
- * stack frame size >= StackBig:
- * MOVQ m->morearg, $((argsize << 32) | frame)
- * CALL sys.morestack(SB)
- *
- * the bottom StackGuard - StackSmall bytes are important:
- * there has to be enough room to execute functions that
- * refuse to check for stack overflow, either because they
- * need to be adjacent to the actual caller's frame (sys.deferproc)
- * or because they handle the imminent stack overflow (sys.morestack).
- *
- * for example, sys.deferproc might call malloc,
- * which does one of the above checks (without allocating a full frame),
- * which might trigger a call to sys.morestack.
- * this sequence needs to fit in the bottom section of the stack.
- * on amd64, sys.morestack's frame is 40 bytes, and
- * sys.deferproc's frame is 56 bytes. that fits well within
- * the StackGuard - StackSmall = 128 bytes at the bottom.
- * there may be other sequences lurking or yet to be written
- * that require more stack. sys.morestack checks to make sure
- * the stack has not completely overflowed and should
- * catch such sequences.
- */
-enum
-{
- // byte offset of stack guard (g->stackguard) above bottom of stack.
- StackGuard = 256,
-
- // checked frames are allowed to protrude below the guard by
- // this many bytes. this saves an instruction in the checking
- // sequence when the stack frame is tiny.
- StackSmall = 128,
-
- // extra space in the frame (beyond the function for which
- // the frame is allocated) is assumed not to be much bigger
- // than this amount. it may not be used efficiently if it is.
- StackBig = 4096,
-};
-
-void
-oldstack(void)
-{
- Stktop *top;
- uint32 args;
- byte *sp;
- uintptr oldsp, oldpc, oldbase, oldguard;
-
-// printf("oldstack m->cret=%p\n", m->cret);
-
- top = (Stktop*)m->curg->stackbase;
-
- args = (top->magic>>32) & 0xffffLL;
-
- sp = (byte*)top;
- if(args > 0) {
- args = (args+7) & ~7;
- sp -= args;
- mcpy(top->oldsp+2*sizeof(uintptr), sp, args);
- }
-
- oldsp = (uintptr)top->oldsp + sizeof(uintptr);
- oldpc = *(uintptr*)oldsp;
- oldbase = (uintptr)top->oldbase;
- oldguard = (uintptr)top->oldguard;
-
- stackfree((byte*)m->curg->stackguard - StackGuard);
-
- m->curg->stackbase = (byte*)oldbase;
- m->curg->stackguard = (byte*)oldguard;
- m->morestack.SP = (byte*)oldsp;
- m->morestack.PC = (byte*)oldpc;
-
- // These two lines must happen in sequence;
- // once g has been changed, must switch to g's stack
- // before calling any non-assembly functions.
- // TODO(rsc): Perhaps make the new g a parameter
- // to gogoret and setspgoto, so that g is never
- // explicitly assigned to without also setting
- // the stack pointer.
- g = m->curg;
- gogoret(&m->morestack, m->cret);
-}
-
-#pragma textflag 7
-void
-lessstack(void)
-{
- g = m->g0;
- setspgoto(m->sched.SP, oldstack, nil);
-}
-
-void
-newstack(void)
-{
- int32 frame, args;
- Stktop *top;
- byte *stk, *sp;
- void (*fn)(void);
-
- frame = m->morearg & 0xffffffffLL;
- args = (m->morearg>>32) & 0xffffLL;
-
-// printf("newstack frame=%d args=%d moresp=%p morepc=%p\n", frame, args, m->moresp, *(uintptr*)m->moresp);
-
- if(frame < StackBig)
- frame = StackBig;
- frame += 1024; // for more functions, Stktop.
- stk = stackalloc(frame);
-
- top = (Stktop*)(stk+frame-sizeof(*top));
-
- top->oldbase = m->curg->stackbase;
- top->oldguard = m->curg->stackguard;
- top->oldsp = m->moresp;
- top->magic = m->morearg;
-
- m->curg->stackbase = (byte*)top;
- m->curg->stackguard = stk + StackGuard;
-
- sp = (byte*)top;
-
- if(args > 0) {
- // Copy args. There have been two function calls
- // since they got pushed, so skip over those return
- // addresses.
- args = (args+7) & ~7;
- sp -= args;
- mcpy(sp, m->moresp+2*sizeof(uintptr), args);
- }
-
- g = m->curg;
-
- // sys.morestack's return address
- fn = (void(*)(void))(*(uintptr*)m->moresp);
-
-// printf("fn=%p\n", fn);
-
- setspgoto(sp, fn, retfromnewstack);
-
- *(int32*)345 = 123; // never return
-}
-
-#pragma textflag 7
-void
-sys·morestack(uintptr u)
-{
- while(g == m->g0) {
- // very bad news
- *(int32*)0x1001 = 123;
- }
-
- // Morestack's frame is about 0x30 bytes on amd64.
- // If that the frame ends below the stack bottom, we've already
- // overflowed. Stop right now.
- while((byte*)&u - 0x30 < m->curg->stackguard - StackGuard) {
- // very bad news
- *(int32*)0x1002 = 123;
- }
-
- g = m->g0;
- m->moresp = (byte*)(&u-1);
- setspgoto(m->sched.SP, newstack, nil);
-
- *(int32*)0x1003 = 123; // never return
-}
-
-G*
-malg(int32 stacksize)
-{
- G *g;
- byte *stk;
-
- g = malloc(sizeof(G));
- stk = stackalloc(stacksize + StackGuard);
- g->stack0 = stk;
- g->stackguard = stk + StackGuard;
- g->stackbase = stk + StackGuard + stacksize;
- return g;
-}
-
-/*
- * Newproc and deferproc need to be textflag 7
- * (no possible stack split when nearing overflow)
- * because they assume that the arguments to fn
- * are available sequentially beginning at &arg0.
- * If a stack split happened, only the one word
- * arg0 would be copied. It's okay if any functions
- * they call split the stack below the newproc frame.
- */
-#pragma textflag 7
-void
-sys·newproc(int32 siz, byte* fn, byte* arg0)
-{
- byte *stk, *sp;
- G *newg;
-
-//printf("newproc siz=%d fn=%p", siz, fn);
-
- siz = (siz+7) & ~7;
- if(siz > 1024)
- throw("sys·newproc: too many args");
-
- lock(&sched);
-
- if((newg = gfget()) != nil){
- newg->status = Gwaiting;
- } else {
- newg = malg(4096);
- newg->status = Gwaiting;
- newg->alllink = allg;
- allg = newg;
- }
- stk = newg->stack0;
-
- newg->stackguard = stk+StackGuard;
-
- sp = stk + 4096 - 4*8;
- newg->stackbase = sp;
-
- sp -= siz;
- mcpy(sp, (byte*)&arg0, siz);
-
- sp -= sizeof(uintptr);
- *(byte**)sp = (byte*)goexit;
-
- sp -= sizeof(uintptr); // retpc used by gogo
- newg->sched.SP = sp;
- newg->sched.PC = fn;
-
- sched.gcount++;
- goidgen++;
- newg->goid = goidgen;
-
- readylocked(newg);
- unlock(&sched);
-
-//printf(" goid=%d\n", newg->goid);
-}
-
-#pragma textflag 7
-void
-sys·deferproc(int32 siz, byte* fn, byte* arg0)
-{
- Defer *d;
-
- d = malloc(sizeof(*d) + siz - sizeof(d->args));
- d->fn = fn;
- d->sp = (byte*)&arg0;
- d->siz = siz;
- mcpy(d->args, d->sp, d->siz);
-
- d->link = g->defer;
- g->defer = d;
-}
-
-#pragma textflag 7
-void
-sys·deferreturn(uintptr arg0)
-{
- Defer *d;
- byte *sp, *fn;
- uintptr *caller;
-
- d = g->defer;
- if(d == nil)
- return;
- sp = (byte*)&arg0;
- if(d->sp != sp)
- return;
- mcpy(d->sp, d->args, d->siz);
- g->defer = d->link;
- fn = d->fn;
- free(d);
- jmpdefer(fn, sp);
- }
-
-void
-runtime·Breakpoint(void)
-{
- breakpoint();
-}
-
-void
-runtime·Goexit(void)
-{
- goexit();
-}
-
-void
-runtime·Gosched(void)
-{
- gosched();
-}
-
diff --git a/src/lib/runtime/rune.c b/src/lib/runtime/rune.c
deleted file mode 100644
index ca4f9ac6a..000000000
--- a/src/lib/runtime/rune.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * The authors of this software are Rob Pike and Ken Thompson.
- * Copyright (c) 2002 by Lucent Technologies.
- * Portions Copyright 2009 The Go Authors. All rights reserved.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
-
-/*
- * The authors of this software are Rob Pike and Ken Thompson.
- * Copyright (c) 2002 by Lucent Technologies.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
-
-/*
- * This code is copied, with slight editing due to type differences,
- * from a subset of ../lib9/utf/rune.c
- */
-
-#include "runtime.h"
-
-enum
-{
- Bit1 = 7,
- Bitx = 6,
- Bit2 = 5,
- Bit3 = 4,
- Bit4 = 3,
- Bit5 = 2,
-
- T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
- Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
- T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
- T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
- T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
- T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */
-
- Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
- Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
- Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
- Rune4 = (1<<(Bit4+3*Bitx))-1,
- /* 0001 1111 1111 1111 1111 1111 */
-
- Maskx = (1<<Bitx)-1, /* 0011 1111 */
- Testx = Maskx ^ 0xFF, /* 1100 0000 */
-
- Runeerror = 0xFFFD,
- Runeself = 0x80,
-
- Bad = Runeerror,
-
- Runemax = 0x10FFFF, /* maximum rune value */
-};
-
-/*
- * Modified by Wei-Hwa Huang, Google Inc., on 2004-09-24
- * This is a slower but "safe" version of the old chartorune
- * that works on strings that are not necessarily null-terminated.
- *
- * If you know for sure that your string is null-terminated,
- * chartorune will be a bit faster.
- *
- * It is guaranteed not to attempt to access "length"
- * past the incoming pointer. This is to avoid
- * possible access violations. If the string appears to be
- * well-formed but incomplete (i.e., to get the whole Rune
- * we'd need to read past str+length) then we'll set the Rune
- * to Bad and return 0.
- *
- * Note that if we have decoding problems for other
- * reasons, we return 1 instead of 0.
- */
-int32
-charntorune(int32 *rune, uint8 *str, int32 length)
-{
- int32 c, c1, c2, c3, l;
-
- /* When we're not allowed to read anything */
- if(length <= 0) {
- goto badlen;
- }
-
- /*
- * one character sequence (7-bit value)
- * 00000-0007F => T1
- */
- c = *(uint8*)str;
- if(c < Tx) {
- *rune = c;
- return 1;
- }
-
- // If we can't read more than one character we must stop
- if(length <= 1) {
- goto badlen;
- }
-
- /*
- * two character sequence (11-bit value)
- * 0080-07FF => T2 Tx
- */
- c1 = *(uint8*)(str+1) ^ Tx;
- if(c1 & Testx)
- goto bad;
- if(c < T3) {
- if(c < T2)
- goto bad;
- l = ((c << Bitx) | c1) & Rune2;
- if(l <= Rune1)
- goto bad;
- *rune = l;
- return 2;
- }
-
- // If we can't read more than two characters we must stop
- if(length <= 2) {
- goto badlen;
- }
-
- /*
- * three character sequence (16-bit value)
- * 0800-FFFF => T3 Tx Tx
- */
- c2 = *(uint8*)(str+2) ^ Tx;
- if(c2 & Testx)
- goto bad;
- if(c < T4) {
- l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
- if(l <= Rune2)
- goto bad;
- *rune = l;
- return 3;
- }
-
- if (length <= 3)
- goto badlen;
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => T4 Tx Tx Tx
- */
- c3 = *(uint8*)(str+3) ^ Tx;
- if (c3 & Testx)
- goto bad;
- if (c < T5) {
- l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
- if (l <= Rune3 || l > Runemax)
- goto bad;
- *rune = l;
- return 4;
- }
-
- // Support for 5-byte or longer UTF-8 would go here, but
- // since we don't have that, we'll just fall through to bad.
-
- /*
- * bad decoding
- */
-bad:
- *rune = Bad;
- return 1;
-badlen:
- *rune = Bad;
- return 0;
-
-}
-
-int32
-runetochar(byte *str, int32 rune) /* note: in original, arg2 was pointer */
-{
- /* Runes are signed, so convert to unsigned for range check. */
- uint32 c;
-
- /*
- * one character sequence
- * 00000-0007F => 00-7F
- */
- c = rune;
- if(c <= Rune1) {
- str[0] = c;
- return 1;
- }
-
- /*
- * two character sequence
- * 0080-07FF => T2 Tx
- */
- if(c <= Rune2) {
- str[0] = T2 | (c >> 1*Bitx);
- str[1] = Tx | (c & Maskx);
- return 2;
- }
-
- /*
- * If the Rune is out of range, convert it to the error rune.
- * Do this test here because the error rune encodes to three bytes.
- * Doing it earlier would duplicate work, since an out of range
- * Rune wouldn't have fit in one or two bytes.
- */
- if (c > Runemax)
- c = Runeerror;
-
- /*
- * three character sequence
- * 0800-FFFF => T3 Tx Tx
- */
- if (c <= Rune3) {
- str[0] = T3 | (c >> 2*Bitx);
- str[1] = Tx | ((c >> 1*Bitx) & Maskx);
- str[2] = Tx | (c & Maskx);
- return 3;
- }
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => T4 Tx Tx Tx
- */
- str[0] = T4 | (c >> 3*Bitx);
- str[1] = Tx | ((c >> 2*Bitx) & Maskx);
- str[2] = Tx | ((c >> 1*Bitx) & Maskx);
- str[3] = Tx | (c & Maskx);
- return 4;
-}
diff --git a/src/lib/runtime/runtime.c b/src/lib/runtime/runtime.c
deleted file mode 100644
index c5ba3e6a5..000000000
--- a/src/lib/runtime/runtime.c
+++ /dev/null
@@ -1,462 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-int32 panicking = 0;
-int32 maxround = sizeof(uintptr);
-
-int32
-gotraceback(void)
-{
- byte *p;
-
- p = getenv("GOTRACEBACK");
- if(p == nil || p[0] == '\0')
- return 1; // default is on
- return atoi(p);
-}
-
-void
-sys·panicl(int32 lno)
-{
- uint8 *sp;
-
- if(panicking) {
- printf("double panic\n");
- exit(3);
- }
- panicking++;
-
- printf("\npanic PC=%X\n", (uint64)(uintptr)&lno);
- sp = (uint8*)&lno;
- if(gotraceback()){
- traceback(sys·getcallerpc(&lno), sp, g);
- tracebackothers(g);
- }
- breakpoint(); // so we can grab it in a debugger
- exit(2);
-}
-
-void
-sys·throwindex(void)
-{
- throw("index out of range");
-}
-
-void
-sys·throwreturn(void)
-{
- throw("no return at end of a typed function");
-}
-
-void
-sys·throwinit(void)
-{
- throw("recursive call during initialization");
-}
-
-void
-throw(int8 *s)
-{
- printf("throw: %s\n", s);
- sys·panicl(-1);
- *(int32*)0 = 0; // not reached
- exit(1); // even more not reached
-}
-
-void
-mcpy(byte *t, byte *f, uint32 n)
-{
- while(n > 0) {
- *t = *f;
- t++;
- f++;
- n--;
- }
-}
-
-int32
-mcmp(byte *s1, byte *s2, uint32 n)
-{
- uint32 i;
- byte c1, c2;
-
- for(i=0; i<n; i++) {
- c1 = s1[i];
- c2 = s2[i];
- if(c1 < c2)
- return -1;
- if(c1 > c2)
- return +1;
- }
- return 0;
-}
-
-
-void
-mmov(byte *t, byte *f, uint32 n)
-{
- if(t < f) {
- while(n > 0) {
- *t = *f;
- t++;
- f++;
- n--;
- }
- } else {
- t += n;
- f += n;
- while(n > 0) {
- t--;
- f--;
- *t = *f;
- n--;
- }
- }
-}
-
-byte*
-mchr(byte *p, byte c, byte *ep)
-{
- for(; p < ep; p++)
- if(*p == c)
- return p;
- return nil;
-}
-
-uint32
-rnd(uint32 n, uint32 m)
-{
- uint32 r;
-
- if(m > maxround)
- m = maxround;
- r = n % m;
- if(r)
- n += m-r;
- return n;
-}
-
-static int32 argc;
-static uint8** argv;
-
-Array os·Args;
-Array os·Envs;
-
-void
-args(int32 c, uint8 **v)
-{
- argc = c;
- argv = v;
-}
-
-void
-goargs(void)
-{
- String *gargv;
- String *genvv;
- int32 i, envc;
-
- for(envc=0; argv[argc+1+envc] != 0; envc++)
- ;
-
- gargv = malloc(argc*sizeof gargv[0]);
- genvv = malloc(envc*sizeof genvv[0]);
-
- for(i=0; i<argc; i++)
- gargv[i] = gostring(argv[i]);
- os·Args.array = (byte*)gargv;
- os·Args.nel = argc;
- os·Args.cap = argc;
-
- for(i=0; i<envc; i++)
- genvv[i] = gostring(argv[argc+1+i]);
- os·Envs.array = (byte*)genvv;
- os·Envs.nel = envc;
- os·Envs.cap = envc;
-}
-
-byte*
-getenv(int8 *s)
-{
- int32 i, j, len;
- byte *v, *bs;
- String* envv;
- int32 envc;
-
- bs = (byte*)s;
- len = findnull(bs);
- envv = (String*)os·Envs.array;
- envc = os·Envs.nel;
- for(i=0; i<envc; i++){
- if(envv[i].len <= len)
- continue;
- v = envv[i].str;
- for(j=0; j<len; j++)
- if(bs[j] != v[j])
- goto nomatch;
- if(v[len] != '=')
- goto nomatch;
- return v+len+1;
- nomatch:;
- }
- return nil;
-}
-
-
-int32
-atoi(byte *p)
-{
- int32 n;
-
- n = 0;
- while('0' <= *p && *p <= '9')
- n = n*10 + *p++ - '0';
- return n;
-}
-
-void
-check(void)
-{
- int8 a;
- uint8 b;
- int16 c;
- uint16 d;
- int32 e;
- uint32 f;
- int64 g;
- uint64 h;
- float32 i;
- float64 j;
- void* k;
- uint16* l;
-
- if(sizeof(a) != 1) throw("bad a");
- if(sizeof(b) != 1) throw("bad b");
- if(sizeof(c) != 2) throw("bad c");
- if(sizeof(d) != 2) throw("bad d");
- if(sizeof(e) != 4) throw("bad e");
- if(sizeof(f) != 4) throw("bad f");
- if(sizeof(g) != 8) throw("bad g");
- if(sizeof(h) != 8) throw("bad h");
- if(sizeof(i) != 4) throw("bad i");
- if(sizeof(j) != 8) throw("bad j");
- if(sizeof(k) != sizeof(uintptr)) throw("bad k");
- if(sizeof(l) != sizeof(uintptr)) throw("bad l");
-// prints(1"check ok\n");
-
- uint32 z;
- z = 1;
- if(!cas(&z, 1, 2))
- throw("cas1");
- if(z != 2)
- throw("cas2");
-
- z = 4;
- if(cas(&z, 5, 6))
- throw("cas3");
- if(z != 4)
- throw("cas4");
-
- initsig();
-}
-
-/*
- * map and chan helpers for
- * dealing with unknown types
- */
-static uintptr
-memhash(uint32 s, void *a)
-{
- byte *b;
- uintptr hash;
-
- b = a;
- if(sizeof(hash) == 4)
- hash = 2860486313U;
- else
- hash = 33054211828000289ULL;
- while(s > 0) {
- if(sizeof(hash) == 4)
- hash = (hash ^ *b) * 3267000013UL;
- else
- hash = (hash ^ *b) * 23344194077549503ULL;
- b++;
- s--;
- }
- return hash;
-}
-
-static uint32
-memequal(uint32 s, void *a, void *b)
-{
- byte *ba, *bb;
- uint32 i;
-
- ba = a;
- bb = b;
- for(i=0; i<s; i++)
- if(ba[i] != bb[i])
- return 0;
- return 1;
-}
-
-static void
-memprint(uint32 s, void *a)
-{
- uint64 v;
-
- v = 0xbadb00b;
- switch(s) {
- case 1:
- v = *(uint8*)a;
- break;
- case 2:
- v = *(uint16*)a;
- break;
- case 4:
- v = *(uint32*)a;
- break;
- case 8:
- v = *(uint64*)a;
- break;
- }
- sys·printint(v);
-}
-
-static void
-memcopy(uint32 s, void *a, void *b)
-{
- byte *ba, *bb;
- uint32 i;
-
- ba = a;
- bb = b;
- if(bb == nil) {
- for(i=0; i<s; i++)
- ba[i] = 0;
- return;
- }
- for(i=0; i<s; i++)
- ba[i] = bb[i];
-}
-
-static uintptr
-strhash(uint32 s, String *a)
-{
- USED(s);
- return memhash((*a).len, (*a).str);
-}
-
-static uint32
-strequal(uint32 s, String *a, String *b)
-{
- USED(s);
- return cmpstring(*a, *b) == 0;
-}
-
-static void
-strprint(uint32 s, String *a)
-{
- USED(s);
- sys·printstring(*a);
-}
-
-static uintptr
-interhash(uint32 s, Iface *a)
-{
- USED(s);
- return ifacehash(*a);
-}
-
-static void
-interprint(uint32 s, Iface *a)
-{
- USED(s);
- sys·printiface(*a);
-}
-
-static uint32
-interequal(uint32 s, Iface *a, Iface *b)
-{
- USED(s);
- return ifaceeq(*a, *b);
-}
-
-static uintptr
-nilinterhash(uint32 s, Eface *a)
-{
- USED(s);
- return efacehash(*a);
-}
-
-static void
-nilinterprint(uint32 s, Eface *a)
-{
- USED(s);
- sys·printeface(*a);
-}
-
-static uint32
-nilinterequal(uint32 s, Eface *a, Eface *b)
-{
- USED(s);
- return efaceeq(*a, *b);
-}
-
-uintptr
-nohash(uint32 s, void *a)
-{
- USED(s);
- USED(a);
- throw("hash of unhashable type");
- return 0;
-}
-
-uint32
-noequal(uint32 s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
- throw("comparing uncomparable types");
- return 0;
-}
-
-static void
-noprint(uint32 s, void *a)
-{
- USED(s);
- USED(a);
- throw("print of unprintable type");
-}
-
-static void
-nocopy(uint32 s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
- throw("copy of uncopyable type");
-}
-
-Alg
-algarray[] =
-{
-[AMEM] { memhash, memequal, memprint, memcopy },
-[ANOEQ] { nohash, noequal, memprint, memcopy },
-[ASTRING] { strhash, strequal, strprint, memcopy },
-[AINTER] { interhash, interequal, interprint, memcopy },
-[ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy },
-[AFAKE] { nohash, noequal, noprint, nocopy },
-};
-
-#pragma textflag 7
-void
-FLUSH(void *v)
-{
- USED(v);
-}
-
diff --git a/src/lib/runtime/runtime.h b/src/lib/runtime/runtime.h
deleted file mode 100644
index 749364f95..000000000
--- a/src/lib/runtime/runtime.h
+++ /dev/null
@@ -1,464 +0,0 @@
-// 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.
-
-/*
- * basic types
- */
-typedef signed char int8;
-typedef unsigned char uint8;
-typedef signed short int16;
-typedef unsigned short uint16;
-typedef signed int int32;
-typedef unsigned int uint32;
-typedef signed long long int int64;
-typedef unsigned long long int uint64;
-typedef float float32;
-typedef double float64;
-
-#ifdef _64BIT
-typedef uint64 uintptr;
-#else
-typedef uint32 uintptr;
-#endif
-
-/*
- * get rid of C types
- * the / / / forces a syntax error immediately,
- * which will show "last name: XXunsigned".
- */
-#define unsigned XXunsigned / / /
-#define signed XXsigned / / /
-#define char XXchar / / /
-#define short XXshort / / /
-#define int XXint / / /
-#define long XXlong / / /
-#define float XXfloat / / /
-#define double XXdouble / / /
-
-/*
- * defined types
- */
-typedef uint8 bool;
-typedef uint8 byte;
-typedef struct Alg Alg;
-typedef struct Array Array;
-typedef struct Func Func;
-typedef struct G G;
-typedef struct Gobuf Gobuf;
-typedef struct Lock Lock;
-typedef struct M M;
-typedef struct Mem Mem;
-typedef union Note Note;
-typedef struct Stktop Stktop;
-typedef struct String String;
-typedef struct Usema Usema;
-typedef struct SigTab SigTab;
-typedef struct MCache MCache;
-typedef struct Iface Iface;
-typedef struct Itype Itype;
-typedef struct Eface Eface;
-typedef struct Sigt Sigt;
-typedef struct Defer Defer;
-
-/*
- * per cpu declaration
- */
-extern register G* g; // R15
-extern register M* m; // R14
-
-/*
- * defined constants
- */
-enum
-{
- // G status
- Gidle,
- Grunnable,
- Grunning,
- Gsyscall,
- Gwaiting,
- Gmoribund,
- Gdead,
-};
-enum
-{
- true = 1,
- false = 0,
-};
-
-/*
- * structures
- */
-struct Lock
-{
- uint32 key;
- uint32 sema; // for OS X
-};
-struct Usema
-{
- uint32 u;
- uint32 k;
-};
-union Note
-{
- struct { // Linux
- Lock lock;
- };
- struct { // OS X
- int32 wakeup;
- Usema sema;
- };
-};
-struct String
-{
- byte* str;
- int32 len;
-};
-struct Iface
-{
- Itype* type;
- void* data;
-};
-struct Eface
-{
- Sigt* type;
- void* data;
-};
-
-struct Array
-{ // must not move anything
- byte* array; // actual data
- uint32 nel; // number of elements
- uint32 cap; // allocated number of elements
-};
-struct Gobuf
-{
- byte* SP;
- byte* PC;
-};
-struct G
-{
- byte* stackguard; // must not move
- byte* stackbase; // must not move
- Defer* defer; // must not move
- byte* stack0; // first stack segment
- Gobuf sched;
- G* alllink; // on allg
- void* param; // passed parameter on wakeup
- int16 status;
- int32 goid;
- int32 selgen; // valid sudog pointer
- G* schedlink;
- bool readyonstop;
- M* m; // for debuggers
-};
-struct Mem
-{
- uint8* hunk;
- uint32 nhunk;
- uint64 nmmap;
- uint64 nmal;
-};
-struct M
-{
- G* g0; // g0 w interrupt stack - must not move
- uint64 morearg; // arg to morestack - must not move
- uint64 cret; // return value from C - must not move
- uint64 procid; // for debuggers - must not move
- G* gsignal; // signal-handling G - must not move
- G* curg; // current running goroutine - must not move
- G* lastg; // last running goroutine - to emulate fifo - must not move
- uint32 tls[8]; // thread-local storage (for 386 extern register) - must not move
- Gobuf sched;
- Gobuf morestack;
- byte* moresp;
- int32 siz1;
- int32 siz2;
- int32 id;
- int32 mallocing;
- int32 locks;
- Note havenextg;
- G* nextg;
- M* schedlink;
- Mem mem;
- uint32 machport; // Return address for Mach IPC (OS X)
- MCache *mcache;
-};
-struct Stktop
-{
- uint8* oldbase;
- uint8* oldsp;
- uint64 magic;
- uint8* oldguard;
-};
-struct Alg
-{
- uintptr (*hash)(uint32, void*);
- uint32 (*equal)(uint32, void*, void*);
- void (*print)(uint32, void*);
- void (*copy)(uint32, void*, void*);
-};
-struct SigTab
-{
- int32 flags;
- int8 *name;
-};
-enum
-{
- SigCatch = 1<<0,
- SigIgnore = 1<<1,
- SigRestart = 1<<2,
-};
-
-// (will be) shared with go; edit ../cmd/6g/sys.go too.
-// should move out of sys.go eventually.
-// also eventually, the loaded symbol table should
-// be closer to this form.
-struct Func
-{
- String name;
- String type; // go type string
- String src; // src file name
- uint64 entry; // entry pc
- int64 frame; // stack frame size
- Array pcln; // pc/ln tab for this func
- int64 pc0; // starting pc, ln for table
- int32 ln0;
- int32 args; // number of 32-bit in/out args
- int32 locals; // number of 32-bit locals
-};
-
-/*
- * defined macros
- * you need super-goru privilege
- * to add this list.
- */
-#define nelem(x) (sizeof(x)/sizeof((x)[0]))
-#define nil ((void*)0)
-
-/*
- * known to compiler
- */
-enum
-{
- AMEM,
- ANOEQ,
- ASTRING,
- AINTER,
- ANILINTER,
- AFAKE,
- Amax
-};
-
-/*
- * deferred subroutine calls
- */
-struct Defer
-{
- int32 siz;
- byte* sp;
- byte* fn;
- Defer* link;
- byte args[8]; // padded to actual size
-};
-
-/*
- * external data
- */
-extern Alg algarray[Amax];
-extern String emptystring;
-G* allg;
-int32 goidgen;
-extern int32 gomaxprocs;
-extern int32 panicking;
-extern int32 maxround;
-
-/*
- * common functions and data
- */
-int32 strcmp(byte*, byte*);
-int32 findnull(byte*);
-void dump(byte*, int32);
-int32 runetochar(byte*, int32);
-int32 charntorune(int32*, uint8*, int32);
-
-/*
- * very low level c-called
- */
-int32 gogo(Gobuf*);
-int32 gosave(Gobuf*);
-int32 gogoret(Gobuf*, uint64);
-void retfromnewstack(void);
-void goargs(void);
-void setspgoto(byte*, void(*)(void), void(*)(void));
-void FLUSH(void*);
-void* getu(void);
-void throw(int8*);
-uint32 rnd(uint32, uint32);
-void prints(int8*);
-void printf(int8*, ...);
-byte* mchr(byte*, byte, byte*);
-void mcpy(byte*, byte*, uint32);
-int32 mcmp(byte*, byte*, uint32);
-void mmov(byte*, byte*, uint32);
-void* mal(uint32);
-uint32 cmpstring(String, String);
-String gostring(byte*);
-void initsig(void);
-int32 gotraceback(void);
-void traceback(uint8 *pc, uint8 *sp, G* gp);
-void tracebackothers(G*);
-int32 open(byte*, int32, ...);
-int32 read(int32, void*, int32);
-int32 write(int32, void*, int32);
-void close(int32);
-int32 fstat(int32, void*);
-bool cas(uint32*, uint32, uint32);
-void jmpdefer(byte*, void*);
-void exit1(int32);
-void ready(G*);
-byte* getenv(int8*);
-int32 atoi(byte*);
-void newosproc(M *m, G *g, void *stk, void (*fn)(void));
-void sigaltstack(void*, void*);
-void signalstack(byte*, int32);
-G* malg(int32);
-void minit(void);
-Func* findfunc(uintptr);
-int32 funcline(Func*, uint64);
-void* stackalloc(uint32);
-void stackfree(void*);
-MCache* allocmcache(void);
-void mallocinit(void);
-bool ifaceeq(Iface, Iface);
-bool efaceeq(Eface, Eface);
-uintptr ifacehash(Iface);
-uintptr efacehash(Eface);
-uintptr nohash(uint32, void*);
-uint32 noequal(uint32, void*, void*);
-void* malloc(uintptr size);
-void* mallocgc(uintptr size);
-void free(void *v);
-void exit(int32);
-void breakpoint(void);
-void gosched(void);
-void goexit(void);
-
-#pragma varargck argpos printf 1
-
-#pragma varargck type "d" int32
-#pragma varargck type "d" uint32
-#pragma varargck type "D" int64
-#pragma varargck type "D" uint64
-#pragma varargck type "x" int32
-#pragma varargck type "x" uint32
-#pragma varargck type "X" int64
-#pragma varargck type "X" uint64
-#pragma varargck type "p" void*
-#pragma varargck type "p" uintptr
-#pragma varargck type "s" int8*
-#pragma varargck type "s" uint8*
-#pragma varargck type "S" String
-
-// TODO(rsc): Remove. These are only temporary,
-// for the mark and sweep collector.
-void stoptheworld(void);
-void starttheworld(void);
-
-/*
- * mutual exclusion locks. in the uncontended case,
- * as fast as spin locks (just a few user-level instructions),
- * but on the contention path they sleep in the kernel.
- * a zeroed Lock is unlocked (no need to initialize each lock).
- */
-void lock(Lock*);
-void unlock(Lock*);
-
-/*
- * sleep and wakeup on one-time events.
- * before any calls to notesleep or notewakeup,
- * must call noteclear to initialize the Note.
- * then, any number of threads can call notesleep
- * and exactly one thread can call notewakeup (once).
- * once notewakeup has been called, all the notesleeps
- * will return. future notesleeps will return immediately.
- */
-void noteclear(Note*);
-void notesleep(Note*);
-void notewakeup(Note*);
-
-/*
- * Redefine methods for the benefit of gcc, which does not support
- * UTF-8 characters in identifiers.
- */
-#ifndef __GNUC__
-#define sys_memclr sys·memclr
-#define sys_write sys·write
-#define sys_catstring sys·catstring
-#define sys_cmpstring sys·cmpstring
-#define sys_getcallerpc sys·getcallerpc
-#define sys_indexstring sys·indexstring
-#define sys_intstring sys·intstring
-#define sys_mal sys·mal
-#define sys_mmap sys·mmap
-#define sys_printarray sys·printarray
-#define sys_printbool sys·printbool
-#define sys_printfloat sys·printfloat
-#define sys_printhex sys·printhex
-#define sys_printint sys·printint
-#define sys_printiface sys·printiface
-#define sys_printeface sys·printeface
-#define sys_printpc sys·printpc
-#define sys_printpointer sys·printpointer
-#define sys_printstring sys·printstring
-#define sys_printuint sys·printuint
-#define sys_setcallerpc sys·setcallerpc
-#define sys_slicestring sys·slicestring
-#endif
-
-/*
- * low level go-called
- */
-void sys_write(int32, void*, int32);
-uint8* sys_mmap(byte*, uint32, int32, int32, int32, uint32);
-void sys_memclr(byte*, uint32);
-void sys_setcallerpc(void*, void*);
-void* sys_getcallerpc(void*);
-
-/*
- * runtime go-called
- */
-void sys_printbool(bool);
-void sys_printfloat(float64);
-void sys_printint(int64);
-void sys_printiface(Iface);
-void sys_printeface(Eface);
-void sys_printstring(String);
-void sys_printpc(void*);
-void sys_printpointer(void*);
-void sys_printuint(uint64);
-void sys_printhex(uint64);
-void sys_printarray(Array);
-void sys_catstring(String, String, String);
-void sys_cmpstring(String, String, int32);
-void sys_slicestring(String, int32, int32, String);
-void sys_indexstring(String, int32, byte);
-void sys_intstring(int64, String);
-
-/*
- * wrapped for go users
- */
-float64 Inf(int32 sign);
-float64 NaN(void);
-float32 float32frombits(uint32 i);
-uint32 float32tobits(float32 f);
-float64 float64frombits(uint64 i);
-uint64 float64tobits(float64 f);
-float64 frexp(float64 d, int32 *ep);
-bool isInf(float64 f, int32 sign);
-bool isNaN(float64 f);
-float64 ldexp(float64 d, int32 e);
-float64 modf(float64 d, float64 *ip);
-void semacquire(uint32*);
-void semrelease(uint32*);
diff --git a/src/lib/runtime/sema.c b/src/lib/runtime/sema.c
deleted file mode 100644
index 5e5b07aa6..000000000
--- a/src/lib/runtime/sema.c
+++ /dev/null
@@ -1,176 +0,0 @@
-// 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.
-
-// Semaphore implementation exposed to Go.
-// Intended use is provide a sleep and wakeup
-// primitive that can be used in the contended case
-// of other synchronization primitives.
-// Thus it targets the same goal as Linux's futex,
-// but it has much simpler semantics.
-//
-// That is, don't think of these as semaphores.
-// Think of them as a way to implement sleep and wakeup
-// such that every sleep is paired with a single wakeup,
-// even if, due to races, the wakeup happens before the sleep.
-//
-// See Mullender and Cox, ``Semaphores in Plan 9,''
-// http://swtch.com/semaphore.pdf
-
-#include "runtime.h"
-
-typedef struct Sema Sema;
-struct Sema
-{
- uint32 *addr;
- G *g;
- Sema *prev;
- Sema *next;
-};
-
-// TODO: For now, a linked list; maybe a hash table of linked lists later.
-static Sema *semfirst, *semlast;
-static Lock semlock;
-
-static void
-semqueue(uint32 *addr, Sema *s)
-{
- s->addr = addr;
- s->g = nil;
-
- lock(&semlock);
- s->prev = semlast;
- s->next = nil;
- if(semlast)
- semlast->next = s;
- else
- semfirst = s;
- semlast = s;
- unlock(&semlock);
-}
-
-static void
-semdequeue(Sema *s)
-{
- lock(&semlock);
- if(s->next)
- s->next->prev = s->prev;
- else
- semlast = s->prev;
- if(s->prev)
- s->prev->next = s->next;
- else
- semfirst = s->next;
- s->prev = nil;
- s->next = nil;
- unlock(&semlock);
-}
-
-static void
-semwakeup(uint32 *addr)
-{
- Sema *s;
-
- lock(&semlock);
- for(s=semfirst; s; s=s->next) {
- if(s->addr == addr && s->g) {
- ready(s->g);
- s->g = nil;
- break;
- }
- }
- unlock(&semlock);
-}
-
-// Step 1 of sleep: make ourselves available for wakeup.
-// TODO(rsc): Maybe we can write a version without
-// locks by using cas on s->g. Maybe not: I need to
-// think more about whether it would be correct.
-static void
-semsleep1(Sema *s)
-{
- lock(&semlock);
- s->g = g;
- unlock(&semlock);
-}
-
-// Decided not to go through with it: undo step 1.
-static void
-semsleepundo1(Sema *s)
-{
- lock(&semlock);
- if(s->g != nil) {
- s->g = nil; // back ourselves out
- } else {
- // If s->g == nil already, semwakeup
- // already readied us. Since we never stopped
- // running, readying us just set g->readyonstop.
- // Clear it.
- if(g->readyonstop == 0)
- *(int32*)0x555 = 555;
- g->readyonstop = 0;
- }
- unlock(&semlock);
-}
-
-// Step 2: wait for the wakeup.
-static void
-semsleep2(Sema *s)
-{
- USED(s);
- g->status = Gwaiting;
- gosched();
-}
-
-static int32
-cansemacquire(uint32 *addr)
-{
- uint32 v;
-
- while((v = *addr) > 0)
- if(cas(addr, v, v-1))
- return 1;
- return 0;
-}
-
-// For now has no return value.
-// Might return an ok (not interrupted) bool in the future?
-void
-semacquire(uint32 *addr)
-{
- Sema s;
-
- // Easy case.
- if(cansemacquire(addr))
- return;
-
- // Harder case:
- // queue
- // try semacquire one more time, sleep if failed
- // dequeue
- // wake up one more guy to avoid races (TODO(rsc): maybe unnecessary?)
- semqueue(addr, &s);
- for(;;) {
- semsleep1(&s);
- if(cansemacquire(addr)) {
- semsleepundo1(&s);
- break;
- }
- semsleep2(&s);
- }
- semdequeue(&s);
- semwakeup(addr);
-}
-
-void
-semrelease(uint32 *addr)
-{
- uint32 v;
-
- for(;;) {
- v = *addr;
- if(cas(addr, v, v+1))
- break;
- }
- semwakeup(addr);
-}
diff --git a/src/lib/runtime/sema_go.cgo b/src/lib/runtime/sema_go.cgo
deleted file mode 100644
index eb4082a0d..000000000
--- a/src/lib/runtime/sema_go.cgo
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 sync
-#include "runtime.h"
-
-func semacquire(addr *uint32) {
- semacquire(addr);
-}
-
-func semrelease(addr *uint32) {
- semrelease(addr);
-}
-
diff --git a/src/lib/runtime/string.c b/src/lib/runtime/string.c
deleted file mode 100644
index 5bfe8196f..000000000
--- a/src/lib/runtime/string.c
+++ /dev/null
@@ -1,263 +0,0 @@
-// 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.
-
-#include "runtime.h"
-
-String emptystring;
-
-int32
-findnull(byte *s)
-{
- int32 l;
-
- if(s == nil)
- return 0;
- for(l=0; s[l]!=0; l++)
- ;
- return l;
-}
-
-int32 maxstring;
-
-String
-gostringsize(int32 l)
-{
- String s;
-
- if(l == 0)
- return emptystring;
- s.str = mal(l+1); // leave room for NUL for C runtime (e.g., callers of getenv)
- s.len = l;
- if(l > maxstring)
- maxstring = l;
- return s;
-}
-
-String
-gostring(byte *str)
-{
- int32 l;
- String s;
-
- l = findnull(str);
- s = gostringsize(l);
- mcpy(s.str, str, l);
- return s;
-}
-
-void
-sys·catstring(String s1, String s2, String s3)
-{
- if(s1.len == 0) {
- s3 = s2;
- goto out;
- }
- if(s2.len == 0) {
- s3 = s1;
- goto out;
- }
-
- s3 = gostringsize(s1.len + s2.len);
- mcpy(s3.str, s1.str, s1.len);
- mcpy(s3.str+s1.len, s2.str, s2.len);
-
-out:
- FLUSH(&s3);
-}
-
-static void
-prbounds(int8* s, int32 a, int32 b, int32 c)
-{
- prints(s);
- prints(" ");
- sys·printint(a);
- prints("<");
- sys·printint(b);
- prints(">");
- sys·printint(c);
- prints("\n");
- throw("string bounds");
-}
-
-uint32
-cmpstring(String s1, String s2)
-{
- uint32 i, l;
- byte c1, c2;
-
- l = s1.len;
- if(s2.len < l)
- l = s2.len;
- for(i=0; i<l; i++) {
- c1 = s1.str[i];
- c2 = s2.str[i];
- if(c1 < c2)
- return -1;
- if(c1 > c2)
- return +1;
- }
- if(s1.len < s2.len)
- return -1;
- if(s1.len > s2.len)
- return +1;
- return 0;
-}
-
-void
-sys·cmpstring(String s1, String s2, int32 v)
-{
- v = cmpstring(s1, s2);
- FLUSH(&v);
-}
-
-int32
-strcmp(byte *s1, byte *s2)
-{
- uint32 i;
- byte c1, c2;
-
- for(i=0;; i++) {
- c1 = s1[i];
- c2 = s2[i];
- if(c1 < c2)
- return -1;
- if(c1 > c2)
- return +1;
- if(c1 == 0)
- return 0;
- }
-}
-
-void
-sys·slicestring(String si, int32 lindex, int32 hindex, String so)
-{
- int32 l;
-
- if(lindex < 0 || lindex > si.len ||
- hindex < lindex || hindex > si.len) {
- sys·printpc(&si);
- prints(" ");
- prbounds("slice", lindex, si.len, hindex);
- }
-
- l = hindex-lindex;
- so.str = si.str + lindex;
- so.len = l;
-
-// alternate to create a new string
-// so = gostringsize(l);
-// mcpy(so.str, si.str+lindex, l);
-
- FLUSH(&so);
-}
-
-void
-sys·indexstring(String s, int32 i, byte b)
-{
- if(i < 0 || i >= s.len) {
- sys·printpc(&s);
- prints(" ");
- prbounds("index", 0, i, s.len);
- }
-
- b = s.str[i];
- FLUSH(&b);
-}
-
-void
-sys·intstring(int64 v, String s)
-{
- s = gostringsize(8);
- s.len = runetochar(s.str, v);
- FLUSH(&s);
-}
-
-void
-sys·arraystring(Array b, String s)
-{
- s = gostringsize(b.nel);
- mcpy(s.str, b.array, s.len);
- FLUSH(&s);
-}
-
-void
-sys·arraystringi(Array b, String s)
-{
- int32 siz1, siz2, i;
- int32 *a;
- byte dum[8];
-
- a = (int32*)b.array;
- siz1 = 0;
- for(i=0; i<b.nel; i++) {
- siz1 += runetochar(dum, a[i]);
- }
-
- s = gostringsize(siz1+4);
- siz2 = 0;
- for(i=0; i<b.nel; i++) {
- // check for race
- if(siz2 >= siz1)
- break;
- siz2 += runetochar(s.str+siz2, a[i]);
- }
- s.len = siz2;
-
- FLUSH(&s);
-}
-
-enum
-{
- Runeself = 0x80,
-};
-
-// func stringiter(string, int) (retk int);
-void
-sys·stringiter(String s, int32 k, int32 retk)
-{
- int32 l;
-
- if(k >= s.len) {
- // retk=0 is end of iteration
- retk = 0;
- goto out;
- }
-
- l = s.str[k];
- if(l < Runeself) {
- retk = k+1;
- goto out;
- }
-
- // multi-char rune
- retk = k + charntorune(&l, s.str+k, s.len-k);
-
-out:
- FLUSH(&retk);
-}
-
-// func stringiter2(string, int) (retk int, retv any);
-void
-sys·stringiter2(String s, int32 k, int32 retk, int32 retv)
-{
- if(k >= s.len) {
- // retk=0 is end of iteration
- retk = 0;
- retv = 0;
- goto out;
- }
-
- retv = s.str[k];
- if(retv < Runeself) {
- retk = k+1;
- goto out;
- }
-
- // multi-char rune
- retk = k + charntorune(&retv, s.str+k, s.len-k);
-
-out:
- FLUSH(&retk);
- FLUSH(&retv);
-}
diff --git a/src/lib/runtime/symtab.c b/src/lib/runtime/symtab.c
deleted file mode 100644
index b4802715e..000000000
--- a/src/lib/runtime/symtab.c
+++ /dev/null
@@ -1,377 +0,0 @@
-// 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.
-
-// Runtime symbol table access. Work in progress.
-// The Plan 9 symbol table is not in a particularly convenient form.
-// The routines here massage it into a more usable form; eventually
-// we'll change 6l to do this for us, but it is easier to experiment
-// here than to change 6l and all the other tools.
-//
-// The symbol table also needs to be better integrated with the type
-// strings table in the future. This is just a quick way to get started
-// and figure out exactly what we want.
-
-#include "runtime.h"
-
-// TODO(rsc): Move this *under* the text segment.
-// Then define names for these addresses instead of hard-coding magic ones.
-#ifdef _64BIT
-#define SYMCOUNTS ((int32*)(0x99LL<<32)) // known to 6l
-#define SYMDATA ((byte*)(0x99LL<<32) + 8)
-#else
-#define SYMCOUNTS ((int32*)(0x99LL<<24)) // known to 8l
-#define SYMDATA ((byte*)(0x99LL<<24) + 8)
-#endif
-
-
-// Return a pointer to a byte array containing the symbol table segment.
-void
-sys·symdat(Array *symtab, Array *pclntab)
-{
- Array *a;
- int32 *v;
-
- v = SYMCOUNTS;
-
- a = mal(sizeof *a);
- a->nel = v[0];
- a->cap = a->nel;
- a->array = SYMDATA;
- symtab = a;
- FLUSH(&symtab);
-
- a = mal(sizeof *a);
- a->nel = v[1];
- a->cap = a->nel;
- a->array = SYMDATA + v[0];
- pclntab = a;
- FLUSH(&pclntab);
-}
-
-typedef struct Sym Sym;
-struct Sym
-{
- uintptr value;
- byte symtype;
- byte *name;
- byte *gotype;
-};
-
-// Walk over symtab, calling fn(&s) for each symbol.
-static void
-walksymtab(void (*fn)(Sym*))
-{
- int32 *v;
- byte *p, *ep, *q;
- Sym s;
-
- v = SYMCOUNTS;
- p = SYMDATA;
- ep = p + v[0];
- while(p < ep) {
- if(p + 7 > ep)
- break;
- s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]);
- if(!(p[4]&0x80))
- break;
- s.symtype = p[4] & ~0x80;
- p += 5;
- s.name = p;
- if(s.symtype == 'z' || s.symtype == 'Z') {
- // path reference string - skip first byte,
- // then 2-byte pairs ending at two zeros.
- q = p+1;
- for(;;) {
- if(q+2 > ep)
- return;
- if(q[0] == '\0' && q[1] == '\0')
- break;
- q += 2;
- }
- p = q+2;
- }else{
- q = mchr(p, '\0', ep);
- if(q == nil)
- break;
- p = q+1;
- }
- q = mchr(p, '\0', ep);
- if(q == nil)
- break;
- s.gotype = p;
- p = q+1;
- fn(&s);
- }
-}
-
-// Symtab walker; accumulates info about functions.
-
-static Func *func;
-static int32 nfunc;
-
-static byte **fname;
-static int32 nfname;
-
-static void
-dofunc(Sym *sym)
-{
- Func *f;
-
- switch(sym->symtype) {
- case 't':
- case 'T':
- if(strcmp(sym->name, (byte*)"etext") == 0)
- break;
- if(func == nil) {
- nfunc++;
- break;
- }
- f = &func[nfunc++];
- f->name = gostring(sym->name);
- f->entry = sym->value;
- break;
- case 'm':
- if(nfunc > 0 && func != nil)
- func[nfunc-1].frame = sym->value;
- break;
- case 'p':
- if(nfunc > 0 && func != nil) {
- f = &func[nfunc-1];
- // args counts 32-bit words.
- // sym->value is the arg's offset.
- // don't know width of this arg, so assume it is 64 bits.
- if(f->args < sym->value/4 + 2)
- f->args = sym->value/4 + 2;
- }
- break;
- case 'f':
- if(fname == nil) {
- if(sym->value >= nfname)
- nfname = sym->value+1;
- break;
- }
- fname[sym->value] = sym->name;
- break;
- }
-}
-
-// put together the path name for a z entry.
-// the f entries have been accumulated into fname already.
-static void
-makepath(byte *buf, int32 nbuf, byte *path)
-{
- int32 n, len;
- byte *p, *ep, *q;
-
- if(nbuf <= 0)
- return;
-
- p = buf;
- ep = buf + nbuf;
- *p = '\0';
- for(;;) {
- if(path[0] == 0 && path[1] == 0)
- break;
- n = (path[0]<<8) | path[1];
- path += 2;
- if(n >= nfname)
- break;
- q = fname[n];
- len = findnull(q);
- if(p+1+len >= ep)
- break;
- if(p > buf && p[-1] != '/')
- *p++ = '/';
- mcpy(p, q, len+1);
- p += len;
- }
-}
-
-// walk symtab accumulating path names for use by pc/ln table.
-// don't need the full generality of the z entry history stack because
-// there are no includes in go (and only sensible includes in our c).
-static void
-dosrcline(Sym *sym)
-{
- static byte srcbuf[1000];
- static String srcstring;
- static int32 lno, incstart;
- static int32 nf, nhist;
- Func *f;
-
- switch(sym->symtype) {
- case 't':
- case 'T':
- if(strcmp(sym->name, (byte*)"etext") == 0)
- break;
- f = &func[nf++];
- f->src = srcstring;
- f->ln0 += lno;
- break;
- case 'z':
- if(sym->value == 1) {
- // entry for main source file for a new object.
- makepath(srcbuf, sizeof srcbuf, sym->name+1);
- srcstring = gostring(srcbuf);
- lno = 0;
- nhist = 0;
- } else {
- // push or pop of included file.
- makepath(srcbuf, sizeof srcbuf, sym->name+1);
- if(srcbuf[0] != '\0') {
- if(nhist++ == 0)
- incstart = sym->value;
- }else{
- if(--nhist == 0)
- lno -= sym->value - incstart;
- }
- }
- }
-}
-
-enum { PcQuant = 1 };
-
-// Interpret pc/ln table, saving the subpiece for each func.
-static void
-splitpcln(void)
-{
- int32 line;
- uintptr pc;
- byte *p, *ep;
- Func *f, *ef;
- int32 *v;
-
- // pc/ln table bounds
- v = SYMCOUNTS;
- p = SYMDATA;
- p += v[0];
- ep = p+v[1];
-
- f = func;
- ef = func + nfunc;
- pc = func[0].entry; // text base
- f->pcln.array = p;
- f->pc0 = pc - PcQuant;
- line = 0;
- for(; p < ep; p++) {
- if(f < ef && pc >= (f+1)->entry) {
- f->pcln.nel = p - f->pcln.array;
- f->pcln.cap = f->pcln.nel;
- f++;
- f->pcln.array = p;
- f->pc0 = pc;
- f->ln0 = line;
- }
- if(*p == 0) {
- // 4 byte add to line
- line += (p[1]<<24) | (p[2]<<16) | (p[3]<<8) | p[4];
- p += 4;
- } else if(*p <= 64) {
- line += *p;
- } else if(*p <= 128) {
- line -= *p - 64;
- } else {
- pc += PcQuant*(*p - 129);
- }
- pc += PcQuant;
- }
- if(f < ef) {
- f->pcln.nel = p - f->pcln.array;
- f->pcln.cap = f->pcln.nel;
- }
-}
-
-
-// Return actual file line number for targetpc in func f.
-// (Source file is f->src.)
-int32
-funcline(Func *f, uint64 targetpc)
-{
- byte *p, *ep;
- uintptr pc;
- int32 line;
-
- p = f->pcln.array;
- ep = p + f->pcln.nel;
- pc = f->pc0;
- line = f->ln0;
- for(; p < ep; p++) {
- if(pc >= targetpc)
- return line;
- if(*p == 0) {
- line += (p[1]<<24) | (p[2]<<16) | (p[3]<<8) | p[4];
- p += 4;
- } else if(*p <= 64) {
- line += *p;
- } else if(*p <= 128) {
- line -= *p - 64;
- } else {
- pc += PcQuant*(*p - 129);
- }
- pc += PcQuant;
- }
- return line;
-}
-
-static void
-buildfuncs(void)
-{
- extern byte etext[];
-
- if(func != nil)
- return;
- // count funcs, fnames
- nfunc = 0;
- nfname = 0;
- walksymtab(dofunc);
-
- // initialize tables
- func = mal((nfunc+1)*sizeof func[0]);
- func[nfunc].entry = (uint64)etext;
- fname = mal(nfname*sizeof fname[0]);
- nfunc = 0;
- walksymtab(dofunc);
-
- // split pc/ln table by func
- splitpcln();
-
- // record src file and line info for each func
- walksymtab(dosrcline);
-}
-
-Func*
-findfunc(uintptr addr)
-{
- Func *f;
- int32 nf, n;
-
- if(func == nil)
- buildfuncs();
- if(nfunc == 0)
- return nil;
- if(addr < func[0].entry || addr >= func[nfunc].entry)
- return nil;
-
- // binary search to find func with entry <= addr.
- f = func;
- nf = nfunc;
- while(nf > 0) {
- n = nf/2;
- if(f[n].entry <= addr && addr < f[n+1].entry)
- return &f[n];
- else if(addr < f[n].entry)
- nf = n;
- else {
- f += n+1;
- nf -= n+1;
- }
- }
-
- // can't get here -- we already checked above
- // that the address was in the table bounds.
- // this can only happen if the table isn't sorted
- // by address or if the binary search above is buggy.
- prints("findfunc unreachable\n");
- return nil;
-}