aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/libgo/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/libgo/runtime')
-rw-r--r--gcc-4.8/libgo/runtime/go-callers.c9
-rw-r--r--gcc-4.8/libgo/runtime/go-cdiv.c46
-rw-r--r--gcc-4.8/libgo/runtime/go-defer.c1
-rw-r--r--gcc-4.8/libgo/runtime/go-defer.h6
-rw-r--r--gcc-4.8/libgo/runtime/go-int-array-to-string.c4
-rw-r--r--gcc-4.8/libgo/runtime/go-make-slice.c5
-rw-r--r--gcc-4.8/libgo/runtime/go-nosys.c57
-rw-r--r--gcc-4.8/libgo/runtime/go-recover.c77
-rw-r--r--gcc-4.8/libgo/runtime/go-reflect-call.c5
-rw-r--r--gcc-4.8/libgo/runtime/go-signal.c9
-rw-r--r--gcc-4.8/libgo/runtime/malloc.goc1
-rw-r--r--gcc-4.8/libgo/runtime/mgc0.c6
-rw-r--r--gcc-4.8/libgo/runtime/mheap.c6
-rw-r--r--gcc-4.8/libgo/runtime/proc.c32
-rw-r--r--gcc-4.8/libgo/runtime/runtime.h3
15 files changed, 243 insertions, 24 deletions
diff --git a/gcc-4.8/libgo/runtime/go-callers.c b/gcc-4.8/libgo/runtime/go-callers.c
index 291dfd0d6..ae411d9c8 100644
--- a/gcc-4.8/libgo/runtime/go-callers.c
+++ b/gcc-4.8/libgo/runtime/go-callers.c
@@ -11,6 +11,13 @@
#include "runtime.h"
#include "array.h"
+/* This is set to non-zero when calling backtrace_full. This is used
+ to avoid getting hanging on a recursive lock in dl_iterate_phdr on
+ older versions of glibc when a SIGPROF signal arrives while
+ collecting a backtrace. */
+
+uint32 runtime_in_callers;
+
/* Argument passed to callback function. */
struct callers_data
@@ -111,8 +118,10 @@ runtime_callers (int32 skip, Location *locbuf, int32 m)
data.skip = skip + 1;
data.index = 0;
data.max = m;
+ runtime_xadd (&runtime_in_callers, 1);
backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
&data);
+ runtime_xadd (&runtime_in_callers, -1);
return data.index;
}
diff --git a/gcc-4.8/libgo/runtime/go-cdiv.c b/gcc-4.8/libgo/runtime/go-cdiv.c
new file mode 100644
index 000000000..0a81e458c
--- /dev/null
+++ b/gcc-4.8/libgo/runtime/go-cdiv.c
@@ -0,0 +1,46 @@
+/* go-cdiv.c -- complex division routines
+
+ Copyright 2013 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. */
+
+/* Calls to these functions are generated by the Go frontend for
+ division of complex64 or complex128. We use these because Go's
+ complex division expects slightly different results from the GCC
+ default. When dividing NaN+1.0i / 0+0i, Go expects NaN+NaNi but
+ GCC generates NaN+Infi. NaN+Infi seems wrong seems the rules of
+ C99 Annex G specify that if either side of a complex number is Inf,
+ the the whole number is Inf, but an operation involving NaN ought
+ to result in NaN, not Inf. */
+
+__complex float
+__go_complex64_div (__complex float a, __complex float b)
+{
+ if (__builtin_expect (b == 0+0i, 0))
+ {
+ if (!__builtin_isinff (__real__ a)
+ && !__builtin_isinff (__imag__ a)
+ && (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a)))
+ {
+ /* Pass "1" to nanf to match math/bits.go. */
+ return __builtin_nanf("1") + __builtin_nanf("1")*1i;
+ }
+ }
+ return a / b;
+}
+
+__complex double
+__go_complex128_div (__complex double a, __complex double b)
+{
+ if (__builtin_expect (b == 0+0i, 0))
+ {
+ if (!__builtin_isinf (__real__ a)
+ && !__builtin_isinf (__imag__ a)
+ && (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a)))
+ {
+ /* Pass "1" to nan to match math/bits.go. */
+ return __builtin_nan("1") + __builtin_nan("1")*1i;
+ }
+ }
+ return a / b;
+}
diff --git a/gcc-4.8/libgo/runtime/go-defer.c b/gcc-4.8/libgo/runtime/go-defer.c
index 3955e0f5c..fed8db385 100644
--- a/gcc-4.8/libgo/runtime/go-defer.c
+++ b/gcc-4.8/libgo/runtime/go-defer.c
@@ -27,6 +27,7 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
n->__pfn = pfn;
n->__arg = arg;
n->__retaddr = NULL;
+ n->__makefunc_can_recover = 0;
g->defer = n;
}
diff --git a/gcc-4.8/libgo/runtime/go-defer.h b/gcc-4.8/libgo/runtime/go-defer.h
index 0b20e8f6e..3298ce950 100644
--- a/gcc-4.8/libgo/runtime/go-defer.h
+++ b/gcc-4.8/libgo/runtime/go-defer.h
@@ -34,4 +34,10 @@ struct __go_defer_stack
set by __go_set_defer_retaddr which is called by the thunks
created by defer statements. */
const void *__retaddr;
+
+ /* Set to true if a function created by reflect.MakeFunc is
+ permitted to recover. The return address of such a function
+ function will be somewhere in libffi, so __retaddr is not
+ useful. */
+ _Bool __makefunc_can_recover;
};
diff --git a/gcc-4.8/libgo/runtime/go-int-array-to-string.c b/gcc-4.8/libgo/runtime/go-int-array-to-string.c
index 6cae2fd8c..e3c008a0b 100644
--- a/gcc-4.8/libgo/runtime/go-int-array-to-string.c
+++ b/gcc-4.8/libgo/runtime/go-int-array-to-string.c
@@ -30,6 +30,8 @@ __go_int_array_to_string (const void* p, intgo len)
if (v < 0 || v > 0x10ffff)
v = 0xfffd;
+ else if (0xd800 <= v && v <= 0xdfff)
+ v = 0xfffd;
if (v <= 0x7f)
slen += 1;
@@ -56,6 +58,8 @@ __go_int_array_to_string (const void* p, intgo len)
character. */
if (v < 0 || v > 0x10ffff)
v = 0xfffd;
+ else if (0xd800 <= v && v <= 0xdfff)
+ v = 0xfffd;
if (v <= 0x7f)
*s++ = v;
diff --git a/gcc-4.8/libgo/runtime/go-make-slice.c b/gcc-4.8/libgo/runtime/go-make-slice.c
index 591ab37e0..f08cb012d 100644
--- a/gcc-4.8/libgo/runtime/go-make-slice.c
+++ b/gcc-4.8/libgo/runtime/go-make-slice.c
@@ -34,7 +34,10 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
std = (const struct __go_slice_type *) td;
ilen = (intgo) len;
- if (ilen < 0 || (uintptr_t) ilen != len)
+ if (ilen < 0
+ || (uintptr_t) ilen != len
+ || (std->__element_type->__size > 0
+ && len > MaxMem / std->__element_type->__size))
runtime_panicstring ("makeslice: len out of range");
icap = (intgo) cap;
diff --git a/gcc-4.8/libgo/runtime/go-nosys.c b/gcc-4.8/libgo/runtime/go-nosys.c
index 3ab5ea235..0a94de052 100644
--- a/gcc-4.8/libgo/runtime/go-nosys.c
+++ b/gcc-4.8/libgo/runtime/go-nosys.c
@@ -43,6 +43,17 @@ accept4 (int sockfd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_DUP3
+int
+dup3 (int oldfd __attribute__ ((unused)),
+ int newfd __attribute__ ((unused)),
+ int flags __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_EPOLL_CREATE1
int
epoll_create1 (int flags __attribute__ ((unused)))
@@ -112,6 +123,18 @@ futimesat (int dirfd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_GETXATTR
+ssize_t
+getxattr (const char *path __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ void *value __attribute__ ((unused)),
+ size_t size __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_INOTIFY_ADD_WATCH
int
inotify_add_watch (int fd __attribute__ ((unused)),
@@ -151,6 +174,17 @@ inotify_rm_watch (int fd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_LISTXATTR
+ssize_t
+listxattr (const char *path __attribute__ ((unused)),
+ char *list __attribute__ ((unused)),
+ size_t size __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_MKDIRAT
int
mkdirat (int dirfd __attribute__ ((unused)),
@@ -196,6 +230,16 @@ pipe2 (int pipefd[2] __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_REMOVEXATTR
+int
+removexattr (const char *path __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_RENAMEAT
int
renameat (int olddirfd __attribute__ ((unused)),
@@ -208,6 +252,19 @@ renameat (int olddirfd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_SETXATTR
+int
+setxattr (const char *path __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ const void *value __attribute__ ((unused)),
+ size_t size __attribute__ ((unused)),
+ int flags __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_SPLICE
int
splice (int fd __attribute__ ((unused)),
diff --git a/gcc-4.8/libgo/runtime/go-recover.c b/gcc-4.8/libgo/runtime/go-recover.c
index d6403e00d..ceb9b5725 100644
--- a/gcc-4.8/libgo/runtime/go-recover.c
+++ b/gcc-4.8/libgo/runtime/go-recover.c
@@ -16,12 +16,14 @@
__go_can_recover--this is, the thunk. */
_Bool
-__go_can_recover (const void* retaddr)
+__go_can_recover (const void *retaddr)
{
G *g;
struct __go_defer_stack *d;
const char* ret;
const char* dret;
+ Location loc;
+ const byte *name;
g = runtime_g ();
@@ -52,7 +54,78 @@ __go_can_recover (const void* retaddr)
#endif
dret = (const char *) d->__retaddr;
- return ret <= dret && ret + 16 >= dret;
+ if (ret <= dret && ret + 16 >= dret)
+ return 1;
+
+ /* If the function calling recover was created by reflect.MakeFunc,
+ then RETADDR will be somewhere in libffi. Our caller is
+ permitted to recover if it was called from libffi. */
+ if (!d->__makefunc_can_recover)
+ return 0;
+
+ if (runtime_callers (2, &loc, 1) < 1)
+ return 0;
+
+ /* If we have no function name, then we weren't called by Go code.
+ Guess that we were called by libffi. */
+ if (loc.function.len == 0)
+ return 1;
+
+ if (loc.function.len < 4)
+ return 0;
+ name = loc.function.str;
+ if (*name == '_')
+ {
+ if (loc.function.len < 5)
+ return 0;
+ ++name;
+ }
+
+ if (name[0] == 'f' && name[1] == 'f' && name[2] == 'i' && name[3] == '_')
+ return 1;
+
+ /* We may also be called by reflect.makeFuncImpl.call, for a
+ function created by reflect.MakeFunc. */
+ if (__builtin_strstr ((const char *) name, "makeFuncImpl") != NULL)
+ return 1;
+
+ return 0;
+}
+
+/* This function is called when code is about to enter a function
+ created by reflect.MakeFunc. It is called by the function stub
+ used by MakeFunc. If the stub is permitted to call recover, then a
+ real MakeFunc function is permitted to call recover. */
+
+void
+__go_makefunc_can_recover (const void *retaddr)
+{
+ struct __go_defer_stack *d;
+
+ d = runtime_g ()->defer;
+ if (d != NULL
+ && !d->__makefunc_can_recover
+ && __go_can_recover (retaddr))
+ d->__makefunc_can_recover = 1;
+}
+
+/* This function is called when code is about to exit a function
+ created by reflect.MakeFunc. It is called by the function stub
+ used by MakeFunc. It clears the __makefunc_can_recover field.
+ It's OK to always clear this field, because __go_can_recover will
+ only be called by a stub created for a function that calls recover.
+ That stub will not call a function created by reflect.MakeFunc, so
+ by the time we get here any caller higher up on the call stack no
+ longer needs the information. */
+
+void
+__go_makefunc_returning (void)
+{
+ struct __go_defer_stack *d;
+
+ d = runtime_g ()->defer;
+ if (d != NULL)
+ d->__makefunc_can_recover = 0;
}
/* This is only called when it is valid for the caller to recover the
diff --git a/gcc-4.8/libgo/runtime/go-reflect-call.c b/gcc-4.8/libgo/runtime/go-reflect-call.c
index 5cf370798..12bd0d7c2 100644
--- a/gcc-4.8/libgo/runtime/go-reflect-call.c
+++ b/gcc-4.8/libgo/runtime/go-reflect-call.c
@@ -98,9 +98,12 @@ go_struct_to_ffi (const struct __go_struct_type *descriptor)
const struct __go_struct_field *fields;
int i;
+ field_count = descriptor->__fields.__count;
+ if (field_count == 0) {
+ return &ffi_type_void;
+ }
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 *));
diff --git a/gcc-4.8/libgo/runtime/go-signal.c b/gcc-4.8/libgo/runtime/go-signal.c
index 9771b71cf..41a807943 100644
--- a/gcc-4.8/libgo/runtime/go-signal.c
+++ b/gcc-4.8/libgo/runtime/go-signal.c
@@ -234,7 +234,7 @@ runtime_sighandler (int sig, Siginfo *info,
G *g;
g = runtime_g ();
- runtime_traceback (g);
+ runtime_traceback ();
runtime_tracebackothers (g);
/* The gc library calls runtime_dumpregs here, and provides
@@ -399,6 +399,9 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
{
G *gp;
M *mp;
+#ifdef USING_SPLIT_STACK
+ void *stack_context[10];
+#endif
/* We are now running on the stack registered via sigaltstack.
(Actually there is a small span of time between runtime_siginit
@@ -409,7 +412,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
if (gp != NULL)
{
#ifdef USING_SPLIT_STACK
- __splitstack_getcontext (&gp->stack_context[0]);
+ __splitstack_getcontext (&stack_context[0]);
#endif
}
@@ -432,7 +435,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
if (gp != NULL)
{
#ifdef USING_SPLIT_STACK
- __splitstack_setcontext (&gp->stack_context[0]);
+ __splitstack_setcontext (&stack_context[0]);
#endif
}
}
diff --git a/gcc-4.8/libgo/runtime/malloc.goc b/gcc-4.8/libgo/runtime/malloc.goc
index 8ccaa6b88..d6ecfe463 100644
--- a/gcc-4.8/libgo/runtime/malloc.goc
+++ b/gcc-4.8/libgo/runtime/malloc.goc
@@ -541,7 +541,6 @@ runtime_settype_flush(M *mp, bool sysalloc)
// (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];
diff --git a/gcc-4.8/libgo/runtime/mgc0.c b/gcc-4.8/libgo/runtime/mgc0.c
index c3b32111c..032a43d01 100644
--- a/gcc-4.8/libgo/runtime/mgc0.c
+++ b/gcc-4.8/libgo/runtime/mgc0.c
@@ -174,7 +174,7 @@ static struct {
Obj *roots;
uint32 nroot;
uint32 rootcap;
-} work;
+} work __attribute__((aligned(8)));
enum {
GC_DEFAULT_PTR = GC_NUM_INSTR,
@@ -239,7 +239,6 @@ markonly(void *obj)
// (Manually inlined copy of MHeap_LookupMaybe.)
k = (uintptr)obj>>PageShift;
x = k;
- if(sizeof(void*) == 8)
x -= (uintptr)runtime_mheap->arena_start>>PageShift;
s = runtime_mheap->map[x];
if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse)
@@ -418,7 +417,6 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
// (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)
@@ -466,7 +464,6 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
// 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];
@@ -585,7 +582,6 @@ checkptr(void *obj, uintptr objti)
if(t == nil)
return;
x = (uintptr)obj >> PageShift;
- if(sizeof(void*) == 8)
x -= (uintptr)(runtime_mheap->arena_start)>>PageShift;
s = runtime_mheap->map[x];
objstart = (byte*)((uintptr)s->start<<PageShift);
diff --git a/gcc-4.8/libgo/runtime/mheap.c b/gcc-4.8/libgo/runtime/mheap.c
index b4d94b685..50ec1527f 100644
--- a/gcc-4.8/libgo/runtime/mheap.c
+++ b/gcc-4.8/libgo/runtime/mheap.c
@@ -150,7 +150,6 @@ HaveSpan:
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;
@@ -169,7 +168,6 @@ HaveSpan:
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;
@@ -241,7 +239,6 @@ MHeap_Grow(MHeap *h, uintptr npage)
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;
@@ -259,7 +256,6 @@ 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];
}
@@ -281,7 +277,6 @@ runtime_MHeap_LookupMaybe(MHeap *h, void *v)
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)
@@ -332,7 +327,6 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
// 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);
diff --git a/gcc-4.8/libgo/runtime/proc.c b/gcc-4.8/libgo/runtime/proc.c
index 0e77a3e06..4ca975680 100644
--- a/gcc-4.8/libgo/runtime/proc.c
+++ b/gcc-4.8/libgo/runtime/proc.c
@@ -1716,10 +1716,30 @@ goexit0(G *gp)
// entersyscall is going to return immediately after.
void runtime_entersyscall(void) __attribute__ ((no_split_stack));
+static void doentersyscall(void) __attribute__ ((no_split_stack, noinline));
void
runtime_entersyscall()
{
+ // Save the registers in the g structure so that any pointers
+ // held in registers will be seen by the garbage collector.
+ getcontext(&g->gcregs);
+
+ // Do the work in a separate function, so that this function
+ // doesn't save any registers on its own stack. If this
+ // function does save any registers, we might store the wrong
+ // value in the call to getcontext.
+ //
+ // FIXME: This assumes that we do not need to save any
+ // callee-saved registers to access the TLS variable g. We
+ // don't want to put the ucontext_t on the stack because it is
+ // large and we can not split the stack here.
+ doentersyscall();
+}
+
+static void
+doentersyscall()
+{
if(m->profilehz > 0)
runtime_setprof(false);
@@ -1736,10 +1756,6 @@ runtime_entersyscall()
}
#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;
if(runtime_atomicload(&runtime_sched.sysmonwait)) { // TODO: fast atomic
@@ -2239,6 +2255,14 @@ runtime_sigprof()
if(prof.fn == nil || prof.hz == 0)
return;
+ if(runtime_atomicload(&runtime_in_callers) > 0) {
+ // If SIGPROF arrived while already fetching runtime
+ // callers we can have trouble on older systems
+ // because the unwind library calls dl_iterate_phdr
+ // which was not recursive in the past.
+ return;
+ }
+
runtime_lock(&prof);
if(prof.fn == nil) {
runtime_unlock(&prof);
diff --git a/gcc-4.8/libgo/runtime/runtime.h b/gcc-4.8/libgo/runtime/runtime.h
index d2e7d4c11..964b2e31e 100644
--- a/gcc-4.8/libgo/runtime/runtime.h
+++ b/gcc-4.8/libgo/runtime/runtime.h
@@ -440,7 +440,7 @@ enum {
};
void runtime_hashinit(void);
-void runtime_traceback();
+void runtime_traceback(void);
void runtime_tracebackothers(G*);
/*
@@ -756,6 +756,7 @@ extern struct backtrace_state *__go_get_backtrace_state(void);
extern _Bool __go_file_line(uintptr, String*, String*, intgo *);
extern byte* runtime_progname();
extern void runtime_main(void*);
+extern uint32 runtime_in_callers;
int32 getproccount(void);