runtime·FixAlloc_Alloc(FixAlloc *f) { void *v; if(f->size == 0) { runtime·printf("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n"); runtime·throw("runtime: internal error"); } if(f->list) { v = f->list; f->list = *(void**)f->list; f->inuse += f->size; return v; } if(f->nchunk < f->size) { f->chunk = runtime·persistentalloc(FixAllocChunk, 0, f->stat); 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; }
static PollDesc* allocPollDesc ( void ) { PollDesc *pd; uint32 i , n; #line 375 "/tmp/makerelease886106415/go/src/pkg/runtime/netpoll.goc" runtime·lock ( &pollcache ) ; if ( pollcache.first == nil ) { n = PageSize/sizeof ( *pd ) ; if ( n == 0 ) n = 1; #line 382 "/tmp/makerelease886106415/go/src/pkg/runtime/netpoll.goc" pd = runtime·persistentalloc ( n*sizeof ( *pd ) , 0 , &mstats.other_sys ) ; for ( i = 0; i < n; i++ ) { pd[i].link = pollcache.first; pollcache.first = &pd[i]; } } pd = pollcache.first; pollcache.first = pd->link; runtime·unlock ( &pollcache ) ; return pd; }
static Itab* itab ( InterfaceType *inter , Type *type , int32 canfail ) { int32 locked; int32 ni; Method *t , *et; IMethod *i , *ei; uint32 h; String *iname , *ipkgPath; Itab *m; UncommonType *x; Type *itype; Eface err; #line 38 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" if ( inter->mhdr.len == 0 ) runtime·throw ( "internal error - misuse of itab" ) ; #line 41 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" locked = 0; #line 44 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" x = type->x; if ( x == nil ) { if ( canfail ) return nil; iname = inter->m[0].name; goto throw; } #line 53 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" h = inter->hash; h += 17 * type->hash; #line 56 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" h %= nelem ( hash ) ; #line 60 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" for ( locked=0; locked<2; locked++ ) { if ( locked ) runtime·lock ( &ifacelock ) ; for ( m=runtime·atomicloadp ( &hash[h] ) ; m!=nil; m=m->link ) { if ( m->inter == inter && m->type == type ) { if ( m->bad ) { m = nil; if ( !canfail ) { #line 75 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" goto search; } } if ( locked ) runtime·unlock ( &ifacelock ) ; return m; } } } #line 85 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" ni = inter->mhdr.len; m = runtime·persistentalloc ( sizeof ( *m ) + ni*sizeof m->fun[0] , 0 , &mstats.other_sys ) ; m->inter = inter; m->type = type; #line 90 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" search: #line 95 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" i = inter->m; ei = i + inter->mhdr.len; t = x->m; et = t + x->mhdr.len; for ( ; i < ei; i++ ) { itype = i->type; iname = i->name; ipkgPath = i->pkgPath; for ( ;; t++ ) { if ( t >= et ) { if ( !canfail ) { throw: #line 108 "/home/pi/go_build/hg/go/src/pkg/runtime/iface.goc" runtime·newTypeAssertionError ( nil , type->string , inter->string , iname , &err ) ; if ( locked ) runtime·unlock ( &ifacelock ) ; runtime·panic ( err ) ; return nil; } m->bad = 1; goto out; } if ( t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath ) break; } if ( m ) m->fun[i - inter->m] = t->ifn; }
static Itab* itab(InterfaceType *inter, Type *type, int32 canfail) { int32 locked; int32 ni; Method *t, *et; IMethod *i, *ei; uint32 h; String *iname, *ipkgPath; Itab *m; UncommonType *x; Type *itype; Eface err; if(inter->mhdr.len == 0) runtime·throw("internal error - misuse of itab"); locked = 0; // easy case x = type->x; if(x == nil) { if(canfail) return nil; iname = inter->m[0].name; goto throw; } // compiler has provided some good hash codes for us. h = inter->hash; h += 17 * type->hash; // TODO(rsc): h += 23 * x->mhash ? h %= nelem(hash); // look twice - once without lock, once with. // common case will be no lock contention. for(locked=0; locked<2; locked++) { if(locked) runtime·lock(&ifacelock); for(m=runtime·atomicloadp(&hash[h]); m!=nil; m=m->link) { if(m->inter == inter && m->type == type) { if(m->bad) { m = nil; if(!canfail) { // this can only happen if the conversion // was already done once using the , ok form // and we have a cached negative result. // the cached result doesn't record which // interface function was missing, so jump // down to the interface check, which will // do more work but give a better error. goto search; } } if(locked) runtime·unlock(&ifacelock); return m; } } } ni = inter->mhdr.len; m = runtime·persistentalloc(sizeof(*m) + ni*sizeof m->fun[0], 0, &mstats.other_sys); m->inter = inter; m->type = type; search: // both inter and type have method sorted by name, // and interface names are unique, // so can iterate over both in lock step; // the loop is O(ni+nt) not O(ni*nt). i = inter->m; ei = i + inter->mhdr.len; t = x->m; et = t + x->mhdr.len; for(; i < ei; i++) { itype = i->type; iname = i->name; ipkgPath = i->pkgPath; for(;; t++) { if(t >= et) { if(!canfail) { throw: // didn't find method runtime·newTypeAssertionError( nil, type->string, inter->string, iname, &err); if(locked) runtime·unlock(&ifacelock); runtime·panic(err); return nil; // not reached } m->bad = 1; goto out; } if(t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath) break; } if(m) m->fun[i - inter->m] = t->ifn; }