@@ -88,60 +88,6 @@
if (add_to_globals)
this->add_named_object(no);
- // Typeof.
- Type* empty_interface = Type::make_empty_interface_type(bloc);
- Typed_identifier_list* parameters = new Typed_identifier_list;
- parameters->push_back(Typed_identifier("i", empty_interface, bloc));
- results = new Typed_identifier_list;
- results->push_back(Typed_identifier("", empty_interface, bloc));
- fntype = Type::make_function_type(NULL, parameters, results, bloc);
- no = bindings->add_function_declaration("Typeof", package, fntype, bloc);
- if (add_to_globals)
- this->add_named_object(no);
-
- // Reflect.
- parameters = new Typed_identifier_list;
- parameters->push_back(Typed_identifier("it", empty_interface, bloc));
- results = new Typed_identifier_list;
- results->push_back(Typed_identifier("", empty_interface, bloc));
- results->push_back(Typed_identifier("", pointer_type, bloc));
- fntype = Type::make_function_type(NULL, parameters, results, bloc);
- no = bindings->add_function_declaration("Reflect", package, fntype, bloc);
- if (add_to_globals)
- this->add_named_object(no);
-
- // Unreflect.
- parameters = new Typed_identifier_list;
- parameters->push_back(Typed_identifier("typ", empty_interface, bloc));
- parameters->push_back(Typed_identifier("addr", pointer_type, bloc));
- results = new Typed_identifier_list;
- results->push_back(Typed_identifier("", empty_interface, bloc));
- fntype = Type::make_function_type(NULL, parameters, results, bloc);
- no = bindings->add_function_declaration("Unreflect", package, fntype, bloc);
- if (add_to_globals)
- this->add_named_object(no);
-
- // New.
- parameters = new Typed_identifier_list;
- parameters->push_back(Typed_identifier("typ", empty_interface, bloc));
- results = new Typed_identifier_list;
- results->push_back(Typed_identifier("", pointer_type, bloc));
- fntype = Type::make_function_type(NULL, parameters, results, bloc);
- no = bindings->add_function_declaration("New", package, fntype, bloc);
- if (add_to_globals)
- this->add_named_object(no);
-
- // NewArray.
- parameters = new Typed_identifier_list;
- parameters->push_back(Typed_identifier("typ", empty_interface, bloc));
- parameters->push_back(Typed_identifier("n", int_type, bloc));
- results = new Typed_identifier_list;
- results->push_back(Typed_identifier("", pointer_type, bloc));
- fntype = Type::make_function_type(NULL, parameters, results, bloc);
- no = bindings->add_function_declaration("NewArray", package, fntype, bloc);
- if (add_to_globals)
- this->add_named_object(no);
-
if (!this->imported_unsafe_)
{
go_imported_unsafe();
@@ -1,4 +1,4 @@
-52ba9506bd99
+43cf9b39b647
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
@@ -225,7 +225,6 @@
$(exp_inotify_gox) \
exp/norm.gox \
exp/proxy.gox \
- exp/signal.gox \
exp/terminal.gox \
exp/types.gox \
exp/utf8string.gox
@@ -325,6 +324,7 @@
toolexeclibgoos_DATA = \
os/exec.gox \
+ os/signal.gox \
os/user.gox
toolexeclibgopathdir = $(toolexeclibgodir)/path
@@ -352,8 +352,7 @@
toolexeclibgotesting_DATA = \
testing/iotest.gox \
- testing/quick.gox \
- testing/script.gox
+ testing/quick.gox
toolexeclibgotextdir = $(toolexeclibgodir)/text
@@ -398,6 +397,7 @@
runtime/go-byte-array-to-string.c \
runtime/go-breakpoint.c \
runtime/go-caller.c \
+ runtime/go-callers.c \
runtime/go-can-convert-interface.c \
runtime/go-cgo.c \
runtime/go-check-interface.c \
@@ -428,7 +428,6 @@
runtime/go-panic.c \
runtime/go-print.c \
runtime/go-recover.c \
- runtime/go-reflect.c \
runtime/go-reflect-call.c \
runtime/go-reflect-map.c \
runtime/go-rune.c \
@@ -450,7 +449,6 @@
runtime/go-type-string.c \
runtime/go-typedesc-equal.c \
runtime/go-typestring.c \
- runtime/go-unreflect.c \
runtime/go-unsafe-new.c \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
@@ -468,6 +466,7 @@
runtime/msize.c \
runtime/proc.c \
runtime/runtime.c \
+ runtime/signal_unix.c \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
@@ -509,7 +508,7 @@
mv -f $@.tmp $@
sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
- ./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
+ ./goc2c --gcc --go-prefix libgo_os $< > $@.tmp
mv -f $@.tmp $@
time.c: $(srcdir)/runtime/time.goc goc2c
@@ -526,7 +525,8 @@
go_bytes_files = \
go/bytes/buffer.go \
go/bytes/bytes.go \
- go/bytes/bytes_decl.go
+ go/bytes/bytes_decl.go \
+ go/bytes/reader.go
go_bytes_c_files = \
go/bytes/indexbyte.c
@@ -784,9 +784,7 @@
$(go_os_stat_file) \
go/os/str.go \
$(go_os_sys_file) \
- go/os/time.go \
- go/os/types.go \
- signal_unix.go
+ go/os/types.go
go_path_files = \
go/path/match.go \
@@ -811,7 +809,6 @@
go/runtime/error.go \
go/runtime/extern.go \
go/runtime/mem.go \
- go/runtime/sig.go \
go/runtime/softfloat64.go \
go/runtime/type.go \
version.go
@@ -1103,8 +1100,6 @@
go/exp/proxy/per_host.go \
go/exp/proxy/proxy.go \
go/exp/proxy/socks5.go
-go_exp_signal_files = \
- go/exp/signal/signal.go
go_exp_terminal_files = \
go/exp/terminal/terminal.go \
go/exp/terminal/util.go
@@ -1302,6 +1297,10 @@
go/os/exec/exec.go \
go/os/exec/lp_unix.go
+go_os_signal_files = \
+ go/os/signal/signal.go \
+ go/os/signal/signal_unix.go
+
go_os_user_files = \
go/os/user/user.go \
go/os/user/lookup_unix.go
@@ -1352,8 +1351,6 @@
go/testing/iotest/writer.go
go_testing_quick_files = \
go/testing/quick/quick.go
-go_testing_script_files = \
- go/testing/script/script.go
go_text_scanner_files = \
go/text/scanner/scanner.go
@@ -1529,6 +1526,7 @@
syscall_arch.go
go_syscall_c_files = \
go/syscall/errno.c \
+ go/syscall/signame.c \
$(syscall_wait_c_file)
libcalls.go: s-libcalls; @true
@@ -1667,7 +1665,6 @@
exp/html.lo \
exp/norm.lo \
exp/proxy.lo \
- exp/signal.lo \
exp/terminal.lo \
exp/types.lo \
exp/utf8string.lo \
@@ -1712,6 +1709,7 @@
old/regexp.lo \
old/template.lo \
$(os_lib_inotify_lo) \
+ os/signal.lo \
os/user.lo \
path/filepath.lo \
regexp/syntax.lo \
@@ -1722,6 +1720,7 @@
sync/atomic_c.lo \
syscall/syscall.lo \
syscall/errno.lo \
+ syscall/signame.lo \
syscall/wait.lo \
text/scanner.lo \
text/tabwriter.lo \
@@ -1730,7 +1729,6 @@
testing/testing.lo \
testing/iotest.lo \
testing/quick.lo \
- testing/script.lo \
unicode/utf16.lo \
unicode/utf8.lo
@@ -1986,10 +1984,6 @@
@$(CHECK)
.PHONY: os/check
-signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
- $(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
- mv -f $@.tmp $@
-
@go_include@ path/path.lo.dep
path/path.lo.dep: $(go_path_files)
$(BUILDDEPS)
@@ -2599,16 +2593,6 @@
@$(CHECK)
.PHONY: exp/proxy/check
-@go_include@ exp/signal.lo.dep
-exp/signal.lo.dep: $(go_exp_signal_files)
- $(BUILDDEPS)
-exp/signal.lo: $(go_exp_signal_files)
- $(BUILDPACKAGE)
-exp/signal/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/signal
- @$(CHECK)
-.PHONY: exp/signal/check
-
@go_include@ exp/terminal.lo.dep
exp/terminal.lo.dep: $(go_exp_terminal_files)
$(BUILDDEPS)
@@ -3060,6 +3044,16 @@
@$(CHECK)
.PHONY: os/exec/check
+@go_include@ os/signal.lo.dep
+os/signal.lo.dep: $(go_os_signal_files)
+ $(BUILDDEPS)
+os/signal.lo: $(go_os_signal_files)
+ $(BUILDPACKAGE)
+os/signal/check: $(CHECK_DEPS)
+ @$(MKDIR_P) os/signal
+ @$(CHECK)
+.PHONY: os/signal/check
+
@go_include@ os/user.lo.dep
os/user.lo.dep: $(go_os_user_files)
$(BUILDDEPS)
@@ -3171,16 +3165,6 @@
@$(CHECK)
.PHONY: testing/quick/check
-@go_include@ testing/script.lo.dep
-testing/script.lo.dep: $(go_testing_script_files)
- $(BUILDDEPS)
-testing/script.lo: $(go_testing_script_files)
- $(BUILDPACKAGE)
-testing/script/check: $(CHECK_DEPS)
- @$(MKDIR_P) testing/script
- @$(CHECK)
-.PHONY: testing/script/check
-
@go_include@ unicode/utf16.lo.dep
unicode/utf16.lo.dep: $(go_unicode_utf16_files)
$(BUILDDEPS)
@@ -3208,6 +3192,8 @@
$(BUILDPACKAGE)
syscall/errno.lo: go/syscall/errno.c
$(LTCOMPILE) -c -o $@ $<
+syscall/signame.lo: go/syscall/signame.c
+ $(LTCOMPILE) -c -o $@ $<
syscall/wait.lo: go/syscall/wait.c
$(LTCOMPILE) -c -o $@ $<
@@ -3384,8 +3370,6 @@
$(BUILDGOX)
exp/proxy.gox: exp/proxy.lo
$(BUILDGOX)
-exp/signal.gox: exp/signal.lo
- $(BUILDGOX)
exp/terminal.gox: exp/terminal.lo
$(BUILDGOX)
exp/types.gox: exp/types.lo
@@ -3486,6 +3470,8 @@
os/exec.gox: os/exec.lo
$(BUILDGOX)
+os/signal.gox: os/signal.lo
+ $(BUILDGOX)
os/user.gox: os/user.lo
$(BUILDGOX)
@@ -3516,8 +3502,6 @@
$(BUILDGOX)
testing/quick.gox: testing/quick.lo
$(BUILDGOX)
-testing/script.gox: testing/script.lo
- $(BUILDGOX)
unicode/utf16.gox: unicode/utf16.lo
$(BUILDGOX)
@@ -3605,7 +3589,6 @@
$(exp_inotify_check) \
exp/norm/check \
exp/proxy/check \
- exp/signal/check \
exp/terminal/check \
exp/utf8string/check \
html/template/check \
@@ -3635,6 +3618,7 @@
net/http/check \
net/http/cgi/check \
net/http/fcgi/check \
+ net/http/httptest/check \
net/http/httputil/check \
net/mail/check \
net/rpc/check \
@@ -3646,6 +3630,7 @@
old/regexp/check \
old/template/check \
os/exec/check \
+ os/signal/check \
os/user/check \
path/filepath/check \
regexp/syntax/check \
@@ -3655,7 +3640,6 @@
text/template/check \
text/template/parse/check \
testing/quick/check \
- testing/script/check \
unicode/utf16/check \
unicode/utf8/check
@@ -163,7 +163,7 @@
done
done
-runtime="chan.c cpuprof.c goc2c.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
+runtime="chan.c cpuprof.c goc2c.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
for f in $runtime; do
merge_c $f $f
done
@@ -172,7 +172,7 @@
# The signal numbers.
grep '^const _SIG[^_]' gen-sysinfo.go | \
grep -v '^const _SIGEV_' | \
- sed -e 's/^\(const \)_\(SIG[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+ sed -e 's/^\(const \)_\(SIG[^= ]*\)\(.*\)$/\1\2 = Signal(_\2)/' >> ${OUT}
# The syscall numbers. We force the names to upper case.
grep '^const _SYS_' gen-sysinfo.go | \
@@ -662,6 +662,10 @@
if(size > 1)
n = size-1;
+ // allocate all the memory we need in a single allocation
+ // start with Select with size cases
+ // then lockorder with size entries
+ // then pollorder with size entries
sel = runtime_mal(sizeof(*sel) +
n*sizeof(sel->scase[0]) +
size*sizeof(sel->lockorder[0]) +
@@ -8,6 +8,7 @@
#include "go-assert.h"
#include "go-panic.h"
#include "interface.h"
+#include "runtime.h"
/* This is called by the compiler to implement a type assertion from
one interface type to another. This returns the value that should
@@ -26,14 +27,8 @@
/* A type assertion is not permitted with a nil interface. */
- newTypeAssertionError (NULL,
- NULL,
- lhs_descriptor,
- NULL,
- NULL,
- lhs_descriptor->__reflection,
- NULL,
- &panic_arg);
+ runtime_newTypeAssertionError (NULL, NULL, lhs_descriptor->__reflection,
+ NULL, &panic_arg);
__go_panic (panic_arg);
}
@@ -0,0 +1,57 @@
+/* go-callers.c -- get callers for Go.
+
+ Copyright 2012 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 "unwind.h"
+
+#include "runtime.h"
+
+/* Argument passed to backtrace function. */
+
+struct callers_data
+{
+ int skip;
+ uintptr *pcbuf;
+ int index;
+ int max;
+};
+
+static _Unwind_Reason_Code
+backtrace (struct _Unwind_Context *context, void *varg)
+{
+ struct callers_data *arg = (struct callers_data *) varg;
+ uintptr pc;
+
+ pc = _Unwind_GetIP (context);
+
+ /* FIXME: If PC is in the __morestack routine, we should ignore
+ it. */
+
+ if (arg->skip > 0)
+ --arg->skip;
+ else if (arg->index >= arg->max)
+ return _URC_END_OF_STACK;
+ else
+ {
+ arg->pcbuf[arg->index] = pc;
+ ++arg->index;
+ }
+ return _URC_NO_REASON;
+}
+
+int32
+runtime_callers (int32 skip, uintptr *pcbuf, int32 m)
+{
+ struct callers_data arg;
+
+ arg.skip = skip;
+ arg.pcbuf = pcbuf;
+ arg.index = 0;
+ arg.max = m;
+ _Unwind_Backtrace (backtrace, &arg);
+ return arg.index;
+}
@@ -6,6 +6,7 @@
#include "go-panic.h"
#include "interface.h"
+#include "runtime.h"
/* Check that an interface type matches for a conversion to a
non-interface type. This panics if the types are bad. The actual
@@ -21,8 +22,8 @@
{
struct __go_empty_interface panic_arg;
- newTypeAssertionError(NULL, NULL, lhs_descriptor, NULL, NULL,
- lhs_descriptor->__reflection, NULL, &panic_arg);
+ runtime_newTypeAssertionError(NULL, NULL, lhs_descriptor->__reflection,
+ NULL, &panic_arg);
__go_panic(panic_arg);
}
@@ -35,12 +36,10 @@
{
struct __go_empty_interface panic_arg;
- newTypeAssertionError(rhs_inter_descriptor, rhs_descriptor,
- lhs_descriptor,
- rhs_inter_descriptor->__reflection,
- rhs_descriptor->__reflection,
- lhs_descriptor->__reflection,
- NULL, &panic_arg);
+ runtime_newTypeAssertionError(rhs_inter_descriptor->__reflection,
+ rhs_descriptor->__reflection,
+ lhs_descriptor->__reflection,
+ NULL, &panic_arg);
__go_panic(panic_arg);
}
}
@@ -8,6 +8,7 @@
#include "go-assert.h"
#include "go-panic.h"
#include "interface.h"
+#include "runtime.h"
/* This is called when converting one interface type into another
interface type. LHS_DESCRIPTOR is the type descriptor of the
@@ -55,14 +56,10 @@
if (may_fail)
return NULL;
- newTypeAssertionError (NULL,
- rhs_descriptor,
- lhs_descriptor,
- NULL,
- rhs_descriptor->__reflection,
- lhs_descriptor->__reflection,
- lhs_methods[0].__name,
- &panic_arg);
+ runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection,
+ lhs_descriptor->__reflection,
+ lhs_methods[0].__name,
+ &panic_arg);
__go_panic (panic_arg);
}
@@ -100,14 +97,9 @@
if (may_fail)
return NULL;
- newTypeAssertionError (NULL,
- rhs_descriptor,
- lhs_descriptor,
- NULL,
- rhs_descriptor->__reflection,
- lhs_descriptor->__reflection,
- p_lhs_method->__name,
- &panic_arg);
+ runtime_newTypeAssertionError (NULL, rhs_descriptor->__reflection,
+ lhs_descriptor->__reflection,
+ p_lhs_method->__name, &panic_arg);
__go_panic (panic_arg);
}
@@ -40,7 +40,7 @@
int
main (int argc, char **argv)
{
- runtime_initsig (0);
+ runtime_initsig ();
runtime_args (argc, (byte **) argv);
runtime_osinit ();
runtime_schedinit ();
@@ -27,7 +27,7 @@
fprintf (stderr, "\t");
}
fprintf (stderr, "panic: ");
- printany (p->__arg);
+ runtime_printany (p->__arg);
if (p->__was_recovered)
fprintf (stderr, " [recovered]");
fputc ('\n', stderr);
@@ -40,23 +40,4 @@
extern void __go_unwind_stack (void);
-/* Functions defined in libgo/go/runtime/error.go. */
-
-extern void newTypeAssertionError(const struct __go_type_descriptor *pt1,
- const struct __go_type_descriptor *pt2,
- const struct __go_type_descriptor *pt3,
- const struct __go_string *ps1,
- const struct __go_string *ps2,
- const struct __go_string *ps3,
- const struct __go_string *pmeth,
- struct __go_empty_interface *ret)
- __asm__ ("libgo_runtime.runtime.NewTypeAssertionError");
-
-extern void runtime_newErrorString(struct __go_string,
- struct __go_empty_interface *)
- __asm__ ("libgo_runtime.runtime.NewErrorString");
-
-extern void printany(struct __go_empty_interface)
- __asm__ ("libgo_runtime.runtime.Printany");
-
#endif /* !defined(LIBGO_GO_PANIC_H) */
@@ -1,192 +0,0 @@
-/* go-reflect.c -- implement unsafe.Reflect and unsafe.Typeof for Go.
-
- Copyright 2009 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 <stdlib.h>
-#include <stdint.h>
-
-#include "runtime.h"
-#include "interface.h"
-#include "go-alloc.h"
-#include "go-string.h"
-#include "go-type.h"
-
-/* For field alignment. */
-
-struct field_align
-{
- char c;
- struct __go_type_descriptor *p;
-};
-
-/* The type descriptors in the runtime package. */
-
-extern const struct __go_type_descriptor ptr_bool_descriptor
- asm ("__go_td_pN30_libgo_runtime.runtime.BoolType");
-extern const struct __go_type_descriptor ptr_float_descriptor
- asm ("__go_td_pN31_libgo_runtime.runtime.FloatType");
-extern const struct __go_type_descriptor ptr_complex_descriptor
- asm ("__go_td_pN33_libgo_runtime.runtime.ComplexType");
-extern const struct __go_type_descriptor ptr_int_descriptor
- asm ("__go_td_pN29_libgo_runtime.runtime.IntType");
-extern const struct __go_type_descriptor ptr_uint_descriptor
- asm ("__go_td_pN30_libgo_runtime.runtime.UintType");
-extern const struct __go_type_descriptor ptr_string_descriptor
- asm ("__go_td_pN32_libgo_runtime.runtime.StringType");
-extern const struct __go_type_descriptor ptr_unsafe_pointer_decriptor
- asm ("__go_td_pN39_libgo_runtime.runtime.UnsafePointerType");
-extern const struct __go_type_descriptor ptr_array_descriptor
- asm ("__go_td_pN31_libgo_runtime.runtime.ArrayType");
-extern const struct __go_type_descriptor ptr_slice_descriptor
- asm ("__go_td_pN31_libgo_runtime.runtime.SliceType");
-extern const struct __go_type_descriptor ptr_chan_descriptor
- asm ("__go_td_pN30_libgo_runtime.runtime.ChanType");
-extern const struct __go_type_descriptor ptr_func_descriptor
- asm ("__go_td_pN30_libgo_runtime.runtime.FuncType");
-extern const struct __go_type_descriptor ptr_interface_descriptor
- asm ("__go_td_pN35_libgo_runtime.runtime.InterfaceType");
-extern const struct __go_type_descriptor ptr_map_descriptor
- asm ("__go_td_pN29_libgo_runtime.runtime.MapType");
-extern const struct __go_type_descriptor ptr_ptr_descriptor
- asm ("__go_td_pN29_libgo_runtime.runtime.PtrType");
-extern const struct __go_type_descriptor ptr_struct_descriptor
- asm ("__go_td_pN32_libgo_runtime.runtime.StructType");
-
-const struct __go_type_descriptor *
-get_descriptor (int code)
-{
- switch (code & GO_CODE_MASK)
- {
- case GO_BOOL:
- return &ptr_bool_descriptor;
- case GO_FLOAT32:
- case GO_FLOAT64:
- return &ptr_float_descriptor;
- case GO_COMPLEX64:
- case GO_COMPLEX128:
- return &ptr_complex_descriptor;
- case GO_INT16:
- case GO_INT32:
- case GO_INT64:
- case GO_INT8:
- case GO_INT:
- return &ptr_int_descriptor;
- case GO_UINT16:
- case GO_UINT32:
- case GO_UINT64:
- case GO_UINT8:
- case GO_UINTPTR:
- case GO_UINT:
- return &ptr_uint_descriptor;
- case GO_STRING:
- return &ptr_string_descriptor;
- case GO_UNSAFE_POINTER:
- return &ptr_unsafe_pointer_decriptor;
- case GO_ARRAY:
- return &ptr_array_descriptor;
- case GO_SLICE:
- return &ptr_slice_descriptor;
- case GO_CHAN:
- return &ptr_chan_descriptor;
- case GO_FUNC:
- return &ptr_func_descriptor;
- case GO_INTERFACE:
- return &ptr_interface_descriptor;
- case GO_MAP:
- return &ptr_map_descriptor;
- case GO_PTR:
- return &ptr_ptr_descriptor;
- case GO_STRUCT:
- return &ptr_struct_descriptor;
- default:
- abort ();
- }
-}
-
-/* Implement unsafe.Reflect. */
-
-struct reflect_ret
-{
- struct __go_empty_interface rettype;
- void *addr;
-};
-
-struct reflect_ret Reflect (struct __go_empty_interface)
- asm ("libgo_unsafe.unsafe.Reflect");
-
-struct reflect_ret
-Reflect (struct __go_empty_interface e)
-{
- struct reflect_ret ret;
-
- if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0)
- runtime_panicstring ("invalid interface value");
-
- if (e.__type_descriptor == NULL)
- {
- ret.rettype.__type_descriptor = NULL;
- ret.rettype.__object = NULL;
- ret.addr = NULL;
- }
- else
- {
- size_t size;
-
- ret.rettype.__type_descriptor =
- get_descriptor (e.__type_descriptor->__code);
-
- /* This memcpy is really just an assignment of a const pointer
- to a non-const pointer. FIXME: We should canonicalize this
- pointer, so that for a given type we always return the same
- pointer. */
- __builtin_memcpy (&ret.rettype.__object, &e.__type_descriptor,
- sizeof (void *));
-
- /* Make a copy of the value. */
- size = e.__type_descriptor->__size;
- if (size <= sizeof (uint64_t))
- ret.addr = __go_alloc (sizeof (uint64_t));
- else
- ret.addr = __go_alloc (size);
- if (__go_is_pointer_type (e.__type_descriptor))
- *(void **) ret.addr = e.__object;
- else
- __builtin_memcpy (ret.addr, e.__object, size);
- }
-
- return ret;
-}
-
-/* Implement unsafe.Typeof. */
-
-struct __go_empty_interface Typeof (struct __go_empty_interface)
- asm ("libgo_unsafe.unsafe.Typeof");
-
-struct __go_empty_interface
-Typeof (const struct __go_empty_interface e)
-{
- struct __go_empty_interface ret;
-
- if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0)
- runtime_panicstring ("invalid interface value");
-
- if (e.__type_descriptor == NULL)
- {
- ret.__type_descriptor = NULL;
- ret.__object = NULL;
- }
- else
- {
- ret.__type_descriptor = get_descriptor (e.__type_descriptor->__code);
-
- /* This memcpy is really just an assignment of a const pointer
- to a non-const pointer. FIXME: We should canonicalize this
- pointer, so that for a given type we always return the same
- pointer. */
- __builtin_memcpy (&ret.__object, &e.__type_descriptor, sizeof (void *));
- }
-
- return ret;
-}
@@ -25,11 +25,11 @@
#endif
-#define C SigCatch
-#define I SigIgnore
-#define R SigRestart
-#define Q SigQueue
+#define N SigNotify
+#define K SigKill
+#define T SigThrow
#define P SigPanic
+#define D SigDefault
/* Signal actions. This collects the sigtab tables for several
different targets from the master library. SIGKILL, SIGCONT, and
@@ -38,105 +38,105 @@
SigTab runtime_sigtab[] = {
#ifdef SIGHUP
- { SIGHUP, Q + R },
+ { SIGHUP, N + K },
#endif
#ifdef SIGINT
- { SIGINT, Q + R },
+ { SIGINT, N + K },
#endif
#ifdef SIGQUIT
- { SIGQUIT, C },
+ { SIGQUIT, N + T },
#endif
#ifdef SIGILL
- { SIGILL, C },
+ { SIGILL, T },
#endif
#ifdef SIGTRAP
- { SIGTRAP, C },
+ { SIGTRAP, T },
#endif
#ifdef SIGABRT
- { SIGABRT, C },
+ { SIGABRT, N + T },
#endif
#ifdef SIGBUS
- { SIGBUS, C + P },
+ { SIGBUS, P },
#endif
#ifdef SIGFPE
- { SIGFPE, C + P },
+ { SIGFPE, P },
#endif
#ifdef SIGUSR1
- { SIGUSR1, Q + I + R },
+ { SIGUSR1, N },
#endif
#ifdef SIGSEGV
- { SIGSEGV, C + P },
+ { SIGSEGV, P },
#endif
#ifdef SIGUSR2
- { SIGUSR2, Q + I + R },
+ { SIGUSR2, N },
#endif
#ifdef SIGPIPE
- { SIGPIPE, I },
+ { SIGPIPE, N },
#endif
#ifdef SIGALRM
- { SIGALRM, Q + I + R },
+ { SIGALRM, N },
#endif
#ifdef SIGTERM
- { SIGTERM, Q + R },
+ { SIGTERM, N + K },
#endif
#ifdef SIGSTKFLT
- { SIGSTKFLT, C },
+ { SIGSTKFLT, T },
#endif
#ifdef SIGCHLD
- { SIGCHLD, Q + I + R },
+ { SIGCHLD, N },
#endif
#ifdef SIGTSTP
- { SIGTSTP, Q + I + R },
+ { SIGTSTP, N + D },
#endif
#ifdef SIGTTIN
- { SIGTTIN, Q + I + R },
+ { SIGTTIN, N + D },
#endif
#ifdef SIGTTOU
- { SIGTTOU, Q + I + R },
+ { SIGTTOU, N + D },
#endif
#ifdef SIGURG
- { SIGURG, Q + I + R },
+ { SIGURG, N },
#endif
#ifdef SIGXCPU
- { SIGXCPU, Q + I + R },
+ { SIGXCPU, N },
#endif
#ifdef SIGXFSZ
- { SIGXFSZ, Q + I + R },
+ { SIGXFSZ, N },
#endif
#ifdef SIGVTALRM
- { SIGVTALRM, Q + I + R },
+ { SIGVTALRM, N },
#endif
#ifdef SIGPROF
- { SIGPROF, Q + I + R },
+ { SIGPROF, N },
#endif
#ifdef SIGWINCH
- { SIGWINCH, Q + I + R },
+ { SIGWINCH, N },
#endif
#ifdef SIGIO
- { SIGIO, Q + I + R },
+ { SIGIO, N },
#endif
#ifdef SIGPWR
- { SIGPWR, Q + I + R },
+ { SIGPWR, N },
#endif
#ifdef SIGSYS
- { SIGSYS, C },
+ { SIGSYS, N },
#endif
#ifdef SIGEMT
- { SIGEMT, C },
+ { SIGEMT, T },
#endif
#ifdef SIGINFO
- { SIGINFO, Q + I + R },
+ { SIGINFO, N },
#endif
#ifdef SIGTHR
- { SIGTHR, Q + I + R },
+ { SIGTHR, N },
#endif
{ -1, 0 }
};
-#undef C
-#undef I
-#undef R
-#undef Q
+#undef N
+#undef K
+#undef T
#undef P
+#undef D
/* Handle a signal, for cases where we don't panic. We can split the
stack here. */
@@ -158,21 +158,24 @@
for (i = 0; runtime_sigtab[i].sig != -1; ++i)
{
struct sigaction sa;
+ SigTab *t;
- if (runtime_sigtab[i].sig != sig)
+ t = &runtime_sigtab[i];
+
+ if (t->sig != sig)
continue;
- if ((runtime_sigtab[i].flags & SigQueue) != 0)
+ if ((t->flags & SigNotify) != 0)
{
- if (__go_sigsend (sig)
- || (runtime_sigtab[sig].flags & SigIgnore) != 0)
+ if (__go_sigsend (sig))
return;
- runtime_exit (2); // SIGINT, SIGTERM, etc
}
+ if ((t->flags & SigKill) != 0)
+ runtime_exit (2);
+ if ((t->flags & SigThrow) == 0)
+ return;
- if (runtime_panicking)
- runtime_exit (2);
- runtime_panicking = 1;
+ runtime_startpanic ();
/* We should do a stack backtrace here. Until we can do that,
we reraise the signal in order to get a slightly better
@@ -227,7 +230,7 @@
sig_panic_info_handler (int sig, siginfo_t *info,
void *context __attribute__ ((unused)))
{
- if (runtime_g () == NULL)
+ if (runtime_g () == NULL || info->si_code == SI_USER)
{
sig_handler (sig);
return;
@@ -316,16 +319,6 @@
#endif /* !defined (SA_SIGINFO) */
-/* Ignore a signal. This is called on the alternate signal stack so
- it may not split the stack. */
-
-static void sig_ignore (int) __attribute__ ((no_split_stack));
-
-static void
-sig_ignore (int sig __attribute__ ((unused)))
-{
-}
-
/* A signal handler used for signals which are not going to panic.
This is called on the alternate signal stack so it may not split
the stack. */
@@ -376,100 +369,41 @@
}
}
-/* Initialize signal handling for Go. This is called when the program
- starts. */
-
void
-runtime_initsig (int32 queue)
+runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
{
struct sigaction sa;
- int i;
-
- siginit ();
+ int r;
+ SigTab *t;
memset (&sa, 0, sizeof sa);
- i = sigfillset (&sa.sa_mask);
- __go_assert (i == 0);
+ r = sigfillset (&sa.sa_mask);
+ __go_assert (r == 0);
- for (i = 0; runtime_sigtab[i].sig != -1; ++i)
+ t = &runtime_sigtab[i];
+
+ if ((t->flags & SigPanic) == 0)
{
- if (runtime_sigtab[i].flags == 0)
- continue;
- if ((runtime_sigtab[i].flags & SigQueue) != queue)
- continue;
-
- if ((runtime_sigtab[i].flags & (SigCatch | SigQueue)) != 0)
- {
- if ((runtime_sigtab[i].flags & SigPanic) == 0)
- {
- sa.sa_flags = SA_ONSTACK;
- sa.sa_handler = sig_tramp;
- }
- else
- {
-#ifdef SA_SIGINFO
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = sig_panic_info_handler;
-#else
- sa.sa_flags = 0;
- sa.sa_handler = sig_panic_handler;
-#endif
- }
- }
- else
- {
- sa.sa_flags = SA_ONSTACK;
- sa.sa_handler = sig_ignore;
- }
-
- if ((runtime_sigtab[i].flags & SigRestart) != 0)
- sa.sa_flags |= SA_RESTART;
-
- if (sigaction (runtime_sigtab[i].sig, &sa, NULL) != 0)
- __go_assert (0);
- }
-}
-
-void
-runtime_resetcpuprofiler(int32 hz)
-{
-#ifdef SIGPROF
- struct itimerval it;
- struct sigaction sa;
- int i;
-
- memset (&it, 0, sizeof it);
-
- memset (&sa, 0, sizeof sa);
- i = sigfillset (&sa.sa_mask);
- __go_assert (i == 0);
-
- if (hz == 0)
- {
- i = setitimer (ITIMER_PROF, &it, NULL);
- __go_assert (i == 0);
-
- sa.sa_handler = SIG_IGN;
- i = sigaction (SIGPROF, &sa, NULL);
- __go_assert (i == 0);
+ sa.sa_flags = SA_ONSTACK;
+ sa.sa_handler = sig_tramp;
}
else
{
- sa.sa_handler = sig_handler;
- sa.sa_flags = SA_RESTART;
- i = sigaction (SIGPROF, &sa, NULL);
- __go_assert (i == 0);
+#ifdef SA_SIGINFO
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = sig_panic_info_handler;
+#else
+ sa.sa_flags = 0;
+ sa.sa_handler = sig_panic_handler;
+#endif
+ }
- it.it_interval.tv_sec = 0;
- it.it_interval.tv_usec = 1000000 / hz;
- it.it_value = it.it_interval;
- i = setitimer (ITIMER_PROF, &it, NULL);
- __go_assert (i == 0);
- }
-#endif
+ if (restart)
+ sa.sa_flags |= SA_RESTART;
- runtime_m()->profilehz = hz;
+ if (sigaction (t->sig, &sa, NULL) != 0)
+ __go_assert (0);
}
/* Used by the os package to raise SIGPIPE. */
@@ -494,3 +428,9 @@
raise (SIGPIPE);
}
+
+void
+runtime_setprof(bool on)
+{
+ USED(on);
+}
@@ -1,34 +0,0 @@
-/* go-unreflect.c -- implement unsafe.Unreflect for Go.
-
- Copyright 2009 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 "runtime.h"
-#include "go-alloc.h"
-#include "go-type.h"
-#include "interface.h"
-
-/* Implement unsafe.Unreflect. */
-
-struct __go_empty_interface Unreflect (struct __go_empty_interface type,
- void *object)
- asm ("libgo_unsafe.unsafe.Unreflect");
-
-struct __go_empty_interface
-Unreflect (struct __go_empty_interface type, void *object)
-{
- struct __go_empty_interface ret;
-
- if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0)
- runtime_panicstring ("invalid interface value");
-
- /* FIXME: We should check __type_descriptor to verify that this is
- really a type descriptor. */
- ret.__type_descriptor = type.__object;
- if (__go_is_pointer_type (ret.__type_descriptor))
- ret.__object = *(void **) object;
- else
- ret.__object = object;
- return ret;
-}
@@ -9,15 +9,16 @@
#include "go-type.h"
#include "interface.h"
-/* Implement unsafe.New. */
+/* Implement unsafe_New, called from the reflect package. */
-void *New (struct __go_empty_interface type) asm ("libgo_unsafe.unsafe.New");
+void *unsafe_New (struct __go_empty_interface type)
+ asm ("libgo_reflect.reflect.unsafe_New");
/* The dynamic type of the argument will be a pointer to a type
descriptor. */
void *
-New (struct __go_empty_interface type)
+unsafe_New (struct __go_empty_interface type)
{
const struct __go_type_descriptor *descriptor;
@@ -9,16 +9,16 @@
#include "go-type.h"
#include "interface.h"
-/* Implement unsafe.NewArray. */
+/* Implement unsafe_NewArray, called from the reflect package. */
-void *NewArray (struct __go_empty_interface type, int n)
- asm ("libgo_unsafe.unsafe.NewArray");
+void *unsafe_NewArray (struct __go_empty_interface type, int n)
+ asm ("libgo_reflect.reflect.unsafe_NewArray");
/* The dynamic type of the argument will be a pointer to a type
descriptor. */
void *
-NewArray (struct __go_empty_interface type, int n)
+unsafe_NewArray (struct __go_empty_interface type, int n)
{
const struct __go_type_descriptor *descriptor;
@@ -279,6 +279,15 @@
runtime_sizeof_C_MStats = sizeof(MStats);
+ p = nil;
+ arena_size = 0;
+ bitmap_size = 0;
+
+ // for 64-bit build
+ USED(p);
+ USED(arena_size);
+ USED(bitmap_size);
+
runtime_InitSizes();
// Set up the allocation arena, a contiguous area of memory where
@@ -307,12 +316,13 @@
// Actually we reserve 17 GB (because the bitmap ends up being 1 GB)
// but it hardly matters: fc is not valid UTF-8 either, and we have to
// allocate 15 GB before we get that far.
+ //
+ // If this fails we fall back to the 32 bit memory mechanism
arena_size = (uintptr)(16LL<<30);
bitmap_size = arena_size / (sizeof(void*)*8/4);
p = runtime_SysReserve((void*)(0x00f8ULL<<32), bitmap_size + arena_size);
- if(p == nil)
- runtime_throw("runtime: cannot reserve arena virtual address space");
- } else {
+ }
+ if (p == nil) {
// On a 32-bit machine, we can't typically get away
// with a giant virtual address space reservation.
// Instead we map the memory information bitmap
@@ -379,8 +389,8 @@
return p;
}
- // On 64-bit, our reservation is all we have.
- if(sizeof(void*) == 8)
+ // If using 64-bit, our reservation is all we have.
+ if(sizeof(void*) == 8 && (uintptr)h->bitmap >= 0xffffffffU)
return nil;
// On 32-bit, once the reservation is gone we can
@@ -39,6 +39,22 @@
return 1;
}
+static void *
+mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset)
+{
+ void *p;
+
+ p = runtime_mmap(v, n, prot, flags, fd, offset);
+ if(p != v && addrspace_free(v, n)) {
+ // On some systems, mmap ignores v without
+ // MAP_FIXED, so retry if the address space is free.
+ if(p != MAP_FAILED)
+ runtime_munmap(p, n);
+ p = runtime_mmap(v, n, prot, flags|MAP_FIXED, fd, offset);
+ }
+ return p;
+}
+
void*
runtime_SysAlloc(uintptr n)
{
@@ -91,12 +107,6 @@
int fd = -1;
void *p;
- // On 64-bit, people with ulimit -v set complain if we reserve too
- // much address space. Instead, assume that the reservation is okay
- // and check the assumption in SysMap.
- if(sizeof(void*) == 8)
- return v;
-
#ifdef USE_DEV_ZERO
if (dev_zero == -1) {
dev_zero = open("/dev/zero", O_RDONLY);
@@ -108,10 +118,21 @@
fd = dev_zero;
#endif
+ // On 64-bit, people with ulimit -v set complain if we reserve too
+ // much address space. Instead, assume that the reservation is okay
+ // if we can reserve at least 64K and check the assumption in SysMap.
+ // Only user-mode Linux (UML) rejects these requests.
+ if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) {
+ p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
+ if (p != v)
+ return nil;
+ runtime_munmap(p, 64<<10);
+ return v;
+ }
+
p = runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
- if((uintptr)p < 4096 || -(uintptr)p < 4096) {
+ if(p == MAP_FAILED)
return nil;
- }
return p;
}
@@ -135,13 +156,10 @@
#endif
// On 64-bit, we don't actually have v reserved, so tread carefully.
- if(sizeof(void*) == 8) {
- p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
- if(p != v && addrspace_free(v, n)) {
- // On some systems, mmap ignores v without
- // MAP_FIXED, so retry if the address space is free.
- p = runtime_mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, fd, 0);
- }
+ if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) {
+ p = mmap_fixed(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
+ if(p == MAP_FAILED && errno == ENOMEM)
+ runtime_throw("runtime: out of memory");
if(p != v) {
runtime_printf("runtime: address space conflict: map(%p) = %p\n", v, p);
runtime_throw("runtime: address space conflict");
@@ -240,7 +240,7 @@
// Go interface to profile data. (Declared in extern.go)
// Assumes Go sizeof(int) == sizeof(int32)
-// Must match MemProfileRecord in extern.go.
+// Must match MemProfileRecord in debug.go.
typedef struct Record Record;
struct Record {
int64 alloc_bytes, free_bytes;
@@ -292,3 +292,28 @@
scan((byte*)&addrhash, sizeof addrhash);
scan((byte*)&addrfree, sizeof addrfree);
}
+
+// Must match ThreadProfileRecord in debug.go.
+typedef struct TRecord TRecord;
+struct TRecord {
+ uintptr stk[32];
+};
+
+func ThreadProfile(p Slice) (n int32, ok bool) {
+ TRecord *r;
+ M *first, *m;
+
+ first = runtime_atomicloadp(&runtime_allm);
+ n = 0;
+ for(m=first; m; m=m->alllink)
+ n++;
+ ok = false;
+ if(n <= p.__count) {
+ ok = true;
+ r = (TRecord*)p.__values;
+ for(m=first; m; m=m->alllink) {
+ runtime_memmove(r->stk, m->createstack, sizeof r->stk);
+ r++;
+ }
+ }
+}
@@ -536,18 +536,20 @@
static void
mcommoninit(M *m)
{
+ m->id = runtime_sched.mcount++;
+ m->fastrand = 0x49f6428aUL + m->id + runtime_cputicks();
+
+ if(m->mcache == nil)
+ m->mcache = runtime_allocmcache();
+
+ runtime_callers(1, m->createstack, nelem(m->createstack));
+
// Add to runtime_allm so garbage collector doesn't free m
// when it is just in a register or thread-local storage.
m->alllink = runtime_allm;
// runtime_Cgocalls() iterates over allm w/o schedlock,
// so we need to publish it safely.
- runtime_atomicstorep((void**)&runtime_allm, m);
-
- m->id = runtime_sched.mcount++;
- m->fastrand = 0x49f6428aUL + m->id + runtime_cputicks();
-
- if(m->mcache == nil)
- m->mcache = runtime_allocmcache();
+ runtime_atomicstorep(&runtime_allm, m);
}
// Try to increment mcpu. Report whether succeeded.
@@ -17,10 +17,10 @@
t = e.__type_descriptor;
if(t == nil) {
// explicit conversions require non-nil interface value.
- newTypeAssertionError(nil, nil, inter,
+ runtime_newTypeAssertionError(
nil, nil, inter->__reflection,
nil, &err);
- __go_panic(err);
+ runtime_panic(err);
}
ret->__object = e.__object;
ret->__methods = __go_convert_interface(inter, t);
@@ -174,6 +174,7 @@
MCache *mcache;
G* lockedg;
G* idleg;
+ uintptr createstack[32]; // Stack that created this thread.
M* nextwaitm; // next M waiting for lock
uintptr waitsema; // semaphore for parking on locks
uint32 waitsemacount;
@@ -187,13 +188,17 @@
};
enum
{
- SigCatch = 1<<0,
- SigIgnore = 1<<1,
- SigRestart = 1<<2,
- SigQueue = 1<<3,
- SigPanic = 1<<4,
+ SigNotify = 1<<0, // let signal.Notify have signal, even if from kernel
+ SigKill = 1<<1, // if signal.Notify doesn't take it, exit quietly
+ SigThrow = 1<<2, // if signal.Notify doesn't take it, exit loudly
+ SigPanic = 1<<3, // if the signal is from the kernel, panic
+ SigDefault = 1<<4, // if the signal isn't explicitly requested, don't monitor it
};
+#ifndef NSIG
+#define NSIG 32
+#endif
+
/* Macros. */
#ifdef GOOS_windows
@@ -271,7 +276,7 @@
void runtime_panicstring(const char*) __attribute__ ((noreturn));
void* runtime_mal(uintptr);
void runtime_schedinit(void);
-void runtime_initsig(int32);
+void runtime_initsig(void);
String runtime_gostringnocopy(const byte*);
void* runtime_mstart(void*);
G* runtime_malg(int32, byte**, size_t*);
@@ -285,6 +290,7 @@
void runtime_exitsyscall(void) __asm__("libgo_syscall.syscall.exitsyscall");
void siginit(void);
bool __go_sigsend(int32 sig);
+int32 runtime_callers(int32, uintptr*, int32);
int64 runtime_nanotime(void);
int64 runtime_cputicks(void);
@@ -336,9 +342,25 @@
void runtime_futexwakeup(uint32*, uint32);
/*
+ * low level C-called
+ */
+#define runtime_mmap mmap
+#define runtime_munmap munmap
+#define runtime_madvise madvise
+#define runtime_memclr(buf, size) __builtin_memset((buf), 0, (size))
+
+#ifdef __rtems__
+void __wrap_rtems_task_variable_add(void **);
+#endif
+
+/*
* runtime go-called
*/
void runtime_panic(Eface);
+struct __go_func_type;
+void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
+ void **, void **)
+ asm ("libgo_reflect.reflect.call");
/* Functions. */
#define runtime_panic __go_panic
@@ -374,29 +396,40 @@
void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
void runtime_usleep(uint32);
+/*
+ * runtime c-called (but written in Go)
+ */
+void runtime_newError(String, Eface*);
+void runtime_printany(Eface)
+ __asm__("libgo_runtime.runtime.Printany");
+void runtime_newTypeAssertionError(const String*, const String*, const String*, const String*, Eface*)
+ __asm__("libgo_runtime.runtime.NewTypeAssertionError");
+void runtime_newErrorString(String, Eface*)
+ __asm__("libgo_runtime.runtime.NewErrorString");
+
+/*
+ * wrapped for go users
+ */
void runtime_semacquire(uint32 volatile *);
void runtime_semrelease(uint32 volatile *);
+String runtime_signame(int32 sig);
int32 runtime_gomaxprocsfunc(int32 n);
void runtime_procyield(uint32);
void runtime_osyield(void);
void runtime_LockOSThread(void) __asm__("libgo_runtime.runtime.LockOSThread");
void runtime_UnlockOSThread(void) __asm__("libgo_runtime.runtime.UnlockOSThread");
-/*
- * low level C-called
- */
-#define runtime_mmap mmap
-#define runtime_munmap munmap
-#define runtime_madvise madvise
-#define runtime_memclr(buf, size) __builtin_memset((buf), 0, (size))
-
-struct __go_func_type;
-void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
- void **, void **)
- asm ("libgo_reflect.reflect.call");
-
-#ifdef __rtems__
-void __wrap_rtems_task_variable_add(void **);
-#endif
+// If appropriate, ask the operating system to control whether this
+// thread should receive profiling signals. This is only necessary on OS X.
+// An operating system should not deliver a profiling signal to a
+// thread that is not actually executing (what good is that?), but that's
+// what OS X prefers to do. When profiling is turned on, we mask
+// away the profiling signal when threads go to sleep, so that OS X
+// is forced to deliver the signal to a thread that's actually running.
+// This is a no-op on other systems.
+void runtime_setprof(bool);
void runtime_time_scan(void (*)(byte*, int64));
+
+void runtime_setsig(int32, bool, bool);
+#define runtime_setitimer setitimer
@@ -0,0 +1,64 @@
+// Copyright 2012 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.
+
+// +build darwin freebsd linux openbsd netbsd
+
+#include <sys/time.h>
+
+#include "runtime.h"
+#include "defs.h"
+
+extern SigTab runtime_sigtab[];
+
+void
+runtime_initsig(void)
+{
+ int32 i;
+ SigTab *t;
+
+ // First call: basic setup.
+ for(i = 0; runtime_sigtab[i].sig != -1; i++) {
+ t = &runtime_sigtab[i];
+ if((t->flags == 0) || (t->flags & SigDefault))
+ continue;
+ runtime_setsig(i, false, true);
+ }
+}
+
+void
+runtime_sigenable(uint32 sig)
+{
+ int32 i;
+ SigTab *t;
+
+ for(i = 0; runtime_sigtab[i].sig != -1; i++) {
+ // ~0 means all signals.
+ if(~sig == 0 || runtime_sigtab[i].sig == (int32)sig) {
+ t = &runtime_sigtab[i];
+ if(t->flags & SigDefault) {
+ runtime_setsig(i, false, true);
+ t->flags &= ~SigDefault; // make this idempotent
+ }
+ }
+ }
+}
+
+void
+runtime_resetcpuprofiler(int32 hz)
+{
+ struct itimerval it;
+
+ runtime_memclr((byte*)&it, sizeof it);
+ if(hz == 0) {
+ runtime_setitimer(ITIMER_PROF, &it, nil);
+ runtime_setprof(false);
+ } else {
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 1000000 / hz;
+ it.it_value = it.it_interval;
+ runtime_setitimer(ITIMER_PROF, &it, nil);
+ runtime_setprof(true);
+ }
+ runtime_m()->profilehz = hz;
+}
@@ -11,7 +11,7 @@
//
// Ownership for sig.Note passes back and forth between
// the signal handler and the signal goroutine in rounds.
-// The initial state is that sig.note is cleared (setup by siginit).
+// The initial state is that sig.note is cleared (setup by signal_enable).
// At the beginning of each round, mask == 0.
// The round goes through three stages:
//
@@ -36,7 +36,7 @@
// ownership by returning from notesleep (caused by the notewakeup)
// and gives up ownership by clearing mask.
-package runtime
+package signal
#include "config.h"
#include "runtime.h"
#include "arch.h"
@@ -45,33 +45,29 @@
static struct {
Note;
- uint32 mask;
+ uint32 mask[(NSIG+31)/32];
+ uint32 wanted[(NSIG+31)/32];
+ uint32 kick;
bool inuse;
} sig;
-void
-siginit(void)
-{
- runtime_noteclear(&sig);
-}
-
// Called from sighandler to send a signal back out of the signal handling thread.
bool
__go_sigsend(int32 s)
{
uint32 bit, mask;
- if(!sig.inuse)
+ if(!sig.inuse || s < 0 || (size_t)s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31))))
return false;
- bit = 1 << s;
+ bit = 1 << (s&31);
for(;;) {
- mask = sig.mask;
+ mask = sig.mask[s/32];
if(mask & bit)
break; // signal already in queue
- if(runtime_cas(&sig.mask, mask, mask|bit)) {
+ if(runtime_cas(&sig.mask[s/32], mask, mask|bit)) {
// Added to queue.
- // Only send a wakeup for the first signal in each round.
- if(mask == 0)
+ // Only send a wakeup if the receiver needs a kick.
+ if(runtime_cas(&sig.kick, 1, 0))
runtime_notewakeup(&sig);
break;
}
@@ -79,37 +75,77 @@
return true;
}
-// Called to receive a bitmask of queued signals.
-func Sigrecv() (m uint32) {
- runtime_entersyscall();
- runtime_notesleep(&sig);
- runtime_exitsyscall();
- runtime_noteclear(&sig);
+// Called to receive the next queued signal.
+// Must only be called from a single goroutine at a time.
+func signal_recv() (m uint32) {
+ static uint32 recv[nelem(sig.mask)];
+ int32 i, more;
+
for(;;) {
- m = sig.mask;
- if(runtime_cas(&sig.mask, m, 0))
- break;
+ // Serve from local copy if there are bits left.
+ for(i=0; i<NSIG; i++) {
+ if(recv[i/32]&(1U<<(i&31))) {
+ recv[i/32] ^= 1U<<(i&31);
+ m = i;
+ goto done;
+ }
+ }
+
+ // Get a new local copy.
+ // Ask for a kick if more signals come in
+ // during or after our check (before the sleep).
+ if(sig.kick == 0) {
+ runtime_noteclear(&sig);
+ runtime_cas(&sig.kick, 0, 1);
+ }
+
+ more = 0;
+ for(i=0; (size_t)i<nelem(sig.mask); i++) {
+ for(;;) {
+ m = sig.mask[i];
+ if(runtime_cas(&sig.mask[i], m, 0))
+ break;
+ }
+ recv[i] = m;
+ if(m != 0)
+ more = 1;
+ }
+ if(more)
+ continue;
+
+ // Sleep waiting for more.
+ runtime_entersyscall();
+ runtime_notesleep(&sig);
+ runtime_exitsyscall();
}
+
+done:;
+ // goc requires that we fall off the end of functions
+ // that return values instead of using our own return
+ // statements.
}
-func Signame(sig int32) (name String) {
- const char* s = NULL;
- char buf[100];
-#if defined(HAVE_STRSIGNAL)
- s = strsignal(sig);
-#endif
- if (s == NULL) {
- snprintf(buf, sizeof buf, "signal %d", sig);
- s = buf;
+// Must only be called from a single goroutine at a time.
+func signal_enable(s uint32) {
+ int32 i;
+
+ if(!sig.inuse) {
+ // The first call to signal_enable is for us
+ // to use for initialization. It does not pass
+ // signal information in m.
+ sig.inuse = true; // enable reception of signals; cannot disable
+ runtime_noteclear(&sig);
+ return;
}
- int32 len = __builtin_strlen(s);
- unsigned char *data = runtime_mallocgc(len, FlagNoPointers, 0, 0);
- __builtin_memcpy(data, s, len);
- name.__data = data;
- name.__length = len;
+
+ if(~s == 0) {
+ // Special case: want everything.
+ for(i=0; (size_t)i<nelem(sig.wanted); i++)
+ sig.wanted[i] = ~(uint32)0;
+ return;
+ }
+
+ if(s >= nelem(sig.wanted)*32)
+ return;
+ sig.wanted[s/32] |= 1U<<(s&31);
}
-
-func Siginit() {
- runtime_initsig(SigQueue);
- sig.inuse = true; // enable reception of signals; cannot disable
-}