void lock(Lock *l) { if(ainc(&l->key) == 1) return; /* changed from 0 -> 1: we hold lock */ /* otherwise wait in kernel */ while(semacquire(&l->sem, 1) < 0){ /* interrupted; try again */ } }
static void syssemacquire(void) { u32int addr, block; long *addrt; addr = arg(0); block = arg(1); if(systrace) fprint(2, "semacquire(%#ux, %ud)\n", addr, block); addrt = vaddrnol(addr, 4); P->R[0] = noteerr(semacquire(addrt, block), 0); }
void semloop(void) { int i; i = 0; while(i < nloops){ if(semacquire(&x, 1)){ incr++; i++; semrelease(&x, 1); } else { sysfatal("semacquire failed"); } } }
long syssemacquire(ulong *arg) { int block; long *addr; Segment *s; validaddr(arg[0], sizeof(long), 1); evenaddr(arg[0]); addr = (long*)arg[0]; block = arg[1]; if((s = seg(up, (ulong)addr, 0)) == nil) error(Ebadarg); if(*addr < 0) error(Ebadarg); return semacquire(s, addr, block); }
// func RaceSemacquire(s *uint32) void runtime·RaceSemacquire(uint32 *s) { runtime·semacquire(s); }
void gc(int32 force) { int64 t0, t1; byte *p; Finalizer *fp; // The gc is turned off (via enablegc) until // the bootstrap has completed. // Also, malloc gets called in the guts // of a number of libraries that might be // holding locks. To avoid priority inversion // problems, don't bother trying to run gc // while holding a lock. The next mallocgc // without a lock will do the gc instead. if(!mstats.enablegc || m->locks > 0 || panicking) return; if(gcpercent == -2) { // first time through p = getenv("GOGC"); if(p == nil || p[0] == '\0') gcpercent = 100; else if(strcmp(p, (byte*)"off") == 0) gcpercent = -1; else gcpercent = atoi(p); } if(gcpercent < 0) return; semacquire(&gcsema); t0 = nanotime(); m->gcing = 1; stoptheworld(); if(mheap.Lock.key != 0) throw("mheap locked during gc"); if(force || mstats.heap_alloc >= mstats.next_gc) { mark(); sweep(); stealcache(); mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100; } m->gcing = 0; m->locks++; // disable gc during the mallocs in newproc fp = finq; if(fp != nil) { // kick off or wake up goroutine to run queued finalizers if(fing == nil) fing = newproc1((byte*)runfinq, nil, 0, 0); else if(fingwait) { fingwait = 0; ready(fing); } } m->locks--; t1 = nanotime(); mstats.numgc++; mstats.pause_ns += t1 - t0; if(mstats.debuggc) printf("pause %D\n", t1-t0); semrelease(&gcsema); starttheworld(); // give the queued finalizers, if any, a chance to run if(fp != nil) gosched(); }