summaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-05-23 09:45:29 +0200
committerOndřej Surý <ondrej@sury.org>2011-05-23 09:45:29 +0200
commit63d29fefab5290dc96e0a03ff70603aefa995887 (patch)
tree95da0105686f9aba568a72e7a8ebd580a4fda20e /src/pkg/runtime
parentad811fbb8897a9a3063274e927133915941f1dca (diff)
downloadgolang-63d29fefab5290dc96e0a03ff70603aefa995887.tar.gz
Imported Upstream version 2011.05.22upstream-weekly/2011.05.22
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/append_test.go51
-rw-r--r--src/pkg/runtime/arm/closure.c2
-rw-r--r--src/pkg/runtime/cgo/Makefile14
-rw-r--r--src/pkg/runtime/cgo/setenv.c16
-rw-r--r--src/pkg/runtime/linux/arm/sys.s15
-rw-r--r--src/pkg/runtime/linux/thread.c8
-rw-r--r--src/pkg/runtime/malloc.goc2
-rw-r--r--src/pkg/runtime/proc.c35
-rw-r--r--src/pkg/runtime/runtime.h14
-rw-r--r--src/pkg/runtime/slice.c91
-rw-r--r--src/pkg/runtime/softfloat64.go4
-rw-r--r--src/pkg/runtime/stack.h14
12 files changed, 192 insertions, 74 deletions
diff --git a/src/pkg/runtime/append_test.go b/src/pkg/runtime/append_test.go
new file mode 100644
index 000000000..75a635306
--- /dev/null
+++ b/src/pkg/runtime/append_test.go
@@ -0,0 +1,51 @@
+// Copyright 2011 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.
+package runtime_test
+
+import "testing"
+
+const N = 20
+
+func BenchmarkAppend(b *testing.B) {
+ b.StopTimer()
+ x := make([]int, 0, N)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ x = x[0:0]
+ for j := 0; j < N; j++ {
+ x = append(x, j)
+ }
+ }
+}
+
+func BenchmarkAppendSpecialCase(b *testing.B) {
+ b.StopTimer()
+ x := make([]int, 0, N)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ x = x[0:0]
+ for j := 0; j < N; j++ {
+ if len(x) < cap(x) {
+ x = x[:len(x)+1]
+ x[len(x)-1] = j
+ } else {
+ x = append(x, j)
+ }
+ }
+ }
+}
+
+var x = make([]int, 0, 10)
+
+func f() int {
+ x[:1][0] = 3
+ return 2
+}
+
+func TestSideEffectOrder(t *testing.T) {
+ x = append(x, 1, f())
+ if x[0] != 1 || x[1] != 2 {
+ t.Error("append failed: ", x[0], x[1])
+ }
+}
diff --git a/src/pkg/runtime/arm/closure.c b/src/pkg/runtime/arm/closure.c
index 3aca3a42d..36a93bc53 100644
--- a/src/pkg/runtime/arm/closure.c
+++ b/src/pkg/runtime/arm/closure.c
@@ -43,7 +43,7 @@ vars: WORD arg0
WORD arg2
*/
-extern void cacheflush(byte* start, byte* end);
+extern void runtime·cacheflush(byte* start, byte* end);
#pragma textflag 7
void
diff --git a/src/pkg/runtime/cgo/Makefile b/src/pkg/runtime/cgo/Makefile
index 768fe80ac..f26da2c51 100644
--- a/src/pkg/runtime/cgo/Makefile
+++ b/src/pkg/runtime/cgo/Makefile
@@ -28,18 +28,20 @@ CGO_OFILES=\
$(GOOS)_$(GOARCH).o\
util.o\
-OFILES=\
- iscgo.$O\
- callbacks.$O\
- _cgo_import.$O\
- $(CGO_OFILES)\
-
ifeq ($(GOOS),windows)
CGO_LDFLAGS=-lm -mthreads
else
CGO_LDFLAGS=-lpthread
+CGO_OFILES+=setenv.o\
+
endif
+OFILES=\
+ iscgo.$O\
+ callbacks.$O\
+ _cgo_import.$O\
+ $(CGO_OFILES)\
+
ifeq ($(GOOS),freebsd)
OFILES+=\
freebsd.$O\
diff --git a/src/pkg/runtime/cgo/setenv.c b/src/pkg/runtime/cgo/setenv.c
new file mode 100644
index 000000000..c911b8392
--- /dev/null
+++ b/src/pkg/runtime/cgo/setenv.c
@@ -0,0 +1,16 @@
+// Copyright 20111 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.
+
+#include "libcgo.h"
+
+#include <stdlib.h>
+
+/* Stub for calling setenv */
+static void
+xlibcgo_setenv(char **arg)
+{
+ setenv(arg[0], arg[1], 1);
+}
+
+void (*libcgo_setenv)(char**) = xlibcgo_setenv;
diff --git a/src/pkg/runtime/linux/arm/sys.s b/src/pkg/runtime/linux/arm/sys.s
index d866b0e22..2b5365bd8 100644
--- a/src/pkg/runtime/linux/arm/sys.s
+++ b/src/pkg/runtime/linux/arm/sys.s
@@ -258,11 +258,22 @@ TEXT cas<>(SB),7,$0
TEXT runtime·cas(SB),7,$0
MOVW valptr+0(FP), R2
MOVW old+4(FP), R0
+casagain:
MOVW new+8(FP), R1
BL cas<>(SB)
- MOVW $0, R0
- MOVW.CS $1, R0
+ BCC cascheck
+ MOVW $1, R0
RET
+cascheck:
+ // Kernel lies; double-check.
+ MOVW valptr+0(FP), R2
+ MOVW old+4(FP), R0
+ MOVW 0(R2), R3
+ CMP R0, R3
+ BEQ casagain
+ MOVW $0, R0
+ RET
+
TEXT runtime·casp(SB),7,$0
B runtime·cas(SB)
diff --git a/src/pkg/runtime/linux/thread.c b/src/pkg/runtime/linux/thread.c
index 7166b0ef2..6c506236f 100644
--- a/src/pkg/runtime/linux/thread.c
+++ b/src/pkg/runtime/linux/thread.c
@@ -252,10 +252,10 @@ runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
stk, m, g, fn, runtime·clone, m->id, m->tls[0], &m);
}
- ret = runtime·clone(flags, stk, m, g, fn);
-
- if(ret < 0)
- *(int32*)123 = 123;
+ if((ret = runtime·clone(flags, stk, m, g, fn)) < 0) {
+ runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -ret);
+ runtime·throw("runtime.newosproc");
+ }
}
void
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index 1f2d6da40..c55be9772 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -487,7 +487,7 @@ func SetFinalizer(obj Eface, finalizer Eface) {
nret = (nret + sizeof(void*)-1) & ~(sizeof(void*)-1);
if(runtime·getfinalizer(obj.data, 0)) {
- runtime·printf("runtime.SetFinalizer: finalizer already set");
+ runtime·printf("runtime.SetFinalizer: finalizer already set\n");
goto throw;
}
}
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 52784854f..c5af8b754 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -714,7 +714,7 @@ runtime·oldstack(void)
goid = old.gobuf.g->goid; // fault if g is bad, before gogo
if(old.free != 0)
- runtime·stackfree(g1->stackguard - StackGuard - StackSystem, old.free);
+ runtime·stackfree(g1->stackguard - StackGuard, old.free);
g1->stackbase = old.stackbase;
g1->stackguard = old.stackguard;
@@ -756,7 +756,7 @@ runtime·newstack(void)
// the new Stktop* is necessary to unwind, but
// we don't need to create a new segment.
top = (Stktop*)(m->morebuf.sp - sizeof(*top));
- stk = g1->stackguard - StackGuard - StackSystem;
+ stk = g1->stackguard - StackGuard;
free = 0;
} else {
// allocate new segment.
@@ -785,7 +785,7 @@ runtime·newstack(void)
g1->ispanic = false;
g1->stackbase = (byte*)top;
- g1->stackguard = stk + StackGuard + StackSystem;
+ g1->stackguard = stk + StackGuard;
sp = (byte*)top;
if(argsize > 0) {
@@ -834,7 +834,7 @@ runtime·malg(int32 stacksize)
g->param = nil;
}
newg->stack0 = stk;
- newg->stackguard = stk + StackSystem + StackGuard;
+ newg->stackguard = stk + StackGuard;
newg->stackbase = stk + StackSystem + stacksize - sizeof(Stktop);
runtime·memclr(newg->stackbase, sizeof(Stktop));
}
@@ -880,7 +880,7 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
if((newg = gfget()) != nil){
newg->status = Gwaiting;
- if(newg->stackguard - StackGuard - StackSystem != newg->stack0)
+ if(newg->stackguard - StackGuard != newg->stack0)
runtime·throw("invalid stack in newg");
} else {
newg = runtime·malg(StackMin);
@@ -1165,7 +1165,7 @@ nomatch:
static void
gfput(G *g)
{
- if(g->stackguard - StackGuard - StackSystem != g->stack0)
+ if(g->stackguard - StackGuard != g->stack0)
runtime·throw("invalid stack in gfput");
g->schedlink = runtime·sched.gfree;
runtime·sched.gfree = g;
@@ -1343,3 +1343,26 @@ runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
if(hz != 0)
runtime·resetcpuprofiler(hz);
}
+
+void (*libcgo_setenv)(byte**);
+
+void
+os·setenv_c(String k, String v)
+{
+ byte *arg[2];
+
+ if(libcgo_setenv == nil)
+ return;
+
+ arg[0] = runtime·malloc(k.len + 1);
+ runtime·mcpy(arg[0], k.str, k.len);
+ arg[0][k.len] = 0;
+
+ arg[1] = runtime·malloc(v.len + 1);
+ runtime·mcpy(arg[1], v.str, v.len);
+ arg[1][v.len] = 0;
+
+ runtime·asmcgocall(libcgo_setenv, arg);
+ runtime·free(arg[0]);
+ runtime·free(arg[1]);
+}
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index f9b404e15..f2f8dcd5b 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -597,17 +597,3 @@ int32 runtime·chancap(Hchan*);
void runtime·ifaceE2I(struct InterfaceType*, Eface, Iface*);
-enum
-{
- // StackSystem is a number of additional bytes to add
- // to each stack below the usual guard area for OS-specific
- // purposes like signal handling.
- // TODO(rsc): This is only for Windows. Can't Windows use
- // a separate exception stack like every other operating system?
-#ifdef __WINDOWS__
- StackSystem = 2048,
-#else
- StackSystem = 0,
-#endif
-};
-
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c
index 1fee923e4..9146c177f 100644
--- a/src/pkg/runtime/slice.c
+++ b/src/pkg/runtime/slice.c
@@ -9,6 +9,8 @@
static int32 debug = 0;
static void makeslice1(SliceType*, int32, int32, Slice*);
+static void growslice1(SliceType*, Slice, int32, Slice *);
+static void appendslice1(SliceType*, Slice, Slice, Slice*);
void runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret);
// see also unsafe·NewArray
@@ -46,22 +48,6 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
ret->array = runtime·mal(size);
}
-static void appendslice1(SliceType*, Slice, Slice, Slice*);
-
-// append(type *Type, n int, old []T, ...,) []T
-#pragma textflag 7
-void
-runtime·append(SliceType *t, int32 n, Slice old, ...)
-{
- Slice sl;
- Slice *ret;
-
- sl.len = n;
- sl.array = (byte*)(&old+1);
- ret = (Slice*)(sl.array + ((t->elem->size*n+sizeof(uintptr)-1) & ~(sizeof(uintptr)-1)));
- appendslice1(t, old, sl, ret);
-}
-
// appendslice(type *Type, x, y, []T) []T
void
runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
@@ -72,36 +58,69 @@ runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
static void
appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
{
- Slice newx;
int32 m;
uintptr w;
- if(x.len+y.len < x.len)
+ m = x.len+y.len;
+
+ if(m < x.len)
runtime·throw("append: slice overflow");
+ if(m > x.cap)
+ growslice1(t, x, m, ret);
+ else
+ *ret = x;
+
w = t->elem->size;
- if(x.len+y.len > x.cap) {
- m = x.cap;
- if(m == 0)
- m = y.len;
- else {
- do {
- if(x.len < 1024)
- m += m;
- else
- m += m/4;
- } while(m < x.len+y.len);
- }
- makeslice1(t, x.len, m, &newx);
- runtime·memmove(newx.array, x.array, x.len*w);
- x = newx;
+ runtime·memmove(ret->array + ret->len*w, y.array, y.len*w);
+ ret->len += y.len;
+}
+
+// growslice(type *Type, x, []T, n int64) []T
+void
+runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
+{
+ int64 cap;
+
+ if(n < 1)
+ runtime·panicstring("growslice: invalid n");
+
+ cap = old.cap + n;
+
+ if((int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
+ runtime·panicstring("growslice: cap out of range");
+
+ growslice1(t, old, cap, &ret);
+
+ FLUSH(&ret);
+
+ if(debug) {
+ runtime·printf("growslice(%S,", *t->string);
+ runtime·printslice(old);
+ runtime·printf(", new cap=%D) =", cap);
+ runtime·printslice(ret);
}
- runtime·memmove(x.array+x.len*w, y.array, y.len*w);
- x.len += y.len;
- *ret = x;
}
+static void
+growslice1(SliceType *t, Slice x, int32 newcap, Slice *ret)
+{
+ int32 m;
+ m = x.cap;
+ if(m == 0)
+ m = newcap;
+ else {
+ do {
+ if(x.len < 1024)
+ m += m;
+ else
+ m += m/4;
+ } while(m < newcap);
+ }
+ makeslice1(t, x.len, m, ret);
+ runtime·memmove(ret->array, x.array, ret->len * t->elem->size);
+}
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
void
diff --git a/src/pkg/runtime/softfloat64.go b/src/pkg/runtime/softfloat64.go
index d9bbe5def..e0c3b7b73 100644
--- a/src/pkg/runtime/softfloat64.go
+++ b/src/pkg/runtime/softfloat64.go
@@ -11,7 +11,7 @@ package runtime
const (
mantbits64 uint = 52
expbits64 uint = 11
- bias64 = -1<<(expbits64-1) + 1
+ bias64 = -1<<(expbits64-1) + 1
nan64 uint64 = (1<<expbits64-1)<<mantbits64 + 1
inf64 uint64 = (1<<expbits64 - 1) << mantbits64
@@ -19,7 +19,7 @@ const (
mantbits32 uint = 23
expbits32 uint = 8
- bias32 = -1<<(expbits32-1) + 1
+ bias32 = -1<<(expbits32-1) + 1
nan32 uint32 = (1<<expbits32-1)<<mantbits32 + 1
inf32 uint32 = (1<<expbits32 - 1) << mantbits32
diff --git a/src/pkg/runtime/stack.h b/src/pkg/runtime/stack.h
index ebf0462b5..2b6b0e387 100644
--- a/src/pkg/runtime/stack.h
+++ b/src/pkg/runtime/stack.h
@@ -53,6 +53,16 @@ functions to make sure that this limit cannot be violated.
*/
enum {
+ // StackSystem is a number of additional bytes to add
+ // to each stack below the usual guard area for OS-specific
+ // purposes like signal handling. Used on Windows because
+ // it does not use a separate stack.
+#ifdef __WINDOWS__
+ StackSystem = 2048,
+#else
+ StackSystem = 0,
+#endif
+
// The amount of extra stack to allocate beyond the size
// needed for the single frame that triggered the split.
StackExtra = 1024,
@@ -73,7 +83,7 @@ enum {
// The stack guard is a pointer this many bytes above the
// bottom of the stack.
- StackGuard = 256,
+ StackGuard = 256 + StackSystem,
// After a stack split check the SP is allowed to be this
// many bytes below the stack guard. This saves an instruction
@@ -82,5 +92,5 @@ enum {
// The maximum number of bytes that a chain of NOSPLIT
// functions can use.
- StackLimit = StackGuard - StackSmall,
+ StackLimit = StackGuard - StackSystem - StackSmall,
};