Commit 0d3dd8fb by Ian Lance Taylor

runtime: copy cgo support from Go 1.7 runtime

    
    Remove support for _cgo_allocate.  It was removed from the gc
    toolchain in Go 1.5, so it is unlikely that anybody is trying to use it.
    
    Reviewed-on: https://go-review.googlesource.com/34557

From-SVN: r243805
parent 4daecdb6
e6fb629c5b246bceab5fc8e8613cf2cf82b1e98f 4a0bb435bbb1d1516b486d1998e8dc184576db61
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
// Copyright 2016 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
import (
"runtime/internal/atomic"
_ "unsafe"
)
// For historical reasons these functions are called as though they
// were in the syscall package.
//go:linkname Cgocall syscall.Cgocall
//go:linkname CgocallDone syscall.CgocallDone
//go:linkname CgocallBack syscall.CgocallBack
//go:linkname CgocallBackDone syscall.CgocallBackDone
// A routine that may be called by SWIG.
//go:linkname _cgo_panic _cgo_panic
// iscgo is set to true if the cgo tool sets the C variable runtime_iscgo
// to true.
var iscgo bool
// cgoHasExtraM is set on startup when an extra M is created for cgo.
// The extra M must be created before any C/C++ code calls cgocallback.
var cgoHasExtraM bool
// Cgocall prepares to call from code written in Go to code written in
// C/C++. This takes the current goroutine out of the Go scheduler, as
// though it were making a system call. Otherwise the program can
// lookup if the C code blocks. The idea is to call this function,
// then immediately call the C/C++ function. After the C/C++ function
// returns, call cgocalldone. The usual Go code would look like
// syscall.Cgocall()
// defer syscall.Cgocalldone()
// cfunction()
func Cgocall() {
lockOSThread()
mp := getg().m
mp.ncgocall++
mp.ncgo++
entersyscall(0)
}
// CgocallDone prepares to return to Go code from C/C++ code.
func CgocallDone() {
gp := getg()
if gp == nil {
throw("no g in CgocallDone")
}
gp.m.ncgo--
// If we are invoked because the C function called _cgo_panic,
// then _cgo_panic will already have exited syscall mode.
if gp.atomicstatus == _Gsyscall {
exitsyscall(0)
}
unlockOSThread()
}
// CgocallBack is used when calling from C/C++ code into Go code.
// The usual approach is
// syscall.CgocallBack()
// defer syscall.CgocallBackDone()
// gofunction()
//go:nosplit
func CgocallBack() {
if getg() == nil || getg().m == nil {
needm(0)
mp := getg().m
mp.dropextram = true
}
exitsyscall(0)
if getg().m.ncgo == 0 {
// The C call to Go came from a thread created by C.
// The C call to Go came from a thread not currently running
// any Go. In the case of -buildmode=c-archive or c-shared,
// this call may be coming in before package initialization
// is complete. Wait until it is.
<-main_init_done
}
mp := getg().m
if mp.needextram || atomic.Load(&extraMWaiters) > 0 {
mp.needextram = false
newextram()
}
}
// CgocallBackDone prepares to return to C/C++ code that has called
// into Go code.
func CgocallBackDone() {
entersyscall(0)
mp := getg().m
if mp.dropextram && mp.ncgo == 0 {
mp.dropextram = false
dropm()
}
}
// _cgo_panic may be called by SWIG code to panic.
func _cgo_panic(p *byte) {
exitsyscall(0)
panic(gostringnocopy(p))
}
// 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.
// +build ignore
// Support for memory sanitizer. See runtime/cgo/mmap.go.
// +build linux,amd64
package runtime
import "unsafe"
// _cgo_mmap is filled in by runtime/cgo when it is linked into the
// program, so it is only non-nil when using cgo.
//go:linkname _cgo_mmap _cgo_mmap
var _cgo_mmap unsafe.Pointer
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer {
if _cgo_mmap != nil {
// Make ret a uintptr so that writing to it in the
// function literal does not trigger a write barrier.
// A write barrier here could break because of the way
// that mmap uses the same value both as a pointer and
// an errno value.
// TODO: Fix mmap to return two values.
var ret uintptr
systemstack(func() {
ret = callCgoMmap(addr, n, prot, flags, fd, off)
})
return unsafe.Pointer(ret)
}
return sysMmap(addr, n, prot, flags, fd, off)
}
// sysMmap calls the mmap system call. It is implemented in assembly.
func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
// cgoMmap calls the mmap function in the runtime/cgo package on the
// callCgoMmap calls the mmap function in the runtime/cgo package
// using the GCC calling convention. It is implemented in assembly.
func callCgoMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) uintptr
...@@ -8,6 +8,44 @@ import ( ...@@ -8,6 +8,44 @@ import (
"unsafe" "unsafe"
) )
// Temporary for C code to call:
//go:linkname minit runtime.minit
// minit is called to initialize a new m (including the bootstrap m).
// Called on the new thread, cannot allocate memory.
func minit() {
// Initialize signal handling.
_g_ := getg()
var st _stack_t
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
signalstack(_g_.m.gsignalstack, _g_.m.gsignalstacksize)
_g_.m.newSigstack = true
} else {
_g_.m.newSigstack = false
}
// FIXME: We should set _g_.m.procid here.
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
for i := range sigtable {
if sigtable[i].flags&_SigUnblock != 0 {
sigdelset(&nmask, int32(i))
}
}
sigprocmask(_SIG_SETMASK, &nmask, nil)
}
// Called from dropm to undo the effect of an minit.
//go:nosplit
func unminit() {
if getg().m.newSigstack {
signalstack(nil, 0)
}
}
var urandom_dev = []byte("/dev/urandom\x00") var urandom_dev = []byte("/dev/urandom\x00")
func getRandomData(r []byte) { func getRandomData(r []byte) {
......
...@@ -479,8 +479,6 @@ type m struct { ...@@ -479,8 +479,6 @@ type m struct {
dropextram bool // drop after call is done dropextram bool // drop after call is done
gcing int32 gcing int32
cgomal *cgoMal // allocations via _cgo_allocate
} }
type p struct { type p struct {
...@@ -801,14 +799,6 @@ var ( ...@@ -801,14 +799,6 @@ var (
// array. // array.
type g_ucontext_t [(_sizeof_ucontext_t + 15) / unsafe.Sizeof(unsafe.Pointer(nil))]unsafe.Pointer type g_ucontext_t [(_sizeof_ucontext_t + 15) / unsafe.Sizeof(unsafe.Pointer(nil))]unsafe.Pointer
// cgoMal tracks allocations made by _cgo_allocate
// FIXME: _cgo_allocate has been removed from gc and can probably be
// removed from gccgo too.
type cgoMal struct {
next *cgoMal
alloc unsafe.Pointer
}
// sigset is the Go version of the C type sigset_t. // sigset is the Go version of the C type sigset_t.
// _sigset_t is defined by the Makefile from <signal.h>. // _sigset_t is defined by the Makefile from <signal.h>.
type sigset _sigset_t type sigset _sigset_t
...@@ -327,7 +327,7 @@ func ensureSigM() { ...@@ -327,7 +327,7 @@ func ensureSigM() {
//go:norace //go:norace
//go:nowritebarrierrec //go:nowritebarrierrec
func badsignal(sig uintptr, c *sigctxt) { func badsignal(sig uintptr, c *sigctxt) {
needm() needm(0)
if !sigsend(uint32(sig)) { if !sigsend(uint32(sig)) {
// A foreign thread received the signal sig, and the // A foreign thread received the signal sig, and the
// Go code does not want to handle it. // Go code does not want to handle it.
......
...@@ -17,18 +17,19 @@ import ( ...@@ -17,18 +17,19 @@ import (
func sigaction(signum int32, act *_sigaction, oact *_sigaction) int32 func sigaction(signum int32, act *_sigaction, oact *_sigaction) int32
//extern sigprocmask //extern sigprocmask
func sigprocmask(how int32, set *_sigset_t, oldset *_sigset_t) int32 func sigprocmask(how int32, set *sigset, oldset *sigset) int32
// The argument should be simply *_sigset_t, but that fails on GNU/Linux
// which sometimes uses _sigset_t and sometimes uses ___sigset_t.
//extern sigfillset //extern sigfillset
func sigfillset(set unsafe.Pointer) int32 func sigfillset(set *sigset) int32
//extern sigemptyset //extern sigemptyset
func sigemptyset(set *_sigset_t) int32 func sigemptyset(set *sigset) int32
//extern sigaddset //extern sigaddset
func sigaddset(set *_sigset_t, signum int32) int32 func sigaddset(set *sigset, signum int32) int32
//extern sigdelset
func sigdelset(set *sigset, signum int32) int32
//extern sigaltstack //extern sigaltstack
func sigaltstack(ss *_stack_t, oss *_stack_t) int32 func sigaltstack(ss *_stack_t, oss *_stack_t) int32
...@@ -57,9 +58,19 @@ func (c *sigctxt) sigcode() uint64 { ...@@ -57,9 +58,19 @@ func (c *sigctxt) sigcode() uint64 {
} }
//go:nosplit //go:nosplit
func msigsave(mp *m) {
sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
}
//go:nosplit
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, &sigmask, nil)
}
//go:nosplit
func sigblock() { func sigblock() {
var set _sigset_t var set sigset
sigfillset(unsafe.Pointer(&set)) sigfillset(&set)
sigprocmask(_SIG_SETMASK, &set, nil) sigprocmask(_SIG_SETMASK, &set, nil)
} }
...@@ -81,7 +92,7 @@ func setsig(i int32, fn uintptr, restart bool) { ...@@ -81,7 +92,7 @@ func setsig(i int32, fn uintptr, restart bool) {
if restart { if restart {
sa.sa_flags |= _SA_RESTART sa.sa_flags |= _SA_RESTART
} }
sigfillset(unsafe.Pointer(&sa.sa_mask)) sigfillset((*sigset)(unsafe.Pointer(&sa.sa_mask)))
setSigactionHandler(&sa, fn) setSigactionHandler(&sa, fn)
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
...@@ -117,10 +128,12 @@ func getsig(i int32) uintptr { ...@@ -117,10 +128,12 @@ func getsig(i int32) uintptr {
return getSigactionHandler(&sa) return getSigactionHandler(&sa)
} }
func signalstack(p unsafe.Pointer, n uintptr)
//go:nosplit //go:nosplit
//go:nowritebarrierrec //go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
var mask _sigset_t var mask sigset
sigemptyset(&mask) sigemptyset(&mask)
for i := int32(0); i < _NSIG; i++ { for i := int32(0); i < _NSIG; i++ {
if m[(i-1)/32]&(1<<((uint(i)-1)&31)) != 0 { if m[(i-1)/32]&(1<<((uint(i)-1)&31)) != 0 {
...@@ -131,7 +144,7 @@ func updatesigmask(m sigmask) { ...@@ -131,7 +144,7 @@ func updatesigmask(m sigmask) {
} }
func unblocksig(sig int32) { func unblocksig(sig int32) {
var mask _sigset_t var mask sigset
sigemptyset(&mask) sigemptyset(&mask)
sigaddset(&mask, sig) sigaddset(&mask, sig)
sigprocmask(_SIG_UNBLOCK, &mask, nil) sigprocmask(_SIG_UNBLOCK, &mask, nil)
......
...@@ -52,8 +52,8 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) { ...@@ -52,8 +52,8 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
// All signals were blocked due to the sigaction mask; // All signals were blocked due to the sigaction mask;
// unblock them. // unblock them.
var set _sigset_t var set sigset
sigfillset(unsafe.Pointer(&set)) sigfillset(&set)
sigprocmask(_SIG_UNBLOCK, &set, nil) sigprocmask(_SIG_UNBLOCK, &set, nil)
sigpanic() sigpanic()
......
...@@ -249,6 +249,24 @@ func funcPC(f interface{}) uintptr { ...@@ -249,6 +249,24 @@ func funcPC(f interface{}) uintptr {
} }
// For gccgo, to communicate from the C code to the Go code. // For gccgo, to communicate from the C code to the Go code.
//go:linkname setIsCgo runtime.setIsCgo
func setIsCgo() {
iscgo = true
}
// Temporary for gccgo until we port proc.go.
//go:linkname makeMainInitDone runtime.makeMainInitDone
func makeMainInitDone() {
main_init_done = make(chan bool)
}
// Temporary for gccgo until we port proc.go.
//go:linkname closeMainInitDone runtime.closeMainInitDone
func closeMainInitDone() {
close(main_init_done)
}
// For gccgo, to communicate from the C code to the Go code.
//go:linkname setCpuidECX runtime.setCpuidECX //go:linkname setCpuidECX runtime.setCpuidECX
func setCpuidECX(v uint32) { func setCpuidECX(v uint32) {
cpuid_ecx = v cpuid_ecx = v
...@@ -301,6 +319,9 @@ var writeBarrier struct { ...@@ -301,6 +319,9 @@ var writeBarrier struct {
alignme uint64 // guarantee alignment so that compiler can use a 32 or 64-bit load alignme uint64 // guarantee alignment so that compiler can use a 32 or 64-bit load
} }
func queueRescan(*g) {
}
// Here for gccgo until we port atomic_pointer.go and mgc.go. // Here for gccgo until we port atomic_pointer.go and mgc.go.
//go:nosplit //go:nosplit
func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
...@@ -446,6 +467,8 @@ func cpuprofAdd(stk []uintptr) { ...@@ -446,6 +467,8 @@ func cpuprofAdd(stk []uintptr) {
func Breakpoint() func Breakpoint()
func LockOSThread() func LockOSThread()
func UnlockOSThread() func UnlockOSThread()
func lockOSThread()
func unlockOSThread()
func allm() *m func allm() *m
func allgs() []*g func allgs() []*g
...@@ -499,8 +522,6 @@ func getZerobase() *uintptr { ...@@ -499,8 +522,6 @@ func getZerobase() *uintptr {
} }
// Temporary for gccgo until we port proc.go. // Temporary for gccgo until we port proc.go.
func needm()
func dropm()
func sigprof() func sigprof()
func mcount() int32 func mcount() int32
func gcount() int32 func gcount() int32
...@@ -529,6 +550,12 @@ func getsched() *schedt { ...@@ -529,6 +550,12 @@ func getsched() *schedt {
return &sched return &sched
} }
// Temporary for gccgo until we port proc.go.
//go:linkname getCgoHasExtraM runtime.getCgoHasExtraM
func getCgoHasExtraM() *bool {
return &cgoHasExtraM
}
// Throw and rethrow an exception. // Throw and rethrow an exception.
func throwException() func throwException()
func rethrowException() func rethrowException()
......
...@@ -5,193 +5,6 @@ ...@@ -5,193 +5,6 @@
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h" #include "runtime.h"
#include "go-alloc.h"
#include "go-type.h"
extern void chanrecv1 (ChanType *, Hchan *, void *)
__asm__ (GOSYM_PREFIX "runtime.chanrecv1");
/* Prepare to call from code written in Go to code written in C or
C++. This takes the current goroutine out of the Go scheduler, as
though it were making a system call. Otherwise the program can
lock up if the C code goes to sleep on a mutex or for some other
reason. This idea is to call this function, then immediately call
the C/C++ function. After the C/C++ function returns, call
syscall_cgocalldone. The usual Go code would look like
syscall.Cgocall()
defer syscall.Cgocalldone()
cfunction()
*/
/* We let Go code call these via the syscall package. */
void syscall_cgocall(void) __asm__ (GOSYM_PREFIX "syscall.Cgocall");
void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallDone");
void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBack");
void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBackDone");
void
syscall_cgocall ()
{
M* m;
if (runtime_needextram && runtime_cas (&runtime_needextram, 1, 0))
runtime_newextram ();
runtime_lockOSThread();
m = runtime_m ();
++m->ncgocall;
++m->ncgo;
runtime_entersyscall (0);
}
/* Prepare to return to Go code from C/C++ code. */
void
syscall_cgocalldone ()
{
G* g;
g = runtime_g ();
__go_assert (g != NULL);
--g->m->ncgo;
if (g->m->ncgo == 0)
{
/* We are going back to Go, and we are not in a recursive call.
Let the garbage collector clean up any unreferenced
memory. */
g->m->cgomal = NULL;
}
/* If we are invoked because the C function called _cgo_panic, then
_cgo_panic will already have exited syscall mode. */
if (g->atomicstatus == _Gsyscall)
runtime_exitsyscall (0);
runtime_unlockOSThread();
}
/* Call back from C/C++ code to Go code. */
void
syscall_cgocallback ()
{
M *mp;
mp = runtime_m ();
if (mp == NULL)
{
runtime_needm ();
mp = runtime_m ();
mp->dropextram = true;
}
runtime_exitsyscall (0);
if (runtime_m ()->ncgo == 0)
{
/* The C call to Go came from a thread not currently running any
Go. In the case of -buildmode=c-archive or c-shared, this
call may be coming in before package initialization is
complete. Wait until it is. */
chanrecv1 (NULL, runtime_main_init_done, NULL);
}
mp = runtime_m ();
if (mp->needextram)
{
mp->needextram = 0;
runtime_newextram ();
}
}
/* Prepare to return to C/C++ code from a callback to Go code. */
void
syscall_cgocallbackdone ()
{
M *mp;
runtime_entersyscall (0);
mp = runtime_m ();
if (mp->dropextram && mp->ncgo == 0)
{
mp->dropextram = false;
runtime_dropm ();
}
}
/* Allocate memory and save it in a list visible to the Go garbage
collector. */
void *
alloc_saved (size_t n)
{
void *ret;
M *m;
CgoMal *c;
ret = __go_alloc (n);
m = runtime_m ();
c = (CgoMal *) __go_alloc (sizeof (CgoMal));
c->next = m->cgomal;
c->alloc = ret;
m->cgomal = c;
return ret;
}
/* These are routines used by SWIG. The gc runtime library provides
the same routines under the same name, though in that case the code
is required to import runtime/cgo. */
void *
_cgo_allocate (size_t n)
{
void *ret;
runtime_exitsyscall (0);
ret = alloc_saved (n);
runtime_entersyscall (0);
return ret;
}
extern const struct __go_type_descriptor string_type_descriptor
__asm__ (GOSYM_PREFIX "__go_tdn_string");
void
_cgo_panic (const char *p)
{
intgo len;
unsigned char *data;
String *ps;
Eface e;
const struct __go_type_descriptor *td;
runtime_exitsyscall (0);
len = __builtin_strlen (p);
data = alloc_saved (len);
__builtin_memcpy (data, p, len);
ps = alloc_saved (sizeof *ps);
ps->str = data;
ps->len = len;
td = &string_type_descriptor;
memcpy(&e._type, &td, sizeof td); /* This is a const_cast. */
e.data = ps;
/* We don't call runtime_entersyscall here, because normally what
will happen is that we will walk up the stack to a Go deferred
function that calls recover. However, this will do the wrong
thing if this panic is recovered and the stack unwinding is
caught by a C++ exception handler. It might be possible to
handle this by calling runtime_entersyscall in the personality
function in go-unwind.c. FIXME. */
runtime_panic (e);
}
/* Used for _cgo_wait_runtime_init_done. This is based on code in /* Used for _cgo_wait_runtime_init_done. This is based on code in
runtime/cgo/gcc_libinit.c in the master library. */ runtime/cgo/gcc_libinit.c in the master library. */
...@@ -249,8 +62,3 @@ _cgo_notify_runtime_init_done (void) ...@@ -249,8 +62,3 @@ _cgo_notify_runtime_init_done (void)
// runtime_iscgo is set to true if some cgo code is linked in. // runtime_iscgo is set to true if some cgo code is linked in.
// This is done by a constructor in the cgo generated code. // This is done by a constructor in the cgo generated code.
_Bool runtime_iscgo; _Bool runtime_iscgo;
// runtime_cgoHasExtraM is set on startup when an extra M is created
// for cgo. The extra M must be created before any C/C++ code calls
// cgocallback.
_Bool runtime_cgoHasExtraM;
...@@ -61,6 +61,7 @@ initfn (int argc, char **argv, char** env __attribute__ ((unused))) ...@@ -61,6 +61,7 @@ initfn (int argc, char **argv, char** env __attribute__ ((unused)))
runtime_isarchive = true; runtime_isarchive = true;
setIsCgo ();
runtime_cpuinit (); runtime_cpuinit ();
runtime_initsig(true); runtime_initsig(true);
......
...@@ -46,6 +46,9 @@ main (int argc, char **argv) ...@@ -46,6 +46,9 @@ main (int argc, char **argv)
return 0; return 0;
runtime_isstarted = true; runtime_isstarted = true;
if (runtime_iscgo)
setIsCgo ();
__go_end = (uintptr)_end; __go_end = (uintptr)_end;
runtime_cpuinit (); runtime_cpuinit ();
runtime_check (); runtime_check ();
......
...@@ -543,4 +543,3 @@ int32 runtime_setgcpercent(int32) ...@@ -543,4 +543,3 @@ int32 runtime_setgcpercent(int32)
#define PoisonStack ((uintptr)0x6868686868686868ULL) #define PoisonStack ((uintptr)0x6868686868686868ULL)
struct Workbuf; struct Workbuf;
void runtime_proc_scan(struct Workbuf**, void (*)(struct Workbuf**, Obj));
...@@ -1283,7 +1283,6 @@ markroot(ParFor *desc, uint32 i) ...@@ -1283,7 +1283,6 @@ markroot(ParFor *desc, uint32 i)
enqueue1(&wbuf, (Obj){(byte*)&runtime_allm, sizeof runtime_allm, 0}); enqueue1(&wbuf, (Obj){(byte*)&runtime_allm, sizeof runtime_allm, 0});
enqueue1(&wbuf, (Obj){(byte*)&runtime_allp, sizeof runtime_allp, 0}); enqueue1(&wbuf, (Obj){(byte*)&runtime_allp, sizeof runtime_allp, 0});
enqueue1(&wbuf, (Obj){(byte*)&work, sizeof work, 0}); enqueue1(&wbuf, (Obj){(byte*)&work, sizeof work, 0});
runtime_proc_scan(&wbuf, enqueue1);
break; break;
case RootFinalizers: case RootFinalizers:
......
...@@ -52,7 +52,7 @@ typedef uintptr uintreg; ...@@ -52,7 +52,7 @@ typedef uintptr uintreg;
/* Defined types. */ /* Defined types. */
typedef uint8 bool; typedef _Bool bool;
typedef uint8 byte; typedef uint8 byte;
typedef struct g G; typedef struct g G;
typedef struct mutex Lock; typedef struct mutex Lock;
...@@ -240,7 +240,6 @@ extern M* runtime_allm; ...@@ -240,7 +240,6 @@ extern M* runtime_allm;
extern P** runtime_allp; extern P** runtime_allp;
extern Sched* runtime_sched; extern Sched* runtime_sched;
extern int32 runtime_gomaxprocs; extern int32 runtime_gomaxprocs;
extern uint32 runtime_needextram;
extern uint32 runtime_panicking(void) extern uint32 runtime_panicking(void)
__asm__ (GOSYM_PREFIX "runtime.getPanicking"); __asm__ (GOSYM_PREFIX "runtime.getPanicking");
extern int8* runtime_goos; extern int8* runtime_goos;
...@@ -298,15 +297,13 @@ void runtime_ready(G*); ...@@ -298,15 +297,13 @@ void runtime_ready(G*);
String runtime_getenv(const char*); String runtime_getenv(const char*);
int32 runtime_atoi(const byte*, intgo); int32 runtime_atoi(const byte*, intgo);
void* runtime_mstart(void*); void* runtime_mstart(void*);
G* runtime_malg(int32, byte**, uintptr*); G* runtime_malg(bool, bool, byte**, uintptr*)
__asm__(GOSYM_PREFIX "runtime.malg");
void runtime_mpreinit(M*); void runtime_mpreinit(M*);
void runtime_minit(void); void runtime_minit(void)
void runtime_unminit(void); __asm__ (GOSYM_PREFIX "runtime.minit");
void runtime_needm(void) void runtime_signalstack(byte*, uintptr)
__asm__ (GOSYM_PREFIX "runtime.needm"); __asm__ (GOSYM_PREFIX "runtime.signalstack");
void runtime_dropm(void)
__asm__ (GOSYM_PREFIX "runtime.dropm");
void runtime_signalstack(byte*, int32);
MCache* runtime_allocmcache(void) MCache* runtime_allocmcache(void)
__asm__ (GOSYM_PREFIX "runtime.allocmcache"); __asm__ (GOSYM_PREFIX "runtime.allocmcache");
void runtime_freemcache(MCache*); void runtime_freemcache(MCache*);
...@@ -345,7 +342,8 @@ int32 runtime_round2(int32 x); // round x up to a power of 2. ...@@ -345,7 +342,8 @@ int32 runtime_round2(int32 x); // round x up to a power of 2.
void runtime_setg(G*) void runtime_setg(G*)
__asm__ (GOSYM_PREFIX "runtime.setg"); __asm__ (GOSYM_PREFIX "runtime.setg");
void runtime_newextram(void); void runtime_newextram(void)
__asm__ (GOSYM_PREFIX "runtime.newextram");
#define runtime_exit(s) exit(s) #define runtime_exit(s) exit(s)
#define runtime_breakpoint() __builtin_trap() #define runtime_breakpoint() __builtin_trap()
void runtime_gosched(void); void runtime_gosched(void);
...@@ -523,9 +521,12 @@ void runtime_procyield(uint32) ...@@ -523,9 +521,12 @@ void runtime_procyield(uint32)
__asm__(GOSYM_PREFIX "runtime.procyield"); __asm__(GOSYM_PREFIX "runtime.procyield");
void runtime_osyield(void) void runtime_osyield(void)
__asm__(GOSYM_PREFIX "runtime.osyield"); __asm__(GOSYM_PREFIX "runtime.osyield");
void runtime_lockOSThread(void); void runtime_lockOSThread(void)
void runtime_unlockOSThread(void); __asm__(GOSYM_PREFIX "runtime.lockOSThread");
bool runtime_lockedOSThread(void); void runtime_unlockOSThread(void)
__asm__(GOSYM_PREFIX "runtime.unlockOSThread");
bool runtime_lockedOSThread(void)
__asm__(GOSYM_PREFIX "runtime.lockedOSThread");
void runtime_printcreatedby(G*) void runtime_printcreatedby(G*)
__asm__(GOSYM_PREFIX "runtime.printcreatedby"); __asm__(GOSYM_PREFIX "runtime.printcreatedby");
...@@ -587,8 +588,6 @@ struct time_now_ret now() __asm__ (GOSYM_PREFIX "time.now") ...@@ -587,8 +588,6 @@ struct time_now_ret now() __asm__ (GOSYM_PREFIX "time.now")
extern void _cgo_wait_runtime_init_done (void); extern void _cgo_wait_runtime_init_done (void);
extern void _cgo_notify_runtime_init_done (void); extern void _cgo_notify_runtime_init_done (void);
extern _Bool runtime_iscgo; extern _Bool runtime_iscgo;
extern _Bool runtime_cgoHasExtraM;
extern Hchan *runtime_main_init_done;
extern uintptr __go_end __attribute__ ((weak)); extern uintptr __go_end __attribute__ ((weak));
extern void *getitab(const struct __go_type_descriptor *, extern void *getitab(const struct __go_type_descriptor *,
const struct __go_type_descriptor *, const struct __go_type_descriptor *,
...@@ -596,5 +595,11 @@ extern void *getitab(const struct __go_type_descriptor *, ...@@ -596,5 +595,11 @@ extern void *getitab(const struct __go_type_descriptor *,
__asm__ (GOSYM_PREFIX "runtime.getitab"); __asm__ (GOSYM_PREFIX "runtime.getitab");
extern void runtime_cpuinit(void); extern void runtime_cpuinit(void);
extern void setIsCgo(void)
__asm__ (GOSYM_PREFIX "runtime.setIsCgo");
extern void setCpuidECX(uint32) extern void setCpuidECX(uint32)
__asm__ (GOSYM_PREFIX "runtime.setCpuidECX"); __asm__ (GOSYM_PREFIX "runtime.setCpuidECX");
extern void makeMainInitDone(void)
__asm__ (GOSYM_PREFIX "runtime.makeMainInitDone");
extern void closeMainInitDone(void)
__asm__ (GOSYM_PREFIX "runtime.closeMainInitDone");
...@@ -99,43 +99,12 @@ runtime_cputicks(void) ...@@ -99,43 +99,12 @@ runtime_cputicks(void)
void void
runtime_mpreinit(M *mp) runtime_mpreinit(M *mp)
{ {
int32 stacksize = 32 * 1024; // OS X wants >=8K, Linux >=2K mp->gsignal = runtime_malg(true, true, (byte**)&mp->gsignalstack, &mp->gsignalstacksize);
#ifdef SIGSTKSZ
if(stacksize < SIGSTKSZ)
stacksize = SIGSTKSZ;
#endif
mp->gsignal = runtime_malg(stacksize, (byte**)&mp->gsignalstack, &mp->gsignalstacksize);
mp->gsignal->m = mp; mp->gsignal->m = mp;
} }
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, can not allocate memory.
void
runtime_minit(void)
{
M* m;
sigset_t sigs;
// Initialize signal handling.
m = runtime_m();
runtime_signalstack(m->gsignalstack, m->gsignalstacksize);
if (sigemptyset(&sigs) != 0)
runtime_throw("sigemptyset");
pthread_sigmask(SIG_SETMASK, &sigs, nil);
}
// Called from dropm to undo the effect of an minit.
void
runtime_unminit(void)
{
runtime_signalstack(nil, 0);
}
void void
runtime_signalstack(byte *p, int32 n) runtime_signalstack(byte *p, uintptr n)
{ {
stack_t st; stack_t st;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment