diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-10-31 00:59:47 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-10-31 00:59:47 +0000 |
commit | af146490bb04205107cb23e301ec7a8ff927b5fc (patch) | |
tree | 13beeaed3698c61903fe93fb1ce70bd9b18d4e7f /libgo/runtime | |
parent | 725e1be3406315d9bcc8195d7eef0a7082b3c7cc (diff) | |
download | gcc-af146490bb04205107cb23e301ec7a8ff927b5fc.zip gcc-af146490bb04205107cb23e301ec7a8ff927b5fc.tar.gz gcc-af146490bb04205107cb23e301ec7a8ff927b5fc.tar.bz2 |
runtime: Remove now unnecessary pad field from ParFor.
It is not needed due to the removal of the ctx field.
Reviewed-on: https://go-review.googlesource.com/16525
From-SVN: r229616
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/env_posix.c | 11 | ||||
-rw-r--r-- | libgo/runtime/go-varargs.c | 13 | ||||
-rw-r--r-- | libgo/runtime/malloc.h | 2 | ||||
-rw-r--r-- | libgo/runtime/mgc0.c | 50 | ||||
-rw-r--r-- | libgo/runtime/parfor.c | 14 | ||||
-rw-r--r-- | libgo/runtime/proc.c | 65 | ||||
-rw-r--r-- | libgo/runtime/runtime.c | 43 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 12 | ||||
-rw-r--r-- | libgo/runtime/runtime1.goc | 19 | ||||
-rw-r--r-- | libgo/runtime/signal_unix.c | 23 | ||||
-rw-r--r-- | libgo/runtime/sigqueue.goc | 8 |
11 files changed, 209 insertions, 51 deletions
diff --git a/libgo/runtime/env_posix.c b/libgo/runtime/env_posix.c index ee3e451..b93edd6 100644 --- a/libgo/runtime/env_posix.c +++ b/libgo/runtime/env_posix.c @@ -11,7 +11,7 @@ extern Slice envs; -const byte* +String runtime_getenv(const char *s) { int32 i, j; @@ -19,6 +19,7 @@ runtime_getenv(const char *s) const byte *v, *bs; String* envv; int32 envc; + String ret; bs = (const byte*)s; len = runtime_findnull(bs); @@ -33,8 +34,12 @@ runtime_getenv(const char *s) goto nomatch; if(v[len] != '=') goto nomatch; - return v+len+1; + ret.str = v+len+1; + ret.len = envv[i].len-len-1; + return ret; nomatch:; } - return nil; + ret.str = nil; + ret.len = 0; + return ret; } diff --git a/libgo/runtime/go-varargs.c b/libgo/runtime/go-varargs.c index 7a2006f..534c0db 100644 --- a/libgo/runtime/go-varargs.c +++ b/libgo/runtime/go-varargs.c @@ -10,6 +10,7 @@ #include <stdint.h> #include <sys/types.h> #include <fcntl.h> +#include <sys/ioctl.h> /* The syscall package calls C functions. The Go compiler can not represent a C varargs functions. On some systems it's important @@ -56,6 +57,18 @@ __go_fcntl_uintptr (uintptr_t fd, uintptr_t cmd, uintptr_t arg) return ret; } +int +__go_ioctl (int d, int request, int arg) +{ + return ioctl (d, request, arg); +} + +int +__go_ioctl_ptr (int d, int request, void *arg) +{ + return ioctl (d, request, arg); +} + #ifdef HAVE_OPEN64 int diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h index 86b9fcc..065f74a 100644 --- a/libgo/runtime/malloc.h +++ b/libgo/runtime/malloc.h @@ -263,7 +263,9 @@ struct MStats uint64 last_gc; // last GC (in absolute time) uint64 pause_total_ns; uint64 pause_ns[256]; + uint64 pause_end[256]; uint32 numgc; + float64 gc_cpu_fraction; bool enablegc; bool debuggc; diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c index 9d8c025..d7d0b27 100644 --- a/libgo/runtime/mgc0.c +++ b/libgo/runtime/mgc0.c @@ -1368,6 +1368,8 @@ markroot(ParFor *desc, uint32 i) scanblock(wbuf, false); } +static const FuncVal markroot_funcval = { (void *) markroot }; + // Get an empty work buffer off the work.empty list, // allocating new buffers as needed. static Workbuf* @@ -2102,14 +2104,16 @@ static void mgc(G *gp); static int32 readgogc(void) { + String s; const byte *p; - p = runtime_getenv("GOGC"); - if(p == nil || p[0] == '\0') + s = runtime_getenv("GOGC"); + if(s.len == 0) return 100; - if(runtime_strcmp((const char *)p, "off") == 0) + p = s.str; + if(s.len == 3 && runtime_strcmp((const char *)p, "off") == 0) return -1; - return runtime_atoi(p); + return runtime_atoi(p, s.len); } // force = 1 - do GC regardless of current heap usage @@ -2252,7 +2256,7 @@ gc(struct gc_args *args) work.nwait = 0; work.ndone = 0; work.nproc = runtime_gcprocs(); - runtime_parforsetup(work.markfor, work.nproc, RootCount + runtime_allglen, nil, false, markroot); + runtime_parforsetup(work.markfor, work.nproc, RootCount + runtime_allglen, false, &markroot_funcval); if(work.nproc > 1) { runtime_noteclear(&work.alldone); runtime_helpgc(work.nproc); @@ -2285,6 +2289,7 @@ gc(struct gc_args *args) t4 = runtime_nanotime(); mstats.last_gc = runtime_unixnanotime(); // must be Unix time to make sense to user mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0; + mstats.pause_end[mstats.numgc%nelem(mstats.pause_end)] = mstats.last_gc; mstats.pause_total_ns += t4 - t0; mstats.numgc++; if(mstats.debuggc) @@ -2749,3 +2754,38 @@ runtime_MHeap_MapBits(MHeap *h) runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped, h->arena_reserved, &mstats.gc_sys); h->bitmap_mapped = n; } + +// typedmemmove copies a value of type t to dst from src. + +extern void typedmemmove(const Type* td, void *dst, const void *src) + __asm__ (GOSYM_PREFIX "reflect.typedmemmove"); + +void +typedmemmove(const Type* td, void *dst, const void *src) +{ + runtime_memmove(dst, src, td->__size); +} + +// typedslicecopy copies a slice of elemType values from src to dst, +// returning the number of elements copied. + +extern intgo typedslicecopy(const Type* elem, Slice dst, Slice src) + __asm__ (GOSYM_PREFIX "reflect.typedslicecopy"); + +intgo +typedslicecopy(const Type* elem, Slice dst, Slice src) +{ + intgo n; + void *dstp; + void *srcp; + + n = dst.__count; + if (n > src.__count) + n = src.__count; + if (n == 0) + return 0; + dstp = dst.__values; + srcp = src.__values; + memmove(dstp, srcp, (uintptr_t)n * elem->__size); + return n; +} diff --git a/libgo/runtime/parfor.c b/libgo/runtime/parfor.c index 386faea..ede921b 100644 --- a/libgo/runtime/parfor.c +++ b/libgo/runtime/parfor.c @@ -34,7 +34,7 @@ runtime_parforalloc(uint32 nthrmax) } void -runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32)) +runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, bool wait, const FuncVal *body) { uint32 i, begin, end; uint64 *pos; @@ -49,7 +49,6 @@ runtime_parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, v desc->nthr = nthr; desc->thrseq = 0; desc->cnt = n; - desc->ctx = ctx; desc->wait = wait; desc->nsteal = 0; desc->nstealcnt = 0; @@ -72,7 +71,8 @@ runtime_parfordo(ParFor *desc) ParForThread *me; uint32 tid, begin, end, begin2, try, victim, i; uint64 *mypos, *victimpos, pos, newpos; - void (*body)(ParFor*, uint32); + const FuncVal *body; + void (*bodyfn)(ParFor*, uint32); bool idle; // Obtain 0-based thread index. @@ -82,14 +82,16 @@ runtime_parfordo(ParFor *desc) runtime_throw("parfor: invalid tid"); } + body = desc->body; + bodyfn = (void (*)(ParFor*, uint32))(void*)body->fn; + // If single-threaded, just execute the for serially. if(desc->nthr==1) { for(i=0; i<desc->cnt; i++) - desc->body(desc, i); + __builtin_call_with_static_chain (bodyfn(desc, i), body); return; } - body = desc->body; me = &desc->thr[tid]; mypos = &me->pos; for(;;) { @@ -100,7 +102,7 @@ runtime_parfordo(ParFor *desc) begin = (uint32)pos-1; end = (uint32)(pos>>32); if(begin < end) { - body(desc, begin); + __builtin_call_with_static_chain(bodyfn(desc, begin), body); continue; } break; diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 8f82f5b..b5741c5 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -443,6 +443,7 @@ void runtime_schedinit(void) { int32 n, procs; + String s; const byte *p; Eface i; @@ -477,8 +478,9 @@ runtime_schedinit(void) runtime_sched.lastpoll = runtime_nanotime(); procs = 1; - p = runtime_getenv("GOMAXPROCS"); - if(p != nil && (n = runtime_atoi(p)) > 0) { + s = runtime_getenv("GOMAXPROCS"); + p = s.str; + if(p != nil && (n = runtime_atoi(p, s.len)) > 0) { if(n > MaxGomaxprocs) n = MaxGomaxprocs; procs = n; @@ -2268,19 +2270,19 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize) // are available sequentially after &fn; they would not be // copied if a stack split occurred. It's OK for this to call // functions that split the stack. -void runtime_testing_entersyscall(void) +void runtime_testing_entersyscall(int32) __asm__ (GOSYM_PREFIX "runtime.entersyscall"); void -runtime_testing_entersyscall() +runtime_testing_entersyscall(int32 dummy __attribute__ ((unused))) { runtime_entersyscall(); } -void runtime_testing_exitsyscall(void) +void runtime_testing_exitsyscall(int32) __asm__ (GOSYM_PREFIX "runtime.exitsyscall"); void -runtime_testing_exitsyscall() +runtime_testing_exitsyscall(int32 dummy __attribute__ ((unused))) { runtime_exitsyscall(); } @@ -3429,3 +3431,54 @@ runtime_gcwaiting(void) { return runtime_sched.gcwaiting; } + +// os_beforeExit is called from os.Exit(0). +//go:linkname os_beforeExit os.runtime_beforeExit + +extern void os_beforeExit() __asm__ (GOSYM_PREFIX "os.runtime_beforeExit"); + +void +os_beforeExit() +{ +} + +// Active spinning for sync.Mutex. +//go:linkname sync_runtime_canSpin sync.runtime_canSpin + +enum +{ + ACTIVE_SPIN = 4, + ACTIVE_SPIN_CNT = 30, +}; + +extern _Bool sync_runtime_canSpin(intgo i) + __asm__ (GOSYM_PREFIX "sync.runtime_canSpin"); + +_Bool +sync_runtime_canSpin(intgo i) +{ + P *p; + + // sync.Mutex is cooperative, so we are conservative with spinning. + // Spin only few times and only if running on a multicore machine and + // GOMAXPROCS>1 and there is at least one other running P and local runq is empty. + // As opposed to runtime mutex we don't do passive spinning here, + // because there can be work on global runq on on other Ps. + if (i >= ACTIVE_SPIN || runtime_ncpu <= 1 || runtime_gomaxprocs <= (int32)(runtime_sched.npidle+runtime_sched.nmspinning)+1) { + return false; + } + p = m->p; + return p != nil && p->runqhead == p->runqtail; +} + +//go:linkname sync_runtime_doSpin sync.runtime_doSpin +//go:nosplit + +extern void sync_runtime_doSpin(void) + __asm__ (GOSYM_PREFIX "sync.runtime_doSpin"); + +void +sync_runtime_doSpin() +{ + runtime_procyield(ACTIVE_SPIN_CNT); +} diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index e332035..be7ccbd 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -35,6 +35,7 @@ extern volatile intgo runtime_MemProfileRate int32 runtime_gotraceback(bool *crash) { + String s; const byte *p; uint32 x; @@ -44,15 +45,14 @@ runtime_gotraceback(bool *crash) return runtime_m()->traceback; x = runtime_atomicload(&traceback_cache); if(x == ~(uint32)0) { - p = runtime_getenv("GOTRACEBACK"); - if(p == nil) - p = (const byte*)""; - if(p[0] == '\0') + s = runtime_getenv("GOTRACEBACK"); + p = s.str; + if(s.len == 0) x = 1<<1; - else if(runtime_strcmp((const char *)p, "crash") == 0) + else if(s.len == 5 && runtime_strcmp((const char *)p, "crash") == 0) x = (2<<1) | 1; else - x = runtime_atoi(p)<<1; + x = runtime_atoi(p, s.len)<<1; runtime_atomicstore(&traceback_cache, x); } if(crash != nil) @@ -136,13 +136,15 @@ os_runtime_args() } int32 -runtime_atoi(const byte *p) +runtime_atoi(const byte *p, intgo len) { int32 n; n = 0; - while('0' <= *p && *p <= '9') + while(len > 0 && '0' <= *p && *p <= '9') { n = n*10 + *p++ - '0'; + len--; + } return n; } @@ -339,7 +341,9 @@ static struct { void runtime_parsedebugvars(void) { - const byte *p; + String s; + const byte *p, *pn; + intgo len; intgo i, n; bool tmp; @@ -352,24 +356,27 @@ runtime_parsedebugvars(void) traceback_cache = ~(uint32)0; runtime_gotraceback(&tmp); - p = runtime_getenv("GODEBUG"); - if(p == nil) + s = runtime_getenv("GODEBUG"); + if(s.len == 0) return; + p = s.str; + len = s.len; for(;;) { for(i=0; i<(intgo)nelem(dbgvar); i++) { n = runtime_findnull((const byte*)dbgvar[i].name); - if(runtime_mcmp(p, "memprofilerate", n) == 0 && p[n] == '=') + if(len > n && runtime_mcmp(p, "memprofilerate", n) == 0 && p[n] == '=') // Set the MemProfileRate directly since it // is an int, not int32, and should only lbe // set here if specified by GODEBUG - runtime_MemProfileRate = runtime_atoi(p+n+1); - else if(runtime_mcmp(p, dbgvar[i].name, n) == 0 && p[n] == '=') - *dbgvar[i].value = runtime_atoi(p+n+1); + runtime_MemProfileRate = runtime_atoi(p+n+1, len-(n+1)); + else if(len > n && runtime_mcmp(p, dbgvar[i].name, n) == 0 && p[n] == '=') + *dbgvar[i].value = runtime_atoi(p+n+1, len-(n+1)); } - p = (const byte *)runtime_strstr((const char *)p, ","); - if(p == nil) + pn = (const byte *)runtime_strstr((const char *)p, ","); + if(pn == nil || pn - p >= len) break; - p++; + len -= (pn - p) - 1; + p = pn + 1; } } diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index b926423..cbf1fe1 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -421,17 +421,15 @@ struct LFNode // Parallel for descriptor. struct ParFor { - void (*body)(ParFor*, uint32); // executed for each element + const FuncVal *body; // 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 - uint32 pad; // to align ParForThread.pos for 64-bit atomic operations // stats uint64 nsteal; uint64 nstealcnt; @@ -544,6 +542,7 @@ void runtime_schedinit(void); void runtime_initsig(void); void runtime_sigenable(uint32 sig); void runtime_sigdisable(uint32 sig); +void runtime_sigignore(uint32 sig); int32 runtime_gotraceback(bool *crash); void runtime_goroutineheader(G*); void runtime_printtrace(Location*, int32, bool); @@ -552,8 +551,8 @@ void runtime_printtrace(Location*, int32, bool); #define runtime_write(d, v, n) write((d), (v), (n)) #define runtime_close(d) close(d) void runtime_ready(G*); -const byte* runtime_getenv(const char*); -int32 runtime_atoi(const byte*); +String runtime_getenv(const char*); +int32 runtime_atoi(const byte*, intgo); void* runtime_mstart(void*); G* runtime_malg(int32, byte**, size_t*); void runtime_mpreinit(M*); @@ -713,12 +712,11 @@ 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_parforsetup(ParFor *desc, uint32 nthr, uint32 n, bool wait, const FuncVal *body); void runtime_parfordo(ParFor *desc); void runtime_parforiters(ParFor*, uintptr, uintptr*, uintptr*); diff --git a/libgo/runtime/runtime1.goc b/libgo/runtime/runtime1.goc index 6d8f09a..cd9d301 100644 --- a/libgo/runtime/runtime1.goc +++ b/libgo/runtime/runtime1.goc @@ -27,8 +27,8 @@ func newParFor(nthrmax uint32) (desc *ParFor) { desc = runtime_parforalloc(nthrmax); } -func parForSetup(desc *ParFor, nthr uint32, n uint32, ctx *byte, wait bool, body *byte) { - runtime_parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body); +func parForSetup(desc *ParFor, nthr uint32, n uint32, wait bool, body *byte) { + runtime_parforsetup(desc, nthr, n, wait, (const FuncVal*) body); } func parForDo(desc *ParFor) { @@ -52,10 +52,7 @@ func NumGoroutine() (ret int) { } func getgoroot() (out String) { - const byte *p; - - p = runtime_getenv("GOROOT"); - out = runtime_gostringnocopy(p); + out = runtime_getenv("GOROOT"); } func runtime_pprof.runtime_cyclesPerSecond() (res int64) { @@ -87,3 +84,13 @@ func sync_atomic.runtime_procPin() (p int) { func sync_atomic.runtime_procUnpin() { runtime_m()->locks--; } + +extern Slice envs; + +func envs() (s Slice) { + s = envs; +} + +func setenvs(e Slice) { + envs = e; +} diff --git a/libgo/runtime/signal_unix.c b/libgo/runtime/signal_unix.c index 66638de..43be0d8 100644 --- a/libgo/runtime/signal_unix.c +++ b/libgo/runtime/signal_unix.c @@ -93,6 +93,29 @@ runtime_sigdisable(uint32 sig) } void +runtime_sigignore(uint32 sig) +{ + int32 i; + SigTab *t; + + t = nil; + for(i = 0; runtime_sigtab[i].sig != -1; i++) { + if(runtime_sigtab[i].sig == (int32)sig) { + t = &runtime_sigtab[i]; + break; + } + } + + if(t == nil) + return; + + if((t->flags & SigNotify) != 0) { + t->flags &= ~SigHandling; + runtime_setsig(i, GO_SIG_IGN, true); + } +} + +void runtime_resetcpuprofiler(int32 hz) { struct itimerval it; diff --git a/libgo/runtime/sigqueue.goc b/libgo/runtime/sigqueue.goc index 6769b23..fba1c71 100644 --- a/libgo/runtime/sigqueue.goc +++ b/libgo/runtime/sigqueue.goc @@ -156,6 +156,14 @@ func signal_disable(s uint32) { runtime_sigdisable(s); } +// Must only be called from a single goroutine at a time. +func signal_ignore(s uint32) { + if (s >= nelem(sig.wanted)*32) + return; + sig.wanted[s/32] &= ~(1U<<(s&31)); + runtime_sigignore(s); +} + // This runs on a foreign stack, without an m or a g. No stack split. void runtime_badsignal(int sig) |