diff options
Diffstat (limited to 'gcc-4.8.1/libgo/runtime')
123 files changed, 0 insertions, 20099 deletions
diff --git a/gcc-4.8.1/libgo/runtime/arch.h b/gcc-4.8.1/libgo/runtime/arch.h deleted file mode 100644 index 0546a5da1..000000000 --- a/gcc-4.8.1/libgo/runtime/arch.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2011 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. - -// FIXME: Ideally CacheLineSize would be dependent on the host architecture. -enum { - CacheLineSize = 64 -}; diff --git a/gcc-4.8.1/libgo/runtime/array.h b/gcc-4.8.1/libgo/runtime/array.h deleted file mode 100644 index 14a9bb48f..000000000 --- a/gcc-4.8.1/libgo/runtime/array.h +++ /dev/null @@ -1,28 +0,0 @@ -/* array.h -- the open array type for Go. - - 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. */ - -#ifndef LIBGO_ARRAY_H -#define LIBGO_ARRAY_H - -/* An open array is an instance of this structure. */ - -struct __go_open_array -{ - /* The elements of the array. In use in the compiler this is a - pointer to the element type. */ - void* __values; - /* The number of elements in the array. Note that this is "int", - not "size_t". The language definition says that "int" is large - enough to hold the size of any allocated object. Using "int" - saves 8 bytes per slice header on a 64-bit system with 32-bit - ints. */ - intgo __count; - /* The capacity of the array--the number of elements that can fit in - the __VALUES field. */ - intgo __capacity; -}; - -#endif /* !defined(LIBGO_ARRAY_H) */ diff --git a/gcc-4.8.1/libgo/runtime/chan.c b/gcc-4.8.1/libgo/runtime/chan.c deleted file mode 100644 index a79ee9e18..000000000 --- a/gcc-4.8.1/libgo/runtime/chan.c +++ /dev/null @@ -1,1430 +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 "arch.h" -#include "go-type.h" -#include "race.h" -#include "malloc.h" - -#define NOSELGEN 1 - -static int32 debug = 0; - -typedef struct WaitQ WaitQ; -typedef struct SudoG SudoG; -typedef struct Select Select; -typedef struct Scase Scase; - -typedef struct __go_type_descriptor Type; -typedef struct __go_channel_type ChanType; - -struct SudoG -{ - G* g; // g and selgen constitute - uint32 selgen; // a weak pointer to g - SudoG* link; - int64 releasetime; - byte* elem; // data element -}; - -struct WaitQ -{ - SudoG* first; - SudoG* last; -}; - -struct Hchan -{ - uintgo qcount; // total data in the q - uintgo dataqsiz; // size of the circular q - uint16 elemsize; - bool closed; - uint8 elemalign; - uintgo sendx; // send index - uintgo recvx; // receive index - WaitQ recvq; // list of recv waiters - WaitQ sendq; // list of send waiters - Lock; -}; - -// Buffer follows Hchan immediately in memory. -// chanbuf(c, i) is pointer to the i'th slot in the buffer. -#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i)) - -enum -{ - // Scase.kind - CaseRecv, - CaseSend, - CaseDefault, -}; - -struct Scase -{ - SudoG sg; // must be first member (cast to Scase) - Hchan* chan; // chan - uint16 kind; - uint16 index; // index to return - bool* receivedp; // pointer to received bool (recv2) -}; - -struct Select -{ - uint16 tcase; // total count of scase[] - uint16 ncase; // currently filled scase[] - uint16* pollorder; // case poll order - Hchan** lockorder; // channel lock order - Scase scase[1]; // one per case (in order of appearance) -}; - -static void dequeueg(WaitQ*); -static SudoG* dequeue(WaitQ*); -static void enqueue(WaitQ*, SudoG*); -static void racesync(Hchan*, SudoG*); - -Hchan* -runtime_makechan_c(ChanType *t, int64 hint) -{ - Hchan *c; - uintptr n; - const Type *elem; - - elem = t->__element_type; - - // compiler checks this but be safe. - if(elem->__size >= (1<<16)) - runtime_throw("makechan: invalid channel element type"); - - if(hint < 0 || (intgo)hint != hint || (elem->__size > 0 && (uintptr)hint > MaxMem / elem->__size)) - runtime_panicstring("makechan: size out of range"); - - n = sizeof(*c); - - // allocate memory in one call - c = (Hchan*)runtime_mal(n + hint*elem->__size); - c->elemsize = elem->__size; - c->elemalign = elem->__align; - c->dataqsiz = hint; - - if(debug) - runtime_printf("makechan: chan=%p; elemsize=%D; elemalign=%d; dataqsiz=%D\n", - c, (int64)elem->__size, elem->__align, (int64)c->dataqsiz); - - return c; -} - -// For reflect -// func makechan(typ *ChanType, size uint64) (chan) -uintptr reflect_makechan(ChanType *, uint64) - __asm__ (GOSYM_PREFIX "reflect.makechan"); - -uintptr -reflect_makechan(ChanType *t, uint64 size) -{ - void *ret; - Hchan *c; - - c = runtime_makechan_c(t, size); - ret = runtime_mal(sizeof(void*)); - __builtin_memcpy(ret, &c, sizeof(void*)); - return (uintptr)ret; -} - -// makechan(t *ChanType, hint int64) (hchan *chan any); -Hchan* -__go_new_channel(ChanType *t, uintptr hint) -{ - return runtime_makechan_c(t, hint); -} - -Hchan* -__go_new_channel_big(ChanType *t, uint64 hint) -{ - return runtime_makechan_c(t, hint); -} - -/* - * 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. - * - * sleep can wake up with g->param == nil - * when a channel involved in the sleep has - * been closed. it is easiest to loop and re-run - * the operation; we'll see that it's now closed. - */ -void -runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc) -{ - SudoG *sg; - SudoG mysg; - G* gp; - int64 t0; - G* g; - - g = runtime_g(); - - if(c == nil) { - USED(t); - if(pres != nil) { - *pres = false; - return; - } - runtime_park(nil, nil, "chan send (nil chan)"); - return; // not reached - } - - if(runtime_gcwaiting) - runtime_gosched(); - - if(debug) { - runtime_printf("chansend: chan=%p\n", c); - } - - t0 = 0; - mysg.releasetime = 0; - if(runtime_blockprofilerate > 0) { - t0 = runtime_cputicks(); - mysg.releasetime = -1; - } - - runtime_lock(c); - // TODO(dvyukov): add similar instrumentation to select. - if(raceenabled) - runtime_racereadpc(c, pc, runtime_chansend); - if(c->closed) - goto closed; - - if(c->dataqsiz > 0) - goto asynch; - - sg = dequeue(&c->recvq); - if(sg != nil) { - if(raceenabled) - racesync(c, sg); - runtime_unlock(c); - - gp = sg->g; - gp->param = sg; - if(sg->elem != nil) - runtime_memmove(sg->elem, ep, c->elemsize); - if(sg->releasetime) - sg->releasetime = runtime_cputicks(); - runtime_ready(gp); - - if(pres != nil) - *pres = true; - return; - } - - if(pres != nil) { - runtime_unlock(c); - *pres = false; - return; - } - - mysg.elem = ep; - mysg.g = g; - mysg.selgen = NOSELGEN; - g->param = nil; - enqueue(&c->sendq, &mysg); - runtime_park(runtime_unlock, c, "chan send"); - - if(g->param == nil) { - runtime_lock(c); - if(!c->closed) - runtime_throw("chansend: spurious wakeup"); - goto closed; - } - - if(mysg.releasetime > 0) - runtime_blockevent(mysg.releasetime - t0, 2); - - return; - -asynch: - if(c->closed) - goto closed; - - if(c->qcount >= c->dataqsiz) { - if(pres != nil) { - runtime_unlock(c); - *pres = false; - return; - } - mysg.g = g; - mysg.elem = nil; - mysg.selgen = NOSELGEN; - enqueue(&c->sendq, &mysg); - runtime_park(runtime_unlock, c, "chan send"); - - runtime_lock(c); - goto asynch; - } - - if(raceenabled) - runtime_racerelease(chanbuf(c, c->sendx)); - - runtime_memmove(chanbuf(c, c->sendx), ep, c->elemsize); - if(++c->sendx == c->dataqsiz) - c->sendx = 0; - c->qcount++; - - sg = dequeue(&c->recvq); - if(sg != nil) { - gp = sg->g; - runtime_unlock(c); - if(sg->releasetime) - sg->releasetime = runtime_cputicks(); - runtime_ready(gp); - } else - runtime_unlock(c); - if(pres != nil) - *pres = true; - if(mysg.releasetime > 0) - runtime_blockevent(mysg.releasetime - t0, 2); - return; - -closed: - runtime_unlock(c); - runtime_panicstring("send on closed channel"); -} - - -void -runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received) -{ - SudoG *sg; - SudoG mysg; - G *gp; - int64 t0; - G *g; - - if(runtime_gcwaiting) - runtime_gosched(); - - if(debug) - runtime_printf("chanrecv: chan=%p\n", c); - - g = runtime_g(); - - if(c == nil) { - USED(t); - if(selected != nil) { - *selected = false; - return; - } - runtime_park(nil, nil, "chan receive (nil chan)"); - return; // not reached - } - - t0 = 0; - mysg.releasetime = 0; - if(runtime_blockprofilerate > 0) { - t0 = runtime_cputicks(); - mysg.releasetime = -1; - } - - runtime_lock(c); - if(c->dataqsiz > 0) - goto asynch; - - if(c->closed) - goto closed; - - sg = dequeue(&c->sendq); - if(sg != nil) { - if(raceenabled) - racesync(c, sg); - runtime_unlock(c); - - if(ep != nil) - runtime_memmove(ep, sg->elem, c->elemsize); - gp = sg->g; - gp->param = sg; - if(sg->releasetime) - sg->releasetime = runtime_cputicks(); - runtime_ready(gp); - - if(selected != nil) - *selected = true; - if(received != nil) - *received = true; - return; - } - - if(selected != nil) { - runtime_unlock(c); - *selected = false; - return; - } - - mysg.elem = ep; - mysg.g = g; - mysg.selgen = NOSELGEN; - g->param = nil; - enqueue(&c->recvq, &mysg); - runtime_park(runtime_unlock, c, "chan receive"); - - if(g->param == nil) { - runtime_lock(c); - if(!c->closed) - runtime_throw("chanrecv: spurious wakeup"); - goto closed; - } - - if(received != nil) - *received = true; - if(mysg.releasetime > 0) - runtime_blockevent(mysg.releasetime - t0, 2); - return; - -asynch: - if(c->qcount <= 0) { - if(c->closed) - goto closed; - - if(selected != nil) { - runtime_unlock(c); - *selected = false; - if(received != nil) - *received = false; - return; - } - mysg.g = g; - mysg.elem = nil; - mysg.selgen = NOSELGEN; - enqueue(&c->recvq, &mysg); - runtime_park(runtime_unlock, c, "chan receive"); - - runtime_lock(c); - goto asynch; - } - - if(raceenabled) - runtime_raceacquire(chanbuf(c, c->recvx)); - - if(ep != nil) - runtime_memmove(ep, chanbuf(c, c->recvx), c->elemsize); - runtime_memclr(chanbuf(c, c->recvx), c->elemsize); - if(++c->recvx == c->dataqsiz) - c->recvx = 0; - c->qcount--; - - sg = dequeue(&c->sendq); - if(sg != nil) { - gp = sg->g; - runtime_unlock(c); - if(sg->releasetime) - sg->releasetime = runtime_cputicks(); - runtime_ready(gp); - } else - runtime_unlock(c); - - if(selected != nil) - *selected = true; - if(received != nil) - *received = true; - if(mysg.releasetime > 0) - runtime_blockevent(mysg.releasetime - t0, 2); - return; - -closed: - if(ep != nil) - runtime_memclr(ep, c->elemsize); - if(selected != nil) - *selected = true; - if(received != nil) - *received = false; - if(raceenabled) - runtime_raceacquire(c); - runtime_unlock(c); - if(mysg.releasetime > 0) - runtime_blockevent(mysg.releasetime - t0, 2); -} - -// The compiler generates a call to __go_send_small to send a value 8 -// bytes or smaller. -void -__go_send_small(ChanType *t, Hchan* c, uint64 val) -{ - union - { - byte b[sizeof(uint64)]; - uint64 v; - } u; - byte *p; - - u.v = val; -#ifndef WORDS_BIGENDIAN - p = u.b; -#else - p = u.b + sizeof(uint64) - t->__element_type->__size; -#endif - runtime_chansend(t, c, p, nil, runtime_getcallerpc(&t)); -} - -// The compiler generates a call to __go_send_big to send a value -// larger than 8 bytes or smaller. -void -__go_send_big(ChanType *t, Hchan* c, byte* p) -{ - runtime_chansend(t, c, p, nil, runtime_getcallerpc(&t)); -} - -// The compiler generates a call to __go_receive_small to receive a -// value 8 bytes or smaller. -uint64 -__go_receive_small(ChanType *t, Hchan* c) -{ - union { - byte b[sizeof(uint64)]; - uint64 v; - } u; - byte *p; - - u.v = 0; -#ifndef WORDS_BIGENDIAN - p = u.b; -#else - p = u.b + sizeof(uint64) - t->__element_type->__size; -#endif - runtime_chanrecv(t, c, p, nil, nil); - return u.v; -} - -// The compiler generates a call to __go_receive_big to receive a -// value larger than 8 bytes. -void -__go_receive_big(ChanType *t, Hchan* c, byte* p) -{ - runtime_chanrecv(t, c, p, nil, nil); -} - -_Bool runtime_chanrecv2(ChanType *t, Hchan* c, byte* p) - __asm__ (GOSYM_PREFIX "runtime.chanrecv2"); - -_Bool -runtime_chanrecv2(ChanType *t, Hchan* c, byte* p) -{ - bool received; - - runtime_chanrecv(t, c, p, nil, &received); - return received; -} - -// func selectnbsend(c chan any, elem any) bool -// -// compiler implements -// -// select { -// case c <- v: -// ... foo -// default: -// ... bar -// } -// -// as -// -// if selectnbsend(c, v) { -// ... foo -// } else { -// ... bar -// } -// -_Bool -runtime_selectnbsend(ChanType *t, Hchan *c, byte *p) -{ - bool res; - - runtime_chansend(t, c, p, &res, runtime_getcallerpc(&t)); - return res; -} - -// func selectnbrecv(elem *any, c chan any) bool -// -// compiler implements -// -// select { -// case v = <-c: -// ... foo -// default: -// ... bar -// } -// -// as -// -// if selectnbrecv(&v, c) { -// ... foo -// } else { -// ... bar -// } -// -_Bool -runtime_selectnbrecv(ChanType *t, byte *v, Hchan *c) -{ - bool selected; - - runtime_chanrecv(t, c, v, &selected, nil); - return selected; -} - -// func selectnbrecv2(elem *any, ok *bool, c chan any) bool -// -// compiler implements -// -// select { -// case v, ok = <-c: -// ... foo -// default: -// ... bar -// } -// -// as -// -// if c != nil && selectnbrecv2(&v, &ok, c) { -// ... foo -// } else { -// ... bar -// } -// -_Bool -runtime_selectnbrecv2(ChanType *t, byte *v, _Bool *received, Hchan *c) -{ - bool selected; - bool r; - - r = false; - runtime_chanrecv(t, c, v, &selected, received == nil ? nil : &r); - if(received != nil) - *received = r; - return selected; -} - -// For reflect: -// func chansend(c chan, val iword, nb bool) (selected bool) -// where an iword is the same word an interface value would use: -// the actual data if it fits, or else a pointer to the data. - -_Bool reflect_chansend(ChanType *, Hchan *, uintptr, _Bool) - __asm__ (GOSYM_PREFIX "reflect.chansend"); - -_Bool -reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb) -{ - bool selected; - bool *sp; - byte *vp; - - if(nb) { - selected = false; - sp = (bool*)&selected; - } else { - selected = true; - sp = nil; - } - if(__go_is_pointer_type(t->__element_type)) - vp = (byte*)&val; - else - vp = (byte*)val; - runtime_chansend(t, c, vp, sp, runtime_getcallerpc(&t)); - return selected; -} - -// For reflect: -// func chanrecv(c chan, nb bool) (val iword, selected, received bool) -// where an iword is the same word an interface value would use: -// the actual data if it fits, or else a pointer to the data. - -struct chanrecv_ret -{ - uintptr val; - _Bool selected; - _Bool received; -}; - -struct chanrecv_ret reflect_chanrecv(ChanType *, Hchan *, _Bool) - __asm__ (GOSYM_PREFIX "reflect.chanrecv"); - -struct chanrecv_ret -reflect_chanrecv(ChanType *t, Hchan *c, _Bool nb) -{ - struct chanrecv_ret ret; - byte *vp; - bool *sp; - bool selected; - bool received; - - if(nb) { - selected = false; - sp = &selected; - } else { - ret.selected = true; - sp = nil; - } - received = false; - if(__go_is_pointer_type(t->__element_type)) { - vp = (byte*)&ret.val; - } else { - vp = runtime_mal(t->__element_type->__size); - ret.val = (uintptr)vp; - } - runtime_chanrecv(t, c, vp, sp, &received); - if(nb) - ret.selected = selected; - ret.received = received; - return ret; -} - -static void newselect(int32, Select**); - -// newselect(size uint32) (sel *byte); - -void* runtime_newselect(int32) __asm__ (GOSYM_PREFIX "runtime.newselect"); - -void* -runtime_newselect(int32 size) -{ - Select *sel; - - newselect(size, &sel); - return (void*)sel; -} - -static void -newselect(int32 size, Select **selp) -{ - int32 n; - Select *sel; - - n = 0; - if(size > 1) - n = size-1; - - // allocate all the memory we need in a single allocation - // start with Select with size cases - // then lockorder with size entries - // then pollorder with size entries - sel = runtime_mal(sizeof(*sel) + - n*sizeof(sel->scase[0]) + - size*sizeof(sel->lockorder[0]) + - size*sizeof(sel->pollorder[0])); - - sel->tcase = size; - sel->ncase = 0; - sel->lockorder = (void*)(sel->scase + size); - sel->pollorder = (void*)(sel->lockorder + size); - *selp = sel; - - if(debug) - runtime_printf("newselect s=%p size=%d\n", sel, size); -} - -// cut in half to give stack a chance to split -static void selectsend(Select *sel, Hchan *c, int index, void *elem); - -// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool); - -void runtime_selectsend(Select *, Hchan *, void *, int32) - __asm__ (GOSYM_PREFIX "runtime.selectsend"); - -void -runtime_selectsend(Select *sel, Hchan *c, void *elem, int32 index) -{ - // nil cases do not compete - if(c == nil) - return; - - selectsend(sel, c, index, elem); -} - -static void -selectsend(Select *sel, Hchan *c, int index, void *elem) -{ - int32 i; - Scase *cas; - - i = sel->ncase; - if(i >= sel->tcase) - runtime_throw("selectsend: too many cases"); - sel->ncase = i+1; - cas = &sel->scase[i]; - - cas->index = index; - cas->chan = c; - cas->kind = CaseSend; - cas->sg.elem = elem; - - if(debug) - runtime_printf("selectsend s=%p index=%d chan=%p\n", - sel, cas->index, cas->chan); -} - -// cut in half to give stack a chance to split -static void selectrecv(Select *sel, Hchan *c, int index, void *elem, bool*); - -// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool); - -void runtime_selectrecv(Select *, Hchan *, void *, int32) - __asm__ (GOSYM_PREFIX "runtime.selectrecv"); - -void -runtime_selectrecv(Select *sel, Hchan *c, void *elem, int32 index) -{ - // nil cases do not compete - if(c == nil) - return; - - selectrecv(sel, c, index, elem, nil); -} - -// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool); - -void runtime_selectrecv2(Select *, Hchan *, void *, bool *, int32) - __asm__ (GOSYM_PREFIX "runtime.selectrecv2"); - -void -runtime_selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, int32 index) -{ - // nil cases do not compete - if(c == nil) - return; - - selectrecv(sel, c, index, elem, received); -} - -static void -selectrecv(Select *sel, Hchan *c, int index, void *elem, bool *received) -{ - int32 i; - Scase *cas; - - i = sel->ncase; - if(i >= sel->tcase) - runtime_throw("selectrecv: too many cases"); - sel->ncase = i+1; - cas = &sel->scase[i]; - cas->index = index; - cas->chan = c; - - cas->kind = CaseRecv; - cas->sg.elem = elem; - cas->receivedp = received; - - if(debug) - runtime_printf("selectrecv s=%p index=%d chan=%p\n", - sel, cas->index, cas->chan); -} - -// cut in half to give stack a chance to split -static void selectdefault(Select*, int); - -// selectdefault(sel *byte) (selected bool); - -void runtime_selectdefault(Select *, int32) __asm__ (GOSYM_PREFIX "runtime.selectdefault"); - -void -runtime_selectdefault(Select *sel, int32 index) -{ - selectdefault(sel, index); -} - -static void -selectdefault(Select *sel, int32 index) -{ - int32 i; - Scase *cas; - - i = sel->ncase; - if(i >= sel->tcase) - runtime_throw("selectdefault: too many cases"); - sel->ncase = i+1; - cas = &sel->scase[i]; - cas->index = index; - cas->chan = nil; - - cas->kind = CaseDefault; - - if(debug) - runtime_printf("selectdefault s=%p index=%d\n", - sel, cas->index); -} - -static void -sellock(Select *sel) -{ - uint32 i; - Hchan *c, *c0; - - c = nil; - for(i=0; i<sel->ncase; i++) { - c0 = sel->lockorder[i]; - if(c0 && c0 != c) { - c = sel->lockorder[i]; - runtime_lock(c); - } - } -} - -static void -selunlock(Select *sel) -{ - uint32 i; - Hchan *c, *c0; - - c = nil; - for(i=sel->ncase; i-->0;) { - c0 = sel->lockorder[i]; - if(c0 && c0 != c) { - c = c0; - runtime_unlock(c); - } - } -} - -void -runtime_block(void) -{ - runtime_park(nil, nil, "select (no cases)"); // forever -} - -static int selectgo(Select**); - -// selectgo(sel *byte); - -int runtime_selectgo(Select *) __asm__ (GOSYM_PREFIX "runtime.selectgo"); - -int -runtime_selectgo(Select *sel) -{ - return selectgo(&sel); -} - -static int -selectgo(Select **selp) -{ - Select *sel; - uint32 o, i, j; - Scase *cas, *dfl; - Hchan *c; - SudoG *sg; - G *gp; - int index; - G *g; - - sel = *selp; - if(runtime_gcwaiting) - runtime_gosched(); - - if(debug) - runtime_printf("select: sel=%p\n", sel); - - g = runtime_g(); - - // The compiler rewrites selects that statically have - // only 0 or 1 cases plus default into simpler constructs. - // The only way we can end up with such small sel->ncase - // values here is for a larger select in which most channels - // have been nilled out. The general code handles those - // cases correctly, and they are rare enough not to bother - // optimizing (and needing to test). - - // generate permuted order - for(i=0; i<sel->ncase; i++) - sel->pollorder[i] = i; - for(i=1; i<sel->ncase; i++) { - o = sel->pollorder[i]; - j = runtime_fastrand1()%(i+1); - sel->pollorder[i] = sel->pollorder[j]; - sel->pollorder[j] = o; - } - - // sort the cases by Hchan address to get the locking order. - for(i=0; i<sel->ncase; i++) { - c = sel->scase[i].chan; - for(j=i; j>0 && sel->lockorder[j-1] >= c; j--) - sel->lockorder[j] = sel->lockorder[j-1]; - sel->lockorder[j] = c; - } - sellock(sel); - -loop: - // pass 1 - look for something already waiting - dfl = nil; - for(i=0; i<sel->ncase; i++) { - o = sel->pollorder[i]; - cas = &sel->scase[o]; - c = cas->chan; - - switch(cas->kind) { - case CaseRecv: - if(c->dataqsiz > 0) { - if(c->qcount > 0) - goto asyncrecv; - } else { - sg = dequeue(&c->sendq); - if(sg != nil) - goto syncrecv; - } - if(c->closed) - goto rclose; - break; - - case CaseSend: - if(c->closed) - goto sclose; - if(c->dataqsiz > 0) { - if(c->qcount < c->dataqsiz) - goto asyncsend; - } else { - sg = dequeue(&c->recvq); - if(sg != nil) - goto syncsend; - } - break; - - case CaseDefault: - dfl = cas; - break; - } - } - - if(dfl != nil) { - selunlock(sel); - cas = dfl; - goto retc; - } - - - // pass 2 - enqueue on all chans - for(i=0; i<sel->ncase; i++) { - o = sel->pollorder[i]; - cas = &sel->scase[o]; - c = cas->chan; - sg = &cas->sg; - sg->g = g; - sg->selgen = g->selgen; - - switch(cas->kind) { - case CaseRecv: - enqueue(&c->recvq, sg); - break; - - case CaseSend: - enqueue(&c->sendq, sg); - break; - } - } - - g->param = nil; - runtime_park((void(*)(Lock*))selunlock, (Lock*)sel, "select"); - - sellock(sel); - sg = g->param; - - // pass 3 - dequeue from unsuccessful chans - // otherwise they stack up on quiet channels - for(i=0; i<sel->ncase; i++) { - cas = &sel->scase[i]; - if(cas != (Scase*)sg) { - c = cas->chan; - if(cas->kind == CaseSend) - dequeueg(&c->sendq); - else - dequeueg(&c->recvq); - } - } - - if(sg == nil) - goto loop; - - cas = (Scase*)sg; - c = cas->chan; - - if(c->dataqsiz > 0) - runtime_throw("selectgo: shouldnt happen"); - - if(debug) - runtime_printf("wait-return: sel=%p c=%p cas=%p kind=%d\n", - sel, c, cas, cas->kind); - - if(cas->kind == CaseRecv) { - if(cas->receivedp != nil) - *cas->receivedp = true; - } - - selunlock(sel); - goto retc; - -asyncrecv: - // can receive from buffer - if(raceenabled) - runtime_raceacquire(chanbuf(c, c->recvx)); - if(cas->receivedp != nil) - *cas->receivedp = true; - if(cas->sg.elem != nil) - runtime_memmove(cas->sg.elem, chanbuf(c, c->recvx), c->elemsize); - runtime_memclr(chanbuf(c, c->recvx), c->elemsize); - if(++c->recvx == c->dataqsiz) - c->recvx = 0; - c->qcount--; - sg = dequeue(&c->sendq); - if(sg != nil) { - gp = sg->g; - selunlock(sel); - runtime_ready(gp); - } else { - selunlock(sel); - } - goto retc; - -asyncsend: - // can send to buffer - if(raceenabled) - runtime_racerelease(chanbuf(c, c->sendx)); - runtime_memmove(chanbuf(c, c->sendx), cas->sg.elem, c->elemsize); - if(++c->sendx == c->dataqsiz) - c->sendx = 0; - c->qcount++; - sg = dequeue(&c->recvq); - if(sg != nil) { - gp = sg->g; - selunlock(sel); - runtime_ready(gp); - } else { - selunlock(sel); - } - goto retc; - -syncrecv: - // can receive from sleeping sender (sg) - if(raceenabled) - racesync(c, sg); - selunlock(sel); - if(debug) - runtime_printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o); - if(cas->receivedp != nil) - *cas->receivedp = true; - if(cas->sg.elem != nil) - runtime_memmove(cas->sg.elem, sg->elem, c->elemsize); - gp = sg->g; - gp->param = sg; - runtime_ready(gp); - goto retc; - -rclose: - // read at end of closed channel - selunlock(sel); - if(cas->receivedp != nil) - *cas->receivedp = false; - if(cas->sg.elem != nil) - runtime_memclr(cas->sg.elem, c->elemsize); - if(raceenabled) - runtime_raceacquire(c); - goto retc; - -syncsend: - // can send to sleeping receiver (sg) - if(raceenabled) - racesync(c, sg); - selunlock(sel); - if(debug) - runtime_printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o); - if(sg->elem != nil) - runtime_memmove(sg->elem, cas->sg.elem, c->elemsize); - gp = sg->g; - gp->param = sg; - runtime_ready(gp); - -retc: - // return index corresponding to chosen case - index = cas->index; - runtime_free(sel); - return index; - -sclose: - // send on closed channel - selunlock(sel); - runtime_panicstring("send on closed channel"); - return 0; // not reached -} - -// This struct must match ../reflect/value.go:/runtimeSelect. -typedef struct runtimeSelect runtimeSelect; -struct runtimeSelect -{ - uintptr dir; - ChanType *typ; - Hchan *ch; - uintptr val; -}; - -// This enum must match ../reflect/value.go:/SelectDir. -enum SelectDir { - SelectSend = 1, - SelectRecv, - SelectDefault, -}; - -struct rselect_ret { - intgo chosen; - uintptr word; - bool recvOK; -}; - -// func rselect(cases []runtimeSelect) (chosen int, word uintptr, recvOK bool) - -struct rselect_ret reflect_rselect(Slice) - __asm__ (GOSYM_PREFIX "reflect.rselect"); - -struct rselect_ret -reflect_rselect(Slice cases) -{ - struct rselect_ret ret; - int32 i; - Select *sel; - runtimeSelect* rcase, *rc; - void *elem; - void *recvptr; - uintptr maxsize; - bool onlyptr; - - ret.chosen = -1; - ret.word = 0; - ret.recvOK = false; - - maxsize = 0; - onlyptr = true; - rcase = (runtimeSelect*)cases.__values; - for(i=0; i<cases.__count; i++) { - rc = &rcase[i]; - if(rc->dir == SelectRecv && rc->ch != nil) { - if(maxsize < rc->typ->__element_type->__size) - maxsize = rc->typ->__element_type->__size; - if(!__go_is_pointer_type(rc->typ->__element_type)) - onlyptr = false; - } - } - - recvptr = nil; - if(!onlyptr) - recvptr = runtime_mal(maxsize); - - newselect(cases.__count, &sel); - for(i=0; i<cases.__count; i++) { - rc = &rcase[i]; - switch(rc->dir) { - case SelectDefault: - selectdefault(sel, i); - break; - case SelectSend: - if(rc->ch == nil) - break; - if(!__go_is_pointer_type(rc->typ->__element_type)) - elem = (void*)rc->val; - else - elem = (void*)&rc->val; - selectsend(sel, rc->ch, i, elem); - break; - case SelectRecv: - if(rc->ch == nil) - break; - if(!__go_is_pointer_type(rc->typ->__element_type)) - elem = recvptr; - else - elem = &ret.word; - selectrecv(sel, rc->ch, i, elem, &ret.recvOK); - break; - } - } - - ret.chosen = (intgo)(uintptr)selectgo(&sel); - if(rcase[ret.chosen].dir == SelectRecv && !__go_is_pointer_type(rcase[ret.chosen].typ->__element_type)) - ret.word = (uintptr)recvptr; - - return ret; -} - -// closechan(sel *byte); -void -runtime_closechan(Hchan *c) -{ - SudoG *sg; - G* gp; - - if(c == nil) - runtime_panicstring("close of nil channel"); - - if(runtime_gcwaiting) - runtime_gosched(); - - runtime_lock(c); - if(c->closed) { - runtime_unlock(c); - runtime_panicstring("close of closed channel"); - } - - if(raceenabled) { - runtime_racewritepc(c, runtime_getcallerpc(&c), runtime_closechan); - runtime_racerelease(c); - } - - c->closed = true; - - // release all readers - for(;;) { - sg = dequeue(&c->recvq); - if(sg == nil) - break; - gp = sg->g; - gp->param = nil; - runtime_ready(gp); - } - - // release all writers - for(;;) { - sg = dequeue(&c->sendq); - if(sg == nil) - break; - gp = sg->g; - gp->param = nil; - runtime_ready(gp); - } - - runtime_unlock(c); -} - -void -__go_builtin_close(Hchan *c) -{ - runtime_closechan(c); -} - -// For reflect -// func chanclose(c chan) - -void reflect_chanclose(uintptr) __asm__ (GOSYM_PREFIX "reflect.chanclose"); - -void -reflect_chanclose(uintptr c) -{ - runtime_closechan((Hchan*)c); -} - -// For reflect -// func chanlen(c chan) (len int) - -intgo reflect_chanlen(uintptr) __asm__ (GOSYM_PREFIX "reflect.chanlen"); - -intgo -reflect_chanlen(uintptr ca) -{ - Hchan *c; - intgo len; - - c = (Hchan*)ca; - if(c == nil) - len = 0; - else - len = c->qcount; - return len; -} - -intgo -__go_chan_len(Hchan *c) -{ - return reflect_chanlen((uintptr)c); -} - -// For reflect -// func chancap(c chan) (cap intgo) - -intgo reflect_chancap(uintptr) __asm__ (GOSYM_PREFIX "reflect.chancap"); - -intgo -reflect_chancap(uintptr ca) -{ - Hchan *c; - intgo cap; - - c = (Hchan*)ca; - if(c == nil) - cap = 0; - else - cap = c->dataqsiz; - return cap; -} - -intgo -__go_chan_cap(Hchan *c) -{ - return reflect_chancap((uintptr)c); -} - -static SudoG* -dequeue(WaitQ *q) -{ - SudoG *sgp; - -loop: - sgp = q->first; - if(sgp == nil) - return nil; - q->first = sgp->link; - - // if sgp is stale, ignore it - if(sgp->selgen != NOSELGEN && - (sgp->selgen != sgp->g->selgen || - !runtime_cas(&sgp->g->selgen, sgp->selgen, sgp->selgen + 2))) { - //prints("INVALID PSEUDOG POINTER\n"); - goto loop; - } - - return sgp; -} - -static void -dequeueg(WaitQ *q) -{ - SudoG **l, *sgp, *prevsgp; - G *g; - - g = runtime_g(); - prevsgp = nil; - for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) { - if(sgp->g == g) { - *l = sgp->link; - if(q->last == sgp) - q->last = prevsgp; - break; - } - } -} - -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 void -racesync(Hchan *c, SudoG *sg) -{ - runtime_racerelease(chanbuf(c, 0)); - runtime_raceacquireg(sg->g, chanbuf(c, 0)); - runtime_racereleaseg(sg->g, chanbuf(c, 0)); - runtime_raceacquire(chanbuf(c, 0)); -} diff --git a/gcc-4.8.1/libgo/runtime/cpuprof.c b/gcc-4.8.1/libgo/runtime/cpuprof.c deleted file mode 100644 index 3ef08ef51..000000000 --- a/gcc-4.8.1/libgo/runtime/cpuprof.c +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2011 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. - -// CPU profiling. -// Based on algorithms and data structures used in -// http://code.google.com/p/google-perftools/. -// -// The main difference between this code and the google-perftools -// code is that this code is written to allow copying the profile data -// to an arbitrary io.Writer, while the google-perftools code always -// writes to an operating system file. -// -// The signal handler for the profiling clock tick adds a new stack trace -// to a hash table tracking counts for recent traces. Most clock ticks -// hit in the cache. In the event of a cache miss, an entry must be -// evicted from the hash table, copied to a log that will eventually be -// written as profile data. The google-perftools code flushed the -// log itself during the signal handler. This code cannot do that, because -// the io.Writer might block or need system calls or locks that are not -// safe to use from within the signal handler. Instead, we split the log -// into two halves and let the signal handler fill one half while a goroutine -// is writing out the other half. When the signal handler fills its half, it -// offers to swap with the goroutine. If the writer is not done with its half, -// we lose the stack trace for this clock tick (and record that loss). -// The goroutine interacts with the signal handler by calling getprofile() to -// get the next log piece to write, implicitly handing back the last log -// piece it obtained. -// -// The state of this dance between the signal handler and the goroutine -// is encoded in the Profile.handoff field. If handoff == 0, then the goroutine -// is not using either log half and is waiting (or will soon be waiting) for -// a new piece by calling notesleep(&p->wait). If the signal handler -// changes handoff from 0 to non-zero, it must call notewakeup(&p->wait) -// to wake the goroutine. The value indicates the number of entries in the -// log half being handed off. The goroutine leaves the non-zero value in -// place until it has finished processing the log half and then flips the number -// back to zero. Setting the high bit in handoff means that the profiling is over, -// and the goroutine is now in charge of flushing the data left in the hash table -// to the log and returning that data. -// -// The handoff field is manipulated using atomic operations. -// For the most part, the manipulation of handoff is orderly: if handoff == 0 -// then the signal handler owns it and can change it to non-zero. -// If handoff != 0 then the goroutine owns it and can change it to zero. -// If that were the end of the story then we would not need to manipulate -// handoff using atomic operations. The operations are needed, however, -// in order to let the log closer set the high bit to indicate "EOF" safely -// in the situation when normally the goroutine "owns" handoff. - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -#include "array.h" -typedef struct __go_open_array Slice; -#define array __values -#define len __count -#define cap __capacity - -enum -{ - HashSize = 1<<10, - LogSize = 1<<17, - Assoc = 4, - MaxStack = 64, -}; - -typedef struct Profile Profile; -typedef struct Bucket Bucket; -typedef struct Entry Entry; - -struct Entry { - uintptr count; - uintptr depth; - uintptr stack[MaxStack]; -}; - -struct Bucket { - Entry entry[Assoc]; -}; - -struct Profile { - bool on; // profiling is on - Note wait; // goroutine waits here - uintptr count; // tick count - uintptr evicts; // eviction count - uintptr lost; // lost ticks that need to be logged - uintptr totallost; // total lost ticks - - // Active recent stack traces. - Bucket hash[HashSize]; - - // Log of traces evicted from hash. - // Signal handler has filled log[toggle][:nlog]. - // Goroutine is writing log[1-toggle][:handoff]. - uintptr log[2][LogSize/2]; - uintptr nlog; - int32 toggle; - uint32 handoff; - - // Writer state. - // Writer maintains its own toggle to avoid races - // looking at signal handler's toggle. - uint32 wtoggle; - bool wholding; // holding & need to release a log half - bool flushing; // flushing hash table - profile is over - bool eod_sent; // special end-of-data record sent; => flushing -}; - -static Lock lk; -static Profile *prof; - -static void tick(uintptr*, int32); -static void add(Profile*, uintptr*, int32); -static bool evict(Profile*, Entry*); -static bool flushlog(Profile*); - -static uintptr eod[3] = {0, 1, 0}; - -// LostProfileData is a no-op function used in profiles -// to mark the number of profiling stack traces that were -// discarded due to slow data writers. -static void LostProfileData(void) { -} - -extern void runtime_SetCPUProfileRate(intgo) - __asm__ (GOSYM_PREFIX "runtime.SetCPUProfileRate"); - -// SetCPUProfileRate sets the CPU profiling rate. -// The user documentation is in debug.go. -void -runtime_SetCPUProfileRate(intgo hz) -{ - uintptr *p; - uintptr n; - - // Clamp hz to something reasonable. - if(hz < 0) - hz = 0; - if(hz > 1000000) - hz = 1000000; - - runtime_lock(&lk); - if(hz > 0) { - if(prof == nil) { - prof = runtime_SysAlloc(sizeof *prof); - if(prof == nil) { - runtime_printf("runtime: cpu profiling cannot allocate memory\n"); - runtime_unlock(&lk); - return; - } - } - if(prof->on || prof->handoff != 0) { - runtime_printf("runtime: cannot set cpu profile rate until previous profile has finished.\n"); - runtime_unlock(&lk); - return; - } - - prof->on = true; - p = prof->log[0]; - // pprof binary header format. - // http://code.google.com/p/google-perftools/source/browse/trunk/src/profiledata.cc#117 - *p++ = 0; // count for header - *p++ = 3; // depth for header - *p++ = 0; // version number - *p++ = 1000000 / hz; // period (microseconds) - *p++ = 0; - prof->nlog = p - prof->log[0]; - prof->toggle = 0; - prof->wholding = false; - prof->wtoggle = 0; - prof->flushing = false; - prof->eod_sent = false; - runtime_noteclear(&prof->wait); - - runtime_setcpuprofilerate(tick, hz); - } else if(prof->on) { - runtime_setcpuprofilerate(nil, 0); - prof->on = false; - - // Now add is not running anymore, and getprofile owns the entire log. - // Set the high bit in prof->handoff to tell getprofile. - for(;;) { - n = prof->handoff; - if(n&0x80000000) - runtime_printf("runtime: setcpuprofile(off) twice"); - if(runtime_cas(&prof->handoff, n, n|0x80000000)) - break; - } - if(n == 0) { - // we did the transition from 0 -> nonzero so we wake getprofile - runtime_notewakeup(&prof->wait); - } - } - runtime_unlock(&lk); -} - -static void -tick(uintptr *pc, int32 n) -{ - add(prof, pc, n); -} - -// add adds the stack trace to the profile. -// It is called from signal handlers and other limited environments -// and cannot allocate memory or acquire locks that might be -// held at the time of the signal, nor can it use substantial amounts -// of stack. It is allowed to call evict. -static void -add(Profile *p, uintptr *pc, int32 n) -{ - int32 i, j; - uintptr h, x; - Bucket *b; - Entry *e; - - if(n > MaxStack) - n = MaxStack; - - // Compute hash. - h = 0; - for(i=0; i<n; i++) { - h = h<<8 | (h>>(8*(sizeof(h)-1))); - x = pc[i]; - h += x*31 + x*7 + x*3; - } - p->count++; - - // Add to entry count if already present in table. - b = &p->hash[h%HashSize]; - for(i=0; i<Assoc; i++) { - e = &b->entry[i]; - if(e->depth != (uintptr)n) - continue; - for(j=0; j<n; j++) - if(e->stack[j] != pc[j]) - goto ContinueAssoc; - e->count++; - return; - ContinueAssoc:; - } - - // Evict entry with smallest count. - e = &b->entry[0]; - for(i=1; i<Assoc; i++) - if(b->entry[i].count < e->count) - e = &b->entry[i]; - if(e->count > 0) { - if(!evict(p, e)) { - // Could not evict entry. Record lost stack. - p->lost++; - p->totallost++; - return; - } - p->evicts++; - } - - // Reuse the newly evicted entry. - e->depth = n; - e->count = 1; - for(i=0; i<n; i++) - e->stack[i] = pc[i]; -} - -// evict copies the given entry's data into the log, so that -// the entry can be reused. evict is called from add, which -// is called from the profiling signal handler, so it must not -// allocate memory or block. It is safe to call flushLog. -// evict returns true if the entry was copied to the log, -// false if there was no room available. -static bool -evict(Profile *p, Entry *e) -{ - int32 i, d, nslot; - uintptr *log, *q; - - d = e->depth; - nslot = d+2; - log = p->log[p->toggle]; - if(p->nlog+nslot > nelem(p->log[0])) { - if(!flushlog(p)) - return false; - log = p->log[p->toggle]; - } - - q = log+p->nlog; - *q++ = e->count; - *q++ = d; - for(i=0; i<d; i++) - *q++ = e->stack[i]; - p->nlog = q - log; - e->count = 0; - return true; -} - -// flushlog tries to flush the current log and switch to the other one. -// flushlog is called from evict, called from add, called from the signal handler, -// so it cannot allocate memory or block. It can try to swap logs with -// the writing goroutine, as explained in the comment at the top of this file. -static bool -flushlog(Profile *p) -{ - uintptr *log, *q; - - if(!runtime_cas(&p->handoff, 0, p->nlog)) - return false; - runtime_notewakeup(&p->wait); - - p->toggle = 1 - p->toggle; - log = p->log[p->toggle]; - q = log; - if(p->lost > 0) { - *q++ = p->lost; - *q++ = 1; - *q++ = (uintptr)LostProfileData; - } - p->nlog = q - log; - return true; -} - -// getprofile blocks until the next block of profiling data is available -// and returns it as a []byte. It is called from the writing goroutine. -Slice -getprofile(Profile *p) -{ - uint32 i, j, n; - Slice ret; - Bucket *b; - Entry *e; - - ret.array = nil; - ret.len = 0; - ret.cap = 0; - - if(p == nil) - return ret; - - if(p->wholding) { - // Release previous log to signal handling side. - // Loop because we are racing against setprofile(off). - for(;;) { - n = p->handoff; - if(n == 0) { - runtime_printf("runtime: phase error during cpu profile handoff\n"); - return ret; - } - if(n & 0x80000000) { - p->wtoggle = 1 - p->wtoggle; - p->wholding = false; - p->flushing = true; - goto flush; - } - if(runtime_cas(&p->handoff, n, 0)) - break; - } - p->wtoggle = 1 - p->wtoggle; - p->wholding = false; - } - - if(p->flushing) - goto flush; - - if(!p->on && p->handoff == 0) - return ret; - - // Wait for new log. - runtime_entersyscall(); - runtime_notesleep(&p->wait); - runtime_exitsyscall(); - runtime_noteclear(&p->wait); - - n = p->handoff; - if(n == 0) { - runtime_printf("runtime: phase error during cpu profile wait\n"); - return ret; - } - if(n == 0x80000000) { - p->flushing = true; - goto flush; - } - n &= ~0x80000000; - - // Return new log to caller. - p->wholding = true; - - ret.array = (byte*)p->log[p->wtoggle]; - ret.len = n*sizeof(uintptr); - ret.cap = ret.len; - return ret; - -flush: - // In flush mode. - // Add is no longer being called. We own the log. - // Also, p->handoff is non-zero, so flushlog will return false. - // Evict the hash table into the log and return it. - for(i=0; i<HashSize; i++) { - b = &p->hash[i]; - for(j=0; j<Assoc; j++) { - e = &b->entry[j]; - if(e->count > 0 && !evict(p, e)) { - // Filled the log. Stop the loop and return what we've got. - goto breakflush; - } - } - } -breakflush: - - // Return pending log data. - if(p->nlog > 0) { - // Note that we're using toggle now, not wtoggle, - // because we're working on the log directly. - ret.array = (byte*)p->log[p->toggle]; - ret.len = p->nlog*sizeof(uintptr); - ret.cap = ret.len; - p->nlog = 0; - return ret; - } - - // Made it through the table without finding anything to log. - if(!p->eod_sent) { - // We may not have space to append this to the partial log buf, - // so we always return a new slice for the end-of-data marker. - p->eod_sent = true; - ret.array = (byte*)eod; - ret.len = sizeof eod; - ret.cap = ret.len; - return ret; - } - - // Finally done. Clean up and return nil. - p->flushing = false; - if(!runtime_cas(&p->handoff, p->handoff, 0)) - runtime_printf("runtime: profile flush racing with something\n"); - return ret; // set to nil at top of function -} - -extern Slice runtime_CPUProfile(void) - __asm__ (GOSYM_PREFIX "runtime.CPUProfile"); - -// CPUProfile returns the next cpu profile block as a []byte. -// The user documentation is in debug.go. -Slice -runtime_CPUProfile(void) -{ - return getprofile(prof); -} diff --git a/gcc-4.8.1/libgo/runtime/defs.h b/gcc-4.8.1/libgo/runtime/defs.h deleted file mode 100644 index 67ad212b8..000000000 --- a/gcc-4.8.1/libgo/runtime/defs.h +++ /dev/null @@ -1,12 +0,0 @@ -/* defs.h -- runtime definitions for Go. - - 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 gc library uses this file for system defines, and generates it - automatically using the godefs program. The logical thing to put - here for gccgo would be #include statements for system header - files. We can't do that, though, because runtime.h #define's the - standard types. So we #include the system headers from runtime.h - instead. */ diff --git a/gcc-4.8.1/libgo/runtime/env_posix.c b/gcc-4.8.1/libgo/runtime/env_posix.c deleted file mode 100644 index 7f3fa0d8e..000000000 --- a/gcc-4.8.1/libgo/runtime/env_posix.c +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 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. - -// +build darwin freebsd linux netbsd openbsd windows - -#include "runtime.h" -#include "array.h" - -extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs"); - -const byte* -runtime_getenv(const char *s) -{ - int32 i, j, len; - const byte *v, *bs; - String* envv; - int32 envc; - - bs = (const byte*)s; - len = runtime_findnull(bs); - envv = (String*)syscall_Envs.__values; - envc = syscall_Envs.__count; - for(i=0; i<envc; i++){ - if(envv[i].len <= len) - continue; - v = (const byte*)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; -} diff --git a/gcc-4.8.1/libgo/runtime/getncpu-bsd.c b/gcc-4.8.1/libgo/runtime/getncpu-bsd.c deleted file mode 100644 index 00a81d1dd..000000000 --- a/gcc-4.8.1/libgo/runtime/getncpu-bsd.c +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 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 <sys/types.h> -#include <sys/sysctl.h> - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - int mib[2], out; - size_t len; - - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(out); - if(sysctl(mib, 2, &out, &len, NULL, 0) >= 0) - return (int32)out; - else - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/getncpu-irix.c b/gcc-4.8.1/libgo/runtime/getncpu-irix.c deleted file mode 100644 index a65ca63d2..000000000 --- a/gcc-4.8.1/libgo/runtime/getncpu-irix.c +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 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 <unistd.h> - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - int32 n; - n = (int32)sysconf(_SC_NPROC_ONLN); - return n > 1 ? n : 1; -} diff --git a/gcc-4.8.1/libgo/runtime/getncpu-linux.c b/gcc-4.8.1/libgo/runtime/getncpu-linux.c deleted file mode 100644 index 0122b77c9..000000000 --- a/gcc-4.8.1/libgo/runtime/getncpu-linux.c +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 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 <features.h> -#include <sched.h> - -// CPU_COUNT is only provided by glibc 2.6 or higher -#if !defined(__GLIBC_PREREQ) || !__GLIBC_PREREQ(2, 6) -#define CPU_COUNT(set) _CPU_COUNT((unsigned int *)(set), sizeof(*(set))/sizeof(unsigned int)) -static int _CPU_COUNT(unsigned int *set, size_t len) { - int cnt; - - cnt = 0; - while (len--) - cnt += __builtin_popcount(*set++); - return cnt; -} -#endif - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - cpu_set_t set; - int32 r, cnt; - - cnt = 0; - r = sched_getaffinity(0, sizeof(set), &set); - if(r == 0) - cnt += CPU_COUNT(&set); - - return cnt ? cnt : 1; -} diff --git a/gcc-4.8.1/libgo/runtime/getncpu-none.c b/gcc-4.8.1/libgo/runtime/getncpu-none.c deleted file mode 100644 index ba6fd4e68..000000000 --- a/gcc-4.8.1/libgo/runtime/getncpu-none.c +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2012 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" - -int32 -getproccount(void) -{ - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/getncpu-solaris.c b/gcc-4.8.1/libgo/runtime/getncpu-solaris.c deleted file mode 100644 index 5d5d7025d..000000000 --- a/gcc-4.8.1/libgo/runtime/getncpu-solaris.c +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 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 <unistd.h> - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - int32 n; - n = (int32)sysconf(_SC_NPROCESSORS_ONLN); - return n > 1 ? n : 1; -} diff --git a/gcc-4.8.1/libgo/runtime/go-alloc.h b/gcc-4.8.1/libgo/runtime/go-alloc.h deleted file mode 100644 index c880a043e..000000000 --- a/gcc-4.8.1/libgo/runtime/go-alloc.h +++ /dev/null @@ -1,11 +0,0 @@ -/* go-alloc.h -- allocate memory for Go. - - 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 <stddef.h> -#include <stdint.h> - -extern void *__go_alloc (unsigned int __attribute__ ((mode (pointer)))); -extern void __go_free (void *); diff --git a/gcc-4.8.1/libgo/runtime/go-append.c b/gcc-4.8.1/libgo/runtime/go-append.c deleted file mode 100644 index 12fe876cb..000000000 --- a/gcc-4.8.1/libgo/runtime/go-append.c +++ /dev/null @@ -1,71 +0,0 @@ -/* go-append.c -- the go builtin append function. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-panic.h" -#include "go-type.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -/* We should be OK if we don't split the stack here, since the only - libc functions we call are memcpy and memmove. If we don't do - this, we will always split the stack, because of memcpy and - memmove. */ -extern struct __go_open_array -__go_append (struct __go_open_array, void *, uintptr_t, uintptr_t) - __attribute__ ((no_split_stack)); - -struct __go_open_array -__go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount, - uintptr_t element_size) -{ - uintptr_t ucount; - int count; - - if (bvalues == NULL || bcount == 0) - return a; - - ucount = (uintptr_t) a.__count + bcount; - count = (int) ucount; - if ((uintptr_t) count != ucount || count <= a.__count) - runtime_panicstring ("append: slice overflow"); - - if (count > a.__capacity) - { - int m; - void *n; - - m = a.__capacity; - if (m == 0) - m = (int) bcount; - else - { - do - { - if (a.__count < 1024) - m += m; - else - m += m / 4; - } - while (m < count); - } - - if ((uintptr) m > MaxMem / element_size) - runtime_panicstring ("growslice: cap out of range"); - - n = __go_alloc (m * element_size); - __builtin_memcpy (n, a.__values, a.__count * element_size); - - a.__values = n; - a.__capacity = m; - } - - __builtin_memmove ((char *) a.__values + a.__count * element_size, - bvalues, bcount * element_size); - a.__count = count; - return a; -} diff --git a/gcc-4.8.1/libgo/runtime/go-assert-interface.c b/gcc-4.8.1/libgo/runtime/go-assert-interface.c deleted file mode 100644 index 2510f9aef..000000000 --- a/gcc-4.8.1/libgo/runtime/go-assert-interface.c +++ /dev/null @@ -1,45 +0,0 @@ -/* go-assert-interface.c -- interface type assertion for Go. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "go-panic.h" -#include "go-type.h" -#include "interface.h" - -/* This is called by the compiler to implement a type assertion from - one interface type to another. This returns the value that should - go in the first field of the result tuple. The result may be an - empty or a non-empty interface. */ - -const void * -__go_assert_interface (const struct __go_type_descriptor *lhs_descriptor, - const struct __go_type_descriptor *rhs_descriptor) -{ - const struct __go_interface_type *lhs_interface; - - if (rhs_descriptor == NULL) - { - struct __go_empty_interface panic_arg; - - /* A type assertion is not permitted with a nil interface. */ - - runtime_newTypeAssertionError (NULL, NULL, lhs_descriptor->__reflection, - NULL, &panic_arg); - __go_panic (panic_arg); - } - - /* A type assertion to an empty interface just returns the object - descriptor. */ - - __go_assert (lhs_descriptor->__code == GO_INTERFACE); - lhs_interface = (const struct __go_interface_type *) lhs_descriptor; - if (lhs_interface->__methods.__count == 0) - return rhs_descriptor; - - return __go_convert_interface_2 (lhs_descriptor, rhs_descriptor, 0); -} diff --git a/gcc-4.8.1/libgo/runtime/go-assert.c b/gcc-4.8.1/libgo/runtime/go-assert.c deleted file mode 100644 index a36f43a75..000000000 --- a/gcc-4.8.1/libgo/runtime/go-assert.c +++ /dev/null @@ -1,19 +0,0 @@ -/* go-assert.c -- libgo specific assertions - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <stdio.h> -#include <stdlib.h> - -#include "runtime.h" -#include "go-assert.h" - -void -__go_assert_fail (const char *file, unsigned int lineno) -{ - /* FIXME: Eventually we should dump a stack trace here. */ - runtime_printf ("%s:%U: libgo assertion failure\n", file, (uint64) lineno); - abort (); -} diff --git a/gcc-4.8.1/libgo/runtime/go-assert.h b/gcc-4.8.1/libgo/runtime/go-assert.h deleted file mode 100644 index 636559597..000000000 --- a/gcc-4.8.1/libgo/runtime/go-assert.h +++ /dev/null @@ -1,18 +0,0 @@ -/* go-assert.h -- libgo specific assertions - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#ifndef LIBGO_GO_ASSERT_H -#define LIBGO_GO_ASSERT_H - -/* We use a Go specific assert function so that functions which call - assert aren't required to always split the stack. */ - -extern void __go_assert_fail (const char *file, unsigned int lineno) - __attribute__ ((noreturn)); - -#define __go_assert(e) ((e) ? (void) 0 : __go_assert_fail (__FILE__, __LINE__)) - -#endif /* !defined(LIBGO_GO_ASSERT_H) */ diff --git a/gcc-4.8.1/libgo/runtime/go-breakpoint.c b/gcc-4.8.1/libgo/runtime/go-breakpoint.c deleted file mode 100644 index e403a2a96..000000000 --- a/gcc-4.8.1/libgo/runtime/go-breakpoint.c +++ /dev/null @@ -1,17 +0,0 @@ -/* go-breakpoint.c -- the runtime.Breakpoint function. - - 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 <sched.h> - -#include "runtime.h" - -void Breakpoint (void) __asm__ (GOSYM_PREFIX "runtime.Breakpoint"); - -void -Breakpoint (void) -{ - __builtin_trap (); -} diff --git a/gcc-4.8.1/libgo/runtime/go-byte-array-to-string.c b/gcc-4.8.1/libgo/runtime/go-byte-array-to-string.c deleted file mode 100644 index 0cd63c76d..000000000 --- a/gcc-4.8.1/libgo/runtime/go-byte-array-to-string.c +++ /dev/null @@ -1,24 +0,0 @@ -/* go-byte-array-to-string.c -- convert an array of bytes to a string in Go. - - 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 "arch.h" -#include "malloc.h" - -String -__go_byte_array_to_string (const void* p, intgo len) -{ - const unsigned char *bytes; - unsigned char *retdata; - String ret; - - bytes = (const unsigned char *) p; - retdata = runtime_mallocgc ((uintptr) len, FlagNoPointers, 1, 0); - __builtin_memcpy (retdata, bytes, len); - ret.str = retdata; - ret.len = len; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-caller.c b/gcc-4.8.1/libgo/runtime/go-caller.c deleted file mode 100644 index d84580fa5..000000000 --- a/gcc-4.8.1/libgo/runtime/go-caller.c +++ /dev/null @@ -1,230 +0,0 @@ -/* go-caller.c -- runtime.Caller and runtime.FuncForPC for Go. - - 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. */ - -/* Implement runtime.Caller. */ - -#include <stdint.h> - -#include "backtrace.h" - -#include "runtime.h" - -/* Get the function name, file name, and line number for a PC value. - We use the backtrace library to get this. */ - -/* Data structure to gather file/line information. */ - -struct caller -{ - String fn; - String file; - intgo line; -}; - -/* Collect file/line information for a PC value. If this is called - more than once, due to inlined functions, we use the last call, as - that is usually the most useful one. */ - -static int -callback (void *data, uintptr_t pc __attribute__ ((unused)), - const char *filename, int lineno, const char *function) -{ - struct caller *c = (struct caller *) data; - - if (function == NULL) - { - c->fn.str = NULL; - c->fn.len = 0; - } - else - { - byte *s; - - c->fn.len = __builtin_strlen (function); - s = runtime_malloc (c->fn.len); - __builtin_memcpy (s, function, c->fn.len); - c->fn.str = s; - } - - if (filename == NULL) - { - c->file.str = NULL; - c->file.len = 0; - } - else - { - byte *s; - - c->file.len = __builtin_strlen (filename); - s = runtime_malloc (c->file.len); - __builtin_memcpy (s, filename, c->file.len); - c->file.str = s; - } - - c->line = lineno; - - return 0; -} - -/* The error callback for backtrace_pcinfo and backtrace_syminfo. */ - -static void -error_callback (void *data __attribute__ ((unused)), - const char *msg, int errnum) -{ - if (errnum == -1) - return; - if (errnum > 0) - runtime_printf ("%s errno %d\n", msg, errnum); - runtime_throw (msg); -} - -/* The backtrace library state. */ - -static void *back_state; - -/* A lock to control creating back_state. */ - -static Lock back_state_lock; - -/* Fetch back_state, creating it if necessary. */ - -struct backtrace_state * -__go_get_backtrace_state () -{ - runtime_lock (&back_state_lock); - if (back_state == NULL) - { - const char *filename; - - filename = (const char *) runtime_progname (); - back_state = backtrace_create_state (filename, 1, error_callback, NULL); - } - runtime_unlock (&back_state_lock); - return back_state; -} - -/* Return function/file/line information for PC. */ - -_Bool -__go_file_line (uintptr pc, String *fn, String *file, intgo *line) -{ - struct caller c; - - runtime_memclr (&c, sizeof c); - backtrace_pcinfo (__go_get_backtrace_state (), pc, callback, - error_callback, &c); - *fn = c.fn; - *file = c.file; - *line = c.line; - return c.file.len > 0; -} - -/* Collect symbol information. */ - -static void -syminfo_callback (void *data, uintptr_t pc __attribute__ ((unused)), - const char *symname __attribute__ ((unused)), - uintptr_t address) -{ - uintptr_t *pval = (uintptr_t *) data; - - *pval = address; -} - -/* Set *VAL to the value of the symbol for PC. */ - -static _Bool -__go_symbol_value (uintptr_t pc, uintptr_t *val) -{ - *val = 0; - backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback, - error_callback, val); - return *val != 0; -} - -/* The values returned by runtime.Caller. */ - -struct caller_ret -{ - uintptr_t pc; - String file; - intgo line; - _Bool ok; -}; - -struct caller_ret Caller (int n) __asm__ (GOSYM_PREFIX "runtime.Caller"); - -Func *FuncForPC (uintptr_t) __asm__ (GOSYM_PREFIX "runtime.FuncForPC"); - -/* Implement runtime.Caller. */ - -struct caller_ret -Caller (int skip) -{ - struct caller_ret ret; - Location loc; - int32 n; - - runtime_memclr (&ret, sizeof ret); - n = runtime_callers (skip + 1, &loc, 1); - if (n < 1) - return ret; - ret.pc = loc.pc; - ret.file = loc.filename; - ret.line = loc.lineno; - ret.ok = 1; - return ret; -} - -/* Implement runtime.FuncForPC. */ - -Func * -FuncForPC (uintptr_t pc) -{ - Func *ret; - String fn; - String file; - intgo line; - uintptr_t val; - - if (!__go_file_line (pc, &fn, &file, &line)) - return NULL; - - ret = (Func *) runtime_malloc (sizeof (*ret)); - ret->name = fn; - - if (__go_symbol_value (pc, &val)) - ret->entry = val; - else - ret->entry = 0; - - return ret; -} - -/* Look up the file and line information for a PC within a - function. */ - -struct funcline_go_return -{ - String retfile; - intgo retline; -}; - -struct funcline_go_return -runtime_funcline_go (Func *f, uintptr targetpc) - __asm__ (GOSYM_PREFIX "runtime.funcline_go"); - -struct funcline_go_return -runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc) -{ - struct funcline_go_return ret; - String fn; - - if (!__go_file_line (targetpc, &fn, &ret.retfile, &ret.retline)) - runtime_memclr (&ret, sizeof ret); - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-callers.c b/gcc-4.8.1/libgo/runtime/go-callers.c deleted file mode 100644 index dd1cf7909..000000000 --- a/gcc-4.8.1/libgo/runtime/go-callers.c +++ /dev/null @@ -1,126 +0,0 @@ -/* go-callers.c -- get callers for Go. - - Copyright 2012 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 "config.h" - -#include "backtrace.h" - -#include "runtime.h" -#include "array.h" - -/* Argument passed to callback function. */ - -struct callers_data -{ - Location *locbuf; - int skip; - int index; - int max; -}; - -/* Callback function for backtrace_full. Just collect the locations. - Return zero to continue, non-zero to stop. */ - -static int -callback (void *data, uintptr_t pc, const char *filename, int lineno, - const char *function) -{ - struct callers_data *arg = (struct callers_data *) data; - Location *loc; - - /* Skip split stack functions. */ - if (function != NULL) - { - const char *p; - - p = function; - if (__builtin_strncmp (p, "___", 3) == 0) - ++p; - if (__builtin_strncmp (p, "__morestack_", 12) == 0) - return 0; - } - else if (filename != NULL) - { - const char *p; - - p = strrchr (filename, '/'); - if (p == NULL) - p = filename; - if (__builtin_strncmp (p, "/morestack.S", 12) == 0) - return 0; - } - - if (arg->skip > 0) - { - --arg->skip; - return 0; - } - - loc = &arg->locbuf[arg->index]; - loc->pc = pc; - - /* The libbacktrace library says that these strings might disappear, - but with the current implementation they won't. We can't easily - allocate memory here, so for now assume that we can save a - pointer to the strings. */ - loc->filename = runtime_gostringnocopy ((const byte *) filename); - loc->function = runtime_gostringnocopy ((const byte *) function); - - loc->lineno = lineno; - ++arg->index; - return arg->index >= arg->max; -} - -/* Error callback. */ - -static void -error_callback (void *data __attribute__ ((unused)), - const char *msg, int errnum) -{ - if (errnum != 0) - runtime_printf ("%s errno %d\n", msg, errnum); - runtime_throw (msg); -} - -/* Gather caller PC's. */ - -int32 -runtime_callers (int32 skip, Location *locbuf, int32 m) -{ - struct callers_data data; - - data.locbuf = locbuf; - data.skip = skip + 1; - data.index = 0; - data.max = m; - backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback, - &data); - return data.index; -} - -int Callers (int, struct __go_open_array) - __asm__ (GOSYM_PREFIX "runtime.Callers"); - -int -Callers (int skip, struct __go_open_array pc) -{ - Location *locbuf; - int ret; - int i; - - locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location)); - - /* In the Go 1 release runtime.Callers has an off-by-one error, - which we can not correct because it would break backward - compatibility. Normally we would add 1 to SKIP here, but we - don't so that we are compatible. */ - ret = runtime_callers (skip, locbuf, pc.__count); - - for (i = 0; i < ret; i++) - ((uintptr *) pc.__values)[i] = locbuf[i].pc; - - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-can-convert-interface.c b/gcc-4.8.1/libgo/runtime/go-can-convert-interface.c deleted file mode 100644 index 4de558077..000000000 --- a/gcc-4.8.1/libgo/runtime/go-can-convert-interface.c +++ /dev/null @@ -1,78 +0,0 @@ -/* go-can-convert-interface.c -- can we convert to an interface? - - 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 "go-assert.h" -#include "go-string.h" -#include "go-type.h" -#include "interface.h" - -/* Return whether we can convert from the type in FROM_DESCRIPTOR to - the interface in TO_DESCRIPTOR. This is used for type - switches. */ - -_Bool -__go_can_convert_to_interface ( - const struct __go_type_descriptor *to_descriptor, - const struct __go_type_descriptor *from_descriptor) -{ - const struct __go_interface_type *to_interface; - int to_method_count; - const struct __go_interface_method *to_method; - const struct __go_uncommon_type *from_uncommon; - int from_method_count; - const struct __go_method *from_method; - int i; - - /* In a type switch FROM_DESCRIPTOR can be NULL. */ - if (from_descriptor == NULL) - return 0; - - __go_assert (to_descriptor->__code == GO_INTERFACE); - to_interface = (const struct __go_interface_type *) to_descriptor; - to_method_count = to_interface->__methods.__count; - to_method = ((const struct __go_interface_method *) - to_interface->__methods.__values); - - from_uncommon = from_descriptor->__uncommon; - if (from_uncommon == NULL) - { - from_method_count = 0; - from_method = NULL; - } - else - { - from_method_count = from_uncommon->__methods.__count; - from_method = ((const struct __go_method *) - from_uncommon->__methods.__values); - } - - for (i = 0; i < to_method_count; ++i) - { - while (from_method_count > 0 - && (!__go_ptr_strings_equal (from_method->__name, - to_method->__name) - || !__go_ptr_strings_equal (from_method->__pkg_path, - to_method->__pkg_path))) - { - ++from_method; - --from_method_count; - } - - if (from_method_count == 0) - return 0; - - if (!__go_type_descriptors_equal (from_method->__mtype, - to_method->__type)) - return 0; - - ++to_method; - ++from_method; - --from_method_count; - } - - return 1; -} diff --git a/gcc-4.8.1/libgo/runtime/go-cgo.c b/gcc-4.8.1/libgo/runtime/go-cgo.c deleted file mode 100644 index 46eb1827a..000000000 --- a/gcc-4.8.1/libgo/runtime/go-cgo.c +++ /dev/null @@ -1,167 +0,0 @@ -/* go-cgo.c -- SWIG support routines for libgo. - - Copyright 2011 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 "go-alloc.h" -#include "interface.h" -#include "go-panic.h" - -/* Prepare to call from code written in Go to code written in C or - C++. This takes the current goroutine out of the Go scheduler, as - though it were making a system call. Otherwise the program can - lock up if the C code goes to sleep on a mutex or for some other - reason. This idea is to call this function, then immediately call - the C/C++ function. After the C/C++ function returns, call - syscall_cgocalldone. The usual Go code would look like - - syscall.Cgocall() - defer syscall.Cgocalldone() - cfunction() - - */ - -/* We let Go code call these via the syscall package. */ -void syscall_cgocall(void) __asm__ (GOSYM_PREFIX "syscall.Cgocall"); -void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallDone"); -void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBack"); -void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBackDone"); - -void -syscall_cgocall () -{ - M* m; - G* g; - - m = runtime_m (); - ++m->ncgocall; - g = runtime_g (); - ++g->ncgo; - runtime_entersyscall (); -} - -/* Prepare to return to Go code from C/C++ code. */ - -void -syscall_cgocalldone () -{ - G* g; - - g = runtime_g (); - __go_assert (g != NULL); - --g->ncgo; - if (g->ncgo == 0) - { - /* We are going back to Go, and we are not in a recursive call. - Let the garbage collector clean up any unreferenced - memory. */ - g->cgomal = NULL; - } - - /* If we are invoked because the C function called _cgo_panic, then - _cgo_panic will already have exited syscall mode. */ - if (g->status == Gsyscall) - runtime_exitsyscall (); -} - -/* Call back from C/C++ code to Go code. */ - -void -syscall_cgocallback () -{ - runtime_exitsyscall (); -} - -/* Prepare to return to C/C++ code from a callback to Go code. */ - -void -syscall_cgocallbackdone () -{ - runtime_entersyscall (); -} - -/* Allocate memory and save it in a list visible to the Go garbage - collector. */ - -void * -alloc_saved (size_t n) -{ - void *ret; - G *g; - CgoMal *c; - - ret = __go_alloc (n); - - g = runtime_g (); - c = (CgoMal *) __go_alloc (sizeof (CgoMal)); - c->next = g->cgomal; - c->alloc = ret; - g->cgomal = c; - - return ret; -} - -/* These are routines used by SWIG. The gc runtime library provides - the same routines under the same name, though in that case the code - is required to import runtime/cgo. */ - -void * -_cgo_allocate (size_t n) -{ - void *ret; - - runtime_exitsyscall (); - ret = alloc_saved (n); - runtime_entersyscall (); - return ret; -} - -extern const struct __go_type_descriptor string_type_descriptor - __asm__ (GOSYM_PREFIX "__go_tdn_string"); - -void -_cgo_panic (const char *p) -{ - intgo len; - unsigned char *data; - String *ps; - struct __go_empty_interface e; - - runtime_exitsyscall (); - len = __builtin_strlen (p); - data = alloc_saved (len); - __builtin_memcpy (data, p, len); - ps = alloc_saved (sizeof *ps); - ps->str = data; - ps->len = len; - e.__type_descriptor = &string_type_descriptor; - e.__object = ps; - - /* We don't call runtime_entersyscall here, because normally what - will happen is that we will walk up the stack to a Go deferred - function that calls recover. However, this will do the wrong - thing if this panic is recovered and the stack unwinding is - caught by a C++ exception handler. It might be possible to - handle this by calling runtime_entersyscall in the personality - function in go-unwind.c. FIXME. */ - - __go_panic (e); -} - -/* Return the number of CGO calls. */ - -int64 runtime_NumCgoCall (void) __asm__ (GOSYM_PREFIX "runtime.NumCgoCall"); - -int64 -runtime_NumCgoCall (void) -{ - int64 ret; - M* m; - - ret = 0; - for (m = runtime_atomicloadp (&runtime_allm); m != NULL; m = m->alllink) - ret += m->ncgocall; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-check-interface.c b/gcc-4.8.1/libgo/runtime/go-check-interface.c deleted file mode 100644 index c29971ada..000000000 --- a/gcc-4.8.1/libgo/runtime/go-check-interface.c +++ /dev/null @@ -1,46 +0,0 @@ -/* go-check-interface.c -- check an interface type for a conversion - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-panic.h" -#include "go-type.h" -#include "interface.h" - -/* Check that an interface type matches for a conversion to a - non-interface type. This panics if the types are bad. The actual - extraction of the object is inlined. */ - -void -__go_check_interface_type ( - const struct __go_type_descriptor *lhs_descriptor, - const struct __go_type_descriptor *rhs_descriptor, - const struct __go_type_descriptor *rhs_inter_descriptor) -{ - if (rhs_descriptor == NULL) - { - struct __go_empty_interface panic_arg; - - runtime_newTypeAssertionError(NULL, NULL, lhs_descriptor->__reflection, - NULL, &panic_arg); - __go_panic(panic_arg); - } - - if (lhs_descriptor != rhs_descriptor - && !__go_type_descriptors_equal (lhs_descriptor, rhs_descriptor) - && (lhs_descriptor->__code != GO_UNSAFE_POINTER - || !__go_is_pointer_type (rhs_descriptor)) - && (rhs_descriptor->__code != GO_UNSAFE_POINTER - || !__go_is_pointer_type (lhs_descriptor))) - { - struct __go_empty_interface panic_arg; - - runtime_newTypeAssertionError(rhs_inter_descriptor->__reflection, - rhs_descriptor->__reflection, - lhs_descriptor->__reflection, - NULL, &panic_arg); - __go_panic(panic_arg); - } -} diff --git a/gcc-4.8.1/libgo/runtime/go-construct-map.c b/gcc-4.8.1/libgo/runtime/go-construct-map.c deleted file mode 100644 index 4bd79d200..000000000 --- a/gcc-4.8.1/libgo/runtime/go-construct-map.c +++ /dev/null @@ -1,35 +0,0 @@ -/* go-construct-map.c -- construct a map from an initializer. - - 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 <stddef.h> -#include <stdint.h> -#include <stdlib.h> - -#include "runtime.h" -#include "map.h" - -struct __go_map * -__go_construct_map (const struct __go_map_descriptor *descriptor, - uintptr_t count, uintptr_t entry_size, - uintptr_t val_offset, uintptr_t val_size, - const void *ventries) -{ - struct __go_map *ret; - const unsigned char *entries; - uintptr_t i; - - ret = __go_new_map (descriptor, count); - - entries = (const unsigned char *) ventries; - for (i = 0; i < count; ++i) - { - void *val = __go_map_index (ret, entries, 1); - __builtin_memcpy (val, entries + val_offset, val_size); - entries += entry_size; - } - - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-convert-interface.c b/gcc-4.8.1/libgo/runtime/go-convert-interface.c deleted file mode 100644 index 3eee6bf4a..000000000 --- a/gcc-4.8.1/libgo/runtime/go-convert-interface.c +++ /dev/null @@ -1,132 +0,0 @@ -/* go-convert-interface.c -- convert interfaces for Go. - - 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 "go-alloc.h" -#include "go-assert.h" -#include "go-panic.h" -#include "go-string.h" -#include "go-type.h" -#include "interface.h" - -/* This is called when converting one interface type into another - interface type. LHS_DESCRIPTOR is the type descriptor of the - resulting interface. RHS_DESCRIPTOR is the type descriptor of the - object being converted. This builds and returns a new interface - method table. If any method in the LHS_DESCRIPTOR interface is not - implemented by the object, the conversion fails. If the conversion - fails, then if MAY_FAIL is true this returns NULL; otherwise, it - panics. */ - -void * -__go_convert_interface_2 (const struct __go_type_descriptor *lhs_descriptor, - const struct __go_type_descriptor *rhs_descriptor, - _Bool may_fail) -{ - const struct __go_interface_type *lhs_interface; - int lhs_method_count; - const struct __go_interface_method* lhs_methods; - const void **methods; - const struct __go_uncommon_type *rhs_uncommon; - int rhs_method_count; - const struct __go_method *p_rhs_method; - int i; - - if (rhs_descriptor == NULL) - { - /* A nil value always converts to nil. */ - return NULL; - } - - __go_assert (lhs_descriptor->__code == GO_INTERFACE); - lhs_interface = (const struct __go_interface_type *) lhs_descriptor; - lhs_method_count = lhs_interface->__methods.__count; - lhs_methods = ((const struct __go_interface_method *) - lhs_interface->__methods.__values); - - /* This should not be called for an empty interface. */ - __go_assert (lhs_method_count > 0); - - rhs_uncommon = rhs_descriptor->__uncommon; - if (rhs_uncommon == NULL || rhs_uncommon->__methods.__count == 0) - { - struct __go_empty_interface panic_arg; - - if (may_fail) - return NULL; - - runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection, - lhs_descriptor->__reflection, - lhs_methods[0].__name, - &panic_arg); - __go_panic (panic_arg); - } - - rhs_method_count = rhs_uncommon->__methods.__count; - p_rhs_method = ((const struct __go_method *) - rhs_uncommon->__methods.__values); - - methods = NULL; - - for (i = 0; i < lhs_method_count; ++i) - { - const struct __go_interface_method *p_lhs_method; - - p_lhs_method = &lhs_methods[i]; - - while (rhs_method_count > 0 - && (!__go_ptr_strings_equal (p_lhs_method->__name, - p_rhs_method->__name) - || !__go_ptr_strings_equal (p_lhs_method->__pkg_path, - p_rhs_method->__pkg_path))) - { - ++p_rhs_method; - --rhs_method_count; - } - - if (rhs_method_count == 0 - || !__go_type_descriptors_equal (p_lhs_method->__type, - p_rhs_method->__mtype)) - { - struct __go_empty_interface panic_arg; - - if (methods != NULL) - __go_free (methods); - - if (may_fail) - return NULL; - - runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection, - lhs_descriptor->__reflection, - p_lhs_method->__name, &panic_arg); - __go_panic (panic_arg); - } - - if (methods == NULL) - { - methods = (const void **) __go_alloc ((lhs_method_count + 1) - * sizeof (void *)); - - /* The first field in the method table is always the type of - the object. */ - methods[0] = rhs_descriptor; - } - - methods[i + 1] = p_rhs_method->__function; - } - - return methods; -} - -/* This is called by the compiler to convert a value from one - interface type to another. */ - -void * -__go_convert_interface (const struct __go_type_descriptor *lhs_descriptor, - const struct __go_type_descriptor *rhs_descriptor) -{ - return __go_convert_interface_2 (lhs_descriptor, rhs_descriptor, 0); -} diff --git a/gcc-4.8.1/libgo/runtime/go-copy.c b/gcc-4.8.1/libgo/runtime/go-copy.c deleted file mode 100644 index 05e16acbf..000000000 --- a/gcc-4.8.1/libgo/runtime/go-copy.c +++ /dev/null @@ -1,22 +0,0 @@ -/* go-append.c -- the go builtin copy function. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <stddef.h> -#include <stdint.h> - -/* We should be OK if we don't split the stack here, since we are just - calling memmove which shouldn't need much stack. If we don't do - this we will always split the stack, because of memmove. */ - -extern void -__go_copy (void *, void *, uintptr_t) - __attribute__ ((no_split_stack)); - -void -__go_copy (void *a, void *b, uintptr_t len) -{ - __builtin_memmove (a, b, len); -} diff --git a/gcc-4.8.1/libgo/runtime/go-defer.c b/gcc-4.8.1/libgo/runtime/go-defer.c deleted file mode 100644 index c27de6ab4..000000000 --- a/gcc-4.8.1/libgo/runtime/go-defer.c +++ /dev/null @@ -1,77 +0,0 @@ -/* go-defer.c -- manage the defer stack. - - 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 <stddef.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-panic.h" -#include "go-defer.h" - -/* This function is called each time we need to defer a call. */ - -void -__go_defer (_Bool *frame, void (*pfn) (void *), void *arg) -{ - G *g; - struct __go_defer_stack *n; - - g = runtime_g (); - n = (struct __go_defer_stack *) __go_alloc (sizeof (struct __go_defer_stack)); - n->__next = g->defer; - n->__frame = frame; - n->__panic = g->panic; - n->__pfn = pfn; - n->__arg = arg; - n->__retaddr = NULL; - g->defer = n; -} - -/* This function is called when we want to undefer the stack. */ - -void -__go_undefer (_Bool *frame) -{ - G *g; - - g = runtime_g (); - while (g->defer != NULL && g->defer->__frame == frame) - { - struct __go_defer_stack *d; - void (*pfn) (void *); - - d = g->defer; - pfn = d->__pfn; - d->__pfn = NULL; - - if (pfn != NULL) - (*pfn) (d->__arg); - - g->defer = d->__next; - __go_free (d); - - /* Since we are executing a defer function here, we know we are - returning from the calling function. If the calling - function, or one of its callees, paniced, then the defer - functions would be executed by __go_panic. */ - *frame = 1; - } -} - -/* This function is called to record the address to which the deferred - function returns. This may in turn be checked by __go_can_recover. - The frontend relies on this function returning false. */ - -_Bool -__go_set_defer_retaddr (void *retaddr) -{ - G *g; - - g = runtime_g (); - if (g->defer != NULL) - g->defer->__retaddr = retaddr; - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-defer.h b/gcc-4.8.1/libgo/runtime/go-defer.h deleted file mode 100644 index 0b20e8f6e..000000000 --- a/gcc-4.8.1/libgo/runtime/go-defer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* go-defer.h -- the defer stack. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -struct __go_panic_stack; - -/* The defer stack is a list of these structures. */ - -struct __go_defer_stack -{ - /* The next entry in the stack. */ - struct __go_defer_stack *__next; - - /* The stack variable for the function which called this defer - statement. This is set to 1 if we are returning from that - function, 0 if we are panicing through it. */ - _Bool *__frame; - - /* The value of the panic stack when this function is deferred. - This function can not recover this value from the panic stack. - This can happen if a deferred function uses its own defer - statement. */ - struct __go_panic_stack *__panic; - - /* The function to call. */ - void (*__pfn) (void *); - - /* The argument to pass to the function. */ - void *__arg; - - /* The return address that a recover thunk matches against. This is - set by __go_set_defer_retaddr which is called by the thunks - created by defer statements. */ - const void *__retaddr; -}; diff --git a/gcc-4.8.1/libgo/runtime/go-deferred-recover.c b/gcc-4.8.1/libgo/runtime/go-deferred-recover.c deleted file mode 100644 index 78ef287cf..000000000 --- a/gcc-4.8.1/libgo/runtime/go-deferred-recover.c +++ /dev/null @@ -1,94 +0,0 @@ -/* go-deferred-recover.c -- support for a deferred recover function. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <stddef.h> - -#include "runtime.h" -#include "go-panic.h" -#include "go-defer.h" - -/* This is called when a call to recover is deferred. That is, - something like - defer recover() - - We need to handle this specially. In 6g/8g, the recover function - looks up the stack frame. In particular, that means that a - deferred recover will not recover a panic thrown in the same - function that defers the recover. It will only recover a panic - thrown in a function that defers the deferred call to recover. - - In other words: - - func f1() { - defer recover() // does not stop panic - panic(0) - } - - func f2() { - defer func() { - defer recover() // stops panic(0) - }() - panic(0) - } - - func f3() { - defer func() { - defer recover() // does not stop panic - panic(0) - }() - panic(1) - } - - func f4() { - defer func() { - defer func() { - defer recover() // stops panic(0) - }() - panic(0) - }() - panic(1) - } - - The interesting case here is f3. As can be seen from f2, the - deferred recover could pick up panic(1). However, this does not - happen because it is blocked by the panic(0). - - When a function calls recover, then when we invoke it we pass a - hidden parameter indicating whether it should recover something. - This parameter is set based on whether the function is being - invoked directly from defer. The parameter winds up determining - whether __go_recover or __go_deferred_recover is called at all. - - In the case of a deferred recover, the hidden parameter which - controls the call is actually the one set up for the function which - runs the defer recover() statement. That is the right thing in all - the cases above except for f3. In f3 the function is permitted to - call recover, but the deferred recover call is not. We address - that here by checking for that specific case before calling - recover. If this function was deferred when there is already a - panic on the panic stack, then we can only recover that panic, not - any other. - - Note that we can get away with using a special function here - because you are not permitted to take the address of a predeclared - function like recover. */ - -struct __go_empty_interface -__go_deferred_recover () -{ - G *g; - - g = runtime_g (); - if (g->defer == NULL || g->defer->__panic != g->panic) - { - struct __go_empty_interface ret; - - ret.__type_descriptor = NULL; - ret.__object = NULL; - return ret; - } - return __go_recover (); -} diff --git a/gcc-4.8.1/libgo/runtime/go-eface-compare.c b/gcc-4.8.1/libgo/runtime/go-eface-compare.c deleted file mode 100644 index e738efced..000000000 --- a/gcc-4.8.1/libgo/runtime/go-eface-compare.c +++ /dev/null @@ -1,39 +0,0 @@ -/* go-eface-compare.c -- compare two empty values. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-type.h" -#include "interface.h" - -/* Compare two interface values. Return 0 for equal, not zero for not - equal (return value is like strcmp). */ - -intgo -__go_empty_interface_compare (struct __go_empty_interface left, - struct __go_empty_interface right) -{ - const struct __go_type_descriptor *left_descriptor; - - left_descriptor = left.__type_descriptor; - - if (((uintptr_t) left_descriptor & reflectFlags) != 0 - || ((uintptr_t) right.__type_descriptor & reflectFlags) != 0) - runtime_panicstring ("invalid interface value"); - - if (left_descriptor == NULL && right.__type_descriptor == NULL) - return 0; - if (left_descriptor == NULL || right.__type_descriptor == NULL) - return 1; - if (!__go_type_descriptors_equal (left_descriptor, - right.__type_descriptor)) - return 1; - if (__go_is_pointer_type (left_descriptor)) - return left.__object == right.__object ? 0 : 1; - if (!left_descriptor->__equalfn (left.__object, right.__object, - left_descriptor->__size)) - return 1; - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-eface-val-compare.c b/gcc-4.8.1/libgo/runtime/go-eface-val-compare.c deleted file mode 100644 index 454ea3eba..000000000 --- a/gcc-4.8.1/libgo/runtime/go-eface-val-compare.c +++ /dev/null @@ -1,35 +0,0 @@ -/* go-eface-val-compare.c -- compare an empty interface with a value. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-type.h" -#include "interface.h" - -/* Compare an empty interface with a value. Return 0 for equal, not - zero for not equal (return value is like strcmp). */ - -intgo -__go_empty_interface_value_compare ( - struct __go_empty_interface left, - const struct __go_type_descriptor *right_descriptor, - const void *val) -{ - const struct __go_type_descriptor *left_descriptor; - - left_descriptor = left.__type_descriptor; - if (((uintptr_t) left_descriptor & reflectFlags) != 0) - runtime_panicstring ("invalid interface value"); - if (left_descriptor == NULL) - return 1; - if (!__go_type_descriptors_equal (left_descriptor, right_descriptor)) - return 1; - if (__go_is_pointer_type (left_descriptor)) - return left.__object == val ? 0 : 1; - if (!left_descriptor->__equalfn (left.__object, val, - left_descriptor->__size)) - return 1; - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-fieldtrack.c b/gcc-4.8.1/libgo/runtime/go-fieldtrack.c deleted file mode 100644 index a7e2c1334..000000000 --- a/gcc-4.8.1/libgo/runtime/go-fieldtrack.c +++ /dev/null @@ -1,101 +0,0 @@ -/* go-fieldtrack.c -- structure field data analysis. - - Copyright 2012 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 "go-type.h" -#include "map.h" - -/* The compiler will track fields that have the tag go:"track". Any - function that refers to such a field will call this function with a - string - fieldtrack "package.type.field" - - This function does not actually do anything. Instead, we gather - the field tracking information by looking for strings of that form - in the read-only data section. This is, of course, a horrible - hack, but it's good enough for now. We can improve it, e.g., by a - linker plugin, if this turns out to be useful. */ - -void -__go_fieldtrack (byte *p __attribute__ ((unused))) -{ -} - -/* A runtime function to add all the tracked fields to a - map[string]bool. */ - -extern const char _etext[] __attribute__ ((weak)); -extern const char __etext[] __attribute__ ((weak)); -extern const char __data_start[] __attribute__ ((weak)); -extern const char _edata[] __attribute__ ((weak)); -extern const char __edata[] __attribute__ ((weak)); -extern const char __bss_start[] __attribute__ ((weak)); - -void runtime_Fieldtrack (struct __go_map *) __asm__ (GOSYM_PREFIX "runtime.Fieldtrack"); - -void -runtime_Fieldtrack (struct __go_map *m) -{ - const char *p; - const char *pend; - const char *prefix; - size_t prefix_len; - - p = __data_start; - if (p == NULL) - p = __etext; - if (p == NULL) - p = _etext; - if (p == NULL) - return; - - pend = __edata; - if (pend == NULL) - pend = _edata; - if (pend == NULL) - pend = __bss_start; - if (pend == NULL) - return; - - prefix = "fieldtrack "; - prefix_len = __builtin_strlen (prefix); - - while (p < pend) - { - const char *q1; - const char *q2; - - q1 = __builtin_memchr (p + prefix_len, '"', pend - (p + prefix_len)); - if (q1 == NULL) - break; - - if (__builtin_memcmp (q1 - prefix_len, prefix, prefix_len) != 0) - { - p = q1 + 1; - continue; - } - - q1++; - q2 = __builtin_memchr (q1, '"', pend - q1); - if (q2 == NULL) - break; - - if (__builtin_memchr (q1, '\0', q2 - q1) == NULL) - { - String s; - void *v; - _Bool *pb; - - s.str = (const byte *) q1; - s.len = q2 - q1; - v = __go_map_index (m, &s, 1); - pb = (_Bool *) v; - *pb = 1; - } - - p = q2; - } -} diff --git a/gcc-4.8.1/libgo/runtime/go-getgoroot.c b/gcc-4.8.1/libgo/runtime/go-getgoroot.c deleted file mode 100644 index 1b52d4404..000000000 --- a/gcc-4.8.1/libgo/runtime/go-getgoroot.c +++ /dev/null @@ -1,26 +0,0 @@ -/* go-getgoroot.c -- getgoroot function for runtime package. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <stdlib.h> - -#include "runtime.h" - -String getgoroot (void) __asm__ (GOSYM_PREFIX "runtime.getgoroot"); - -String -getgoroot () -{ - const char *p; - String ret; - - p = getenv ("GOROOT"); - ret.str = (const byte *) p; - if (ret.str == NULL) - ret.len = 0; - else - ret.len = __builtin_strlen (p); - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-int-array-to-string.c b/gcc-4.8.1/libgo/runtime/go-int-array-to-string.c deleted file mode 100644 index 6cae2fd8c..000000000 --- a/gcc-4.8.1/libgo/runtime/go-int-array-to-string.c +++ /dev/null @@ -1,85 +0,0 @@ -/* go-int-array-to-string.c -- convert an array of ints to a string in Go. - - 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 "go-assert.h" -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -String -__go_int_array_to_string (const void* p, intgo len) -{ - const int32 *ints; - intgo slen; - intgo i; - unsigned char *retdata; - String ret; - unsigned char *s; - - ints = (const int32 *) p; - - slen = 0; - for (i = 0; i < len; ++i) - { - int32 v; - - v = ints[i]; - - if (v < 0 || v > 0x10ffff) - v = 0xfffd; - - if (v <= 0x7f) - slen += 1; - else if (v <= 0x7ff) - slen += 2; - else if (v <= 0xffff) - slen += 3; - else - slen += 4; - } - - retdata = runtime_mallocgc ((uintptr) slen, FlagNoPointers, 1, 0); - ret.str = retdata; - ret.len = slen; - - s = retdata; - for (i = 0; i < len; ++i) - { - int32 v; - - v = ints[i]; - - /* If V is out of range for UTF-8, substitute the replacement - character. */ - if (v < 0 || v > 0x10ffff) - v = 0xfffd; - - if (v <= 0x7f) - *s++ = v; - else if (v <= 0x7ff) - { - *s++ = 0xc0 | ((v >> 6) & 0x1f); - *s++ = 0x80 | (v & 0x3f); - } - else if (v <= 0xffff) - { - *s++ = 0xe0 | ((v >> 12) & 0xf); - *s++ = 0x80 | ((v >> 6) & 0x3f); - *s++ = 0x80 | (v & 0x3f); - } - else - { - *s++ = 0xf0 | ((v >> 18) & 0x7); - *s++ = 0x80 | ((v >> 12) & 0x3f); - *s++ = 0x80 | ((v >> 6) & 0x3f); - *s++ = 0x80 | (v & 0x3f); - } - } - - __go_assert (s - retdata == slen); - - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-int-to-string.c b/gcc-4.8.1/libgo/runtime/go-int-to-string.c deleted file mode 100644 index eb441674b..000000000 --- a/gcc-4.8.1/libgo/runtime/go-int-to-string.c +++ /dev/null @@ -1,69 +0,0 @@ -/* go-int-to-string.c -- convert an integer to a string in Go. - - 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 "arch.h" -#include "malloc.h" - -String -__go_int_to_string (intgo v) -{ - char buf[4]; - int len; - unsigned char *retdata; - String ret; - - /* A negative value is not valid UTF-8; turn it into the replacement - character. */ - if (v < 0) - v = 0xfffd; - - if (v <= 0x7f) - { - buf[0] = v; - len = 1; - } - else if (v <= 0x7ff) - { - buf[0] = 0xc0 + (v >> 6); - buf[1] = 0x80 + (v & 0x3f); - len = 2; - } - else - { - /* If the value is out of range for UTF-8, turn it into the - "replacement character". */ - if (v > 0x10ffff) - v = 0xfffd; - /* If the value is a surrogate pair, which is invalid in UTF-8, - turn it into the replacement character. */ - if (v >= 0xd800 && v < 0xe000) - v = 0xfffd; - - if (v <= 0xffff) - { - buf[0] = 0xe0 + (v >> 12); - buf[1] = 0x80 + ((v >> 6) & 0x3f); - buf[2] = 0x80 + (v & 0x3f); - len = 3; - } - else - { - buf[0] = 0xf0 + (v >> 18); - buf[1] = 0x80 + ((v >> 12) & 0x3f); - buf[2] = 0x80 + ((v >> 6) & 0x3f); - buf[3] = 0x80 + (v & 0x3f); - len = 4; - } - } - - retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0); - __builtin_memcpy (retdata, buf, len); - ret.str = retdata; - ret.len = len; - - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-interface-compare.c b/gcc-4.8.1/libgo/runtime/go-interface-compare.c deleted file mode 100644 index 6374bd2fb..000000000 --- a/gcc-4.8.1/libgo/runtime/go-interface-compare.c +++ /dev/null @@ -1,35 +0,0 @@ -/* go-interface-compare.c -- compare two interface values. - - 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 <stddef.h> - -#include "runtime.h" -#include "go-type.h" -#include "interface.h" - -/* Compare two interface values. Return 0 for equal, not zero for not - equal (return value is like strcmp). */ - -int -__go_interface_compare (struct __go_interface left, - struct __go_interface right) -{ - const struct __go_type_descriptor *left_descriptor; - - if (left.__methods == NULL && right.__methods == NULL) - return 0; - if (left.__methods == NULL || right.__methods == NULL) - return 1; - left_descriptor = left.__methods[0]; - if (!__go_type_descriptors_equal (left_descriptor, right.__methods[0])) - return 1; - if (__go_is_pointer_type (left_descriptor)) - return left.__object == right.__object ? 0 : 1; - if (!left_descriptor->__equalfn (left.__object, right.__object, - left_descriptor->__size)) - return 1; - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-interface-eface-compare.c b/gcc-4.8.1/libgo/runtime/go-interface-eface-compare.c deleted file mode 100644 index bb81ff813..000000000 --- a/gcc-4.8.1/libgo/runtime/go-interface-eface-compare.c +++ /dev/null @@ -1,36 +0,0 @@ -/* go-interface-eface-compare.c -- compare non-empty and empty interface. - - Copyright 2011 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 "go-type.h" -#include "interface.h" - -/* Compare a non-empty interface value with an empty interface value. - Return 0 for equal, not zero for not equal (return value is like - strcmp). */ - -intgo -__go_interface_empty_compare (struct __go_interface left, - struct __go_empty_interface right) -{ - const struct __go_type_descriptor *left_descriptor; - - if (((uintptr_t) right.__type_descriptor & reflectFlags) != 0) - runtime_panicstring ("invalid interface value"); - if (left.__methods == NULL && right.__type_descriptor == NULL) - return 0; - if (left.__methods == NULL || right.__type_descriptor == NULL) - return 1; - left_descriptor = left.__methods[0]; - if (!__go_type_descriptors_equal (left_descriptor, right.__type_descriptor)) - return 1; - if (__go_is_pointer_type (left_descriptor)) - return left.__object == right.__object ? 0 : 1; - if (!left_descriptor->__equalfn (left.__object, right.__object, - left_descriptor->__size)) - return 1; - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-interface-val-compare.c b/gcc-4.8.1/libgo/runtime/go-interface-val-compare.c deleted file mode 100644 index e2dae6a18..000000000 --- a/gcc-4.8.1/libgo/runtime/go-interface-val-compare.c +++ /dev/null @@ -1,33 +0,0 @@ -/* go-interface-val-compare.c -- compare an interface to a value. - - 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 "go-type.h" -#include "interface.h" - -/* Compare two interface values. Return 0 for equal, not zero for not - equal (return value is like strcmp). */ - -intgo -__go_interface_value_compare ( - struct __go_interface left, - const struct __go_type_descriptor *right_descriptor, - const void *val) -{ - const struct __go_type_descriptor *left_descriptor; - - if (left.__methods == NULL) - return 1; - left_descriptor = left.__methods[0]; - if (!__go_type_descriptors_equal (left_descriptor, right_descriptor)) - return 1; - if (__go_is_pointer_type (left_descriptor)) - return left.__object == val ? 0 : 1; - if (!left_descriptor->__equalfn (left.__object, val, - left_descriptor->__size)) - return 1; - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-main.c b/gcc-4.8.1/libgo/runtime/go-main.c deleted file mode 100644 index 97d140583..000000000 --- a/gcc-4.8.1/libgo/runtime/go-main.c +++ /dev/null @@ -1,54 +0,0 @@ -/* go-main.c -- the main function for a Go program. - - 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 "config.h" - -#include <stdlib.h> -#include <time.h> -#include <unistd.h> - -#ifdef HAVE_FPU_CONTROL_H -#include <fpu_control.h> -#endif - -#include "runtime.h" -#include "go-alloc.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -#undef int -#undef char -#undef unsigned - -/* The main function for a Go program. This records the command line - parameters, calls the real main function, and returns a zero status - if the real main function returns. */ - -extern char **environ; - -extern void runtime_main (void); -static void mainstart (void *); - -/* The main function. */ - -int -main (int argc, char **argv) -{ - runtime_check (); - runtime_args (argc, (byte **) argv); - runtime_osinit (); - runtime_schedinit (); - __go_go (mainstart, NULL); - runtime_mstart (runtime_m ()); - abort (); -} - -static void -mainstart (void *arg __attribute__ ((unused))) -{ - runtime_main (); -} diff --git a/gcc-4.8.1/libgo/runtime/go-make-slice.c b/gcc-4.8.1/libgo/runtime/go-make-slice.c deleted file mode 100644 index 591ab37e0..000000000 --- a/gcc-4.8.1/libgo/runtime/go-make-slice.c +++ /dev/null @@ -1,96 +0,0 @@ -/* go-make-slice.c -- make a slice. - - Copyright 2011 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 <stdint.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "go-panic.h" -#include "go-type.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -/* Dummy word to use as base pointer for make([]T, 0). - Since you cannot take the address of such a slice, - you can't tell that they all have the same base pointer. */ -uintptr runtime_zerobase; - -struct __go_open_array -__go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len, - uintptr_t cap) -{ - const struct __go_slice_type* std; - intgo ilen; - intgo icap; - uintptr_t size; - struct __go_open_array ret; - - __go_assert (td->__code == GO_SLICE); - std = (const struct __go_slice_type *) td; - - ilen = (intgo) len; - if (ilen < 0 || (uintptr_t) ilen != len) - runtime_panicstring ("makeslice: len out of range"); - - icap = (intgo) cap; - if (cap < len - || (uintptr_t) icap != cap - || (std->__element_type->__size > 0 - && cap > MaxMem / std->__element_type->__size)) - runtime_panicstring ("makeslice: cap out of range"); - - ret.__count = ilen; - ret.__capacity = icap; - - size = cap * std->__element_type->__size; - - if (size == 0) - ret.__values = &runtime_zerobase; - else if ((std->__element_type->__code & GO_NO_POINTERS) != 0) - ret.__values = runtime_mallocgc (size, FlagNoPointers, 1, 1); - else - { - ret.__values = runtime_mallocgc (size, 0, 1, 1); - - if (UseSpanType) - runtime_settype (ret.__values, - (uintptr) std->__element_type | TypeInfo_Array); - } - - return ret; -} - -struct __go_open_array -__go_make_slice1 (const struct __go_type_descriptor *td, uintptr_t len) -{ - return __go_make_slice2 (td, len, len); -} - -struct __go_open_array -__go_make_slice2_big (const struct __go_type_descriptor *td, uint64_t len, - uint64_t cap) -{ - uintptr_t slen; - uintptr_t scap; - - slen = (uintptr_t) len; - if ((uint64_t) slen != len) - runtime_panicstring ("makeslice: len out of range"); - - scap = (uintptr_t) cap; - if ((uint64_t) scap != cap) - runtime_panicstring ("makeslice: cap out of range"); - - return __go_make_slice2 (td, slen, scap); -} - -struct __go_open_array -__go_make_slice1_big (const struct __go_type_descriptor *td, uint64_t len) -{ - return __go_make_slice2_big (td, len, len); -} diff --git a/gcc-4.8.1/libgo/runtime/go-map-delete.c b/gcc-4.8.1/libgo/runtime/go-map-delete.c deleted file mode 100644 index f8f8907c3..000000000 --- a/gcc-4.8.1/libgo/runtime/go-map-delete.c +++ /dev/null @@ -1,56 +0,0 @@ -/* go-map-delete.c -- delete an entry from a map. - - 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 <stddef.h> -#include <stdlib.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "map.h" - -/* Delete the entry matching KEY from MAP. */ - -void -__go_map_delete (struct __go_map *map, const void *key) -{ - const struct __go_map_descriptor *descriptor; - const struct __go_type_descriptor *key_descriptor; - uintptr_t key_offset; - _Bool (*equalfn) (const void*, const void*, uintptr_t); - size_t key_hash; - size_t key_size; - size_t bucket_index; - void **pentry; - - if (map == NULL) - return; - - descriptor = map->__descriptor; - - key_descriptor = descriptor->__map_descriptor->__key_type; - key_offset = descriptor->__key_offset; - key_size = key_descriptor->__size; - __go_assert (key_size != 0 && key_size != -1UL); - equalfn = key_descriptor->__equalfn; - - key_hash = key_descriptor->__hashfn (key, key_size); - bucket_index = key_hash % map->__bucket_count; - - pentry = map->__buckets + bucket_index; - while (*pentry != NULL) - { - char *entry = (char *) *pentry; - if (equalfn (key, entry + key_offset, key_size)) - { - *pentry = *(void **) entry; - __go_free (entry); - map->__element_count -= 1; - break; - } - pentry = (void **) entry; - } -} diff --git a/gcc-4.8.1/libgo/runtime/go-map-index.c b/gcc-4.8.1/libgo/runtime/go-map-index.c deleted file mode 100644 index a602d2ad0..000000000 --- a/gcc-4.8.1/libgo/runtime/go-map-index.c +++ /dev/null @@ -1,135 +0,0 @@ -/* go-map-index.c -- find or insert an entry in a map. - - 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 <stddef.h> -#include <stdlib.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "map.h" - -/* Rehash MAP to a larger size. */ - -static void -__go_map_rehash (struct __go_map *map) -{ - const struct __go_map_descriptor *descriptor; - const struct __go_type_descriptor *key_descriptor; - uintptr_t key_offset; - size_t key_size; - uintptr_t (*hashfn) (const void *, uintptr_t); - uintptr_t old_bucket_count; - void **old_buckets; - uintptr_t new_bucket_count; - void **new_buckets; - uintptr_t i; - - descriptor = map->__descriptor; - - key_descriptor = descriptor->__map_descriptor->__key_type; - key_offset = descriptor->__key_offset; - key_size = key_descriptor->__size; - hashfn = key_descriptor->__hashfn; - - old_bucket_count = map->__bucket_count; - old_buckets = map->__buckets; - - new_bucket_count = __go_map_next_prime (old_bucket_count * 2); - new_buckets = (void **) __go_alloc (new_bucket_count * sizeof (void *)); - __builtin_memset (new_buckets, 0, new_bucket_count * sizeof (void *)); - - for (i = 0; i < old_bucket_count; ++i) - { - char* entry; - char* next; - - for (entry = old_buckets[i]; entry != NULL; entry = next) - { - size_t key_hash; - size_t new_bucket_index; - - /* We could speed up rehashing at the cost of memory space - by caching the hash code. */ - key_hash = hashfn (entry + key_offset, key_size); - new_bucket_index = key_hash % new_bucket_count; - - next = *(char **) entry; - *(char **) entry = new_buckets[new_bucket_index]; - new_buckets[new_bucket_index] = entry; - } - } - - __go_free (old_buckets); - - map->__bucket_count = new_bucket_count; - map->__buckets = new_buckets; -} - -/* Find KEY in MAP, return a pointer to the value. If KEY is not - present, then if INSERT is false, return NULL, and if INSERT is - true, insert a new value and zero-initialize it before returning a - pointer to it. */ - -void * -__go_map_index (struct __go_map *map, const void *key, _Bool insert) -{ - const struct __go_map_descriptor *descriptor; - const struct __go_type_descriptor *key_descriptor; - uintptr_t key_offset; - _Bool (*equalfn) (const void*, const void*, uintptr_t); - size_t key_hash; - size_t key_size; - size_t bucket_index; - char *entry; - - if (map == NULL) - { - if (insert) - runtime_panicstring ("assignment to entry in nil map"); - return NULL; - } - - descriptor = map->__descriptor; - - key_descriptor = descriptor->__map_descriptor->__key_type; - key_offset = descriptor->__key_offset; - key_size = key_descriptor->__size; - __go_assert (key_size != 0 && key_size != -1UL); - equalfn = key_descriptor->__equalfn; - - key_hash = key_descriptor->__hashfn (key, key_size); - bucket_index = key_hash % map->__bucket_count; - - entry = (char *) map->__buckets[bucket_index]; - while (entry != NULL) - { - if (equalfn (key, entry + key_offset, key_size)) - return entry + descriptor->__val_offset; - entry = *(char **) entry; - } - - if (!insert) - return NULL; - - if (map->__element_count >= map->__bucket_count) - { - __go_map_rehash (map); - bucket_index = key_hash % map->__bucket_count; - } - - entry = (char *) __go_alloc (descriptor->__entry_size); - __builtin_memset (entry, 0, descriptor->__entry_size); - - __builtin_memcpy (entry + key_offset, key, key_size); - - *(char **) entry = map->__buckets[bucket_index]; - map->__buckets[bucket_index] = entry; - - map->__element_count += 1; - - return entry + descriptor->__val_offset; -} diff --git a/gcc-4.8.1/libgo/runtime/go-map-len.c b/gcc-4.8.1/libgo/runtime/go-map-len.c deleted file mode 100644 index 7da10c249..000000000 --- a/gcc-4.8.1/libgo/runtime/go-map-len.c +++ /dev/null @@ -1,25 +0,0 @@ -/* go-map-len.c -- return the length of a map. - - 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 <stddef.h> - -#include "runtime.h" -#include "go-assert.h" -#include "map.h" - -/* Return the length of a map. This could be done inline, of course, - but I'm doing it as a function for now to make it easy to change - the map structure. */ - -intgo -__go_map_len (struct __go_map *map) -{ - if (map == NULL) - return 0; - __go_assert (map->__element_count - == (uintptr_t) (intgo) map->__element_count); - return map->__element_count; -} diff --git a/gcc-4.8.1/libgo/runtime/go-map-range.c b/gcc-4.8.1/libgo/runtime/go-map-range.c deleted file mode 100644 index 5dbb92ccb..000000000 --- a/gcc-4.8.1/libgo/runtime/go-map-range.c +++ /dev/null @@ -1,103 +0,0 @@ -/* go-map-range.c -- implement a range clause over a map. - - Copyright 2009, 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-assert.h" -#include "map.h" - -/* Initialize a range over a map. */ - -void -__go_mapiterinit (const struct __go_map *h, struct __go_hash_iter *it) -{ - it->entry = NULL; - if (h != NULL) - { - it->map = h; - it->next_entry = NULL; - it->bucket = 0; - --it->bucket; - __go_mapiternext(it); - } -} - -/* Move to the next iteration, updating *HITER. */ - -void -__go_mapiternext (struct __go_hash_iter *it) -{ - const void *entry; - - entry = it->next_entry; - if (entry == NULL) - { - const struct __go_map *map; - uintptr_t bucket; - - map = it->map; - bucket = it->bucket; - while (1) - { - ++bucket; - if (bucket >= map->__bucket_count) - { - /* Map iteration is complete. */ - it->entry = NULL; - return; - } - entry = map->__buckets[bucket]; - if (entry != NULL) - break; - } - it->bucket = bucket; - } - it->entry = entry; - it->next_entry = *(const void * const *) entry; -} - -/* Get the key of the current iteration. */ - -void -__go_mapiter1 (struct __go_hash_iter *it, unsigned char *key) -{ - const struct __go_map *map; - const struct __go_map_descriptor *descriptor; - const struct __go_type_descriptor *key_descriptor; - const char *p; - - map = it->map; - descriptor = map->__descriptor; - key_descriptor = descriptor->__map_descriptor->__key_type; - p = it->entry; - __go_assert (p != NULL); - __builtin_memcpy (key, p + descriptor->__key_offset, key_descriptor->__size); -} - -/* Get the key and value of the current iteration. */ - -void -__go_mapiter2 (struct __go_hash_iter *it, unsigned char *key, - unsigned char *val) -{ - const struct __go_map *map; - const struct __go_map_descriptor *descriptor; - const struct __go_map_type *map_descriptor; - const struct __go_type_descriptor *key_descriptor; - const struct __go_type_descriptor *val_descriptor; - const char *p; - - map = it->map; - descriptor = map->__descriptor; - map_descriptor = descriptor->__map_descriptor; - key_descriptor = map_descriptor->__key_type; - val_descriptor = map_descriptor->__val_type; - p = it->entry; - __go_assert (p != NULL); - __builtin_memcpy (key, p + descriptor->__key_offset, - key_descriptor->__size); - __builtin_memcpy (val, p + descriptor->__val_offset, - val_descriptor->__size); -} diff --git a/gcc-4.8.1/libgo/runtime/go-matherr.c b/gcc-4.8.1/libgo/runtime/go-matherr.c deleted file mode 100644 index d620ba08b..000000000 --- a/gcc-4.8.1/libgo/runtime/go-matherr.c +++ /dev/null @@ -1,88 +0,0 @@ -/* go-matherr.c -- a Go version of the matherr function. - - Copyright 2012 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 gccgo version of the math library calls libc functions. On - some systems, such as Solaris, those functions will call matherr on - exceptional conditions. This is a version of matherr appropriate - for Go, one which returns the values that the Go math library - expects. This is fine for pure Go programs. For mixed Go and C - programs this will be problematic if the C programs themselves use - matherr. Normally the C version of matherr will override this, and - the Go code will just have to cope. If this turns out to be too - problematic we can change to run pure Go code in the math library - on systems that use matherr. */ - -#include <math.h> -#include <stdint.h> - -#include "config.h" - -#if defined(HAVE_MATHERR) && defined(HAVE_STRUCT_EXCEPTION) - -#define PI 3.14159265358979323846264338327950288419716939937510582097494459 - -int -matherr (struct exception* e) -{ - const char *n; - - if (e->type != DOMAIN) - return 0; - - n = e->name; - if (__builtin_strcmp (n, "acos") == 0 - || __builtin_strcmp (n, "asin") == 0) - e->retval = __builtin_nan (""); - else if (__builtin_strcmp (n, "atan2") == 0) - { - if (e->arg1 == 0 && e->arg2 == 0) - { - double nz; - - nz = -0.0; - if (__builtin_memcmp (&e->arg2, &nz, sizeof (double)) != 0) - e->retval = e->arg1; - else - e->retval = copysign (PI, e->arg1); - } - else - return 0; - } - else if (__builtin_strcmp (n, "log") == 0 - || __builtin_strcmp (n, "log10") == 0) - e->retval = __builtin_nan (""); - else if (__builtin_strcmp (n, "pow") == 0) - { - if (e->arg1 < 0) - e->retval = __builtin_nan (""); - else if (e->arg1 == 0 && e->arg2 == 0) - e->retval = 1.0; - else if (e->arg1 == 0 && e->arg2 < 0) - { - double i; - - if (modf (e->arg2, &i) == 0 && ((int64_t) i & 1) == 1) - e->retval = copysign (__builtin_inf (), e->arg1); - else - e->retval = __builtin_inf (); - } - else - return 0; - } - else if (__builtin_strcmp (n, "sqrt") == 0) - { - if (e->arg1 < 0) - e->retval = __builtin_nan (""); - else - return 0; - } - else - return 0; - - return 1; -} - -#endif diff --git a/gcc-4.8.1/libgo/runtime/go-memcmp.c b/gcc-4.8.1/libgo/runtime/go-memcmp.c deleted file mode 100644 index 78a356b08..000000000 --- a/gcc-4.8.1/libgo/runtime/go-memcmp.c +++ /dev/null @@ -1,13 +0,0 @@ -/* go-memcmp.c -- the go memory comparison function. - - Copyright 2012 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" - -intgo -__go_memcmp (const void *p1, const void *p2, uintptr len) -{ - return __builtin_memcmp (p1, p2, len); -} diff --git a/gcc-4.8.1/libgo/runtime/go-nanotime.c b/gcc-4.8.1/libgo/runtime/go-nanotime.c deleted file mode 100644 index 7e5e3e098..000000000 --- a/gcc-4.8.1/libgo/runtime/go-nanotime.c +++ /dev/null @@ -1,21 +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. - -// Return current time in nanoseconds. - -#include <sys/time.h> - -#include "runtime.h" - -int64 runtime_nanotime (void) - __attribute__ ((no_split_stack)); - -int64 -runtime_nanotime (void) -{ - struct timeval tv; - - gettimeofday (&tv, NULL); - return (int64) tv.tv_sec * 1000000000 + (int64) tv.tv_usec * 1000; -} diff --git a/gcc-4.8.1/libgo/runtime/go-new-map.c b/gcc-4.8.1/libgo/runtime/go-new-map.c deleted file mode 100644 index c289bc0be..000000000 --- a/gcc-4.8.1/libgo/runtime/go-new-map.c +++ /dev/null @@ -1,142 +0,0 @@ -/* go-new-map.c -- allocate a new map. - - 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 "go-alloc.h" -#include "map.h" - -/* List of prime numbers, copied from libstdc++/src/hashtable.c. */ - -static const unsigned long prime_list[] = /* 256 + 1 or 256 + 48 + 1 */ -{ - 2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul, - 37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul, - 83ul, 89ul, 97ul, 103ul, 109ul, 113ul, 127ul, 137ul, 139ul, 149ul, - 157ul, 167ul, 179ul, 193ul, 199ul, 211ul, 227ul, 241ul, 257ul, - 277ul, 293ul, 313ul, 337ul, 359ul, 383ul, 409ul, 439ul, 467ul, - 503ul, 541ul, 577ul, 619ul, 661ul, 709ul, 761ul, 823ul, 887ul, - 953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, 1493ul, 1613ul, - 1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, 2753ul, 2971ul, - 3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, 5087ul, 5503ul, - 5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, 9497ul, 10273ul, - 11113ul, 12011ul, 12983ul, 14033ul, 15173ul, 16411ul, 17749ul, - 19183ul, 20753ul, 22447ul, 24281ul, 26267ul, 28411ul, 30727ul, - 33223ul, 35933ul, 38873ul, 42043ul, 45481ul, 49201ul, 53201ul, - 57557ul, 62233ul, 67307ul, 72817ul, 78779ul, 85229ul, 92203ul, - 99733ul, 107897ul, 116731ul, 126271ul, 136607ul, 147793ul, - 159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul, - 256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul, - 410857ul, 444487ul, 480881ul, 520241ul, 562841ul, 608903ul, - 658753ul, 712697ul, 771049ul, 834181ul, 902483ul, 976369ul, - 1056323ul, 1142821ul, 1236397ul, 1337629ul, 1447153ul, 1565659ul, - 1693859ul, 1832561ul, 1982627ul, 2144977ul, 2320627ul, 2510653ul, - 2716249ul, 2938679ul, 3179303ul, 3439651ul, 3721303ul, 4026031ul, - 4355707ul, 4712381ul, 5098259ul, 5515729ul, 5967347ul, 6456007ul, - 6984629ul, 7556579ul, 8175383ul, 8844859ul, 9569143ul, 10352717ul, - 11200489ul, 12117689ul, 13109983ul, 14183539ul, 15345007ul, - 16601593ul, 17961079ul, 19431899ul, 21023161ul, 22744717ul, - 24607243ul, 26622317ul, 28802401ul, 31160981ul, 33712729ul, - 36473443ul, 39460231ul, 42691603ul, 46187573ul, 49969847ul, - 54061849ul, 58488943ul, 63278561ul, 68460391ul, 74066549ul, - 80131819ul, 86693767ul, 93793069ul, 101473717ul, 109783337ul, - 118773397ul, 128499677ul, 139022417ul, 150406843ul, 162723577ul, - 176048909ul, 190465427ul, 206062531ul, 222936881ul, 241193053ul, - 260944219ul, 282312799ul, 305431229ul, 330442829ul, 357502601ul, - 386778277ul, 418451333ul, 452718089ul, 489790921ul, 529899637ul, - 573292817ul, 620239453ul, 671030513ul, 725980837ul, 785430967ul, - 849749479ul, 919334987ul, 994618837ul, 1076067617ul, 1164186217ul, - 1259520799ul, 1362662261ul, 1474249943ul, 1594975441ul, 1725587117ul, - 1866894511ul, 2019773507ul, 2185171673ul, 2364114217ul, 2557710269ul, - 2767159799ul, 2993761039ul, 3238918481ul, 3504151727ul, 3791104843ul, - 4101556399ul, 4294967291ul, -#if __SIZEOF_LONG__ >= 8 - 6442450933ul, 8589934583ul, 12884901857ul, 17179869143ul, - 25769803693ul, 34359738337ul, 51539607367ul, 68719476731ul, - 103079215087ul, 137438953447ul, 206158430123ul, 274877906899ul, - 412316860387ul, 549755813881ul, 824633720731ul, 1099511627689ul, - 1649267441579ul, 2199023255531ul, 3298534883309ul, 4398046511093ul, - 6597069766607ul, 8796093022151ul, 13194139533241ul, 17592186044399ul, - 26388279066581ul, 35184372088777ul, 52776558133177ul, 70368744177643ul, - 105553116266399ul, 140737488355213ul, 211106232532861ul, 281474976710597ul, - 562949953421231ul, 1125899906842597ul, 2251799813685119ul, - 4503599627370449ul, 9007199254740881ul, 18014398509481951ul, - 36028797018963913ul, 72057594037927931ul, 144115188075855859ul, - 288230376151711717ul, 576460752303423433ul, - 1152921504606846883ul, 2305843009213693951ul, - 4611686018427387847ul, 9223372036854775783ul, - 18446744073709551557ul -#endif -}; - -/* Return the next number from PRIME_LIST >= N. */ - -uintptr_t -__go_map_next_prime (uintptr_t n) -{ - size_t low; - size_t high; - - low = 0; - high = sizeof prime_list / sizeof prime_list[0]; - while (low < high) - { - size_t mid; - - mid = (low + high) / 2; - - /* Here LOW <= MID < HIGH. */ - - if (prime_list[mid] < n) - low = mid + 1; - else if (prime_list[mid] > n) - high = mid; - else - return n; - } - if (low >= sizeof prime_list / sizeof prime_list[0]) - return n; - return prime_list[low]; -} - -/* Allocate a new map. */ - -struct __go_map * -__go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries) -{ - int32 ientries; - struct __go_map *ret; - - /* The master library limits map entries to int32, so we do too. */ - ientries = (int32) entries; - if (ientries < 0 || (uintptr_t) ientries != entries) - runtime_panicstring ("map size out of range"); - - if (entries == 0) - entries = 5; - else - entries = __go_map_next_prime (entries); - ret = (struct __go_map *) __go_alloc (sizeof (struct __go_map)); - ret->__descriptor = descriptor; - ret->__element_count = 0; - ret->__bucket_count = entries; - ret->__buckets = (void **) __go_alloc (entries * sizeof (void *)); - __builtin_memset (ret->__buckets, 0, entries * sizeof (void *)); - return ret; -} - -/* Allocate a new map when the argument to make is a large type. */ - -struct __go_map * -__go_new_map_big (const struct __go_map_descriptor *descriptor, - uint64_t entries) -{ - uintptr_t sentries; - - sentries = (uintptr_t) entries; - if ((uint64_t) sentries != entries) - runtime_panicstring ("map size out of range"); - return __go_new_map (descriptor, sentries); -} diff --git a/gcc-4.8.1/libgo/runtime/go-new.c b/gcc-4.8.1/libgo/runtime/go-new.c deleted file mode 100644 index b1af5f224..000000000 --- a/gcc-4.8.1/libgo/runtime/go-new.c +++ /dev/null @@ -1,22 +0,0 @@ -/* go-new.c -- the generic go new() function. - - 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 "go-alloc.h" -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -void * -__go_new (uintptr_t size) -{ - return runtime_mallocgc (size, 0, 1, 1); -} - -void * -__go_new_nopointers (uintptr_t size) -{ - return runtime_mallocgc (size, FlagNoPointers, 1, 1); -} diff --git a/gcc-4.8.1/libgo/runtime/go-nosys.c b/gcc-4.8.1/libgo/runtime/go-nosys.c deleted file mode 100644 index 3ab5ea235..000000000 --- a/gcc-4.8.1/libgo/runtime/go-nosys.c +++ /dev/null @@ -1,393 +0,0 @@ -/* go-nosys.c -- functions missing from system. - - Copyright 2012 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -/* This file exists to provide definitions for functions that are - missing from libc, according to the configure script. This permits - the Go syscall package to not worry about whether the functions - exist or not. */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <math.h> -#include <stdint.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <time.h> -#include <unistd.h> - -#ifndef HAVE_OFF64_T -typedef signed int off64_t __attribute__ ((mode (DI))); -#endif - -#ifndef HAVE_LOFF_T -typedef off64_t loff_t; -#endif - -#ifndef HAVE_ACCEPT4 -struct sockaddr; -int -accept4 (int sockfd __attribute__ ((unused)), - struct sockaddr *addr __attribute__ ((unused)), - socklen_t *addrlen __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_EPOLL_CREATE1 -int -epoll_create1 (int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_FACCESSAT -int -faccessat (int fd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - int mode __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_FALLOCATE -int -fallocate (int fd __attribute__ ((unused)), - int mode __attribute__ ((unused)), - off_t offset __attribute__ ((unused)), - off_t len __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_FCHMODAT -int -fchmodat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - mode_t mode __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_FCHOWNAT -int -fchownat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - uid_t owner __attribute__ ((unused)), - gid_t group __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_FUTIMESAT -int -futimesat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - const struct timeval times[2] __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_INOTIFY_ADD_WATCH -int -inotify_add_watch (int fd __attribute__ ((unused)), - const char* pathname __attribute__ ((unused)), - uint32_t mask __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_INOTIFY_INIT -int -inotify_init (void) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_INOTIFY_INIT1 -int -inotify_init1 (int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_INOTIFY_RM_WATCH -int -inotify_rm_watch (int fd __attribute__ ((unused)), - uint32_t wd __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_MKDIRAT -int -mkdirat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - mode_t mode __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_MKNODAT -int -mknodat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - mode_t mode __attribute__ ((unused)), - dev_t dev __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_OPENAT -int -openat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - int oflag __attribute__ ((unused)), - ...) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_PIPE2 -int -pipe2 (int pipefd[2] __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_RENAMEAT -int -renameat (int olddirfd __attribute__ ((unused)), - const char *oldpath __attribute__ ((unused)), - int newdirfd __attribute__ ((unused)), - const char *newpath __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_SPLICE -int -splice (int fd __attribute__ ((unused)), - loff_t *off_in __attribute__ ((unused)), - int fd_out __attribute__ ((unused)), - loff_t *off_out __attribute__ ((unused)), - size_t len __attribute__ ((unused)), - unsigned int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_SYNC_FILE_RANGE -int -sync_file_range (int fd __attribute__ ((unused)), - off64_t offset __attribute__ ((unused)), - off64_t nbytes __attribute__ ((unused)), - unsigned int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_TEE -int -tee (int fd_in __attribute__ ((unused)), - int fd_out __attribute__ ((unused)), - size_t len __attribute__ ((unused)), - unsigned int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_UNLINKAT -int -unlinkat (int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_UNSHARE -int -unshare (int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -#ifndef HAVE_UTIMENSAT -struct timespec; -int -utimensat(int dirfd __attribute__ ((unused)), - const char *pathname __attribute__ ((unused)), - const struct timespec times[2] __attribute__ ((unused)), - int flags __attribute__ ((unused))) -{ - errno = ENOSYS; - return -1; -} -#endif - -/* Long double math functions. These are needed on old i386 systems - that don't have them in libm. The compiler translates calls to - these functions on float64 to call an 80-bit floating point - function instead, because when optimizing that function can be - executed as an x87 instructure. However, when not optimizing, this - translates into a call to the math function. So on systems that - don't provide these functions, we provide a version that just calls - the float64 version. */ - -#ifndef HAVE_COSL -long double -cosl (long double a) -{ - return (long double) cos ((double) a); -} -#endif - -#ifndef HAVE_EXPL -long double -expl (long double a) -{ - return (long double) exp ((double) a); -} -#endif - -#ifndef HAVE_LOGL -long double -logl (long double a) -{ - return (long double) log ((double) a); -} -#endif - -#ifndef HAVE_SINL -long double -sinl (long double a) -{ - return (long double) sin ((double) a); -} -#endif - -#ifndef HAVE_TANL -long double -tanl (long double a) -{ - return (long double) tan ((double) a); -} -#endif - -#ifndef HAVE_ACOSL -long double -acosl (long double a) -{ - return (long double) acos ((double) a); -} -#endif - -#ifndef HAVE_ASINL -long double -asinl (long double a) -{ - return (long double) asin ((double) a); -} -#endif - -#ifndef HAVE_ATANL -long double -atanl (long double a) -{ - return (long double) atan ((double) a); -} -#endif - -#ifndef HAVE_ATAN2L -long double -atan2l (long double a, long double b) -{ - return (long double) atan2 ((double) a, (double) b); -} -#endif - -#ifndef HAVE_EXPM1L -long double -expm1l (long double a) -{ - return (long double) expm1 ((double) a); -} -#endif - -#ifndef HAVE_LDEXPL -long double -ldexpl (long double a, int exp) -{ - return (long double) ldexp ((double) a, exp); -} -#endif - -#ifndef HAVE_LOG10L -long double -log10l (long double a) -{ - return (long double) log10 ((double) a); -} -#endif - -#ifndef HAVE_LOG1PL -long double -log1pl (long double a) -{ - return (long double) log1p ((double) a); -} -#endif diff --git a/gcc-4.8.1/libgo/runtime/go-now.c b/gcc-4.8.1/libgo/runtime/go-now.c deleted file mode 100644 index 73cc1602d..000000000 --- a/gcc-4.8.1/libgo/runtime/go-now.c +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2011 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 <stddef.h> -#include <stdint.h> -#include <sys/time.h> - -#include "runtime.h" - -// Return current time. This is the implementation of time.now(). - -struct time_now_ret -{ - int64_t sec; - int32_t nsec; -}; - -struct time_now_ret now() - __asm__ (GOSYM_PREFIX "time.now") - __attribute__ ((no_split_stack)); - -struct time_now_ret -now() -{ - struct timeval tv; - struct time_now_ret ret; - - gettimeofday (&tv, NULL); - ret.sec = tv.tv_sec; - ret.nsec = tv.tv_usec * 1000; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-panic.c b/gcc-4.8.1/libgo/runtime/go-panic.c deleted file mode 100644 index 530629ca3..000000000 --- a/gcc-4.8.1/libgo/runtime/go-panic.c +++ /dev/null @@ -1,106 +0,0 @@ -/* go-panic.c -- support for the go panic function. - - 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 <stdio.h> -#include <stdlib.h> - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "go-alloc.h" -#include "go-defer.h" -#include "go-panic.h" -#include "interface.h" - -/* Print the panic stack. This is used when there is no recover. */ - -static void -__printpanics (struct __go_panic_stack *p) -{ - if (p->__next != NULL) - { - __printpanics (p->__next); - runtime_printf ("\t"); - } - runtime_printf ("panic: "); - runtime_printany (p->__arg); - if (p->__was_recovered) - runtime_printf (" [recovered]"); - runtime_printf ("\n"); -} - -/* This implements __go_panic which is used for the panic - function. */ - -void -__go_panic (struct __go_empty_interface arg) -{ - G *g; - struct __go_panic_stack *n; - - g = runtime_g (); - - n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack)); - n->__arg = arg; - n->__next = g->panic; - g->panic = n; - - /* Run all the defer functions. */ - - while (1) - { - struct __go_defer_stack *d; - void (*pfn) (void *); - - d = g->defer; - if (d == NULL) - break; - - pfn = d->__pfn; - d->__pfn = NULL; - - if (pfn != NULL) - { - (*pfn) (d->__arg); - - if (n->__was_recovered) - { - /* Some defer function called recover. That means that - we should stop running this panic. */ - - g->panic = n->__next; - __go_free (n); - - /* Now unwind the stack by throwing an exception. The - compiler has arranged to create exception handlers in - each function which uses a defer statement. These - exception handlers will check whether the entry on - the top of the defer stack is from the current - function. If it is, we have unwound the stack far - enough. */ - __go_unwind_stack (); - - /* __go_unwind_stack should not return. */ - abort (); - } - - /* Because we executed that defer function by a panic, and - it did not call recover, we know that we are not - returning from the calling function--we are panicing - through it. */ - *d->__frame = 0; - } - - g->defer = d->__next; - __go_free (d); - } - - /* The panic was not recovered. */ - - runtime_startpanic (); - __printpanics (g->panic); - runtime_dopanic (0); -} diff --git a/gcc-4.8.1/libgo/runtime/go-panic.h b/gcc-4.8.1/libgo/runtime/go-panic.h deleted file mode 100644 index e7031d404..000000000 --- a/gcc-4.8.1/libgo/runtime/go-panic.h +++ /dev/null @@ -1,43 +0,0 @@ -/* go-panic.h -- declare the go panic functions. - - 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. */ - -#ifndef LIBGO_GO_PANIC_H -#define LIBGO_GO_PANIC_H - -#include "interface.h" - -struct String; -struct __go_type_descriptor; -struct __go_defer_stack; - -/* The stack of panic calls. */ - -struct __go_panic_stack -{ - /* The next entry in the stack. */ - struct __go_panic_stack *__next; - - /* The value associated with this panic. */ - struct __go_empty_interface __arg; - - /* Whether this panic has been recovered. */ - _Bool __was_recovered; - - /* Whether this panic was pushed on the stack because of an - exception thrown in some other language. */ - _Bool __is_foreign; -}; - -extern void __go_panic (struct __go_empty_interface) - __attribute__ ((noreturn)); - -extern void __go_print_string (struct String); - -extern struct __go_empty_interface __go_recover (void); - -extern void __go_unwind_stack (void); - -#endif /* !defined(LIBGO_GO_PANIC_H) */ diff --git a/gcc-4.8.1/libgo/runtime/go-print.c b/gcc-4.8.1/libgo/runtime/go-print.c deleted file mode 100644 index 4c520de3c..000000000 --- a/gcc-4.8.1/libgo/runtime/go-print.c +++ /dev/null @@ -1,36 +0,0 @@ -/* go-print.c -- support for the go print statement. - - 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 <math.h> -#include <stdint.h> -#include <stdio.h> - -#include "runtime.h" -#include "array.h" -#include "go-panic.h" -#include "interface.h" - -/* This implements the various little functions which are called by - the predeclared functions print/println/panic/panicln. */ - -void -__go_print_empty_interface (struct __go_empty_interface e) -{ - runtime_printf ("(%p,%p)", e.__type_descriptor, e.__object); -} - -void -__go_print_interface (struct __go_interface i) -{ - runtime_printf ("(%p,%p)", i.__methods, i.__object); -} - -void -__go_print_slice (struct __go_open_array val) -{ - runtime_printf ("[%d/%d]", val.__count, val.__capacity); - runtime_printpointer (val.__values); -} diff --git a/gcc-4.8.1/libgo/runtime/go-recover.c b/gcc-4.8.1/libgo/runtime/go-recover.c deleted file mode 100644 index d6403e00d..000000000 --- a/gcc-4.8.1/libgo/runtime/go-recover.c +++ /dev/null @@ -1,80 +0,0 @@ -/* go-recover.c -- support for the go recover function. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "interface.h" -#include "go-panic.h" -#include "go-defer.h" - -/* This is called by a thunk to see if the real function should be - permitted to recover a panic value. Recovering a value is - permitted if the thunk was called directly by defer. RETADDR is - the return address of the function which is calling - __go_can_recover--this is, the thunk. */ - -_Bool -__go_can_recover (const void* retaddr) -{ - G *g; - struct __go_defer_stack *d; - const char* ret; - const char* dret; - - g = runtime_g (); - - d = g->defer; - if (d == NULL) - return 0; - - /* The panic which this function would recover is the one on the top - of the panic stack. We do not want to recover it if that panic - was on the top of the panic stack when this function was - deferred. */ - if (d->__panic == g->panic) - return 0; - - /* D->__RETADDR is the address of a label immediately following the - call to the thunk. We can recover a panic if that is the same as - the return address of the thunk. We permit a bit of slack in - case there is any code between the function return and the label, - such as an instruction to adjust the stack pointer. */ - - ret = (const char *) retaddr; - -#ifdef __sparc__ - /* On SPARC the address we get, from __builtin_return_address, is - the address of the call instruction. Adjust forward, also - skipping the delayed instruction following the call. */ - ret += 8; -#endif - - dret = (const char *) d->__retaddr; - return ret <= dret && ret + 16 >= dret; -} - -/* This is only called when it is valid for the caller to recover the - value on top of the panic stack, if there is one. */ - -struct __go_empty_interface -__go_recover () -{ - G *g; - struct __go_panic_stack *p; - - g = runtime_g (); - - if (g->panic == NULL || g->panic->__was_recovered) - { - struct __go_empty_interface ret; - - ret.__type_descriptor = NULL; - ret.__object = NULL; - return ret; - } - p = g->panic; - p->__was_recovered = 1; - return p->__arg; -} diff --git a/gcc-4.8.1/libgo/runtime/go-reflect-call.c b/gcc-4.8.1/libgo/runtime/go-reflect-call.c deleted file mode 100644 index a66f92868..000000000 --- a/gcc-4.8.1/libgo/runtime/go-reflect-call.c +++ /dev/null @@ -1,535 +0,0 @@ -/* go-reflect-call.c -- call reflection support for Go. - - 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 <stdio.h> -#include <stdint.h> -#include <stdlib.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "go-type.h" - -#ifdef USE_LIBFFI - -#include "ffi.h" - -/* The functions in this file are only called from reflect_call. As - reflect_call calls a libffi function, which will be compiled - without -fsplit-stack, it will always run with a large stack. */ - -static ffi_type *go_array_to_ffi (const struct __go_array_type *) - __attribute__ ((no_split_stack)); -static ffi_type *go_slice_to_ffi (const struct __go_slice_type *) - __attribute__ ((no_split_stack)); -static ffi_type *go_struct_to_ffi (const struct __go_struct_type *) - __attribute__ ((no_split_stack)); -static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack)); -static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack)); -static ffi_type *go_complex_to_ffi (ffi_type *) - __attribute__ ((no_split_stack, unused)); -static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *) - __attribute__ ((no_split_stack)); -static ffi_type *go_func_return_ffi (const struct __go_func_type *) - __attribute__ ((no_split_stack)); -static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool, - ffi_cif *) - __attribute__ ((no_split_stack)); -static size_t go_results_size (const struct __go_func_type *) - __attribute__ ((no_split_stack)); -static void go_set_results (const struct __go_func_type *, unsigned char *, - void **) - __attribute__ ((no_split_stack)); - -/* Return an ffi_type for a Go array type. The libffi library does - not have any builtin support for passing arrays as values. We work - around this by pretending that the array is a struct. */ - -static ffi_type * -go_array_to_ffi (const struct __go_array_type *descriptor) -{ - ffi_type *ret; - uintptr_t len; - ffi_type *element; - uintptr_t i; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - len = descriptor->__len; - ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *)); - element = go_type_to_ffi (descriptor->__element_type); - for (i = 0; i < len; ++i) - ret->elements[i] = element; - ret->elements[len] = NULL; - return ret; -} - -/* Return an ffi_type for a Go slice type. This describes the - __go_open_array type defines in array.h. */ - -static ffi_type * -go_slice_to_ffi ( - const struct __go_slice_type *descriptor __attribute__ ((unused))) -{ - ffi_type *ret; - ffi_type *ffi_intgo; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *)); - ret->elements[0] = &ffi_type_pointer; - ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; - ret->elements[1] = ffi_intgo; - ret->elements[2] = ffi_intgo; - ret->elements[3] = NULL; - return ret; -} - -/* Return an ffi_type for a Go struct type. */ - -static ffi_type * -go_struct_to_ffi (const struct __go_struct_type *descriptor) -{ - ffi_type *ret; - int field_count; - const struct __go_struct_field *fields; - int i; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - field_count = descriptor->__fields.__count; - fields = (const struct __go_struct_field *) descriptor->__fields.__values; - ret->elements = (ffi_type **) __go_alloc ((field_count + 1) - * sizeof (ffi_type *)); - for (i = 0; i < field_count; ++i) - ret->elements[i] = go_type_to_ffi (fields[i].__type); - ret->elements[field_count] = NULL; - return ret; -} - -/* Return an ffi_type for a Go string type. This describes the String - struct. */ - -static ffi_type * -go_string_to_ffi (void) -{ - ffi_type *ret; - ffi_type *ffi_intgo; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); - ret->elements[0] = &ffi_type_pointer; - ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; - ret->elements[1] = ffi_intgo; - ret->elements[2] = NULL; - return ret; -} - -/* Return an ffi_type for a Go interface type. This describes the - __go_interface and __go_empty_interface structs. */ - -static ffi_type * -go_interface_to_ffi (void) -{ - ffi_type *ret; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); - ret->elements[0] = &ffi_type_pointer; - ret->elements[1] = &ffi_type_pointer; - ret->elements[2] = NULL; - return ret; -} - -/* Return an ffi_type for a Go complex type. */ - -static ffi_type * -go_complex_to_ffi (ffi_type *float_type) -{ - ffi_type *ret; - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); - ret->elements[0] = float_type; - ret->elements[1] = float_type; - ret->elements[2] = NULL; - return ret; -} - -/* Return an ffi_type for a type described by a - __go_type_descriptor. */ - -static ffi_type * -go_type_to_ffi (const struct __go_type_descriptor *descriptor) -{ - switch (descriptor->__code & GO_CODE_MASK) - { - case GO_BOOL: - if (sizeof (_Bool) == 1) - return &ffi_type_uint8; - else if (sizeof (_Bool) == sizeof (int)) - return &ffi_type_uint; - abort (); - case GO_FLOAT32: - if (sizeof (float) == 4) - return &ffi_type_float; - abort (); - case GO_FLOAT64: - if (sizeof (double) == 8) - return &ffi_type_double; - abort (); - case GO_COMPLEX64: -#ifdef __alpha__ - runtime_throw("the libffi library does not support Complex64 type with " - "reflect.Call or runtime.SetFinalizer"); -#else - if (sizeof (float) == 4) - return go_complex_to_ffi (&ffi_type_float); - abort (); -#endif - case GO_COMPLEX128: -#ifdef __alpha__ - runtime_throw("the libffi library does not support Complex128 type with " - "reflect.Call or runtime.SetFinalizer"); -#else - if (sizeof (double) == 8) - return go_complex_to_ffi (&ffi_type_double); - abort (); -#endif - case GO_INT16: - return &ffi_type_sint16; - case GO_INT32: - return &ffi_type_sint32; - case GO_INT64: - return &ffi_type_sint64; - case GO_INT8: - return &ffi_type_sint8; - case GO_INT: - return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64; - case GO_UINT16: - return &ffi_type_uint16; - case GO_UINT32: - return &ffi_type_uint32; - case GO_UINT64: - return &ffi_type_uint64; - case GO_UINT8: - return &ffi_type_uint8; - case GO_UINT: - return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64; - case GO_UINTPTR: - if (sizeof (void *) == 2) - return &ffi_type_uint16; - else if (sizeof (void *) == 4) - return &ffi_type_uint32; - else if (sizeof (void *) == 8) - return &ffi_type_uint64; - abort (); - case GO_ARRAY: - return go_array_to_ffi ((const struct __go_array_type *) descriptor); - case GO_SLICE: - return go_slice_to_ffi ((const struct __go_slice_type *) descriptor); - case GO_STRUCT: - return go_struct_to_ffi ((const struct __go_struct_type *) descriptor); - case GO_STRING: - return go_string_to_ffi (); - case GO_INTERFACE: - return go_interface_to_ffi (); - case GO_CHAN: - case GO_FUNC: - case GO_MAP: - case GO_PTR: - case GO_UNSAFE_POINTER: - /* These types are always pointers, and for FFI purposes nothing - else matters. */ - return &ffi_type_pointer; - default: - abort (); - } -} - -/* Return the return type for a function, given the number of out - parameters and their types. */ - -static ffi_type * -go_func_return_ffi (const struct __go_func_type *func) -{ - int count; - const struct __go_type_descriptor **types; - ffi_type *ret; - int i; - - count = func->__out.__count; - if (count == 0) - return &ffi_type_void; - - types = (const struct __go_type_descriptor **) func->__out.__values; - - if (count == 1) - return go_type_to_ffi (types[0]); - - ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - ret->type = FFI_TYPE_STRUCT; - ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *)); - for (i = 0; i < count; ++i) - ret->elements[i] = go_type_to_ffi (types[i]); - ret->elements[count] = NULL; - return ret; -} - -/* Build an ffi_cif structure for a function described by a - __go_func_type structure. */ - -static void -go_func_to_cif (const struct __go_func_type *func, _Bool is_interface, - _Bool is_method, ffi_cif *cif) -{ - int num_params; - const struct __go_type_descriptor **in_types; - size_t num_args; - ffi_type **args; - int off; - int i; - ffi_type *rettype; - ffi_status status; - - num_params = func->__in.__count; - in_types = ((const struct __go_type_descriptor **) - func->__in.__values); - - num_args = num_params + (is_interface ? 1 : 0); - args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *)); - i = 0; - off = 0; - if (is_interface) - { - args[0] = &ffi_type_pointer; - off = 1; - } - else if (is_method) - { - args[0] = &ffi_type_pointer; - i = 1; - } - for (; i < num_params; ++i) - args[i + off] = go_type_to_ffi (in_types[i]); - - rettype = go_func_return_ffi (func); - - status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args); - __go_assert (status == FFI_OK); -} - -/* Get the total size required for the result parameters of a - function. */ - -static size_t -go_results_size (const struct __go_func_type *func) -{ - int count; - const struct __go_type_descriptor **types; - size_t off; - size_t maxalign; - int i; - - count = func->__out.__count; - if (count == 0) - return 0; - - types = (const struct __go_type_descriptor **) func->__out.__values; - - /* A single integer return value is always promoted to a full - word. */ - if (count == 1) - { - switch (types[0]->__code & GO_CODE_MASK) - { - case GO_BOOL: - case GO_INT8: - case GO_INT16: - case GO_INT32: - case GO_UINT8: - case GO_UINT16: - case GO_UINT32: - case GO_INT: - case GO_UINT: - return sizeof (ffi_arg); - - default: - break; - } - } - - off = 0; - maxalign = 0; - for (i = 0; i < count; ++i) - { - size_t align; - - align = types[i]->__field_align; - if (align > maxalign) - maxalign = align; - off = (off + align - 1) & ~ (align - 1); - off += types[i]->__size; - } - - off = (off + maxalign - 1) & ~ (maxalign - 1); - - return off; -} - -/* Copy the results of calling a function via FFI from CALL_RESULT - into the addresses in RESULTS. */ - -static void -go_set_results (const struct __go_func_type *func, unsigned char *call_result, - void **results) -{ - int count; - const struct __go_type_descriptor **types; - size_t off; - int i; - - count = func->__out.__count; - if (count == 0) - return; - - types = (const struct __go_type_descriptor **) func->__out.__values; - - /* A single integer return value is always promoted to a full - word. */ - if (count == 1) - { - switch (types[0]->__code & GO_CODE_MASK) - { - case GO_BOOL: - case GO_INT8: - case GO_INT16: - case GO_INT32: - case GO_UINT8: - case GO_UINT16: - case GO_UINT32: - case GO_INT: - case GO_UINT: - { - union - { - unsigned char buf[sizeof (ffi_arg)]; - ffi_arg v; - } u; - ffi_arg v; - - __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg)); - v = u.v; - - switch (types[0]->__size) - { - case 1: - { - uint8_t b; - - b = (uint8_t) v; - __builtin_memcpy (results[0], &b, 1); - } - break; - - case 2: - { - uint16_t s; - - s = (uint16_t) v; - __builtin_memcpy (results[0], &s, 2); - } - break; - - case 4: - { - uint32_t w; - - w = (uint32_t) v; - __builtin_memcpy (results[0], &w, 4); - } - break; - - case 8: - { - uint64_t d; - - d = (uint64_t) v; - __builtin_memcpy (results[0], &d, 8); - } - break; - - default: - abort (); - } - } - return; - - default: - break; - } - } - - off = 0; - for (i = 0; i < count; ++i) - { - size_t align; - size_t size; - - align = types[i]->__field_align; - size = types[i]->__size; - off = (off + align - 1) & ~ (align - 1); - __builtin_memcpy (results[i], call_result + off, size); - off += size; - } -} - -/* Call a function. The type of the function is FUNC_TYPE, and the - address is FUNC_ADDR. PARAMS is an array of parameter addresses. - RESULTS is an array of result addresses. */ - -void -reflect_call (const struct __go_func_type *func_type, const void *func_addr, - _Bool is_interface, _Bool is_method, void **params, - void **results) -{ - ffi_cif cif; - unsigned char *call_result; - - __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC); - go_func_to_cif (func_type, is_interface, is_method, &cif); - - call_result = (unsigned char *) malloc (go_results_size (func_type)); - - ffi_call (&cif, func_addr, call_result, params); - - /* Some day we may need to free result values if RESULTS is - NULL. */ - if (results != NULL) - go_set_results (func_type, call_result, results); - - free (call_result); -} - -#else /* !defined(USE_LIBFFI) */ - -void -reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)), - const void *func_addr __attribute__ ((unused)), - _Bool is_interface __attribute__ ((unused)), - _Bool is_method __attribute__ ((unused)), - void **params __attribute__ ((unused)), - void **results __attribute__ ((unused))) -{ - /* Without FFI there is nothing we can do. */ - runtime_throw("libgo built without FFI does not support " - "reflect.Call or runtime.SetFinalizer"); -} - -#endif /* !defined(USE_LIBFFI) */ diff --git a/gcc-4.8.1/libgo/runtime/go-reflect-map.c b/gcc-4.8.1/libgo/runtime/go-reflect-map.c deleted file mode 100644 index 369753749..000000000 --- a/gcc-4.8.1/libgo/runtime/go-reflect-map.c +++ /dev/null @@ -1,240 +0,0 @@ -/* go-reflect-map.c -- map reflection support for Go. - - Copyright 2009, 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <stdlib.h> -#include <stdint.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "go-type.h" -#include "map.h" - -/* This file implements support for reflection on maps. These - functions are called from reflect/value.go. */ - -struct mapaccess_ret -{ - uintptr_t val; - _Bool pres; -}; - -extern struct mapaccess_ret mapaccess (struct __go_map_type *, uintptr_t, - uintptr_t) - __asm__ (GOSYM_PREFIX "reflect.mapaccess"); - -struct mapaccess_ret -mapaccess (struct __go_map_type *mt, uintptr_t m, uintptr_t key_i) -{ - struct __go_map *map = (struct __go_map *) m; - void *key; - const struct __go_type_descriptor *key_descriptor; - void *p; - const struct __go_type_descriptor *val_descriptor; - struct mapaccess_ret ret; - void *val; - void *pv; - - __go_assert (mt->__common.__code == GO_MAP); - - key_descriptor = mt->__key_type; - if (__go_is_pointer_type (key_descriptor)) - key = &key_i; - else - key = (void *) key_i; - - if (map == NULL) - p = NULL; - else - p = __go_map_index (map, key, 0); - - val_descriptor = mt->__val_type; - if (__go_is_pointer_type (val_descriptor)) - { - val = NULL; - pv = &val; - } - else - { - val = __go_alloc (val_descriptor->__size); - pv = val; - } - - if (p == NULL) - ret.pres = 0; - else - { - __builtin_memcpy (pv, p, val_descriptor->__size); - ret.pres = 1; - } - - ret.val = (uintptr_t) val; - return ret; -} - -extern void mapassign (struct __go_map_type *, uintptr_t, uintptr_t, - uintptr_t, _Bool) - __asm__ (GOSYM_PREFIX "reflect.mapassign"); - -void -mapassign (struct __go_map_type *mt, uintptr_t m, uintptr_t key_i, - uintptr_t val_i, _Bool pres) -{ - struct __go_map *map = (struct __go_map *) m; - const struct __go_type_descriptor *key_descriptor; - void *key; - - __go_assert (mt->__common.__code == GO_MAP); - - if (map == NULL) - runtime_panicstring ("assignment to entry in nil map"); - - key_descriptor = mt->__key_type; - if (__go_is_pointer_type (key_descriptor)) - key = &key_i; - else - key = (void *) key_i; - - if (!pres) - __go_map_delete (map, key); - else - { - void *p; - const struct __go_type_descriptor *val_descriptor; - void *pv; - - p = __go_map_index (map, key, 1); - - val_descriptor = mt->__val_type; - if (__go_is_pointer_type (val_descriptor)) - pv = &val_i; - else - pv = (void *) val_i; - __builtin_memcpy (p, pv, val_descriptor->__size); - } -} - -extern int32_t maplen (uintptr_t) - __asm__ (GOSYM_PREFIX "reflect.maplen"); - -int32_t -maplen (uintptr_t m) -{ - struct __go_map *map = (struct __go_map *) m; - - if (map == NULL) - return 0; - return (int32_t) map->__element_count; -} - -extern unsigned char *mapiterinit (struct __go_map_type *, uintptr_t) - __asm__ (GOSYM_PREFIX "reflect.mapiterinit"); - -unsigned char * -mapiterinit (struct __go_map_type *mt, uintptr_t m) -{ - struct __go_hash_iter *it; - - __go_assert (mt->__common.__code == GO_MAP); - it = __go_alloc (sizeof (struct __go_hash_iter)); - __go_mapiterinit ((struct __go_map *) m, it); - return (unsigned char *) it; -} - -extern void mapiternext (unsigned char *) - __asm__ (GOSYM_PREFIX "reflect.mapiternext"); - -void -mapiternext (unsigned char *it) -{ - __go_mapiternext ((struct __go_hash_iter *) it); -} - -struct mapiterkey_ret -{ - uintptr_t key; - _Bool ok; -}; - -extern struct mapiterkey_ret mapiterkey (unsigned char *) - __asm__ (GOSYM_PREFIX "reflect.mapiterkey"); - -struct mapiterkey_ret -mapiterkey (unsigned char *ita) -{ - struct __go_hash_iter *it = (struct __go_hash_iter *) ita; - struct mapiterkey_ret ret; - - if (it->entry == NULL) - { - ret.key = 0; - ret.ok = 0; - } - else - { - const struct __go_type_descriptor *key_descriptor; - void *key; - void *pk; - - key_descriptor = it->map->__descriptor->__map_descriptor->__key_type; - if (__go_is_pointer_type (key_descriptor)) - { - key = NULL; - pk = &key; - } - else - { - key = __go_alloc (key_descriptor->__size); - pk = key; - } - - __go_mapiter1 (it, pk); - - ret.key = (uintptr_t) key; - ret.ok = 1; - } - - return ret; -} - -/* Make a new map. We have to build our own map descriptor. */ - -extern uintptr_t makemap (const struct __go_map_type *) - __asm__ (GOSYM_PREFIX "reflect.makemap"); - -uintptr_t -makemap (const struct __go_map_type *t) -{ - struct __go_map_descriptor *md; - unsigned int o; - const struct __go_type_descriptor *kt; - const struct __go_type_descriptor *vt; - struct __go_map* map; - void *ret; - - /* FIXME: Reference count. */ - md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md)); - md->__map_descriptor = t; - o = sizeof (void *); - kt = t->__key_type; - o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1); - md->__key_offset = o; - o += kt->__size; - vt = t->__val_type; - o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1); - md->__val_offset = o; - o += vt->__size; - o = (o + sizeof (void *) - 1) & ~ (sizeof (void *) - 1); - o = (o + kt->__field_align - 1) & ~ (kt->__field_align - 1); - o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1); - md->__entry_size = o; - - map = __go_new_map (md, 0); - - ret = __go_alloc (sizeof (void *)); - __builtin_memcpy (ret, &map, sizeof (void *)); - return (uintptr_t) ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-rune.c b/gcc-4.8.1/libgo/runtime/go-rune.c deleted file mode 100644 index 4c65e2151..000000000 --- a/gcc-4.8.1/libgo/runtime/go-rune.c +++ /dev/null @@ -1,97 +0,0 @@ -/* go-rune.c -- rune functions for Go. - - Copyright 2009, 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <stddef.h> - -#include "runtime.h" -#include "go-string.h" - -/* Get a character from the UTF-8 string STR, of length LEN. Store - the Unicode character, if any, in *RUNE. Return the number of - characters used from STR. */ - -int -__go_get_rune (const unsigned char *str, size_t len, int32 *rune) -{ - int c, c1, c2, c3, l; - - /* Default to the "replacement character". */ - *rune = 0xfffd; - - if (len <= 0) - return 1; - - c = *str; - if (c <= 0x7f) - { - *rune = c; - return 1; - } - - if (len <= 1) - return 1; - - c1 = str[1]; - if ((c & 0xe0) == 0xc0 - && (c1 & 0xc0) == 0x80) - { - l = (((c & 0x1f) << 6) + (c1 & 0x3f)); - if (l <= 0x7f) - return 1; - *rune = l; - return 2; - } - - if (len <= 2) - return 1; - - c2 = str[2]; - if ((c & 0xf0) == 0xe0 - && (c1 & 0xc0) == 0x80 - && (c2 & 0xc0) == 0x80) - { - l = (((c & 0xf) << 12) - + ((c1 & 0x3f) << 6) - + (c2 & 0x3f)); - - if (l <= 0x7ff) - return 1; - - if (l >= 0xd800 && l < 0xe000) - { - /* Invalid surrogate half; return replace character. */ - return 1; - } - - *rune = l; - - return 3; - } - - if (len <= 3) - return 1; - - c3 = str[3]; - if ((c & 0xf8) == 0xf0 - && (c1 & 0xc0) == 0x80 - && (c2 & 0xc0) == 0x80 - && (c3 & 0xc0) == 0x80) - { - l = (((c & 0x7) << 18) - + ((c1 & 0x3f) << 12) - + ((c2 & 0x3f) << 6) - + (c3 & 0x3f)); - - if (l <= 0xffff || l > 0x10ffff) - return 1; - - *rune = l; - return 4; - } - - /* Invalid encoding. Return 1 so that we advance. */ - return 1; -} diff --git a/gcc-4.8.1/libgo/runtime/go-runtime-error.c b/gcc-4.8.1/libgo/runtime/go-runtime-error.c deleted file mode 100644 index f5ab4f919..000000000 --- a/gcc-4.8.1/libgo/runtime/go-runtime-error.c +++ /dev/null @@ -1,90 +0,0 @@ -/* go-runtime-error.c -- Go runtime error. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" - -/* The compiler generates calls to this function. This enum values - are known to the compiler and used by compiled code. Any change - here must be reflected in the compiler. */ - -enum -{ - /* Slice index out of bounds: negative or larger than the length of - the slice. */ - SLICE_INDEX_OUT_OF_BOUNDS = 0, - - /* Array index out of bounds. */ - ARRAY_INDEX_OUT_OF_BOUNDS = 1, - - /* String index out of bounds. */ - STRING_INDEX_OUT_OF_BOUNDS = 2, - - /* Slice slice out of bounds: negative or larger than the length of - the slice or high bound less than low bound. */ - SLICE_SLICE_OUT_OF_BOUNDS = 3, - - /* Array slice out of bounds. */ - ARRAY_SLICE_OUT_OF_BOUNDS = 4, - - /* String slice out of bounds. */ - STRING_SLICE_OUT_OF_BOUNDS = 5, - - /* Dereference of nil pointer. This is used when there is a - dereference of a pointer to a very large struct or array, to - ensure that a gigantic array is not used a proxy to access random - memory locations. */ - NIL_DEREFERENCE = 6, - - /* Slice length or capacity out of bounds in make: negative or - overflow or length greater than capacity. */ - MAKE_SLICE_OUT_OF_BOUNDS = 7, - - /* Map capacity out of bounds in make: negative or overflow. */ - MAKE_MAP_OUT_OF_BOUNDS = 8, - - /* Channel capacity out of bounds in make: negative or overflow. */ - MAKE_CHAN_OUT_OF_BOUNDS = 9, - - /* Integer division by zero. */ - DIVISION_BY_ZERO = 10 -}; - -extern void __go_runtime_error () __attribute__ ((noreturn)); - -void -__go_runtime_error (int32 i) -{ - switch (i) - { - case SLICE_INDEX_OUT_OF_BOUNDS: - case ARRAY_INDEX_OUT_OF_BOUNDS: - case STRING_INDEX_OUT_OF_BOUNDS: - runtime_panicstring ("index out of range"); - - case SLICE_SLICE_OUT_OF_BOUNDS: - case ARRAY_SLICE_OUT_OF_BOUNDS: - case STRING_SLICE_OUT_OF_BOUNDS: - runtime_panicstring ("slice bounds out of range"); - - case NIL_DEREFERENCE: - runtime_panicstring ("nil pointer dereference"); - - case MAKE_SLICE_OUT_OF_BOUNDS: - runtime_panicstring ("make slice len or cap out of range"); - - case MAKE_MAP_OUT_OF_BOUNDS: - runtime_panicstring ("make map len out of range"); - - case MAKE_CHAN_OUT_OF_BOUNDS: - runtime_panicstring ("make chan len out of range"); - - case DIVISION_BY_ZERO: - runtime_panicstring ("integer divide by zero"); - - default: - runtime_panicstring ("unknown runtime error"); - } -} diff --git a/gcc-4.8.1/libgo/runtime/go-setenv.c b/gcc-4.8.1/libgo/runtime/go-setenv.c deleted file mode 100644 index 6c7378c9e..000000000 --- a/gcc-4.8.1/libgo/runtime/go-setenv.c +++ /dev/null @@ -1,70 +0,0 @@ -/* go-setenv.c -- set the C environment from Go. - - Copyright 2011 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 "config.h" - -#include <stddef.h> -#include <stdlib.h> - -#include "go-alloc.h" -#include "runtime.h" - -/* Set the C environment from Go. This is called by syscall.Setenv. */ - -void setenv_c (String, String) __asm__ (GOSYM_PREFIX "syscall.setenv_c"); - -void -setenv_c (String k, String v) -{ - const byte *ks; - unsigned char *kn; - const byte *vs; - unsigned char *vn; - - ks = k.str; - if (ks == NULL) - ks = (const byte *) ""; - kn = NULL; - - vs = v.str; - if (vs == NULL) - vs = (const byte *) ""; - vn = NULL; - -#ifdef HAVE_SETENV - - if (ks != NULL && ks[k.len] != 0) - { - kn = __go_alloc (k.len + 1); - __builtin_memcpy (kn, ks, k.len); - ks = kn; - } - - if (vs != NULL && vs[v.len] != 0) - { - vn = __go_alloc (v.len + 1); - __builtin_memcpy (vn, vs, v.len); - vs = vn; - } - - setenv ((const char *) ks, (const char *) vs, 1); - -#else /* !defined(HAVE_SETENV) */ - - kn = __go_alloc (k.len + v.len + 2); - __builtin_memcpy (kn, ks, k.len); - kn[k.len] = '='; - __builtin_memcpy (kn + k.len + 1, vs, v.len); - kn[k.len + v.len + 1] = '\0'; - putenv ((char *) kn); - -#endif /* !defined(HAVE_SETENV) */ - - if (kn != NULL) - __go_free (kn); - if (vn != NULL) - __go_free (vn); -} diff --git a/gcc-4.8.1/libgo/runtime/go-signal.c b/gcc-4.8.1/libgo/runtime/go-signal.c deleted file mode 100644 index 1965e0588..000000000 --- a/gcc-4.8.1/libgo/runtime/go-signal.c +++ /dev/null @@ -1,485 +0,0 @@ -/* go-signal.c -- signal handling for Go. - - 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 <signal.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/time.h> - -#include "runtime.h" -#include "go-assert.h" -#include "go-panic.h" - -#ifndef SA_RESTART - #define SA_RESTART 0 -#endif - -#ifdef USING_SPLIT_STACK - -extern void __splitstack_getcontext(void *context[10]); - -extern void __splitstack_setcontext(void *context[10]); - -#endif - -#define N SigNotify -#define K SigKill -#define T SigThrow -#define P SigPanic -#define D SigDefault - -/* Signal actions. This collects the sigtab tables for several - different targets from the master library. SIGKILL, SIGCONT, and - SIGSTOP are not listed, as we don't want to set signal handlers for - them. */ - -SigTab runtime_sigtab[] = { -#ifdef SIGHUP - { SIGHUP, N + K }, -#endif -#ifdef SIGINT - { SIGINT, N + K }, -#endif -#ifdef SIGQUIT - { SIGQUIT, N + T }, -#endif -#ifdef SIGILL - { SIGILL, T }, -#endif -#ifdef SIGTRAP - { SIGTRAP, T }, -#endif -#ifdef SIGABRT - { SIGABRT, N + T }, -#endif -#ifdef SIGBUS - { SIGBUS, P }, -#endif -#ifdef SIGFPE - { SIGFPE, P }, -#endif -#ifdef SIGUSR1 - { SIGUSR1, N }, -#endif -#ifdef SIGSEGV - { SIGSEGV, P }, -#endif -#ifdef SIGUSR2 - { SIGUSR2, N }, -#endif -#ifdef SIGPIPE - { SIGPIPE, N }, -#endif -#ifdef SIGALRM - { SIGALRM, N }, -#endif -#ifdef SIGTERM - { SIGTERM, N + K }, -#endif -#ifdef SIGSTKFLT - { SIGSTKFLT, T }, -#endif -#ifdef SIGCHLD - { SIGCHLD, N }, -#endif -#ifdef SIGTSTP - { SIGTSTP, N + D }, -#endif -#ifdef SIGTTIN - { SIGTTIN, N + D }, -#endif -#ifdef SIGTTOU - { SIGTTOU, N + D }, -#endif -#ifdef SIGURG - { SIGURG, N }, -#endif -#ifdef SIGXCPU - { SIGXCPU, N }, -#endif -#ifdef SIGXFSZ - { SIGXFSZ, N }, -#endif -#ifdef SIGVTALRM - { SIGVTALRM, N }, -#endif -#ifdef SIGPROF - { SIGPROF, N }, -#endif -#ifdef SIGWINCH - { SIGWINCH, N }, -#endif -#ifdef SIGIO - { SIGIO, N }, -#endif -#ifdef SIGPWR - { SIGPWR, N }, -#endif -#ifdef SIGSYS - { SIGSYS, N }, -#endif -#ifdef SIGEMT - { SIGEMT, T }, -#endif -#ifdef SIGINFO - { SIGINFO, N }, -#endif -#ifdef SIGTHR - { SIGTHR, N }, -#endif - { -1, 0 } -}; -#undef N -#undef K -#undef T -#undef P -#undef D - - -static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n"; - -static void -runtime_badsignal(int32 sig) -{ - // Avoid -D_FORTIFY_SOURCE problems. - int rv __attribute__((unused)); - - if (sig == SIGPROF) { - return; // Ignore SIGPROFs intended for a non-Go thread. - } - rv = runtime_write(2, badsignal, sizeof badsignal - 1); - runtime_exit(1); -} - -/* Handle a signal, for cases where we don't panic. We can split the - stack here. */ - -static void -sig_handler (int sig) -{ - int i; - - if (runtime_m () == NULL) - { - runtime_badsignal (sig); - return; - } - -#ifdef SIGPROF - if (sig == SIGPROF) - { - runtime_sigprof (); - return; - } -#endif - - for (i = 0; runtime_sigtab[i].sig != -1; ++i) - { - SigTab *t; - - t = &runtime_sigtab[i]; - - if (t->sig != sig) - continue; - - if ((t->flags & SigNotify) != 0) - { - if (__go_sigsend (sig)) - return; - } - if ((t->flags & SigKill) != 0) - runtime_exit (2); - if ((t->flags & SigThrow) == 0) - return; - - runtime_startpanic (); - - { - const char *name = NULL; - -#ifdef HAVE_STRSIGNAL - name = strsignal (sig); -#endif - - if (name == NULL) - runtime_printf ("Signal %d\n", sig); - else - runtime_printf ("%s\n", name); - } - - runtime_printf ("\n"); - - if (runtime_gotraceback ()) - { - G *g; - - g = runtime_g (); - runtime_traceback (g); - runtime_tracebackothers (g); - - /* The gc library calls runtime_dumpregs here, and provides - a function that prints the registers saved in context in - a readable form. */ - } - - runtime_exit (2); - } - - __builtin_unreachable (); -} - -/* The start of handling a signal which panics. */ - -static void -sig_panic_leadin (int sig) -{ - int i; - sigset_t clear; - - if (runtime_m ()->mallocing) - { - runtime_printf ("caught signal while mallocing: %d\n", sig); - runtime_throw ("caught signal while mallocing"); - } - - /* The signal handler blocked signals; unblock them. */ - i = sigfillset (&clear); - __go_assert (i == 0); - i = sigprocmask (SIG_UNBLOCK, &clear, NULL); - __go_assert (i == 0); -} - -#ifdef SA_SIGINFO - -/* Signal dispatch for signals which panic, on systems which support - SA_SIGINFO. This is called on the thread stack, and as such it is - permitted to split the stack. */ - -static void -sig_panic_info_handler (int sig, siginfo_t *info, - void *context __attribute__ ((unused))) -{ - G *g; - - g = runtime_g (); - if (g == NULL || info->si_code == SI_USER) - { - sig_handler (sig); - return; - } - - g->sig = sig; - g->sigcode0 = info->si_code; - g->sigcode1 = (uintptr_t) info->si_addr; - - /* It would be nice to set g->sigpc here as the gc library does, but - I don't know how to get it portably. */ - - sig_panic_leadin (sig); - - switch (sig) - { -#ifdef SIGBUS - case SIGBUS: - if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000) - runtime_panicstring ("invalid memory address or " - "nil pointer dereference"); - runtime_printf ("unexpected fault address %p\n", info->si_addr); - runtime_throw ("fault"); -#endif - -#ifdef SIGSEGV - case SIGSEGV: - if ((info->si_code == 0 - || info->si_code == SEGV_MAPERR - || info->si_code == SEGV_ACCERR) - && (uintptr_t) info->si_addr < 0x1000) - runtime_panicstring ("invalid memory address or " - "nil pointer dereference"); - runtime_printf ("unexpected fault address %p\n", info->si_addr); - runtime_throw ("fault"); -#endif - -#ifdef SIGFPE - case SIGFPE: - switch (info->si_code) - { - case FPE_INTDIV: - runtime_panicstring ("integer divide by zero"); - case FPE_INTOVF: - runtime_panicstring ("integer overflow"); - } - runtime_panicstring ("floating point error"); -#endif - } - - /* All signals with SigPanic should be in cases above, and this - handler should only be invoked for those signals. */ - __builtin_unreachable (); -} - -#else /* !defined (SA_SIGINFO) */ - -static void -sig_panic_handler (int sig) -{ - G *g; - - g = runtime_g (); - if (g == NULL) - { - sig_handler (sig); - return; - } - - g->sig = sig; - g->sigcode0 = 0; - g->sigcode1 = 0; - - sig_panic_leadin (sig); - - switch (sig) - { -#ifdef SIGBUS - case SIGBUS: - runtime_panicstring ("invalid memory address or " - "nil pointer dereference"); -#endif - -#ifdef SIGSEGV - case SIGSEGV: - runtime_panicstring ("invalid memory address or " - "nil pointer dereference"); -#endif - -#ifdef SIGFPE - case SIGFPE: - runtime_panicstring ("integer divide by zero or floating point error"); -#endif - } - - /* All signals with SigPanic should be in cases above, and this - handler should only be invoked for those signals. */ - __builtin_unreachable (); -} - -#endif /* !defined (SA_SIGINFO) */ - -/* A signal handler used for signals which are not going to panic. - This is called on the alternate signal stack so it may not split - the stack. */ - -static void -sig_tramp (int) __attribute__ ((no_split_stack)); - -static void -sig_tramp (int sig) -{ - G *gp; - M *mp; - - /* We are now running on the stack registered via sigaltstack. - (Actually there is a small span of time between runtime_siginit - and sigaltstack when the program starts.) */ - gp = runtime_g (); - mp = runtime_m (); - - if (gp != NULL) - { -#ifdef USING_SPLIT_STACK - __splitstack_getcontext (&gp->stack_context[0]); -#endif - } - - if (gp != NULL && mp->gsignal != NULL) - { - /* We are running on the signal stack. Set the split stack - context so that the stack guards are checked correctly. */ -#ifdef USING_SPLIT_STACK - __splitstack_setcontext (&mp->gsignal->stack_context[0]); -#endif - } - - sig_handler (sig); - - /* We are going to return back to the signal trampoline and then to - whatever we were doing before we got the signal. Restore the - split stack context so that stack guards are checked - correctly. */ - - if (gp != NULL) - { -#ifdef USING_SPLIT_STACK - __splitstack_setcontext (&gp->stack_context[0]); -#endif - } -} - -void -runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart) -{ - struct sigaction sa; - int r; - SigTab *t; - - memset (&sa, 0, sizeof sa); - - r = sigfillset (&sa.sa_mask); - __go_assert (r == 0); - - t = &runtime_sigtab[i]; - - if ((t->flags & SigPanic) == 0) - { - sa.sa_flags = SA_ONSTACK; - sa.sa_handler = sig_tramp; - } - else - { -#ifdef SA_SIGINFO - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = sig_panic_info_handler; -#else - sa.sa_flags = 0; - sa.sa_handler = sig_panic_handler; -#endif - } - - if (restart) - sa.sa_flags |= SA_RESTART; - - if (sigaction (t->sig, &sa, NULL) != 0) - __go_assert (0); -} - -/* Used by the os package to raise SIGPIPE. */ - -void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe"); - -void -os_sigpipe (void) -{ - struct sigaction sa; - int i; - - memset (&sa, 0, sizeof sa); - - sa.sa_handler = SIG_DFL; - - i = sigemptyset (&sa.sa_mask); - __go_assert (i == 0); - - if (sigaction (SIGPIPE, &sa, NULL) != 0) - abort (); - - raise (SIGPIPE); -} - -void -runtime_setprof(bool on) -{ - USED(on); -} diff --git a/gcc-4.8.1/libgo/runtime/go-strcmp.c b/gcc-4.8.1/libgo/runtime/go-strcmp.c deleted file mode 100644 index bcc270bf8..000000000 --- a/gcc-4.8.1/libgo/runtime/go-strcmp.c +++ /dev/null @@ -1,25 +0,0 @@ -/* go-strcmp.c -- the go string comparison function. - - 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" - -intgo -__go_strcmp(String s1, String s2) -{ - int i; - - i = __builtin_memcmp(s1.str, s2.str, - (s1.len < s2.len ? s1.len : s2.len)); - if (i != 0) - return i; - - if (s1.len < s2.len) - return -1; - else if (s1.len > s2.len) - return 1; - else - return 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-string-to-byte-array.c b/gcc-4.8.1/libgo/runtime/go-string-to-byte-array.c deleted file mode 100644 index 75fac1dbf..000000000 --- a/gcc-4.8.1/libgo/runtime/go-string-to-byte-array.c +++ /dev/null @@ -1,24 +0,0 @@ -/* go-string-to-byte-array.c -- convert a string to an array of bytes in Go. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -struct __go_open_array -__go_string_to_byte_array (String str) -{ - unsigned char *data; - struct __go_open_array ret; - - data = (unsigned char *) runtime_mallocgc (str.len, FlagNoPointers, 1, 0); - __builtin_memcpy (data, str.str, str.len); - ret.__values = (void *) data; - ret.__count = str.len; - ret.__capacity = str.len; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-string-to-int-array.c b/gcc-4.8.1/libgo/runtime/go-string-to-int-array.c deleted file mode 100644 index 16970bdd0..000000000 --- a/gcc-4.8.1/libgo/runtime/go-string-to-int-array.c +++ /dev/null @@ -1,51 +0,0 @@ -/* go-string-to-int-array.c -- convert a string to an array of ints in Go. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "go-alloc.h" -#include "go-string.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -struct __go_open_array -__go_string_to_int_array (String str) -{ - size_t c; - const unsigned char *p; - const unsigned char *pend; - uint32_t *data; - uint32_t *pd; - struct __go_open_array ret; - - c = 0; - p = str.str; - pend = p + str.len; - while (p < pend) - { - int rune; - - ++c; - p += __go_get_rune (p, pend - p, &rune); - } - - data = (uint32_t *) runtime_mallocgc (c * sizeof (uint32_t), FlagNoPointers, - 1, 0); - p = str.str; - pd = data; - while (p < pend) - { - int rune; - - p += __go_get_rune (p, pend - p, &rune); - *pd++ = rune; - } - - ret.__values = (void *) data; - ret.__count = c; - ret.__capacity = c; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-string.h b/gcc-4.8.1/libgo/runtime/go-string.h deleted file mode 100644 index 7fee1da03..000000000 --- a/gcc-4.8.1/libgo/runtime/go-string.h +++ /dev/null @@ -1,31 +0,0 @@ -/* go-string.h -- the string type for Go. - - 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. */ - -#ifndef LIBGO_GO_STRING_H -#define LIBGO_GO_STRING_H - -#include <stddef.h> - -static inline _Bool -__go_strings_equal (String s1, String s2) -{ - return (s1.len == s2.len - && __builtin_memcmp (s1.str, s2.str, s1.len) == 0); -} - -static inline _Bool -__go_ptr_strings_equal (const String *ps1, const String *ps2) -{ - if (ps1 == NULL) - return ps2 == NULL; - if (ps2 == NULL) - return 0; - return __go_strings_equal (*ps1, *ps2); -} - -extern int __go_get_rune (const unsigned char *, size_t, int32 *); - -#endif /* !defined(LIBGO_GO_STRING_H) */ diff --git a/gcc-4.8.1/libgo/runtime/go-strplus.c b/gcc-4.8.1/libgo/runtime/go-strplus.c deleted file mode 100644 index d6e6df67f..000000000 --- a/gcc-4.8.1/libgo/runtime/go-strplus.c +++ /dev/null @@ -1,30 +0,0 @@ -/* go-strplus.c -- the go string append function. - - 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 "arch.h" -#include "malloc.h" - -String -__go_string_plus (String s1, String s2) -{ - int len; - byte *retdata; - String ret; - - if (s1.len == 0) - return s2; - else if (s2.len == 0) - return s1; - - len = s1.len + s2.len; - retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0); - __builtin_memcpy (retdata, s1.str, s1.len); - __builtin_memcpy (retdata + s1.len, s2.str, s2.len); - ret.str = retdata; - ret.len = len; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-strslice.c b/gcc-4.8.1/libgo/runtime/go-strslice.c deleted file mode 100644 index 21e1bc031..000000000 --- a/gcc-4.8.1/libgo/runtime/go-strslice.c +++ /dev/null @@ -1,26 +0,0 @@ -/* go-strslice.c -- the go string slice function. - - 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 "go-panic.h" -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -String -__go_string_slice (String s, intgo start, intgo end) -{ - intgo len; - String ret; - - len = s.len; - if (end == -1) - end = len; - if (start > len || end < start || end > len) - runtime_panicstring ("string index out of bounds"); - ret.str = s.str + start; - ret.len = end - start; - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-traceback.c b/gcc-4.8.1/libgo/runtime/go-traceback.c deleted file mode 100644 index f397f0752..000000000 --- a/gcc-4.8.1/libgo/runtime/go-traceback.c +++ /dev/null @@ -1,37 +0,0 @@ -/* go-traceback.c -- stack backtrace for Go. - - Copyright 2012 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 "config.h" - -#include "runtime.h" - -/* Print a stack trace for the current goroutine. */ - -void -runtime_traceback () -{ - Location locbuf[100]; - int32 c; - - c = runtime_callers (1, locbuf, nelem (locbuf)); - runtime_printtrace (locbuf, c, true); -} - -void -runtime_printtrace (Location *locbuf, int32 c, bool current) -{ - int32 i; - - for (i = 0; i < c; ++i) - { - if (runtime_showframe (locbuf[i].function, current)) - { - runtime_printf ("%S\n", locbuf[i].function); - runtime_printf ("\t%S:%D\n", locbuf[i].filename, - (int64) locbuf[i].lineno); - } - } -} diff --git a/gcc-4.8.1/libgo/runtime/go-trampoline.c b/gcc-4.8.1/libgo/runtime/go-trampoline.c deleted file mode 100644 index 17f73d4f5..000000000 --- a/gcc-4.8.1/libgo/runtime/go-trampoline.c +++ /dev/null @@ -1,113 +0,0 @@ -/* go-trampoline.c -- allocate a trampoline for a nested function. - - 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 "config.h" - -#include <stddef.h> -#include <stdint.h> -#include <unistd.h> - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "go-assert.h" - -/* Trampolines need to run in memory that is both writable and - executable. In order to implement them, we grab a page of memory - and mprotect it. We fill in the page with trampolines as they are - required. When we run out of space, we drop the pointer to the - page and allocate a new one. The page will be freed by the garbage - collector when there are no more variables of type func pointing to - it. */ - -/* A lock to control access to the page of closures. */ - -static Lock trampoline_lock; - -/* The page of closures. */ - -static unsigned char *trampoline_page; - -/* The size of trampoline_page. */ - -static uintptr_t trampoline_page_size; - -/* The number of bytes we have used on trampoline_page. */ - -static uintptr_t trampoline_page_used; - -/* Allocate a trampoline of SIZE bytes that will use the closure in - CLOSURE. */ - -void * -__go_allocate_trampoline (uintptr_t size, void *closure) -{ - uintptr_t ptr_size; - uintptr_t full_size; - unsigned char *ret; - - /* Because the garbage collector only looks at aligned addresses, we - need to store the closure at an aligned address to ensure that it - sees it. */ - ptr_size = sizeof (void *); - full_size = (((size + ptr_size - 1) / ptr_size) * ptr_size); - full_size += ptr_size; - - runtime_lock (&trampoline_lock); - - if (full_size < trampoline_page_size - trampoline_page_used) - trampoline_page = NULL; - - if (trampoline_page == NULL) - { - uintptr_t page_size; - unsigned char *page; - - page_size = getpagesize (); - __go_assert (page_size >= full_size); - page = (unsigned char *) runtime_mallocgc (2 * page_size - 1, 0, 0, 0); - page = (unsigned char *) (((uintptr_t) page + page_size - 1) - & ~ (page_size - 1)); - -#ifdef HAVE_SYS_MMAN_H - { - int i; - - i = mprotect (page, page_size, PROT_READ | PROT_WRITE | PROT_EXEC); - __go_assert (i == 0); - } -#endif - - trampoline_page = page; - trampoline_page_size = page_size; - trampoline_page_used = 0; - } - - ret = trampoline_page + trampoline_page_used; - trampoline_page_used += full_size; - - runtime_unlock (&trampoline_lock); - - __builtin_memcpy (ret + full_size - ptr_size, &closure, ptr_size); - - return (void *) ret; -} - -/* Scan the trampoline page when running the garbage collector. This - just makes sure that the garbage collector sees the pointer in - trampoline_page, so that the page itself is not freed if there are - no other references to it. */ - -void -runtime_trampoline_scan (void (*addroot) (Obj)) -{ - if (trampoline_page != NULL) - addroot ((Obj){(byte *) &trampoline_page, sizeof trampoline_page, 0}); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-complex.c b/gcc-4.8.1/libgo/runtime/go-type-complex.c deleted file mode 100644 index 106024f5c..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-complex.c +++ /dev/null @@ -1,128 +0,0 @@ -/* go-type-complex.c -- hash and equality complex functions. - - Copyright 2012 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 "go-type.h" - -/* The 64-bit type. */ - -typedef unsigned int DItype __attribute__ ((mode (DI))); - -/* Hash function for float types. */ - -uintptr_t -__go_type_hash_complex (const void *vkey, uintptr_t key_size) -{ - if (key_size == 8) - { - union - { - unsigned char a[8]; - __complex float cf; - DItype di; - } ucf; - __complex float cf; - float cfr; - float cfi; - - __builtin_memcpy (ucf.a, vkey, 8); - cf = ucf.cf; - cfr = __builtin_crealf (cf); - cfi = __builtin_cimagf (cf); - if (__builtin_isinff (cfr) || __builtin_isinff (cfi)) - return 0; - - /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it - random so that not all NaNs wind up in the same place. */ - if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi)) - return runtime_fastrand1 (); - - /* Avoid negative zero. */ - if (cfr == 0 && cfi == 0) - return 0; - else if (cfr == 0) - ucf.cf = cfi * 1.0iF; - else if (cfi == 0) - ucf.cf = cfr; - - return ucf.di; - } - else if (key_size == 16) - { - union - { - unsigned char a[16]; - __complex double cd; - DItype adi[2]; - } ucd; - __complex double cd; - double cdr; - double cdi; - - __builtin_memcpy (ucd.a, vkey, 16); - cd = ucd.cd; - cdr = __builtin_crealf (cd); - cdi = __builtin_cimagf (cd); - if (__builtin_isinf (cdr) || __builtin_isinf (cdi)) - return 0; - - if (__builtin_isnan (cdr) || __builtin_isnan (cdi)) - return runtime_fastrand1 (); - - /* Avoid negative zero. */ - if (cdr == 0 && cdi == 0) - return 0; - else if (cdr == 0) - ucd.cd = cdi * 1.0i; - else if (cdi == 0) - ucd.cd = cdr; - - return ucd.adi[0] ^ ucd.adi[1]; - } - else - runtime_throw ("__go_type_hash_complex: invalid complex size"); -} - -/* Equality function for complex types. */ - -_Bool -__go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size) -{ - if (key_size == 8) - { - union - { - unsigned char a[8]; - __complex float cf; - } ucf; - __complex float cf1; - __complex float cf2; - - __builtin_memcpy (ucf.a, vk1, 8); - cf1 = ucf.cf; - __builtin_memcpy (ucf.a, vk2, 8); - cf2 = ucf.cf; - return cf1 == cf2; - } - else if (key_size == 16) - { - union - { - unsigned char a[16]; - __complex double cd; - } ucd; - __complex double cd1; - __complex double cd2; - - __builtin_memcpy (ucd.a, vk1, 16); - cd1 = ucd.cd; - __builtin_memcpy (ucd.a, vk2, 16); - cd2 = ucd.cd; - return cd1 == cd2; - } - else - runtime_throw ("__go_type_equal_complex: invalid complex size"); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-eface.c b/gcc-4.8.1/libgo/runtime/go-type-eface.c deleted file mode 100644 index cb3424b98..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-eface.c +++ /dev/null @@ -1,59 +0,0 @@ -/* go-type-eface.c -- hash and equality empty interface functions. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "interface.h" -#include "go-type.h" - -/* A hash function for an empty interface. */ - -uintptr_t -__go_type_hash_empty_interface (const void *vval, - uintptr_t key_size __attribute__ ((unused))) -{ - const struct __go_empty_interface *val; - const struct __go_type_descriptor *descriptor; - uintptr_t size; - - val = (const struct __go_empty_interface *) vval; - descriptor = val->__type_descriptor; - if (descriptor == NULL) - return 0; - size = descriptor->__size; - if (__go_is_pointer_type (descriptor)) - return descriptor->__hashfn (&val->__object, size); - else - return descriptor->__hashfn (val->__object, size); -} - -/* An equality function for an empty interface. */ - -_Bool -__go_type_equal_empty_interface (const void *vv1, const void *vv2, - uintptr_t key_size __attribute__ ((unused))) -{ - const struct __go_empty_interface *v1; - const struct __go_empty_interface *v2; - const struct __go_type_descriptor* v1_descriptor; - const struct __go_type_descriptor* v2_descriptor; - - v1 = (const struct __go_empty_interface *) vv1; - v2 = (const struct __go_empty_interface *) vv2; - v1_descriptor = v1->__type_descriptor; - v2_descriptor = v2->__type_descriptor; - if (((uintptr_t) v1_descriptor & reflectFlags) != 0 - || ((uintptr_t) v2_descriptor & reflectFlags) != 0) - runtime_panicstring ("invalid interface value"); - if (v1_descriptor == NULL || v2_descriptor == NULL) - return v1_descriptor == v2_descriptor; - if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor)) - return 0; - if (__go_is_pointer_type (v1_descriptor)) - return v1->__object == v2->__object; - else - return v1_descriptor->__equalfn (v1->__object, v2->__object, - v1_descriptor->__size); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-error.c b/gcc-4.8.1/libgo/runtime/go-type-error.c deleted file mode 100644 index b4c609b93..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-error.c +++ /dev/null @@ -1,28 +0,0 @@ -/* go-type-error.c -- invalid hash and equality functions. - - 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 "go-type.h" - -/* A hash function used for a type which does not support hash - functions. */ - -uintptr_t -__go_type_hash_error (const void *val __attribute__ ((unused)), - uintptr_t key_size __attribute__ ((unused))) -{ - runtime_panicstring ("hash of unhashable type"); -} - -/* An equality function for an interface. */ - -_Bool -__go_type_equal_error (const void *v1 __attribute__ ((unused)), - const void *v2 __attribute__ ((unused)), - uintptr_t key_size __attribute__ ((unused))) -{ - runtime_panicstring ("comparing uncomparable types"); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-float.c b/gcc-4.8.1/libgo/runtime/go-type-float.c deleted file mode 100644 index e1c03e428..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-float.c +++ /dev/null @@ -1,106 +0,0 @@ -/* go-type-float.c -- hash and equality float functions. - - Copyright 2012 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 "go-type.h" - -/* The 32-bit and 64-bit types. */ - -typedef unsigned int SItype __attribute__ ((mode (SI))); -typedef unsigned int DItype __attribute__ ((mode (DI))); - -/* Hash function for float types. */ - -uintptr_t -__go_type_hash_float (const void *vkey, uintptr_t key_size) -{ - if (key_size == 4) - { - union - { - unsigned char a[4]; - float f; - SItype si; - } uf; - float f; - - __builtin_memcpy (uf.a, vkey, 4); - f = uf.f; - if (__builtin_isinff (f) || f == 0) - return 0; - - /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it - random so that not all NaNs wind up in the same place. */ - if (__builtin_isnanf (f)) - return runtime_fastrand1 (); - - return (uintptr_t) uf.si; - } - else if (key_size == 8) - { - union - { - unsigned char a[8]; - double d; - DItype di; - } ud; - double d; - - __builtin_memcpy (ud.a, vkey, 8); - d = ud.d; - if (__builtin_isinf (d) || d == 0) - return 0; - - if (__builtin_isnan (d)) - return runtime_fastrand1 (); - - return (uintptr_t) ud.di; - } - else - runtime_throw ("__go_type_hash_float: invalid float size"); -} - -/* Equality function for float types. */ - -_Bool -__go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size) -{ - if (key_size == 4) - { - union - { - unsigned char a[4]; - float f; - } uf; - float f1; - float f2; - - __builtin_memcpy (uf.a, vk1, 4); - f1 = uf.f; - __builtin_memcpy (uf.a, vk2, 4); - f2 = uf.f; - return f1 == f2; - } - else if (key_size == 8) - { - union - { - unsigned char a[8]; - double d; - DItype di; - } ud; - double d1; - double d2; - - __builtin_memcpy (ud.a, vk1, 8); - d1 = ud.d; - __builtin_memcpy (ud.a, vk2, 8); - d2 = ud.d; - return d1 == d2; - } - else - runtime_throw ("__go_type_equal_float: invalid float size"); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-identity.c b/gcc-4.8.1/libgo/runtime/go-type-identity.c deleted file mode 100644 index ed510f75a..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-identity.c +++ /dev/null @@ -1,56 +0,0 @@ -/* go-type-identity.c -- hash and equality identity functions. - - 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 <stddef.h> - -#include "runtime.h" -#include "go-type.h" - -/* An identity hash function for a type. This is used for types where - we can simply use the type value itself as a hash code. This is - true of, e.g., integers and pointers. */ - -uintptr_t -__go_type_hash_identity (const void *key, uintptr_t key_size) -{ - uintptr_t ret; - uintptr_t i; - const unsigned char *p; - - if (key_size <= 8) - { - union - { - uint64 v; - unsigned char a[8]; - } u; - u.v = 0; -#ifdef WORDS_BIGENDIAN - __builtin_memcpy (&u.a[8 - key_size], key, key_size); -#else - __builtin_memcpy (&u.a[0], key, key_size); -#endif - if (sizeof (uintptr_t) >= 8) - return (uintptr_t) u.v; - else - return (uintptr_t) ((u.v >> 32) ^ (u.v & 0xffffffff)); - } - - ret = 5381; - for (i = 0, p = (const unsigned char *) key; i < key_size; i++, p++) - ret = ret * 33 + *p; - return ret; -} - -/* An identity equality function for a type. This is used for types - where we can check for equality by checking that the values have - the same bits. */ - -_Bool -__go_type_equal_identity (const void *k1, const void *k2, uintptr_t key_size) -{ - return __builtin_memcmp (k1, k2, key_size) == 0; -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-interface.c b/gcc-4.8.1/libgo/runtime/go-type-interface.c deleted file mode 100644 index 9aad72008..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-interface.c +++ /dev/null @@ -1,56 +0,0 @@ -/* go-type-interface.c -- hash and equality interface functions. - - 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 "interface.h" -#include "go-type.h" - -/* A hash function for an interface. */ - -uintptr_t -__go_type_hash_interface (const void *vval, - uintptr_t key_size __attribute__ ((unused))) -{ - const struct __go_interface *val; - const struct __go_type_descriptor *descriptor; - uintptr_t size; - - val = (const struct __go_interface *) vval; - if (val->__methods == NULL) - return 0; - descriptor = (const struct __go_type_descriptor *) val->__methods[0]; - size = descriptor->__size; - if (__go_is_pointer_type (descriptor)) - return descriptor->__hashfn (&val->__object, size); - else - return descriptor->__hashfn (val->__object, size); -} - -/* An equality function for an interface. */ - -_Bool -__go_type_equal_interface (const void *vv1, const void *vv2, - uintptr_t key_size __attribute__ ((unused))) -{ - const struct __go_interface *v1; - const struct __go_interface *v2; - const struct __go_type_descriptor* v1_descriptor; - const struct __go_type_descriptor* v2_descriptor; - - v1 = (const struct __go_interface *) vv1; - v2 = (const struct __go_interface *) vv2; - if (v1->__methods == NULL || v2->__methods == NULL) - return v1->__methods == v2->__methods; - v1_descriptor = (const struct __go_type_descriptor *) v1->__methods[0]; - v2_descriptor = (const struct __go_type_descriptor *) v2->__methods[0]; - if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor)) - return 0; - if (__go_is_pointer_type (v1_descriptor)) - return v1->__object == v2->__object; - else - return v1_descriptor->__equalfn (v1->__object, v2->__object, - v1_descriptor->__size); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type-string.c b/gcc-4.8.1/libgo/runtime/go-type-string.c deleted file mode 100644 index a96af0290..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type-string.c +++ /dev/null @@ -1,43 +0,0 @@ -/* go-type-string.c -- hash and equality string functions. - - 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 "go-type.h" -#include "go-string.h" - -/* A string hash function for a map. */ - -uintptr_t -__go_type_hash_string (const void *vkey, - uintptr_t key_size __attribute__ ((unused))) -{ - uintptr_t ret; - const String *key; - intgo len; - intgo i; - const byte *p; - - ret = 5381; - key = (const String *) vkey; - len = key->len; - for (i = 0, p = key->str; i < len; i++, p++) - ret = ret * 33 + *p; - return ret; -} - -/* A string equality function for a map. */ - -_Bool -__go_type_equal_string (const void *vk1, const void *vk2, - uintptr_t key_size __attribute__ ((unused))) -{ - const String *k1; - const String *k2; - - k1 = (const String *) vk1; - k2 = (const String *) vk2; - return __go_ptr_strings_equal (k1, k2); -} diff --git a/gcc-4.8.1/libgo/runtime/go-type.h b/gcc-4.8.1/libgo/runtime/go-type.h deleted file mode 100644 index 2269ae633..000000000 --- a/gcc-4.8.1/libgo/runtime/go-type.h +++ /dev/null @@ -1,334 +0,0 @@ -/* go-type.h -- basic information for a Go type. - - 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. */ - -#ifndef LIBGO_GO_TYPE_H -#define LIBGO_GO_TYPE_H - -#include <stddef.h> -#include <stdint.h> - -#include "array.h" - -struct String; - -/* Many of the types in this file must match the data structures - generated by the compiler, and must also match the Go types which - appear in go/runtime/type.go and go/reflect/type.go. */ - -/* Type kinds. These are used to get the type descriptor to use for - the type itself, when using unsafe.Typeof or unsafe.Reflect. The - values here must match the values generated by the compiler (the - RUNTIME_TYPE_KIND_xxx values in gcc/go/types.h). These are macros - rather than an enum to make it easy to change values in the future - and hard to get confused about it. - - These correspond to the kind values used by the gc compiler. */ - -#define GO_BOOL 1 -#define GO_INT 2 -#define GO_INT8 3 -#define GO_INT16 4 -#define GO_INT32 5 -#define GO_INT64 6 -#define GO_UINT 7 -#define GO_UINT8 8 -#define GO_UINT16 9 -#define GO_UINT32 10 -#define GO_UINT64 11 -#define GO_UINTPTR 12 -#define GO_FLOAT32 13 -#define GO_FLOAT64 14 -#define GO_COMPLEX64 15 -#define GO_COMPLEX128 16 -#define GO_ARRAY 17 -#define GO_CHAN 18 -#define GO_FUNC 19 -#define GO_INTERFACE 20 -#define GO_MAP 21 -#define GO_PTR 22 -#define GO_SLICE 23 -#define GO_STRING 24 -#define GO_STRUCT 25 -#define GO_UNSAFE_POINTER 26 - -#define GO_NO_POINTERS (1 << 7) - -#define GO_CODE_MASK 0x7f - -/* For each Go type the compiler constructs one of these structures. - This is used for type reflectin, interfaces, maps, and reference - counting. */ - -struct __go_type_descriptor -{ - /* The type code for this type, one of the type kind values above. - This is used by unsafe.Reflect and unsafe.Typeof to determine the - type descriptor to return for this type itself. It is also used - by reflect.toType when mapping to a reflect Type structure. */ - unsigned char __code; - - /* The alignment in bytes of a variable with this type. */ - unsigned char __align; - - /* The alignment in bytes of a struct field with this type. */ - unsigned char __field_align; - - /* The size in bytes of a value of this type. Note that all types - in Go have a fixed size. */ - uintptr_t __size; - - /* The type's hash code. */ - uint32_t __hash; - - /* This function takes a pointer to a value of this type, and the - size of this type, and returns a hash code. We pass the size - explicitly becaues it means that we can share a single instance - of this function for various different types. */ - uintptr_t (*__hashfn) (const void *, uintptr_t); - - /* This function takes two pointers to values of this type, and the - size of this type, and returns whether the values are equal. */ - _Bool (*__equalfn) (const void *, const void *, uintptr_t); - - /* A string describing this type. This is only used for - debugging. */ - const struct String *__reflection; - - /* A pointer to fields which are only used for some types. */ - const struct __go_uncommon_type *__uncommon; - - /* The descriptor for the type which is a pointer to this type. - This may be NULL. */ - const struct __go_type_descriptor *__pointer_to_this; -}; - -/* The information we store for each method of a type. */ - -struct __go_method -{ - /* The name of the method. */ - const struct String *__name; - - /* This is NULL for an exported method, or the name of the package - where it lives. */ - const struct String *__pkg_path; - - /* The type of the method, without the receiver. This will be a - function type. */ - const struct __go_type_descriptor *__mtype; - - /* The type of the method, with the receiver. This will be a - function type. */ - const struct __go_type_descriptor *__type; - - /* A pointer to the code which implements the method. This is - really a function pointer. */ - const void *__function; -}; - -/* Additional information that we keep for named types and for types - with methods. */ - -struct __go_uncommon_type -{ - /* The name of the type. */ - const struct String *__name; - - /* The type's package. This is NULL for builtin types. */ - const struct String *__pkg_path; - - /* The type's methods. This is an array of struct __go_method. */ - struct __go_open_array __methods; -}; - -/* The type descriptor for a fixed array type. */ - -struct __go_array_type -{ - /* Starts like all type descriptors. */ - struct __go_type_descriptor __common; - - /* The element type. */ - struct __go_type_descriptor *__element_type; - - /* The type of a slice of the same element type. */ - struct __go_type_descriptor *__slice_type; - - /* The length of the array. */ - uintptr_t __len; -}; - -/* The type descriptor for a slice. */ - -struct __go_slice_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* The element type. */ - struct __go_type_descriptor *__element_type; -}; - -/* The direction of a channel. */ -#define CHANNEL_RECV_DIR 1 -#define CHANNEL_SEND_DIR 2 -#define CHANNEL_BOTH_DIR (CHANNEL_RECV_DIR | CHANNEL_SEND_DIR) - -/* The type descriptor for a channel. */ - -struct __go_channel_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* The element type. */ - const struct __go_type_descriptor *__element_type; - - /* The direction. */ - uintptr_t __dir; -}; - -/* The type descriptor for a function. */ - -struct __go_func_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* Whether this is a varargs function. If this is true, there will - be at least one parameter. For "..." the last parameter type is - "interface{}". For "... T" the last parameter type is "[]T". */ - _Bool __dotdotdot; - - /* The input parameter types. This is an array of pointers to - struct __go_type_descriptor. */ - struct __go_open_array __in; - - /* The output parameter types. This is an array of pointers to - struct __go_type_descriptor. */ - struct __go_open_array __out; -}; - -/* A method on an interface type. */ - -struct __go_interface_method -{ - /* The name of the method. */ - const struct String *__name; - - /* This is NULL for an exported method, or the name of the package - where it lives. */ - const struct String *__pkg_path; - - /* The real type of the method. */ - struct __go_type_descriptor *__type; -}; - -/* An interface type. */ - -struct __go_interface_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* Array of __go_interface_method . The methods are sorted in the - same order that they appear in the definition of the - interface. */ - struct __go_open_array __methods; -}; - -/* A map type. */ - -struct __go_map_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* The map key type. */ - const struct __go_type_descriptor *__key_type; - - /* The map value type. */ - const struct __go_type_descriptor *__val_type; -}; - -/* A pointer type. */ - -struct __go_ptr_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* The type to which this points. */ - const struct __go_type_descriptor *__element_type; -}; - -/* A field in a structure. */ - -struct __go_struct_field -{ - /* The name of the field--NULL for an anonymous field. */ - const struct String *__name; - - /* This is NULL for an exported method, or the name of the package - where it lives. */ - const struct String *__pkg_path; - - /* The type of the field. */ - const struct __go_type_descriptor *__type; - - /* The field tag, or NULL. */ - const struct String *__tag; - - /* The offset of the field in the struct. */ - uintptr_t __offset; -}; - -/* A struct type. */ - -struct __go_struct_type -{ - /* Starts like all other type descriptors. */ - struct __go_type_descriptor __common; - - /* An array of struct __go_struct_field. */ - struct __go_open_array __fields; -}; - -/* If an empty interface has these bits set in its type pointer, it - was copied from a reflect.Value and is not a valid empty - interface. */ - -enum -{ - reflectFlags = 3, -}; - -/* Whether a type descriptor is a pointer. */ - -static inline _Bool -__go_is_pointer_type (const struct __go_type_descriptor *td) -{ - return td->__code == GO_PTR || td->__code == GO_UNSAFE_POINTER; -} - -extern _Bool -__go_type_descriptors_equal(const struct __go_type_descriptor*, - const struct __go_type_descriptor*); - -extern uintptr_t __go_type_hash_identity (const void *, uintptr_t); -extern _Bool __go_type_equal_identity (const void *, const void *, uintptr_t); -extern uintptr_t __go_type_hash_string (const void *, uintptr_t); -extern _Bool __go_type_equal_string (const void *, const void *, uintptr_t); -extern uintptr_t __go_type_hash_float (const void *, uintptr_t); -extern _Bool __go_type_equal_float (const void *, const void *, uintptr_t); -extern uintptr_t __go_type_hash_complex (const void *, uintptr_t); -extern _Bool __go_type_equal_complex (const void *, const void *, uintptr_t); -extern uintptr_t __go_type_hash_interface (const void *, uintptr_t); -extern _Bool __go_type_equal_interface (const void *, const void *, uintptr_t); -extern uintptr_t __go_type_hash_error (const void *, uintptr_t); -extern _Bool __go_type_equal_error (const void *, const void *, uintptr_t); - -#endif /* !defined(LIBGO_GO_TYPE_H) */ diff --git a/gcc-4.8.1/libgo/runtime/go-typedesc-equal.c b/gcc-4.8.1/libgo/runtime/go-typedesc-equal.c deleted file mode 100644 index f8474fc9f..000000000 --- a/gcc-4.8.1/libgo/runtime/go-typedesc-equal.c +++ /dev/null @@ -1,39 +0,0 @@ -/* go-typedesc-equal.c -- return whether two type descriptors are equal. - - 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 "go-string.h" -#include "go-type.h" - -/* Compare type descriptors for equality. This is necessary because - types may have different descriptors in different shared libraries. - Also, unnamed types may have multiple type descriptors even in a - single shared library. */ - -_Bool -__go_type_descriptors_equal (const struct __go_type_descriptor *td1, - const struct __go_type_descriptor *td2) -{ - if (td1 == td2) - return 1; - /* In a type switch we can get a NULL descriptor. */ - if (td1 == NULL || td2 == NULL) - return 0; - if (td1->__code != td2->__code || td1->__hash != td2->__hash) - return 0; - if (td1->__uncommon != NULL && td1->__uncommon->__name != NULL) - { - if (td2->__uncommon == NULL || td2->__uncommon->__name == NULL) - return 0; - return (__go_ptr_strings_equal (td1->__uncommon->__name, - td2->__uncommon->__name) - && __go_ptr_strings_equal (td1->__uncommon->__pkg_path, - td2->__uncommon->__pkg_path)); - } - if (td2->__uncommon != NULL && td2->__uncommon->__name != NULL) - return 0; - return __go_ptr_strings_equal (td1->__reflection, td2->__reflection); -} diff --git a/gcc-4.8.1/libgo/runtime/go-typestring.c b/gcc-4.8.1/libgo/runtime/go-typestring.c deleted file mode 100644 index 0a90e84bc..000000000 --- a/gcc-4.8.1/libgo/runtime/go-typestring.c +++ /dev/null @@ -1,17 +0,0 @@ -/* go-typestring.c -- the runtime.typestring function. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "runtime.h" -#include "interface.h" -#include "go-type.h" - -String typestring(struct __go_empty_interface) __asm__ (GOSYM_PREFIX "runtime.typestring"); - -String -typestring (struct __go_empty_interface e) -{ - return *e.__type_descriptor->__reflection; -} diff --git a/gcc-4.8.1/libgo/runtime/go-unsafe-new.c b/gcc-4.8.1/libgo/runtime/go-unsafe-new.c deleted file mode 100644 index 54788f196..000000000 --- a/gcc-4.8.1/libgo/runtime/go-unsafe-new.c +++ /dev/null @@ -1,34 +0,0 @@ -/* go-unsafe-new.c -- unsafe.New function for Go. - - 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 "arch.h" -#include "malloc.h" -#include "go-type.h" -#include "interface.h" - -/* Implement unsafe_New, called from the reflect package. */ - -void *unsafe_New (const struct __go_type_descriptor *) - __asm__ (GOSYM_PREFIX "reflect.unsafe_New"); - -/* The dynamic type of the argument will be a pointer to a type - descriptor. */ - -void * -unsafe_New (const struct __go_type_descriptor *descriptor) -{ - uint32 flag; - void *ret; - - flag = (descriptor->__code & GO_NO_POINTERS) != 0 ? FlagNoPointers : 0; - ret = runtime_mallocgc (descriptor->__size, flag, 1, 1); - - if (UseSpanType && flag == 0) - runtime_settype (ret, (uintptr) descriptor | TypeInfo_SingleObject); - - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-unsafe-newarray.c b/gcc-4.8.1/libgo/runtime/go-unsafe-newarray.c deleted file mode 100644 index e4fb3366b..000000000 --- a/gcc-4.8.1/libgo/runtime/go-unsafe-newarray.c +++ /dev/null @@ -1,41 +0,0 @@ -/* go-unsafe-newarray.c -- unsafe.NewArray function for Go. - - 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 "arch.h" -#include "malloc.h" -#include "go-type.h" -#include "interface.h" - -/* Implement unsafe_NewArray, called from the reflect package. */ - -void *unsafe_NewArray (const struct __go_type_descriptor *, intgo) - __asm__ (GOSYM_PREFIX "reflect.unsafe_NewArray"); - -/* The dynamic type of the argument will be a pointer to a type - descriptor. */ - -void * -unsafe_NewArray (const struct __go_type_descriptor *descriptor, intgo n) -{ - uint64 size; - void *ret; - - size = n * descriptor->__size; - if (size == 0) - ret = &runtime_zerobase; - else if ((descriptor->__code & GO_NO_POINTERS) != 0) - ret = runtime_mallocgc (size, FlagNoPointers, 1, 1); - else - { - ret = runtime_mallocgc (size, 0, 1, 1); - - if (UseSpanType) - runtime_settype (ret, (uintptr) descriptor | TypeInfo_Array); - } - - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/go-unsafe-pointer.c b/gcc-4.8.1/libgo/runtime/go-unsafe-pointer.c deleted file mode 100644 index ca1d25364..000000000 --- a/gcc-4.8.1/libgo/runtime/go-unsafe-pointer.c +++ /dev/null @@ -1,101 +0,0 @@ -/* go-unsafe-pointer.c -- unsafe.Pointer type descriptor for Go. - - 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 <stddef.h> - -#include "runtime.h" -#include "go-type.h" - -/* This file provides the type descriptor for the unsafe.Pointer type. - The unsafe package is defined by the compiler itself, which means - that there is no package to compile to define the type - descriptor. */ - -extern const struct __go_type_descriptor unsafe_Pointer - __asm__ (GOSYM_PREFIX "__go_tdn_unsafe.Pointer"); - -/* Used to determine the field alignment. */ -struct field_align -{ - char c; - void *p; -}; - -/* The reflection string. */ -#define REFLECTION "unsafe.Pointer" -static const String reflection_string = -{ - (const byte *) REFLECTION, - sizeof REFLECTION - 1 -}; - -const struct __go_type_descriptor unsafe_Pointer = -{ - /* __code */ - GO_UNSAFE_POINTER, - /* __align */ - __alignof (void *), - /* __field_align */ - offsetof (struct field_align, p) - 1, - /* __size */ - sizeof (void *), - /* __hash */ - 78501163U, - /* __hashfn */ - __go_type_hash_identity, - /* __equalfn */ - __go_type_equal_identity, - /* __reflection */ - &reflection_string, - /* __uncommon */ - NULL, - /* __pointer_to_this */ - NULL -}; - -/* We also need the type descriptor for the pointer to unsafe.Pointer, - since any package which refers to that type descriptor will expect - it to be defined elsewhere. */ - -extern const struct __go_ptr_type pointer_unsafe_Pointer - __asm__ (GOSYM_PREFIX "__go_td_pN14_unsafe.Pointer"); - -/* The reflection string. */ -#define PREFLECTION "*unsafe.Pointer" -static const String preflection_string = -{ - (const byte *) PREFLECTION, - sizeof PREFLECTION - 1, -}; - -const struct __go_ptr_type pointer_unsafe_Pointer = -{ - /* __common */ - { - /* __code */ - GO_PTR, - /* __align */ - __alignof (void *), - /* __field_align */ - offsetof (struct field_align, p) - 1, - /* __size */ - sizeof (void *), - /* __hash */ - 1256018616U, - /* __hashfn */ - __go_type_hash_identity, - /* __equalfn */ - __go_type_equal_identity, - /* __reflection */ - &preflection_string, - /* __uncommon */ - NULL, - /* __pointer_to_this */ - NULL - }, - /* __element_type */ - &unsafe_Pointer -}; diff --git a/gcc-4.8.1/libgo/runtime/go-unwind.c b/gcc-4.8.1/libgo/runtime/go-unwind.c deleted file mode 100644 index c669a3ce8..000000000 --- a/gcc-4.8.1/libgo/runtime/go-unwind.c +++ /dev/null @@ -1,440 +0,0 @@ -/* go-unwind.c -- unwind the stack for panic/recover. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include "config.h" - -#include <stdlib.h> -#include <unistd.h> - -#include "unwind.h" -#define NO_SIZE_OF_ENCODED_VALUE -#include "unwind-pe.h" - -#include "runtime.h" -#include "go-alloc.h" -#include "go-defer.h" -#include "go-panic.h" - -/* The code for a Go exception. */ - -#ifdef __ARM_EABI_UNWINDER__ -static const _Unwind_Exception_Class __go_exception_class = - { 'G', 'N', 'U', 'C', 'G', 'O', '\0', '\0' }; -#else -static const _Unwind_Exception_Class __go_exception_class = - ((((((((_Unwind_Exception_Class) 'G' - << 8 | (_Unwind_Exception_Class) 'N') - << 8 | (_Unwind_Exception_Class) 'U') - << 8 | (_Unwind_Exception_Class) 'C') - << 8 | (_Unwind_Exception_Class) 'G') - << 8 | (_Unwind_Exception_Class) 'O') - << 8 | (_Unwind_Exception_Class) '\0') - << 8 | (_Unwind_Exception_Class) '\0'); -#endif - - -/* This function is called by exception handlers used when unwinding - the stack after a recovered panic. The exception handler looks - like this: - __go_check_defer (frame); - return; - If we have not yet reached the frame we are looking for, we - continue unwinding. */ - -void -__go_check_defer (_Bool *frame) -{ - G *g; - struct _Unwind_Exception *hdr; - - g = runtime_g (); - - if (g == NULL) - { - /* Some other language has thrown an exception. We know there - are no defer handlers, so there is nothing to do. */ - } - else if (g->is_foreign) - { - struct __go_panic_stack *n; - _Bool was_recovered; - - /* Some other language has thrown an exception. We need to run - the local defer handlers. If they call recover, we stop - unwinding the stack here. */ - - n = ((struct __go_panic_stack *) - __go_alloc (sizeof (struct __go_panic_stack))); - - n->__arg.__type_descriptor = NULL; - n->__arg.__object = NULL; - n->__was_recovered = 0; - n->__is_foreign = 1; - n->__next = g->panic; - g->panic = n; - - while (1) - { - struct __go_defer_stack *d; - void (*pfn) (void *); - - d = g->defer; - if (d == NULL || d->__frame != frame || d->__pfn == NULL) - break; - - pfn = d->__pfn; - g->defer = d->__next; - - (*pfn) (d->__arg); - - __go_free (d); - - if (n->__was_recovered) - { - /* The recover function caught the panic thrown by some - other language. */ - break; - } - } - - was_recovered = n->__was_recovered; - g->panic = n->__next; - __go_free (n); - - if (was_recovered) - { - /* Just return and continue executing Go code. */ - *frame = 1; - return; - } - - /* We are panicing through this function. */ - *frame = 0; - } - else if (g->defer != NULL - && g->defer->__pfn == NULL - && g->defer->__frame == frame) - { - struct __go_defer_stack *d; - - /* This is the defer function which called recover. Simply - return to stop the stack unwind, and let the Go code continue - to execute. */ - d = g->defer; - g->defer = d->__next; - __go_free (d); - - /* We are returning from this function. */ - *frame = 1; - - return; - } - - /* This is some other defer function. It was already run by the - call to panic, or just above. Rethrow the exception. */ - - hdr = (struct _Unwind_Exception *) g->exception; - -#ifdef LIBGO_SJLJ_EXCEPTIONS - _Unwind_SjLj_Resume_or_Rethrow (hdr); -#else -#if defined(_LIBUNWIND_STD_ABI) - _Unwind_RaiseException (hdr); -#else - _Unwind_Resume_or_Rethrow (hdr); -#endif -#endif - - /* Rethrowing the exception should not return. */ - abort(); -} - -/* Unwind function calls until we reach the one which used a defer - function which called recover. Each function which uses a defer - statement will have an exception handler, as shown above. */ - -void -__go_unwind_stack () -{ - struct _Unwind_Exception *hdr; - - hdr = ((struct _Unwind_Exception *) - __go_alloc (sizeof (struct _Unwind_Exception))); - __builtin_memcpy (&hdr->exception_class, &__go_exception_class, - sizeof hdr->exception_class); - hdr->exception_cleanup = NULL; - - runtime_g ()->exception = hdr; - -#ifdef __USING_SJLJ_EXCEPTIONS__ - _Unwind_SjLj_RaiseException (hdr); -#else - _Unwind_RaiseException (hdr); -#endif - - /* Raising an exception should not return. */ - abort (); -} - -/* The rest of this code is really similar to gcc/unwind-c.c and - libjava/exception.cc. */ - -typedef struct -{ - _Unwind_Ptr Start; - _Unwind_Ptr LPStart; - _Unwind_Ptr ttype_base; - const unsigned char *TType; - const unsigned char *action_table; - unsigned char ttype_encoding; - unsigned char call_site_encoding; -} lsda_header_info; - -static const unsigned char * -parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, - lsda_header_info *info) -{ - _uleb128_t tmp; - unsigned char lpstart_encoding; - - info->Start = (context ? _Unwind_GetRegionStart (context) : 0); - - /* Find @LPStart, the base to which landing pad offsets are relative. */ - lpstart_encoding = *p++; - if (lpstart_encoding != DW_EH_PE_omit) - p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart); - else - info->LPStart = info->Start; - - /* Find @TType, the base of the handler and exception spec type data. */ - info->ttype_encoding = *p++; - if (info->ttype_encoding != DW_EH_PE_omit) - { - p = read_uleb128 (p, &tmp); - info->TType = p + tmp; - } - else - info->TType = 0; - - /* The encoding and length of the call-site table; the action table - immediately follows. */ - info->call_site_encoding = *p++; - p = read_uleb128 (p, &tmp); - info->action_table = p + tmp; - - return p; -} - -/* The personality function is invoked when unwinding the stack due to - a panic. Its job is to find the cleanup and exception handlers to - run. We can't split the stack here, because we won't be able to - unwind from that split. */ - -#ifdef __ARM_EABI_UNWINDER__ -/* ARM EABI personality routines must also unwind the stack. */ -#define CONTINUE_UNWINDING \ - do \ - { \ - if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \ - return _URC_FAILURE; \ - return _URC_CONTINUE_UNWIND; \ - } \ - while (0) -#else -#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND -#endif - -#ifdef __USING_SJLJ_EXCEPTIONS__ -#define PERSONALITY_FUNCTION __gccgo_personality_sj0 -#define __builtin_eh_return_data_regno(x) x -#else -#define PERSONALITY_FUNCTION __gccgo_personality_v0 -#endif - -#ifdef __ARM_EABI_UNWINDER__ -_Unwind_Reason_Code -PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *, - struct _Unwind_Context *) - __attribute__ ((no_split_stack, flatten)); - -_Unwind_Reason_Code -PERSONALITY_FUNCTION (_Unwind_State state, - struct _Unwind_Exception * ue_header, - struct _Unwind_Context * context) -#else -_Unwind_Reason_Code -PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class, - struct _Unwind_Exception *, struct _Unwind_Context *) - __attribute__ ((no_split_stack, flatten)); - -_Unwind_Reason_Code -PERSONALITY_FUNCTION (int version, - _Unwind_Action actions, - _Unwind_Exception_Class exception_class, - struct _Unwind_Exception *ue_header, - struct _Unwind_Context *context) -#endif -{ - lsda_header_info info; - const unsigned char *language_specific_data, *p, *action_record; - _Unwind_Ptr landing_pad, ip; - int ip_before_insn = 0; - _Bool is_foreign; - G *g; - -#ifdef __ARM_EABI_UNWINDER__ - _Unwind_Action actions; - - switch (state & _US_ACTION_MASK) - { - case _US_VIRTUAL_UNWIND_FRAME: - actions = _UA_SEARCH_PHASE; - break; - - case _US_UNWIND_FRAME_STARTING: - actions = _UA_CLEANUP_PHASE; - if (!(state & _US_FORCE_UNWIND) - && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13)) - actions |= _UA_HANDLER_FRAME; - break; - - case _US_UNWIND_FRAME_RESUME: - CONTINUE_UNWINDING; - break; - - default: - abort(); - } - actions |= state & _US_FORCE_UNWIND; - - is_foreign = 0; - - /* The dwarf unwinder assumes the context structure holds things like the - function and LSDA pointers. The ARM implementation caches these in - the exception header (UCB). To avoid rewriting everything we make the - virtual IP register point at the UCB. */ - ip = (_Unwind_Ptr) ue_header; - _Unwind_SetGR (context, 12, ip); -#else - if (version != 1) - return _URC_FATAL_PHASE1_ERROR; - - is_foreign = exception_class != __go_exception_class; -#endif - - language_specific_data = (const unsigned char *) - _Unwind_GetLanguageSpecificData (context); - - /* If no LSDA, then there are no handlers or cleanups. */ - if (! language_specific_data) - CONTINUE_UNWINDING; - - /* Parse the LSDA header. */ - p = parse_lsda_header (context, language_specific_data, &info); -#ifdef HAVE_GETIPINFO - ip = _Unwind_GetIPInfo (context, &ip_before_insn); -#else - ip = _Unwind_GetIP (context); -#endif - if (! ip_before_insn) - --ip; - landing_pad = 0; - action_record = NULL; - -#ifdef __USING_SJLJ_EXCEPTIONS__ - /* The given "IP" is an index into the call-site table, with two - exceptions -- -1 means no-action, and 0 means terminate. But - since we're using uleb128 values, we've not got random access - to the array. */ - if ((int) ip <= 0) - return _URC_CONTINUE_UNWIND; - else - { - _uleb128_t cs_lp, cs_action; - do - { - p = read_uleb128 (p, &cs_lp); - p = read_uleb128 (p, &cs_action); - } - while (--ip); - - /* Can never have null landing pad for sjlj -- that would have - been indicated by a -1 call site index. */ - landing_pad = (_Unwind_Ptr)cs_lp + 1; - if (cs_action) - action_record = info.action_table + cs_action - 1; - goto found_something; - } -#else - /* Search the call-site table for the action associated with this IP. */ - while (p < info.action_table) - { - _Unwind_Ptr cs_start, cs_len, cs_lp; - _uleb128_t cs_action; - - /* Note that all call-site encodings are "absolute" displacements. */ - p = read_encoded_value (0, info.call_site_encoding, p, &cs_start); - p = read_encoded_value (0, info.call_site_encoding, p, &cs_len); - p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp); - p = read_uleb128 (p, &cs_action); - - /* The table is sorted, so if we've passed the ip, stop. */ - if (ip < info.Start + cs_start) - p = info.action_table; - else if (ip < info.Start + cs_start + cs_len) - { - if (cs_lp) - landing_pad = info.LPStart + cs_lp; - if (cs_action) - action_record = info.action_table + cs_action - 1; - goto found_something; - } - } -#endif - - /* IP is not in table. No associated cleanups. */ - CONTINUE_UNWINDING; - - found_something: - if (landing_pad == 0) - { - /* IP is present, but has a null landing pad. - No handler to be run. */ - CONTINUE_UNWINDING; - } - - if (actions & _UA_SEARCH_PHASE) - { - if (action_record == 0) - { - /* This indicates a cleanup rather than an exception - handler. */ - CONTINUE_UNWINDING; - } - - return _URC_HANDLER_FOUND; - } - - /* It's possible for g to be NULL here for an exception thrown by a - language other than Go. */ - g = runtime_g (); - if (g == NULL) - { - if (!is_foreign) - abort (); - } - else - { - g->exception = ue_header; - g->is_foreign = is_foreign; - } - - _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), - (_Unwind_Ptr) ue_header); - _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0); - _Unwind_SetIP (context, landing_pad); - return _URC_INSTALL_CONTEXT; -} diff --git a/gcc-4.8.1/libgo/runtime/goc2c.c b/gcc-4.8.1/libgo/runtime/goc2c.c deleted file mode 100644 index 87db58f50..000000000 --- a/gcc-4.8.1/libgo/runtime/goc2c.c +++ /dev/null @@ -1,676 +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. - -// +build ignore - -/* - * Translate a .goc file into a .c file. A .goc 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 <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -/* Package path to use. */ -static const char *pkgpath; - -/* Package prefix to use. */ -static const char *prefix; - -/* File and line number */ -static const char *file; -static unsigned int lineno = 1; - -/* List of names and types. */ -struct params { - struct params *next; - char *name; - char *type; -}; - -char *argv0; - -static void -sysfatal(char *fmt, ...) -{ - char buf[256]; - va_list arg; - - va_start(arg, fmt); - vsnprintf(buf, sizeof buf, fmt, arg); - va_end(arg); - - fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "<prog>", buf); - exit(1); -} - -/* Unexpected EOF. */ -static void -bad_eof(void) -{ - sysfatal("%s:%ud: unexpected EOF\n", file, lineno); -} - -/* Out of memory. */ -static void -bad_mem(void) -{ - sysfatal("%s:%ud: out of memory\n", file, lineno); -} - -/* 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; -} - -/* Copy a string into memory without fail. */ -static char * -xstrdup(const char *p) -{ - char *ret = xmalloc(strlen(p) + 1); - strcpy(ret, p); - 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 string or character literals - * or else delimited by whitespace or by [(),{}]. - * The latter are all returned as single characters. - */ -static char * -read_token(void) -{ - int c, q; - 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(c == '"' || c == '\'') { - q = c; - buf[off] = c; - ++off; - while (1) { - if (off+2 >= alc) { // room for c and maybe next char - alc *= 2; - buf = xrealloc(buf, alc + 1); - } - c = getchar_no_eof(); - buf[off] = c; - ++off; - if(c == q) - break; - if(c == '\\') { - buf[off] = getchar_no_eof(); - ++off; - } - } - } else 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) { - if (c == '\n') - lineno--; - 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 (token == NULL) - sysfatal("%s:%ud: no token\n", file, lineno); - if (strcmp(token, "package") != 0) { - sysfatal("%s:%ud: expected \"package\", got \"%s\"\n", - file, lineno, token); - } - 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); - break; - } - 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 != '*') { - /* Convert the Go type "int" to the C type "intgo", - and similarly for "uint". */ - if (strcmp(p, "int") == 0) - return xstrdup("intgo"); - else if (strcmp(p, "uint") == 0) - return xstrdup("uintgo"); - return p; - } - op = p; - pointer_count = 0; - while (*p == '*') { - ++pointer_count; - ++p; - } - - /* Convert the Go type "int" to the C type "intgo", and - similarly for "uint". */ - if (strcmp(p, "int") == 0) - p = (char *) "intgo"; - else if (strcmp(p, "uint") == 0) - p = (char *) "uintgo"; - - 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() -{ - char *token; - struct params *ret, **pp, *p; - - ret = NULL; - pp = &ret; - token = read_token_no_eof(); - if (strcmp(token, ")") != 0) { - while (1) { - p = xmalloc(sizeof(struct params)); - p->name = token; - p->type = read_type(); - p->next = NULL; - *pp = p; - pp = &p->next; - - token = read_token_no_eof(); - if (strcmp(token, ",") != 0) - break; - token = read_token_no_eof(); - } - } - if (strcmp(token, ")") != 0) { - sysfatal("%s:%ud: expected '('\n", - file, lineno); - } - 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) -{ - int lastline; - char *token; - - lastline = -1; - while (1) { - token = read_token(); - if (token == NULL) - return 0; - if (strcmp(token, "func") == 0) { - if(lastline != -1) - printf("\n"); - break; - } - if (lastline != lineno) { - if (lastline == lineno-1) - printf("\n"); - else - printf("\n#line %d \"%s\"\n", lineno, file); - lastline = lineno; - } - printf("%s ", token); - } - - *name = read_token_no_eof(); - - token = read_token(); - if (token == NULL || strcmp(token, "(") != 0) { - sysfatal("%s:%ud: expected \"(\"\n", - file, lineno); - } - *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) { - sysfatal("%s:%ud: expected \"{\"\n", - file, lineno); - } - 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); - } -} - -/* 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__ (GOSYM_PREFIX \""); - if (pkgpath != NULL) - printf("%s", pkgpath); - else if (prefix != NULL) - printf("%s.%s", prefix, package); - else - printf("%s", package); - printf(".%s\");\n", 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) -{ - write_gcc_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) -{ - write_gcc_func_trailer(package, name, 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, ¶ms, &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) -{ - sysfatal("Usage: goc2c [--go-pkgpath PKGPATH] [--go-prefix PREFIX] [file]\n"); -} - -int -main(int argc, char **argv) -{ - char *goarch; - - argv0 = argv[0]; - while(argc > 1 && argv[1][0] == '-') { - if(strcmp(argv[1], "-") == 0) - break; - if (strcmp(argv[1], "--go-pkgpath") == 0 && argc > 2) { - pkgpath = argv[2]; - argc--; - argv++; - } else if (strcmp(argv[1], "--go-prefix") == 0 && argc > 2) { - prefix = argv[2]; - argc--; - argv++; - } else - usage(); - argc--; - argv++; - } - - if(argc <= 1 || strcmp(argv[1], "-") == 0) { - file = "<stdin>"; - process_file(); - exit(0); - } - - if(argc > 2) - usage(); - - file = argv[1]; - if(freopen(file, "r", stdin) == 0) { - sysfatal("open %s: %r\n", file); - } - - printf("// AUTO-GENERATED by autogen.sh; DO NOT EDIT\n\n"); - process_file(); - exit(0); -} diff --git a/gcc-4.8.1/libgo/runtime/iface.goc b/gcc-4.8.1/libgo/runtime/iface.goc deleted file mode 100644 index 7c74e80ac..000000000 --- a/gcc-4.8.1/libgo/runtime/iface.goc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package runtime -#include "runtime.h" -#include "go-type.h" -#include "interface.h" - -typedef struct __go_type_descriptor descriptor; -typedef const struct __go_type_descriptor const_descriptor; -typedef struct __go_interface interface; -typedef struct __go_empty_interface empty_interface; - -// Compare two type descriptors. -func ifacetypeeq(a *descriptor, b *descriptor) (eq bool) { - eq = __go_type_descriptors_equal(a, b); -} - -// Return the descriptor for an empty interface type.n -func efacetype(e empty_interface) (d *const_descriptor) { - return e.__type_descriptor; -} - -// Return the descriptor for a non-empty interface type. -func ifacetype(i interface) (d *const_descriptor) { - if (i.__methods == nil) { - return nil; - } - d = i.__methods[0]; -} - -// Convert an empty interface to an empty interface. -func ifaceE2E2(e empty_interface) (ret empty_interface, ok bool) { - if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) - runtime_panicstring("invalid interface value"); - ret = e; - ok = ret.__type_descriptor != nil; -} - -// Convert a non-empty interface to an empty interface. -func ifaceI2E2(i interface) (ret empty_interface, ok bool) { - if (i.__methods == nil) { - ret.__type_descriptor = nil; - ret.__object = nil; - ok = 0; - } else { - ret.__type_descriptor = i.__methods[0]; - ret.__object = i.__object; - ok = 1; - } -} - -// Convert an empty interface to a non-empty interface. -func ifaceE2I2(inter *descriptor, e empty_interface) (ret interface, ok bool) { - if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) - runtime_panicstring("invalid interface value"); - if (e.__type_descriptor == nil) { - ret.__methods = nil; - ret.__object = nil; - ok = 0; - } else { - ret.__methods = __go_convert_interface_2(inter, - e.__type_descriptor, - 1); - ret.__object = e.__object; - ok = ret.__methods != nil; - } -} - -// Convert a non-empty interface to a non-empty interface. -func ifaceI2I2(inter *descriptor, i interface) (ret interface, ok bool) { - if (i.__methods == nil) { - ret.__methods = nil; - ret.__object = nil; - ok = 0; - } else { - ret.__methods = __go_convert_interface_2(inter, - i.__methods[0], 1); - ret.__object = i.__object; - ok = ret.__methods != nil; - } -} - -// Convert an empty interface to a pointer type. -func ifaceE2T2P(inter *descriptor, e empty_interface) (ret *void, ok bool) { - if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) - runtime_panicstring("invalid interface value"); - if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) { - ret = nil; - ok = 0; - } else { - ret = e.__object; - ok = 1; - } -} - -// Convert a non-empty interface to a pointer type. -func ifaceI2T2P(inter *descriptor, i interface) (ret *void, ok bool) { - if (i.__methods == nil - || !__go_type_descriptors_equal(inter, i.__methods[0])) { - ret = nil; - ok = 0; - } else { - ret = i.__object; - ok = 1; - } -} - -// Convert an empty interface to a non-pointer type. -func ifaceE2T2(inter *descriptor, e empty_interface, ret *void) (ok bool) { - if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) - runtime_panicstring("invalid interface value"); - if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) { - __builtin_memset(ret, 0, inter->__size); - ok = 0; - } else { - __builtin_memcpy(ret, e.__object, inter->__size); - ok = 1; - } -} - -// Convert a non-empty interface to a non-pointer type. -func ifaceI2T2(inter *descriptor, i interface, ret *void) (ok bool) { - if (i.__methods == nil - || !__go_type_descriptors_equal(inter, i.__methods[0])) { - __builtin_memset(ret, 0, inter->__size); - ok = 0; - } else { - __builtin_memcpy(ret, i.__object, inter->__size); - ok = 1; - } -} - -// Return whether we can convert an interface to a type. -func ifaceI2Tp(to *descriptor, from *descriptor) (ok bool) { - ok = __go_can_convert_to_interface(to, from); -} diff --git a/gcc-4.8.1/libgo/runtime/interface.h b/gcc-4.8.1/libgo/runtime/interface.h deleted file mode 100644 index f3068a656..000000000 --- a/gcc-4.8.1/libgo/runtime/interface.h +++ /dev/null @@ -1,57 +0,0 @@ -/* interface.h -- the interface type for Go. - - 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. */ - -#ifndef LIBGO_INTERFACE_H -#define LIBGO_INTERFACE_H - -struct __go_type_descriptor; - -/* A variable of interface type is an instance of this struct, if the - interface has any methods. */ - -struct __go_interface -{ - /* A pointer to the interface method table. The first pointer is - the type descriptor of the object. Subsequent pointers are - pointers to functions. This is effectively the vtable for this - interface. The function pointers are in the same order as the - list in the internal representation of the interface, which sorts - them by name. */ - const void **__methods; - - /* The object. If the object is a pointer--if the type descriptor - code is GO_PTR or GO_UNSAFE_POINTER--then this field is the value - of the object itself. Otherwise this is a pointer to memory - which holds the value. */ - void *__object; -}; - -/* A variable of an empty interface type is an instance of this - struct. */ - -struct __go_empty_interface -{ - /* The type descriptor of the object. */ - const struct __go_type_descriptor *__type_descriptor; - - /* The object. This is the same as __go_interface above. */ - void *__object; -}; - -extern void * -__go_convert_interface (const struct __go_type_descriptor *, - const struct __go_type_descriptor *); - -extern void * -__go_convert_interface_2 (const struct __go_type_descriptor *, - const struct __go_type_descriptor *, - _Bool may_fail); - -extern _Bool -__go_can_convert_to_interface(const struct __go_type_descriptor *, - const struct __go_type_descriptor *); - -#endif /* !defined(LIBGO_INTERFACE_H) */ diff --git a/gcc-4.8.1/libgo/runtime/lfstack.c b/gcc-4.8.1/libgo/runtime/lfstack.c deleted file mode 100644 index 230ed87c4..000000000 --- a/gcc-4.8.1/libgo/runtime/lfstack.c +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2012 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. - -// Lock-free stack. - -#include "runtime.h" -#include "arch.h" - -#if __SIZEOF_POINTER__ == 8 -// Amd64 uses 48-bit virtual addresses, 47-th bit is used as kernel/user flag. -// So we use 17msb of pointers as ABA counter. -# define PTR_BITS 47 -#else -# define PTR_BITS 32 -#endif -#define PTR_MASK ((1ull<<PTR_BITS)-1) -#define CNT_MASK (0ull-1) - -#if __SIZEOF_POINTER__ == 8 && (defined(__sparc__) || (defined(__sun__) && defined(__amd64__))) -// SPARC64 and Solaris on AMD64 uses all 64 bits of virtual addresses. -// Use low-order three bits as ABA counter. -// http://docs.oracle.com/cd/E19120-01/open.solaris/816-5138/6mba6ua5p/index.html -#undef PTR_BITS -#undef CNT_MASK -#undef PTR_MASK -#define PTR_BITS 0 -#define CNT_MASK 7 -#define PTR_MASK ((0ull-1)<<3) -#endif - -void -runtime_lfstackpush(uint64 *head, LFNode *node) -{ - uint64 old, new; - - if((uintptr)node != ((uintptr)node&PTR_MASK)) { - runtime_printf("p=%p\n", node); - runtime_throw("runtime_lfstackpush: invalid pointer"); - } - - node->pushcnt++; - new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS); - old = runtime_atomicload64(head); - for(;;) { - node->next = (LFNode*)(uintptr)(old&PTR_MASK); - if(runtime_cas64(head, &old, new)) - break; - } -} - -LFNode* -runtime_lfstackpop(uint64 *head) -{ - LFNode *node, *node2; - uint64 old, new; - - old = runtime_atomicload64(head); - for(;;) { - if(old == 0) - return nil; - node = (LFNode*)(uintptr)(old&PTR_MASK); - node2 = runtime_atomicloadp(&node->next); - new = 0; - if(node2 != nil) - new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<<PTR_BITS); - if(runtime_cas64(head, &old, new)) - return node; - } -} - -LFNode* runtime_lfstackpop2(uint64*) - __asm__ (GOSYM_PREFIX "runtime.lfstackpop2"); - -LFNode* -runtime_lfstackpop2(uint64 *head) -{ - return runtime_lfstackpop(head); -} diff --git a/gcc-4.8.1/libgo/runtime/lock_futex.c b/gcc-4.8.1/libgo/runtime/lock_futex.c deleted file mode 100644 index 5374aff6d..000000000 --- a/gcc-4.8.1/libgo/runtime/lock_futex.c +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2011 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. - -// +build freebsd linux - -#include "runtime.h" - -// This implementation depends on OS-specific implementations of -// -// runtime_futexsleep(uint32 *addr, uint32 val, int64 ns) -// Atomically, -// if(*addr == val) sleep -// Might be woken up spuriously; that's allowed. -// Don't sleep longer than ns; ns < 0 means forever. -// -// runtime_futexwakeup(uint32 *addr, uint32 cnt) -// If any procs are sleeping on addr, wake up at most cnt. - -enum -{ - MUTEX_UNLOCKED = 0, - MUTEX_LOCKED = 1, - MUTEX_SLEEPING = 2, - - ACTIVE_SPIN = 4, - ACTIVE_SPIN_CNT = 30, - PASSIVE_SPIN = 1, -}; - -// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING. -// MUTEX_SLEEPING means that there is presumably at least one sleeping thread. -// Note that there can be spinning threads during all states - they do not -// affect mutex's state. -void -runtime_lock(Lock *l) -{ - uint32 i, v, wait, spin; - - if(runtime_m()->locks++ < 0) - runtime_throw("runtime_lock: lock count"); - - // Speculative grab for lock. - v = runtime_xchg(&l->key, MUTEX_LOCKED); - if(v == MUTEX_UNLOCKED) - return; - - // wait is either MUTEX_LOCKED or MUTEX_SLEEPING - // depending on whether there is a thread sleeping - // on this mutex. If we ever change l->key from - // MUTEX_SLEEPING to some other value, we must be - // careful to change it back to MUTEX_SLEEPING before - // returning, to ensure that the sleeping thread gets - // its wakeup call. - wait = v; - - // On uniprocessor's, no point spinning. - // On multiprocessors, spin for ACTIVE_SPIN attempts. - spin = 0; - if(runtime_ncpu > 1) - spin = ACTIVE_SPIN; - - for(;;) { - // Try for lock, spinning. - for(i = 0; i < spin; i++) { - while(l->key == MUTEX_UNLOCKED) - if(runtime_cas(&l->key, MUTEX_UNLOCKED, wait)) - return; - runtime_procyield(ACTIVE_SPIN_CNT); - } - - // Try for lock, rescheduling. - for(i=0; i < PASSIVE_SPIN; i++) { - while(l->key == MUTEX_UNLOCKED) - if(runtime_cas(&l->key, MUTEX_UNLOCKED, wait)) - return; - runtime_osyield(); - } - - // Sleep. - v = runtime_xchg(&l->key, MUTEX_SLEEPING); - if(v == MUTEX_UNLOCKED) - return; - wait = MUTEX_SLEEPING; - runtime_futexsleep(&l->key, MUTEX_SLEEPING, -1); - } -} - -void -runtime_unlock(Lock *l) -{ - uint32 v; - - if(--runtime_m()->locks < 0) - runtime_throw("runtime_unlock: lock count"); - - v = runtime_xchg(&l->key, MUTEX_UNLOCKED); - if(v == MUTEX_UNLOCKED) - runtime_throw("unlock of unlocked lock"); - if(v == MUTEX_SLEEPING) - runtime_futexwakeup(&l->key, 1); -} - -// One-time notifications. -void -runtime_noteclear(Note *n) -{ - n->key = 0; -} - -void -runtime_notewakeup(Note *n) -{ - if(runtime_xchg(&n->key, 1)) - runtime_throw("notewakeup - double wakeup"); - runtime_futexwakeup(&n->key, 1); -} - -void -runtime_notesleep(Note *n) -{ - if(runtime_m()->profilehz > 0) - runtime_setprof(false); - while(runtime_atomicload(&n->key) == 0) - runtime_futexsleep(&n->key, 0, -1); - if(runtime_m()->profilehz > 0) - runtime_setprof(true); -} - -void -runtime_notetsleep(Note *n, int64 ns) -{ - int64 deadline, now; - - if(ns < 0) { - runtime_notesleep(n); - return; - } - - if(runtime_atomicload(&n->key) != 0) - return; - - if(runtime_m()->profilehz > 0) - runtime_setprof(false); - deadline = runtime_nanotime() + ns; - for(;;) { - runtime_futexsleep(&n->key, 0, ns); - if(runtime_atomicload(&n->key) != 0) - break; - now = runtime_nanotime(); - if(now >= deadline) - break; - ns = deadline - now; - } - if(runtime_m()->profilehz > 0) - runtime_setprof(true); -} diff --git a/gcc-4.8.1/libgo/runtime/lock_sema.c b/gcc-4.8.1/libgo/runtime/lock_sema.c deleted file mode 100644 index 8c4b3973b..000000000 --- a/gcc-4.8.1/libgo/runtime/lock_sema.c +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2011 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. - -// +build darwin netbsd openbsd plan9 windows - -#include "runtime.h" - -// This implementation depends on OS-specific implementations of -// -// uintptr runtime_semacreate(void) -// Create a semaphore, which will be assigned to m->waitsema. -// The zero value is treated as absence of any semaphore, -// so be sure to return a non-zero value. -// -// int32 runtime_semasleep(int64 ns) -// If ns < 0, acquire m->waitsema and return 0. -// If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds. -// Return 0 if the semaphore was acquired, -1 if interrupted or timed out. -// -// int32 runtime_semawakeup(M *mp) -// Wake up mp, which is or will soon be sleeping on mp->waitsema. -// - -enum -{ - LOCKED = 1, - - ACTIVE_SPIN = 4, - ACTIVE_SPIN_CNT = 30, - PASSIVE_SPIN = 1, -}; - -void -runtime_lock(Lock *l) -{ - M *m; - uintptr v; - uint32 i, spin; - - m = runtime_m(); - if(m->locks++ < 0) - runtime_throw("runtime_lock: lock count"); - - // Speculative grab for lock. - if(runtime_casp(&l->waitm, nil, (void*)LOCKED)) - return; - - if(m->waitsema == 0) - m->waitsema = runtime_semacreate(); - - // On uniprocessor's, no point spinning. - // On multiprocessors, spin for ACTIVE_SPIN attempts. - spin = 0; - if(runtime_ncpu > 1) - spin = ACTIVE_SPIN; - - for(i=0;; i++) { - v = (uintptr)runtime_atomicloadp(&l->waitm); - if((v&LOCKED) == 0) { -unlocked: - if(runtime_casp(&l->waitm, (void*)v, (void*)(v|LOCKED))) - return; - i = 0; - } - if(i<spin) - runtime_procyield(ACTIVE_SPIN_CNT); - else if(i<spin+PASSIVE_SPIN) - runtime_osyield(); - else { - // Someone else has it. - // l->waitm points to a linked list of M's waiting - // for this lock, chained through m->nextwaitm. - // Queue this M. - for(;;) { - m->nextwaitm = (void*)(v&~LOCKED); - if(runtime_casp(&l->waitm, (void*)v, (void*)((uintptr)m|LOCKED))) - break; - v = (uintptr)runtime_atomicloadp(&l->waitm); - if((v&LOCKED) == 0) - goto unlocked; - } - if(v&LOCKED) { - // Queued. Wait. - runtime_semasleep(-1); - i = 0; - } - } - } -} - -void -runtime_unlock(Lock *l) -{ - uintptr v; - M *mp; - - if(--runtime_m()->locks < 0) - runtime_throw("runtime_unlock: lock count"); - - for(;;) { - v = (uintptr)runtime_atomicloadp(&l->waitm); - if(v == LOCKED) { - if(runtime_casp(&l->waitm, (void*)LOCKED, nil)) - break; - } else { - // Other M's are waiting for the lock. - // Dequeue an M. - mp = (void*)(v&~LOCKED); - if(runtime_casp(&l->waitm, (void*)v, mp->nextwaitm)) { - // Dequeued an M. Wake it. - runtime_semawakeup(mp); - break; - } - } - } -} - -// One-time notifications. -void -runtime_noteclear(Note *n) -{ - n->waitm = nil; -} - -void -runtime_notewakeup(Note *n) -{ - M *mp; - - do - mp = runtime_atomicloadp(&n->waitm); - while(!runtime_casp(&n->waitm, mp, (void*)LOCKED)); - - // Successfully set waitm to LOCKED. - // What was it before? - if(mp == nil) { - // Nothing was waiting. Done. - } else if(mp == (M*)LOCKED) { - // Two notewakeups! Not allowed. - runtime_throw("notewakeup - double wakeup"); - } else { - // Must be the waiting m. Wake it up. - runtime_semawakeup(mp); - } -} - -void -runtime_notesleep(Note *n) -{ - M *m; - - m = runtime_m(); - if(m->waitsema == 0) - m->waitsema = runtime_semacreate(); - if(!runtime_casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup) - if(n->waitm != (void*)LOCKED) - runtime_throw("notesleep - waitm out of sync"); - return; - } - // Queued. Sleep. - if(m->profilehz > 0) - runtime_setprof(false); - runtime_semasleep(-1); - if(m->profilehz > 0) - runtime_setprof(true); -} - -void -runtime_notetsleep(Note *n, int64 ns) -{ - M *m; - M *mp; - int64 deadline, now; - - if(ns < 0) { - runtime_notesleep(n); - return; - } - - m = runtime_m(); - if(m->waitsema == 0) - m->waitsema = runtime_semacreate(); - - // Register for wakeup on n->waitm. - if(!runtime_casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup already) - if(n->waitm != (void*)LOCKED) - runtime_throw("notetsleep - waitm out of sync"); - return; - } - - if(m->profilehz > 0) - runtime_setprof(false); - deadline = runtime_nanotime() + ns; - for(;;) { - // Registered. Sleep. - if(runtime_semasleep(ns) >= 0) { - // Acquired semaphore, semawakeup unregistered us. - // Done. - if(m->profilehz > 0) - runtime_setprof(true); - return; - } - - // Interrupted or timed out. Still registered. Semaphore not acquired. - now = runtime_nanotime(); - if(now >= deadline) - break; - - // Deadline hasn't arrived. Keep sleeping. - ns = deadline - now; - } - - if(m->profilehz > 0) - runtime_setprof(true); - - // Deadline arrived. Still registered. Semaphore not acquired. - // Want to give up and return, but have to unregister first, - // so that any notewakeup racing with the return does not - // try to grant us the semaphore when we don't expect it. - for(;;) { - mp = runtime_atomicloadp(&n->waitm); - if(mp == m) { - // No wakeup yet; unregister if possible. - if(runtime_casp(&n->waitm, mp, nil)) - return; - } else if(mp == (M*)LOCKED) { - // Wakeup happened so semaphore is available. - // Grab it to avoid getting out of sync. - if(runtime_semasleep(-1) < 0) - runtime_throw("runtime: unable to acquire - semaphore out of sync"); - return; - } else { - runtime_throw("runtime: unexpected waitm - semaphore out of sync"); - } - } -} diff --git a/gcc-4.8.1/libgo/runtime/malloc.goc b/gcc-4.8.1/libgo/runtime/malloc.goc deleted file mode 100644 index a48464207..000000000 --- a/gcc-4.8.1/libgo/runtime/malloc.goc +++ /dev/null @@ -1,784 +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. - -package runtime -#include <stddef.h> -#include <errno.h> -#include <stdlib.h> -#include "go-alloc.h" -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "interface.h" -#include "go-type.h" -#include "race.h" - -MHeap runtime_mheap; - -int32 runtime_checking; - -extern MStats mstats; // defined in zruntime_def_$GOOS_$GOARCH.go - -extern volatile intgo runtime_MemProfileRate - __asm__ (GOSYM_PREFIX "runtime.MemProfileRate"); - -// 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* -runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed) -{ - M *m; - G *g; - int32 sizeclass; - intgo rate; - MCache *c; - uintptr npages; - MSpan *s; - void *v; - - m = runtime_m(); - g = runtime_g(); - if(g->status == Gsyscall) - dogc = 0; - if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && g->status != Gsyscall) { - runtime_gosched(); - m = runtime_m(); - } - if(m->mallocing) - runtime_throw("malloc/free - deadlock"); - m->mallocing = 1; - if(size == 0) - size = 1; - - if(DebugTypeAtBlockEnd) - size += sizeof(uintptr); - - c = m->mcache; - c->local_nmalloc++; - if(size <= MaxSmallSize) { - // Allocate from mcache free lists. - sizeclass = runtime_SizeToClass(size); - size = runtime_class_to_size[sizeclass]; - v = runtime_MCache_Alloc(c, sizeclass, size, zeroed); - if(v == nil) - runtime_throw("out of memory"); - c->local_alloc += size; - c->local_total_alloc += size; - c->local_by_size[sizeclass].nmalloc++; - } else { - // TODO(rsc): Report tracebacks for very large allocations. - - // Allocate directly from heap. - npages = size >> PageShift; - if((size & PageMask) != 0) - npages++; - s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, zeroed); - if(s == nil) - runtime_throw("out of memory"); - size = npages<<PageShift; - c->local_alloc += size; - c->local_total_alloc += size; - v = (void*)(s->start << PageShift); - - // setup for mark sweep - runtime_markspan(v, 0, 0, true); - } - - if (sizeof(void*) == 4 && c->local_total_alloc >= (1<<30)) { - // purge cache stats to prevent overflow - runtime_lock(&runtime_mheap); - runtime_purgecachedstats(c); - runtime_unlock(&runtime_mheap); - } - - if(!(flag & FlagNoGC)) - runtime_markallocated(v, size, (flag&FlagNoPointers) != 0); - - if(DebugTypeAtBlockEnd) - *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = 0; - - m->mallocing = 0; - - if(!(flag & FlagNoProfiling) && (rate = runtime_MemProfileRate) > 0) { - if(size >= (uint32) rate) - goto profile; - if((uint32) m->mcache->next_sample > size) - m->mcache->next_sample -= size; - else { - // pick next profile time - // If you change this, also change allocmcache. - if(rate > 0x3fffffff) // make 2*rate not overflow - rate = 0x3fffffff; - m->mcache->next_sample = runtime_fastrand1() % (2*rate); - profile: - runtime_setblockspecial(v, true); - runtime_MProf_Malloc(v, size); - } - } - - if(dogc && mstats.heap_alloc >= mstats.next_gc) - runtime_gc(0); - - if(raceenabled) { - runtime_racemalloc(v, size, m->racepc); - m->racepc = nil; - } - return v; -} - -void* -__go_alloc(uintptr size) -{ - return runtime_mallocgc(size, 0, 0, 1); -} - -// Free the object whose base pointer is v. -void -__go_free(void *v) -{ - M *m; - int32 sizeclass; - MSpan *s; - MCache *c; - uint32 prof; - uintptr size; - - if(v == nil) - return; - - // If you change this also change mgc0.c:/^sweep, - // which has a copy of the guts of free. - - m = runtime_m(); - if(m->mallocing) - runtime_throw("malloc/free - deadlock"); - m->mallocing = 1; - - if(!runtime_mlookup(v, nil, nil, &s)) { - runtime_printf("free %p: not an allocated block\n", v); - runtime_throw("free runtime_mlookup"); - } - prof = runtime_blockspecial(v); - - if(raceenabled) - runtime_racefree(v); - - // Find size class for v. - sizeclass = s->sizeclass; - c = m->mcache; - if(sizeclass == 0) { - // Large object. - size = s->npages<<PageShift; - *(uintptr*)(s->start<<PageShift) = 1; // mark as "needs to be zeroed" - // Must mark v freed before calling unmarkspan and MHeap_Free: - // they might coalesce v into other spans and change the bitmap further. - runtime_markfreed(v, size); - runtime_unmarkspan(v, 1<<PageShift); - runtime_MHeap_Free(&runtime_mheap, s, 1); - } else { - // Small object. - size = runtime_class_to_size[sizeclass]; - if(size > sizeof(uintptr)) - ((uintptr*)v)[1] = 1; // mark as "needs to be zeroed" - // Must mark v freed before calling MCache_Free: - // it might coalesce v and other blocks into a bigger span - // and change the bitmap further. - runtime_markfreed(v, size); - c->local_by_size[sizeclass].nfree++; - runtime_MCache_Free(c, v, sizeclass, size); - } - c->local_nfree++; - c->local_alloc -= size; - if(prof) - runtime_MProf_Free(v, size); - m->mallocing = 0; -} - -int32 -runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp) -{ - M *m; - uintptr n, i; - byte *p; - MSpan *s; - - m = runtime_m(); - - m->mcache->local_nlookup++; - if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) { - // purge cache stats to prevent overflow - runtime_lock(&runtime_mheap); - runtime_purgecachedstats(m->mcache); - runtime_unlock(&runtime_mheap); - } - - s = runtime_MHeap_LookupMaybe(&runtime_mheap, v); - if(sp) - *sp = s; - if(s == nil) { - runtime_checkfreed(v, 1); - if(base) - *base = nil; - if(size) - *size = 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; - return 1; - } - - if((byte*)v >= (byte*)s->limit) { - // pointers past the last block do not count as pointers. - return 0; - } - - n = s->elemsize; - if(base) { - i = ((byte*)v - p)/n; - *base = p + i*n; - } - if(size) - *size = n; - - return 1; -} - -MCache* -runtime_allocmcache(void) -{ - intgo rate; - MCache *c; - - runtime_lock(&runtime_mheap); - c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc); - mstats.mcache_inuse = runtime_mheap.cachealloc.inuse; - mstats.mcache_sys = runtime_mheap.cachealloc.sys; - runtime_unlock(&runtime_mheap); - runtime_memclr((byte*)c, sizeof(*c)); - - // Set first allocation sample size. - rate = runtime_MemProfileRate; - if(rate > 0x3fffffff) // make 2*rate not overflow - rate = 0x3fffffff; - if(rate != 0) - c->next_sample = runtime_fastrand1() % (2*rate); - - return c; -} - -void -runtime_freemcache(MCache *c) -{ - runtime_MCache_ReleaseAll(c); - runtime_lock(&runtime_mheap); - runtime_purgecachedstats(c); - runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c); - runtime_unlock(&runtime_mheap); -} - -void -runtime_purgecachedstats(MCache *c) -{ - // Protected by either heap or GC lock. - mstats.heap_alloc += c->local_cachealloc; - c->local_cachealloc = 0; - mstats.heap_objects += c->local_objects; - c->local_objects = 0; - mstats.nmalloc += c->local_nmalloc; - c->local_nmalloc = 0; - mstats.nfree += c->local_nfree; - c->local_nfree = 0; - mstats.nlookup += c->local_nlookup; - c->local_nlookup = 0; - mstats.alloc += c->local_alloc; - c->local_alloc= 0; - mstats.total_alloc += c->local_total_alloc; - c->local_total_alloc= 0; -} - -extern uintptr runtime_sizeof_C_MStats - __asm__ (GOSYM_PREFIX "runtime.Sizeof_C_MStats"); - -#define MaxArena32 (2U<<30) - -void -runtime_mallocinit(void) -{ - byte *p; - uintptr arena_size, bitmap_size; - extern byte end[]; - byte *want; - uintptr limit; - - runtime_sizeof_C_MStats = sizeof(MStats); - - p = nil; - arena_size = 0; - bitmap_size = 0; - - // for 64-bit build - USED(p); - USED(arena_size); - USED(bitmap_size); - - runtime_InitSizes(); - - limit = runtime_memlimit(); - - // Set up the allocation arena, a contiguous area of memory where - // allocated data will be found. The arena begins with a bitmap large - // enough to hold 4 bits per allocated word. - if(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) { - // On a 64-bit machine, allocate from a single contiguous reservation. - // 128 GB (MaxMem) should be big enough for now. - // - // The code will work with the reservation at any address, but ask - // SysReserve to use 0x000000c000000000 if possible. - // Allocating a 128 GB region takes away 37 bits, and the amd64 - // doesn't let us choose the top 17 bits, so that leaves the 11 bits - // in the middle of 0x00c0 for us to choose. Choosing 0x00c0 means - // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x0x00df. - // In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid - // UTF-8 sequences, and they are otherwise as far away from - // ff (likely a common byte) as possible. An earlier attempt to use 0x11f8 - // caused out of memory errors on OS X during thread allocations. - // These choices are both for debuggability and to reduce the - // odds of the conservative garbage collector not collecting memory - // because some non-pointer block of memory had a bit pattern - // that matched a memory address. - // - // Actually we reserve 136 GB (because the bitmap ends up being 8 GB) - // but it hardly matters: e0 00 is not valid UTF-8 either. - // - // If this fails we fall back to the 32 bit memory mechanism - arena_size = MaxMem; - bitmap_size = arena_size / (sizeof(void*)*8/4); - p = runtime_SysReserve((void*)(0x00c0ULL<<32), bitmap_size + arena_size); - } - if (p == nil) { - // On a 32-bit machine, we can't typically get away - // with a giant virtual address space reservation. - // Instead we map the memory information bitmap - // immediately after the data segment, large enough - // to handle another 2GB of mappings (256 MB), - // along with a reservation for another 512 MB of memory. - // When that gets used up, we'll start asking the kernel - // for any memory anywhere and hope it's in the 2GB - // following the bitmap (presumably the executable begins - // near the bottom of memory, so we'll have to use up - // most of memory before the kernel resorts to giving out - // memory before the beginning of the text segment). - // - // Alternatively we could reserve 512 MB bitmap, enough - // for 4GB of mappings, and then accept any memory the - // kernel threw at us, but normally that's a waste of 512 MB - // of address space, which is probably too much in a 32-bit world. - bitmap_size = MaxArena32 / (sizeof(void*)*8/4); - arena_size = 512<<20; - if(limit > 0 && arena_size+bitmap_size > limit) { - bitmap_size = (limit / 9) & ~((1<<PageShift) - 1); - arena_size = bitmap_size * 8; - } - - // SysReserve treats the address we ask for, end, as a hint, - // not as an absolute requirement. If we ask for the end - // of the data segment but the operating system requires - // a little more space before we can start allocating, it will - // give out a slightly higher pointer. Except QEMU, which - // is buggy, as usual: it won't adjust the pointer upward. - // So adjust it upward a little bit ourselves: 1/4 MB to get - // away from the running binary image and then round up - // to a MB boundary. - want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1)); - if(0xffffffff - (uintptr)want <= bitmap_size + arena_size) - want = 0; - p = runtime_SysReserve(want, bitmap_size + arena_size); - if(p == nil) - runtime_throw("runtime: cannot reserve arena virtual address space"); - if((uintptr)p & (((uintptr)1<<PageShift)-1)) - runtime_printf("runtime: SysReserve returned unaligned address %p; asked for %p", p, bitmap_size+arena_size); - } - if((uintptr)p & (((uintptr)1<<PageShift)-1)) - runtime_throw("runtime: SysReserve returned unaligned address"); - - runtime_mheap.bitmap = p; - runtime_mheap.arena_start = p + bitmap_size; - runtime_mheap.arena_used = runtime_mheap.arena_start; - runtime_mheap.arena_end = runtime_mheap.arena_start + arena_size; - - // Initialize the rest of the allocator. - runtime_MHeap_Init(&runtime_mheap, runtime_SysAlloc); - runtime_m()->mcache = runtime_allocmcache(); - - // See if it works. - runtime_free(runtime_malloc(1)); -} - -void* -runtime_MHeap_SysAlloc(MHeap *h, uintptr n) -{ - byte *p; - - - if(n > (uintptr)(h->arena_end - h->arena_used)) { - // We are in 32-bit mode, maybe we didn't use all possible address space yet. - // Reserve some more space. - byte *new_end; - uintptr needed; - - needed = (uintptr)h->arena_used + n - (uintptr)h->arena_end; - // Round wanted arena size to a multiple of 256MB. - needed = (needed + (256<<20) - 1) & ~((256<<20)-1); - new_end = h->arena_end + needed; - if(new_end <= h->arena_start + MaxArena32) { - p = runtime_SysReserve(h->arena_end, new_end - h->arena_end); - if(p == h->arena_end) - h->arena_end = new_end; - } - } - if(n <= (uintptr)(h->arena_end - h->arena_used)) { - // Keep taking from our reservation. - p = h->arena_used; - runtime_SysMap(p, n); - h->arena_used += n; - runtime_MHeap_MapBits(h); - if(raceenabled) - runtime_racemapshadow(p, n); - return p; - } - - // If using 64-bit, our reservation is all we have. - if(sizeof(void*) == 8 && (uintptr)h->bitmap >= 0xffffffffU) - return nil; - - // On 32-bit, once the reservation is gone we can - // try to get memory at a location chosen by the OS - // and hope that it is in the range we allocated bitmap for. - p = runtime_SysAlloc(n); - if(p == nil) - return nil; - - if(p < h->arena_start || (uintptr)(p+n - h->arena_start) >= MaxArena32) { - runtime_printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n", - p, h->arena_start, h->arena_start+MaxArena32); - runtime_SysFree(p, n); - return nil; - } - - if(p+n > h->arena_used) { - h->arena_used = p+n; - if(h->arena_used > h->arena_end) - h->arena_end = h->arena_used; - runtime_MHeap_MapBits(h); - if(raceenabled) - runtime_racemapshadow(p, n); - } - - return p; -} - -static Lock settype_lock; - -void -runtime_settype_flush(M *mp, bool sysalloc) -{ - uintptr *buf, *endbuf; - uintptr size, ofs, j, t; - uintptr ntypes, nbytes2, nbytes3; - uintptr *data2; - byte *data3; - bool sysalloc3; - void *v; - uintptr typ, p; - MSpan *s; - - buf = mp->settype_buf; - endbuf = buf + mp->settype_bufsize; - - runtime_lock(&settype_lock); - while(buf < endbuf) { - v = (void*)*buf; - *buf = 0; - buf++; - typ = *buf; - buf++; - - // (Manually inlined copy of runtime_MHeap_Lookup) - p = (uintptr)v>>PageShift; - if(sizeof(void*) == 8) - p -= (uintptr)runtime_mheap.arena_start >> PageShift; - s = runtime_mheap.map[p]; - - if(s->sizeclass == 0) { - s->types.compression = MTypes_Single; - s->types.data = typ; - continue; - } - - size = s->elemsize; - ofs = ((uintptr)v - (s->start<<PageShift)) / size; - - switch(s->types.compression) { - case MTypes_Empty: - ntypes = (s->npages << PageShift) / size; - nbytes3 = 8*sizeof(uintptr) + 1*ntypes; - - if(!sysalloc) { - data3 = runtime_mallocgc(nbytes3, FlagNoPointers, 0, 1); - } else { - data3 = runtime_SysAlloc(nbytes3); - if(0) runtime_printf("settype(0->3): SysAlloc(%x) --> %p\n", (uint32)nbytes3, data3); - } - - s->types.compression = MTypes_Bytes; - s->types.sysalloc = sysalloc; - s->types.data = (uintptr)data3; - - ((uintptr*)data3)[1] = typ; - data3[8*sizeof(uintptr) + ofs] = 1; - break; - - case MTypes_Words: - ((uintptr*)s->types.data)[ofs] = typ; - break; - - case MTypes_Bytes: - data3 = (byte*)s->types.data; - for(j=1; j<8; j++) { - if(((uintptr*)data3)[j] == typ) { - break; - } - if(((uintptr*)data3)[j] == 0) { - ((uintptr*)data3)[j] = typ; - break; - } - } - if(j < 8) { - data3[8*sizeof(uintptr) + ofs] = j; - } else { - ntypes = (s->npages << PageShift) / size; - nbytes2 = ntypes * sizeof(uintptr); - - if(!sysalloc) { - data2 = runtime_mallocgc(nbytes2, FlagNoPointers, 0, 1); - } else { - data2 = runtime_SysAlloc(nbytes2); - if(0) runtime_printf("settype.(3->2): SysAlloc(%x) --> %p\n", (uint32)nbytes2, data2); - } - - sysalloc3 = s->types.sysalloc; - - s->types.compression = MTypes_Words; - s->types.sysalloc = sysalloc; - s->types.data = (uintptr)data2; - - // Move the contents of data3 to data2. Then deallocate data3. - for(j=0; j<ntypes; j++) { - t = data3[8*sizeof(uintptr) + j]; - t = ((uintptr*)data3)[t]; - data2[j] = t; - } - if(sysalloc3) { - nbytes3 = 8*sizeof(uintptr) + 1*ntypes; - if(0) runtime_printf("settype.(3->2): SysFree(%p,%x)\n", data3, (uint32)nbytes3); - runtime_SysFree(data3, nbytes3); - } - - data2[ofs] = typ; - } - break; - } - } - runtime_unlock(&settype_lock); - - mp->settype_bufsize = 0; -} - -// It is forbidden to use this function if it is possible that -// explicit deallocation via calling runtime_free(v) may happen. -void -runtime_settype(void *v, uintptr t) -{ - M *mp; - uintptr *buf; - uintptr i; - MSpan *s; - - if(t == 0) - runtime_throw("settype: zero type"); - - mp = runtime_m(); - buf = mp->settype_buf; - i = mp->settype_bufsize; - buf[i+0] = (uintptr)v; - buf[i+1] = t; - i += 2; - mp->settype_bufsize = i; - - if(i == nelem(mp->settype_buf)) { - runtime_settype_flush(mp, false); - } - - if(DebugTypeAtBlockEnd) { - s = runtime_MHeap_Lookup(&runtime_mheap, v); - *(uintptr*)((uintptr)v+s->elemsize-sizeof(uintptr)) = t; - } -} - -void -runtime_settype_sysfree(MSpan *s) -{ - uintptr ntypes, nbytes; - - if(!s->types.sysalloc) - return; - - nbytes = (uintptr)-1; - - switch (s->types.compression) { - case MTypes_Words: - ntypes = (s->npages << PageShift) / s->elemsize; - nbytes = ntypes * sizeof(uintptr); - break; - case MTypes_Bytes: - ntypes = (s->npages << PageShift) / s->elemsize; - nbytes = 8*sizeof(uintptr) + 1*ntypes; - break; - } - - if(nbytes != (uintptr)-1) { - if(0) runtime_printf("settype: SysFree(%p,%x)\n", (void*)s->types.data, (uint32)nbytes); - runtime_SysFree((void*)s->types.data, nbytes); - } -} - -uintptr -runtime_gettype(void *v) -{ - MSpan *s; - uintptr t, ofs; - byte *data; - - s = runtime_MHeap_LookupMaybe(&runtime_mheap, v); - if(s != nil) { - t = 0; - switch(s->types.compression) { - case MTypes_Empty: - break; - case MTypes_Single: - t = s->types.data; - break; - case MTypes_Words: - ofs = (uintptr)v - (s->start<<PageShift); - t = ((uintptr*)s->types.data)[ofs/s->elemsize]; - break; - case MTypes_Bytes: - ofs = (uintptr)v - (s->start<<PageShift); - data = (byte*)s->types.data; - t = data[8*sizeof(uintptr) + ofs/s->elemsize]; - t = ((uintptr*)data)[t]; - break; - default: - runtime_throw("runtime_gettype: invalid compression kind"); - } - if(0) { - runtime_lock(&settype_lock); - runtime_printf("%p -> %d,%X\n", v, (int32)s->types.compression, (int64)t); - runtime_unlock(&settype_lock); - } - return t; - } - return 0; -} - -// Runtime stubs. - -void* -runtime_mal(uintptr n) -{ - return runtime_mallocgc(n, 0, 1, 1); -} - -void * -runtime_new(const Type *typ) -{ - void *ret; - uint32 flag; - - if(raceenabled) - runtime_m()->racepc = runtime_getcallerpc(&typ); - - if(typ->__size == 0) { - // All 0-length allocations use this pointer. - // The language does not require the allocations to - // have distinct values. - ret = (uint8*)&runtime_zerobase; - } else { - flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0; - ret = runtime_mallocgc(typ->__size, flag, 1, 1); - - if(UseSpanType && !flag) { - if(false) { - runtime_printf("new %S: %p\n", *typ->__reflection, ret); - } - runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject); - } - } - - return ret; -} - -func GC() { - runtime_gc(1); -} - -func SetFinalizer(obj Eface, finalizer Eface) { - byte *base; - uintptr size; - const FuncType *ft; - - if(obj.__type_descriptor == nil) { - runtime_printf("runtime.SetFinalizer: first argument is nil interface\n"); - goto throw; - } - if(obj.__type_descriptor->__code != GO_PTR) { - runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.__type_descriptor->__reflection); - goto throw; - } - if(!runtime_mlookup(obj.__object, &base, &size, nil) || obj.__object != base) { - runtime_printf("runtime.SetFinalizer: pointer not at beginning of allocated block\n"); - goto throw; - } - ft = nil; - if(finalizer.__type_descriptor != nil) { - if(finalizer.__type_descriptor->__code != GO_FUNC) - goto badfunc; - ft = (const FuncType*)finalizer.__type_descriptor; - if(ft->__dotdotdot || ft->__in.__count != 1 || !__go_type_descriptors_equal(*(Type**)ft->__in.__values, obj.__type_descriptor)) - goto badfunc; - } - - if(!runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft)) { - runtime_printf("runtime.SetFinalizer: finalizer already set\n"); - goto throw; - } - return; - -badfunc: - runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.__type_descriptor->__reflection, *obj.__type_descriptor->__reflection); -throw: - runtime_throw("runtime.SetFinalizer"); -} diff --git a/gcc-4.8.1/libgo/runtime/malloc.h b/gcc-4.8.1/libgo/runtime/malloc.h deleted file mode 100644 index a82077420..000000000 --- a/gcc-4.8.1/libgo/runtime/malloc.h +++ /dev/null @@ -1,508 +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. -// 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. -// -// The small objects on the MCache and MCentral free lists -// may or may not be zeroed. They are zeroed if and only if -// the second word of the object is zero. The spans in the -// page heap are always zeroed. When a span full of objects -// is returned to the page heap, the objects that need to be -// are zeroed first. There are two main benefits to delaying the -// zeroing this way: -// -// 1. stack frames allocated from the small object lists -// can avoid zeroing altogether. -// 2. the cost of zeroing when reusing a small object is -// charged to the mutator, not the garbage collector. -// -// 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 MCentral MCentral; -typedef struct MHeap MHeap; -typedef struct MSpan MSpan; -typedef struct MStats MStats; -typedef struct MLink MLink; -typedef struct MTypes MTypes; - -enum -{ - PageShift = 12, - PageSize = 1<<PageShift, - PageMask = PageSize - 1, -}; -typedef uintptr PageID; // address >> PageShift - -enum -{ - // Computed constant. The definition of MaxSmallSize and the - // algorithm in msize.c produce some number of different allocation - // size classes. NumSizeClasses is that number. It's needed here - // because there are static arrays of this length; when msize runs its - // size choosing algorithm it double-checks that NumSizeClasses agrees. - NumSizeClasses = 61, - - // Tunable constants. - 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 - - // Number of bits in page to span calculations (4k pages). - // On 64-bit, we limit the arena to 128GB, or 37 bits. - // On 32-bit, we don't bother limiting anything, so we use the full 32-bit address. -#if __SIZEOF_POINTER__ == 8 - MHeapMap_Bits = 37 - PageShift, -#else - MHeapMap_Bits = 32 - PageShift, -#endif - - // Max number of threads to run garbage collection. - // 2, 3, and 4 are all plausible maximums depending - // on the hardware details of the machine. The garbage - // collector scales well to 8 cpus. - MaxGcproc = 8, -}; - -// Maximum memory allocation size, a hint for callers. -// This must be a #define instead of an enum because it -// is so large. -#if __SIZEOF_POINTER__ == 8 -#define MaxMem (1ULL<<(MHeapMap_Bits+PageShift)) /* 128 GB */ -#else -#define MaxMem ((uintptr)-1) -#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 zeroed memory from the -// operating system, typically on the order of a hundred kilobytes -// or a megabyte. If the pointer argument is non-nil, the caller -// wants a mapping there or nowhere. -// -// 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. -// -// SysReserve reserves address space without allocating memory. -// If the pointer passed to it is non-nil, the caller wants the -// reservation there, but SysReserve can still choose another -// location if that one is unavailable. -// -// SysMap maps previously reserved address space for use. - -void* runtime_SysAlloc(uintptr nbytes); -void runtime_SysFree(void *v, uintptr nbytes); -void runtime_SysUnused(void *v, uintptr nbytes); -void runtime_SysMap(void *v, uintptr nbytes); -void* runtime_SysReserve(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; - uintptr inuse; // in-use bytes now - uintptr sys; // bytes obtained from system -}; - -void runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void *(*alloc)(uintptr), void (*first)(void*, byte*), void *arg); -void* runtime_FixAlloc_Alloc(FixAlloc *f); -void runtime_FixAlloc_Free(FixAlloc *f, void *p); - - -// Statistics. -// Shared with Go: if you edit this structure, also edit type MemStats in mem.go. -struct MStats -{ - // General statistics. - uint64 alloc; // bytes allocated and still in use - uint64 total_alloc; // bytes allocated (even if freed) - uint64 sys; // bytes obtained from system (should be sum of xxx_sys below, no locking, approximate) - uint64 nlookup; // number of pointer lookups - uint64 nmalloc; // number of mallocs - uint64 nfree; // number of frees - - // Statistics about malloc heap. - // protected by mheap.Lock - uint64 heap_alloc; // bytes allocated and still in use - uint64 heap_sys; // bytes obtained from system - uint64 heap_idle; // bytes in idle spans - uint64 heap_inuse; // bytes in non-idle spans - uint64 heap_released; // bytes released to the OS - uint64 heap_objects; // total number of allocated objects - - // Statistics about allocation of low-level fixed-size structures. - // Protected by FixAlloc locks. - uint64 stacks_inuse; // bootstrap stacks - uint64 stacks_sys; - uint64 mspan_inuse; // MSpan structures - uint64 mspan_sys; - uint64 mcache_inuse; // MCache structures - uint64 mcache_sys; - uint64 buckhash_sys; // profiling bucket hash table - - // Statistics about garbage collector. - // Protected by stopping the world during GC. - uint64 next_gc; // next GC (in heap_alloc time) - uint64 last_gc; // last GC (in absolute time) - uint64 pause_total_ns; - uint64 pause_ns[256]; - uint32 numgc; - bool enablegc; - bool debuggc; - - // Statistics about allocation size classes. - struct { - uint32 size; - uint64 nmalloc; - uint64 nfree; - } by_size[NumSizeClasses]; -}; - -extern MStats mstats - __asm__ (GOSYM_PREFIX "runtime.VmemStats"); - - -// 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 runtime_SizeToClass(int32); -extern int32 runtime_class_to_size[NumSizeClasses]; -extern int32 runtime_class_to_allocnpages[NumSizeClasses]; -extern int32 runtime_class_to_transfercount[NumSizeClasses]; -extern void runtime_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]; - uintptr size; - intptr local_cachealloc; // bytes allocated (or freed) from cache since last lock of heap - intptr local_objects; // objects allocated (or freed) from cache since last lock of heap - intptr local_alloc; // bytes allocated (or freed) since last lock of heap - uintptr local_total_alloc; // bytes allocated (even if freed) since last lock of heap - uintptr local_nmalloc; // number of mallocs since last lock of heap - uintptr local_nfree; // number of frees since last lock of heap - uintptr local_nlookup; // number of pointer lookups since last lock of heap - int32 next_sample; // trigger heap sample after allocating this many bytes - // Statistics about allocation size classes since last lock of heap - struct { - uintptr nmalloc; - uintptr nfree; - } local_by_size[NumSizeClasses]; - -}; - -void* runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed); -void runtime_MCache_Free(MCache *c, void *p, int32 sizeclass, uintptr size); -void runtime_MCache_ReleaseAll(MCache *c); - -// MTypes describes the types of blocks allocated within a span. -// The compression field describes the layout of the data. -// -// MTypes_Empty: -// All blocks are free, or no type information is available for -// allocated blocks. -// The data field has no meaning. -// MTypes_Single: -// The span contains just one block. -// The data field holds the type information. -// The sysalloc field has no meaning. -// MTypes_Words: -// The span contains multiple blocks. -// The data field points to an array of type [NumBlocks]uintptr, -// and each element of the array holds the type of the corresponding -// block. -// MTypes_Bytes: -// The span contains at most seven different types of blocks. -// The data field points to the following structure: -// struct { -// type [8]uintptr // type[0] is always 0 -// index [NumBlocks]byte -// } -// The type of the i-th block is: data.type[data.index[i]] -enum -{ - MTypes_Empty = 0, - MTypes_Single = 1, - MTypes_Words = 2, - MTypes_Bytes = 3, -}; -struct MTypes -{ - byte compression; // one of MTypes_* - bool sysalloc; // whether (void*)data is from runtime_SysAlloc - uintptr data; -}; - -// 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 - 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 - int32 sizeclass; // size class - uintptr elemsize; // computed from sizeclass or from npages - uint32 state; // MSpanInUse etc - int64 unusedsince; // First time spotted by GC in MSpanFree state - uintptr npreleased; // number of pages released to the OS - byte *limit; // end of data in span - MTypes types; // types of allocated objects in this span -}; - -void runtime_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 runtime_MSpanList_Init(MSpan *list); -bool runtime_MSpanList_IsEmpty(MSpan *list); -void runtime_MSpanList_Insert(MSpan *list, MSpan *span); -void runtime_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 runtime_MCentral_Init(MCentral *c, int32 sizeclass); -int32 runtime_MCentral_AllocList(MCentral *c, int32 n, MLink **first); -void runtime_MCentral_FreeList(MCentral *c, int32 n, MLink *first); -void runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end); - -// 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; - uint32 nspan; - uint32 nspancap; - - // span lookup - MSpan *map[1<<MHeapMap_Bits]; - - // range of addresses we might see in the heap - byte *bitmap; - uintptr bitmap_mapped; - byte *arena_start; - byte *arena_used; - byte *arena_end; - - // central free lists for small size classes. - // the union makes sure that the MCentrals are - // spaced CacheLineSize bytes apart, so that each MCentral.Lock - // gets its own cache line. - union { - MCentral; - byte pad[CacheLineSize]; - } central[NumSizeClasses]; - - FixAlloc spanalloc; // allocator for Span* - FixAlloc cachealloc; // allocator for MCache* -}; -extern MHeap runtime_mheap; - -void runtime_MHeap_Init(MHeap *h, void *(*allocator)(uintptr)); -MSpan* runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed); -void runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct); -MSpan* runtime_MHeap_Lookup(MHeap *h, void *v); -MSpan* runtime_MHeap_LookupMaybe(MHeap *h, void *v); -void runtime_MGetSizeClassInfo(int32 sizeclass, uintptr *size, int32 *npages, int32 *nobj); -void* runtime_MHeap_SysAlloc(MHeap *h, uintptr n); -void runtime_MHeap_MapBits(MHeap *h); -void runtime_MHeap_Scavenger(void*); - -void* runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed); -int32 runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **s); -void runtime_gc(int32 force); -void runtime_markallocated(void *v, uintptr n, bool noptr); -void runtime_checkallocated(void *v, uintptr n); -void runtime_markfreed(void *v, uintptr n); -void runtime_checkfreed(void *v, uintptr n); -extern int32 runtime_checking; -void runtime_markspan(void *v, uintptr size, uintptr n, bool leftover); -void runtime_unmarkspan(void *v, uintptr size); -bool runtime_blockspecial(void*); -void runtime_setblockspecial(void*, bool); -void runtime_purgecachedstats(MCache*); -void* runtime_new(const Type *); -#define runtime_cnew(T) runtime_new(T) - -void runtime_settype(void*, uintptr); -void runtime_settype_flush(M*, bool); -void runtime_settype_sysfree(MSpan*); -uintptr runtime_gettype(void*); - -enum -{ - // flags to malloc - FlagNoPointers = 1<<0, // no pointers here - FlagNoProfiling = 1<<1, // must not profile - FlagNoGC = 1<<2, // must not free or scan for pointers -}; - -typedef struct Obj Obj; -struct Obj -{ - byte *p; // data pointer - uintptr n; // size of data in bytes - uintptr ti; // type info -}; - -void runtime_MProf_Malloc(void*, uintptr); -void runtime_MProf_Free(void*, uintptr); -void runtime_MProf_GC(void); -void runtime_MProf_Mark(void (*addroot)(Obj)); -int32 runtime_gcprocs(void); -void runtime_helpgc(int32 nproc); -void runtime_gchelper(void); - -struct __go_func_type; -bool runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft); -void runtime_walkfintab(void (*fn)(void*), void (*scan)(Obj)); - -enum -{ - TypeInfo_SingleObject = 0, - TypeInfo_Array = 1, - TypeInfo_Map = 2, - - // Enables type information at the end of blocks allocated from heap - DebugTypeAtBlockEnd = 0, -}; - -// defined in mgc0.go -void runtime_gc_m_ptr(Eface*); -void runtime_gc_itab_ptr(Eface*); - -void runtime_memorydump(void); - -void runtime_time_scan(void (*)(Obj)); -void runtime_trampoline_scan(void (*)(Obj)); diff --git a/gcc-4.8.1/libgo/runtime/map.goc b/gcc-4.8.1/libgo/runtime/map.goc deleted file mode 100644 index e4b8456dc..000000000 --- a/gcc-4.8.1/libgo/runtime/map.goc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package runtime -#include "runtime.h" -#include "map.h" - -typedef struct __go_map Hmap; -typedef struct __go_hash_iter hiter; - -/* Access a value in a map, returning a value and a presence indicator. */ - -func mapaccess2(t *MapType, h *Hmap, key *byte, val *byte) (present bool) { - byte *mapval; - size_t valsize; - - mapval = __go_map_index(h, key, 0); - valsize = t->__val_type->__size; - if (mapval == nil) { - __builtin_memset(val, 0, valsize); - present = 0; - } else { - __builtin_memcpy(val, mapval, valsize); - present = 1; - } -} - -/* Optionally assign a value to a map (m[k] = v, p). */ - -func mapassign2(h *Hmap, key *byte, val *byte, p bool) { - if (!p) { - __go_map_delete(h, key); - } else { - byte *mapval; - size_t valsize; - - mapval = __go_map_index(h, key, 1); - valsize = h->__descriptor->__map_descriptor->__val_type->__size; - __builtin_memcpy(mapval, val, valsize); - } -} - -/* Delete a key from a map. */ - -func mapdelete(h *Hmap, key *byte) { - __go_map_delete(h, key); -} - -/* Initialize a range over a map. */ - -func mapiterinit(h *Hmap, it *hiter) { - __go_mapiterinit(h, it); -} - -/* Move to the next iteration, updating *HITER. */ - -func mapiternext(it *hiter) { - __go_mapiternext(it); -} - -/* Get the key of the current iteration. */ - -func mapiter1(it *hiter, key *byte) { - __go_mapiter1(it, key); -} - -/* Get the key and value of the current iteration. */ - -func mapiter2(it *hiter, key *byte, val *byte) { - __go_mapiter2(it, key, val); -} diff --git a/gcc-4.8.1/libgo/runtime/map.h b/gcc-4.8.1/libgo/runtime/map.h deleted file mode 100644 index 0c587bb2a..000000000 --- a/gcc-4.8.1/libgo/runtime/map.h +++ /dev/null @@ -1,87 +0,0 @@ -/* map.h -- the map type for Go. - - 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 <stddef.h> -#include <stdint.h> - -#include "go-type.h" - -/* A map descriptor is what we need to manipulate the map. This is - constant for a given map type. */ - -struct __go_map_descriptor -{ - /* A pointer to the type descriptor for the type of the map itself. */ - const struct __go_map_type *__map_descriptor; - - /* A map entry is a struct with three fields: - map_entry_type *next_entry; - key_type key; - value_type value; - This is the size of that struct. */ - uintptr_t __entry_size; - - /* The offset of the key field in a map entry struct. */ - uintptr_t __key_offset; - - /* The offset of the value field in a map entry struct (the value - field immediately follows the key field, but there may be some - bytes inserted for alignment). */ - uintptr_t __val_offset; -}; - -struct __go_map -{ - /* The constant descriptor for this map. */ - const struct __go_map_descriptor *__descriptor; - - /* The number of elements in the hash table. */ - uintptr_t __element_count; - - /* The number of entries in the __buckets array. */ - uintptr_t __bucket_count; - - /* Each bucket is a pointer to a linked list of map entries. */ - void **__buckets; -}; - -/* For a map iteration the compiled code will use a pointer to an - iteration structure. The iteration structure will be allocated on - the stack. The Go code must allocate at least enough space. */ - -struct __go_hash_iter -{ - /* A pointer to the current entry. This will be set to NULL when - the range has completed. The Go will test this field, so it must - be the first one in the structure. */ - const void *entry; - /* The map we are iterating over. */ - const struct __go_map *map; - /* A pointer to the next entry in the current bucket. This permits - deleting the current entry. This will be NULL when we have seen - all the entries in the current bucket. */ - const void *next_entry; - /* The bucket index of the current and next entry. */ - uintptr_t bucket; -}; - -extern struct __go_map *__go_new_map (const struct __go_map_descriptor *, - uintptr_t); - -extern uintptr_t __go_map_next_prime (uintptr_t); - -extern void *__go_map_index (struct __go_map *, const void *, _Bool); - -extern void __go_map_delete (struct __go_map *, const void *); - -extern void __go_mapiterinit (const struct __go_map *, struct __go_hash_iter *); - -extern void __go_mapiternext (struct __go_hash_iter *); - -extern void __go_mapiter1 (struct __go_hash_iter *it, unsigned char *key); - -extern void __go_mapiter2 (struct __go_hash_iter *it, unsigned char *key, - unsigned char *val); diff --git a/gcc-4.8.1/libgo/runtime/mcache.c b/gcc-4.8.1/libgo/runtime/mcache.c deleted file mode 100644 index 570c06a73..000000000 --- a/gcc-4.8.1/libgo/runtime/mcache.c +++ /dev/null @@ -1,129 +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 "arch.h" -#include "malloc.h" - -void* -runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed) -{ - MCacheList *l; - MLink *first, *v; - int32 n; - - // Allocate from list. - l = &c->list[sizeclass]; - if(l->list == nil) { - // Replenish using central lists. - n = runtime_MCentral_AllocList(&runtime_mheap.central[sizeclass], - runtime_class_to_transfercount[sizeclass], &first); - if(n == 0) - runtime_throw("out of memory"); - 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; - if(zeroed) { - // block is zeroed iff second word is zero ... - if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0) - runtime_memclr((byte*)v, size); - } - c->local_cachealloc += size; - c->local_objects++; - 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*runtime_class_to_size[sizeclass]; - - // Return them to central free list. - runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass], n, first); -} - -void -runtime_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; - c->local_cachealloc -= size; - c->local_objects--; - - if(l->nlist >= MaxMCacheListLen) { - // Release a chunk back. - ReleaseN(c, l, runtime_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; - } - } -} - -void -runtime_MCache_ReleaseAll(MCache *c) -{ - int32 i; - MCacheList *l; - - for(i=0; i<NumSizeClasses; i++) { - l = &c->list[i]; - ReleaseN(c, l, l->nlist, i); - l->nlistmin = 0; - } -} diff --git a/gcc-4.8.1/libgo/runtime/mcentral.c b/gcc-4.8.1/libgo/runtime/mcentral.c deleted file mode 100644 index b405438f9..000000000 --- a/gcc-4.8.1/libgo/runtime/mcentral.c +++ /dev/null @@ -1,227 +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 "arch.h" -#include "malloc.h" - -static bool MCentral_Grow(MCentral *c); -static void MCentral_Free(MCentral *c, void *v); - -// Initialize a single central free list. -void -runtime_MCentral_Init(MCentral *c, int32 sizeclass) -{ - c->sizeclass = sizeclass; - runtime_MSpanList_Init(&c->nonempty); - runtime_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. -int32 -runtime_MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst) -{ - MSpan *s; - MLink *first, *last; - int32 cap, avail, i; - - runtime_lock(c); - // Replenish central list if empty. - if(runtime_MSpanList_IsEmpty(&c->nonempty)) { - if(!MCentral_Grow(c)) { - runtime_unlock(c); - *pfirst = nil; - return 0; - } - } - s = c->nonempty.next; - cap = (s->npages << PageShift) / s->elemsize; - avail = cap - s->ref; - if(avail < n) - n = avail; - - // First one is guaranteed to work, because we just grew the list. - first = s->freelist; - last = first; - for(i=1; i<n; i++) { - last = last->next; - } - s->freelist = last->next; - last->next = nil; - s->ref += n; - c->nfree -= n; - - if(n == avail) { - if(s->freelist != nil || s->ref != (uint32)cap) { - runtime_throw("invalid freelist"); - } - runtime_MSpanList_Remove(s); - runtime_MSpanList_Insert(&c->empty, s); - } - - runtime_unlock(c); - *pfirst = first; - return n; -} - -// Free n objects back into the central free list. -void -runtime_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); - - runtime_lock(c); - for(v=start; v; v=next) { - next = v->next; - MCentral_Free(c, v); - } - runtime_unlock(c); -} - -// Helper: free one object back into the central free list. -static void -MCentral_Free(MCentral *c, void *v) -{ - MSpan *s; - MLink *p; - int32 size; - - // Find span for v. - s = runtime_MHeap_Lookup(&runtime_mheap, v); - if(s == nil || s->ref == 0) - runtime_throw("invalid free"); - - // Move to nonempty if necessary. - if(s->freelist == nil) { - runtime_MSpanList_Remove(s); - runtime_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) { - size = runtime_class_to_size[c->sizeclass]; - runtime_MSpanList_Remove(s); - runtime_unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift); - *(uintptr*)(s->start<<PageShift) = 1; // needs zeroing - s->freelist = nil; - c->nfree -= (s->npages << PageShift) / size; - runtime_unlock(c); - runtime_MHeap_Free(&runtime_mheap, s, 0); - runtime_lock(c); - } -} - -// Free n objects from a span s back into the central free list c. -// Called from GC. -void -runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end) -{ - int32 size; - - runtime_lock(c); - - // Move to nonempty if necessary. - if(s->freelist == nil) { - runtime_MSpanList_Remove(s); - runtime_MSpanList_Insert(&c->nonempty, s); - } - - // Add the objects back to s's free list. - end->next = s->freelist; - s->freelist = start; - s->ref -= n; - c->nfree += n; - - // If s is completely freed, return it to the heap. - if(s->ref == 0) { - size = runtime_class_to_size[c->sizeclass]; - runtime_MSpanList_Remove(s); - *(uintptr*)(s->start<<PageShift) = 1; // needs zeroing - s->freelist = nil; - c->nfree -= (s->npages << PageShift) / size; - runtime_unlock(c); - runtime_unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift); - runtime_MHeap_Free(&runtime_mheap, s, 0); - } else { - runtime_unlock(c); - } -} - -void -runtime_MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj) -{ - int32 size; - int32 npages; - - npages = runtime_class_to_allocnpages[sizeclass]; - size = runtime_class_to_size[sizeclass]; - *npagesp = npages; - *sizep = size; - *nobj = (npages << PageShift) / size; -} - -// 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; - uintptr size; - MLink **tailp, *v; - byte *p; - MSpan *s; - - runtime_unlock(c); - runtime_MGetSizeClassInfo(c->sizeclass, &size, &npages, &n); - s = runtime_MHeap_Alloc(&runtime_mheap, npages, c->sizeclass, 0, 1); - if(s == nil) { - // TODO(rsc): Log out of memory - runtime_lock(c); - return false; - } - - // Carve span into sequence of blocks. - tailp = &s->freelist; - p = (byte*)(s->start << PageShift); - s->limit = p + size*n; - for(i=0; i<n; i++) { - v = (MLink*)p; - *tailp = v; - tailp = &v->next; - p += size; - } - *tailp = nil; - runtime_markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift)); - - runtime_lock(c); - c->nfree += n; - runtime_MSpanList_Insert(&c->nonempty, s); - return true; -} diff --git a/gcc-4.8.1/libgo/runtime/mem.c b/gcc-4.8.1/libgo/runtime/mem.c deleted file mode 100644 index e606bdd4d..000000000 --- a/gcc-4.8.1/libgo/runtime/mem.c +++ /dev/null @@ -1,185 +0,0 @@ -/* Defining _XOPEN_SOURCE hides the declaration of madvise() on Solaris < - 11 and the MADV_DONTNEED definition on IRIX 6.5. */ -#undef _XOPEN_SOURCE - -#include <errno.h> -#include <unistd.h> - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -#ifndef MAP_ANON -#ifdef MAP_ANONYMOUS -#define MAP_ANON MAP_ANONYMOUS -#else -#define USE_DEV_ZERO -#define MAP_ANON 0 -#endif -#endif - -#ifndef MAP_NORESERVE -#define MAP_NORESERVE 0 -#endif - -#ifdef USE_DEV_ZERO -static int dev_zero = -1; -#endif - -static _Bool -addrspace_free(void *v __attribute__ ((unused)), uintptr n __attribute__ ((unused))) -{ -#ifdef HAVE_MINCORE - size_t page_size = getpagesize(); - size_t off; - char one_byte; - - errno = 0; - for(off = 0; off < n; off += page_size) - if(mincore((char *)v + off, page_size, (void *)&one_byte) != -1 - || errno != ENOMEM) - return 0; -#endif - return 1; -} - -static void * -mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset) -{ - void *p; - - p = runtime_mmap((void *)v, n, prot, flags, fd, offset); - if(p != v && addrspace_free(v, n)) { - // On some systems, mmap ignores v without - // MAP_FIXED, so retry if the address space is free. - if(p != MAP_FAILED) - runtime_munmap(p, n); - p = runtime_mmap((void *)v, n, prot, flags|MAP_FIXED, fd, offset); - } - return p; -} - -void* -runtime_SysAlloc(uintptr n) -{ - void *p; - int fd = -1; - - mstats.sys += n; - -#ifdef USE_DEV_ZERO - if (dev_zero == -1) { - dev_zero = open("/dev/zero", O_RDONLY); - if (dev_zero < 0) { - runtime_printf("open /dev/zero: errno=%d\n", errno); - exit(2); - } - } - fd = dev_zero; -#endif - - p = runtime_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0); - if (p == MAP_FAILED) { - if(errno == EACCES) { - runtime_printf("runtime: mmap: access denied\n"); - runtime_printf("if you're running SELinux, enable execmem for this process.\n"); - exit(2); - } - if(errno == EAGAIN) { - runtime_printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n"); - runtime_exit(2); - } - return nil; - } - return p; -} - -void -runtime_SysUnused(void *v __attribute__ ((unused)), uintptr n __attribute__ ((unused))) -{ -#ifdef MADV_DONTNEED - runtime_madvise(v, n, MADV_DONTNEED); -#endif -} - -void -runtime_SysFree(void *v, uintptr n) -{ - mstats.sys -= n; - runtime_munmap(v, n); -} - -void* -runtime_SysReserve(void *v, uintptr n) -{ - int fd = -1; - void *p; - -#ifdef USE_DEV_ZERO - if (dev_zero == -1) { - dev_zero = open("/dev/zero", O_RDONLY); - if (dev_zero < 0) { - runtime_printf("open /dev/zero: errno=%d\n", errno); - exit(2); - } - } - fd = dev_zero; -#endif - - // On 64-bit, people with ulimit -v set complain if we reserve too - // much address space. Instead, assume that the reservation is okay - // if we can reserve at least 64K and check the assumption in SysMap. - // Only user-mode Linux (UML) rejects these requests. - if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) { - p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0); - if (p != v) - return nil; - runtime_munmap(p, 64<<10); - return v; - } - - // Use the MAP_NORESERVE mmap() flag here because typically most of - // this reservation will never be used. It does not make sense - // reserve a huge amount of unneeded swap space. This is important on - // systems which do not overcommit memory by default. - p = runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, fd, 0); - if(p == MAP_FAILED) - return nil; - return p; -} - -void -runtime_SysMap(void *v, uintptr n) -{ - void *p; - int fd = -1; - - mstats.sys += n; - -#ifdef USE_DEV_ZERO - if (dev_zero == -1) { - dev_zero = open("/dev/zero", O_RDONLY); - if (dev_zero < 0) { - runtime_printf("open /dev/zero: errno=%d\n", errno); - exit(2); - } - } - fd = dev_zero; -#endif - - // On 64-bit, we don't actually have v reserved, so tread carefully. - if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) { - p = mmap_fixed(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0); - if(p == MAP_FAILED && errno == ENOMEM) - runtime_throw("runtime: out of memory"); - if(p != v) { - runtime_printf("runtime: address space conflict: map(%p) = %p\n", v, p); - runtime_throw("runtime: address space conflict"); - } - return; - } - - p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0); - if(p != v) - runtime_throw("runtime: cannot map pages in arena address space"); -} diff --git a/gcc-4.8.1/libgo/runtime/mem_posix_memalign.c b/gcc-4.8.1/libgo/runtime/mem_posix_memalign.c deleted file mode 100644 index 8acdf0705..000000000 --- a/gcc-4.8.1/libgo/runtime/mem_posix_memalign.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <errno.h> - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -void* -runtime_SysAlloc(uintptr n) -{ - void *p; - - mstats.sys += n; - errno = posix_memalign(&p, PageSize, n); - if (errno > 0) { - perror("posix_memalign"); - exit(2); - } - return p; -} - -void -runtime_SysUnused(void *v, uintptr n) -{ - USED(v); - USED(n); - // TODO(rsc): call madvise MADV_DONTNEED -} - -void -runtime_SysFree(void *v, uintptr n) -{ - mstats.sys -= n; - free(v); -} - -void* -runtime_SysReserve(void *v, uintptr n) -{ - USED(v); - return runtime_SysAlloc(n); -} - -void -runtime_SysMap(void *v, uintptr n) -{ - USED(v); - USED(n); -} diff --git a/gcc-4.8.1/libgo/runtime/mfinal.c b/gcc-4.8.1/libgo/runtime/mfinal.c deleted file mode 100644 index 7c906daf3..000000000 --- a/gcc-4.8.1/libgo/runtime/mfinal.c +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -enum { debug = 0 }; - -typedef struct Fin Fin; -struct Fin -{ - void (*fn)(void*); - const struct __go_func_type *ft; -}; - -// Finalizer hash table. Direct hash, linear scan, at most 3/4 full. -// Table size is power of 3 so that hash can be key % max. -// Key[i] == (void*)-1 denotes free but formerly occupied entry -// (doesn't stop the linear scan). -// Key and val are separate tables because the garbage collector -// must be instructed to ignore the pointers in key but follow the -// pointers in val. -typedef struct Fintab Fintab; -struct Fintab -{ - Lock; - void **fkey; - Fin *val; - int32 nkey; // number of non-nil entries in key - int32 ndead; // number of dead (-1) entries in key - int32 max; // size of key, val allocations -}; - -#define TABSZ 17 -#define TAB(p) (&fintab[((uintptr)(p)>>3)%TABSZ]) - -static struct { - Fintab; - uint8 pad[0 /* CacheLineSize - sizeof(Fintab) */]; -} fintab[TABSZ]; - -static void -addfintab(Fintab *t, void *k, void (*fn)(void*), const struct __go_func_type *ft) -{ - int32 i, j; - - i = (uintptr)k % (uintptr)t->max; - for(j=0; j<t->max; j++) { - if(t->fkey[i] == nil) { - t->nkey++; - goto ret; - } - if(t->fkey[i] == (void*)-1) { - t->ndead--; - goto ret; - } - if(++i == t->max) - i = 0; - } - - // cannot happen - table is known to be non-full - runtime_throw("finalizer table inconsistent"); - -ret: - t->fkey[i] = k; - t->val[i].fn = fn; - t->val[i].ft = ft; -} - -static bool -lookfintab(Fintab *t, void *k, bool del, Fin *f) -{ - int32 i, j; - - if(t->max == 0) - return false; - i = (uintptr)k % (uintptr)t->max; - for(j=0; j<t->max; j++) { - if(t->fkey[i] == nil) - return false; - if(t->fkey[i] == k) { - if(f) - *f = t->val[i]; - if(del) { - t->fkey[i] = (void*)-1; - t->val[i].fn = nil; - t->val[i].ft = nil; - t->ndead++; - } - return true; - } - if(++i == t->max) - i = 0; - } - - // cannot happen - table is known to be non-full - runtime_throw("finalizer table inconsistent"); - return false; -} - -static void -resizefintab(Fintab *tab) -{ - Fintab newtab; - void *k; - int32 i; - - runtime_memclr((byte*)&newtab, sizeof newtab); - newtab.max = tab->max; - if(newtab.max == 0) - newtab.max = 3*3*3; - else if(tab->ndead < tab->nkey/2) { - // grow table if not many dead values. - // otherwise just rehash into table of same size. - newtab.max *= 3; - } - - newtab.fkey = runtime_mallocgc(newtab.max*sizeof newtab.fkey[0], FlagNoPointers, 0, 1); - newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1); - - for(i=0; i<tab->max; i++) { - k = tab->fkey[i]; - if(k != nil && k != (void*)-1) - addfintab(&newtab, k, tab->val[i].fn, tab->val[i].ft); - } - - runtime_free(tab->fkey); - runtime_free(tab->val); - - tab->fkey = newtab.fkey; - tab->val = newtab.val; - tab->nkey = newtab.nkey; - tab->ndead = newtab.ndead; - tab->max = newtab.max; -} - -bool -runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft) -{ - Fintab *tab; - byte *base; - - if(debug) { - if(!runtime_mlookup(p, &base, nil, nil) || p != base) - runtime_throw("addfinalizer on invalid pointer"); - } - - tab = TAB(p); - runtime_lock(tab); - if(f == nil) { - lookfintab(tab, p, true, nil); - runtime_unlock(tab); - return true; - } - - if(lookfintab(tab, p, false, nil)) { - runtime_unlock(tab); - return false; - } - - if(tab->nkey >= tab->max/2+tab->max/4) { - // keep table at most 3/4 full: - // allocate new table and rehash. - resizefintab(tab); - } - - addfintab(tab, p, f, ft); - runtime_setblockspecial(p, true); - runtime_unlock(tab); - return true; -} - -// get finalizer; if del, delete finalizer. -// caller is responsible for updating RefHasFinalizer (special) bit. -bool -runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft) -{ - Fintab *tab; - bool res; - Fin f; - - tab = TAB(p); - runtime_lock(tab); - res = lookfintab(tab, p, del, &f); - runtime_unlock(tab); - if(res==false) - return false; - *fn = f.fn; - *ft = f.ft; - return true; -} - -void -runtime_walkfintab(void (*fn)(void*), void (*addroot)(Obj)) -{ - void **key; - void **ekey; - int32 i; - - for(i=0; i<TABSZ; i++) { - runtime_lock(&fintab[i]); - key = fintab[i].fkey; - ekey = key + fintab[i].max; - for(; key < ekey; key++) - if(*key != nil && *key != ((void*)-1)) - fn(*key); - addroot((Obj){(byte*)&fintab[i].fkey, sizeof(void*), 0}); - addroot((Obj){(byte*)&fintab[i].val, sizeof(void*), 0}); - runtime_unlock(&fintab[i]); - } -} diff --git a/gcc-4.8.1/libgo/runtime/mfixalloc.c b/gcc-4.8.1/libgo/runtime/mfixalloc.c deleted file mode 100644 index 109cfe8ee..000000000 --- a/gcc-4.8.1/libgo/runtime/mfixalloc.c +++ /dev/null @@ -1,63 +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 "arch.h" -#include "malloc.h" - -// Initialize f to allocate objects of the given size, -// using the allocator to obtain chunks of memory. -void -runtime_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; - f->inuse = 0; - f->sys = 0; -} - -void* -runtime_FixAlloc_Alloc(FixAlloc *f) -{ - void *v; - - if(f->list) { - v = f->list; - f->list = *(void**)f->list; - f->inuse += f->size; - return v; - } - if(f->nchunk < f->size) { - f->sys += FixAllocChunk; - f->chunk = f->alloc(FixAllocChunk); - if(f->chunk == nil) - runtime_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; - f->inuse += f->size; - return v; -} - -void -runtime_FixAlloc_Free(FixAlloc *f, void *p) -{ - f->inuse -= f->size; - *(void**)p = f->list; - f->list = p; -} - diff --git a/gcc-4.8.1/libgo/runtime/mgc0.c b/gcc-4.8.1/libgo/runtime/mgc0.c deleted file mode 100644 index ffbe2cefb..000000000 --- a/gcc-4.8.1/libgo/runtime/mgc0.c +++ /dev/null @@ -1,1956 +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. - -#include <unistd.h> - -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "mgc0.h" -#include "race.h" -#include "go-type.h" - -// Map gccgo field names to gc field names. -// Slice aka __go_open_array. -#define array __values -#define cap __capacity -// Iface aka __go_interface -#define tab __methods -// Eface aka __go_empty_interface. -#define type __type_descriptor -// Type aka __go_type_descriptor -#define kind __code -#define KindPtr GO_PTR -#define KindNoPointers GO_NO_POINTERS -// PtrType aka __go_ptr_type -#define elem __element_type - -#ifdef USING_SPLIT_STACK - -extern void * __splitstack_find (void *, void *, size_t *, void **, void **, - void **); - -extern void * __splitstack_find_context (void *context[10], size_t *, void **, - void **, void **); - -#endif - -enum { - Debug = 0, - DebugMark = 0, // run second pass to check mark - - // Four bits per word (see #defines below). - wordsPerBitmapWord = sizeof(void*)*8/4, - bitShift = sizeof(void*)*8/4, - - handoffThreshold = 4, - IntermediateBufferCapacity = 64, - - // Bits in type information - PRECISE = 1, - LOOP = 2, - PC_BITS = PRECISE | LOOP, -}; - -// Bits in per-word bitmap. -// #defines because enum might not be able to hold the values. -// -// Each word in the bitmap describes wordsPerBitmapWord words -// of heap memory. There are 4 bitmap bits dedicated to each heap word, -// so on a 64-bit system there is one bitmap word per 16 heap words. -// The bits in the word are packed together by type first, then by -// heap location, so each 64-bit bitmap word consists of, from top to bottom, -// the 16 bitSpecial bits for the corresponding heap words, then the 16 bitMarked bits, -// then the 16 bitNoPointers/bitBlockBoundary bits, then the 16 bitAllocated bits. -// This layout makes it easier to iterate over the bits of a given type. -// -// The bitmap starts at mheap.arena_start and extends *backward* from -// there. On a 64-bit system the off'th word in the arena is tracked by -// the off/16+1'th word before mheap.arena_start. (On a 32-bit system, -// the only difference is that the divisor is 8.) -// -// To pull out the bits corresponding to a given pointer p, we use: -// -// off = p - (uintptr*)mheap.arena_start; // word offset -// b = (uintptr*)mheap.arena_start - off/wordsPerBitmapWord - 1; -// shift = off % wordsPerBitmapWord -// bits = *b >> shift; -// /* then test bits & bitAllocated, bits & bitMarked, etc. */ -// -#define bitAllocated ((uintptr)1<<(bitShift*0)) -#define bitNoPointers ((uintptr)1<<(bitShift*1)) /* when bitAllocated is set */ -#define bitMarked ((uintptr)1<<(bitShift*2)) /* when bitAllocated is set */ -#define bitSpecial ((uintptr)1<<(bitShift*3)) /* when bitAllocated is set - has finalizer or being profiled */ -#define bitBlockBoundary ((uintptr)1<<(bitShift*1)) /* when bitAllocated is NOT set */ - -#define bitMask (bitBlockBoundary | bitAllocated | bitMarked | bitSpecial) - -// Holding worldsema grants an M the right to try to stop the world. -// The procedure is: -// -// runtime_semacquire(&runtime_worldsema); -// m->gcing = 1; -// runtime_stoptheworld(); -// -// ... do stuff ... -// -// m->gcing = 0; -// runtime_semrelease(&runtime_worldsema); -// runtime_starttheworld(); -// -uint32 runtime_worldsema = 1; - -static int32 gctrace; - -// The size of Workbuf is N*PageSize. -typedef struct Workbuf Workbuf; -struct Workbuf -{ -#define SIZE (2*PageSize-sizeof(LFNode)-sizeof(uintptr)) - LFNode node; // must be first - uintptr nobj; - Obj obj[SIZE/sizeof(Obj) - 1]; - uint8 _padding[SIZE%sizeof(Obj) + sizeof(Obj)]; -#undef SIZE -}; - -typedef struct Finalizer Finalizer; -struct Finalizer -{ - void (*fn)(void*); - void *arg; - const struct __go_func_type *ft; -}; - -typedef struct FinBlock FinBlock; -struct FinBlock -{ - FinBlock *alllink; - FinBlock *next; - int32 cnt; - int32 cap; - Finalizer fin[1]; -}; - -static G *fing; -static FinBlock *finq; // list of finalizers that are to be executed -static FinBlock *finc; // cache of free blocks -static FinBlock *allfin; // list of all blocks -static Lock finlock; -static int32 fingwait; - -static void runfinq(void*); -static Workbuf* getempty(Workbuf*); -static Workbuf* getfull(Workbuf*); -static void putempty(Workbuf*); -static Workbuf* handoff(Workbuf*); - -static struct { - uint64 full; // lock-free list of full blocks - uint64 empty; // lock-free list of empty blocks - byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait - uint32 nproc; - volatile uint32 nwait; - volatile uint32 ndone; - volatile uint32 debugmarkdone; - Note alldone; - ParFor *markfor; - ParFor *sweepfor; - - Lock; - byte *chunk; - uintptr nchunk; - - Obj *roots; - uint32 nroot; - uint32 rootcap; -} work; - -enum { - // TODO(atom): to be expanded in a next CL - GC_DEFAULT_PTR = GC_NUM_INSTR, -}; - -// PtrTarget and BitTarget are structures used by intermediate buffers. -// The intermediate buffers hold GC data before it -// is moved/flushed to the work buffer (Workbuf). -// The size of an intermediate buffer is very small, -// such as 32 or 64 elements. -typedef struct PtrTarget PtrTarget; -struct PtrTarget -{ - void *p; - uintptr ti; -}; - -typedef struct BitTarget BitTarget; -struct BitTarget -{ - void *p; - uintptr ti; - uintptr *bitp, shift; -}; - -typedef struct BufferList BufferList; -struct BufferList -{ - PtrTarget ptrtarget[IntermediateBufferCapacity]; - BitTarget bittarget[IntermediateBufferCapacity]; - BufferList *next; -}; -static BufferList *bufferList; - -static Lock lock; -static Type *itabtype; - -static void enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj); - -// flushptrbuf moves data from the PtrTarget buffer to the work buffer. -// The PtrTarget buffer contains blocks irrespective of whether the blocks have been marked or scanned, -// while the work buffer contains blocks which have been marked -// and are prepared to be scanned by the garbage collector. -// -// _wp, _wbuf, _nobj are input/output parameters and are specifying the work buffer. -// bitbuf holds temporary data generated by this function. -// -// A simplified drawing explaining how the todo-list moves from a structure to another: -// -// scanblock -// (find pointers) -// Obj ------> PtrTarget (pointer targets) -// ↑ | -// | | flushptrbuf (1st part, -// | | find block start) -// | ↓ -// `--------- BitTarget (pointer targets and the corresponding locations in bitmap) -// flushptrbuf -// (2nd part, mark and enqueue) -static void -flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf, uintptr *_nobj, BitTarget *bitbuf) -{ - byte *p, *arena_start, *obj; - uintptr size, *bitp, bits, shift, j, x, xbits, off, nobj, ti, n; - MSpan *s; - PageID k; - Obj *wp; - Workbuf *wbuf; - PtrTarget *ptrbuf_end; - BitTarget *bitbufpos, *bt; - - arena_start = runtime_mheap.arena_start; - - wp = *_wp; - wbuf = *_wbuf; - nobj = *_nobj; - - ptrbuf_end = *ptrbufpos; - n = ptrbuf_end - ptrbuf; - *ptrbufpos = ptrbuf; - - // If buffer is nearly full, get a new one. - if(wbuf == nil || nobj+n >= nelem(wbuf->obj)) { - if(wbuf != nil) - wbuf->nobj = nobj; - wbuf = getempty(wbuf); - wp = wbuf->obj; - nobj = 0; - - if(n >= nelem(wbuf->obj)) - runtime_throw("ptrbuf has to be smaller than WorkBuf"); - } - - // TODO(atom): This block is a branch of an if-then-else statement. - // The single-threaded branch may be added in a next CL. - { - // Multi-threaded version. - - bitbufpos = bitbuf; - - while(ptrbuf < ptrbuf_end) { - obj = ptrbuf->p; - ti = ptrbuf->ti; - ptrbuf++; - - // obj belongs to interval [mheap.arena_start, mheap.arena_used). - if(Debug > 1) { - if(obj < runtime_mheap.arena_start || obj >= runtime_mheap.arena_used) - runtime_throw("object is outside of mheap"); - } - - // obj may be a pointer to a live object. - // Try to find the beginning of the object. - - // Round down to word boundary. - if(((uintptr)obj & ((uintptr)PtrSize-1)) != 0) { - obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1)); - ti = 0; - } - - // Find bits for this word. - off = (uintptr*)obj - (uintptr*)arena_start; - bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - xbits = *bitp; - bits = xbits >> shift; - - // Pointing at the beginning of a block? - if((bits & (bitAllocated|bitBlockBoundary)) != 0) - goto found; - - ti = 0; - - // Pointing just past the beginning? - // Scan backward a little to find a block boundary. - for(j=shift; j-->0; ) { - if(((xbits>>j) & (bitAllocated|bitBlockBoundary)) != 0) { - obj = (byte*)obj - (shift-j)*PtrSize; - shift = j; - bits = xbits>>shift; - goto found; - } - } - - // Otherwise consult span table to find beginning. - // (Manually inlined copy of MHeap_LookupMaybe.) - k = (uintptr)obj>>PageShift; - x = k; - if(sizeof(void*) == 8) - x -= (uintptr)arena_start>>PageShift; - s = runtime_mheap.map[x]; - if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse) - continue; - p = (byte*)((uintptr)s->start<<PageShift); - if(s->sizeclass == 0) { - obj = p; - } else { - if((byte*)obj >= (byte*)s->limit) - continue; - size = s->elemsize; - int32 i = ((byte*)obj - p)/size; - obj = p+i*size; - } - - // Now that we know the object header, reload bits. - off = (uintptr*)obj - (uintptr*)arena_start; - bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - xbits = *bitp; - bits = xbits >> shift; - - found: - // Now we have bits, bitp, and shift correct for - // obj pointing at the base of the object. - // Only care about allocated and not marked. - if((bits & (bitAllocated|bitMarked)) != bitAllocated) - continue; - - *bitbufpos++ = (BitTarget){obj, ti, bitp, shift}; - } - - runtime_lock(&lock); - for(bt=bitbuf; bt<bitbufpos; bt++){ - xbits = *bt->bitp; - bits = xbits >> bt->shift; - if((bits & bitMarked) != 0) - continue; - - // Mark the block - *bt->bitp = xbits | (bitMarked << bt->shift); - - // If object has no pointers, don't need to scan further. - if((bits & bitNoPointers) != 0) - continue; - - obj = bt->p; - - // Ask span about size class. - // (Manually inlined copy of MHeap_Lookup.) - x = (uintptr)obj >> PageShift; - if(sizeof(void*) == 8) - x -= (uintptr)arena_start>>PageShift; - s = runtime_mheap.map[x]; - - PREFETCH(obj); - - *wp = (Obj){obj, s->elemsize, bt->ti}; - wp++; - nobj++; - } - runtime_unlock(&lock); - - // If another proc wants a pointer, give it some. - if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) { - wbuf->nobj = nobj; - wbuf = handoff(wbuf); - nobj = wbuf->nobj; - wp = wbuf->obj + nobj; - } - } - - *_wp = wp; - *_wbuf = wbuf; - *_nobj = nobj; -} - -// Program that scans the whole block and treats every block element as a potential pointer -static uintptr defaultProg[2] = {PtrSize, GC_DEFAULT_PTR}; - -// Local variables of a program fragment or loop -typedef struct Frame Frame; -struct Frame { - uintptr count, elemsize, b; - uintptr *loop_or_ret; -}; - -// scanblock scans a block of n bytes starting at pointer b for references -// to other objects, scanning any it finds recursively until there are no -// unscanned objects left. Instead of using an explicit recursion, it keeps -// a work list in the Workbuf* structures and loops in the main function -// body. Keeping an explicit work list is easier on the stack allocator and -// more efficient. -// -// wbuf: current work buffer -// wp: storage for next queued pointer (write pointer) -// nobj: number of queued objects -static void -scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking) -{ - byte *b, *arena_start, *arena_used; - uintptr n, i, end_b, elemsize, ti, objti, count /* , type */; - uintptr *pc, precise_type, nominal_size; - void *obj; - const Type *t; - Slice *sliceptr; - Frame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4]; - BufferList *scanbuffers; - PtrTarget *ptrbuf, *ptrbuf_end, *ptrbufpos; - BitTarget *bitbuf; - Eface *eface; - Iface *iface; - - if(sizeof(Workbuf) % PageSize != 0) - runtime_throw("scanblock: size of Workbuf is suboptimal"); - - // Memory arena parameters. - arena_start = runtime_mheap.arena_start; - arena_used = runtime_mheap.arena_used; - - stack_ptr = stack+nelem(stack)-1; - - precise_type = false; - nominal_size = 0; - - // Allocate ptrbuf, bitbuf - { - runtime_lock(&lock); - - if(bufferList == nil) { - bufferList = runtime_SysAlloc(sizeof(*bufferList)); - bufferList->next = nil; - } - scanbuffers = bufferList; - bufferList = bufferList->next; - - ptrbuf = &scanbuffers->ptrtarget[0]; - ptrbuf_end = &scanbuffers->ptrtarget[0] + nelem(scanbuffers->ptrtarget); - bitbuf = &scanbuffers->bittarget[0]; - - runtime_unlock(&lock); - } - - ptrbufpos = ptrbuf; - - goto next_block; - - for(;;) { - // Each iteration scans the block b of length n, queueing pointers in - // the work buffer. - if(Debug > 1) { - runtime_printf("scanblock %p %D\n", b, (int64)n); - } - - if(ti != 0 && 0) { - pc = (uintptr*)(ti & ~(uintptr)PC_BITS); - precise_type = (ti & PRECISE); - stack_top.elemsize = pc[0]; - if(!precise_type) - nominal_size = pc[0]; - if(ti & LOOP) { - stack_top.count = 0; // 0 means an infinite number of iterations - stack_top.loop_or_ret = pc+1; - } else { - stack_top.count = 1; - } - } else if(UseSpanType && 0) { -#if 0 - type = runtime_gettype(b); - if(type != 0) { - t = (Type*)(type & ~(uintptr)(PtrSize-1)); - switch(type & (PtrSize-1)) { - case TypeInfo_SingleObject: - pc = (uintptr*)t->gc; - precise_type = true; // type information about 'b' is precise - stack_top.count = 1; - stack_top.elemsize = pc[0]; - break; - case TypeInfo_Array: - pc = (uintptr*)t->gc; - if(pc[0] == 0) - goto next_block; - precise_type = true; // type information about 'b' is precise - stack_top.count = 0; // 0 means an infinite number of iterations - stack_top.elemsize = pc[0]; - stack_top.loop_or_ret = pc+1; - break; - case TypeInfo_Map: - // TODO(atom): to be expanded in a next CL - pc = defaultProg; - break; - default: - runtime_throw("scanblock: invalid type"); - return; - } - } else { - pc = defaultProg; - } -#endif - } else { - pc = defaultProg; - } - - pc++; - stack_top.b = (uintptr)b; - - end_b = (uintptr)b + n - PtrSize; - - for(;;) { - obj = nil; - objti = 0; - switch(pc[0]) { - case GC_PTR: - obj = *(void**)(stack_top.b + pc[1]); - objti = pc[2]; - pc += 3; - break; - - case GC_SLICE: - sliceptr = (Slice*)(stack_top.b + pc[1]); - if(sliceptr->cap != 0) { - obj = sliceptr->array; - objti = pc[2] | PRECISE | LOOP; - } - pc += 3; - break; - - case GC_APTR: - obj = *(void**)(stack_top.b + pc[1]); - pc += 2; - break; - - case GC_STRING: - obj = *(void**)(stack_top.b + pc[1]); - pc += 2; - break; - - case GC_EFACE: - eface = (Eface*)(stack_top.b + pc[1]); - pc += 2; - if(eface->type != nil && ((byte*)eface->__object >= arena_start && (byte*)eface->__object < arena_used)) { - t = eface->type; - if(t->__size <= sizeof(void*)) { - if((t->kind & KindNoPointers)) - break; - - obj = eface->__object; - if((t->kind & ~KindNoPointers) == KindPtr) - // objti = (uintptr)((PtrType*)t)->elem->gc; - objti = 0; - } else { - obj = eface->__object; - // objti = (uintptr)t->gc; - objti = 0; - } - } - break; - - case GC_IFACE: - iface = (Iface*)(stack_top.b + pc[1]); - pc += 2; - if(iface->tab == nil) - break; - - // iface->tab - if((byte*)iface->tab >= arena_start && (byte*)iface->tab < arena_used) { - // *ptrbufpos++ = (struct PtrTarget){iface->tab, (uintptr)itabtype->gc}; - *ptrbufpos++ = (struct PtrTarget){iface->tab, 0}; - if(ptrbufpos == ptrbuf_end) - flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf); - } - - // iface->data - if((byte*)iface->__object >= arena_start && (byte*)iface->__object < arena_used) { - // t = iface->tab->type; - t = nil; - if(t->__size <= sizeof(void*)) { - if((t->kind & KindNoPointers)) - break; - - obj = iface->__object; - if((t->kind & ~KindNoPointers) == KindPtr) - // objti = (uintptr)((const PtrType*)t)->elem->gc; - objti = 0; - } else { - obj = iface->__object; - // objti = (uintptr)t->gc; - objti = 0; - } - } - break; - - case GC_DEFAULT_PTR: - while((i = stack_top.b) <= end_b) { - stack_top.b += PtrSize; - obj = *(byte**)i; - if((byte*)obj >= arena_start && (byte*)obj < arena_used) { - *ptrbufpos++ = (struct PtrTarget){obj, 0}; - if(ptrbufpos == ptrbuf_end) - flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf); - } - } - goto next_block; - - case GC_END: - if(--stack_top.count != 0) { - // Next iteration of a loop if possible. - elemsize = stack_top.elemsize; - stack_top.b += elemsize; - if(stack_top.b + elemsize <= end_b+PtrSize) { - pc = stack_top.loop_or_ret; - continue; - } - i = stack_top.b; - } else { - // Stack pop if possible. - if(stack_ptr+1 < stack+nelem(stack)) { - pc = stack_top.loop_or_ret; - stack_top = *(++stack_ptr); - continue; - } - i = (uintptr)b + nominal_size; - } - if(!precise_type) { - // Quickly scan [b+i,b+n) for possible pointers. - for(; i<=end_b; i+=PtrSize) { - if(*(byte**)i != nil) { - // Found a value that may be a pointer. - // Do a rescan of the entire block. - enqueue((Obj){b, n, 0}, &wbuf, &wp, &nobj); - break; - } - } - } - goto next_block; - - case GC_ARRAY_START: - i = stack_top.b + pc[1]; - count = pc[2]; - elemsize = pc[3]; - pc += 4; - - // Stack push. - *stack_ptr-- = stack_top; - stack_top = (Frame){count, elemsize, i, pc}; - continue; - - case GC_ARRAY_NEXT: - if(--stack_top.count != 0) { - stack_top.b += stack_top.elemsize; - pc = stack_top.loop_or_ret; - } else { - // Stack pop. - stack_top = *(++stack_ptr); - pc += 1; - } - continue; - - case GC_CALL: - // Stack push. - *stack_ptr-- = stack_top; - stack_top = (Frame){1, 0, stack_top.b + pc[1], pc+3 /*return address*/}; - pc = (uintptr*)pc[2]; // target of the CALL instruction - continue; - - case GC_MAP_PTR: - // TODO(atom): to be expanded in a next CL. Same as GC_APTR for now. - obj = *(void**)(stack_top.b + pc[1]); - pc += 3; - break; - - case GC_REGION: - // TODO(atom): to be expanded in a next CL. Same as GC_APTR for now. - obj = (void*)(stack_top.b + pc[1]); - pc += 4; - break; - - default: - runtime_throw("scanblock: invalid GC instruction"); - return; - } - - if((byte*)obj >= arena_start && (byte*)obj < arena_used) { - *ptrbufpos++ = (PtrTarget){obj, objti}; - if(ptrbufpos == ptrbuf_end) - flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf); - } - } - - next_block: - // Done scanning [b, b+n). Prepare for the next iteration of - // the loop by setting b, n, ti to the parameters for the next block. - - if(nobj == 0) { - flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf); - - if(nobj == 0) { - if(!keepworking) { - if(wbuf) - putempty(wbuf); - goto endscan; - } - // Emptied our buffer: refill. - wbuf = getfull(wbuf); - if(wbuf == nil) - goto endscan; - nobj = wbuf->nobj; - wp = wbuf->obj + wbuf->nobj; - } - } - - // Fetch b from the work buffer. - --wp; - b = wp->p; - n = wp->n; - ti = wp->ti; - nobj--; - } - -endscan: - runtime_lock(&lock); - scanbuffers->next = bufferList; - bufferList = scanbuffers; - runtime_unlock(&lock); -} - -// debug_scanblock is the debug copy of scanblock. -// it is simpler, slower, single-threaded, recursive, -// and uses bitSpecial as the mark bit. -static void -debug_scanblock(byte *b, uintptr n) -{ - byte *obj, *p; - void **vp; - uintptr size, *bitp, bits, shift, i, xbits, off; - MSpan *s; - - if(!DebugMark) - runtime_throw("debug_scanblock without DebugMark"); - - if((intptr)n < 0) { - runtime_printf("debug_scanblock %p %D\n", b, (int64)n); - runtime_throw("debug_scanblock"); - } - - // Align b to a word boundary. - off = (uintptr)b & (PtrSize-1); - if(off != 0) { - b += PtrSize - off; - n -= PtrSize - off; - } - - vp = (void**)b; - n /= PtrSize; - for(i=0; i<(uintptr)n; i++) { - obj = (byte*)vp[i]; - - // Words outside the arena cannot be pointers. - if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used) - continue; - - // Round down to word boundary. - obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1)); - - // Consult span table to find beginning. - s = runtime_MHeap_LookupMaybe(&runtime_mheap, obj); - if(s == nil) - continue; - - p = (byte*)((uintptr)s->start<<PageShift); - size = s->elemsize; - if(s->sizeclass == 0) { - obj = p; - } else { - if((byte*)obj >= (byte*)s->limit) - continue; - int32 i = ((byte*)obj - p)/size; - obj = p+i*size; - } - - // Now that we know the object header, reload bits. - off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start; - bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - xbits = *bitp; - bits = xbits >> shift; - - // Now we have bits, bitp, and shift correct for - // obj pointing at the base of the object. - // If not allocated or already marked, done. - if((bits & bitAllocated) == 0 || (bits & bitSpecial) != 0) // NOTE: bitSpecial not bitMarked - continue; - *bitp |= bitSpecial<<shift; - if(!(bits & bitMarked)) - runtime_printf("found unmarked block %p in %p\n", obj, vp+i); - - // If object has no pointers, don't need to scan further. - if((bits & bitNoPointers) != 0) - continue; - - debug_scanblock(obj, size); - } -} - -// Append obj to the work buffer. -// _wbuf, _wp, _nobj are input/output parameters and are specifying the work buffer. -static void -enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj) -{ - uintptr nobj, off; - Obj *wp; - Workbuf *wbuf; - - if(Debug > 1) - runtime_printf("append obj(%p %D %p)\n", obj.p, (int64)obj.n, obj.ti); - - // Align obj.b to a word boundary. - off = (uintptr)obj.p & (PtrSize-1); - if(off != 0) { - obj.p += PtrSize - off; - obj.n -= PtrSize - off; - obj.ti = 0; - } - - if(obj.p == nil || obj.n == 0) - return; - - // Load work buffer state - wp = *_wp; - wbuf = *_wbuf; - nobj = *_nobj; - - // If another proc wants a pointer, give it some. - if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) { - wbuf->nobj = nobj; - wbuf = handoff(wbuf); - nobj = wbuf->nobj; - wp = wbuf->obj + nobj; - } - - // If buffer is full, get a new one. - if(wbuf == nil || nobj >= nelem(wbuf->obj)) { - if(wbuf != nil) - wbuf->nobj = nobj; - wbuf = getempty(wbuf); - wp = wbuf->obj; - nobj = 0; - } - - *wp = obj; - wp++; - nobj++; - - // Save work buffer state - *_wp = wp; - *_wbuf = wbuf; - *_nobj = nobj; -} - -static void -markroot(ParFor *desc, uint32 i) -{ - Obj *wp; - Workbuf *wbuf; - uintptr nobj; - - USED(&desc); - wp = nil; - wbuf = nil; - nobj = 0; - enqueue(work.roots[i], &wbuf, &wp, &nobj); - scanblock(wbuf, wp, nobj, false); -} - -// Get an empty work buffer off the work.empty list, -// allocating new buffers as needed. -static Workbuf* -getempty(Workbuf *b) -{ - if(b != nil) - runtime_lfstackpush(&work.full, &b->node); - b = (Workbuf*)runtime_lfstackpop(&work.empty); - if(b == nil) { - // Need to allocate. - runtime_lock(&work); - if(work.nchunk < sizeof *b) { - work.nchunk = 1<<20; - work.chunk = runtime_SysAlloc(work.nchunk); - } - b = (Workbuf*)work.chunk; - work.chunk += sizeof *b; - work.nchunk -= sizeof *b; - runtime_unlock(&work); - } - b->nobj = 0; - return b; -} - -static void -putempty(Workbuf *b) -{ - runtime_lfstackpush(&work.empty, &b->node); -} - -// Get a full work buffer off the work.full list, or return nil. -static Workbuf* -getfull(Workbuf *b) -{ - M *m; - int32 i; - - if(b != nil) - runtime_lfstackpush(&work.empty, &b->node); - b = (Workbuf*)runtime_lfstackpop(&work.full); - if(b != nil || work.nproc == 1) - return b; - - m = runtime_m(); - runtime_xadd(&work.nwait, +1); - for(i=0;; i++) { - if(work.full != 0) { - runtime_xadd(&work.nwait, -1); - b = (Workbuf*)runtime_lfstackpop(&work.full); - if(b != nil) - return b; - runtime_xadd(&work.nwait, +1); - } - if(work.nwait == work.nproc) - return nil; - if(i < 10) { - m->gcstats.nprocyield++; - runtime_procyield(20); - } else if(i < 20) { - m->gcstats.nosyield++; - runtime_osyield(); - } else { - m->gcstats.nsleep++; - runtime_usleep(100); - } - } -} - -static Workbuf* -handoff(Workbuf *b) -{ - M *m; - int32 n; - Workbuf *b1; - - m = runtime_m(); - - // Make new buffer with half of b's pointers. - b1 = getempty(nil); - n = b->nobj/2; - b->nobj -= n; - b1->nobj = n; - runtime_memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]); - m->gcstats.nhandoff++; - m->gcstats.nhandoffcnt += n; - - // Put b on full list - let first half of b get stolen. - runtime_lfstackpush(&work.full, &b->node); - return b1; -} - -static void -addroot(Obj obj) -{ - uint32 cap; - Obj *new; - - if(work.nroot >= work.rootcap) { - cap = PageSize/sizeof(Obj); - if(cap < 2*work.rootcap) - cap = 2*work.rootcap; - new = (Obj*)runtime_SysAlloc(cap*sizeof(Obj)); - if(work.roots != nil) { - runtime_memmove(new, work.roots, work.rootcap*sizeof(Obj)); - runtime_SysFree(work.roots, work.rootcap*sizeof(Obj)); - } - work.roots = new; - work.rootcap = cap; - } - work.roots[work.nroot] = obj; - work.nroot++; -} - -static void -addstackroots(G *gp) -{ -#ifdef USING_SPLIT_STACK - M *mp; - void* sp; - size_t spsize; - void* next_segment; - void* next_sp; - void* initial_sp; - - if(gp == runtime_g()) { - // Scanning our own stack. - sp = __splitstack_find(nil, nil, &spsize, &next_segment, - &next_sp, &initial_sp); - } else if((mp = gp->m) != nil && mp->helpgc) { - // gchelper's stack is in active use and has no interesting pointers. - return; - } else { - // Scanning another goroutine's stack. - // The goroutine is usually asleep (the world is stopped). - - // The exception is that if the goroutine is about to enter or might - // have just exited a system call, it may be executing code such - // as schedlock and may have needed to start a new stack segment. - // Use the stack segment and stack pointer at the time of - // the system call instead, since that won't change underfoot. - if(gp->gcstack != nil) { - sp = gp->gcstack; - spsize = gp->gcstack_size; - next_segment = gp->gcnext_segment; - next_sp = gp->gcnext_sp; - initial_sp = gp->gcinitial_sp; - } else { - sp = __splitstack_find_context(&gp->stack_context[0], - &spsize, &next_segment, - &next_sp, &initial_sp); - } - } - if(sp != nil) { - addroot((Obj){sp, spsize, 0}); - while((sp = __splitstack_find(next_segment, next_sp, - &spsize, &next_segment, - &next_sp, &initial_sp)) != nil) - addroot((Obj){sp, spsize, 0}); - } -#else - M *mp; - byte* bottom; - byte* top; - - if(gp == runtime_g()) { - // Scanning our own stack. - bottom = (byte*)&gp; - } else if((mp = gp->m) != nil && mp->helpgc) { - // gchelper's stack is in active use and has no interesting pointers. - return; - } else { - // Scanning another goroutine's stack. - // The goroutine is usually asleep (the world is stopped). - bottom = (byte*)gp->gcnext_sp; - if(bottom == nil) - return; - } - top = (byte*)gp->gcinitial_sp + gp->gcstack_size; - if(top > bottom) - addroot((Obj){bottom, top - bottom, 0}); - else - addroot((Obj){top, bottom - top, 0}); -#endif -} - -static void -addfinroots(void *v) -{ - uintptr size; - - size = 0; - if(!runtime_mlookup(v, (byte**)&v, &size, nil) || !runtime_blockspecial(v)) - runtime_throw("mark - finalizer inconsistency"); - - // do not mark the finalizer block itself. just mark the things it points at. - addroot((Obj){v, size, 0}); -} - -static struct root_list* roots; - -void -__go_register_gc_roots (struct root_list* r) -{ - // FIXME: This needs locking if multiple goroutines can call - // dlopen simultaneously. - r->next = roots; - roots = r; -} - -static void -addroots(void) -{ - struct root_list *pl; - G *gp; - FinBlock *fb; - MSpan *s, **allspans; - uint32 spanidx; - - work.nroot = 0; - - // mark data+bss. - for(pl = roots; pl != nil; pl = pl->next) { - struct root* pr = &pl->roots[0]; - while(1) { - void *decl = pr->decl; - if(decl == nil) - break; - addroot((Obj){decl, pr->size, 0}); - pr++; - } - } - - addroot((Obj){(byte*)&runtime_m0, sizeof runtime_m0, 0}); - addroot((Obj){(byte*)&runtime_g0, sizeof runtime_g0, 0}); - addroot((Obj){(byte*)&runtime_allg, sizeof runtime_allg, 0}); - addroot((Obj){(byte*)&runtime_allm, sizeof runtime_allm, 0}); - runtime_MProf_Mark(addroot); - runtime_time_scan(addroot); - runtime_trampoline_scan(addroot); - - // MSpan.types - allspans = runtime_mheap.allspans; - for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) { - s = allspans[spanidx]; - if(s->state == MSpanInUse) { - switch(s->types.compression) { - case MTypes_Empty: - case MTypes_Single: - break; - case MTypes_Words: - case MTypes_Bytes: - // TODO(atom): consider using defaultProg instead of 0 - addroot((Obj){(byte*)&s->types.data, sizeof(void*), 0}); - break; - } - } - } - - // stacks - for(gp=runtime_allg; gp!=nil; gp=gp->alllink) { - switch(gp->status){ - default: - runtime_printf("unexpected G.status %d\n", gp->status); - runtime_throw("mark - bad status"); - case Gdead: - break; - case Grunning: - if(gp != runtime_g()) - runtime_throw("mark - world not stopped"); - addstackroots(gp); - break; - case Grunnable: - case Gsyscall: - case Gwaiting: - addstackroots(gp); - break; - } - } - - runtime_walkfintab(addfinroots, addroot); - - for(fb=allfin; fb; fb=fb->alllink) - addroot((Obj){(byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), 0}); - - addroot((Obj){(byte*)&work, sizeof work, 0}); -} - -static bool -handlespecial(byte *p, uintptr size) -{ - void (*fn)(void*); - const struct __go_func_type *ft; - FinBlock *block; - Finalizer *f; - - if(!runtime_getfinalizer(p, true, &fn, &ft)) { - runtime_setblockspecial(p, false); - runtime_MProf_Free(p, size); - return false; - } - - runtime_lock(&finlock); - if(finq == nil || finq->cnt == finq->cap) { - if(finc == nil) { - finc = runtime_SysAlloc(PageSize); - finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1; - finc->alllink = allfin; - allfin = finc; - } - block = finc; - finc = block->next; - block->next = finq; - finq = block; - } - f = &finq->fin[finq->cnt]; - finq->cnt++; - f->fn = fn; - f->ft = ft; - f->arg = p; - runtime_unlock(&finlock); - return true; -} - -// Sweep frees or collects finalizers for blocks not marked in the mark phase. -// It clears the mark bits in preparation for the next GC round. -static void -sweepspan(ParFor *desc, uint32 idx) -{ - M *m; - int32 cl, n, npages; - uintptr size; - byte *p; - MCache *c; - byte *arena_start; - MLink head, *end; - int32 nfree; - byte *type_data; - byte compression; - uintptr type_data_inc; - MSpan *s; - - m = runtime_m(); - - USED(&desc); - s = runtime_mheap.allspans[idx]; - if(s->state != MSpanInUse) - return; - arena_start = runtime_mheap.arena_start; - p = (byte*)(s->start << PageShift); - cl = s->sizeclass; - size = s->elemsize; - if(cl == 0) { - n = 1; - } else { - // Chunk full of small blocks. - npages = runtime_class_to_allocnpages[cl]; - n = (npages << PageShift) / size; - } - nfree = 0; - end = &head; - c = m->mcache; - - type_data = (byte*)s->types.data; - type_data_inc = sizeof(uintptr); - compression = s->types.compression; - switch(compression) { - case MTypes_Bytes: - type_data += 8*sizeof(uintptr); - type_data_inc = 1; - break; - } - - // Sweep through n objects of given size starting at p. - // This thread owns the span now, so it can manipulate - // the block bitmap without atomic operations. - for(; n > 0; n--, p += size, type_data+=type_data_inc) { - uintptr off, *bitp, shift, bits; - - off = (uintptr*)p - (uintptr*)arena_start; - bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - bits = *bitp>>shift; - - if((bits & bitAllocated) == 0) - continue; - - if((bits & bitMarked) != 0) { - if(DebugMark) { - if(!(bits & bitSpecial)) - runtime_printf("found spurious mark on %p\n", p); - *bitp &= ~(bitSpecial<<shift); - } - *bitp &= ~(bitMarked<<shift); - continue; - } - - // Special means it has a finalizer or is being profiled. - // In DebugMark mode, the bit has been coopted so - // we have to assume all blocks are special. - if(DebugMark || (bits & bitSpecial) != 0) { - if(handlespecial(p, size)) - continue; - } - - // Mark freed; restore block boundary bit. - *bitp = (*bitp & ~(bitMask<<shift)) | (bitBlockBoundary<<shift); - - if(cl == 0) { - // Free large span. - runtime_unmarkspan(p, 1<<PageShift); - *(uintptr*)p = 1; // needs zeroing - runtime_MHeap_Free(&runtime_mheap, s, 1); - c->local_alloc -= size; - c->local_nfree++; - } else { - // Free small object. - switch(compression) { - case MTypes_Words: - *(uintptr*)type_data = 0; - break; - case MTypes_Bytes: - *(byte*)type_data = 0; - break; - } - if(size > sizeof(uintptr)) - ((uintptr*)p)[1] = 1; // mark as "needs to be zeroed" - - end->next = (MLink*)p; - end = (MLink*)p; - nfree++; - } - } - - if(nfree) { - c->local_by_size[cl].nfree += nfree; - c->local_alloc -= size * nfree; - c->local_nfree += nfree; - c->local_cachealloc -= nfree * size; - c->local_objects -= nfree; - runtime_MCentral_FreeSpan(&runtime_mheap.central[cl], s, nfree, head.next, end); - } -} - -static void -dumpspan(uint32 idx) -{ - int32 sizeclass, n, npages, i, column; - uintptr size; - byte *p; - byte *arena_start; - MSpan *s; - bool allocated, special; - - s = runtime_mheap.allspans[idx]; - if(s->state != MSpanInUse) - return; - arena_start = runtime_mheap.arena_start; - p = (byte*)(s->start << PageShift); - sizeclass = s->sizeclass; - size = s->elemsize; - if(sizeclass == 0) { - n = 1; - } else { - npages = runtime_class_to_allocnpages[sizeclass]; - n = (npages << PageShift) / size; - } - - runtime_printf("%p .. %p:\n", p, p+n*size); - column = 0; - for(; n>0; n--, p+=size) { - uintptr off, *bitp, shift, bits; - - off = (uintptr*)p - (uintptr*)arena_start; - bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - bits = *bitp>>shift; - - allocated = ((bits & bitAllocated) != 0); - special = ((bits & bitSpecial) != 0); - - for(i=0; (uint32)i<size; i+=sizeof(void*)) { - if(column == 0) { - runtime_printf("\t"); - } - if(i == 0) { - runtime_printf(allocated ? "(" : "["); - runtime_printf(special ? "@" : ""); - runtime_printf("%p: ", p+i); - } else { - runtime_printf(" "); - } - - runtime_printf("%p", *(void**)(p+i)); - - if(i+sizeof(void*) >= size) { - runtime_printf(allocated ? ") " : "] "); - } - - column++; - if(column == 8) { - runtime_printf("\n"); - column = 0; - } - } - } - runtime_printf("\n"); -} - -// A debugging function to dump the contents of memory -void -runtime_memorydump(void) -{ - uint32 spanidx; - - for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) { - dumpspan(spanidx); - } -} - -void -runtime_gchelper(void) -{ - // parallel mark for over gc roots - runtime_parfordo(work.markfor); - - // help other threads scan secondary blocks - scanblock(nil, nil, 0, true); - - if(DebugMark) { - // wait while the main thread executes mark(debug_scanblock) - while(runtime_atomicload(&work.debugmarkdone) == 0) - runtime_usleep(10); - } - - runtime_parfordo(work.sweepfor); - if(runtime_xadd(&work.ndone, +1) == work.nproc-1) - runtime_notewakeup(&work.alldone); -} - -// 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; - -static void -stealcache(void) -{ - M *mp; - - for(mp=runtime_allm; mp; mp=mp->alllink) - runtime_MCache_ReleaseAll(mp->mcache); -} - -static void -cachestats(GCStats *stats) -{ - M *mp; - MCache *c; - uint32 i; - uint64 stacks_inuse; - uint64 *src, *dst; - - if(stats) - runtime_memclr((byte*)stats, sizeof(*stats)); - stacks_inuse = 0; - for(mp=runtime_allm; mp; mp=mp->alllink) { - c = mp->mcache; - runtime_purgecachedstats(c); - // stacks_inuse += mp->stackinuse*FixedStack; - if(stats) { - src = (uint64*)&mp->gcstats; - dst = (uint64*)stats; - for(i=0; i<sizeof(*stats)/sizeof(uint64); i++) - dst[i] += src[i]; - runtime_memclr((byte*)&mp->gcstats, sizeof(mp->gcstats)); - } - for(i=0; i<nelem(c->local_by_size); i++) { - mstats.by_size[i].nmalloc += c->local_by_size[i].nmalloc; - c->local_by_size[i].nmalloc = 0; - mstats.by_size[i].nfree += c->local_by_size[i].nfree; - c->local_by_size[i].nfree = 0; - } - } - mstats.stacks_inuse = stacks_inuse; -} - -// Structure of arguments passed to function gc(). -// This allows the arguments to be passed via reflect_call. -struct gc_args -{ - int32 force; -}; - -static void gc(struct gc_args *args); - -void -runtime_gc(int32 force) -{ - M *m; - const byte *p; - struct gc_args a, *ap; - - // The atomic operations are not atomic if the uint64s - // are not aligned on uint64 boundaries. This has been - // a problem in the past. - if((((uintptr)&work.empty) & 7) != 0) - runtime_throw("runtime: gc work buffer is misaligned"); - - // Make sure all registers are saved on stack so that - // scanstack sees them. - __builtin_unwind_init(); - - // 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. - m = runtime_m(); - if(!mstats.enablegc || m->locks > 0 || runtime_panicking) - return; - - if(gcpercent == -2) { // first time through - p = runtime_getenv("GOGC"); - if(p == nil || p[0] == '\0') - gcpercent = 100; - else if(runtime_strcmp((const char*)p, "off") == 0) - gcpercent = -1; - else - gcpercent = runtime_atoi(p); - - p = runtime_getenv("GOGCTRACE"); - if(p != nil) - gctrace = runtime_atoi(p); - } - if(gcpercent < 0) - return; - - // Run gc on a bigger stack to eliminate - // a potentially large number of calls to runtime_morestack. - // But not when using gccgo. - a.force = force; - ap = &a; - gc(ap); - - if(gctrace > 1 && !force) { - a.force = 1; - gc(&a); - } -} - -static void -gc(struct gc_args *args) -{ - M *m; - int64 t0, t1, t2, t3, t4; - uint64 heap0, heap1, obj0, obj1; - GCStats stats; - M *mp; - uint32 i; - // Eface eface; - - runtime_semacquire(&runtime_worldsema); - if(!args->force && mstats.heap_alloc < mstats.next_gc) { - runtime_semrelease(&runtime_worldsema); - return; - } - - m = runtime_m(); - - t0 = runtime_nanotime(); - - m->gcing = 1; - runtime_stoptheworld(); - - for(mp=runtime_allm; mp; mp=mp->alllink) - runtime_settype_flush(mp, false); - - heap0 = 0; - obj0 = 0; - if(gctrace) { - cachestats(nil); - heap0 = mstats.heap_alloc; - obj0 = mstats.nmalloc - mstats.nfree; - } - - m->locks++; // disable gc during mallocs in parforalloc - if(work.markfor == nil) - work.markfor = runtime_parforalloc(MaxGcproc); - if(work.sweepfor == nil) - work.sweepfor = runtime_parforalloc(MaxGcproc); - m->locks--; - - if(itabtype == nil) { - // get C pointer to the Go type "itab" - // runtime_gc_itab_ptr(&eface); - // itabtype = ((PtrType*)eface.type)->elem; - } - - work.nwait = 0; - work.ndone = 0; - work.debugmarkdone = 0; - work.nproc = runtime_gcprocs(); - addroots(); - runtime_parforsetup(work.markfor, work.nproc, work.nroot, nil, false, markroot); - runtime_parforsetup(work.sweepfor, work.nproc, runtime_mheap.nspan, nil, true, sweepspan); - if(work.nproc > 1) { - runtime_noteclear(&work.alldone); - runtime_helpgc(work.nproc); - } - - t1 = runtime_nanotime(); - - runtime_parfordo(work.markfor); - scanblock(nil, nil, 0, true); - - if(DebugMark) { - for(i=0; i<work.nroot; i++) - debug_scanblock(work.roots[i].p, work.roots[i].n); - runtime_atomicstore(&work.debugmarkdone, 1); - } - t2 = runtime_nanotime(); - - runtime_parfordo(work.sweepfor); - t3 = runtime_nanotime(); - - stealcache(); - cachestats(&stats); - - if(work.nproc > 1) - runtime_notesleep(&work.alldone); - - stats.nprocyield += work.sweepfor->nprocyield; - stats.nosyield += work.sweepfor->nosyield; - stats.nsleep += work.sweepfor->nsleep; - - mstats.next_gc = mstats.heap_alloc+(mstats.heap_alloc-runtime_stacks_sys)*gcpercent/100; - m->gcing = 0; - - if(finq != nil) { - m->locks++; // disable gc during the mallocs in newproc - // kick off or wake up goroutine to run queued finalizers - if(fing == nil) - fing = __go_go(runfinq, nil); - else if(fingwait) { - fingwait = 0; - runtime_ready(fing); - } - m->locks--; - } - - heap1 = mstats.heap_alloc; - obj1 = mstats.nmalloc - mstats.nfree; - - t4 = runtime_nanotime(); - mstats.last_gc = t4; - mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0; - mstats.pause_total_ns += t4 - t0; - mstats.numgc++; - if(mstats.debuggc) - runtime_printf("pause %D\n", t4-t0); - - if(gctrace) { - runtime_printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-%D) objects," - " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n", - mstats.numgc, work.nproc, (t2-t1)/1000000, (t3-t2)/1000000, (t1-t0+t4-t3)/1000000, - heap0>>20, heap1>>20, obj0, obj1, - mstats.nmalloc, mstats.nfree, - stats.nhandoff, stats.nhandoffcnt, - work.sweepfor->nsteal, work.sweepfor->nstealcnt, - stats.nprocyield, stats.nosyield, stats.nsleep); - } - - runtime_MProf_GC(); - runtime_semrelease(&runtime_worldsema); - runtime_starttheworld(); - - // give the queued finalizers, if any, a chance to run - if(finq != nil) - runtime_gosched(); -} - -void runtime_ReadMemStats(MStats *) - __asm__ (GOSYM_PREFIX "runtime.ReadMemStats"); - -void -runtime_ReadMemStats(MStats *stats) -{ - M *m; - - // Have to acquire worldsema to stop the world, - // because stoptheworld can only be used by - // one goroutine at a time, and there might be - // a pending garbage collection already calling it. - runtime_semacquire(&runtime_worldsema); - m = runtime_m(); - m->gcing = 1; - runtime_stoptheworld(); - cachestats(nil); - *stats = mstats; - m->gcing = 0; - runtime_semrelease(&runtime_worldsema); - runtime_starttheworld(); -} - -static void -runfinq(void* dummy __attribute__ ((unused))) -{ - Finalizer *f; - FinBlock *fb, *next; - uint32 i; - - for(;;) { - // There's no need for a lock in this section - // because it only conflicts with the garbage - // collector, and the garbage collector only - // runs when everyone else is stopped, and - // runfinq only stops at the gosched() or - // during the calls in the for loop. - fb = finq; - finq = nil; - if(fb == nil) { - fingwait = 1; - runtime_park(nil, nil, "finalizer wait"); - continue; - } - if(raceenabled) - runtime_racefingo(); - for(; fb; fb=next) { - next = fb->next; - for(i=0; i<(uint32)fb->cnt; i++) { - void *params[1]; - - f = &fb->fin[i]; - params[0] = &f->arg; - reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil); - f->fn = nil; - f->arg = nil; - } - fb->cnt = 0; - fb->next = finc; - finc = fb; - } - runtime_gc(1); // trigger another gc to clean up the finalized objects, if possible - } -} - -// mark the block at v of size n as allocated. -// If noptr is true, mark it as having no pointers. -void -runtime_markallocated(void *v, uintptr n, bool noptr) -{ - uintptr *b, obits, bits, off, shift; - - if(0) - runtime_printf("markallocated %p+%p\n", v, n); - - if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start) - runtime_throw("markallocated: bad pointer"); - - off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; // word offset - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - - for(;;) { - obits = *b; - bits = (obits & ~(bitMask<<shift)) | (bitAllocated<<shift); - if(noptr) - bits |= bitNoPointers<<shift; - if(runtime_singleproc) { - *b = bits; - break; - } else { - // more than one goroutine is potentially running: use atomic op - if(runtime_casp((void**)b, (void*)obits, (void*)bits)) - break; - } - } -} - -// mark the block at v of size n as freed. -void -runtime_markfreed(void *v, uintptr n) -{ - uintptr *b, obits, bits, off, shift; - - if(0) - runtime_printf("markallocated %p+%p\n", v, n); - - if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start) - runtime_throw("markallocated: bad pointer"); - - off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; // word offset - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - - for(;;) { - obits = *b; - bits = (obits & ~(bitMask<<shift)) | (bitBlockBoundary<<shift); - if(runtime_singleproc) { - *b = bits; - break; - } else { - // more than one goroutine is potentially running: use atomic op - if(runtime_casp((void**)b, (void*)obits, (void*)bits)) - break; - } - } -} - -// check that the block at v of size n is marked freed. -void -runtime_checkfreed(void *v, uintptr n) -{ - uintptr *b, bits, off, shift; - - if(!runtime_checking) - return; - - if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start) - return; // not allocated, so okay - - off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; // word offset - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - - bits = *b>>shift; - if((bits & bitAllocated) != 0) { - runtime_printf("checkfreed %p+%p: off=%p have=%p\n", - v, n, off, bits & bitMask); - runtime_throw("checkfreed: not freed"); - } -} - -// mark the span of memory at v as having n blocks of the given size. -// if leftover is true, there is left over space at the end of the span. -void -runtime_markspan(void *v, uintptr size, uintptr n, bool leftover) -{ - uintptr *b, off, shift; - byte *p; - - if((byte*)v+size*n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start) - runtime_throw("markspan: bad pointer"); - - p = v; - if(leftover) // mark a boundary just past end of last block too - n++; - for(; n-- > 0; p += size) { - // Okay to use non-atomic ops here, because we control - // the entire span, and each bitmap word has bits for only - // one span, so no other goroutines are changing these - // bitmap words. - off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start; // word offset - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - *b = (*b & ~(bitMask<<shift)) | (bitBlockBoundary<<shift); - } -} - -// unmark the span of memory at v of length n bytes. -void -runtime_unmarkspan(void *v, uintptr n) -{ - uintptr *p, *b, off; - - if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start) - runtime_throw("markspan: bad pointer"); - - p = v; - off = p - (uintptr*)runtime_mheap.arena_start; // word offset - if(off % wordsPerBitmapWord != 0) - runtime_throw("markspan: unaligned pointer"); - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - n /= PtrSize; - if(n%wordsPerBitmapWord != 0) - runtime_throw("unmarkspan: unaligned length"); - // Okay to use non-atomic ops here, because we control - // the entire span, and each bitmap word has bits for only - // one span, so no other goroutines are changing these - // bitmap words. - n /= wordsPerBitmapWord; - while(n-- > 0) - *b-- = 0; -} - -bool -runtime_blockspecial(void *v) -{ - uintptr *b, off, shift; - - if(DebugMark) - return true; - - off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - - return (*b & (bitSpecial<<shift)) != 0; -} - -void -runtime_setblockspecial(void *v, bool s) -{ - uintptr *b, off, shift, bits, obits; - - if(DebugMark) - return; - - off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; - b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1; - shift = off % wordsPerBitmapWord; - - for(;;) { - obits = *b; - if(s) - bits = obits | (bitSpecial<<shift); - else - bits = obits & ~(bitSpecial<<shift); - if(runtime_singleproc) { - *b = bits; - break; - } else { - // more than one goroutine is potentially running: use atomic op - if(runtime_casp((void**)b, (void*)obits, (void*)bits)) - break; - } - } -} - -void -runtime_MHeap_MapBits(MHeap *h) -{ - size_t page_size; - - // Caller has added extra mappings to the arena. - // Add extra mappings of bitmap words as needed. - // We allocate extra bitmap pieces in chunks of bitmapChunk. - enum { - bitmapChunk = 8192 - }; - uintptr n; - - n = (h->arena_used - h->arena_start) / wordsPerBitmapWord; - n = (n+bitmapChunk-1) & ~(bitmapChunk-1); - if(h->bitmap_mapped >= n) - return; - - page_size = getpagesize(); - n = (n+page_size-1) & ~(page_size-1); - - runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped); - h->bitmap_mapped = n; -} diff --git a/gcc-4.8.1/libgo/runtime/mgc0.h b/gcc-4.8.1/libgo/runtime/mgc0.h deleted file mode 100644 index a2798ef34..000000000 --- a/gcc-4.8.1/libgo/runtime/mgc0.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 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 (GC) - -// GC instruction opcodes. -// -// The opcode of an instruction is followed by zero or more -// arguments to the instruction. -// -// Meaning of arguments: -// off Offset (in bytes) from the start of the current object -// objgc Pointer to GC info of an object -// len Length of an array -// elemsize Size (in bytes) of an element -// size Size (in bytes) -enum { - GC_END, // End of object, loop or subroutine. Args: none - GC_PTR, // A typed pointer. Args: (off, objgc) - GC_APTR, // Pointer to an arbitrary object. Args: (off) - GC_ARRAY_START, // Start an array with a fixed length. Args: (off, len, elemsize) - GC_ARRAY_NEXT, // The next element of an array. Args: none - GC_CALL, // Call a subroutine. Args: (off, objgc) - GC_MAP_PTR, // Go map. Args: (off, MapType*) - GC_STRING, // Go string. Args: (off) - GC_EFACE, // interface{}. Args: (off) - GC_IFACE, // interface{...}. Args: (off) - GC_SLICE, // Go slice. Args: (off, objgc) - GC_REGION, // A region/part of the current object. Args: (off, size, objgc) - - GC_NUM_INSTR, // Number of instruction opcodes -}; - -enum { - // Size of GC's fixed stack. - // - // The current GC implementation permits: - // - at most 1 stack allocation because of GC_CALL - // - at most GC_STACK_CAPACITY allocations because of GC_ARRAY_START - GC_STACK_CAPACITY = 8, -}; diff --git a/gcc-4.8.1/libgo/runtime/mheap.c b/gcc-4.8.1/libgo/runtime/mheap.c deleted file mode 100644 index 6636b015d..000000000 --- a/gcc-4.8.1/libgo/runtime/mheap.c +++ /dev/null @@ -1,504 +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 "arch.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; - MSpan **all; - uint32 cap; - - h = vh; - s = (MSpan*)p; - if(h->nspan >= h->nspancap) { - cap = 64*1024/sizeof(all[0]); - if(cap < h->nspancap*3/2) - cap = h->nspancap*3/2; - all = (MSpan**)runtime_SysAlloc(cap*sizeof(all[0])); - if(h->allspans) { - runtime_memmove(all, h->allspans, h->nspancap*sizeof(all[0])); - runtime_SysFree(h->allspans, h->nspancap*sizeof(all[0])); - } - h->allspans = all; - h->nspancap = cap; - } - h->allspans[h->nspan++] = s; -} - -// Initialize the heap; fetch memory using alloc. -void -runtime_MHeap_Init(MHeap *h, void *(*alloc)(uintptr)) -{ - uint32 i; - - runtime_FixAlloc_Init(&h->spanalloc, sizeof(MSpan), alloc, RecordSpan, h); - runtime_FixAlloc_Init(&h->cachealloc, sizeof(MCache), alloc, nil, nil); - // h->mapcache needs no init - for(i=0; i<nelem(h->free); i++) - runtime_MSpanList_Init(&h->free[i]); - runtime_MSpanList_Init(&h->large); - for(i=0; i<nelem(h->central); i++) - runtime_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* -runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed) -{ - MSpan *s; - - runtime_lock(h); - runtime_purgecachedstats(runtime_m()->mcache); - s = MHeap_AllocLocked(h, npage, sizeclass); - if(s != nil) { - mstats.heap_inuse += npage<<PageShift; - if(acct) { - mstats.heap_objects++; - mstats.heap_alloc += npage<<PageShift; - } - } - runtime_unlock(h); - if(s != nil && *(uintptr*)(s->start<<PageShift) != 0 && zeroed) - runtime_memclr((byte*)(s->start<<PageShift), s->npages<<PageShift); - return s; -} - -static MSpan* -MHeap_AllocLocked(MHeap *h, uintptr npage, int32 sizeclass) -{ - uintptr n; - MSpan *s, *t; - PageID p; - - // Try in fixed-size lists up to max. - for(n=npage; n < nelem(h->free); n++) { - if(!runtime_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) - runtime_throw("MHeap_AllocLocked - MSpan not free"); - if(s->npages < npage) - runtime_throw("MHeap_AllocLocked - bad npages"); - runtime_MSpanList_Remove(s); - s->state = MSpanInUse; - mstats.heap_idle -= s->npages<<PageShift; - mstats.heap_released -= s->npreleased<<PageShift; - s->npreleased = 0; - - if(s->npages > npage) { - // Trim extra and put it back in the heap. - t = runtime_FixAlloc_Alloc(&h->spanalloc); - mstats.mspan_inuse = h->spanalloc.inuse; - mstats.mspan_sys = h->spanalloc.sys; - runtime_MSpan_Init(t, s->start + npage, s->npages - npage); - s->npages = npage; - p = t->start; - if(sizeof(void*) == 8) - p -= ((uintptr)h->arena_start>>PageShift); - if(p > 0) - h->map[p-1] = s; - h->map[p] = t; - h->map[p+t->npages-1] = t; - *(uintptr*)(t->start<<PageShift) = *(uintptr*)(s->start<<PageShift); // copy "needs zeroing" mark - t->state = MSpanInUse; - MHeap_FreeLocked(h, t); - t->unusedsince = s->unusedsince; // preserve age - } - s->unusedsince = 0; - - // Record span info, because gc needs to be - // able to map interior pointer to containing span. - s->sizeclass = sizeclass; - s->elemsize = (sizeclass==0 ? s->npages<<PageShift : (uintptr)runtime_class_to_size[sizeclass]); - s->types.compression = MTypes_Empty; - p = s->start; - if(sizeof(void*) == 8) - p -= ((uintptr)h->arena_start>>PageShift); - for(n=0; n<npage; n++) - h->map[p+n] = s; - 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; - PageID p; - - // 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. - // Allocate a multiple of 64kB (16 pages). - npage = (npage+15)&~15; - ask = npage<<PageShift; - if(ask < HeapAllocChunk) - ask = HeapAllocChunk; - - v = runtime_MHeap_SysAlloc(h, ask); - if(v == nil) { - if(ask > (npage<<PageShift)) { - ask = npage<<PageShift; - v = runtime_MHeap_SysAlloc(h, ask); - } - if(v == nil) { - runtime_printf("runtime: out of memory: cannot allocate %D-byte block (%D in use)\n", (uint64)ask, mstats.heap_sys); - return false; - } - } - mstats.heap_sys += ask; - - // Create a fake "in use" span and free it, so that the - // right coalescing happens. - s = runtime_FixAlloc_Alloc(&h->spanalloc); - mstats.mspan_inuse = h->spanalloc.inuse; - mstats.mspan_sys = h->spanalloc.sys; - runtime_MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift); - p = s->start; - if(sizeof(void*) == 8) - p -= ((uintptr)h->arena_start>>PageShift); - h->map[p] = s; - h->map[p + s->npages - 1] = s; - s->state = MSpanInUse; - MHeap_FreeLocked(h, s); - return true; -} - -// Look up the span at the given address. -// Address is guaranteed to be in map -// and is guaranteed to be start or end of span. -MSpan* -runtime_MHeap_Lookup(MHeap *h, void *v) -{ - uintptr p; - - p = (uintptr)v; - if(sizeof(void*) == 8) - p -= (uintptr)h->arena_start; - return h->map[p >> PageShift]; -} - -// Look up the span at the given address. -// Address 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* -runtime_MHeap_LookupMaybe(MHeap *h, void *v) -{ - MSpan *s; - PageID p, q; - - if((byte*)v < h->arena_start || (byte*)v >= h->arena_used) - return nil; - p = (uintptr)v>>PageShift; - q = p; - if(sizeof(void*) == 8) - q -= (uintptr)h->arena_start >> PageShift; - s = h->map[q]; - 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 -runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct) -{ - runtime_lock(h); - runtime_purgecachedstats(runtime_m()->mcache); - mstats.heap_inuse -= s->npages<<PageShift; - if(acct) { - mstats.heap_alloc -= s->npages<<PageShift; - mstats.heap_objects--; - } - MHeap_FreeLocked(h, s); - runtime_unlock(h); -} - -static void -MHeap_FreeLocked(MHeap *h, MSpan *s) -{ - uintptr *sp, *tp; - MSpan *t; - PageID p; - - if(s->types.sysalloc) - runtime_settype_sysfree(s); - s->types.compression = MTypes_Empty; - - if(s->state != MSpanInUse || s->ref != 0) { - runtime_printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref); - runtime_throw("MHeap_FreeLocked - invalid free"); - } - mstats.heap_idle += s->npages<<PageShift; - s->state = MSpanFree; - runtime_MSpanList_Remove(s); - sp = (uintptr*)(s->start<<PageShift); - // Stamp newly unused spans. The scavenger will use that - // info to potentially give back some pages to the OS. - s->unusedsince = runtime_nanotime(); - s->npreleased = 0; - - // Coalesce with earlier, later spans. - p = s->start; - if(sizeof(void*) == 8) - p -= (uintptr)h->arena_start >> PageShift; - if(p > 0 && (t = h->map[p-1]) != nil && t->state != MSpanInUse) { - tp = (uintptr*)(t->start<<PageShift); - *tp |= *sp; // propagate "needs zeroing" mark - s->start = t->start; - s->npages += t->npages; - s->npreleased = t->npreleased; // absorb released pages - p -= t->npages; - h->map[p] = s; - runtime_MSpanList_Remove(t); - t->state = MSpanDead; - runtime_FixAlloc_Free(&h->spanalloc, t); - mstats.mspan_inuse = h->spanalloc.inuse; - mstats.mspan_sys = h->spanalloc.sys; - } - if(p+s->npages < nelem(h->map) && (t = h->map[p+s->npages]) != nil && t->state != MSpanInUse) { - tp = (uintptr*)(t->start<<PageShift); - *sp |= *tp; // propagate "needs zeroing" mark - s->npages += t->npages; - s->npreleased += t->npreleased; - h->map[p + s->npages - 1] = s; - runtime_MSpanList_Remove(t); - t->state = MSpanDead; - runtime_FixAlloc_Free(&h->spanalloc, t); - mstats.mspan_inuse = h->spanalloc.inuse; - mstats.mspan_sys = h->spanalloc.sys; - } - - // Insert s into appropriate list. - if(s->npages < nelem(h->free)) - runtime_MSpanList_Insert(&h->free[s->npages], s); - else - runtime_MSpanList_Insert(&h->large, s); -} - -static void -forcegchelper(void *vnote) -{ - Note *note = (Note*)vnote; - - runtime_gc(1); - runtime_notewakeup(note); -} - -// Release (part of) unused memory to OS. -// Goroutine created at startup. -// Loop forever. -void -runtime_MHeap_Scavenger(void* dummy) -{ - MHeap *h; - MSpan *s, *list; - uint64 tick, now, forcegc, limit; - uint32 k, i; - uintptr released, sumreleased; - const byte *env; - bool trace; - Note note, *notep; - - USED(dummy); - - // If we go two minutes without a garbage collection, force one to run. - forcegc = 2*60*1e9; - // If a span goes unused for 5 minutes after a garbage collection, - // we hand it back to the operating system. - limit = 5*60*1e9; - // Make wake-up period small enough for the sampling to be correct. - if(forcegc < limit) - tick = forcegc/2; - else - tick = limit/2; - - trace = false; - env = runtime_getenv("GOGCTRACE"); - if(env != nil) - trace = runtime_atoi(env) > 0; - - h = &runtime_mheap; - for(k=0;; k++) { - runtime_noteclear(¬e); - runtime_entersyscall(); - runtime_notetsleep(¬e, tick); - runtime_exitsyscall(); - - runtime_lock(h); - now = runtime_nanotime(); - if(now - mstats.last_gc > forcegc) { - runtime_unlock(h); - // The scavenger can not block other goroutines, - // otherwise deadlock detector can fire spuriously. - // GC blocks other goroutines via the runtime_worldsema. - runtime_noteclear(¬e); - notep = ¬e; - __go_go(forcegchelper, (void*)notep); - runtime_entersyscall(); - runtime_notesleep(¬e); - runtime_exitsyscall(); - if(trace) - runtime_printf("scvg%d: GC forced\n", k); - runtime_lock(h); - now = runtime_nanotime(); - } - sumreleased = 0; - for(i=0; i < nelem(h->free)+1; i++) { - if(i < nelem(h->free)) - list = &h->free[i]; - else - list = &h->large; - if(runtime_MSpanList_IsEmpty(list)) - continue; - for(s=list->next; s != list; s=s->next) { - if((now - s->unusedsince) > limit) { - released = (s->npages - s->npreleased) << PageShift; - mstats.heap_released += released; - sumreleased += released; - s->npreleased = s->npages; - runtime_SysUnused((void*)(s->start << PageShift), s->npages << PageShift); - } - } - } - runtime_unlock(h); - - if(trace) { - if(sumreleased > 0) - runtime_printf("scvg%d: %p MB released\n", k, sumreleased>>20); - runtime_printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n", - k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20, - mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20); - } - } -} - -// Initialize a new span with the given start and npages. -void -runtime_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->elemsize = 0; - span->state = 0; - span->unusedsince = 0; - span->npreleased = 0; - span->types.compression = MTypes_Empty; -} - -// Initialize an empty doubly-linked list. -void -runtime_MSpanList_Init(MSpan *list) -{ - list->state = MSpanListHead; - list->next = list; - list->prev = list; -} - -void -runtime_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 -runtime_MSpanList_IsEmpty(MSpan *list) -{ - return list->next == list; -} - -void -runtime_MSpanList_Insert(MSpan *list, MSpan *span) -{ - if(span->next != nil || span->prev != nil) { - runtime_printf("failed MSpanList_Insert %p %p %p\n", span, span->next, span->prev); - runtime_throw("MSpanList_Insert"); - } - span->next = list->next; - span->prev = list; - span->next->prev = span; - span->prev->next = span; -} - - diff --git a/gcc-4.8.1/libgo/runtime/mprof.goc b/gcc-4.8.1/libgo/runtime/mprof.goc deleted file mode 100644 index c1b09bea7..000000000 --- a/gcc-4.8.1/libgo/runtime/mprof.goc +++ /dev/null @@ -1,533 +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 profiling. -// Patterned after tcmalloc's algorithms; shorter code. - -package runtime -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "defs.h" -#include "go-type.h" -#include "go-string.h" - -// NOTE(rsc): Everything here could use cas if contention became an issue. -static Lock proflock; - -enum { MProf, BProf }; // profile types - -// Per-call-stack profiling information. -// Lookup by hashing call stack into a linked-list hash table. -typedef struct Bucket Bucket; -struct Bucket -{ - Bucket *next; // next in hash list - Bucket *allnext; // next in list of all mbuckets/bbuckets - int32 typ; - union - { - struct // typ == MProf - { - uintptr allocs; - uintptr frees; - uintptr alloc_bytes; - uintptr free_bytes; - uintptr recent_allocs; // since last gc - uintptr recent_frees; - uintptr recent_alloc_bytes; - uintptr recent_free_bytes; - }; - struct // typ == BProf - { - int64 count; - int64 cycles; - }; - }; - uintptr hash; - uintptr nstk; - Location stk[1]; -}; -enum { - BuckHashSize = 179999, -}; -static Bucket **buckhash; -static Bucket *mbuckets; // memory profile buckets -static Bucket *bbuckets; // blocking profile buckets -static uintptr bucketmem; - -// Return the bucket for stk[0:nstk], allocating new bucket if needed. -static Bucket* -stkbucket(int32 typ, Location *stk, int32 nstk, bool alloc) -{ - int32 i, j; - uintptr h; - Bucket *b; - - if(buckhash == nil) { - buckhash = runtime_SysAlloc(BuckHashSize*sizeof buckhash[0]); - mstats.buckhash_sys += BuckHashSize*sizeof buckhash[0]; - } - - // Hash stack. - h = 0; - for(i=0; i<nstk; i++) { - h += stk[i].pc; - h += h<<10; - h ^= h>>6; - } - h += h<<3; - h ^= h>>11; - - i = h%BuckHashSize; - for(b = buckhash[i]; b; b=b->next) { - if(b->typ == typ && b->hash == h && b->nstk == (uintptr)nstk) { - for(j = 0; j < nstk; j++) { - if(b->stk[j].pc != stk[j].pc || - b->stk[j].lineno != stk[j].lineno || - !__go_strings_equal(b->stk[j].filename, stk[j].filename)) - break; - } - if (j == nstk) - return b; - } - } - - if(!alloc) - return nil; - - b = runtime_mallocgc(sizeof *b + nstk*sizeof stk[0], FlagNoProfiling, 0, 1); - bucketmem += sizeof *b + nstk*sizeof stk[0]; - runtime_memmove(b->stk, stk, nstk*sizeof stk[0]); - b->typ = typ; - b->hash = h; - b->nstk = nstk; - b->next = buckhash[i]; - buckhash[i] = b; - if(typ == MProf) { - b->allnext = mbuckets; - mbuckets = b; - } else { - b->allnext = bbuckets; - bbuckets = b; - } - return b; -} - -// Record that a gc just happened: all the 'recent' statistics are now real. -void -runtime_MProf_GC(void) -{ - Bucket *b; - - runtime_lock(&proflock); - for(b=mbuckets; b; b=b->allnext) { - b->allocs += b->recent_allocs; - b->frees += b->recent_frees; - b->alloc_bytes += b->recent_alloc_bytes; - b->free_bytes += b->recent_free_bytes; - b->recent_allocs = 0; - b->recent_frees = 0; - b->recent_alloc_bytes = 0; - b->recent_free_bytes = 0; - } - runtime_unlock(&proflock); -} - -// Map from pointer to Bucket* that allocated it. -// Three levels: -// Linked-list hash table for top N-AddrHashShift bits. -// Array index for next AddrDenseBits bits. -// Linked list for next AddrHashShift-AddrDenseBits bits. -// This is more efficient than using a general map, -// because of the typical clustering of the pointer keys. - -typedef struct AddrHash AddrHash; -typedef struct AddrEntry AddrEntry; - -enum { - AddrHashBits = 12, // good for 4GB of used address space - AddrHashShift = 20, // each AddrHash knows about 1MB of address space - AddrDenseBits = 8, // good for a profiling rate of 4096 bytes -}; - -struct AddrHash -{ - AddrHash *next; // next in top-level hash table linked list - uintptr addr; // addr>>20 - AddrEntry *dense[1<<AddrDenseBits]; -}; - -struct AddrEntry -{ - AddrEntry *next; // next in bottom-level linked list - uint32 addr; - Bucket *b; -}; - -static AddrHash *addrhash[1<<AddrHashBits]; -static AddrEntry *addrfree; -static uintptr addrmem; - -// Multiplicative hash function: -// hashMultiplier is the bottom 32 bits of int((sqrt(5)-1)/2 * (1<<32)). -// This is a good multiplier as suggested in CLR, Knuth. The hash -// value is taken to be the top AddrHashBits bits of the bottom 32 bits -// of the multiplied value. -enum { - HashMultiplier = 2654435769U -}; - -// Set the bucket associated with addr to b. -static void -setaddrbucket(uintptr addr, Bucket *b) -{ - int32 i; - uint32 h; - AddrHash *ah; - AddrEntry *e; - - h = (uint32)((addr>>AddrHashShift)*HashMultiplier) >> (32-AddrHashBits); - for(ah=addrhash[h]; ah; ah=ah->next) - if(ah->addr == (addr>>AddrHashShift)) - goto found; - - ah = runtime_mallocgc(sizeof *ah, FlagNoProfiling, 0, 1); - addrmem += sizeof *ah; - ah->next = addrhash[h]; - ah->addr = addr>>AddrHashShift; - addrhash[h] = ah; - -found: - if((e = addrfree) == nil) { - e = runtime_mallocgc(64*sizeof *e, FlagNoProfiling, 0, 0); - addrmem += 64*sizeof *e; - for(i=0; i+1<64; i++) - e[i].next = &e[i+1]; - e[63].next = nil; - } - addrfree = e->next; - e->addr = (uint32)~(addr & ((1<<AddrHashShift)-1)); - e->b = b; - h = (addr>>(AddrHashShift-AddrDenseBits))&(nelem(ah->dense)-1); // entry in dense is top 8 bits of low 20. - e->next = ah->dense[h]; - ah->dense[h] = e; -} - -// Get the bucket associated with addr and clear the association. -static Bucket* -getaddrbucket(uintptr addr) -{ - uint32 h; - AddrHash *ah; - AddrEntry *e, **l; - Bucket *b; - - h = (uint32)((addr>>AddrHashShift)*HashMultiplier) >> (32-AddrHashBits); - for(ah=addrhash[h]; ah; ah=ah->next) - if(ah->addr == (addr>>AddrHashShift)) - goto found; - return nil; - -found: - h = (addr>>(AddrHashShift-AddrDenseBits))&(nelem(ah->dense)-1); // entry in dense is top 8 bits of low 20. - for(l=&ah->dense[h]; (e=*l) != nil; l=&e->next) { - if(e->addr == (uint32)~(addr & ((1<<AddrHashShift)-1))) { - *l = e->next; - b = e->b; - e->next = addrfree; - addrfree = e; - return b; - } - } - return nil; -} - -// Called by malloc to record a profiled block. -void -runtime_MProf_Malloc(void *p, uintptr size) -{ - M *m; - int32 nstk; - Location stk[32]; - Bucket *b; - - m = runtime_m(); - if(m->nomemprof > 0) - return; - - m->nomemprof++; - nstk = runtime_callers(1, stk, 32); - runtime_lock(&proflock); - b = stkbucket(MProf, stk, nstk, true); - b->recent_allocs++; - b->recent_alloc_bytes += size; - setaddrbucket((uintptr)p, b); - runtime_unlock(&proflock); - m = runtime_m(); - m->nomemprof--; -} - -// Called when freeing a profiled block. -void -runtime_MProf_Free(void *p, uintptr size) -{ - M *m; - Bucket *b; - - m = runtime_m(); - if(m->nomemprof > 0) - return; - - m->nomemprof++; - runtime_lock(&proflock); - b = getaddrbucket((uintptr)p); - if(b != nil) { - b->recent_frees++; - b->recent_free_bytes += size; - } - runtime_unlock(&proflock); - m = runtime_m(); - m->nomemprof--; -} - -int64 runtime_blockprofilerate; // in CPU ticks - -void runtime_SetBlockProfileRate(intgo) __asm__ (GOSYM_PREFIX "runtime.SetBlockProfileRate"); - -void -runtime_SetBlockProfileRate(intgo rate) -{ - runtime_atomicstore64((uint64*)&runtime_blockprofilerate, rate * runtime_tickspersecond() / (1000*1000*1000)); -} - -void -runtime_blockevent(int64 cycles, int32 skip) -{ - int32 nstk; - int64 rate; - Location stk[32]; - Bucket *b; - - if(cycles <= 0) - return; - rate = runtime_atomicload64((uint64*)&runtime_blockprofilerate); - if(rate <= 0 || (rate > cycles && runtime_fastrand1()%rate > cycles)) - return; - - nstk = runtime_callers(skip, stk, 32); - runtime_lock(&proflock); - b = stkbucket(BProf, stk, nstk, true); - b->count++; - b->cycles += cycles; - runtime_unlock(&proflock); -} - -// Go interface to profile data. (Declared in debug.go) - -// Must match MemProfileRecord in debug.go. -typedef struct Record Record; -struct Record { - int64 alloc_bytes, free_bytes; - int64 alloc_objects, free_objects; - uintptr stk[32]; -}; - -// Write b's data to r. -static void -record(Record *r, Bucket *b) -{ - uint32 i; - - r->alloc_bytes = b->alloc_bytes; - r->free_bytes = b->free_bytes; - r->alloc_objects = b->allocs; - r->free_objects = b->frees; - for(i=0; i<b->nstk && i<nelem(r->stk); i++) - r->stk[i] = b->stk[i].pc; - for(; i<nelem(r->stk); i++) - r->stk[i] = 0; -} - -func MemProfile(p Slice, include_inuse_zero bool) (n int, ok bool) { - Bucket *b; - Record *r; - - runtime_lock(&proflock); - n = 0; - for(b=mbuckets; b; b=b->allnext) - if(include_inuse_zero || b->alloc_bytes != b->free_bytes) - n++; - ok = false; - if(n <= p.__count) { - ok = true; - r = (Record*)p.__values; - for(b=mbuckets; b; b=b->allnext) - if(include_inuse_zero || b->alloc_bytes != b->free_bytes) - record(r++, b); - } - runtime_unlock(&proflock); -} - -void -runtime_MProf_Mark(void (*addroot)(Obj)) -{ - // buckhash is not allocated via mallocgc. - addroot((Obj){(byte*)&mbuckets, sizeof mbuckets, 0}); - addroot((Obj){(byte*)&bbuckets, sizeof bbuckets, 0}); - addroot((Obj){(byte*)&addrhash, sizeof addrhash, 0}); - addroot((Obj){(byte*)&addrfree, sizeof addrfree, 0}); -} - -// Must match BlockProfileRecord in debug.go. -typedef struct BRecord BRecord; -struct BRecord { - int64 count; - int64 cycles; - uintptr stk[32]; -}; - -func BlockProfile(p Slice) (n int, ok bool) { - Bucket *b; - BRecord *r; - int32 i; - - runtime_lock(&proflock); - n = 0; - for(b=bbuckets; b; b=b->allnext) - n++; - ok = false; - if(n <= p.__count) { - ok = true; - r = (BRecord*)p.__values; - for(b=bbuckets; b; b=b->allnext, r++) { - r->count = b->count; - r->cycles = b->cycles; - for(i=0; (uintptr)i<b->nstk && (uintptr)i<nelem(r->stk); i++) - r->stk[i] = b->stk[i].pc; - for(; (uintptr)i<nelem(r->stk); i++) - r->stk[i] = 0; - } - } - runtime_unlock(&proflock); -} - -// Must match StackRecord in debug.go. -typedef struct TRecord TRecord; -struct TRecord { - uintptr stk[32]; -}; - -func ThreadCreateProfile(p Slice) (n int, ok bool) { - TRecord *r; - M *first, *mp; - int32 i; - - first = runtime_atomicloadp(&runtime_allm); - n = 0; - for(mp=first; mp; mp=mp->alllink) - n++; - ok = false; - if(n <= p.__count) { - ok = true; - r = (TRecord*)p.__values; - for(mp=first; mp; mp=mp->alllink) { - for(i = 0; (uintptr)i < nelem(r->stk); i++) { - r->stk[i] = mp->createstack[i].pc; - } - r++; - } - } -} - -func Stack(b Slice, all bool) (n int) { - byte *pc, *sp; - bool enablegc; - - sp = runtime_getcallersp(&b); - pc = runtime_getcallerpc(&b); - - if(all) { - runtime_semacquire(&runtime_worldsema); - runtime_m()->gcing = 1; - runtime_stoptheworld(); - enablegc = mstats.enablegc; - mstats.enablegc = false; - } - - if(b.__count == 0) - n = 0; - else{ - G* g = runtime_g(); - g->writebuf = (byte*)b.__values; - g->writenbuf = b.__count; - USED(pc); - USED(sp); - runtime_goroutineheader(g); - runtime_traceback(); - runtime_goroutinetrailer(g); - if(all) - runtime_tracebackothers(g); - n = b.__count - g->writenbuf; - g->writebuf = nil; - g->writenbuf = 0; - } - - if(all) { - runtime_m()->gcing = 0; - mstats.enablegc = enablegc; - runtime_semrelease(&runtime_worldsema); - runtime_starttheworld(); - } -} - -static void -saveg(G *gp, TRecord *r) -{ - int32 n, i; - Location locstk[nelem(r->stk)]; - - if(gp == runtime_g()) { - n = runtime_callers(0, locstk, nelem(r->stk)); - for(i = 0; i < n; i++) - r->stk[i] = locstk[i].pc; - } - else { - // FIXME: Not implemented. - n = 0; - } - if((size_t)n < nelem(r->stk)) - r->stk[n] = 0; -} - -func GoroutineProfile(b Slice) (n int, ok bool) { - TRecord *r; - G *gp; - - ok = false; - n = runtime_gcount(); - if(n <= b.__count) { - runtime_semacquire(&runtime_worldsema); - runtime_m()->gcing = 1; - runtime_stoptheworld(); - - n = runtime_gcount(); - if(n <= b.__count) { - G* g = runtime_g(); - ok = true; - r = (TRecord*)b.__values; - saveg(g, r++); - for(gp = runtime_allg; gp != nil; gp = gp->alllink) { - if(gp == g || gp->status == Gdead) - continue; - saveg(gp, r++); - } - } - - runtime_m()->gcing = 0; - runtime_semrelease(&runtime_worldsema); - runtime_starttheworld(); - } -} - diff --git a/gcc-4.8.1/libgo/runtime/msize.c b/gcc-4.8.1/libgo/runtime/msize.c deleted file mode 100644 index 3b5591c1b..000000000 --- a/gcc-4.8.1/libgo/runtime/msize.c +++ /dev/null @@ -1,169 +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 "arch.h" -#include "malloc.h" - -int32 runtime_class_to_size[NumSizeClasses]; -int32 runtime_class_to_allocnpages[NumSizeClasses]; -int32 runtime_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 -runtime_SizeToClass(int32 size) -{ - if(size > MaxSmallSize) - runtime_throw("SizeToClass - invalid size"); - if(size > 1024-8) - return size_to_class128[(size-1024+127) >> 7]; - return size_to_class8[(size+7)>>3]; -} - -void -runtime_InitSizes(void) -{ - int32 align, sizeclass, size, nextsize, n; - uint32 i; - uintptr allocsize, npages; - - // Initialize the runtime_class_to_size table (and choose class sizes in the process). - runtime_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) - runtime_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; - while(allocsize%size > 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 - && (int32)npages == runtime_class_to_allocnpages[sizeclass-1] - && allocsize/size == allocsize/runtime_class_to_size[sizeclass-1]) { - runtime_class_to_size[sizeclass-1] = size; - continue; - } - - runtime_class_to_allocnpages[sizeclass] = npages; - runtime_class_to_size[sizeclass] = size; - sizeclass++; - } - if(sizeclass != NumSizeClasses) { - runtime_printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses); - runtime_throw("InitSizes - bad NumSizeClasses"); - } - - // Initialize the size_to_class tables. - nextsize = 0; - for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) { - for(; nextsize < 1024 && nextsize <= runtime_class_to_size[sizeclass]; nextsize+=8) - size_to_class8[nextsize/8] = sizeclass; - if(nextsize >= 1024) - for(; nextsize <= runtime_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 = runtime_SizeToClass(n); - if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime_class_to_size[sizeclass] < n) { - runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]); - runtime_printf("incorrect SizeToClass"); - goto dump; - } - if(sizeclass > 1 && runtime_class_to_size[sizeclass-1] >= n) { - runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]); - runtime_printf("SizeToClass too big"); - goto dump; - } - } - } - - // Copy out for statistics table. - for(i=0; i<nelem(runtime_class_to_size); i++) - mstats.by_size[i].size = runtime_class_to_size[i]; - - // Initialize the runtime_class_to_transfercount table. - for(sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) { - n = 64*1024 / runtime_class_to_size[sizeclass]; - if(n < 2) - n = 2; - if(n > 32) - n = 32; - runtime_class_to_transfercount[sizeclass] = n; - } - return; - -dump: - if(1){ - runtime_printf("NumSizeClasses=%d\n", NumSizeClasses); - runtime_printf("runtime_class_to_size:"); - for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++) - runtime_printf(" %d", runtime_class_to_size[sizeclass]); - runtime_printf("\n\n"); - runtime_printf("size_to_class8:"); - for(i=0; i<nelem(size_to_class8); i++) - runtime_printf(" %d=>%d(%d)\n", i*8, size_to_class8[i], runtime_class_to_size[size_to_class8[i]]); - runtime_printf("\n"); - runtime_printf("size_to_class128:"); - for(i=0; i<nelem(size_to_class128); i++) - runtime_printf(" %d=>%d(%d)\n", i*128, size_to_class128[i], runtime_class_to_size[size_to_class128[i]]); - runtime_printf("\n"); - } - runtime_throw("InitSizes failed"); -} diff --git a/gcc-4.8.1/libgo/runtime/panic.c b/gcc-4.8.1/libgo/runtime/panic.c deleted file mode 100644 index 7b9b578e4..000000000 --- a/gcc-4.8.1/libgo/runtime/panic.c +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2012 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 "go-defer.h" -#include "go-panic.h" - -// Code related to defer, panic and recover. - -uint32 runtime_panicking; -static Lock paniclk; - -// Run all deferred functions for the current goroutine. -static void -rundefer(void) -{ - G *g; - Defer *d; - - g = runtime_g(); - while((d = g->defer) != nil) { - void (*pfn)(void*); - - g->defer = d->__next; - pfn = d->__pfn; - d->__pfn = nil; - if (pfn != nil) - (*pfn)(d->__arg); - runtime_free(d); - } -} - -void -runtime_startpanic(void) -{ - M *m; - - m = runtime_m(); - if(m->dying) { - runtime_printf("panic during panic\n"); - runtime_exit(3); - } - m->dying = 1; - runtime_xadd(&runtime_panicking, 1); - runtime_lock(&paniclk); -} - -void -runtime_dopanic(int32 unused __attribute__ ((unused))) -{ - G *g; - static bool didothers; - - g = runtime_g(); - if(g->sig != 0) - runtime_printf("[signal %x code=%p addr=%p]\n", - g->sig, (void*)g->sigcode0, (void*)g->sigcode1); - - if(runtime_gotraceback()){ - if(g != runtime_m()->g0) { - runtime_printf("\n"); - runtime_goroutineheader(g); - runtime_traceback(); - runtime_goroutinetrailer(g); - } - if(!didothers) { - didothers = true; - runtime_tracebackothers(g); - } - } - runtime_unlock(&paniclk); - if(runtime_xadd(&runtime_panicking, -1) != 0) { - // Some other m is panicking too. - // Let it print what it needs to print. - // Wait forever without chewing up cpu. - // It will exit when it's done. - static Lock deadlock; - runtime_lock(&deadlock); - runtime_lock(&deadlock); - } - - runtime_exit(2); -} - -void -runtime_throw(const char *s) -{ - M *mp; - - mp = runtime_m(); - if(mp->throwing == 0) - mp->throwing = 1; - runtime_startpanic(); - runtime_printf("fatal error: %s\n", s); - runtime_dopanic(0); - *(int32*)0 = 0; // not reached - runtime_exit(1); // even more not reached -} - -void -runtime_panicstring(const char *s) -{ - Eface err; - - if(runtime_m()->gcing) { - runtime_printf("panic: %s\n", s); - runtime_throw("panic during gc"); - } - runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err); - runtime_panic(err); -} - -void runtime_Goexit (void) __asm__ (GOSYM_PREFIX "runtime.Goexit"); - -void -runtime_Goexit(void) -{ - rundefer(); - runtime_goexit(); -} diff --git a/gcc-4.8.1/libgo/runtime/parfor.c b/gcc-4.8.1/libgo/runtime/parfor.c deleted file mode 100644 index 591b968c0..000000000 --- a/gcc-4.8.1/libgo/runtime/parfor.c +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2012 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. - -// Parallel for algorithm. - -#include "runtime.h" -#include "arch.h" - -struct ParForThread -{ - // the thread's iteration space [32lsb, 32msb) - uint64 pos; - // stats - uint64 nsteal; - uint64 nstealcnt; - uint64 nprocyield; - uint64 nosyield; - uint64 nsleep; - byte pad[CacheLineSize]; -}; - -ParFor* -runtime_parforalloc(uint32 nthrmax) -{ - ParFor *desc; - - // The ParFor object is followed by CacheLineSize padding - // and then nthrmax ParForThread. - desc = (ParFor*)runtime_malloc(sizeof(ParFor) + CacheLineSize + nthrmax * sizeof(ParForThread)); - desc->thr = (ParForThread*)((byte*)(desc+1) + CacheLineSize); - desc->nthrmax = nthrmax; - return desc; -} - -// For testing from Go -// func parforalloc2(nthrmax uint32) *ParFor - -ParFor *runtime_parforalloc2(uint32) - __asm__ (GOSYM_PREFIX "runtime.parforalloc2"); - -ParFor * -runtime_parforalloc2(uint32 nthrmax) -{ - return runtime_parforalloc(nthrmax); -} - -void -runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32)) -{ - uint32 i, begin, end; - - if(desc == nil || nthr == 0 || nthr > desc->nthrmax || body == nil) { - runtime_printf("desc=%p nthr=%d count=%d body=%p\n", desc, nthr, n, body); - runtime_throw("parfor: invalid args"); - } - - desc->body = body; - desc->done = 0; - desc->nthr = nthr; - desc->thrseq = 0; - desc->cnt = n; - desc->ctx = ctx; - desc->wait = wait; - desc->nsteal = 0; - desc->nstealcnt = 0; - desc->nprocyield = 0; - desc->nosyield = 0; - desc->nsleep = 0; - for(i=0; i<nthr; i++) { - begin = (uint64)n*i / nthr; - end = (uint64)n*(i+1) / nthr; - desc->thr[i].pos = (uint64)begin | (((uint64)end)<<32); - } -} - -// For testing from Go -// func parforsetup2(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32)) - -void runtime_parforsetup2(ParFor *, uint32, uint32, void *, bool, void *) - __asm__ (GOSYM_PREFIX "runtime.parforsetup2"); - -void -runtime_parforsetup2(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void *body) -{ - runtime_parforsetup(desc, nthr, n, ctx, wait, (void(*)(ParFor*, uint32))body); -} - -void -runtime_parfordo(ParFor *desc) -{ - ParForThread *me; - uint32 tid, begin, end, begin2, try, victim, i; - uint64 *mypos, *victimpos, pos, newpos; - void (*body)(ParFor*, uint32); - bool idle; - - // Obtain 0-based thread index. - tid = runtime_xadd(&desc->thrseq, 1) - 1; - if(tid >= desc->nthr) { - runtime_printf("tid=%d nthr=%d\n", tid, desc->nthr); - runtime_throw("parfor: invalid tid"); - } - - // If single-threaded, just execute the for serially. - if(desc->nthr==1) { - for(i=0; i<desc->cnt; i++) - desc->body(desc, i); - return; - } - - body = desc->body; - me = &desc->thr[tid]; - mypos = &me->pos; - for(;;) { - for(;;) { - // While there is local work, - // bump low index and execute the iteration. - pos = runtime_xadd64(mypos, 1); - begin = (uint32)pos-1; - end = (uint32)(pos>>32); - if(begin < end) { - body(desc, begin); - continue; - } - break; - } - - // Out of work, need to steal something. - idle = false; - for(try=0;; try++) { - // If we don't see any work for long enough, - // increment the done counter... - if(try > desc->nthr*4 && !idle) { - idle = true; - runtime_xadd(&desc->done, 1); - } - // ...if all threads have incremented the counter, - // we are done. - if(desc->done + !idle == desc->nthr) { - if(!idle) - runtime_xadd(&desc->done, 1); - goto exit; - } - // Choose a random victim for stealing. - victim = runtime_fastrand1() % (desc->nthr-1); - if(victim >= tid) - victim++; - victimpos = &desc->thr[victim].pos; - pos = runtime_atomicload64(victimpos); - for(;;) { - // See if it has any work. - begin = (uint32)pos; - end = (uint32)(pos>>32); - if(begin >= end-1) { - begin = end = 0; - break; - } - if(idle) { - runtime_xadd(&desc->done, -1); - idle = false; - } - begin2 = begin + (end-begin)/2; - newpos = (uint64)begin | (uint64)begin2<<32; - if(runtime_cas64(victimpos, &pos, newpos)) { - begin = begin2; - break; - } - } - if(begin < end) { - // Has successfully stolen some work. - if(idle) - runtime_throw("parfor: should not be idle"); - runtime_atomicstore64(mypos, (uint64)begin | (uint64)end<<32); - me->nsteal++; - me->nstealcnt += end-begin; - break; - } - // Backoff. - if(try < desc->nthr) { - // nothing - } else if (try < 4*desc->nthr) { - me->nprocyield++; - runtime_procyield(20); - // If a caller asked not to wait for the others, exit now - // (assume that most work is already done at this point). - } else if (!desc->wait) { - if(!idle) - runtime_xadd(&desc->done, 1); - goto exit; - } else if (try < 6*desc->nthr) { - me->nosyield++; - runtime_osyield(); - } else { - me->nsleep++; - runtime_usleep(1); - } - } - } -exit: - runtime_xadd64(&desc->nsteal, me->nsteal); - runtime_xadd64(&desc->nstealcnt, me->nstealcnt); - runtime_xadd64(&desc->nprocyield, me->nprocyield); - runtime_xadd64(&desc->nosyield, me->nosyield); - runtime_xadd64(&desc->nsleep, me->nsleep); - me->nsteal = 0; - me->nstealcnt = 0; - me->nprocyield = 0; - me->nosyield = 0; - me->nsleep = 0; -} - -// For testing from Go -// func parforiters(desc *ParFor, tid uintptr) (uintptr, uintptr) - -struct parforiters_ret { - uintptr start; - uintptr end; -}; - -struct parforiters_ret runtime_parforiters(ParFor *, uintptr) - __asm__ (GOSYM_PREFIX "runtime.parforiters"); - -struct parforiters_ret -runtime_parforiters(ParFor *desc, uintptr tid) -{ - struct parforiters_ret ret; - - ret.start = (uint32)desc->thr[tid].pos; - ret.end = (uint32)(desc->thr[tid].pos>>32); - return ret; -} diff --git a/gcc-4.8.1/libgo/runtime/print.c b/gcc-4.8.1/libgo/runtime/print.c deleted file mode 100644 index 9e0c45b0d..000000000 --- a/gcc-4.8.1/libgo/runtime/print.c +++ /dev/null @@ -1,315 +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 <stdarg.h> -#include "runtime.h" -#include "array.h" - -//static Lock debuglock; - -static void go_vprintf(const char*, va_list); - -// write to goroutine-local buffer if diverting output, -// or else standard error. -static void -gwrite(const void *v, int32 n) -{ - G* g = runtime_g(); - - if(g == nil || g->writebuf == nil) { - // Avoid -D_FORTIFY_SOURCE problems. - int rv __attribute__((unused)); - - rv = runtime_write(2, v, n); - return; - } - - if(g->writenbuf == 0) - return; - - if(n > g->writenbuf) - n = g->writenbuf; - runtime_memmove(g->writebuf, v, n); - g->writebuf += n; - g->writenbuf -= n; -} - -void -runtime_dump(byte *p, int32 n) -{ - int32 i; - - for(i=0; i<n; i++) { - runtime_printpointer((byte*)(uintptr)(p[i]>>4)); - runtime_printpointer((byte*)(uintptr)(p[i]&0xf)); - if((i&15) == 15) - runtime_prints("\n"); - else - runtime_prints(" "); - } - if(n & 15) - runtime_prints("\n"); -} - -void -runtime_prints(const char *s) -{ - gwrite(s, runtime_findnull((const byte*)s)); -} - -void -runtime_printf(const char *s, ...) -{ - va_list va; - - va_start(va, s); - go_vprintf(s, va); - va_end(va); -} - -// Very simple printf. Only for debugging prints. -// Do not add to this without checking with Rob. -static void -go_vprintf(const char *s, va_list va) -{ - const char *p, *lp; - - //runtime_lock(&debuglock); - - lp = p = s; - for(; *p; p++) { - if(*p != '%') - continue; - if(p > lp) - gwrite(lp, p-lp); - p++; - switch(*p) { - case 'a': - runtime_printslice(va_arg(va, Slice)); - break; - case 'd': - runtime_printint(va_arg(va, int32)); - break; - case 'D': - runtime_printint(va_arg(va, int64)); - break; - case 'e': - runtime_printeface(va_arg(va, Eface)); - break; - case 'f': - runtime_printfloat(va_arg(va, float64)); - break; - case 'C': - runtime_printcomplex(va_arg(va, __complex double)); - break; - case 'i': - runtime_printiface(va_arg(va, Iface)); - break; - case 'p': - runtime_printpointer(va_arg(va, void*)); - break; - case 's': - runtime_prints(va_arg(va, char*)); - break; - case 'S': - runtime_printstring(va_arg(va, String)); - break; - case 't': - runtime_printbool(va_arg(va, int)); - break; - case 'U': - runtime_printuint(va_arg(va, uint64)); - break; - case 'x': - runtime_printhex(va_arg(va, uint32)); - break; - case 'X': - runtime_printhex(va_arg(va, uint64)); - break; - } - lp = p+1; - } - if(p > lp) - gwrite(lp, p-lp); - - //runtime_unlock(&debuglock); -} - -void -runtime_printpc(void *p __attribute__ ((unused))) -{ - runtime_prints("PC="); - runtime_printhex((uint64)(uintptr)runtime_getcallerpc(p)); -} - -void -runtime_printbool(_Bool v) -{ - if(v) { - gwrite("true", 4); - return; - } - gwrite("false", 5); -} - -void -runtime_printfloat(double v) -{ - byte buf[20]; - int32 e, s, i, n; - float64 h; - - if(ISNAN(v)) { - gwrite("NaN", 3); - return; - } - i = __builtin_isinf_sign(v); - if(i > 0) { - gwrite("+Inf", 4); - return; - } - if(i < 0) { - gwrite("-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'; - gwrite(buf, n+7); -} - -void -runtime_printcomplex(__complex double v) -{ - gwrite("(", 1); - runtime_printfloat(__builtin_creal(v)); - runtime_printfloat(__builtin_cimag(v)); - gwrite("i)", 2); -} - -void -runtime_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; - } - gwrite(buf+i, nelem(buf)-i); -} - -void -runtime_printint(int64 v) -{ - if(v < 0) { - gwrite("-", 1); - v = -v; - } - runtime_printuint(v); -} - -void -runtime_printhex(uint64 v) -{ - static const char *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'; - gwrite(buf+i, nelem(buf)-i); -} - -void -runtime_printpointer(void *p) -{ - runtime_printhex((uint64)(uintptr)p); -} - -void -runtime_printstring(String v) -{ - // extern uint32 runtime_maxstring; - - // if(v.len > runtime_maxstring) { - // gwrite("[string too long]", 17); - // return; - // } - if(v.len > 0) - gwrite(v.str, v.len); -} - -void -__go_print_space(void) -{ - gwrite(" ", 1); -} - -void -__go_print_nl(void) -{ - gwrite("\n", 1); -} diff --git a/gcc-4.8.1/libgo/runtime/proc.c b/gcc-4.8.1/libgo/runtime/proc.c deleted file mode 100644 index 9b563a509..000000000 --- a/gcc-4.8.1/libgo/runtime/proc.c +++ /dev/null @@ -1,1815 +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 <limits.h> -#include <signal.h> -#include <stdlib.h> -#include <pthread.h> -#include <unistd.h> - -#include "config.h" - -#ifdef HAVE_DL_ITERATE_PHDR -#include <link.h> -#endif - -#include "runtime.h" -#include "arch.h" -#include "defs.h" -#include "malloc.h" -#include "race.h" -#include "go-type.h" -#include "go-defer.h" - -#ifdef USING_SPLIT_STACK - -/* FIXME: These are not declared anywhere. */ - -extern void __splitstack_getcontext(void *context[10]); - -extern void __splitstack_setcontext(void *context[10]); - -extern void *__splitstack_makecontext(size_t, void *context[10], size_t *); - -extern void * __splitstack_resetcontext(void *context[10], size_t *); - -extern void *__splitstack_find(void *, void *, size_t *, void **, void **, - void **); - -extern void __splitstack_block_signals (int *, int *); - -extern void __splitstack_block_signals_context (void *context[10], int *, - int *); - -#endif - -#ifndef PTHREAD_STACK_MIN -# define PTHREAD_STACK_MIN 8192 -#endif - -#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK) -# define StackMin PTHREAD_STACK_MIN -#else -# define StackMin 2 * 1024 * 1024 -#endif - -uintptr runtime_stacks_sys; - -static void schedule(G*); - -static void gtraceback(G*); - -typedef struct Sched Sched; - -M runtime_m0; -G runtime_g0; // idle goroutine for m0 - -#ifdef __rtems__ -#define __thread -#endif - -static __thread G *g; -static __thread M *m; - -#ifndef SETCONTEXT_CLOBBERS_TLS - -static inline void -initcontext(void) -{ -} - -static inline void -fixcontext(ucontext_t *c __attribute__ ((unused))) -{ -} - -#else - -# if defined(__x86_64__) && defined(__sun__) - -// x86_64 Solaris 10 and 11 have a bug: setcontext switches the %fs -// register to that of the thread which called getcontext. The effect -// is that the address of all __thread variables changes. This bug -// also affects pthread_self() and pthread_getspecific. We work -// around it by clobbering the context field directly to keep %fs the -// same. - -static __thread greg_t fs; - -static inline void -initcontext(void) -{ - ucontext_t c; - - getcontext(&c); - fs = c.uc_mcontext.gregs[REG_FSBASE]; -} - -static inline void -fixcontext(ucontext_t* c) -{ - c->uc_mcontext.gregs[REG_FSBASE] = fs; -} - -# elif defined(__NetBSD__) - -// NetBSD has a bug: setcontext clobbers tlsbase, we need to save -// and restore it ourselves. - -static __thread __greg_t tlsbase; - -static inline void -initcontext(void) -{ - ucontext_t c; - - getcontext(&c); - tlsbase = c.uc_mcontext._mc_tlsbase; -} - -static inline void -fixcontext(ucontext_t* c) -{ - c->uc_mcontext._mc_tlsbase = tlsbase; -} - -# else - -# error unknown case for SETCONTEXT_CLOBBERS_TLS - -# endif - -#endif - -// We can not always refer to the TLS variables directly. The -// compiler will call tls_get_addr to get the address of the variable, -// and it may hold it in a register across a call to schedule. When -// we get back from the call we may be running in a different thread, -// in which case the register now points to the TLS variable for a -// different thread. We use non-inlinable functions to avoid this -// when necessary. - -G* runtime_g(void) __attribute__ ((noinline, no_split_stack)); - -G* -runtime_g(void) -{ - return g; -} - -M* runtime_m(void) __attribute__ ((noinline, no_split_stack)); - -M* -runtime_m(void) -{ - return m; -} - -int32 runtime_gcwaiting; - -G* runtime_allg; -G* runtime_lastg; -M* runtime_allm; - -int8* runtime_goos; -int32 runtime_ncpu; - -// The static TLS size. See runtime_newm. -static int tlssize; - -#ifdef HAVE_DL_ITERATE_PHDR - -// Called via dl_iterate_phdr. - -static int -addtls(struct dl_phdr_info* info, size_t size __attribute__ ((unused)), void *data) -{ - size_t *total = (size_t *)data; - unsigned int i; - - for(i = 0; i < info->dlpi_phnum; ++i) { - if(info->dlpi_phdr[i].p_type == PT_TLS) - *total += info->dlpi_phdr[i].p_memsz; - } - return 0; -} - -// Set the total TLS size. - -static void -inittlssize() -{ - size_t total = 0; - - dl_iterate_phdr(addtls, (void *)&total); - tlssize = total; -} - -#else - -static void -inittlssize() -{ -} - -#endif - -// 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 g's -// and no waiting m's, ready() will start a new m running in a new -// OS thread, so that all ready g's can run simultaneously, up to a limit. -// For now, m's never go away. -// -// By default, Go keeps only one kernel thread (m) running user code -// at a single time; other threads may be blocked in the operating system. -// Setting the environment variable $GOMAXPROCS or calling -// runtime.GOMAXPROCS() will change the number of user threads -// allowed to execute simultaneously. $GOMAXPROCS is thus an -// approximation of the maximum number of cores to use. -// -// Even a program that can run without deadlock in a single process -// might use more m's if given the chance. For example, the prime -// sieve will use as many m's as there are primes (up to runtime_sched.mmax), -// allowing different stages of the pipeline to execute in parallel. -// We could revisit this choice, only kicking off new m's 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 g's (status == Gdead) - int64 goidgen; - - G *ghead; // g's waiting to run - G *gtail; - int32 gwait; // number of g's waiting to run - int32 gcount; // number of g's that are alive - int32 grunning; // number of g's running on cpu or in syscall - - M *mhead; // m's waiting for work - int32 mwait; // number of m's waiting for work - int32 mcount; // number of m's that have been created - - volatile uint32 atomic; // atomic scheduling word (see below) - - int32 profilehz; // cpu profiling rate - - bool init; // running initialization - bool lockmain; // init called runtime.LockOSThread - - Note stopped; // one g can set waitstop and wait here for m's to stop -}; - -// The atomic word in sched is an atomic uint32 that -// holds these fields. -// -// [15 bits] mcpu number of m's executing on cpu -// [15 bits] mcpumax max number of m's allowed on cpu -// [1 bit] waitstop some g is waiting on stopped -// [1 bit] gwaiting gwait != 0 -// -// These fields are the information needed by entersyscall -// and exitsyscall to decide whether to coordinate with the -// scheduler. Packing them into a single machine word lets -// them use a fast path with a single atomic read/write and -// no lock/unlock. This greatly reduces contention in -// syscall- or cgo-heavy multithreaded programs. -// -// Except for entersyscall and exitsyscall, the manipulations -// to these fields only happen while holding the schedlock, -// so the routines holding schedlock only need to worry about -// what entersyscall and exitsyscall do, not the other routines -// (which also use the schedlock). -// -// In particular, entersyscall and exitsyscall only read mcpumax, -// waitstop, and gwaiting. They never write them. Thus, writes to those -// fields can be done (holding schedlock) without fear of write conflicts. -// There may still be logic conflicts: for example, the set of waitstop must -// be conditioned on mcpu >= mcpumax or else the wait may be a -// spurious sleep. The Promela model in proc.p verifies these accesses. -enum { - mcpuWidth = 15, - mcpuMask = (1<<mcpuWidth) - 1, - mcpuShift = 0, - mcpumaxShift = mcpuShift + mcpuWidth, - waitstopShift = mcpumaxShift + mcpuWidth, - gwaitingShift = waitstopShift+1, - - // The max value of GOMAXPROCS is constrained - // by the max value we can store in the bit fields - // of the atomic word. Reserve a few high values - // so that we can detect accidental decrement - // beyond zero. - maxgomaxprocs = mcpuMask - 10, -}; - -#define atomic_mcpu(v) (((v)>>mcpuShift)&mcpuMask) -#define atomic_mcpumax(v) (((v)>>mcpumaxShift)&mcpuMask) -#define atomic_waitstop(v) (((v)>>waitstopShift)&1) -#define atomic_gwaiting(v) (((v)>>gwaitingShift)&1) - -Sched runtime_sched; -int32 runtime_gomaxprocs; -bool runtime_singleproc; - -static bool canaddmcpu(void); - -// An m that is waiting for notewakeup(&m->havenextg). This may -// only be accessed while the scheduler lock is held. This is used to -// minimize the number of times we call notewakeup while the scheduler -// lock is held, since the m will normally move quickly to lock the -// scheduler itself, producing lock contention. -static M* mwakeup; - -// 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(G*); -static void gfput(G*); // put/get on gfree -static G* gfget(void); -static void matchmg(void); // match m's to g's -static void readylocked(G*); // ready, but sched is locked -static void mnextg(M*, G*); -static void mcommoninit(M*); - -void -setmcpumax(uint32 n) -{ - uint32 v, w; - - for(;;) { - v = runtime_sched.atomic; - w = v; - w &= ~(mcpuMask<<mcpumaxShift); - w |= n<<mcpumaxShift; - if(runtime_cas(&runtime_sched.atomic, v, w)) - break; - } -} - -// First function run by a new goroutine. This replaces gogocall. -static void -kickoff(void) -{ - void (*fn)(void*); - - if(g->traceback != nil) - gtraceback(g); - - fn = (void (*)(void*))(g->entry); - fn(g->param); - runtime_goexit(); -} - -// Switch context to a different goroutine. This is like longjmp. -static void runtime_gogo(G*) __attribute__ ((noinline)); -static void -runtime_gogo(G* newg) -{ -#ifdef USING_SPLIT_STACK - __splitstack_setcontext(&newg->stack_context[0]); -#endif - g = newg; - newg->fromgogo = true; - fixcontext(&newg->context); - setcontext(&newg->context); - runtime_throw("gogo setcontext returned"); -} - -// Save context and call fn passing g as a parameter. This is like -// setjmp. Because getcontext always returns 0, unlike setjmp, we use -// g->fromgogo as a code. It will be true if we got here via -// setcontext. g == nil the first time this is called in a new m. -static void runtime_mcall(void (*)(G*)) __attribute__ ((noinline)); -static void -runtime_mcall(void (*pfn)(G*)) -{ - M *mp; - G *gp; -#ifndef USING_SPLIT_STACK - int i; -#endif - - // Ensure that all registers are on the stack for the garbage - // collector. - __builtin_unwind_init(); - - mp = m; - gp = g; - if(gp == mp->g0) - runtime_throw("runtime: mcall called on m->g0 stack"); - - if(gp != nil) { - -#ifdef USING_SPLIT_STACK - __splitstack_getcontext(&g->stack_context[0]); -#else - gp->gcnext_sp = &i; -#endif - gp->fromgogo = false; - getcontext(&gp->context); - - // When we return from getcontext, we may be running - // in a new thread. That means that m and g may have - // changed. They are global variables so we will - // reload them, but the addresses of m and g may be - // cached in our local stack frame, and those - // addresses may be wrong. Call functions to reload - // the values for this thread. - mp = runtime_m(); - gp = runtime_g(); - - if(gp->traceback != nil) - gtraceback(gp); - } - if (gp == nil || !gp->fromgogo) { -#ifdef USING_SPLIT_STACK - __splitstack_setcontext(&mp->g0->stack_context[0]); -#endif - mp->g0->entry = (byte*)pfn; - mp->g0->param = gp; - - // It's OK to set g directly here because this case - // can not occur if we got here via a setcontext to - // the getcontext call just above. - g = mp->g0; - - fixcontext(&mp->g0->context); - setcontext(&mp->g0->context); - runtime_throw("runtime: mcall function returned"); - } -} - -// Keep trace of scavenger's goroutine for deadlock detection. -static G *scvg; - -// The bootstrap sequence is: -// -// call osinit -// call schedinit -// make & queue new G -// call runtime_mstart -// -// The new G calls runtime_main. -void -runtime_schedinit(void) -{ - int32 n; - const byte *p; - - m = &runtime_m0; - g = &runtime_g0; - m->g0 = g; - m->curg = g; - g->m = m; - - initcontext(); - inittlssize(); - - m->nomemprof++; - runtime_mallocinit(); - mcommoninit(m); - - runtime_goargs(); - runtime_goenvs(); - - // For debugging: - // Allocate internal symbol table representation now, - // so that we don't need to call malloc when we crash. - // runtime_findfunc(0); - - runtime_gomaxprocs = 1; - p = runtime_getenv("GOMAXPROCS"); - if(p != nil && (n = runtime_atoi(p)) != 0) { - if(n > maxgomaxprocs) - n = maxgomaxprocs; - runtime_gomaxprocs = n; - } - // wait for the main goroutine to start before taking - // GOMAXPROCS into account. - setmcpumax(1); - runtime_singleproc = runtime_gomaxprocs == 1; - - canaddmcpu(); // mcpu++ to account for bootstrap m - m->helpgc = 1; // flag to tell schedule() to mcpu-- - runtime_sched.grunning++; - - // Can not enable GC until all roots are registered. - // mstats.enablegc = 1; - m->nomemprof--; - - if(raceenabled) - runtime_raceinit(); -} - -extern void main_init(void) __asm__ (GOSYM_PREFIX "__go_init_main"); -extern void main_main(void) __asm__ (GOSYM_PREFIX "main.main"); - -// The main goroutine. -void -runtime_main(void) -{ - // Lock the main goroutine onto this, the main OS thread, - // during initialization. Most programs won't care, but a few - // do require certain calls to be made by the main thread. - // Those can arrange for main.main to run in the main thread - // by calling runtime.LockOSThread during initialization - // to preserve the lock. - runtime_LockOSThread(); - // From now on, newgoroutines may use non-main threads. - setmcpumax(runtime_gomaxprocs); - runtime_sched.init = true; - scvg = __go_go(runtime_MHeap_Scavenger, nil); - scvg->issystem = true; - main_init(); - runtime_sched.init = false; - if(!runtime_sched.lockmain) - runtime_UnlockOSThread(); - - // For gccgo we have to wait until after main is initialized - // to enable GC, because initializing main registers the GC - // roots. - mstats.enablegc = 1; - - // The deadlock detection has false negatives. - // Let scvg start up, to eliminate the false negative - // for the trivial program func main() { select{} }. - runtime_gosched(); - - main_main(); - if(raceenabled) - runtime_racefini(); - runtime_exit(0); - for(;;) - *(int32*)0 = 0; -} - -// Lock the scheduler. -static void -schedlock(void) -{ - runtime_lock(&runtime_sched); -} - -// Unlock the scheduler. -static void -schedunlock(void) -{ - M *mp; - - mp = mwakeup; - mwakeup = nil; - runtime_unlock(&runtime_sched); - if(mp != nil) - runtime_notewakeup(&mp->havenextg); -} - -void -runtime_goexit(void) -{ - g->status = Gmoribund; - runtime_gosched(); -} - -void -runtime_goroutineheader(G *gp) -{ - const char *status; - - switch(gp->status) { - case Gidle: - status = "idle"; - break; - case Grunnable: - status = "runnable"; - break; - case Grunning: - status = "running"; - break; - case Gsyscall: - status = "syscall"; - break; - case Gwaiting: - if(gp->waitreason) - status = gp->waitreason; - else - status = "waiting"; - break; - case Gmoribund: - status = "moribund"; - break; - default: - status = "???"; - break; - } - runtime_printf("goroutine %D [%s]:\n", gp->goid, status); -} - -void -runtime_goroutinetrailer(G *g) -{ - if(g != nil && g->gopc != 0 && g->goid != 1) { - String fn; - String file; - intgo line; - - if(__go_file_line(g->gopc - 1, &fn, &file, &line)) { - runtime_printf("created by %S\n", fn); - runtime_printf("\t%S:%D\n", file, (int64) line); - } - } -} - -struct Traceback -{ - G* gp; - Location locbuf[100]; - int32 c; -}; - -void -runtime_tracebackothers(G * volatile me) -{ - G * volatile gp; - Traceback tb; - int32 traceback; - - tb.gp = me; - traceback = runtime_gotraceback(); - for(gp = runtime_allg; gp != nil; gp = gp->alllink) { - if(gp == me || gp->status == Gdead) - continue; - if(gp->issystem && traceback < 2) - continue; - runtime_printf("\n"); - runtime_goroutineheader(gp); - - // Our only mechanism for doing a stack trace is - // _Unwind_Backtrace. And that only works for the - // current thread, not for other random goroutines. - // So we need to switch context to the goroutine, get - // the backtrace, and then switch back. - - // This means that if g is running or in a syscall, we - // can't reliably print a stack trace. FIXME. - if(gp->status == Gsyscall || gp->status == Grunning) { - runtime_printf("no stack trace available\n"); - runtime_goroutinetrailer(gp); - continue; - } - - gp->traceback = &tb; - -#ifdef USING_SPLIT_STACK - __splitstack_getcontext(&me->stack_context[0]); -#endif - getcontext(&me->context); - - if(gp->traceback != nil) { - runtime_gogo(gp); - } - - runtime_printtrace(tb.locbuf, tb.c, false); - runtime_goroutinetrailer(gp); - } -} - -// Do a stack trace of gp, and then restore the context to -// gp->dotraceback. - -static void -gtraceback(G* gp) -{ - Traceback* traceback; - - traceback = gp->traceback; - gp->traceback = nil; - traceback->c = runtime_callers(1, traceback->locbuf, - sizeof traceback->locbuf / sizeof traceback->locbuf[0]); - runtime_gogo(traceback->gp); -} - -// Mark this g as m's idle goroutine. -// This functionality might be used in environments where programs -// are limited to a single thread, to simulate a select-driven -// network server. It is not exposed via the standard runtime API. -void -runtime_idlegoroutine(void) -{ - if(g->idlem != nil) - runtime_throw("g is already an idle goroutine"); - g->idlem = m; -} - -static void -mcommoninit(M *mp) -{ - mp->id = runtime_sched.mcount++; - mp->fastrand = 0x49f6428aUL + mp->id + runtime_cputicks(); - - if(mp->mcache == nil) - mp->mcache = runtime_allocmcache(); - - runtime_callers(1, mp->createstack, nelem(mp->createstack)); - - // Add to runtime_allm so garbage collector doesn't free m - // when it is just in a register or thread-local storage. - mp->alllink = runtime_allm; - // runtime_NumCgoCall() iterates over allm w/o schedlock, - // so we need to publish it safely. - runtime_atomicstorep(&runtime_allm, mp); -} - -// Try to increment mcpu. Report whether succeeded. -static bool -canaddmcpu(void) -{ - uint32 v; - - for(;;) { - v = runtime_sched.atomic; - if(atomic_mcpu(v) >= atomic_mcpumax(v)) - return 0; - if(runtime_cas(&runtime_sched.atomic, v, v+(1<<mcpuShift))) - return 1; - } -} - -// Put on `g' queue. Sched must be locked. -static void -gput(G *gp) -{ - M *mp; - - // If g is wired, hand it off directly. - if((mp = gp->lockedm) != nil && canaddmcpu()) { - mnextg(mp, gp); - return; - } - - // If g is the idle goroutine for an m, hand it off. - if(gp->idlem != nil) { - if(gp->idlem->idleg != nil) { - runtime_printf("m%d idle out of sync: g%D g%D\n", - gp->idlem->id, - gp->idlem->idleg->goid, gp->goid); - runtime_throw("runtime: double idle"); - } - gp->idlem->idleg = gp; - return; - } - - gp->schedlink = nil; - if(runtime_sched.ghead == nil) - runtime_sched.ghead = gp; - else - runtime_sched.gtail->schedlink = gp; - runtime_sched.gtail = gp; - - // increment gwait. - // if it transitions to nonzero, set atomic gwaiting bit. - if(runtime_sched.gwait++ == 0) - runtime_xadd(&runtime_sched.atomic, 1<<gwaitingShift); -} - -// Report whether gget would return something. -static bool -haveg(void) -{ - return runtime_sched.ghead != nil || m->idleg != nil; -} - -// Get from `g' queue. Sched must be locked. -static G* -gget(void) -{ - G *gp; - - gp = runtime_sched.ghead; - if(gp) { - runtime_sched.ghead = gp->schedlink; - if(runtime_sched.ghead == nil) - runtime_sched.gtail = nil; - // decrement gwait. - // if it transitions to zero, clear atomic gwaiting bit. - if(--runtime_sched.gwait == 0) - runtime_xadd(&runtime_sched.atomic, -1<<gwaitingShift); - } else if(m->idleg != nil) { - gp = m->idleg; - m->idleg = nil; - } - return gp; -} - -// Put on `m' list. Sched must be locked. -static void -mput(M *mp) -{ - mp->schedlink = runtime_sched.mhead; - runtime_sched.mhead = mp; - runtime_sched.mwait++; -} - -// Get an `m' to run `g'. Sched must be locked. -static M* -mget(G *gp) -{ - M *mp; - - // if g has its own m, use it. - if(gp && (mp = gp->lockedm) != nil) - return mp; - - // otherwise use general m pool. - if((mp = runtime_sched.mhead) != nil) { - runtime_sched.mhead = mp->schedlink; - runtime_sched.mwait--; - } - return mp; -} - -// Mark g ready to run. -void -runtime_ready(G *gp) -{ - schedlock(); - readylocked(gp); - schedunlock(); -} - -// 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 *gp) -{ - if(gp->m) { - // Running on another machine. - // Ready it when it stops. - gp->readyonstop = 1; - return; - } - - // Mark runnable. - if(gp->status == Grunnable || gp->status == Grunning) { - runtime_printf("goroutine %D has status %d\n", gp->goid, gp->status); - runtime_throw("bad g->status in ready"); - } - gp->status = Grunnable; - - gput(gp); - matchmg(); -} - -// Same as readylocked but a different symbol so that -// debuggers can set a breakpoint here and catch all -// new goroutines. -static void -newprocreadylocked(G *gp) -{ - readylocked(gp); -} - -// Pass g to m for running. -// Caller has already incremented mcpu. -static void -mnextg(M *mp, G *gp) -{ - runtime_sched.grunning++; - mp->nextg = gp; - if(mp->waitnextg) { - mp->waitnextg = 0; - if(mwakeup != nil) - runtime_notewakeup(&mwakeup->havenextg); - mwakeup = mp; - } -} - -// Get the next goroutine that m should run. -// Sched must be locked on entry, is unlocked on exit. -// Makes sure that at most $GOMAXPROCS g's are -// running on cpus (not in system calls) at any given time. -static G* -nextgandunlock(void) -{ - G *gp; - uint32 v; - -top: - if(atomic_mcpu(runtime_sched.atomic) >= maxgomaxprocs) - runtime_throw("negative mcpu"); - - // If there is a g waiting as m->nextg, the mcpu++ - // happened before it was passed to mnextg. - if(m->nextg != nil) { - gp = m->nextg; - m->nextg = nil; - schedunlock(); - return gp; - } - - if(m->lockedg != nil) { - // We can only run one g, and it's not available. - // Make sure some other cpu is running to handle - // the ordinary run queue. - if(runtime_sched.gwait != 0) { - matchmg(); - // m->lockedg might have been on the queue. - if(m->nextg != nil) { - gp = m->nextg; - m->nextg = nil; - schedunlock(); - return gp; - } - } - } else { - // Look for work on global queue. - while(haveg() && canaddmcpu()) { - gp = gget(); - if(gp == nil) - runtime_throw("gget inconsistency"); - - if(gp->lockedm) { - mnextg(gp->lockedm, gp); - continue; - } - runtime_sched.grunning++; - schedunlock(); - return gp; - } - - // The while loop ended either because the g queue is empty - // or because we have maxed out our m procs running go - // code (mcpu >= mcpumax). We need to check that - // concurrent actions by entersyscall/exitsyscall cannot - // invalidate the decision to end the loop. - // - // We hold the sched lock, so no one else is manipulating the - // g queue or changing mcpumax. Entersyscall can decrement - // mcpu, but if does so when there is something on the g queue, - // the gwait bit will be set, so entersyscall will take the slow path - // and use the sched lock. So it cannot invalidate our decision. - // - // Wait on global m queue. - mput(m); - } - - // Look for deadlock situation. - // There is a race with the scavenger that causes false negatives: - // if the scavenger is just starting, then we have - // scvg != nil && grunning == 0 && gwait == 0 - // and we do not detect a deadlock. It is possible that we should - // add that case to the if statement here, but it is too close to Go 1 - // to make such a subtle change. Instead, we work around the - // false negative in trivial programs by calling runtime.gosched - // from the main goroutine just before main.main. - // See runtime_main above. - // - // On a related note, it is also possible that the scvg == nil case is - // wrong and should include gwait, but that does not happen in - // standard Go programs, which all start the scavenger. - // - if((scvg == nil && runtime_sched.grunning == 0) || - (scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 && - (scvg->status == Grunning || scvg->status == Gsyscall))) { - m->throwing = -1; // do not dump full stacks - runtime_throw("all goroutines are asleep - deadlock!"); - } - - m->nextg = nil; - m->waitnextg = 1; - runtime_noteclear(&m->havenextg); - - // Stoptheworld is waiting for all but its cpu to go to stop. - // Entersyscall might have decremented mcpu too, but if so - // it will see the waitstop and take the slow path. - // Exitsyscall never increments mcpu beyond mcpumax. - v = runtime_atomicload(&runtime_sched.atomic); - if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { - // set waitstop = 0 (known to be 1) - runtime_xadd(&runtime_sched.atomic, -1<<waitstopShift); - runtime_notewakeup(&runtime_sched.stopped); - } - schedunlock(); - - runtime_notesleep(&m->havenextg); - if(m->helpgc) { - runtime_gchelper(); - m->helpgc = 0; - runtime_lock(&runtime_sched); - goto top; - } - if((gp = m->nextg) == nil) - runtime_throw("bad m->nextg in nextgoroutine"); - m->nextg = nil; - return gp; -} - -int32 -runtime_gcprocs(void) -{ - int32 n; - - // Figure out how many CPUs to use during GC. - // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc. - n = runtime_gomaxprocs; - if(n > runtime_ncpu) - n = runtime_ncpu > 0 ? runtime_ncpu : 1; - if(n > MaxGcproc) - n = MaxGcproc; - if(n > runtime_sched.mwait+1) // one M is currently running - n = runtime_sched.mwait+1; - return n; -} - -void -runtime_helpgc(int32 nproc) -{ - M *mp; - int32 n; - - runtime_lock(&runtime_sched); - for(n = 1; n < nproc; n++) { // one M is currently running - mp = mget(nil); - if(mp == nil) - runtime_throw("runtime_gcprocs inconsistency"); - mp->helpgc = 1; - mp->waitnextg = 0; - runtime_notewakeup(&mp->havenextg); - } - runtime_unlock(&runtime_sched); -} - -void -runtime_stoptheworld(void) -{ - uint32 v; - - schedlock(); - runtime_gcwaiting = 1; - - setmcpumax(1); - - // while mcpu > 1 - for(;;) { - v = runtime_sched.atomic; - if(atomic_mcpu(v) <= 1) - break; - - // It would be unsafe for multiple threads to be using - // the stopped note at once, but there is only - // ever one thread doing garbage collection. - runtime_noteclear(&runtime_sched.stopped); - if(atomic_waitstop(v)) - runtime_throw("invalid waitstop"); - - // atomic { waitstop = 1 }, predicated on mcpu <= 1 check above - // still being true. - if(!runtime_cas(&runtime_sched.atomic, v, v+(1<<waitstopShift))) - continue; - - schedunlock(); - runtime_notesleep(&runtime_sched.stopped); - schedlock(); - } - runtime_singleproc = runtime_gomaxprocs == 1; - schedunlock(); -} - -void -runtime_starttheworld(void) -{ - M *mp; - int32 max; - - // Figure out how many CPUs GC could possibly use. - max = runtime_gomaxprocs; - if(max > runtime_ncpu) - max = runtime_ncpu > 0 ? runtime_ncpu : 1; - if(max > MaxGcproc) - max = MaxGcproc; - - schedlock(); - runtime_gcwaiting = 0; - setmcpumax(runtime_gomaxprocs); - matchmg(); - if(runtime_gcprocs() < max && canaddmcpu()) { - // If GC could have used another helper proc, start one now, - // in the hope that it will be available next time. - // It would have been even better to start it before the collection, - // but doing so requires allocating memory, so it's tricky to - // coordinate. This lazy approach works out in practice: - // we don't mind if the first couple gc rounds don't have quite - // the maximum number of procs. - // canaddmcpu above did mcpu++ - // (necessary, because m will be doing various - // initialization work so is definitely running), - // but m is not running a specific goroutine, - // so set the helpgc flag as a signal to m's - // first schedule(nil) to mcpu-- and grunning--. - mp = runtime_newm(); - mp->helpgc = 1; - runtime_sched.grunning++; - } - schedunlock(); -} - -// Called to start an M. -void* -runtime_mstart(void* mp) -{ - m = (M*)mp; - g = m->g0; - - initcontext(); - - g->entry = nil; - g->param = nil; - - // Record top of stack for use by mcall. - // Once we call schedule we're never coming back, - // so other calls can reuse this stack space. -#ifdef USING_SPLIT_STACK - __splitstack_getcontext(&g->stack_context[0]); -#else - g->gcinitial_sp = ∓ - // Setting gcstack_size to 0 is a marker meaning that gcinitial_sp - // is the top of the stack, not the bottom. - g->gcstack_size = 0; - g->gcnext_sp = ∓ -#endif - getcontext(&g->context); - - if(g->entry != nil) { - // Got here from mcall. - void (*pfn)(G*) = (void (*)(G*))g->entry; - G* gp = (G*)g->param; - pfn(gp); - *(int*)0x21 = 0x21; - } - runtime_minit(); - -#ifdef USING_SPLIT_STACK - { - int dont_block_signals = 0; - __splitstack_block_signals(&dont_block_signals, nil); - } -#endif - - // Install signal handlers; after minit so that minit can - // prepare the thread to be able to handle the signals. - if(m == &runtime_m0) - runtime_initsig(); - - schedule(nil); - - // TODO(brainman): This point is never reached, because scheduler - // does not release os threads at the moment. But once this path - // is enabled, we must remove our seh here. - - return nil; -} - -typedef struct CgoThreadStart CgoThreadStart; -struct CgoThreadStart -{ - M *m; - G *g; - void (*fn)(void); -}; - -// Kick off new m's as needed (up to mcpumax). -// Sched is locked. -static void -matchmg(void) -{ - G *gp; - M *mp; - - if(m->mallocing || m->gcing) - return; - - while(haveg() && canaddmcpu()) { - gp = gget(); - if(gp == nil) - runtime_throw("gget inconsistency"); - - // Find the m that will run gp. - if((mp = mget(gp)) == nil) - mp = runtime_newm(); - mnextg(mp, gp); - } -} - -// Create a new m. It will start off with a call to runtime_mstart. -M* -runtime_newm(void) -{ - M *mp; - pthread_attr_t attr; - pthread_t tid; - size_t stacksize; - sigset_t clear; - sigset_t old; - int ret; - -#if 0 - static const Type *mtype; // The Go type M - if(mtype == nil) { - Eface e; - runtime_gc_m_ptr(&e); - mtype = ((const PtrType*)e.__type_descriptor)->__element_type; - } -#endif - - mp = runtime_mal(sizeof *mp); - mcommoninit(mp); - mp->g0 = runtime_malg(-1, nil, nil); - - if(pthread_attr_init(&attr) != 0) - runtime_throw("pthread_attr_init"); - if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) - runtime_throw("pthread_attr_setdetachstate"); - - stacksize = PTHREAD_STACK_MIN; - - // With glibc before version 2.16 the static TLS size is taken - // out of the stack size, and we get an error or a crash if - // there is not enough stack space left. Add it back in if we - // can, in case the program uses a lot of TLS space. FIXME: - // This can be disabled in glibc 2.16 and later, if the bug is - // indeed fixed then. - stacksize += tlssize; - - if(pthread_attr_setstacksize(&attr, stacksize) != 0) - runtime_throw("pthread_attr_setstacksize"); - - // Block signals during pthread_create so that the new thread - // starts with signals disabled. It will enable them in minit. - sigfillset(&clear); - -#ifdef SIGTRAP - // Blocking SIGTRAP reportedly breaks gdb on Alpha GNU/Linux. - sigdelset(&clear, SIGTRAP); -#endif - - sigemptyset(&old); - sigprocmask(SIG_BLOCK, &clear, &old); - ret = pthread_create(&tid, &attr, runtime_mstart, mp); - sigprocmask(SIG_SETMASK, &old, nil); - - if (ret != 0) - runtime_throw("pthread_create"); - - return mp; -} - -// One round of scheduler: find a goroutine and run it. -// The argument is the goroutine that was running before -// schedule was called, or nil if this is the first call. -// Never returns. -static void -schedule(G *gp) -{ - int32 hz; - uint32 v; - - schedlock(); - if(gp != nil) { - // Just finished running gp. - gp->m = nil; - runtime_sched.grunning--; - - // atomic { mcpu-- } - v = runtime_xadd(&runtime_sched.atomic, -1<<mcpuShift); - if(atomic_mcpu(v) > maxgomaxprocs) - runtime_throw("negative mcpu in scheduler"); - - switch(gp->status) { - case Grunnable: - case Gdead: - // Shouldn't have been running! - runtime_throw("bad gp->status in sched"); - case Grunning: - gp->status = Grunnable; - gput(gp); - break; - case Gmoribund: - if(raceenabled) - runtime_racegoend(gp->goid); - gp->status = Gdead; - if(gp->lockedm) { - gp->lockedm = nil; - m->lockedg = nil; - } - gp->idlem = nil; - runtime_memclr(&gp->context, sizeof gp->context); - gfput(gp); - if(--runtime_sched.gcount == 0) - runtime_exit(0); - break; - } - if(gp->readyonstop) { - gp->readyonstop = 0; - readylocked(gp); - } - } else if(m->helpgc) { - // Bootstrap m or new m started by starttheworld. - // atomic { mcpu-- } - v = runtime_xadd(&runtime_sched.atomic, -1<<mcpuShift); - if(atomic_mcpu(v) > maxgomaxprocs) - runtime_throw("negative mcpu in scheduler"); - // Compensate for increment in starttheworld(). - runtime_sched.grunning--; - m->helpgc = 0; - } else if(m->nextg != nil) { - // New m started by matchmg. - } else { - runtime_throw("invalid m state in scheduler"); - } - - // Find (or wait for) g to run. Unlocks runtime_sched. - gp = nextgandunlock(); - gp->readyonstop = 0; - gp->status = Grunning; - m->curg = gp; - gp->m = m; - - // Check whether the profiler needs to be turned on or off. - hz = runtime_sched.profilehz; - if(m->profilehz != hz) - runtime_resetcpuprofiler(hz); - - runtime_gogo(gp); -} - -// 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 -runtime_gosched(void) -{ - if(m->locks != 0) - runtime_throw("gosched holding locks"); - if(g == m->g0) - runtime_throw("gosched of g0"); - runtime_mcall(schedule); -} - -// Puts the current goroutine into a waiting state and unlocks the lock. -// The goroutine can be made runnable again by calling runtime_ready(gp). -void -runtime_park(void (*unlockf)(Lock*), Lock *lock, const char *reason) -{ - g->status = Gwaiting; - g->waitreason = reason; - if(unlockf) - unlockf(lock); - runtime_gosched(); -} - -// 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 and cgocall, -// not from the low-level system calls used by the runtime. -// -// Entersyscall cannot split the stack: the runtime_gosave must -// make g->sched refer to the caller's stack segment, because -// entersyscall is going to return immediately after. -// It's okay to call matchmg and notewakeup even after -// decrementing mcpu, because we haven't released the -// sched lock yet, so the garbage collector cannot be running. - -void runtime_entersyscall(void) __attribute__ ((no_split_stack)); - -void -runtime_entersyscall(void) -{ - uint32 v; - - if(m->profilehz > 0) - runtime_setprof(false); - - // Leave SP around for gc and traceback. -#ifdef USING_SPLIT_STACK - g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size, - &g->gcnext_segment, &g->gcnext_sp, - &g->gcinitial_sp); -#else - g->gcnext_sp = (byte *) &v; -#endif - - // Save the registers in the g structure so that any pointers - // held in registers will be seen by the garbage collector. - getcontext(&g->gcregs); - - g->status = Gsyscall; - - // Fast path. - // The slow path inside the schedlock/schedunlock will get - // through without stopping if it does: - // mcpu-- - // gwait not true - // waitstop && mcpu <= mcpumax not true - // If we can do the same with a single atomic add, - // then we can skip the locks. - v = runtime_xadd(&runtime_sched.atomic, -1<<mcpuShift); - if(!atomic_gwaiting(v) && (!atomic_waitstop(v) || atomic_mcpu(v) > atomic_mcpumax(v))) - return; - - schedlock(); - v = runtime_atomicload(&runtime_sched.atomic); - if(atomic_gwaiting(v)) { - matchmg(); - v = runtime_atomicload(&runtime_sched.atomic); - } - if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { - runtime_xadd(&runtime_sched.atomic, -1<<waitstopShift); - runtime_notewakeup(&runtime_sched.stopped); - } - - schedunlock(); -} - -// 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 -runtime_exitsyscall(void) -{ - G *gp; - uint32 v; - - // Fast path. - // If we can do the mcpu++ bookkeeping and - // find that we still have mcpu <= mcpumax, then we can - // start executing Go code immediately, without having to - // schedlock/schedunlock. - // Also do fast return if any locks are held, so that - // panic code can use syscalls to open a file. - gp = g; - v = runtime_xadd(&runtime_sched.atomic, (1<<mcpuShift)); - if((m->profilehz == runtime_sched.profilehz && atomic_mcpu(v) <= atomic_mcpumax(v)) || m->locks > 0) { - // There's a cpu for us, so we can run. - gp->status = Grunning; - // Garbage collector isn't running (since we are), - // so okay to clear gcstack. -#ifdef USING_SPLIT_STACK - gp->gcstack = nil; -#endif - gp->gcnext_sp = nil; - runtime_memclr(&gp->gcregs, sizeof gp->gcregs); - - if(m->profilehz > 0) - runtime_setprof(true); - return; - } - - // Tell scheduler to put g back on the run queue: - // mostly equivalent to g->status = Grunning, - // but keeps the garbage collector from thinking - // that g is running right now, which it's not. - gp->readyonstop = 1; - - // All the cpus are taken. - // The scheduler will ready g and put this m to sleep. - // When the scheduler takes g away from m, - // it will undo the runtime_sched.mcpu++ above. - runtime_gosched(); - - // Gosched returned, so we're allowed to run now. - // Delete the gcstack information that we left for - // the garbage collector during the system call. - // Must wait until now because until gosched returns - // we don't know for sure that the garbage collector - // is not running. -#ifdef USING_SPLIT_STACK - gp->gcstack = nil; -#endif - gp->gcnext_sp = nil; - runtime_memclr(&gp->gcregs, sizeof gp->gcregs); -} - -// Allocate a new g, with a stack big enough for stacksize bytes. -G* -runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize) -{ - G *newg; - - newg = runtime_malloc(sizeof(G)); - if(stacksize >= 0) { -#if USING_SPLIT_STACK - int dont_block_signals = 0; - - *ret_stack = __splitstack_makecontext(stacksize, - &newg->stack_context[0], - ret_stacksize); - __splitstack_block_signals_context(&newg->stack_context[0], - &dont_block_signals, nil); -#else - *ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0); - *ret_stacksize = stacksize; - newg->gcinitial_sp = *ret_stack; - newg->gcstack_size = stacksize; - runtime_xadd(&runtime_stacks_sys, stacksize); -#endif - } - return newg; -} - -/* For runtime package testing. */ - -void runtime_testing_entersyscall(void) - __asm__ (GOSYM_PREFIX "runtime.entersyscall"); - -void -runtime_testing_entersyscall() -{ - runtime_entersyscall(); -} - -void runtime_testing_exitsyscall(void) - __asm__ (GOSYM_PREFIX "runtime.exitsyscall"); - -void -runtime_testing_exitsyscall() -{ - runtime_exitsyscall(); -} - -G* -__go_go(void (*fn)(void*), void* arg) -{ - byte *sp; - size_t spsize; - G *newg; - int64 goid; - - goid = runtime_xadd64((uint64*)&runtime_sched.goidgen, 1); - if(raceenabled) - runtime_racegostart(goid, runtime_getcallerpc(&fn)); - - schedlock(); - - if((newg = gfget()) != nil) { -#ifdef USING_SPLIT_STACK - int dont_block_signals = 0; - - sp = __splitstack_resetcontext(&newg->stack_context[0], - &spsize); - __splitstack_block_signals_context(&newg->stack_context[0], - &dont_block_signals, nil); -#else - sp = newg->gcinitial_sp; - spsize = newg->gcstack_size; - if(spsize == 0) - runtime_throw("bad spsize in __go_go"); - newg->gcnext_sp = sp; -#endif - } else { - newg = runtime_malg(StackMin, &sp, &spsize); - if(runtime_lastg == nil) - runtime_allg = newg; - else - runtime_lastg->alllink = newg; - runtime_lastg = newg; - } - newg->status = Gwaiting; - newg->waitreason = "new goroutine"; - - newg->entry = (byte*)fn; - newg->param = arg; - newg->gopc = (uintptr)__builtin_return_address(0); - - runtime_sched.gcount++; - newg->goid = goid; - - if(sp == nil) - runtime_throw("nil g->stack0"); - - { - // Avoid warnings about variables clobbered by - // longjmp. - byte * volatile vsp = sp; - size_t volatile vspsize = spsize; - G * volatile vnewg = newg; - - getcontext(&vnewg->context); - vnewg->context.uc_stack.ss_sp = vsp; -#ifdef MAKECONTEXT_STACK_TOP - vnewg->context.uc_stack.ss_sp += vspsize; -#endif - vnewg->context.uc_stack.ss_size = vspsize; - makecontext(&vnewg->context, kickoff, 0); - - newprocreadylocked(vnewg); - schedunlock(); - - return vnewg; - } -} - -// Put on gfree list. Sched must be locked. -static void -gfput(G *gp) -{ - gp->schedlink = runtime_sched.gfree; - runtime_sched.gfree = gp; -} - -// Get from gfree list. Sched must be locked. -static G* -gfget(void) -{ - G *gp; - - gp = runtime_sched.gfree; - if(gp) - runtime_sched.gfree = gp->schedlink; - return gp; -} - -void runtime_Gosched (void) __asm__ (GOSYM_PREFIX "runtime.Gosched"); - -void -runtime_Gosched(void) -{ - runtime_gosched(); -} - -// Implementation of runtime.GOMAXPROCS. -// delete when scheduler is stronger -int32 -runtime_gomaxprocsfunc(int32 n) -{ - int32 ret; - uint32 v; - - schedlock(); - ret = runtime_gomaxprocs; - if(n <= 0) - n = ret; - if(n > maxgomaxprocs) - n = maxgomaxprocs; - runtime_gomaxprocs = n; - if(runtime_gomaxprocs > 1) - runtime_singleproc = false; - if(runtime_gcwaiting != 0) { - if(atomic_mcpumax(runtime_sched.atomic) != 1) - runtime_throw("invalid mcpumax during gc"); - schedunlock(); - return ret; - } - - setmcpumax(n); - - // If there are now fewer allowed procs - // than procs running, stop. - v = runtime_atomicload(&runtime_sched.atomic); - if((int32)atomic_mcpu(v) > n) { - schedunlock(); - runtime_gosched(); - return ret; - } - // handle more procs - matchmg(); - schedunlock(); - return ret; -} - -void -runtime_LockOSThread(void) -{ - if(m == &runtime_m0 && runtime_sched.init) { - runtime_sched.lockmain = true; - return; - } - m->lockedg = g; - g->lockedm = m; -} - -void -runtime_UnlockOSThread(void) -{ - if(m == &runtime_m0 && runtime_sched.init) { - runtime_sched.lockmain = false; - return; - } - m->lockedg = nil; - g->lockedm = nil; -} - -bool -runtime_lockedOSThread(void) -{ - return g->lockedm != nil && m->lockedg != nil; -} - -// for testing of callbacks - -_Bool runtime_golockedOSThread(void) - __asm__ (GOSYM_PREFIX "runtime.golockedOSThread"); - -_Bool -runtime_golockedOSThread(void) -{ - return runtime_lockedOSThread(); -} - -// for testing of wire, unwire -uint32 -runtime_mid() -{ - return m->id; -} - -intgo runtime_NumGoroutine (void) - __asm__ (GOSYM_PREFIX "runtime.NumGoroutine"); - -intgo -runtime_NumGoroutine() -{ - return runtime_sched.gcount; -} - -int32 -runtime_gcount(void) -{ - return runtime_sched.gcount; -} - -int32 -runtime_mcount(void) -{ - return runtime_sched.mcount; -} - -static struct { - Lock; - void (*fn)(uintptr*, int32); - int32 hz; - uintptr pcbuf[100]; - Location locbuf[100]; -} prof; - -// Called if we receive a SIGPROF signal. -void -runtime_sigprof() -{ - int32 n, i; - - if(prof.fn == nil || prof.hz == 0) - return; - - runtime_lock(&prof); - if(prof.fn == nil) { - runtime_unlock(&prof); - return; - } - n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf)); - for(i = 0; i < n; i++) - prof.pcbuf[i] = prof.locbuf[i].pc; - if(n > 0) - prof.fn(prof.pcbuf, n); - runtime_unlock(&prof); -} - -// Arrange to call fn with a traceback hz times a second. -void -runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz) -{ - // Force sane arguments. - if(hz < 0) - hz = 0; - if(hz == 0) - fn = nil; - if(fn == nil) - hz = 0; - - // Stop profiler on this cpu so that it is safe to lock prof. - // if a profiling signal came in while we had prof locked, - // it would deadlock. - runtime_resetcpuprofiler(0); - - runtime_lock(&prof); - prof.fn = fn; - prof.hz = hz; - runtime_unlock(&prof); - runtime_lock(&runtime_sched); - runtime_sched.profilehz = hz; - runtime_unlock(&runtime_sched); - - if(hz != 0) - runtime_resetcpuprofiler(hz); -} diff --git a/gcc-4.8.1/libgo/runtime/race.h b/gcc-4.8.1/libgo/runtime/race.h deleted file mode 100644 index 9f3b3ec66..000000000 --- a/gcc-4.8.1/libgo/runtime/race.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2012 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. - -// Definitions related to data race detection. - -#ifdef RACE -enum { raceenabled = 1 }; -#else -enum { raceenabled = 0 }; -#endif - -// Initialize race detection subsystem. -void runtime_raceinit(void); -// Finalize race detection subsystem, does not return. -void runtime_racefini(void); - -void runtime_racemapshadow(void *addr, uintptr size); -void runtime_racemalloc(void *p, uintptr sz, void *pc); -void runtime_racefree(void *p); -void runtime_racegostart(int32 goid, void *pc); -void runtime_racegoend(int32 goid); -void runtime_racewritepc(void *addr, void *callpc, void *pc); -void runtime_racereadpc(void *addr, void *callpc, void *pc); -void runtime_racefingo(void); -void runtime_raceacquire(void *addr); -void runtime_raceacquireg(G *gp, void *addr); -void runtime_racerelease(void *addr); -void runtime_racereleaseg(G *gp, void *addr); -void runtime_racereleasemerge(void *addr); -void runtime_racereleasemergeg(G *gp, void *addr); diff --git a/gcc-4.8.1/libgo/runtime/reflect.goc b/gcc-4.8.1/libgo/runtime/reflect.goc deleted file mode 100644 index c798b269e..000000000 --- a/gcc-4.8.1/libgo/runtime/reflect.goc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package reflect -#include "runtime.h" -#include "go-type.h" -#include "interface.h" -#include "go-panic.h" - -func ifaceE2I(inter *Type, e Eface, ret *Iface) { - const Type *t; - Eface err; - - if(((uintptr)e.__type_descriptor&reflectFlags) != 0) - runtime_throw("invalid interface value"); - t = e.__type_descriptor; - if(t == nil) { - // explicit conversions require non-nil interface value. - runtime_newTypeAssertionError( - nil, nil, inter->__reflection, - nil, &err); - runtime_panic(err); - } - ret->__object = e.__object; - ret->__methods = __go_convert_interface(inter, t); -} diff --git a/gcc-4.8.1/libgo/runtime/rtems-task-variable-add.c b/gcc-4.8.1/libgo/runtime/rtems-task-variable-add.c deleted file mode 100644 index 89dbb007a..000000000 --- a/gcc-4.8.1/libgo/runtime/rtems-task-variable-add.c +++ /dev/null @@ -1,24 +0,0 @@ -/* rtems-task-variable-add.c -- adding a task specific variable in RTEMS OS. - - Copyright 2010 The Go Authors. All rights reserved. - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file. */ - -#include <rtems/error.h> -#include <rtems/system.h> -#include <rtems/rtems/tasks.h> - -#include "go-assert.h" - -/* RTEMS does not support GNU TLS extension __thread. */ -void -__wrap_rtems_task_variable_add (void **var) -{ - rtems_status_code sc = rtems_task_variable_add (RTEMS_SELF, var, NULL); - if (sc != RTEMS_SUCCESSFUL) - { - rtems_error (sc, "rtems_task_variable_add failed"); - __go_assert (0); - } -} - diff --git a/gcc-4.8.1/libgo/runtime/runtime.c b/gcc-4.8.1/libgo/runtime/runtime.c deleted file mode 100644 index 48ece55d1..000000000 --- a/gcc-4.8.1/libgo/runtime/runtime.c +++ /dev/null @@ -1,183 +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 <unistd.h> - -#include "config.h" - -#include "runtime.h" -#include "array.h" -#include "go-panic.h" - -int32 -runtime_gotraceback(void) -{ - const byte *p; - - p = runtime_getenv("GOTRACEBACK"); - if(p == nil || p[0] == '\0') - return 1; // default is on - return runtime_atoi(p); -} - -static int32 argc; -static byte** argv; - -extern Slice os_Args __asm__ (GOSYM_PREFIX "os.Args"); -extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs"); - -void (*runtime_sysargs)(int32, uint8**); - -void -runtime_args(int32 c, byte **v) -{ - argc = c; - argv = v; - if(runtime_sysargs != nil) - runtime_sysargs(c, v); -} - -byte* -runtime_progname() -{ - return argc == 0 ? nil : argv[0]; -} - -void -runtime_goargs(void) -{ - String *s; - int32 i; - - // for windows implementation see "os" package - if(Windows) - return; - - s = runtime_malloc(argc*sizeof s[0]); - for(i=0; i<argc; i++) - s[i] = runtime_gostringnocopy((const byte*)argv[i]); - os_Args.__values = (void*)s; - os_Args.__count = argc; - os_Args.__capacity = argc; -} - -void -runtime_goenvs_unix(void) -{ - String *s; - int32 i, n; - - for(n=0; argv[argc+1+n] != 0; n++) - ; - - s = runtime_malloc(n*sizeof s[0]); - for(i=0; i<n; i++) - s[i] = runtime_gostringnocopy(argv[argc+1+i]); - syscall_Envs.__values = (void*)s; - syscall_Envs.__count = n; - syscall_Envs.__capacity = n; -} - -int32 -runtime_atoi(const byte *p) -{ - int32 n; - - n = 0; - while('0' <= *p && *p <= '9') - n = n*10 + *p++ - '0'; - return n; -} - -uint32 -runtime_fastrand1(void) -{ - M *m; - uint32 x; - - m = runtime_m(); - x = m->fastrand; - x += x; - if(x & 0x80000000L) - x ^= 0x88888eefUL; - m->fastrand = x; - return x; -} - -static struct root_list runtime_roots = -{ nil, - { { &syscall_Envs, sizeof syscall_Envs }, - { &os_Args, sizeof os_Args }, - { nil, 0 } }, -}; - -void -runtime_check(void) -{ - __go_register_gc_roots(&runtime_roots); -} - -int64 -runtime_cputicks(void) -{ -#if defined(__386__) || defined(__x86_64__) - uint32 low, high; - asm("rdtsc" : "=a" (low), "=d" (high)); - return (int64)(((uint64)high << 32) | (uint64)low); -#else - // FIXME: implement for other processors. - return 0; -#endif -} - -bool -runtime_showframe(String s, bool current) -{ - static int32 traceback = -1; - - if(current && runtime_m()->throwing > 0) - return 1; - if(traceback < 0) - traceback = runtime_gotraceback(); - return traceback > 1 || (__builtin_memchr(s.str, '.', s.len) != nil && __builtin_memcmp(s.str, "runtime.", 7) != 0); -} - -static Lock ticksLock; -static int64 ticks; - -int64 -runtime_tickspersecond(void) -{ - int64 res, t0, t1, c0, c1; - - res = (int64)runtime_atomicload64((uint64*)&ticks); - if(res != 0) - return ticks; - runtime_lock(&ticksLock); - res = ticks; - if(res == 0) { - t0 = runtime_nanotime(); - c0 = runtime_cputicks(); - runtime_usleep(100*1000); - t1 = runtime_nanotime(); - c1 = runtime_cputicks(); - if(t1 == t0) - t1++; - res = (c1-c0)*1000*1000*1000/(t1-t0); - if(res == 0) - res++; - runtime_atomicstore64((uint64*)&ticks, res); - } - runtime_unlock(&ticksLock); - return res; -} - -int64 runtime_pprof_runtime_cyclesPerSecond(void) - __asm__ (GOSYM_PREFIX "runtime_pprof.runtime_cyclesPerSecond"); - -int64 -runtime_pprof_runtime_cyclesPerSecond(void) -{ - return runtime_tickspersecond(); -} diff --git a/gcc-4.8.1/libgo/runtime/runtime.h b/gcc-4.8.1/libgo/runtime/runtime.h deleted file mode 100644 index 9392df162..000000000 --- a/gcc-4.8.1/libgo/runtime/runtime.h +++ /dev/null @@ -1,656 +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 "config.h" - -#include "go-assert.h" -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <pthread.h> -#include <semaphore.h> -#include <ucontext.h> - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#include "interface.h" -#include "go-alloc.h" - -#define _STRINGIFY2_(x) #x -#define _STRINGIFY_(x) _STRINGIFY2_(x) -#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__) - -/* This file supports C files copied from the 6g runtime library. - This is a version of the 6g runtime.h rewritten for gccgo's version - of the code. */ - -typedef signed int int8 __attribute__ ((mode (QI))); -typedef unsigned int uint8 __attribute__ ((mode (QI))); -typedef signed int int16 __attribute__ ((mode (HI))); -typedef unsigned int uint16 __attribute__ ((mode (HI))); -typedef signed int int32 __attribute__ ((mode (SI))); -typedef unsigned int uint32 __attribute__ ((mode (SI))); -typedef signed int int64 __attribute__ ((mode (DI))); -typedef unsigned int uint64 __attribute__ ((mode (DI))); -typedef float float32 __attribute__ ((mode (SF))); -typedef double float64 __attribute__ ((mode (DF))); -typedef signed int intptr __attribute__ ((mode (pointer))); -typedef unsigned int uintptr __attribute__ ((mode (pointer))); - -typedef intptr intgo; // Go's int -typedef uintptr uintgo; // Go's uint - -/* Defined types. */ - -typedef uint8 bool; -typedef uint8 byte; -typedef struct Func Func; -typedef struct G G; -typedef union Lock Lock; -typedef struct M M; -typedef union Note Note; -typedef struct SigTab SigTab; -typedef struct MCache MCache; -typedef struct FixAlloc FixAlloc; -typedef struct Hchan Hchan; -typedef struct Timers Timers; -typedef struct Timer Timer; -typedef struct GCStats GCStats; -typedef struct LFNode LFNode; -typedef struct ParFor ParFor; -typedef struct ParForThread ParForThread; -typedef struct CgoMal CgoMal; - -typedef struct __go_open_array Slice; -typedef struct String String; -typedef struct __go_interface Iface; -typedef struct __go_empty_interface Eface; -typedef struct __go_type_descriptor Type; -typedef struct __go_defer_stack Defer; -typedef struct __go_panic_stack Panic; - -typedef struct __go_ptr_type PtrType; -typedef struct __go_func_type FuncType; -typedef struct __go_map_type MapType; - -typedef struct Traceback Traceback; - -typedef struct Location Location; - -/* - * Per-CPU declaration. - */ -extern M* runtime_m(void); -extern G* runtime_g(void); - -extern M runtime_m0; -extern G runtime_g0; - -/* - * defined constants - */ -enum -{ - // G status - // - // If you add to this list, add to the list - // of "okay during garbage collection" status - // in mgc0.c too. - Gidle, - Grunnable, - Grunning, - Gsyscall, - Gwaiting, - Gmoribund, - Gdead, -}; -enum -{ - true = 1, - false = 0, -}; -enum -{ - PtrSize = sizeof(void*), -}; -enum -{ - // Per-M stack segment cache size. - StackCacheSize = 32, - // Global <-> per-M stack segment cache transfer batch size. - StackCacheBatch = 16, -}; - -/* - * structures - */ -union Lock -{ - uint32 key; // futex-based impl - M* waitm; // linked list of waiting M's (sema-based impl) -}; -union Note -{ - uint32 key; // futex-based impl - M* waitm; // waiting M (sema-based impl) -}; -struct String -{ - const byte* str; - intgo len; -}; -struct GCStats -{ - // the struct must consist of only uint64's, - // because it is casted to uint64[]. - uint64 nhandoff; - uint64 nhandoffcnt; - uint64 nprocyield; - uint64 nosyield; - uint64 nsleep; -}; - -// A location in the program, used for backtraces. -struct Location -{ - uintptr pc; - String filename; - String function; - intgo lineno; -}; - -struct G -{ - Defer* defer; - Panic* panic; - void* exception; // current exception being thrown - bool is_foreign; // whether current exception from other language - void *gcstack; // if status==Gsyscall, gcstack = stackbase to use during gc - uintptr gcstack_size; - void* gcnext_segment; - void* gcnext_sp; - void* gcinitial_sp; - ucontext_t gcregs; - byte* entry; // initial function - G* alllink; // on allg - void* param; // passed parameter on wakeup - bool fromgogo; // reached from gogo - int16 status; - int64 goid; - uint32 selgen; // valid sudog pointer - const char* waitreason; // if status==Gwaiting - G* schedlink; - bool readyonstop; - bool ispanic; - bool issystem; - int8 raceignore; // ignore race detection events - M* m; // for debuggers, but offset not hard-coded - M* lockedm; - M* idlem; - int32 sig; - int32 writenbuf; - byte* writebuf; - // DeferChunk *dchunk; - // DeferChunk *dchunknext; - uintptr sigcode0; - uintptr sigcode1; - // uintptr sigpc; - uintptr gopc; // pc of go statement that created this goroutine - - int32 ncgo; - CgoMal* cgomal; - - Traceback* traceback; - - ucontext_t context; - void* stack_context[10]; -}; - -struct M -{ - G* g0; // goroutine with scheduling stack - G* gsignal; // signal-handling G - G* curg; // current running goroutine - int32 id; - int32 mallocing; - int32 throwing; - int32 gcing; - int32 locks; - int32 nomemprof; - int32 waitnextg; - int32 dying; - int32 profilehz; - int32 helpgc; - uint32 fastrand; - uint64 ncgocall; // number of cgo calls in total - Note havenextg; - G* nextg; - M* alllink; // on allm - M* schedlink; - MCache *mcache; - G* lockedg; - G* idleg; - Location createstack[32]; // Stack that created this thread. - M* nextwaitm; // next M waiting for lock - uintptr waitsema; // semaphore for parking on locks - uint32 waitsemacount; - uint32 waitsemalock; - GCStats gcstats; - bool racecall; - void* racepc; - - uintptr settype_buf[1024]; - uintptr settype_bufsize; - - uintptr end[]; -}; - -struct SigTab -{ - int32 sig; - int32 flags; -}; -enum -{ - SigNotify = 1<<0, // let signal.Notify have signal, even if from kernel - SigKill = 1<<1, // if signal.Notify doesn't take it, exit quietly - SigThrow = 1<<2, // if signal.Notify doesn't take it, exit loudly - SigPanic = 1<<3, // if the signal is from the kernel, panic - SigDefault = 1<<4, // if the signal isn't explicitly requested, don't monitor it -}; - -#ifndef NSIG -#define NSIG 32 -#endif - -// NOTE(rsc): keep in sync with extern.go:/type.Func. -// Eventually, the loaded symbol table should be closer to this form. -struct Func -{ - String name; - uintptr entry; // entry pc -}; - - -#ifdef GOOS_windows -enum { - Windows = 1 -}; -#else -enum { - Windows = 0 -}; -#endif - -struct Timers -{ - Lock; - G *timerproc; - bool sleeping; - bool rescheduling; - Note waitnote; - Timer **t; - int32 len; - int32 cap; -}; - -// Package time knows the layout of this structure. -// If this struct changes, adjust ../time/sleep.go:/runtimeTimer. -struct Timer -{ - int32 i; // heap index - - // Timer wakes up at when, and then at when+period, ... (period > 0 only) - // each time calling f(now, arg) in the timer goroutine, so f must be - // a well-behaved function and not block. - int64 when; - int64 period; - void (*f)(int64, Eface); - Eface arg; -}; - -// Lock-free stack node. -struct LFNode -{ - LFNode *next; - uintptr pushcnt; -}; - -// Parallel for descriptor. -struct ParFor -{ - void (*body)(ParFor*, uint32); // executed for each element - uint32 done; // number of idle threads - uint32 nthr; // total number of threads - uint32 nthrmax; // maximum number of threads - uint32 thrseq; // thread id sequencer - uint32 cnt; // iteration space [0, cnt) - void *ctx; // arbitrary user context - bool wait; // if true, wait while all threads finish processing, - // otherwise parfor may return while other threads are still working - ParForThread *thr; // array of thread descriptors - // stats - uint64 nsteal; - uint64 nstealcnt; - uint64 nprocyield; - uint64 nosyield; - uint64 nsleep; -}; - -// Track memory allocated by code not written in Go during a cgo call, -// so that the garbage collector can see them. -struct CgoMal -{ - CgoMal *next; - byte *alloc; -}; - -/* - * defined macros - * you need super-gopher-guru privilege - * to add this list. - */ -#define nelem(x) (sizeof(x)/sizeof((x)[0])) -#define nil ((void*)0) -#define USED(v) ((void) v) -#define ROUND(x, n) (((x)+(n)-1)&~((n)-1)) /* all-caps to mark as macro: it evaluates n twice */ - -/* - * external data - */ -extern uintptr runtime_zerobase; -extern G* runtime_allg; -extern G* runtime_lastg; -extern M* runtime_allm; -extern int32 runtime_gomaxprocs; -extern bool runtime_singleproc; -extern uint32 runtime_panicking; -extern int32 runtime_gcwaiting; // gc is waiting to run -extern int32 runtime_ncpu; - -/* - * common functions and data - */ -intgo runtime_findnull(const byte*); -void runtime_dump(byte*, int32); - -/* - * very low level c-called - */ -void runtime_args(int32, byte**); -void runtime_osinit(); -void runtime_goargs(void); -void runtime_goenvs(void); -void runtime_goenvs_unix(void); -void runtime_throw(const char*) __attribute__ ((noreturn)); -void runtime_panicstring(const char*) __attribute__ ((noreturn)); -void runtime_prints(const char*); -void runtime_printf(const char*, ...); -void* runtime_mal(uintptr); -void runtime_schedinit(void); -void runtime_initsig(void); -void runtime_sigenable(uint32 sig); -int32 runtime_gotraceback(void); -void runtime_goroutineheader(G*); -void runtime_goroutinetrailer(G*); -void runtime_traceback(); -void runtime_tracebackothers(G*); -void runtime_printtrace(Location*, int32, bool); -String runtime_gostring(const byte*); -String runtime_gostringnocopy(const byte*); -void* runtime_mstart(void*); -G* runtime_malg(int32, byte**, size_t*); -void runtime_minit(void); -void runtime_mallocinit(void); -void runtime_gosched(void); -void runtime_park(void(*)(Lock*), Lock*, const char*); -void runtime_tsleep(int64, const char*); -M* runtime_newm(void); -void runtime_goexit(void); -void runtime_entersyscall(void) __asm__ (GOSYM_PREFIX "syscall.Entersyscall"); -void runtime_exitsyscall(void) __asm__ (GOSYM_PREFIX "syscall.Exitsyscall"); -void siginit(void); -bool __go_sigsend(int32 sig); -int32 runtime_callers(int32, Location*, int32); -int64 runtime_nanotime(void); -int64 runtime_cputicks(void); -int64 runtime_tickspersecond(void); -void runtime_blockevent(int64, int32); -extern int64 runtime_blockprofilerate; - -void runtime_stoptheworld(void); -void runtime_starttheworld(void); -extern uint32 runtime_worldsema; -G* __go_go(void (*pfn)(void*), 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 runtime_lock(Lock*); -void runtime_unlock(Lock*); - -/* - * sleep and wakeup on one-time events. - * before any calls to notesleep or notewakeup, - * must call noteclear to initialize the Note. - * then, exactly one thread can call notesleep - * and exactly one thread can call notewakeup (once). - * once notewakeup has been called, the notesleep - * will return. future notesleep will return immediately. - * subsequent noteclear must be called only after - * previous notesleep has returned, e.g. it's disallowed - * to call noteclear straight after notewakeup. - * - * notetsleep is like notesleep but wakes up after - * a given number of nanoseconds even if the event - * has not yet happened. if a goroutine uses notetsleep to - * wake up early, it must wait to call noteclear until it - * can be sure that no other goroutine is calling - * notewakeup. - */ -void runtime_noteclear(Note*); -void runtime_notesleep(Note*); -void runtime_notewakeup(Note*); -void runtime_notetsleep(Note*, int64); - -/* - * low-level synchronization for implementing the above - */ -uintptr runtime_semacreate(void); -int32 runtime_semasleep(int64); -void runtime_semawakeup(M*); -// or -void runtime_futexsleep(uint32*, uint32, int64); -void runtime_futexwakeup(uint32*, uint32); - -/* - * Lock-free stack. - * Initialize uint64 head to 0, compare with 0 to test for emptiness. - * The stack does not keep pointers to nodes, - * so they can be garbage collected if there are no other pointers to nodes. - */ -void runtime_lfstackpush(uint64 *head, LFNode *node) - __asm__ (GOSYM_PREFIX "runtime.lfstackpush"); -LFNode* runtime_lfstackpop(uint64 *head); - -/* - * Parallel for over [0, n). - * body() is executed for each iteration. - * nthr - total number of worker threads. - * ctx - arbitrary user context. - * if wait=true, threads return from parfor() when all work is done; - * otherwise, threads can return while other threads are still finishing processing. - */ -ParFor* runtime_parforalloc(uint32 nthrmax); -void runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32)); -void runtime_parfordo(ParFor *desc) __asm__ (GOSYM_PREFIX "runtime.parfordo"); - -/* - * low level C-called - */ -#define runtime_mmap mmap -#define runtime_munmap munmap -#define runtime_madvise madvise -#define runtime_memclr(buf, size) __builtin_memset((buf), 0, (size)) -#define runtime_getcallerpc(p) __builtin_return_address(0) - -#ifdef __rtems__ -void __wrap_rtems_task_variable_add(void **); -#endif - -/* - * Names generated by gccgo. - */ -#define runtime_printbool __go_print_bool -#define runtime_printfloat __go_print_double -#define runtime_printint __go_print_int64 -#define runtime_printiface __go_print_interface -#define runtime_printeface __go_print_empty_interface -#define runtime_printstring __go_print_string -#define runtime_printpointer __go_print_pointer -#define runtime_printuint __go_print_uint64 -#define runtime_printslice __go_print_slice -#define runtime_printcomplex __go_print_complex - -/* - * runtime go-called - */ -void runtime_printbool(_Bool); -void runtime_printfloat(double); -void runtime_printint(int64); -void runtime_printiface(Iface); -void runtime_printeface(Eface); -void runtime_printstring(String); -void runtime_printpc(void*); -void runtime_printpointer(void*); -void runtime_printuint(uint64); -void runtime_printhex(uint64); -void runtime_printslice(Slice); -void runtime_printcomplex(__complex double); - -struct __go_func_type; -void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool, - void **, void **) - __asm__ (GOSYM_PREFIX "reflect.call"); - -/* Functions. */ -#define runtime_panic __go_panic -#define runtime_write(d, v, n) write((d), (v), (n)) -#define runtime_malloc(s) __go_alloc(s) -#define runtime_free(p) __go_free(p) -#define runtime_strcmp(s1, s2) __builtin_strcmp((s1), (s2)) -#define runtime_mcmp(a, b, s) __builtin_memcmp((a), (b), (s)) -#define runtime_memmove(a, b, s) __builtin_memmove((a), (b), (s)) -#define runtime_exit(s) exit(s) -MCache* runtime_allocmcache(void); -void free(void *v); -#define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new) -#define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new) -#define runtime_cas64(pval, pold, new) __atomic_compare_exchange_n (pval, pold, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) -#define runtime_xadd(p, v) __sync_add_and_fetch (p, v) -#define runtime_xadd64(p, v) __sync_add_and_fetch (p, v) -#define runtime_xchg(p, v) __atomic_exchange_n (p, v, __ATOMIC_SEQ_CST) -#define runtime_atomicload(p) __atomic_load_n (p, __ATOMIC_SEQ_CST) -#define runtime_atomicstore(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST) -#define runtime_atomicloadp(p) __atomic_load_n (p, __ATOMIC_SEQ_CST) -#define runtime_atomicstorep(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST) -#define runtime_atomicload64(p) __atomic_load_n (p, __ATOMIC_SEQ_CST) -#define runtime_atomicstore64(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST) -#define PREFETCH(p) __builtin_prefetch(p) - -struct __go_func_type; -bool runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *); -#define runtime_getcallersp(p) __builtin_frame_address(1) -int32 runtime_mcount(void); -int32 runtime_gcount(void); -void runtime_dopanic(int32) __attribute__ ((noreturn)); -void runtime_startpanic(void); -void runtime_ready(G*); -const byte* runtime_getenv(const char*); -int32 runtime_atoi(const byte*); -uint32 runtime_fastrand1(void); - -void runtime_sigprof(); -void runtime_resetcpuprofiler(int32); -void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32); -void runtime_usleep(uint32); - -/* - * runtime c-called (but written in Go) - */ -void runtime_printany(Eface) - __asm__ (GOSYM_PREFIX "runtime.Printany"); -void runtime_newTypeAssertionError(const String*, const String*, const String*, const String*, Eface*) - __asm__ (GOSYM_PREFIX "runtime.NewTypeAssertionError"); -void runtime_newErrorString(String, Eface*) - __asm__ (GOSYM_PREFIX "runtime.NewErrorString"); - -/* - * wrapped for go users - */ -#define ISNAN(f) __builtin_isnan(f) -void runtime_semacquire(uint32 volatile *); -void runtime_semrelease(uint32 volatile *); -int32 runtime_gomaxprocsfunc(int32 n); -void runtime_procyield(uint32); -void runtime_osyield(void); -void runtime_LockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.LockOSThread"); -void runtime_UnlockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.UnlockOSThread"); - -bool runtime_showframe(String, bool); - -uintptr runtime_memlimit(void); - -// If appropriate, ask the operating system to control whether this -// thread should receive profiling signals. This is only necessary on OS X. -// An operating system should not deliver a profiling signal to a -// thread that is not actually executing (what good is that?), but that's -// what OS X prefers to do. When profiling is turned on, we mask -// away the profiling signal when threads go to sleep, so that OS X -// is forced to deliver the signal to a thread that's actually running. -// This is a no-op on other systems. -void runtime_setprof(bool); - -enum -{ - UseSpanType = 1, -}; - -void runtime_setsig(int32, bool, bool); -#define runtime_setitimer setitimer - -void runtime_check(void); - -// A list of global variables that the garbage collector must scan. -struct root_list { - struct root_list *next; - struct root { - void *decl; - size_t size; - } roots[]; -}; - -void __go_register_gc_roots(struct root_list*); - -// Size of stack space allocated using Go's allocator. -// This will be 0 when using split stacks, as in that case -// the stacks are allocated by the splitstack library. -extern uintptr runtime_stacks_sys; - -struct backtrace_state; -extern struct backtrace_state *__go_get_backtrace_state(void); -extern _Bool __go_file_line(uintptr, String*, String*, intgo *); -extern byte* runtime_progname(); - -int32 getproccount(void); diff --git a/gcc-4.8.1/libgo/runtime/runtime1.goc b/gcc-4.8.1/libgo/runtime/runtime1.goc deleted file mode 100644 index 9ce83000b..000000000 --- a/gcc-4.8.1/libgo/runtime/runtime1.goc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package runtime -#include "runtime.h" - -func GOMAXPROCS(n int) (ret int) { - ret = runtime_gomaxprocsfunc(n); -} - -func NumCPU() (ret int) { - ret = runtime_ncpu; -} diff --git a/gcc-4.8.1/libgo/runtime/sema.goc b/gcc-4.8.1/libgo/runtime/sema.goc deleted file mode 100644 index 4622f6c8a..000000000 --- a/gcc-4.8.1/libgo/runtime/sema.goc +++ /dev/null @@ -1,197 +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 - -package sync -#include "runtime.h" -#include "arch.h" - -typedef struct Sema Sema; -struct Sema -{ - uint32 volatile* addr; - G* g; - int64 releasetime; - Sema* prev; - Sema* next; -}; - -typedef struct SemaRoot SemaRoot; -struct SemaRoot -{ - Lock; - Sema* head; - Sema* tail; - // Number of waiters. Read w/o the lock. - uint32 volatile nwait; -}; - -// Prime to not correlate with any user patterns. -#define SEMTABLESZ 251 - -union semtable -{ - SemaRoot; - uint8 pad[CacheLineSize]; -}; -static union semtable semtable[SEMTABLESZ]; - -static SemaRoot* -semroot(uint32 volatile *addr) -{ - return &semtable[((uintptr)addr >> 3) % SEMTABLESZ]; -} - -static void -semqueue(SemaRoot *root, uint32 volatile *addr, Sema *s) -{ - s->g = runtime_g(); - s->addr = addr; - s->next = nil; - s->prev = root->tail; - if(root->tail) - root->tail->next = s; - else - root->head = s; - root->tail = s; -} - -static void -semdequeue(SemaRoot *root, Sema *s) -{ - if(s->next) - s->next->prev = s->prev; - else - root->tail = s->prev; - if(s->prev) - s->prev->next = s->next; - else - root->head = s->next; - s->prev = nil; - s->next = nil; -} - -static int32 -cansemacquire(uint32 volatile *addr) -{ - uint32 v; - - while((v = runtime_atomicload(addr)) > 0) - if(runtime_cas(addr, v, v-1)) - return 1; - return 0; -} - -static void -semacquireimpl(uint32 volatile *addr, int32 profile) -{ - Sema s; // Needs to be allocated on stack, otherwise garbage collector could deallocate it - SemaRoot *root; - int64 t0; - - // Easy case. - if(cansemacquire(addr)) - return; - - // Harder case: - // increment waiter count - // try cansemacquire one more time, return if succeeded - // enqueue itself as a waiter - // sleep - // (waiter descriptor is dequeued by signaler) - root = semroot(addr); - t0 = 0; - s.releasetime = 0; - if(profile && runtime_blockprofilerate > 0) { - t0 = runtime_cputicks(); - s.releasetime = -1; - } - for(;;) { - - runtime_lock(root); - // Add ourselves to nwait to disable "easy case" in semrelease. - runtime_xadd(&root->nwait, 1); - // Check cansemacquire to avoid missed wakeup. - if(cansemacquire(addr)) { - runtime_xadd(&root->nwait, -1); - runtime_unlock(root); - return; - } - // Any semrelease after the cansemacquire knows we're waiting - // (we set nwait above), so go to sleep. - semqueue(root, addr, &s); - runtime_park(runtime_unlock, root, "semacquire"); - if(cansemacquire(addr)) { - if(t0) - runtime_blockevent(s.releasetime - t0, 3); - return; - } - } -} - -void -runtime_semacquire(uint32 volatile *addr) -{ - semacquireimpl(addr, 0); -} - -void -runtime_semrelease(uint32 volatile *addr) -{ - Sema *s; - SemaRoot *root; - - root = semroot(addr); - runtime_xadd(addr, 1); - - // Easy case: no waiters? - // This check must happen after the xadd, to avoid a missed wakeup - // (see loop in semacquire). - if(runtime_atomicload(&root->nwait) == 0) - return; - - // Harder case: search for a waiter and wake it. - runtime_lock(root); - if(runtime_atomicload(&root->nwait) == 0) { - // The count is already consumed by another goroutine, - // so no need to wake up another goroutine. - runtime_unlock(root); - return; - } - for(s = root->head; s; s = s->next) { - if(s->addr == addr) { - runtime_xadd(&root->nwait, -1); - semdequeue(root, s); - break; - } - } - runtime_unlock(root); - if(s) { - if(s->releasetime) - s->releasetime = runtime_cputicks(); - runtime_ready(s->g); - } -} - -func runtime_Semacquire(addr *uint32) { - semacquireimpl(addr, 1); -} - -func runtime_Semrelease(addr *uint32) { - runtime_semrelease(addr); -} diff --git a/gcc-4.8.1/libgo/runtime/signal_unix.c b/gcc-4.8.1/libgo/runtime/signal_unix.c deleted file mode 100644 index 3b8f43937..000000000 --- a/gcc-4.8.1/libgo/runtime/signal_unix.c +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2012 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. - -// +build darwin freebsd linux openbsd netbsd - -#include <sys/time.h> - -#include "runtime.h" -#include "defs.h" - -extern SigTab runtime_sigtab[]; - -void -runtime_initsig(void) -{ - int32 i; - SigTab *t; - - // First call: basic setup. - for(i = 0; runtime_sigtab[i].sig != -1; i++) { - t = &runtime_sigtab[i]; - if((t->flags == 0) || (t->flags & SigDefault)) - continue; - runtime_setsig(i, false, true); - } -} - -void -runtime_sigenable(uint32 sig) -{ - int32 i; - SigTab *t; - - for(i = 0; runtime_sigtab[i].sig != -1; i++) { - // ~0 means all signals. - if(~sig == 0 || runtime_sigtab[i].sig == (int32)sig) { - t = &runtime_sigtab[i]; - if(t->flags & SigDefault) { - runtime_setsig(i, false, true); - t->flags &= ~SigDefault; // make this idempotent - } - } - } -} - -void -runtime_resetcpuprofiler(int32 hz) -{ - struct itimerval it; - - runtime_memclr((byte*)&it, sizeof it); - if(hz == 0) { - runtime_setitimer(ITIMER_PROF, &it, nil); - runtime_setprof(false); - } else { - it.it_interval.tv_sec = 0; - it.it_interval.tv_usec = 1000000 / hz; - it.it_value = it.it_interval; - runtime_setitimer(ITIMER_PROF, &it, nil); - runtime_setprof(true); - } - runtime_m()->profilehz = hz; -} diff --git a/gcc-4.8.1/libgo/runtime/sigqueue.goc b/gcc-4.8.1/libgo/runtime/sigqueue.goc deleted file mode 100644 index 82b0400d6..000000000 --- a/gcc-4.8.1/libgo/runtime/sigqueue.goc +++ /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. - -// This file implements runtime support for signal handling. -// -// Most synchronization primitives are not available from -// the signal handler (it cannot block, allocate memory, or use locks) -// so the handler communicates with a processing goroutine -// via struct sig, below. -// -// sigsend() is called by the signal handler to queue a new signal. -// signal_recv() is called by the Go program to receive a newly queued signal. -// Synchronization between sigsend() and signal_recv() is based on the sig.state -// variable. It can be in 3 states: 0, HASWAITER and HASSIGNAL. -// HASWAITER means that signal_recv() is blocked on sig.Note and there are no -// new pending signals. -// HASSIGNAL means that sig.mask *may* contain new pending signals, -// signal_recv() can't be blocked in this state. -// 0 means that there are no new pending signals and signal_recv() is not blocked. -// Transitions between states are done atomically with CAS. -// When signal_recv() is unblocked, it resets sig.Note and rechecks sig.mask. -// If several sigsend()'s and signal_recv() execute concurrently, it can lead to -// unnecessary rechecks of sig.mask, but must not lead to missed signals -// nor deadlocks. - -package signal -#include "config.h" -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "defs.h" - -static struct { - Note; - uint32 mask[(NSIG+31)/32]; - uint32 wanted[(NSIG+31)/32]; - uint32 state; - bool inuse; -} sig; - -enum { - HASWAITER = 1, - HASSIGNAL = 2, -}; - -// Called from sighandler to send a signal back out of the signal handling thread. -bool -__go_sigsend(int32 s) -{ - uint32 bit, mask, old, new; - - if(!sig.inuse || s < 0 || (size_t)s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31)))) - return false; - bit = 1 << (s&31); - for(;;) { - mask = sig.mask[s/32]; - if(mask & bit) - break; // signal already in queue - if(runtime_cas(&sig.mask[s/32], mask, mask|bit)) { - // Added to queue. - // Only send a wakeup if the receiver needs a kick. - for(;;) { - old = runtime_atomicload(&sig.state); - if(old == HASSIGNAL) - break; - if(old == HASWAITER) - new = 0; - else // if(old == 0) - new = HASSIGNAL; - if(runtime_cas(&sig.state, old, new)) { - if (old == HASWAITER) - runtime_notewakeup(&sig); - break; - } - } - break; - } - } - return true; -} - -// Called to receive the next queued signal. -// Must only be called from a single goroutine at a time. -func signal_recv() (m uint32) { - static uint32 recv[nelem(sig.mask)]; - uint32 i, old, new; - - for(;;) { - // Serve from local copy if there are bits left. - for(i=0; i<NSIG; i++) { - if(recv[i/32]&(1U<<(i&31))) { - recv[i/32] ^= 1U<<(i&31); - m = i; - goto done; - } - } - - // Check and update sig.state. - for(;;) { - old = runtime_atomicload(&sig.state); - if(old == HASWAITER) - runtime_throw("inconsistent state in signal_recv"); - if(old == HASSIGNAL) - new = 0; - else // if(old == 0) - new = HASWAITER; - if(runtime_cas(&sig.state, old, new)) { - if (new == HASWAITER) { - runtime_entersyscall(); - runtime_notesleep(&sig); - runtime_exitsyscall(); - runtime_noteclear(&sig); - } - break; - } - } - - // Get a new local copy. - for(i=0; (size_t)i<nelem(sig.mask); i++) { - for(;;) { - m = sig.mask[i]; - if(runtime_cas(&sig.mask[i], m, 0)) - break; - } - recv[i] = m; - } - } - -done:; - // goc requires that we fall off the end of functions - // that return values instead of using our own return - // statements. -} - -// Must only be called from a single goroutine at a time. -func signal_enable(s uint32) { - int32 i; - - if(!sig.inuse) { - // The first call to signal_enable is for us - // to use for initialization. It does not pass - // signal information in m. - sig.inuse = true; // enable reception of signals; cannot disable - runtime_noteclear(&sig); - return; - } - - if(~s == 0) { - // Special case: want everything. - for(i=0; (size_t)i<nelem(sig.wanted); i++) - sig.wanted[i] = ~(uint32)0; - runtime_sigenable(s); - return; - } - - if(s >= nelem(sig.wanted)*32) - return; - sig.wanted[s/32] |= 1U<<(s&31); - runtime_sigenable(s); -} diff --git a/gcc-4.8.1/libgo/runtime/string.goc b/gcc-4.8.1/libgo/runtime/string.goc deleted file mode 100644 index 04ecbe6f7..000000000 --- a/gcc-4.8.1/libgo/runtime/string.goc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2009, 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package runtime -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "go-string.h" - -#define charntorune(pv, str, len) __go_get_rune(str, len, pv) - -const String runtime_emptystring; - -intgo -runtime_findnull(const byte *s) -{ - if(s == nil) - return 0; - return __builtin_strlen((const char*) s); -} - -static String -gostringsize(intgo l, byte** pmem) -{ - String s; - byte *mem; - - if(l == 0) { - *pmem = nil; - return runtime_emptystring; - } - // leave room for NUL for C runtime (e.g., callers of getenv) - mem = runtime_mallocgc(l+1, FlagNoPointers, 1, 0); - s.str = mem; - s.len = l; - mem[l] = 0; - *pmem = mem; - return s; -} - -String -runtime_gostring(const byte *str) -{ - intgo l; - String s; - byte *mem; - - l = runtime_findnull(str); - s = gostringsize(l, &mem); - runtime_memmove(mem, str, l); - return s; -} - -String -runtime_gostringnocopy(const byte *str) -{ - String s; - - s.str = str; - s.len = runtime_findnull(str); - return s; -} - -enum -{ - Runeself = 0x80, -}; - -func stringiter(s String, k int) (retk int) { - 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: -} - -func stringiter2(s String, k int) (retk int, retv int32) { - 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: -} diff --git a/gcc-4.8.1/libgo/runtime/thread-linux.c b/gcc-4.8.1/libgo/runtime/thread-linux.c deleted file mode 100644 index 13d23c47b..000000000 --- a/gcc-4.8.1/libgo/runtime/thread-linux.c +++ /dev/null @@ -1,85 +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" - -// 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 threads sleeping on addr. -// Futexsleep is allowed to wake up spuriously. - -#include <errno.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <syscall.h> -#include <linux/futex.h> - -typedef struct timespec Timespec; - -// Atomically, -// if(*addr == val) sleep -// Might be woken up spuriously; that's allowed. -// Don't sleep longer than ns; ns < 0 means forever. -void -runtime_futexsleep(uint32 *addr, uint32 val, int64 ns) -{ - Timespec ts, *tsp; - - if(ns < 0) - tsp = nil; - else { - ts.tv_sec = ns/1000000000LL; - ts.tv_nsec = ns%1000000000LL; - // Avoid overflow - if(ts.tv_sec > 1<<30) - ts.tv_sec = 1<<30; - tsp = &ts; - } - - // Some Linux kernels have a bug where futex of - // FUTEX_WAIT returns an internal error code - // as an errno. Libpthread ignores the return value - // here, and so can we: as it says a few lines up, - // spurious wakeups are allowed. - syscall(__NR_futex, addr, FUTEX_WAIT, val, tsp, nil, 0); -} - -// If any procs are sleeping on addr, wake up at most cnt. -void -runtime_futexwakeup(uint32 *addr, uint32 cnt) -{ - int64 ret; - - ret = syscall(__NR_futex, addr, FUTEX_WAKE, cnt, 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. - runtime_printf("futexwakeup addr=%p returned %D\n", addr, ret); - *(int32*)0x1006 = 0x1006; -} - -void -runtime_osinit(void) -{ - runtime_ncpu = getproccount(); -} - -void -runtime_goenvs(void) -{ - runtime_goenvs_unix(); -} diff --git a/gcc-4.8.1/libgo/runtime/thread-sema.c b/gcc-4.8.1/libgo/runtime/thread-sema.c deleted file mode 100644 index 18827b025..000000000 --- a/gcc-4.8.1/libgo/runtime/thread-sema.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 "config.h" -#include "runtime.h" - -#include <errno.h> -#include <stdlib.h> -#include <time.h> -#include <semaphore.h> - -/* If we don't have sem_timedwait, use pthread_cond_timedwait instead. - We don't always use condition variables because on some systems - pthread_mutex_lock and pthread_mutex_unlock must be called by the - same thread. That is never true of semaphores. */ - -struct go_sem -{ - sem_t sem; - -#ifndef HAVE_SEM_TIMEDWAIT - int timedwait; - pthread_mutex_t mutex; - pthread_cond_t cond; -#endif -}; - -/* Create a semaphore. */ - -uintptr -runtime_semacreate(void) -{ - struct go_sem *p; - - /* Call malloc rather than runtime_malloc. This will allocate space - on the C heap. We can't call runtime_malloc here because it - could cause a deadlock. */ - p = malloc (sizeof (struct go_sem)); - if (sem_init (&p->sem, 0, 0) != 0) - runtime_throw ("sem_init"); - -#ifndef HAVE_SEM_TIMEDWAIT - if (pthread_mutex_init (&p->mutex, NULL) != 0) - runtime_throw ("pthread_mutex_init"); - if (pthread_cond_init (&p->cond, NULL) != 0) - runtime_throw ("pthread_cond_init"); -#endif - - return (uintptr) p; -} - -/* Acquire m->waitsema. */ - -int32 -runtime_semasleep (int64 ns) -{ - M *m; - struct go_sem *sem; - int r; - - m = runtime_m (); - sem = (struct go_sem *) m->waitsema; - if (ns >= 0) - { - int64 abs; - struct timespec ts; - int err; - - abs = ns + runtime_nanotime (); - ts.tv_sec = abs / 1000000000LL; - ts.tv_nsec = abs % 1000000000LL; - - err = 0; - -#ifdef HAVE_SEM_TIMEDWAIT - r = sem_timedwait (&sem->sem, &ts); - if (r != 0) - err = errno; -#else - if (pthread_mutex_lock (&sem->mutex) != 0) - runtime_throw ("pthread_mutex_lock"); - - while ((r = sem_trywait (&sem->sem)) != 0) - { - r = pthread_cond_timedwait (&sem->cond, &sem->mutex, &ts); - if (r != 0) - { - err = r; - break; - } - } - - if (pthread_mutex_unlock (&sem->mutex) != 0) - runtime_throw ("pthread_mutex_unlock"); -#endif - - if (err != 0) - { - if (err == ETIMEDOUT || err == EAGAIN || err == EINTR) - return -1; - runtime_throw ("sema_timedwait"); - } - return 0; - } - - while (sem_wait (&sem->sem) != 0) - { - if (errno == EINTR) - continue; - runtime_throw ("sem_wait"); - } - - return 0; -} - -/* Wake up mp->waitsema. */ - -void -runtime_semawakeup (M *mp) -{ - struct go_sem *sem; - - sem = (struct go_sem *) mp->waitsema; - if (sem_post (&sem->sem) != 0) - runtime_throw ("sem_post"); - -#ifndef HAVE_SEM_TIMEDWAIT - if (pthread_mutex_lock (&sem->mutex) != 0) - runtime_throw ("pthread_mutex_lock"); - if (pthread_cond_broadcast (&sem->cond) != 0) - runtime_throw ("pthread_cond_broadcast"); - if (pthread_mutex_unlock (&sem->mutex) != 0) - runtime_throw ("pthread_mutex_unlock"); -#endif -} - -void -runtime_osinit (void) -{ - runtime_ncpu = getproccount(); -} - -void -runtime_goenvs (void) -{ - runtime_goenvs_unix (); -} diff --git a/gcc-4.8.1/libgo/runtime/thread.c b/gcc-4.8.1/libgo/runtime/thread.c deleted file mode 100644 index 12d009926..000000000 --- a/gcc-4.8.1/libgo/runtime/thread.c +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include <errno.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/resource.h> - -#include "runtime.h" -#include "go-assert.h" - -/* For targets which don't have the required sync support. Really - these should be provided by gcc itself. FIXME. */ - -#if !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4) || !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8) || !defined (HAVE_SYNC_FETCH_AND_ADD_4) || !defined (HAVE_SYNC_ADD_AND_FETCH_8) - -static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER; - -#endif - -#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 - -_Bool -__sync_bool_compare_and_swap_4 (uint32*, uint32, uint32) - __attribute__ ((visibility ("hidden"))); - -_Bool -__sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new) -{ - int i; - _Bool ret; - - i = pthread_mutex_lock (&sync_lock); - __go_assert (i == 0); - - if (*ptr != old) - ret = 0; - else - { - *ptr = new; - ret = 1; - } - - i = pthread_mutex_unlock (&sync_lock); - __go_assert (i == 0); - - return ret; -} - -#endif - -#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8 - -_Bool -__sync_bool_compare_and_swap_8 (uint64*, uint64, uint64) - __attribute__ ((visibility ("hidden"))); - -_Bool -__sync_bool_compare_and_swap_8 (uint64* ptr, uint64 old, uint64 new) -{ - int i; - _Bool ret; - - i = pthread_mutex_lock (&sync_lock); - __go_assert (i == 0); - - if (*ptr != old) - ret = 0; - else - { - *ptr = new; - ret = 1; - } - - i = pthread_mutex_unlock (&sync_lock); - __go_assert (i == 0); - - return ret; -} - -#endif - -#ifndef HAVE_SYNC_FETCH_AND_ADD_4 - -uint32 -__sync_fetch_and_add_4 (uint32*, uint32) - __attribute__ ((visibility ("hidden"))); - -uint32 -__sync_fetch_and_add_4 (uint32* ptr, uint32 add) -{ - int i; - uint32 ret; - - i = pthread_mutex_lock (&sync_lock); - __go_assert (i == 0); - - ret = *ptr; - *ptr += add; - - i = pthread_mutex_unlock (&sync_lock); - __go_assert (i == 0); - - return ret; -} - -#endif - -#ifndef HAVE_SYNC_ADD_AND_FETCH_8 - -uint64 -__sync_add_and_fetch_8 (uint64*, uint64) - __attribute__ ((visibility ("hidden"))); - -uint64 -__sync_add_and_fetch_8 (uint64* ptr, uint64 add) -{ - int i; - uint64 ret; - - i = pthread_mutex_lock (&sync_lock); - __go_assert (i == 0); - - *ptr += add; - ret = *ptr; - - i = pthread_mutex_unlock (&sync_lock); - __go_assert (i == 0); - - return ret; -} - -#endif - -// Called to initialize a new m (including the bootstrap m). -void -runtime_minit(void) -{ - byte* stack; - size_t stacksize; - stack_t ss; - sigset_t sigs; - - // Initialize signal handling. - runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize); // OS X wants >=8K, Linux >=2K - ss.ss_sp = stack; - ss.ss_flags = 0; - ss.ss_size = stacksize; - if(sigaltstack(&ss, nil) < 0) - *(int *)0xf1 = 0xf1; - if (sigemptyset(&sigs) != 0) - runtime_throw("sigemptyset"); - sigprocmask(SIG_SETMASK, &sigs, nil); -} - -uintptr -runtime_memlimit(void) -{ - struct rlimit rl; - uintptr used; - - if(getrlimit(RLIMIT_AS, &rl) != 0) - return 0; - if(rl.rlim_cur >= 0x7fffffff) - return 0; - - // Estimate our VM footprint excluding the heap. - // Not an exact science: use size of binary plus - // some room for thread stacks. - used = (64<<20); - if(used >= rl.rlim_cur) - return 0; - - // If there's not at least 16 MB left, we're probably - // not going to be able to do much. Treat as no limit. - rl.rlim_cur -= used; - if(rl.rlim_cur < (16<<20)) - return 0; - - return rl.rlim_cur - used; -} diff --git a/gcc-4.8.1/libgo/runtime/time.goc b/gcc-4.8.1/libgo/runtime/time.goc deleted file mode 100644 index 9a5cbdfed..000000000 --- a/gcc-4.8.1/libgo/runtime/time.goc +++ /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. - -// Time-related runtime and pieces of package time. - -package time - -#include "runtime.h" -#include "defs.h" -#include "arch.h" -#include "malloc.h" -#include "race.h" - -static Timers timers; -static void addtimer(Timer*); -static bool deltimer(Timer*); - -// Package time APIs. -// Godoc uses the comments in package time, not these. - -// time.now is implemented in assembly. - -// Sleep puts the current goroutine to sleep for at least ns nanoseconds. -func Sleep(ns int64) { - runtime_tsleep(ns, "sleep"); -} - -// startTimer adds t to the timer heap. -func startTimer(t *Timer) { - if(raceenabled) - runtime_racerelease(t); - runtime_lock(&timers); - addtimer(t); - runtime_unlock(&timers); -} - -// stopTimer removes t from the timer heap if it is there. -// It returns true if t was removed, false if t wasn't even there. -func stopTimer(t *Timer) (stopped bool) { - stopped = deltimer(t); -} - -// C runtime. - -static void timerproc(void*); -static void siftup(int32); -static void siftdown(int32); - -// Ready the goroutine e.data. -static void -ready(int64 now, Eface e) -{ - USED(now); - - runtime_ready(e.__object); -} - -// Put the current goroutine to sleep for ns nanoseconds. -void -runtime_tsleep(int64 ns, const char *reason) -{ - G* g; - Timer t; - - g = runtime_g(); - - if(ns <= 0) - return; - - t.when = runtime_nanotime() + ns; - t.period = 0; - t.f = ready; - t.arg.__object = g; - runtime_lock(&timers); - addtimer(&t); - runtime_park(runtime_unlock, &timers, reason); -} - -// Add a timer to the heap and start or kick the timer proc -// if the new timer is earlier than any of the others. -static void -addtimer(Timer *t) -{ - int32 n; - Timer **nt; - - if(timers.len >= timers.cap) { - // Grow slice. - n = 16; - if(n <= timers.cap) - n = timers.cap*3 / 2; - nt = runtime_malloc(n*sizeof nt[0]); - runtime_memmove(nt, timers.t, timers.len*sizeof nt[0]); - runtime_free(timers.t); - timers.t = nt; - timers.cap = n; - } - t->i = timers.len++; - timers.t[t->i] = t; - siftup(t->i); - if(t->i == 0) { - // siftup moved to top: new earliest deadline. - if(timers.sleeping) { - timers.sleeping = false; - runtime_notewakeup(&timers.waitnote); - } - if(timers.rescheduling) { - timers.rescheduling = false; - runtime_ready(timers.timerproc); - } - } - if(timers.timerproc == nil) { - timers.timerproc = __go_go(timerproc, nil); - timers.timerproc->issystem = true; - } -} - -// Delete timer t from the heap. -// Do not need to update the timerproc: -// if it wakes up early, no big deal. -static bool -deltimer(Timer *t) -{ - int32 i; - - runtime_lock(&timers); - - // t may not be registered anymore and may have - // a bogus i (typically 0, if generated by Go). - // Verify it before proceeding. - i = t->i; - if(i < 0 || i >= timers.len || timers.t[i] != t) { - runtime_unlock(&timers); - return false; - } - - timers.len--; - if(i == timers.len) { - timers.t[i] = nil; - } else { - timers.t[i] = timers.t[timers.len]; - timers.t[timers.len] = nil; - timers.t[i]->i = i; - siftup(i); - siftdown(i); - } - runtime_unlock(&timers); - return true; -} - -// Timerproc runs the time-driven events. -// It sleeps until the next event in the timers heap. -// If addtimer inserts a new earlier event, addtimer -// wakes timerproc early. -static void -timerproc(void* dummy __attribute__ ((unused))) -{ - int64 delta, now; - Timer *t; - void (*f)(int64, Eface); - Eface arg; - - for(;;) { - runtime_lock(&timers); - now = runtime_nanotime(); - for(;;) { - if(timers.len == 0) { - delta = -1; - break; - } - t = timers.t[0]; - delta = t->when - now; - if(delta > 0) - break; - if(t->period > 0) { - // leave in heap but adjust next time to fire - t->when += t->period * (1 + -delta/t->period); - siftdown(0); - } else { - // remove from heap - timers.t[0] = timers.t[--timers.len]; - timers.t[0]->i = 0; - siftdown(0); - t->i = -1; // mark as removed - } - f = t->f; - arg = t->arg; - runtime_unlock(&timers); - if(raceenabled) - runtime_raceacquire(t); - f(now, arg); - runtime_lock(&timers); - } - if(delta < 0) { - // No timers left - put goroutine to sleep. - timers.rescheduling = true; - runtime_park(runtime_unlock, &timers, "timer goroutine (idle)"); - continue; - } - // At least one timer pending. Sleep until then. - timers.sleeping = true; - runtime_noteclear(&timers.waitnote); - runtime_unlock(&timers); - runtime_entersyscall(); - runtime_notetsleep(&timers.waitnote, delta); - runtime_exitsyscall(); - } -} - -// heap maintenance algorithms. - -static void -siftup(int32 i) -{ - int32 p; - Timer **t, *tmp; - - t = timers.t; - while(i > 0) { - p = (i-1)/2; // parent - if(t[i]->when >= t[p]->when) - break; - tmp = t[i]; - t[i] = t[p]; - t[p] = tmp; - t[i]->i = i; - t[p]->i = p; - i = p; - } -} - -static void -siftdown(int32 i) -{ - int32 c, len; - Timer **t, *tmp; - - t = timers.t; - len = timers.len; - for(;;) { - c = i*2 + 1; // left child - if(c >= len) { - break; - } - if(c+1 < len && t[c+1]->when < t[c]->when) - c++; - if(t[c]->when >= t[i]->when) - break; - tmp = t[i]; - t[i] = t[c]; - t[c] = tmp; - t[i]->i = i; - t[c]->i = c; - i = c; - } -} - -void -runtime_time_scan(void (*addroot)(Obj)) -{ - addroot((Obj){(byte*)&timers, sizeof timers, 0}); -} diff --git a/gcc-4.8.1/libgo/runtime/yield.c b/gcc-4.8.1/libgo/runtime/yield.c deleted file mode 100644 index 5c47719d4..000000000 --- a/gcc-4.8.1/libgo/runtime/yield.c +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2011 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 "config.h" - -#include <stddef.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sched.h> -#include <unistd.h> - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#include "runtime.h" - -/* Spin wait. */ - -void -runtime_procyield (uint32 cnt) -{ - volatile uint32 i; - - for (i = 0; i < cnt; ++i) - { -#if defined (__i386__) || defined (__x86_64__) - __builtin_ia32_pause (); -#endif - } -} - -/* Ask the OS to reschedule this thread. */ - -void -runtime_osyield (void) -{ - sched_yield (); -} - -/* Sleep for some number of microseconds. */ - -void -runtime_usleep (uint32 us) -{ - struct timeval tv; - - tv.tv_sec = us / 1000000; - tv.tv_usec = us % 1000000; - select (0, NULL, NULL, NULL, &tv); -} |