aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2015-10-31 00:59:47 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2015-10-31 00:59:47 +0000
commitaf146490bb04205107cb23e301ec7a8ff927b5fc (patch)
tree13beeaed3698c61903fe93fb1ce70bd9b18d4e7f /libgo/runtime
parent725e1be3406315d9bcc8195d7eef0a7082b3c7cc (diff)
downloadgcc-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.c11
-rw-r--r--libgo/runtime/go-varargs.c13
-rw-r--r--libgo/runtime/malloc.h2
-rw-r--r--libgo/runtime/mgc0.c50
-rw-r--r--libgo/runtime/parfor.c14
-rw-r--r--libgo/runtime/proc.c65
-rw-r--r--libgo/runtime/runtime.c43
-rw-r--r--libgo/runtime/runtime.h12
-rw-r--r--libgo/runtime/runtime1.goc19
-rw-r--r--libgo/runtime/signal_unix.c23
-rw-r--r--libgo/runtime/sigqueue.goc8
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)