diff options
Diffstat (limited to 'gcc-4.8/libgo/runtime')
-rw-r--r-- | gcc-4.8/libgo/runtime/go-callers.c | 9 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-cdiv.c | 46 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-defer.c | 1 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-defer.h | 6 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-int-array-to-string.c | 4 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-make-slice.c | 5 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-nosys.c | 57 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-recover.c | 77 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-reflect-call.c | 5 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/go-signal.c | 9 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/malloc.goc | 1 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/mgc0.c | 6 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/mheap.c | 6 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/proc.c | 32 | ||||
-rw-r--r-- | gcc-4.8/libgo/runtime/runtime.h | 3 |
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); |