summaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/chan.c20
-rw-r--r--libgo/runtime/cpuprof.c14
-rw-r--r--libgo/runtime/go-append.c3
-rw-r--r--libgo/runtime/go-int-to-string.c9
-rw-r--r--libgo/runtime/go-make-slice.c2
-rw-r--r--libgo/runtime/go-rune.c8
-rw-r--r--libgo/runtime/go-type-complex.c14
-rw-r--r--libgo/runtime/go-type-float.c14
-rw-r--r--libgo/runtime/malloc.h9
-rw-r--r--libgo/runtime/print.c9
-rw-r--r--libgo/runtime/runtime.c6
11 files changed, 88 insertions, 20 deletions
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c
index c8ee10e8c88..1e389a218de 100644
--- a/libgo/runtime/chan.c
+++ b/libgo/runtime/chan.c
@@ -3,6 +3,8 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
#include "go-type.h"
#define NOSELGEN 1
@@ -85,10 +87,10 @@ runtime_makechan_c(ChanType *t, int64 hint)
Hchan *c;
int32 n;
const Type *elem;
-
+
elem = t->__element_type;
- if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > ((uintptr)-1) / elem->__size))
+ if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > MaxMem / elem->__size))
runtime_panicstring("makechan: size out of range");
n = sizeof(*c);
@@ -189,7 +191,7 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
sg = dequeue(&c->recvq);
if(sg != nil) {
runtime_unlock(c);
-
+
gp = sg->g;
gp->param = sg;
if(sg->elem != nil)
@@ -528,7 +530,7 @@ runtime_selectnbrecv(ChanType *t, byte *v, Hchan *c)
runtime_chanrecv(t, c, v, &selected, nil);
return selected;
-}
+}
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
//
@@ -560,7 +562,7 @@ runtime_selectnbrecv2(ChanType *t, byte *v, _Bool *received, Hchan *c)
if(received != nil)
*received = r;
return selected;
-}
+}
// For reflect:
// func chansend(c chan, val iword, nb bool) (selected bool)
@@ -576,7 +578,7 @@ reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb)
bool selected;
bool *sp;
byte *vp;
-
+
if(nb) {
selected = false;
sp = (bool*)&selected;
@@ -695,7 +697,7 @@ runtime_selectsend(Select *sel, Hchan *c, void *elem, int index)
// nil cases do not compete
if(c == nil)
return;
-
+
selectsend(sel, c, index, elem);
}
@@ -704,7 +706,7 @@ selectsend(Select *sel, Hchan *c, int index, void *elem)
{
int32 i;
Scase *cas;
-
+
i = sel->ncase;
if(i >= sel->tcase)
runtime_throw("selectsend: too many cases");
@@ -975,7 +977,7 @@ loop:
case CaseRecv:
enqueue(&c->recvq, sg);
break;
-
+
case CaseSend:
enqueue(&c->sendq, sg);
break;
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index 252948d6659..9bf5d11e687 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -105,6 +105,7 @@ struct Profile {
uint32 wtoggle;
bool wholding; // holding & need to release a log half
bool flushing; // flushing hash table - profile is over
+ bool eod_sent; // special end-of-data record sent; => flushing
};
static Lock lk;
@@ -115,6 +116,8 @@ static void add(Profile*, uintptr*, int32);
static bool evict(Profile*, Entry*);
static bool flushlog(Profile*);
+static uintptr eod[3] = {0, 1, 0};
+
// LostProfileData is a no-op function used in profiles
// to mark the number of profiling stack traces that were
// discarded due to slow data writers.
@@ -168,6 +171,7 @@ runtime_SetCPUProfileRate(int32 hz)
prof->wholding = false;
prof->wtoggle = 0;
prof->flushing = false;
+ prof->eod_sent = false;
runtime_noteclear(&prof->wait);
runtime_setcpuprofilerate(tick, hz);
@@ -414,6 +418,16 @@ breakflush:
}
// Made it through the table without finding anything to log.
+ if(!p->eod_sent) {
+ // We may not have space to append this to the partial log buf,
+ // so we always return a new slice for the end-of-data marker.
+ p->eod_sent = true;
+ ret.array = (byte*)eod;
+ ret.len = sizeof eod;
+ ret.cap = ret.len;
+ return ret;
+ }
+
// Finally done. Clean up and return nil.
p->flushing = false;
if(!runtime_cas(&p->handoff, p->handoff, 0))
diff --git a/libgo/runtime/go-append.c b/libgo/runtime/go-append.c
index 3a0c7781126..dac4c902c15 100644
--- a/libgo/runtime/go-append.c
+++ b/libgo/runtime/go-append.c
@@ -54,6 +54,9 @@ __go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount,
while (m < count);
}
+ if ((uintptr) m > MaxMem / element_size)
+ runtime_panicstring ("growslice: cap out of range");
+
n = __go_alloc (m * element_size);
__builtin_memcpy (n, a.__values, a.__count * element_size);
diff --git a/libgo/runtime/go-int-to-string.c b/libgo/runtime/go-int-to-string.c
index e9645bf98fe..17a5fcb04c0 100644
--- a/libgo/runtime/go-int-to-string.c
+++ b/libgo/runtime/go-int-to-string.c
@@ -17,6 +17,11 @@ __go_int_to_string (int v)
unsigned char *retdata;
struct __go_string ret;
+ /* A negative value is not valid UTF-8; turn it into the replacement
+ character. */
+ if (v < 0)
+ v = 0xfffd;
+
if (v <= 0x7f)
{
buf[0] = v;
@@ -34,6 +39,10 @@ __go_int_to_string (int v)
"replacement character". */
if (v > 0x10ffff)
v = 0xfffd;
+ /* If the value is a surrogate pair, which is invalid in UTF-8,
+ turn it into the replacement character. */
+ if (v >= 0xd800 && v < 0xe000)
+ v = 0xfffd;
if (v <= 0xffff)
{
diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c
index 42b412c772b..822c9b68f0a 100644
--- a/libgo/runtime/go-make-slice.c
+++ b/libgo/runtime/go-make-slice.c
@@ -37,7 +37,7 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
if (cap < len
|| (uintptr_t) icap != cap
|| (std->__element_type->__size > 0
- && cap > (uintptr_t) -1U / std->__element_type->__size))
+ && cap > MaxMem / std->__element_type->__size))
runtime_panicstring ("makeslice: cap out of range");
ret.__count = ilen;
diff --git a/libgo/runtime/go-rune.c b/libgo/runtime/go-rune.c
index 7e31eb8d622..acdecb02467 100644
--- a/libgo/runtime/go-rune.c
+++ b/libgo/runtime/go-rune.c
@@ -53,6 +53,14 @@ __go_get_rune (const unsigned char *str, size_t len, int *rune)
*rune = (((c & 0xf) << 12)
+ ((c1 & 0x3f) << 6)
+ (c2 & 0x3f));
+
+ if (*rune >= 0xd800 && *rune < 0xe000)
+ {
+ /* Invalid surrogate half; return replace character. */
+ *rune = 0xfffd;
+ return 1;
+ }
+
return 3;
}
diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c
index f923c867d99..106024f5c88 100644
--- a/libgo/runtime/go-type-complex.c
+++ b/libgo/runtime/go-type-complex.c
@@ -32,10 +32,14 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size)
cf = ucf.cf;
cfr = __builtin_crealf (cf);
cfi = __builtin_cimagf (cf);
- if (__builtin_isinff (cfr) || __builtin_isinff (cfi)
- || __builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
return 0;
+ /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
+ random so that not all NaNs wind up in the same place. */
+ if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ return runtime_fastrand1 ();
+
/* Avoid negative zero. */
if (cfr == 0 && cfi == 0)
return 0;
@@ -62,10 +66,12 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size)
cd = ucd.cd;
cdr = __builtin_crealf (cd);
cdi = __builtin_cimagf (cd);
- if (__builtin_isinf (cdr) || __builtin_isinf (cdi)
- || __builtin_isnan (cdr) || __builtin_isnan (cdi))
+ if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
return 0;
+ if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
+ return runtime_fastrand1 ();
+
/* Avoid negative zero. */
if (cdr == 0 && cdi == 0)
return 0;
diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c
index cc6e247e531..e1c03e42843 100644
--- a/libgo/runtime/go-type-float.c
+++ b/libgo/runtime/go-type-float.c
@@ -29,8 +29,14 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size)
__builtin_memcpy (uf.a, vkey, 4);
f = uf.f;
- if (__builtin_isinff (f) || __builtin_isnanf (f) || f == 0)
+ if (__builtin_isinff (f) || f == 0)
return 0;
+
+ /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
+ random so that not all NaNs wind up in the same place. */
+ if (__builtin_isnanf (f))
+ return runtime_fastrand1 ();
+
return (uintptr_t) uf.si;
}
else if (key_size == 8)
@@ -45,8 +51,12 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size)
__builtin_memcpy (ud.a, vkey, 8);
d = ud.d;
- if (__builtin_isinf (d) || __builtin_isnan (d) || d == 0)
+ if (__builtin_isinf (d) || d == 0)
return 0;
+
+ if (__builtin_isnan (d))
+ return runtime_fastrand1 ();
+
return (uintptr_t) ud.di;
}
else
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h
index 16bb449f128..96cb609367f 100644
--- a/libgo/runtime/malloc.h
+++ b/libgo/runtime/malloc.h
@@ -128,6 +128,15 @@ enum
MaxGcproc = 4,
};
+// Maximum memory allocation size, a hint for callers.
+// This must be a #define instead of an enum because it
+// is so large.
+#if __SIZEOF_POINTER__ == 8
+#define MaxMem (16ULL<<30) /* 16 GB */
+#else
+#define MaxMem ((uintptr)-1)
+#endif
+
// A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).)
struct MLink
{
diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c
index c24304e2487..fcf57ea4144 100644
--- a/libgo/runtime/print.c
+++ b/libgo/runtime/print.c
@@ -17,13 +17,16 @@ gwrite(const void *v, int32 n)
G* g = runtime_g();
if(g == nil || g->writebuf == nil) {
- runtime_write(2, v, n);
+ // Avoid -D_FORTIFY_SOURCE problems.
+ int rv __attribute__((unused));
+
+ rv = runtime_write(2, v, n);
return;
}
-
+
if(g->writenbuf == 0)
return;
-
+
if(n > g->writenbuf)
n = g->writenbuf;
runtime_memmove(g->writebuf, v, n);
diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c
index 72875fd53f7..e0a7925aed1 100644
--- a/libgo/runtime/runtime.c
+++ b/libgo/runtime/runtime.c
@@ -106,11 +106,15 @@ static byte** argv;
extern Slice os_Args asm ("os.Args");
extern Slice syscall_Envs asm ("syscall.Envs");
+void (*runtime_sysargs)(int32, uint8**);
+
void
runtime_args(int32 c, byte **v)
{
argc = c;
argv = v;
+ if(runtime_sysargs != nil)
+ runtime_sysargs(c, v);
}
void
@@ -234,7 +238,7 @@ runtime_showframe(const unsigned char *s)
if(traceback < 0)
traceback = runtime_gotraceback();
- return traceback > 1 || (__builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0);
+ return traceback > 1 || (s != nil && __builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0);
}
bool