aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2015-01-15 00:27:56 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2015-01-15 00:27:56 +0000
commitf8d9fa9e80b57f89e7877ce6cad8a3464879009b (patch)
tree58a1724fee16d2b03c65678c4dd9b50bb97137a9 /libgo/runtime
parent6bd3f109d8d8fa58eeccd6b3504721b4f20c00c2 (diff)
downloadgcc-f8d9fa9e80b57f89e7877ce6cad8a3464879009b.zip
gcc-f8d9fa9e80b57f89e7877ce6cad8a3464879009b.tar.gz
gcc-f8d9fa9e80b57f89e7877ce6cad8a3464879009b.tar.bz2
libgo, compiler: Upgrade libgo to Go 1.4, except for runtime.
This upgrades all of libgo other than the runtime package to the Go 1.4 release. In Go 1.4 much of the runtime was rewritten into Go. Merging that code will take more time and will not change the API, so I'm putting it off for now. There are a few runtime changes anyhow, to accomodate other packages that rely on minor modifications to the runtime support. The compiler changes slightly to add a one-bit flag to each type descriptor kind that is stored directly in an interface, which for gccgo is currently only pointer types. Another one-bit flag (gcprog) is reserved because it is used by the gc compiler, but gccgo does not currently use it. There is another error check in the compiler since I ran across it during testing. gotools/: * Makefile.am (go_cmd_go_files): Sort entries. Add generate.go. * Makefile.in: Rebuild. From-SVN: r219627
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/env_posix.c6
-rw-r--r--libgo/runtime/go-assert-interface.c2
-rw-r--r--libgo/runtime/go-can-convert-interface.c2
-rw-r--r--libgo/runtime/go-check-interface.c4
-rw-r--r--libgo/runtime/go-convert-interface.c2
-rw-r--r--libgo/runtime/go-make-slice.c2
-rw-r--r--libgo/runtime/go-reflect-map.c8
-rw-r--r--libgo/runtime/go-type.h7
-rw-r--r--libgo/runtime/go-unsafe-pointer.c4
-rw-r--r--libgo/runtime/go-unsetenv.c54
-rw-r--r--libgo/runtime/malloc.goc13
-rw-r--r--libgo/runtime/mgc0.c9
-rw-r--r--libgo/runtime/netpoll.goc36
-rw-r--r--libgo/runtime/runtime.c37
-rw-r--r--libgo/runtime/runtime.h5
-rw-r--r--libgo/runtime/runtime1.goc13
-rw-r--r--libgo/runtime/time.goc11
17 files changed, 154 insertions, 61 deletions
diff --git a/libgo/runtime/env_posix.c b/libgo/runtime/env_posix.c
index ff4bf0c..ee3e451 100644
--- a/libgo/runtime/env_posix.c
+++ b/libgo/runtime/env_posix.c
@@ -9,7 +9,7 @@
#include "arch.h"
#include "malloc.h"
-extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs");
+extern Slice envs;
const byte*
runtime_getenv(const char *s)
@@ -22,8 +22,8 @@ runtime_getenv(const char *s)
bs = (const byte*)s;
len = runtime_findnull(bs);
- envv = (String*)syscall_Envs.__values;
- envc = syscall_Envs.__count;
+ envv = (String*)envs.__values;
+ envc = envs.__count;
for(i=0; i<envc; i++){
if(envv[i].len <= len)
continue;
diff --git a/libgo/runtime/go-assert-interface.c b/libgo/runtime/go-assert-interface.c
index 2510f9a..427916f 100644
--- a/libgo/runtime/go-assert-interface.c
+++ b/libgo/runtime/go-assert-interface.c
@@ -36,7 +36,7 @@ __go_assert_interface (const struct __go_type_descriptor *lhs_descriptor,
/* A type assertion to an empty interface just returns the object
descriptor. */
- __go_assert (lhs_descriptor->__code == GO_INTERFACE);
+ __go_assert ((lhs_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE);
lhs_interface = (const struct __go_interface_type *) lhs_descriptor;
if (lhs_interface->__methods.__count == 0)
return rhs_descriptor;
diff --git a/libgo/runtime/go-can-convert-interface.c b/libgo/runtime/go-can-convert-interface.c
index 4de5580..aac889d 100644
--- a/libgo/runtime/go-can-convert-interface.c
+++ b/libgo/runtime/go-can-convert-interface.c
@@ -31,7 +31,7 @@ __go_can_convert_to_interface (
if (from_descriptor == NULL)
return 0;
- __go_assert (to_descriptor->__code == GO_INTERFACE);
+ __go_assert ((to_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE);
to_interface = (const struct __go_interface_type *) to_descriptor;
to_method_count = to_interface->__methods.__count;
to_method = ((const struct __go_interface_method *)
diff --git a/libgo/runtime/go-check-interface.c b/libgo/runtime/go-check-interface.c
index c29971a..722a421 100644
--- a/libgo/runtime/go-check-interface.c
+++ b/libgo/runtime/go-check-interface.c
@@ -30,9 +30,9 @@ __go_check_interface_type (
if (lhs_descriptor != rhs_descriptor
&& !__go_type_descriptors_equal (lhs_descriptor, rhs_descriptor)
- && (lhs_descriptor->__code != GO_UNSAFE_POINTER
+ && ((lhs_descriptor->__code & GO_CODE_MASK) != GO_UNSAFE_POINTER
|| !__go_is_pointer_type (rhs_descriptor))
- && (rhs_descriptor->__code != GO_UNSAFE_POINTER
+ && ((rhs_descriptor->__code & GO_CODE_MASK) != GO_UNSAFE_POINTER
|| !__go_is_pointer_type (lhs_descriptor)))
{
struct __go_empty_interface panic_arg;
diff --git a/libgo/runtime/go-convert-interface.c b/libgo/runtime/go-convert-interface.c
index 3eee6bf4..0e8a306 100644
--- a/libgo/runtime/go-convert-interface.c
+++ b/libgo/runtime/go-convert-interface.c
@@ -41,7 +41,7 @@ __go_convert_interface_2 (const struct __go_type_descriptor *lhs_descriptor,
return NULL;
}
- __go_assert (lhs_descriptor->__code == GO_INTERFACE);
+ __go_assert ((lhs_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE);
lhs_interface = (const struct __go_interface_type *) lhs_descriptor;
lhs_method_count = lhs_interface->__methods.__count;
lhs_methods = ((const struct __go_interface_method *)
diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c
index 855bb17..ccd07e5 100644
--- a/libgo/runtime/go-make-slice.c
+++ b/libgo/runtime/go-make-slice.c
@@ -30,7 +30,7 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
uintptr_t size;
struct __go_open_array ret;
- __go_assert (td->__code == GO_SLICE);
+ __go_assert ((td->__code & GO_CODE_MASK) == GO_SLICE);
std = (const struct __go_slice_type *) td;
ilen = (intgo) len;
diff --git a/libgo/runtime/go-reflect-map.c b/libgo/runtime/go-reflect-map.c
index ab116e8..58e1b34 100644
--- a/libgo/runtime/go-reflect-map.c
+++ b/libgo/runtime/go-reflect-map.c
@@ -24,7 +24,7 @@ mapaccess (struct __go_map_type *mt, void *m, void *key)
{
struct __go_map *map = (struct __go_map *) m;
- __go_assert (mt->__common.__code == GO_MAP);
+ __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
if (map == NULL)
return NULL;
else
@@ -40,7 +40,7 @@ mapassign (struct __go_map_type *mt, void *m, void *key, void *val)
struct __go_map *map = (struct __go_map *) m;
void *p;
- __go_assert (mt->__common.__code == GO_MAP);
+ __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
if (map == NULL)
runtime_panicstring ("assignment to entry in nil map");
p = __go_map_index (map, key, 1);
@@ -55,7 +55,7 @@ mapdelete (struct __go_map_type *mt, void *m, void *key)
{
struct __go_map *map = (struct __go_map *) m;
- __go_assert (mt->__common.__code == GO_MAP);
+ __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
if (map == NULL)
return;
__go_map_delete (map, key);
@@ -81,7 +81,7 @@ mapiterinit (struct __go_map_type *mt, void *m)
{
struct __go_hash_iter *it;
- __go_assert (mt->__common.__code == GO_MAP);
+ __go_assert ((mt->__common.__code & GO_CODE_MASK) == GO_MAP);
it = __go_alloc (sizeof (struct __go_hash_iter));
__go_mapiterinit ((struct __go_map *) m, it);
return (unsigned char *) it;
diff --git a/libgo/runtime/go-type.h b/libgo/runtime/go-type.h
index 74e8340..d769335 100644
--- a/libgo/runtime/go-type.h
+++ b/libgo/runtime/go-type.h
@@ -54,9 +54,11 @@ struct String;
#define GO_STRUCT 25
#define GO_UNSAFE_POINTER 26
+#define GO_DIRECT_IFACE (1 << 5)
+#define GO_GC_PROG (1 << 6)
#define GO_NO_POINTERS (1 << 7)
-#define GO_CODE_MASK 0x7f
+#define GO_CODE_MASK 0x1f
/* For each Go type the compiler constructs one of these structures.
This is used for type reflection, interfaces, maps, and reference
@@ -310,7 +312,8 @@ struct __go_struct_type
static inline _Bool
__go_is_pointer_type (const struct __go_type_descriptor *td)
{
- return td->__code == GO_PTR || td->__code == GO_UNSAFE_POINTER;
+ return ((td->__code & GO_CODE_MASK) == GO_PTR
+ || (td->__code & GO_CODE_MASK) == GO_UNSAFE_POINTER);
}
extern _Bool
diff --git a/libgo/runtime/go-unsafe-pointer.c b/libgo/runtime/go-unsafe-pointer.c
index 729e9a1..71364f5 100644
--- a/libgo/runtime/go-unsafe-pointer.c
+++ b/libgo/runtime/go-unsafe-pointer.c
@@ -44,7 +44,7 @@ const uintptr unsafe_Pointer_gc[] = {sizeof(void*), GC_APTR, 0, GC_END};
const struct __go_type_descriptor unsafe_Pointer =
{
/* __code */
- GO_UNSAFE_POINTER,
+ GO_UNSAFE_POINTER | GO_DIRECT_IFACE,
/* __align */
__alignof (void *),
/* __field_align */
@@ -89,7 +89,7 @@ const struct __go_ptr_type pointer_unsafe_Pointer =
/* __common */
{
/* __code */
- GO_PTR,
+ GO_PTR | GO_DIRECT_IFACE,
/* __align */
__alignof (void *),
/* __field_align */
diff --git a/libgo/runtime/go-unsetenv.c b/libgo/runtime/go-unsetenv.c
new file mode 100644
index 0000000..409436a
--- /dev/null
+++ b/libgo/runtime/go-unsetenv.c
@@ -0,0 +1,54 @@
+/* go-unsetenv.c -- unset an environment variable from Go.
+
+ Copyright 2015 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 "config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "go-alloc.h"
+#include "runtime.h"
+#include "arch.h"
+#include "malloc.h"
+
+/* Unset an environment variable from Go. This is called by
+ syscall.Unsetenv. */
+
+void unsetenv_c (String) __asm__ (GOSYM_PREFIX "syscall.unsetenv_c");
+
+void
+unsetenv_c (String k)
+{
+ const byte *ks;
+ unsigned char *kn;
+ intgo len;
+
+ ks = k.str;
+ if (ks == NULL)
+ ks = (const byte *) "";
+ kn = NULL;
+
+#ifdef HAVE_UNSETENV
+
+ if (ks != NULL && ks[k.len] != 0)
+ {
+ // Objects that are explicitly freed must be at least 16 bytes in size,
+ // so that they are not allocated using tiny alloc.
+ len = k.len + 1;
+ if (len < TinySize)
+ len = TinySize;
+ kn = __go_alloc (len);
+ __builtin_memcpy (kn, ks, k.len);
+ ks = kn;
+ }
+
+ unsetenv ((const char *) ks);
+
+#endif /* !defined(HAVE_UNSETENV) */
+
+ if (kn != NULL)
+ __go_free (kn);
+}
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index f240ffb..b05c5fa 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -25,6 +25,7 @@ package runtime
#define string __reflection
#define KindPtr GO_PTR
#define KindNoPointers GO_NO_POINTERS
+#define kindMask GO_CODE_MASK
// GCCGO SPECIFIC CHANGE
//
@@ -935,7 +936,7 @@ func SetFinalizer(obj Eface, finalizer Eface) {
runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
goto throw;
}
- if(obj.__type_descriptor->__code != GO_PTR) {
+ if((obj.__type_descriptor->kind&kindMask) != GO_PTR) {
runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.__type_descriptor->__reflection);
goto throw;
}
@@ -956,14 +957,14 @@ func SetFinalizer(obj Eface, finalizer Eface) {
if(!runtime_mlookup(obj.__object, &base, &size, nil) || obj.__object != base) {
// As an implementation detail we allow to set finalizers for an inner byte
// of an object if it could come from tiny alloc (see mallocgc for details).
- if(ot->__element_type == nil || (ot->__element_type->__code&KindNoPointers) == 0 || ot->__element_type->__size >= TinySize) {
+ if(ot->__element_type == nil || (ot->__element_type->kind&KindNoPointers) == 0 || ot->__element_type->__size >= TinySize) {
runtime_printf("runtime.SetFinalizer: pointer not at beginning of allocated block (%p)\n", obj.__object);
goto throw;
}
}
if(finalizer.__type_descriptor != nil) {
runtime_createfing();
- if(finalizer.__type_descriptor->__code != GO_FUNC)
+ if((finalizer.__type_descriptor->kind&kindMask) != GO_FUNC)
goto badfunc;
ft = (const FuncType*)finalizer.__type_descriptor;
if(ft->__dotdotdot || ft->__in.__count != 1)
@@ -971,12 +972,12 @@ func SetFinalizer(obj Eface, finalizer Eface) {
fint = *(Type**)ft->__in.__values;
if(__go_type_descriptors_equal(fint, obj.__type_descriptor)) {
// ok - same type
- } else if(fint->__code == GO_PTR && (fint->__uncommon == nil || fint->__uncommon->__name == nil || obj.type->__uncommon == nil || obj.type->__uncommon->__name == nil) && __go_type_descriptors_equal(((const PtrType*)fint)->__element_type, ((const PtrType*)obj.type)->__element_type)) {
+ } else if((fint->kind&kindMask) == GO_PTR && (fint->__uncommon == nil || fint->__uncommon->__name == nil || obj.type->__uncommon == nil || obj.type->__uncommon->__name == nil) && __go_type_descriptors_equal(((const PtrType*)fint)->__element_type, ((const PtrType*)obj.type)->__element_type)) {
// ok - not same type, but both pointers,
// one or the other is unnamed, and same element type, so assignable.
- } else if(fint->kind == GO_INTERFACE && ((const InterfaceType*)fint)->__methods.__count == 0) {
+ } else if((fint->kind&kindMask) == GO_INTERFACE && ((const InterfaceType*)fint)->__methods.__count == 0) {
// ok - satisfies empty interface
- } else if(fint->kind == GO_INTERFACE && __go_convert_interface_2(fint, obj.__type_descriptor, 1) != nil) {
+ } else if((fint->kind&kindMask) == GO_INTERFACE && __go_convert_interface_2(fint, obj.__type_descriptor, 1) != nil) {
// ok - satisfies non-empty interface
} else
goto badfunc;
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index b09054c..0867abf 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -71,6 +71,7 @@ typedef struct __go_map Hmap;
#define string __reflection
#define KindPtr GO_PTR
#define KindNoPointers GO_NO_POINTERS
+#define kindMask GO_CODE_MASK
// PtrType aka __go_ptr_type
#define elem __element_type
@@ -946,7 +947,7 @@ scanblock(Workbuf *wbuf, bool keepworking)
continue;
obj = eface->__object;
- if((t->__code & ~KindNoPointers) == KindPtr) {
+ if((t->__code & kindMask) == KindPtr) {
// Only use type information if it is a pointer-containing type.
// This matches the GC programs written by cmd/gc/reflect.c's
// dgcsym1 in case TPTR32/case TPTR64. See rationale there.
@@ -984,7 +985,7 @@ scanblock(Workbuf *wbuf, bool keepworking)
continue;
obj = iface->__object;
- if((t->__code & ~KindNoPointers) == KindPtr) {
+ if((t->__code & kindMask) == KindPtr) {
// Only use type information if it is a pointer-containing type.
// This matches the GC programs written by cmd/gc/reflect.c's
// dgcsym1 in case TPTR32/case TPTR64. See rationale there.
@@ -2369,6 +2370,8 @@ gc(struct gc_args *args)
// Sweep all spans eagerly.
while(runtime_sweepone() != (uintptr)-1)
gcstats.npausesweep++;
+ // Do an additional mProf_GC, because all 'free' events are now real as well.
+ runtime_MProf_GC();
}
runtime_MProf_GC();
@@ -2514,7 +2517,7 @@ runfinq(void* dummy __attribute__ ((unused)))
f = &fb->fin[i];
fint = ((const Type**)f->ft->__in.array)[0];
- if(fint->__code == KindPtr) {
+ if((fint->__code & kindMask) == KindPtr) {
// direct use of pointer
param = &f->arg;
} else if(((const InterfaceType*)fint)->__methods.__count == 0) {
diff --git a/libgo/runtime/netpoll.goc b/libgo/runtime/netpoll.goc
index 5308e01..2f3fa45 100644
--- a/libgo/runtime/netpoll.goc
+++ b/libgo/runtime/netpoll.goc
@@ -79,9 +79,9 @@ static struct
static bool netpollblock(PollDesc*, int32, bool);
static G* netpollunblock(PollDesc*, int32, bool);
-static void deadline(int64, Eface);
-static void readDeadline(int64, Eface);
-static void writeDeadline(int64, Eface);
+static void deadline(Eface, uintptr);
+static void readDeadline(Eface, uintptr);
+static void writeDeadline(Eface, uintptr);
static PollDesc* allocPollDesc(void);
static intgo checkerr(PollDesc *pd, int32 mode);
@@ -197,22 +197,25 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
// Copy current seq into the timer arg.
// Timer func will check the seq against current descriptor seq,
// if they differ the descriptor was reused or timers were reset.
- pd->rt.arg.type = (Type*)pd->seq;
+ pd->rt.arg.type = nil; // should be *pollDesc type descriptor.
pd->rt.arg.data = pd;
+ pd->rt.seq = pd->seq;
runtime_addtimer(&pd->rt);
} else {
if(pd->rd > 0) {
pd->rt.fv = &readDeadlineFn;
pd->rt.when = pd->rd;
- pd->rt.arg.type = (Type*)pd->seq;
+ pd->rt.arg.type = nil; // should be *pollDesc type descriptor.
pd->rt.arg.data = pd;
+ pd->rt.seq = pd->seq;
runtime_addtimer(&pd->rt);
}
if(pd->wd > 0) {
pd->wt.fv = &writeDeadlineFn;
pd->wt.when = pd->wd;
- pd->wt.arg.type = (Type*)pd->seq;
+ pd->wt.arg.type = nil; // should be *pollDesc type descriptor.
pd->wt.arg.data = pd;
+ pd->wt.seq = pd->seq;
runtime_addtimer(&pd->wt);
}
}
@@ -389,19 +392,16 @@ netpollunblock(PollDesc *pd, int32 mode, bool ioready)
}
static void
-deadlineimpl(int64 now, Eface arg, bool read, bool write)
+deadlineimpl(Eface arg, uintptr seq, bool read, bool write)
{
PollDesc *pd;
- uint32 seq;
G *rg, *wg;
- USED(now);
pd = (PollDesc*)arg.data;
- // This is the seq when the timer was set.
- // If it's stale, ignore the timer event.
- seq = (uintptr)arg.type;
rg = wg = nil;
runtime_lock(pd);
+ // Seq arg is seq when the timer was set.
+ // If it's stale, ignore the timer event.
if(seq != pd->seq) {
// The descriptor was reused or timers were reset.
runtime_unlock(pd);
@@ -429,21 +429,21 @@ deadlineimpl(int64 now, Eface arg, bool read, bool write)
}
static void
-deadline(int64 now, Eface arg)
+deadline(Eface arg, uintptr seq)
{
- deadlineimpl(now, arg, true, true);
+ deadlineimpl(arg, seq, true, true);
}
static void
-readDeadline(int64 now, Eface arg)
+readDeadline(Eface arg, uintptr seq)
{
- deadlineimpl(now, arg, true, false);
+ deadlineimpl(arg, seq, true, false);
}
static void
-writeDeadline(int64 now, Eface arg)
+writeDeadline(Eface arg, uintptr seq)
{
- deadlineimpl(now, arg, false, true);
+ deadlineimpl(arg, seq, false, true);
}
static PollDesc*
diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c
index 496e77b..6e0d164 100644
--- a/libgo/runtime/runtime.c
+++ b/libgo/runtime/runtime.c
@@ -59,8 +59,8 @@ runtime_gotraceback(bool *crash)
static int32 argc;
static byte** argv;
-extern Slice os_Args __asm__ (GOSYM_PREFIX "os.Args");
-extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs");
+static Slice args;
+Slice envs;
void (*runtime_sysargs)(int32, uint8**);
@@ -92,9 +92,9 @@ runtime_goargs(void)
s = runtime_malloc(argc*sizeof s[0]);
for(i=0; i<argc; i++)
s[i] = runtime_gostringnocopy((const byte*)argv[i]);
- os_Args.__values = (void*)s;
- os_Args.__count = argc;
- os_Args.__capacity = argc;
+ args.__values = (void*)s;
+ args.__count = argc;
+ args.__capacity = argc;
}
void
@@ -109,9 +109,26 @@ runtime_goenvs_unix(void)
s = runtime_malloc(n*sizeof s[0]);
for(i=0; i<n; i++)
s[i] = runtime_gostringnocopy(argv[argc+1+i]);
- syscall_Envs.__values = (void*)s;
- syscall_Envs.__count = n;
- syscall_Envs.__capacity = n;
+ envs.__values = (void*)s;
+ envs.__count = n;
+ envs.__capacity = n;
+}
+
+// Called from the syscall package.
+Slice runtime_envs(void) __asm__ (GOSYM_PREFIX "syscall.runtime_envs");
+
+Slice
+runtime_envs()
+{
+ return envs;
+}
+
+Slice os_runtime_args(void) __asm__ (GOSYM_PREFIX "os.runtime_args");
+
+Slice
+os_runtime_args()
+{
+ return args;
}
int32
@@ -127,8 +144,8 @@ runtime_atoi(const byte *p)
static struct root_list runtime_roots =
{ nil,
- { { &syscall_Envs, sizeof syscall_Envs },
- { &os_Args, sizeof os_Args },
+ { { &envs, sizeof envs },
+ { &args, sizeof args },
{ nil, 0 } },
};
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index c96290a..1f1358a 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -400,7 +400,7 @@ struct Timers
// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
struct Timer
{
- int32 i; // heap index
+ intgo i; // heap index
// Timer wakes up at when, and then at when+period, ... (period > 0 only)
// each time calling f(now, arg) in the timer goroutine, so f must be
@@ -409,6 +409,7 @@ struct Timer
int64 period;
FuncVal *fv;
Eface arg;
+ uintptr seq;
};
// Lock-free stack node.
@@ -774,8 +775,6 @@ void runtime_printany(Eface)
__asm__ (GOSYM_PREFIX "runtime.Printany");
void runtime_newTypeAssertionError(const String*, const String*, const String*, const String*, Eface*)
__asm__ (GOSYM_PREFIX "runtime.NewTypeAssertionError");
-void runtime_newErrorString(String, Eface*)
- __asm__ (GOSYM_PREFIX "runtime.NewErrorString");
void runtime_newErrorCString(const char*, Eface*)
__asm__ (GOSYM_PREFIX "runtime.NewErrorCString");
diff --git a/libgo/runtime/runtime1.goc b/libgo/runtime/runtime1.goc
index e643965..6d8f09a 100644
--- a/libgo/runtime/runtime1.goc
+++ b/libgo/runtime/runtime1.goc
@@ -74,3 +74,16 @@ func sync.runtime_procPin() (p int) {
func sync.runtime_procUnpin() {
runtime_m()->locks--;
}
+
+func sync_atomic.runtime_procPin() (p int) {
+ M *mp;
+
+ mp = runtime_m();
+ // Disable preemption.
+ mp->locks++;
+ p = mp->p->id;
+}
+
+func sync_atomic.runtime_procUnpin() {
+ runtime_m()->locks--;
+}
diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc
index cb13bbf..ee24b9c 100644
--- a/libgo/runtime/time.goc
+++ b/libgo/runtime/time.goc
@@ -66,9 +66,9 @@ static void siftdown(int32);
// Ready the goroutine e.data.
static void
-ready(int64 now, Eface e)
+ready(Eface e, uintptr seq)
{
- USED(now);
+ USED(seq);
runtime_ready(e.__object);
}
@@ -91,6 +91,7 @@ runtime_tsleep(int64 ns, const char *reason)
t.period = 0;
t.fv = &readyv;
t.arg.__object = g;
+ t.seq = 0;
runtime_lock(&timers);
addtimer(&t);
runtime_parkunlock(&timers, reason);
@@ -203,8 +204,9 @@ timerproc(void* dummy __attribute__ ((unused)))
int64 delta, now;
Timer *t;
FuncVal *fv;
- void (*f)(int64, Eface);
+ void (*f)(Eface, uintptr);
Eface arg;
+ uintptr seq;
for(;;) {
runtime_lock(&timers);
@@ -233,9 +235,10 @@ timerproc(void* dummy __attribute__ ((unused)))
fv = t->fv;
f = (void*)t->fv->fn;
arg = t->arg;
+ seq = t->seq;
runtime_unlock(&timers);
__go_set_closure(fv);
- f(now, arg);
+ f(arg, seq);
// clear f and arg to avoid leak while sleeping for next timer
f = nil;