diff options
author | Russ Cox <rsc@golang.org> | 2014-11-24 12:07:11 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-11-24 12:07:11 -0500 |
commit | e5fc9ffb729e31c4eb0a6518e819e9fc70f14818 (patch) | |
tree | 5f67f9fb6c209085505b8fa6a01a245942ea45c3 /src/runtime | |
parent | df7d4576f312e1b646af4f5f1a32412a4221b785 (diff) | |
parent | db6a11ff558add790779fdef118b5ad899f77137 (diff) | |
download | go-e5fc9ffb729e31c4eb0a6518e819e9fc70f14818.tar.gz |
[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage
TBR=austin
CC=golang-codereviews
https://codereview.appspot.com/179290043
Diffstat (limited to 'src/runtime')
135 files changed, 4013 insertions, 4065 deletions
diff --git a/src/runtime/arch1_386.go b/src/runtime/arch1_386.go index 7746dfbf0..a73e207ed 100644 --- a/src/runtime/arch1_386.go +++ b/src/runtime/arch1_386.go @@ -9,7 +9,7 @@ const ( _BigEndian = 0 _CacheLineSize = 64 _RuntimeGogoBytes = 64 - _PhysPageSize = _NaCl*65536 + (1-_NaCl)*4096 // 4k normally; 64k on NaCl + _PhysPageSize = goos_nacl*65536 + (1-goos_nacl)*4096 // 4k normally; 64k on NaCl _PCQuantum = 1 _Int64Align = 4 ) diff --git a/src/runtime/arch1_amd64.go b/src/runtime/arch1_amd64.go index 83c9c2dc9..794b7f65c 100644 --- a/src/runtime/arch1_amd64.go +++ b/src/runtime/arch1_amd64.go @@ -8,7 +8,7 @@ const ( thechar = '6' _BigEndian = 0 _CacheLineSize = 64 - _RuntimeGogoBytes = 64 + (_Plan9|_Solaris|_Windows)*16 + _RuntimeGogoBytes = 64 + (goos_plan9|goos_solaris|goos_windows)*16 _PhysPageSize = 4096 _PCQuantum = 1 _Int64Align = 8 diff --git a/src/runtime/arch1_amd64p32.go b/src/runtime/arch1_amd64p32.go new file mode 100644 index 000000000..2cee21f0c --- /dev/null +++ b/src/runtime/arch1_amd64p32.go @@ -0,0 +1,15 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +const ( + thechar = '6' + _BigEndian = 0 + _CacheLineSize = 64 + _RuntimeGogoBytes = 64 + _PhysPageSize = 65536*goos_nacl + 4096*(1-goos_nacl) + _PCQuantum = 1 + _Int64Align = 8 +) diff --git a/src/runtime/arch1_arm.go b/src/runtime/arch1_arm.go index 5cb79fd68..6662eaeac 100644 --- a/src/runtime/arch1_arm.go +++ b/src/runtime/arch1_arm.go @@ -9,7 +9,7 @@ const ( _BigEndian = 0 _CacheLineSize = 32 _RuntimeGogoBytes = 60 - _PhysPageSize = 65536*_NaCl + 4096*(1-_NaCl) + _PhysPageSize = 65536*goos_nacl + 4096*(1-goos_nacl) _PCQuantum = 4 _Int64Align = 4 ) diff --git a/src/runtime/arch1_power64.go b/src/runtime/arch1_power64.go new file mode 100644 index 000000000..01e2b70f9 --- /dev/null +++ b/src/runtime/arch1_power64.go @@ -0,0 +1,15 @@ +// Copyright 2014 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 + +const ( + thechar = '9' + _BigEndian = 1 + _CacheLineSize = 64 + _RuntimeGogoBytes = 64 + _PhysPageSize = 65536 + _PCQuantum = 4 + _Int64Align = 8 +) diff --git a/src/runtime/arch1_power64le.go b/src/runtime/arch1_power64le.go new file mode 100644 index 000000000..6580732a3 --- /dev/null +++ b/src/runtime/arch1_power64le.go @@ -0,0 +1,15 @@ +// Copyright 2014 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 + +const ( + thechar = '9' + _BigEndian = 0 + _CacheLineSize = 64 + _RuntimeGogoBytes = 64 + _PhysPageSize = 65536 + _PCQuantum = 4 + _Int64Align = 8 +) diff --git a/src/runtime/arch_amd64p32.h b/src/runtime/arch_amd64p32.h deleted file mode 100644 index d3e864987..000000000 --- a/src/runtime/arch_amd64p32.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -enum { - thechar = '6', - BigEndian = 0, - CacheLineSize = 64, - RuntimeGogoBytes = 64, -#ifdef GOOS_nacl - PhysPageSize = 65536, -#else - PhysPageSize = 4096, -#endif - PCQuantum = 1, - Int64Align = 8 -}; diff --git a/src/runtime/arch_power64le.h b/src/runtime/arch_power64le.h deleted file mode 100644 index 684ac9953..000000000 --- a/src/runtime/arch_power64le.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2014 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. - -enum { - thechar = '9', - BigEndian = 0, - CacheLineSize = 64, - RuntimeGogoBytes = 64, - PhysPageSize = 65536, - PCQuantum = 4, - Int64Align = 8 -}; - diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s index 60c438c1d..c87d848fe 100644 --- a/src/runtime/asm_amd64p32.s +++ b/src/runtime/asm_amd64p32.s @@ -169,7 +169,7 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4 // of the G stack. We need to distinguish the routine that // lives at the bottom of the G stack from the one that lives // at the top of the system stack because the one at the top of -// the M stack terminates the stack walk (see topofstack()). +// the system stack terminates the stack walk (see topofstack()). TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 RET diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index 6169202ea..548c88e47 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -4,7 +4,8 @@ // +build power64 power64le -#include "zasm_GOOS_GOARCH.h" +#include "go_asm.h" +#include "go_tls.h" #include "funcdata.h" #include "textflag.h" @@ -144,58 +145,44 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8 BL (CTR) BR runtime·badmcall2(SB) -// switchtoM is a dummy routine that onM leaves at the bottom +// systemstack_switch is a dummy routine that systemstack leaves at the bottom // of the G stack. We need to distinguish the routine that // lives at the bottom of the G stack from the one that lives -// at the top of the M stack because the one at the top of -// the M stack terminates the stack walk (see topofstack()). -TEXT runtime·switchtoM(SB), NOSPLIT, $0-0 +// at the top of the system stack because the one at the top of +// the system stack terminates the stack walk (see topofstack()). +TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 UNDEF BL (LR) // make sure this function is not leaf RETURN -// func onM_signalok(fn func()) -TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8 - MOVD g, R3 // R3 = g - MOVD g_m(R3), R4 // R4 = g->m - MOVD m_gsignal(R4), R4 // R4 = g->m->gsignal - MOVD fn+0(FP), R11 // context for call below - CMP R3, R4 - BEQ onsignal - MOVD R11, 8(R1) - BL runtime·onM(SB) - RETURN - -onsignal: - MOVD 0(R11), R3 // code pointer - MOVD R3, CTR - BL (CTR) - RETURN - -// void onM(fn func()) -TEXT runtime·onM(SB), NOSPLIT, $0-8 +// func systemstack(fn func()) +TEXT runtime·systemstack(SB), NOSPLIT, $0-8 MOVD fn+0(FP), R3 // R3 = fn MOVD R3, R11 // context MOVD g_m(g), R4 // R4 = m + MOVD m_gsignal(R4), R5 // R5 = gsignal + CMP g, R5 + BEQ noswitch + MOVD m_g0(R4), R5 // R5 = g0 CMP g, R5 - BEQ onm + BEQ noswitch MOVD m_curg(R4), R6 CMP g, R6 - BEQ oncurg + BEQ switch - // Not g0, not curg. Must be gsignal, but that's not allowed. + // Bad: g is not gsignal, not g0, not curg. What is it? // Hide call from linker nosplit analysis. - MOVD $runtime·badonm(SB), R3 + MOVD $runtime·badsystemstack(SB), R3 MOVD R3, CTR BL (CTR) -oncurg: +switch: // save our state in g->sched. Pretend to - // be switchtoM if the G stack is scanned. - MOVD $runtime·switchtoM(SB), R6 + // be systemstack_switch if the G stack is scanned. + MOVD $runtime·systemstack_switch(SB), R6 ADD $8, R6 // get past prologue MOVD R6, (g_sched+gobuf_pc)(g) MOVD R1, (g_sched+gobuf_sp)(g) @@ -205,7 +192,7 @@ oncurg: // switch to g0 MOVD R5, g MOVD (g_sched+gobuf_sp)(g), R3 - // make it look like mstart called onM on g0, to stop traceback + // make it look like mstart called systemstack on g0, to stop traceback SUB $8, R3 MOVD $runtime·mstart(SB), R4 MOVD R4, 0(R3) @@ -223,7 +210,7 @@ oncurg: MOVD R0, (g_sched+gobuf_sp)(g) RETURN -onm: +noswitch: // already on m stack, just call directly MOVD 0(R11), R3 // code pointer MOVD R3, CTR @@ -987,6 +974,10 @@ TEXT runtime·goexit(SB),NOSPLIT,$-8-0 MOVD R0, R0 // NOP BL runtime·goexit1(SB) // does not return +TEXT runtime·getg(SB),NOSPLIT,$-8-8 + MOVD g, ret+0(FP) + RETURN + TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8 RETURN diff --git a/src/runtime/atomic_power64x.go b/src/runtime/atomic_power64x.go new file mode 100644 index 000000000..a0dcf514b --- /dev/null +++ b/src/runtime/atomic_power64x.go @@ -0,0 +1,69 @@ +// Copyright 2014 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 power64 power64le + +package runtime + +import "unsafe" + +//go:noescape +func xadd(ptr *uint32, delta int32) uint32 + +//go:noescape +func xadd64(ptr *uint64, delta int64) uint64 + +//go:noescape +func xchg(ptr *uint32, new uint32) uint32 + +//go:noescape +func xchg64(ptr *uint64, new uint64) uint64 + +// xchgp cannot have a go:noescape annotation, because +// while ptr does not escape, new does. If new is marked as +// not escaping, the compiler will make incorrect escape analysis +// decisions about the value being xchg'ed. +// Instead, make xchgp a wrapper around the actual atomic. +// When calling the wrapper we mark ptr as noescape explicitly. + +//go:nosplit +func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer { + return xchgp1(noescape(ptr), new) +} + +func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer + +//go:noescape +func xchguintptr(ptr *uintptr, new uintptr) uintptr + +//go:noescape +func atomicload(ptr *uint32) uint32 + +//go:noescape +func atomicload64(ptr *uint64) uint64 + +//go:noescape +func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer + +//go:noescape +func atomicor8(ptr *uint8, val uint8) + +//go:noescape +func cas64(ptr *uint64, old, new uint64) bool + +//go:noescape +func atomicstore(ptr *uint32, val uint32) + +//go:noescape +func atomicstore64(ptr *uint64, val uint64) + +// atomicstorep cannot have a go:noescape annotation. +// See comment above for xchgp. + +//go:nosplit +func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) { + atomicstorep1(noescape(ptr), new) +} + +func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer) diff --git a/src/runtime/chan.go b/src/runtime/chan.go index bb0110f94..330422ad0 100644 --- a/src/runtime/chan.go +++ b/src/runtime/chan.go @@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog { return nil } q.first = sgp.next + sgp.next = nil if q.last == sgp { q.last = nil } diff --git a/src/runtime/defs1_netbsd_386.go b/src/runtime/defs1_netbsd_386.go index e39fd04c7..f222bed99 100644 --- a/src/runtime/defs1_netbsd_386.go +++ b/src/runtime/defs1_netbsd_386.go @@ -84,8 +84,8 @@ const ( ) type sigaltstackt struct { - ss_sp *byte - ss_size uint32 + ss_sp uintptr + ss_size uintptr ss_flags int32 } @@ -101,8 +101,8 @@ type siginfo struct { } type stackt struct { - ss_sp *byte - ss_size uint32 + ss_sp uintptr + ss_size uintptr ss_flags int32 } @@ -111,18 +111,30 @@ type timespec struct { tv_nsec int32 } +func (ts *timespec) set_sec(x int32) { + ts.tv_sec = int64(x) +} + +func (ts *timespec) set_nsec(x int32) { + ts.tv_nsec = x +} + type timeval struct { tv_sec int64 tv_usec int32 } +func (tv *timeval) set_usec(x int32) { + tv.tv_usec = x +} + type itimerval struct { it_interval timeval it_value timeval } type mcontextt struct { - __gregs [19]int32 + __gregs [19]uint32 __fpregs [644]byte _mc_tlsbase int32 } diff --git a/src/runtime/defs1_netbsd_amd64.go b/src/runtime/defs1_netbsd_amd64.go index cca701e5b..c2bde4dab 100644 --- a/src/runtime/defs1_netbsd_amd64.go +++ b/src/runtime/defs1_netbsd_amd64.go @@ -84,8 +84,8 @@ const ( ) type sigaltstackt struct { - ss_sp *byte - ss_size uint64 + ss_sp uintptr + ss_size uintptr ss_flags int32 pad_cgo_0 [4]byte } @@ -103,8 +103,8 @@ type siginfo struct { } type stackt struct { - ss_sp *byte - ss_size uint64 + ss_sp uintptr + ss_size uintptr ss_flags int32 pad_cgo_0 [4]byte } @@ -114,12 +114,24 @@ type timespec struct { tv_nsec int64 } +func (ts *timespec) set_sec(x int32) { + ts.tv_sec = int64(x) +} + +func (ts *timespec) set_nsec(x int32) { + ts.tv_nsec = int64(x) +} + type timeval struct { tv_sec int64 tv_usec int32 pad_cgo_0 [4]byte } +func (tv *timeval) set_usec(x int32) { + tv.tv_usec = x +} + type itimerval struct { it_interval timeval it_value timeval diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index ddf592c91..f55924b61 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -155,10 +155,11 @@ type sigactiont struct { } type siginfo struct { - si_signo int32 - si_errno int32 - si_code int32 - _sifields [116]byte + si_signo int32 + si_errno int32 + si_code int32 + // below here is a union; si_addr is the only field we use + si_addr uint32 } type sigaltstackt struct { diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go index 7f8f5816c..a73f47514 100644 --- a/src/runtime/defs_linux_amd64.go +++ b/src/runtime/defs_linux_amd64.go @@ -117,11 +117,11 @@ type sigactiont struct { } type siginfo struct { - si_signo int32 - si_errno int32 - si_code int32 - pad_cgo_0 [4]byte - _sifields [112]byte + si_signo int32 + si_errno int32 + si_code int32 + // below here is a union; si_addr is the only field we use + si_addr uint64 } type itimerval struct { diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index a874b1594..c3a6e2f01 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -147,10 +147,11 @@ type itimerval struct { } type siginfo struct { - si_signo int32 - si_errno int32 - si_code int32 - _sifields [4]uint8 + si_signo int32 + si_errno int32 + si_code int32 + // below here is a union; si_addr is the only field we use + si_addr uint32 } type sigactiont struct { diff --git a/src/runtime/defs_linux_power64.go b/src/runtime/defs_linux_power64.go new file mode 100644 index 000000000..f90b84874 --- /dev/null +++ b/src/runtime/defs_linux_power64.go @@ -0,0 +1,198 @@ +// created by cgo -cdefs and then converted to Go +// cgo -cdefs defs_linux.go defs3_linux.go + +package runtime + +const ( + _EINTR = 0x4 + _EAGAIN = 0xb + _ENOMEM = 0xc + + _PROT_NONE = 0x0 + _PROT_READ = 0x1 + _PROT_WRITE = 0x2 + _PROT_EXEC = 0x4 + + _MAP_ANON = 0x20 + _MAP_PRIVATE = 0x2 + _MAP_FIXED = 0x10 + + _MADV_DONTNEED = 0x4 + + _SA_RESTART = 0x10000000 + _SA_ONSTACK = 0x8000000 + _SA_SIGINFO = 0x4 + + _SIGHUP = 0x1 + _SIGINT = 0x2 + _SIGQUIT = 0x3 + _SIGILL = 0x4 + _SIGTRAP = 0x5 + _SIGABRT = 0x6 + _SIGBUS = 0x7 + _SIGFPE = 0x8 + _SIGKILL = 0x9 + _SIGUSR1 = 0xa + _SIGSEGV = 0xb + _SIGUSR2 = 0xc + _SIGPIPE = 0xd + _SIGALRM = 0xe + _SIGSTKFLT = 0x10 + _SIGCHLD = 0x11 + _SIGCONT = 0x12 + _SIGSTOP = 0x13 + _SIGTSTP = 0x14 + _SIGTTIN = 0x15 + _SIGTTOU = 0x16 + _SIGURG = 0x17 + _SIGXCPU = 0x18 + _SIGXFSZ = 0x19 + _SIGVTALRM = 0x1a + _SIGPROF = 0x1b + _SIGWINCH = 0x1c + _SIGIO = 0x1d + _SIGPWR = 0x1e + _SIGSYS = 0x1f + + _FPE_INTDIV = 0x1 + _FPE_INTOVF = 0x2 + _FPE_FLTDIV = 0x3 + _FPE_FLTOVF = 0x4 + _FPE_FLTUND = 0x5 + _FPE_FLTRES = 0x6 + _FPE_FLTINV = 0x7 + _FPE_FLTSUB = 0x8 + + _BUS_ADRALN = 0x1 + _BUS_ADRERR = 0x2 + _BUS_OBJERR = 0x3 + + _SEGV_MAPERR = 0x1 + _SEGV_ACCERR = 0x2 + + _ITIMER_REAL = 0x0 + _ITIMER_VIRTUAL = 0x1 + _ITIMER_PROF = 0x2 + + _EPOLLIN = 0x1 + _EPOLLOUT = 0x4 + _EPOLLERR = 0x8 + _EPOLLHUP = 0x10 + _EPOLLRDHUP = 0x2000 + _EPOLLET = 0x80000000 + _EPOLL_CLOEXEC = 0x80000 + _EPOLL_CTL_ADD = 0x1 + _EPOLL_CTL_DEL = 0x2 + _EPOLL_CTL_MOD = 0x3 +) + +//struct Sigset { +// uint64 sig[1]; +//}; +//typedef uint64 Sigset; + +type timespec struct { + tv_sec int64 + tv_nsec int64 +} + +func (ts *timespec) set_sec(x int64) { + ts.tv_sec = x +} + +func (ts *timespec) set_nsec(x int32) { + ts.tv_nsec = int64(x) +} + +type timeval struct { + tv_sec int64 + tv_usec int64 +} + +func (tv *timeval) set_usec(x int32) { + tv.tv_usec = int64(x) +} + +type sigactiont struct { + sa_handler uintptr + sa_flags uint64 + sa_restorer uintptr + sa_mask uint64 +} + +type siginfo struct { + si_signo int32 + si_errno int32 + si_code int32 + // below here is a union; si_addr is the only field we use + si_addr uint64 +} + +type itimerval struct { + it_interval timeval + it_value timeval +} + +type epollevent struct { + events uint32 + pad_cgo_0 [4]byte + data [8]byte // unaligned uintptr +} + +// created by cgo -cdefs and then converted to Go +// cgo -cdefs defs_linux.go defs3_linux.go + +const ( + _O_RDONLY = 0x0 + _O_CLOEXEC = 0x80000 + _SA_RESTORER = 0 +) + +type ptregs struct { + gpr [32]uint64 + nip uint64 + msr uint64 + orig_gpr3 uint64 + ctr uint64 + link uint64 + xer uint64 + ccr uint64 + softe uint64 + trap uint64 + dar uint64 + dsisr uint64 + result uint64 +} + +type vreg struct { + u [4]uint32 +} + +type sigaltstackt struct { + ss_sp *byte + ss_flags int32 + pad_cgo_0 [4]byte + ss_size uintptr +} + +type sigcontext struct { + _unused [4]uint64 + signal int32 + _pad0 int32 + handler uint64 + oldmask uint64 + regs *ptregs + gp_regs [48]uint64 + fp_regs [33]float64 + v_regs *vreg + vmx_reserve [101]int64 +} + +type ucontext struct { + uc_flags uint64 + uc_link *ucontext + uc_stack sigaltstackt + uc_sigmask uint64 + __unused [15]uint64 + uc_mcontext sigcontext +} diff --git a/src/runtime/defs_linux_power64.h b/src/runtime/defs_linux_power64.h deleted file mode 100644 index 93742fa34..000000000 --- a/src/runtime/defs_linux_power64.h +++ /dev/null @@ -1,204 +0,0 @@ -// Created by cgo -cdefs - DO NOT EDIT -// cgo -cdefs defs_linux.go defs3_linux.go - - -enum { - EINTR = 0x4, - EAGAIN = 0xb, - ENOMEM = 0xc, - - PROT_NONE = 0x0, - PROT_READ = 0x1, - PROT_WRITE = 0x2, - PROT_EXEC = 0x4, - - MAP_ANON = 0x20, - MAP_PRIVATE = 0x2, - MAP_FIXED = 0x10, - - MADV_DONTNEED = 0x4, - - SA_RESTART = 0x10000000, - SA_ONSTACK = 0x8000000, - SA_SIGINFO = 0x4, - - SIGHUP = 0x1, - SIGINT = 0x2, - SIGQUIT = 0x3, - SIGILL = 0x4, - SIGTRAP = 0x5, - SIGABRT = 0x6, - SIGBUS = 0x7, - SIGFPE = 0x8, - SIGKILL = 0x9, - SIGUSR1 = 0xa, - SIGSEGV = 0xb, - SIGUSR2 = 0xc, - SIGPIPE = 0xd, - SIGALRM = 0xe, - SIGSTKFLT = 0x10, - SIGCHLD = 0x11, - SIGCONT = 0x12, - SIGSTOP = 0x13, - SIGTSTP = 0x14, - SIGTTIN = 0x15, - SIGTTOU = 0x16, - SIGURG = 0x17, - SIGXCPU = 0x18, - SIGXFSZ = 0x19, - SIGVTALRM = 0x1a, - SIGPROF = 0x1b, - SIGWINCH = 0x1c, - SIGIO = 0x1d, - SIGPWR = 0x1e, - SIGSYS = 0x1f, - - FPE_INTDIV = 0x1, - FPE_INTOVF = 0x2, - FPE_FLTDIV = 0x3, - FPE_FLTOVF = 0x4, - FPE_FLTUND = 0x5, - FPE_FLTRES = 0x6, - FPE_FLTINV = 0x7, - FPE_FLTSUB = 0x8, - - BUS_ADRALN = 0x1, - BUS_ADRERR = 0x2, - BUS_OBJERR = 0x3, - - SEGV_MAPERR = 0x1, - SEGV_ACCERR = 0x2, - - ITIMER_REAL = 0x0, - ITIMER_VIRTUAL = 0x1, - ITIMER_PROF = 0x2, - - EPOLLIN = 0x1, - EPOLLOUT = 0x4, - EPOLLERR = 0x8, - EPOLLHUP = 0x10, - EPOLLRDHUP = 0x2000, - EPOLLET = -0x80000000, - EPOLL_CLOEXEC = 0x80000, - EPOLL_CTL_ADD = 0x1, - EPOLL_CTL_DEL = 0x2, - EPOLL_CTL_MOD = 0x3, -}; - -typedef struct Sigset Sigset; -typedef struct Timespec Timespec; -typedef struct Timeval Timeval; -typedef struct SigactionT SigactionT; -typedef struct Siginfo Siginfo; -typedef struct Itimerval Itimerval; -typedef struct EpollEvent EpollEvent; - -#pragma pack on - -//struct Sigset { -// uint64 sig[1]; -//}; -//typedef uint64 Sigset; - -struct Timespec { - int64 tv_sec; - int64 tv_nsec; -}; -struct Timeval { - int64 tv_sec; - int64 tv_usec; -}; -struct SigactionT { - void *sa_handler; - uint64 sa_flags; - void *sa_restorer; - uint64 sa_mask; -}; -struct Siginfo { - int32 si_signo; - int32 si_errno; - int32 si_code; - byte Pad_cgo_0[4]; - byte _sifields[112]; -}; -struct Itimerval { - Timeval it_interval; - Timeval it_value; -}; -struct EpollEvent { - uint32 events; - byte Pad_cgo_0[4]; - byte data[8]; // unaligned uintptr -}; - - -#pragma pack off -// Created by cgo -cdefs - DO NOT EDIT -// cgo -cdefs defs_linux.go defs3_linux.go - - -enum { - O_RDONLY = 0x0, - O_CLOEXEC = 0x80000, - SA_RESTORER = 0, -}; - -typedef struct Ptregs Ptregs; -typedef struct Vreg Vreg; -typedef struct SigaltstackT SigaltstackT; -typedef struct Sigcontext Sigcontext; -typedef struct Ucontext Ucontext; - -#pragma pack on - -struct Ptregs { - uint64 gpr[32]; - uint64 nip; - uint64 msr; - uint64 orig_gpr3; - uint64 ctr; - uint64 link; - uint64 xer; - uint64 ccr; - uint64 softe; - uint64 trap; - uint64 dar; - uint64 dsisr; - uint64 result; -}; -typedef uint64 Gregset[48]; -typedef float64 FPregset[33]; -struct Vreg { - uint32 u[4]; -}; - -struct SigaltstackT { - byte *ss_sp; - int32 ss_flags; - byte Pad_cgo_0[4]; - uint64 ss_size; -}; - -struct Sigcontext { - uint64 _unused[4]; - int32 signal; - int32 _pad0; - uint64 handler; - uint64 oldmask; - Ptregs *regs; - uint64 gp_regs[48]; - float64 fp_regs[33]; - Vreg *v_regs; - int64 vmx_reserve[101]; -}; -struct Ucontext { - uint64 uc_flags; - Ucontext *uc_link; - SigaltstackT uc_stack; - uint64 uc_sigmask; - uint64 __unused[15]; - Sigcontext uc_mcontext; -}; - - -#pragma pack off diff --git a/src/runtime/defs_linux_power64le.go b/src/runtime/defs_linux_power64le.go new file mode 100644 index 000000000..f90b84874 --- /dev/null +++ b/src/runtime/defs_linux_power64le.go @@ -0,0 +1,198 @@ +// created by cgo -cdefs and then converted to Go +// cgo -cdefs defs_linux.go defs3_linux.go + +package runtime + +const ( + _EINTR = 0x4 + _EAGAIN = 0xb + _ENOMEM = 0xc + + _PROT_NONE = 0x0 + _PROT_READ = 0x1 + _PROT_WRITE = 0x2 + _PROT_EXEC = 0x4 + + _MAP_ANON = 0x20 + _MAP_PRIVATE = 0x2 + _MAP_FIXED = 0x10 + + _MADV_DONTNEED = 0x4 + + _SA_RESTART = 0x10000000 + _SA_ONSTACK = 0x8000000 + _SA_SIGINFO = 0x4 + + _SIGHUP = 0x1 + _SIGINT = 0x2 + _SIGQUIT = 0x3 + _SIGILL = 0x4 + _SIGTRAP = 0x5 + _SIGABRT = 0x6 + _SIGBUS = 0x7 + _SIGFPE = 0x8 + _SIGKILL = 0x9 + _SIGUSR1 = 0xa + _SIGSEGV = 0xb + _SIGUSR2 = 0xc + _SIGPIPE = 0xd + _SIGALRM = 0xe + _SIGSTKFLT = 0x10 + _SIGCHLD = 0x11 + _SIGCONT = 0x12 + _SIGSTOP = 0x13 + _SIGTSTP = 0x14 + _SIGTTIN = 0x15 + _SIGTTOU = 0x16 + _SIGURG = 0x17 + _SIGXCPU = 0x18 + _SIGXFSZ = 0x19 + _SIGVTALRM = 0x1a + _SIGPROF = 0x1b + _SIGWINCH = 0x1c + _SIGIO = 0x1d + _SIGPWR = 0x1e + _SIGSYS = 0x1f + + _FPE_INTDIV = 0x1 + _FPE_INTOVF = 0x2 + _FPE_FLTDIV = 0x3 + _FPE_FLTOVF = 0x4 + _FPE_FLTUND = 0x5 + _FPE_FLTRES = 0x6 + _FPE_FLTINV = 0x7 + _FPE_FLTSUB = 0x8 + + _BUS_ADRALN = 0x1 + _BUS_ADRERR = 0x2 + _BUS_OBJERR = 0x3 + + _SEGV_MAPERR = 0x1 + _SEGV_ACCERR = 0x2 + + _ITIMER_REAL = 0x0 + _ITIMER_VIRTUAL = 0x1 + _ITIMER_PROF = 0x2 + + _EPOLLIN = 0x1 + _EPOLLOUT = 0x4 + _EPOLLERR = 0x8 + _EPOLLHUP = 0x10 + _EPOLLRDHUP = 0x2000 + _EPOLLET = 0x80000000 + _EPOLL_CLOEXEC = 0x80000 + _EPOLL_CTL_ADD = 0x1 + _EPOLL_CTL_DEL = 0x2 + _EPOLL_CTL_MOD = 0x3 +) + +//struct Sigset { +// uint64 sig[1]; +//}; +//typedef uint64 Sigset; + +type timespec struct { + tv_sec int64 + tv_nsec int64 +} + +func (ts *timespec) set_sec(x int64) { + ts.tv_sec = x +} + +func (ts *timespec) set_nsec(x int32) { + ts.tv_nsec = int64(x) +} + +type timeval struct { + tv_sec int64 + tv_usec int64 +} + +func (tv *timeval) set_usec(x int32) { + tv.tv_usec = int64(x) +} + +type sigactiont struct { + sa_handler uintptr + sa_flags uint64 + sa_restorer uintptr + sa_mask uint64 +} + +type siginfo struct { + si_signo int32 + si_errno int32 + si_code int32 + // below here is a union; si_addr is the only field we use + si_addr uint64 +} + +type itimerval struct { + it_interval timeval + it_value timeval +} + +type epollevent struct { + events uint32 + pad_cgo_0 [4]byte + data [8]byte // unaligned uintptr +} + +// created by cgo -cdefs and then converted to Go +// cgo -cdefs defs_linux.go defs3_linux.go + +const ( + _O_RDONLY = 0x0 + _O_CLOEXEC = 0x80000 + _SA_RESTORER = 0 +) + +type ptregs struct { + gpr [32]uint64 + nip uint64 + msr uint64 + orig_gpr3 uint64 + ctr uint64 + link uint64 + xer uint64 + ccr uint64 + softe uint64 + trap uint64 + dar uint64 + dsisr uint64 + result uint64 +} + +type vreg struct { + u [4]uint32 +} + +type sigaltstackt struct { + ss_sp *byte + ss_flags int32 + pad_cgo_0 [4]byte + ss_size uintptr +} + +type sigcontext struct { + _unused [4]uint64 + signal int32 + _pad0 int32 + handler uint64 + oldmask uint64 + regs *ptregs + gp_regs [48]uint64 + fp_regs [33]float64 + v_regs *vreg + vmx_reserve [101]int64 +} + +type ucontext struct { + uc_flags uint64 + uc_link *ucontext + uc_stack sigaltstackt + uc_sigmask uint64 + __unused [15]uint64 + uc_mcontext sigcontext +} diff --git a/src/runtime/defs_linux_power64le.h b/src/runtime/defs_linux_power64le.h deleted file mode 100644 index 93742fa34..000000000 --- a/src/runtime/defs_linux_power64le.h +++ /dev/null @@ -1,204 +0,0 @@ -// Created by cgo -cdefs - DO NOT EDIT -// cgo -cdefs defs_linux.go defs3_linux.go - - -enum { - EINTR = 0x4, - EAGAIN = 0xb, - ENOMEM = 0xc, - - PROT_NONE = 0x0, - PROT_READ = 0x1, - PROT_WRITE = 0x2, - PROT_EXEC = 0x4, - - MAP_ANON = 0x20, - MAP_PRIVATE = 0x2, - MAP_FIXED = 0x10, - - MADV_DONTNEED = 0x4, - - SA_RESTART = 0x10000000, - SA_ONSTACK = 0x8000000, - SA_SIGINFO = 0x4, - - SIGHUP = 0x1, - SIGINT = 0x2, - SIGQUIT = 0x3, - SIGILL = 0x4, - SIGTRAP = 0x5, - SIGABRT = 0x6, - SIGBUS = 0x7, - SIGFPE = 0x8, - SIGKILL = 0x9, - SIGUSR1 = 0xa, - SIGSEGV = 0xb, - SIGUSR2 = 0xc, - SIGPIPE = 0xd, - SIGALRM = 0xe, - SIGSTKFLT = 0x10, - SIGCHLD = 0x11, - SIGCONT = 0x12, - SIGSTOP = 0x13, - SIGTSTP = 0x14, - SIGTTIN = 0x15, - SIGTTOU = 0x16, - SIGURG = 0x17, - SIGXCPU = 0x18, - SIGXFSZ = 0x19, - SIGVTALRM = 0x1a, - SIGPROF = 0x1b, - SIGWINCH = 0x1c, - SIGIO = 0x1d, - SIGPWR = 0x1e, - SIGSYS = 0x1f, - - FPE_INTDIV = 0x1, - FPE_INTOVF = 0x2, - FPE_FLTDIV = 0x3, - FPE_FLTOVF = 0x4, - FPE_FLTUND = 0x5, - FPE_FLTRES = 0x6, - FPE_FLTINV = 0x7, - FPE_FLTSUB = 0x8, - - BUS_ADRALN = 0x1, - BUS_ADRERR = 0x2, - BUS_OBJERR = 0x3, - - SEGV_MAPERR = 0x1, - SEGV_ACCERR = 0x2, - - ITIMER_REAL = 0x0, - ITIMER_VIRTUAL = 0x1, - ITIMER_PROF = 0x2, - - EPOLLIN = 0x1, - EPOLLOUT = 0x4, - EPOLLERR = 0x8, - EPOLLHUP = 0x10, - EPOLLRDHUP = 0x2000, - EPOLLET = -0x80000000, - EPOLL_CLOEXEC = 0x80000, - EPOLL_CTL_ADD = 0x1, - EPOLL_CTL_DEL = 0x2, - EPOLL_CTL_MOD = 0x3, -}; - -typedef struct Sigset Sigset; -typedef struct Timespec Timespec; -typedef struct Timeval Timeval; -typedef struct SigactionT SigactionT; -typedef struct Siginfo Siginfo; -typedef struct Itimerval Itimerval; -typedef struct EpollEvent EpollEvent; - -#pragma pack on - -//struct Sigset { -// uint64 sig[1]; -//}; -//typedef uint64 Sigset; - -struct Timespec { - int64 tv_sec; - int64 tv_nsec; -}; -struct Timeval { - int64 tv_sec; - int64 tv_usec; -}; -struct SigactionT { - void *sa_handler; - uint64 sa_flags; - void *sa_restorer; - uint64 sa_mask; -}; -struct Siginfo { - int32 si_signo; - int32 si_errno; - int32 si_code; - byte Pad_cgo_0[4]; - byte _sifields[112]; -}; -struct Itimerval { - Timeval it_interval; - Timeval it_value; -}; -struct EpollEvent { - uint32 events; - byte Pad_cgo_0[4]; - byte data[8]; // unaligned uintptr -}; - - -#pragma pack off -// Created by cgo -cdefs - DO NOT EDIT -// cgo -cdefs defs_linux.go defs3_linux.go - - -enum { - O_RDONLY = 0x0, - O_CLOEXEC = 0x80000, - SA_RESTORER = 0, -}; - -typedef struct Ptregs Ptregs; -typedef struct Vreg Vreg; -typedef struct SigaltstackT SigaltstackT; -typedef struct Sigcontext Sigcontext; -typedef struct Ucontext Ucontext; - -#pragma pack on - -struct Ptregs { - uint64 gpr[32]; - uint64 nip; - uint64 msr; - uint64 orig_gpr3; - uint64 ctr; - uint64 link; - uint64 xer; - uint64 ccr; - uint64 softe; - uint64 trap; - uint64 dar; - uint64 dsisr; - uint64 result; -}; -typedef uint64 Gregset[48]; -typedef float64 FPregset[33]; -struct Vreg { - uint32 u[4]; -}; - -struct SigaltstackT { - byte *ss_sp; - int32 ss_flags; - byte Pad_cgo_0[4]; - uint64 ss_size; -}; - -struct Sigcontext { - uint64 _unused[4]; - int32 signal; - int32 _pad0; - uint64 handler; - uint64 oldmask; - Ptregs *regs; - uint64 gp_regs[48]; - float64 fp_regs[33]; - Vreg *v_regs; - int64 vmx_reserve[101]; -}; -struct Ucontext { - uint64 uc_flags; - Ucontext *uc_link; - SigaltstackT uc_stack; - uint64 uc_sigmask; - uint64 __unused[15]; - Sigcontext uc_mcontext; -}; - - -#pragma pack off diff --git a/src/runtime/defs_plan9_386.go b/src/runtime/defs_plan9_386.go index 170506b23..212ecdf14 100644 --- a/src/runtime/defs_plan9_386.go +++ b/src/runtime/defs_plan9_386.go @@ -1,5 +1,7 @@ package runtime +const _PAGESIZE = 0x1000 + type ureg struct { di uint32 /* general registers */ si uint32 /* ... */ diff --git a/src/runtime/defs_plan9_amd64.go b/src/runtime/defs_plan9_amd64.go index 17becfb66..510da0e99 100644 --- a/src/runtime/defs_plan9_amd64.go +++ b/src/runtime/defs_plan9_amd64.go @@ -1,5 +1,7 @@ package runtime +const _PAGESIZE = 0x1000 + type ureg struct { ax uint64 bx uint64 diff --git a/src/runtime/env_plan9.go b/src/runtime/env_plan9.go index e442c3483..ec50cac48 100644 --- a/src/runtime/env_plan9.go +++ b/src/runtime/env_plan9.go @@ -54,3 +54,6 @@ func gogetenv(key string) string { sp.len = int(r) return s } + +var _cgo_setenv unsafe.Pointer // pointer to C function +var _cgo_unsetenv unsafe.Pointer // pointer to C function diff --git a/src/runtime/gengoos.go b/src/runtime/gengoos.go new file mode 100644 index 000000000..06621c8db --- /dev/null +++ b/src/runtime/gengoos.go @@ -0,0 +1,84 @@ +// Copyright 2014 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 + +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "strconv" + "strings" +) + +var gooses, goarches []string + +func main() { + data, err := ioutil.ReadFile("../go/build/syslist.go") + if err != nil { + log.Fatal(err) + } + const ( + goosPrefix = `const goosList = ` + goarchPrefix = `const goarchList = ` + ) + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, goosPrefix) { + text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix)) + if err != nil { + log.Fatalf("parsing goosList %#q: %v", strings.TrimPrefix(line, goosPrefix), err) + } + gooses = strings.Fields(text) + } + if strings.HasPrefix(line, goarchPrefix) { + text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix)) + if err != nil { + log.Fatal("parsing goarchList: %v", err) + } + goarches = strings.Fields(text) + } + } + + for _, target := range gooses { + var buf bytes.Buffer + fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n") + if target == "linux" { + fmt.Fprintf(&buf, "// +build !android\n\n") // must explicitly exclude android for linux + } + fmt.Fprintf(&buf, "package runtime\n\n") + fmt.Fprintf(&buf, "const theGoos = `%s`\n\n", target) + for _, goos := range gooses { + value := 0 + if goos == target { + value = 1 + } + fmt.Fprintf(&buf, "const goos_%s = %d\n", goos, value) + } + err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666) + if err != nil { + log.Fatal(err) + } + } + + for _, target := range goarches { + var buf bytes.Buffer + fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n") + fmt.Fprintf(&buf, "package runtime\n\n") + fmt.Fprintf(&buf, "const theGoarch = `%s`\n\n", target) + for _, goarch := range goarches { + value := 0 + if goarch == target { + value = 1 + } + fmt.Fprintf(&buf, "const goarch_%s = %d\n", goarch, value) + } + err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) + if err != nil { + log.Fatal(err) + } + } +} diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index c6f97025f..e1693d40f 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -7,7 +7,7 @@ // finalizers, etc.) to a file. // The format of the dumped file is described at -// http://code.google.com/p/go-wiki/wiki/heapdump14 +// http://golang.org/s/go14heapdump. package runtime diff --git a/src/runtime/lfstack.go b/src/runtime/lfstack.go index a4ad8a10c..fd3325972 100644 --- a/src/runtime/lfstack.go +++ b/src/runtime/lfstack.go @@ -12,6 +12,10 @@ import "unsafe" func lfstackpush(head *uint64, node *lfnode) { node.pushcnt++ new := lfstackPack(node, node.pushcnt) + if node1, _ := lfstackUnpack(new); node1 != node { + println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n") + gothrow("lfstackpush") + } for { old := atomicload64(head) node.next = old diff --git a/src/runtime/lfstack_32bit.go b/src/runtime/lfstack_32bit.go index 61d8678d9..4b8bcbac6 100644 --- a/src/runtime/lfstack_32bit.go +++ b/src/runtime/lfstack_32bit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 arm +// +build 386 arm nacl package runtime diff --git a/src/runtime/lfstack_linux_power64x.go b/src/runtime/lfstack_linux_power64x.go index 7a122bf92..89e389fc7 100644 --- a/src/runtime/lfstack_linux_power64x.go +++ b/src/runtime/lfstack_linux_power64x.go @@ -9,18 +9,24 @@ package runtime import "unsafe" -// On Power64, Linux limits the user address space to 43 bits. -// (https://www.kernel.org/doc/ols/2001/ppc64.pdf) -// In addition to the 21 bits taken from the top, we can take 3 from the -// bottom, because node must be pointer-aligned, giving a total of 24 bits +// On Power64, Linux limits the user address space to 46 bits (see +// TASK_SIZE_USER64 in the Linux kernel). This has grown over time, +// so here we allow 48 bit addresses. +// +// In addition to the 16 bits taken from the top, we can take 3 from the +// bottom, because node must be pointer-aligned, giving a total of 19 bits // of count. +const ( + addrBits = 48 + cntBits = 64 - addrBits + 3 +) func lfstackPack(node *lfnode, cnt uintptr) uint64 { - return uint64(uintptr(unsafe.Pointer(node)))<<21 | uint64(cnt&(1<<24-1)) + return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1)) } func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) { - node = (*lfnode)(unsafe.Pointer(uintptr(val >> 24 << 3))) - cnt = uintptr(val & (1<<24 - 1)) + node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3))) + cnt = uintptr(val & (1<<cntBits - 1)) return } diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 86e20b249..e9fec7bb1 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -546,6 +546,8 @@ func GC() { // linker-provided var noptrdata struct{} +var enoptrdata struct{} +var noptrbss struct{} var enoptrbss struct{} // SetFinalizer sets the finalizer associated with x to f. @@ -622,8 +624,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) { // func main() { // runtime.SetFinalizer(Foo, nil) // } - // The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss. - if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) { + // The relevant segments are: noptrdata, data, bss, noptrbss. + // We cannot assume they are in any order or even contiguous, + // due to external linking. + if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) || + uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) || + uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) || + uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) { return } gothrow("runtime.SetFinalizer: pointer not in allocated block") diff --git a/src/runtime/malloc2.go b/src/runtime/malloc2.go index 511638d3d..a9d40de30 100644 --- a/src/runtime/malloc2.go +++ b/src/runtime/malloc2.go @@ -126,7 +126,7 @@ const ( // See http://golang.org/issue/5402 and http://golang.org/issue/5236. // On other 64-bit platforms, we limit the arena to 128GB, or 37 bits. // On 32-bit, we don't bother limiting anything, so we use the full 32-bit address. - _MHeapMap_TotalBits = (_64bit*_Windows)*35 + (_64bit*(1-_Windows))*37 + (1-_64bit)*32 + _MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows))*37 + (1-_64bit)*32 _MHeapMap_Bits = _MHeapMap_TotalBits - _PageShift _MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1) diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go index 4bd40a39f..e9be5ec8c 100644 --- a/src/runtime/mem_bsd.go +++ b/src/runtime/mem_bsd.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build dragonfly freebsd netbsd openbsd solaris +// +build dragonfly freebsd nacl netbsd openbsd solaris package runtime @@ -38,7 +38,7 @@ func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer { // 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 ptrSize == 8 && uint64(n) > 1<<32 { + if ptrSize == 8 && uint64(n) > 1<<32 || goos_nacl != 0 { *reserved = false return v } diff --git a/src/runtime/mem_nacl.c b/src/runtime/mem_nacl.c deleted file mode 100644 index 6c836f18a..000000000 --- a/src/runtime/mem_nacl.c +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2010 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 "arch_GOARCH.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "malloc.h" -#include "textflag.h" - -enum -{ - Debug = 0, -}; - -#pragma textflag NOSPLIT -void* -runtime·sysAlloc(uintptr n, uint64 *stat) -{ - void *v; - - v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); - if(v < (void*)4096) { - if(Debug) - runtime·printf("sysAlloc(%p): %p\n", n, v); - return nil; - } - runtime·xadd64(stat, n); - if(Debug) - runtime·printf("sysAlloc(%p) = %p\n", n, v); - return v; -} - -void -runtime·SysUnused(void *v, uintptr n) -{ - if(Debug) - runtime·printf("SysUnused(%p, %p)\n", v, n); -} - -void -runtime·SysUsed(void *v, uintptr n) -{ - USED(v); - USED(n); -} - -void -runtime·SysFree(void *v, uintptr n, uint64 *stat) -{ - if(Debug) - runtime·printf("SysFree(%p, %p)\n", v, n); - runtime·xadd64(stat, -(uint64)n); - runtime·munmap(v, n); -} - -void -runtime·SysFault(void *v, uintptr n) -{ - runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0); -} - -void* -runtime·SysReserve(void *v, uintptr n, bool *reserved) -{ - 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(NaCl || sizeof(void*) == 8) { - *reserved = false; - return v; - } - - p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); - if(p < (void*)4096) - return nil; - *reserved = true; - return p; -} - -void -runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat) -{ - void *p; - - runtime·xadd64(stat, n); - - // On 64-bit, we don't actually have v reserved, so tread carefully. - if(!reserved) { - p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); - if(p == (void*)ENOMEM) { - runtime·printf("SysMap(%p, %p): %p\n", v, n, p); - runtime·throw("runtime: out of memory"); - } - if(p != v) { - runtime·printf("SysMap(%p, %p): %p\n", v, n, p); - runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p); - runtime·throw("runtime: address space conflict"); - } - if(Debug) - runtime·printf("SysMap(%p, %p) = %p\n", v, n, p); - return; - } - - p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0); - if(p == (void*)ENOMEM) { - runtime·printf("SysMap(%p, %p): %p\n", v, n, p); - runtime·throw("runtime: out of memory"); - } - if(p != v) { - runtime·printf("SysMap(%p, %p): %p\n", v, n, p); - runtime·printf("mmap MAP_FIXED %p returned %p\n", v, p); - runtime·throw("runtime: cannot map pages in arena address space"); - } - if(Debug) - runtime·printf("SysMap(%p, %p) = %p\n", v, n, p); -} diff --git a/src/runtime/mem_plan9.c b/src/runtime/mem_plan9.c deleted file mode 100644 index d673d6f83..000000000 --- a/src/runtime/mem_plan9.c +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2010 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 "defs_GOOS_GOARCH.h" -#include "arch_GOARCH.h" -#include "malloc.h" -#include "os_GOOS.h" -#include "textflag.h" - -extern byte runtime·end[]; -#pragma dataflag NOPTR -static byte *bloc = { runtime·end }; -static Mutex memlock; - -enum -{ - Round = PAGESIZE-1 -}; - -static void* -brk(uintptr nbytes) -{ - uintptr bl; - - runtime·lock(&memlock); - // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c - bl = ((uintptr)bloc + Round) & ~Round; - if(runtime·brk_((void*)(bl + nbytes)) < 0) { - runtime·unlock(&memlock); - return nil; - } - bloc = (byte*)bl + nbytes; - runtime·unlock(&memlock); - return (void*)bl; -} - -static void -sysalloc(void) -{ - uintptr nbytes; - uint64 *stat; - void *p; - - nbytes = g->m->scalararg[0]; - stat = g->m->ptrarg[0]; - g->m->scalararg[0] = 0; - g->m->ptrarg[0] = nil; - - p = brk(nbytes); - if(p != nil) - runtime·xadd64(stat, nbytes); - - g->m->ptrarg[0] = p; -} - -#pragma textflag NOSPLIT -void* -runtime·sysAlloc(uintptr nbytes, uint64 *stat) -{ - void (*fn)(void); - void *p; - - g->m->scalararg[0] = nbytes; - g->m->ptrarg[0] = stat; - fn = sysalloc; - runtime·onM(&fn); - p = g->m->ptrarg[0]; - g->m->ptrarg[0] = nil; - return p; -} - -void -runtime·SysFree(void *v, uintptr nbytes, uint64 *stat) -{ - runtime·xadd64(stat, -(uint64)nbytes); - runtime·lock(&memlock); - // from tiny/mem.c - // Push pointer back if this is a free - // of the most recent sysAlloc. - nbytes += (nbytes + Round) & ~Round; - if(bloc == (byte*)v+nbytes) - bloc -= nbytes; - runtime·unlock(&memlock); -} - -void -runtime·SysUnused(void *v, uintptr nbytes) -{ - USED(v, nbytes); -} - -void -runtime·SysUsed(void *v, uintptr nbytes) -{ - USED(v, nbytes); -} - -void -runtime·SysMap(void *v, uintptr nbytes, bool reserved, uint64 *stat) -{ - // SysReserve has already allocated all heap memory, - // but has not adjusted stats. - USED(v, reserved); - runtime·xadd64(stat, nbytes); -} - -void -runtime·SysFault(void *v, uintptr nbytes) -{ - USED(v, nbytes); -} - -void* -runtime·SysReserve(void *v, uintptr nbytes, bool *reserved) -{ - USED(v); - *reserved = true; - return brk(nbytes); -} diff --git a/src/runtime/mem_plan9.go b/src/runtime/mem_plan9.go new file mode 100644 index 000000000..a5d7c1a4c --- /dev/null +++ b/src/runtime/mem_plan9.go @@ -0,0 +1,70 @@ +// Copyright 2010 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 "unsafe" + +var bloc uintptr +var memlock mutex + +const memRound = _PAGESIZE - 1 + +func initBloc() { + bloc = uintptr(unsafe.Pointer(&end)) +} + +func sbrk(n uintptr) unsafe.Pointer { + lock(&memlock) + // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c + bl := (bloc + memRound) &^ memRound + if brk_(unsafe.Pointer(bl+n)) < 0 { + unlock(&memlock) + return nil + } + bloc = bl + n + unlock(&memlock) + return unsafe.Pointer(bl) +} + +func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer { + p := sbrk(n) + if p != nil { + xadd64(stat, int64(n)) + } + return p +} + +func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) { + xadd64(stat, -int64(n)) + lock(&memlock) + // from tiny/mem.c + // Push pointer back if this is a free + // of the most recent sysAlloc. + n += (n + memRound) &^ memRound + if bloc == uintptr(v)+n { + bloc -= n + } + unlock(&memlock) +} + +func sysUnused(v unsafe.Pointer, n uintptr) { +} + +func sysUsed(v unsafe.Pointer, n uintptr) { +} + +func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) { + // sysReserve has already allocated all heap memory, + // but has not adjusted stats. + xadd64(stat, int64(n)) +} + +func sysFault(v unsafe.Pointer, n uintptr) { +} + +func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer { + *reserved = true + return sbrk(n) +} diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index 00e64c0ff..7797894fc 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -51,10 +51,26 @@ func clearpools() { if c := p.mcache; c != nil { c.tiny = nil c.tinysize = 0 + + // disconnect cached list before dropping it on the floor, + // so that a dangling ref to one entry does not pin all of them. + var sg, sgnext *sudog + for sg = c.sudogcache; sg != nil; sg = sgnext { + sgnext = sg.next + sg.next = nil + } c.sudogcache = nil } + // clear defer pools for i := range p.deferpool { + // disconnect cached list before dropping it on the floor, + // so that a dangling ref to one entry does not pin all of them. + var d, dlink *_defer + for d = p.deferpool[i]; d != nil; d = dlink { + dlink = d.link + d.link = nil + } p.deferpool[i] = nil } } diff --git a/src/runtime/netpoll_stub.c b/src/runtime/netpoll_stub.go index b7a8f2944..6c7e79ea3 100644 --- a/src/runtime/netpoll_stub.c +++ b/src/runtime/netpoll_stub.go @@ -4,15 +4,12 @@ // +build plan9 -#include "runtime.h" +package runtime // Polls for ready network connections. // Returns list of goroutines that become runnable. -G* -runtime·netpoll(bool block) -{ +func netpoll(block bool) (gp *g) { // Implementation for platforms that do not support // integrated network poller. - USED(block); - return nil; + return } diff --git a/src/runtime/netpoll_windows.go b/src/runtime/netpoll_windows.go index 88e878137..23d5dc00f 100644 --- a/src/runtime/netpoll_windows.go +++ b/src/runtime/netpoll_windows.go @@ -108,7 +108,7 @@ retry: op = entries[i].op errno = 0 qty = 0 - if stdcall5(_WSAGetOverlappedResult, netpollfd(op.pd), uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 { + if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 { errno = int32(getlasterror()) } handlecompletion(&gp, op, errno, qty) @@ -152,5 +152,5 @@ func handlecompletion(gpp **g, op *net_op, errno int32, qty uint32) { } op.errno = errno op.qty = qty - netpollready(gpp, op.pd, mode) + netpollready((**g)(noescape(unsafe.Pointer(gpp))), op.pd, mode) } diff --git a/src/runtime/os1_nacl.go b/src/runtime/os1_nacl.go new file mode 100644 index 000000000..7b4c99a3d --- /dev/null +++ b/src/runtime/os1_nacl.go @@ -0,0 +1,197 @@ +// Copyright 2010 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 "unsafe" + +// Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +func mpreinit(mp *m) { + mp.gsignal = malg(32 * 1024) + mp.gsignal.m = mp +} + +func sigtramp() + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. +func minit() { + _g_ := getg() + + // Initialize signal handling + ret := nacl_exception_stack(_g_.m.gsignal.stack.lo, 32*1024) + if ret < 0 { + print("runtime: nacl_exception_stack: error ", -ret, "\n") + } + + ret = nacl_exception_handler(funcPC(sigtramp), nil) + if ret < 0 { + print("runtime: nacl_exception_handler: error ", -ret, "\n") + } +} + +// Called from dropm to undo the effect of an minit. +func unminit() { +} + +func osinit() { + ncpu = 1 + getg().m.procid = 2 + //nacl_exception_handler(funcPC(sigtramp), nil); +} + +func crash() { + *(*int32)(nil) = 0 +} + +//go:nosplit +func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) { + *rnd = nil + *rnd_len = 0 +} + +func goenvs() { + goenvs_unix() +} + +func initsig() { +} + +//go:nosplit +func usleep(us uint32) { + var ts timespec + + ts.tv_sec = int64(us / 1e6) + ts.tv_nsec = int32(us%1e6) * 1e3 + nacl_nanosleep(&ts, nil) +} + +func mstart_nacl() + +func newosproc(mp *m, stk unsafe.Pointer) { + tls := (*[3]unsafe.Pointer)(unsafe.Pointer(&mp.tls)) + tls[0] = unsafe.Pointer(mp.g0) + tls[1] = unsafe.Pointer(mp) + ret := nacl_thread_create(funcPC(mstart_nacl), stk, unsafe.Pointer(&tls[2]), nil) + if ret < 0 { + print("nacl_thread_create: error ", -ret, "\n") + gothrow("newosproc") + } +} + +//go:nosplit +func semacreate() uintptr { + var cond uintptr + systemstack(func() { + mu := nacl_mutex_create(0) + if mu < 0 { + print("nacl_mutex_create: error ", -mu, "\n") + gothrow("semacreate") + } + c := nacl_cond_create(0) + if c < 0 { + print("nacl_cond_create: error ", -cond, "\n") + gothrow("semacreate") + } + cond = uintptr(c) + _g_ := getg() + _g_.m.waitsemalock = uint32(mu) + }) + return cond +} + +//go:nosplit +func semasleep(ns int64) int32 { + var ret int32 + + systemstack(func() { + _g_ := getg() + if nacl_mutex_lock(int32(_g_.m.waitsemalock)) < 0 { + gothrow("semasleep") + } + + for _g_.m.waitsemacount == 0 { + if ns < 0 { + if nacl_cond_wait(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock)) < 0 { + gothrow("semasleep") + } + } else { + var ts timespec + end := ns + nanotime() + ts.tv_sec = end / 1e9 + ts.tv_nsec = int32(end % 1e9) + r := nacl_cond_timed_wait_abs(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock), &ts) + if r == -_ETIMEDOUT { + nacl_mutex_unlock(int32(_g_.m.waitsemalock)) + ret = -1 + return + } + if r < 0 { + gothrow("semasleep") + } + } + } + + _g_.m.waitsemacount = 0 + nacl_mutex_unlock(int32(_g_.m.waitsemalock)) + ret = 0 + }) + return ret +} + +//go:nosplit +func semawakeup(mp *m) { + systemstack(func() { + if nacl_mutex_lock(int32(mp.waitsemalock)) < 0 { + gothrow("semawakeup") + } + if mp.waitsemacount != 0 { + gothrow("semawakeup") + } + mp.waitsemacount = 1 + nacl_cond_signal(int32(mp.waitsema)) + nacl_mutex_unlock(int32(mp.waitsemalock)) + }) +} + +func memlimit() uintptr { + return 0 +} + +// This runs on a foreign stack, without an m or a g. No stack split. +//go:nosplit +func badsignal2() { + write(2, unsafe.Pointer(&badsignal1[0]), int32(len(badsignal1))) + exit(2) +} + +var badsignal1 = []byte("runtime: signal received on thread not created by Go.\n") + +func madvise(addr unsafe.Pointer, n uintptr, flags int32) {} +func munmap(addr unsafe.Pointer, n uintptr) {} +func resetcpuprofiler(hz int32) {} +func sigdisable(uint32) {} +func sigenable(uint32) {} +func closeonexec(int32) {} + +var writelock uint32 // test-and-set spin lock for write + +/* +An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s. + +void (*nacl_irt_query)(void); + +int8 nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1"; +void *nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf +int32 nacl_irt_basic_v0_1_size = sizeof(nacl_irt_basic_v0_1); + +int8 nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3"; +void *nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect +int32 nacl_irt_memory_v0_3_size = sizeof(nacl_irt_memory_v0_3); + +int8 nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1"; +void *nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice +int32 nacl_irt_thread_v0_1_size = sizeof(nacl_irt_thread_v0_1); +*/ diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go new file mode 100644 index 000000000..493be30fa --- /dev/null +++ b/src/runtime/os1_netbsd.go @@ -0,0 +1,265 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import "unsafe" + +const ( + _ESRCH = 3 + _ENOTSUP = 91 + + // From NetBSD's <sys/time.h> + _CLOCK_REALTIME = 0 + _CLOCK_VIRTUAL = 1 + _CLOCK_PROF = 2 + _CLOCK_MONOTONIC = 3 +) + +var sigset_none = sigset{} +var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}} + +// From NetBSD's <sys/sysctl.h> +const ( + _CTL_HW = 6 + _HW_NCPU = 3 +) + +func getncpu() int32 { + mib := [2]uint32{_CTL_HW, _HW_NCPU} + out := uint32(0) + nout := unsafe.Sizeof(out) + ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) + if ret >= 0 { + return int32(out) + } + return 1 +} + +//go:nosplit +func semacreate() uintptr { + return 1 +} + +//go:nosplit +func semasleep(ns int64) int32 { + _g_ := getg() + + // spin-mutex lock + for { + if xchg(&_g_.m.waitsemalock, 1) == 0 { + break + } + osyield() + } + + for { + // lock held + if _g_.m.waitsemacount == 0 { + // sleep until semaphore != 0 or timeout. + // thrsleep unlocks m.waitsemalock. + if ns < 0 { + // TODO(jsing) - potential deadlock! + // + // There is a potential deadlock here since we + // have to release the waitsemalock mutex + // before we call lwp_park() to suspend the + // thread. This allows another thread to + // release the lock and call lwp_unpark() + // before the thread is actually suspended. + // If this occurs the current thread will end + // up sleeping indefinitely. Unfortunately + // the NetBSD kernel does not appear to provide + // a mechanism for unlocking the userspace + // mutex once the thread is actually parked. + atomicstore(&_g_.m.waitsemalock, 0) + lwp_park(nil, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil) + } else { + var ts timespec + var nsec int32 + ns += nanotime() + ts.set_sec(timediv(ns, 1000000000, &nsec)) + ts.set_nsec(nsec) + // TODO(jsing) - potential deadlock! + // See above for details. + atomicstore(&_g_.m.waitsemalock, 0) + lwp_park(&ts, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil) + } + // reacquire lock + for { + if xchg(&_g_.m.waitsemalock, 1) == 0 { + break + } + osyield() + } + } + + // lock held (again) + if _g_.m.waitsemacount != 0 { + // semaphore is available. + _g_.m.waitsemacount-- + // spin-mutex unlock + atomicstore(&_g_.m.waitsemalock, 0) + return 0 + } + + // semaphore not available. + // if there is a timeout, stop now. + // otherwise keep trying. + if ns >= 0 { + break + } + } + + // lock held but giving up + // spin-mutex unlock + atomicstore(&_g_.m.waitsemalock, 0) + return -1 +} + +//go:nosplit +func semawakeup(mp *m) { + // spin-mutex lock + for { + if xchg(&mp.waitsemalock, 1) == 0 { + break + } + osyield() + } + + mp.waitsemacount++ + // TODO(jsing) - potential deadlock, see semasleep() for details. + // Confirm that LWP is parked before unparking... + ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount)) + if ret != 0 && ret != _ESRCH { + // semawakeup can be called on signal stack. + systemstack(func() { + print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n") + }) + } + + // spin-mutex unlock + atomicstore(&mp.waitsemalock, 0) +} + +func newosproc(mp *m, stk unsafe.Pointer) { + if false { + print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n") + } + + mp.tls[0] = uintptr(mp.id) // so 386 asm can find it + + var uc ucontextt + getcontext(unsafe.Pointer(&uc)) + + uc.uc_flags = _UC_SIGMASK | _UC_CPU + uc.uc_link = nil + uc.uc_sigmask = sigset_all + + lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(mstart)) + + ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid)) + if ret < 0 { + print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n") + gothrow("runtime.newosproc") + } +} + +func osinit() { + ncpu = getncpu() +} + +var urandom_data [_HashRandomBytes]byte +var urandom_dev = []byte("/dev/urandom\x00") + +//go:nosplit +func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) { + fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) + if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes { + *rnd = unsafe.Pointer(&urandom_data[0]) + *rnd_len = _HashRandomBytes + } else { + *rnd = nil + *rnd_len = 0 + } + close(fd) +} + +func goenvs() { + goenvs_unix() +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +func mpreinit(mp *m) { + mp.gsignal = malg(32 * 1024) + mp.gsignal.m = mp +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. +func minit() { + _g_ := getg() + _g_.m.procid = uint64(lwp_self()) + + // Initialize signal handling + signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024) + sigprocmask(_SIG_SETMASK, &sigset_none, nil) +} + +// Called from dropm to undo the effect of an minit. +func unminit() { + signalstack(nil, 0) +} + +func memlimit() uintptr { + return 0 +} + +func sigtramp() + +type sigactiont struct { + sa_sigaction uintptr + sa_mask sigset + sa_flags int32 +} + +func setsig(i int32, fn uintptr, restart bool) { + var sa sigactiont + sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK + if restart { + sa.sa_flags |= _SA_RESTART + } + sa.sa_mask = sigset_all + if fn == funcPC(sighandler) { + fn = funcPC(sigtramp) + } + sa.sa_sigaction = fn + sigaction(i, &sa, nil) +} + +func getsig(i int32) uintptr { + var sa sigactiont + sigaction(i, nil, &sa) + if sa.sa_sigaction == funcPC(sigtramp) { + return funcPC(sighandler) + } + return sa.sa_sigaction +} + +func signalstack(p *byte, n int32) { + var st sigaltstackt + + st.ss_sp = uintptr(unsafe.Pointer(p)) + st.ss_size = uintptr(n) + st.ss_flags = 0 + if p == nil { + st.ss_flags = _SS_DISABLE + } + sigaltstack(&st, nil) +} + +func unblocksignals() { + sigprocmask(_SIG_SETMASK, &sigset_none, nil) +} diff --git a/src/runtime/os1_netbsd_386.go b/src/runtime/os1_netbsd_386.go new file mode 100644 index 000000000..037f7e36d --- /dev/null +++ b/src/runtime/os1_netbsd_386.go @@ -0,0 +1,16 @@ +// 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. + +package runtime + +import "unsafe" + +func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { + // Machine dependent mcontext initialisation for LWP. + mc.__gregs[_REG_EIP] = uint32(funcPC(lwp_tramp)) + mc.__gregs[_REG_UESP] = uint32(uintptr(stk)) + mc.__gregs[_REG_EBX] = uint32(uintptr(unsafe.Pointer(mp))) + mc.__gregs[_REG_EDX] = uint32(uintptr(unsafe.Pointer(gp))) + mc.__gregs[_REG_ESI] = uint32(fn) +} diff --git a/src/runtime/os1_netbsd_amd64.go b/src/runtime/os1_netbsd_amd64.go new file mode 100644 index 000000000..5118b0c4f --- /dev/null +++ b/src/runtime/os1_netbsd_amd64.go @@ -0,0 +1,16 @@ +// 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. + +package runtime + +import "unsafe" + +func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { + // Machine dependent mcontext initialisation for LWP. + mc.__gregs[_REG_RIP] = uint64(funcPC(lwp_tramp)) + mc.__gregs[_REG_RSP] = uint64(uintptr(stk)) + mc.__gregs[_REG_R8] = uint64(uintptr(unsafe.Pointer(mp))) + mc.__gregs[_REG_R9] = uint64(uintptr(unsafe.Pointer(gp))) + mc.__gregs[_REG_R12] = uint64(fn) +} diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go new file mode 100644 index 000000000..0f8da03f2 --- /dev/null +++ b/src/runtime/os1_plan9.go @@ -0,0 +1,270 @@ +// Copyright 2010 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 "unsafe" + +// Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +func mpreinit(mp *m) { + // Initialize stack and goroutine for note handling. + mp.gsignal = malg(32 * 1024) + mp.gsignal.m = mp + mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, _FlagNoScan)) + // Initialize stack for handling strings from the + // errstr system call, as used in package syscall. + mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, _FlagNoScan)) +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. +func minit() { + // Mask all SSE floating-point exceptions + // when running on the 64-bit kernel. + setfpmasks() +} + +// Called from dropm to undo the effect of an minit. +func unminit() { +} + +var sysstat = []byte("/dev/sysstat\x00") + +func getproccount() int32 { + var buf [2048]byte + fd := open(&sysstat[0], _OREAD, 0) + if fd < 0 { + return 1 + } + ncpu := int32(0) + for { + n := read(fd, unsafe.Pointer(&buf), int32(len(buf))) + if n <= 0 { + break + } + for i := int32(0); i < n; i++ { + if buf[i] == '\n' { + ncpu++ + } + } + } + close(fd) + if ncpu == 0 { + ncpu = 1 + } + return ncpu +} + +var pid = []byte("#c/pid\x00") + +func getpid() uint64 { + var b [20]byte + fd := open(&pid[0], 0, 0) + if fd >= 0 { + read(fd, unsafe.Pointer(&b), int32(len(b))) + close(fd) + } + c := b[:] + for c[0] == ' ' || c[0] == '\t' { + c = c[1:] + } + return uint64(atoi(c)) +} + +func osinit() { + initBloc() + ncpu = getproccount() + getg().m.procid = getpid() + notify(unsafe.Pointer(funcPC(sigtramp))) +} + +func crash() { + notify(nil) + *(*int)(nil) = 0 +} + +var random_data [_HashRandomBytes]byte +var random_dev = []byte("/dev/random\x00") + +//go:nosplit +func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) { + fd := open(&random_dev[0], 0 /* O_RDONLY */, 0) + if read(fd, unsafe.Pointer(&random_data), _HashRandomBytes) == _HashRandomBytes { + *rnd = unsafe.Pointer(&random_data[0]) + *rnd_len = _HashRandomBytes + } else { + *rnd = nil + *rnd_len = 0 + } + close(fd) +} + +func goenvs() { +} + +func initsig() { +} + +//go:nosplit +func osyield() { + sleep(0) +} + +//go:nosplit +func usleep(µs uint32) { + ms := int32(µs / 1000) + if ms == 0 { + ms = 1 + } + sleep(ms) +} + +//go:nosplit +func nanotime() int64 { + var scratch int64 + ns := nsec(&scratch) + // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. + if ns == 0 { + return scratch + } + return ns +} + +//go:nosplit +func itoa(buf []byte, val uint64) []byte { + i := len(buf) - 1 + for val >= 10 { + buf[i] = byte(val%10 + '0') + i-- + val /= 10 + } + buf[i] = byte(val + '0') + return buf[i:] +} + +var goexits = []byte("go: exit ") + +func goexitsall(status *byte) { + var buf [_ERRMAX]byte + n := copy(buf[:], goexits) + n = copy(buf[n:], gostringnocopy(status)) + pid := getpid() + for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { + if mp.procid != pid { + postnote(mp.procid, buf[:]) + } + } +} + +var procdir = []byte("/proc/") +var notefile = []byte("/note\x00") + +func postnote(pid uint64, msg []byte) int { + var buf [128]byte + var tmp [32]byte + n := copy(buf[:], procdir) + n += copy(buf[n:], itoa(tmp[:], pid)) + copy(buf[n:], notefile) + fd := open(&buf[0], _OWRITE, 0) + if fd < 0 { + return -1 + } + len := findnull(&msg[0]) + if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) { + close(fd) + return -1 + } + close(fd) + return 0 +} + +//go:nosplit +func exit(e int) { + var status []byte + if e == 0 { + status = []byte("\x00") + } else { + // build error string + var tmp [32]byte + status = []byte(gostringnocopy(&itoa(tmp[:], uint64(e))[0]) + "\x00") + } + goexitsall(&status[0]) + exits(&status[0]) +} + +func newosproc(mp *m, stk unsafe.Pointer) { + if false { + print("newosproc mp=", mp, " ostk=", &mp, "\n") + } + pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT) + if pid < 0 { + gothrow("newosproc: rfork failed") + } + if pid == 0 { + tstart_plan9(mp) + } +} + +//go:nosplit +func semacreate() uintptr { + return 1 +} + +//go:nosplit +func semasleep(ns int64) int { + _g_ := getg() + if ns >= 0 { + ms := timediv(ns, 1000000, nil) + if ms == 0 { + ms = 1 + } + ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms) + if ret == 1 { + return 0 // success + } + return -1 // timeout or interrupted + } + for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 { + // interrupted; try again (c.f. lock_sema.go) + } + return 0 // success +} + +//go:nosplit +func semawakeup(mp *m) { + plan9_semrelease(&mp.waitsemacount, 1) +} + +//go:nosplit +func read(fd int32, buf unsafe.Pointer, n int32) int32 { + return pread(fd, buf, n, -1) +} + +//go:nosplit +func write(fd uintptr, buf unsafe.Pointer, n int32) int64 { + return int64(pwrite(int32(fd), buf, n, -1)) +} + +func memlimit() uint64 { + return 0 +} + +var _badsignal = []byte("runtime: signal received on thread not created by Go.\n") + +// This runs on a foreign stack, without an m or a g. No stack split. +//go:nosplit +func badsignal2() { + pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1) + exits(&_badsignal[0]) +} + +func atoi(b []byte) int { + n := 0 + for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { + n = n*10 + int(b[0]) - '0' + b = b[1:] + } + return n +} diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go new file mode 100644 index 000000000..57ea050f2 --- /dev/null +++ b/src/runtime/os1_windows.go @@ -0,0 +1,564 @@ +// 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. + +package runtime + +import ( + "unsafe" +) + +//go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll" +//go:cgo_import_dynamic runtime._CloseHandle CloseHandle "kernel32.dll" +//go:cgo_import_dynamic runtime._CreateEventA CreateEventA "kernel32.dll" +//go:cgo_import_dynamic runtime._CreateThread CreateThread "kernel32.dll" +//go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA "kernel32.dll" +//go:cgo_import_dynamic runtime._CryptAcquireContextW CryptAcquireContextW "advapi32.dll" +//go:cgo_import_dynamic runtime._CryptGenRandom CryptGenRandom "advapi32.dll" +//go:cgo_import_dynamic runtime._CryptReleaseContext CryptReleaseContext "advapi32.dll" +//go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle "kernel32.dll" +//go:cgo_import_dynamic runtime._ExitProcess ExitProcess "kernel32.dll" +//go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll" +//go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll" +//go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress "kernel32.dll" +//go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle "kernel32.dll" +//go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo "kernel32.dll" +//go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext "kernel32.dll" +//go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW "kernel32.dll" +//go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA "kernel32.dll" +//go:cgo_import_dynamic runtime._NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll" +//go:cgo_import_dynamic runtime._ResumeThread ResumeThread "kernel32.dll" +//go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll" +//go:cgo_import_dynamic runtime._SetEvent SetEvent "kernel32.dll" +//go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll" +//go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority "kernel32.dll" +//go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll" +//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer "kernel32.dll" +//go:cgo_import_dynamic runtime._Sleep Sleep "kernel32.dll" +//go:cgo_import_dynamic runtime._SuspendThread SuspendThread "kernel32.dll" +//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject "kernel32.dll" +//go:cgo_import_dynamic runtime._WriteFile WriteFile "kernel32.dll" +//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod "winmm.dll" + +var ( + _AddVectoredExceptionHandler, + _CloseHandle, + _CreateEventA, + _CreateThread, + _CreateWaitableTimerA, + _CryptAcquireContextW, + _CryptGenRandom, + _CryptReleaseContext, + _DuplicateHandle, + _ExitProcess, + _FreeEnvironmentStringsW, + _GetEnvironmentStringsW, + _GetProcAddress, + _GetStdHandle, + _GetSystemInfo, + _GetThreadContext, + _LoadLibraryW, + _LoadLibraryA, + _NtWaitForSingleObject, + _ResumeThread, + _SetConsoleCtrlHandler, + _SetEvent, + _SetProcessPriorityBoost, + _SetThreadPriority, + _SetUnhandledExceptionFilter, + _SetWaitableTimer, + _Sleep, + _SuspendThread, + _WaitForSingleObject, + _WriteFile, + _timeBeginPeriod stdFunction +) + +var _GetQueuedCompletionStatusEx stdFunction + +// in sys_windows_386.s and sys_windows_amd64.s +func externalthreadhandler() +func exceptiontramp() +func firstcontinuetramp() +func lastcontinuetramp() + +//go:nosplit +func getLoadLibrary() uintptr { + return uintptr(unsafe.Pointer(_LoadLibraryW)) +} + +//go:nosplit +func getGetProcAddress() uintptr { + return uintptr(unsafe.Pointer(_GetProcAddress)) +} + +func getproccount() int32 { + var info systeminfo + stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info))) + return int32(info.dwnumberofprocessors) +} + +const ( + currentProcess = ^uintptr(0) // -1 = current process + currentThread = ^uintptr(1) // -2 = current thread +) + +var ( + kernel32Name = []byte("kernel32.dll\x00") + addVectoredContinueHandlerName = []byte("AddVectoredContinueHandler\x00") + getQueuedCompletionStatusExName = []byte("GetQueuedCompletionStatusEx\x00") +) + +func osinit() { + setBadSignalMsg() + + kernel32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32Name[0]))) + + externalthreadhandlerp = funcPC(externalthreadhandler) + + stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp)) + addVectoredContinueHandler := uintptr(0) + if kernel32 != 0 { + addVectoredContinueHandler = stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&addVectoredContinueHandlerName[0]))) + } + if addVectoredContinueHandler == 0 || unsafe.Sizeof(&kernel32) == 4 { + // use SetUnhandledExceptionFilter for windows-386 or + // if VectoredContinueHandler is unavailable. + // note: SetUnhandledExceptionFilter handler won't be called, if debugging. + stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp)) + } else { + stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 1, funcPC(firstcontinuetramp)) + stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 0, funcPC(lastcontinuetramp)) + } + + stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) + + stdcall1(_timeBeginPeriod, 1) + + ncpu = getproccount() + + // Windows dynamic priority boosting assumes that a process has different types + // of dedicated threads -- GUI, IO, computational, etc. Go processes use + // equivalent threads that all do a mix of GUI, IO, computations, etc. + // In such context dynamic priority boosting does nothing but harm, so we turn it off. + stdcall2(_SetProcessPriorityBoost, currentProcess, 1) + + if kernel32 != 0 { + _GetQueuedCompletionStatusEx = stdFunction(unsafe.Pointer(stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&getQueuedCompletionStatusExName[0]))))) + } +} + +var random_data [_HashRandomBytes]byte + +//go:nosplit +func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) { + const ( + prov_rsa_full = 1 + crypt_verifycontext = 0xF0000000 + ) + var handle uintptr + *rnd = nil + *rnd_len = 0 + if stdcall5(_CryptAcquireContextW, uintptr(unsafe.Pointer(&handle)), 0, 0, prov_rsa_full, crypt_verifycontext) != 0 { + if stdcall3(_CryptGenRandom, handle, _HashRandomBytes, uintptr(unsafe.Pointer(&random_data[0]))) != 0 { + *rnd = unsafe.Pointer(&random_data[0]) + *rnd_len = _HashRandomBytes + } + stdcall2(_CryptReleaseContext, handle, 0) + } +} + +func goenvs() { + var p *uint16 + + env := (*uint16)(unsafe.Pointer(stdcall0(_GetEnvironmentStringsW))) + + n := 0 + for p = env; *p != 0; n++ { + p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)*unsafe.Sizeof(*p))) + } + + envs = makeStringSlice(int(n)) + + p = env + for i := 0; i < n; i++ { + envs[i] = gostringw(p) + p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)*unsafe.Sizeof(*p))) + } + + stdcall1(_FreeEnvironmentStringsW, uintptr(unsafe.Pointer(env))) +} + +//go:nosplit +func exit(code int32) { + stdcall1(_ExitProcess, uintptr(code)) +} + +//go:nosplit +func write(fd uintptr, buf unsafe.Pointer, n int32) int32 { + const ( + _STD_OUTPUT_HANDLE = ^uintptr(10) // -11 + _STD_ERROR_HANDLE = ^uintptr(11) // -12 + ) + var handle uintptr + switch fd { + case 1: + handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE) + case 2: + handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE) + default: + // assume fd is real windows handle. + handle = fd + } + var written uint32 + stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0) + return int32(written) +} + +//go:nosplit +func semasleep(ns int64) int32 { + // store ms in ns to save stack space + if ns < 0 { + ns = _INFINITE + } else { + ns = int64(timediv(ns, 1000000, nil)) + if ns == 0 { + ns = 1 + } + } + if stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) != 0 { + return -1 // timeout + } + return 0 +} + +//go:nosplit +func semawakeup(mp *m) { + stdcall1(_SetEvent, mp.waitsema) +} + +//go:nosplit +func semacreate() uintptr { + return stdcall4(_CreateEventA, 0, 0, 0, 0) +} + +func newosproc(mp *m, stk unsafe.Pointer) { + const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000 + thandle := stdcall6(_CreateThread, 0, 0x20000, + funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)), + _STACK_SIZE_PARAM_IS_A_RESERVATION, 0) + if thandle == 0 { + println("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")") + gothrow("runtime.newosproc") + } +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +func mpreinit(mp *m) { +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. +func minit() { + var thandle uintptr + stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) + atomicstoreuintptr(&getg().m.thread, thandle) +} + +// Called from dropm to undo the effect of an minit. +func unminit() { + tp := &getg().m.thread + stdcall1(_CloseHandle, *tp) + *tp = 0 +} + +// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/ +type _KSYSTEM_TIME struct { + LowPart uint32 + High1Time int32 + High2Time int32 +} + +const ( + _INTERRUPT_TIME = 0x7ffe0008 + _SYSTEM_TIME = 0x7ffe0014 +) + +//go:nosplit +func systime(addr uintptr) int64 { + timeaddr := (*_KSYSTEM_TIME)(unsafe.Pointer(addr)) + + var t _KSYSTEM_TIME + for i := 1; i < 10000; i++ { + // these fields must be read in that order (see URL above) + t.High1Time = timeaddr.High1Time + t.LowPart = timeaddr.LowPart + t.High2Time = timeaddr.High2Time + if t.High1Time == t.High2Time { + return int64(t.High1Time)<<32 | int64(t.LowPart) + } + if (i % 100) == 0 { + osyield() + } + } + systemstack(func() { + gothrow("interrupt/system time is changing too fast") + }) + return 0 +} + +//go:nosplit +func unixnano() int64 { + return (systime(_SYSTEM_TIME) - 116444736000000000) * 100 +} + +//go:nosplit +func nanotime() int64 { + return systime(_INTERRUPT_TIME) * 100 +} + +// Calling stdcall on os stack. +//go:nosplit +func stdcall(fn stdFunction) uintptr { + gp := getg() + mp := gp.m + mp.libcall.fn = uintptr(unsafe.Pointer(fn)) + + if mp.profilehz != 0 { + // leave pc/sp for cpu profiler + mp.libcallg = gp + mp.libcallpc = getcallerpc(unsafe.Pointer(&fn)) + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp(unsafe.Pointer(&fn)) + } + asmcgocall(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&mp.libcall)) + mp.libcallsp = 0 + return mp.libcall.r1 +} + +//go:nosplit +func stdcall0(fn stdFunction) uintptr { + mp := getg().m + mp.libcall.n = 0 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes + return stdcall(fn) +} + +//go:nosplit +func stdcall1(fn stdFunction, a0 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 1 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +//go:nosplit +func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 2 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +//go:nosplit +func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 3 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +//go:nosplit +func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 4 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +//go:nosplit +func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 5 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +//go:nosplit +func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 6 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +//go:nosplit +func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr { + mp := getg().m + mp.libcall.n = 7 + mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) + return stdcall(fn) +} + +// in sys_windows_386.s and sys_windows_amd64.s +func usleep1(usec uint32) + +//go:nosplit +func osyield() { + usleep1(1) +} + +//go:nosplit +func usleep(us uint32) { + // Have 1us units; want 100ns units. + usleep1(10 * us) +} + +func issigpanic(code uint32) uint32 { + switch code { + default: + return 0 + case _EXCEPTION_ACCESS_VIOLATION: + case _EXCEPTION_INT_DIVIDE_BY_ZERO: + case _EXCEPTION_INT_OVERFLOW: + case _EXCEPTION_FLT_DENORMAL_OPERAND: + case _EXCEPTION_FLT_DIVIDE_BY_ZERO: + case _EXCEPTION_FLT_INEXACT_RESULT: + case _EXCEPTION_FLT_OVERFLOW: + case _EXCEPTION_FLT_UNDERFLOW: + case _EXCEPTION_BREAKPOINT: + } + return 1 +} + +func initsig() { + /* + // TODO(brainman): I don't think we need that bit of code + // following line keeps these functions alive at link stage + // if there's a better way please write it here + void *e = runtime·exceptiontramp; + void *f = runtime·firstcontinuetramp; + void *l = runtime·lastcontinuetramp; + USED(e); + USED(f); + USED(l); + */ +} + +func ctrlhandler1(_type uint32) uint32 { + var s uint32 + + switch _type { + case _CTRL_C_EVENT, _CTRL_BREAK_EVENT: + s = _SIGINT + default: + return 0 + } + + if sigsend(s) { + return 1 + } + exit(2) // SIGINT, SIGTERM, etc + return 0 +} + +// in sys_windows_386.s and sys_windows_amd64.s +func profileloop() + +var profiletimer uintptr + +func profilem(mp *m) { + var r *context + rbuf := make([]byte, unsafe.Sizeof(*r)+15) + + tls := &mp.tls[0] + if mp == &m0 { + tls = &tls0[0] + } + gp := *((**g)(unsafe.Pointer(tls))) + + // align Context to 16 bytes + r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15)) + r.contextflags = _CONTEXT_CONTROL + stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r))) + dosigprof(r, gp, mp) +} + +func profileloop1() { + stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST) + + for { + stdcall2(_WaitForSingleObject, profiletimer, _INFINITE) + first := (*m)(atomicloadp(unsafe.Pointer(&allm))) + for mp := first; mp != nil; mp = mp.alllink { + thread := atomicloaduintptr(&mp.thread) + // Do not profile threads blocked on Notes, + // this includes idle worker threads, + // idle timer thread, idle heap scavenger, etc. + if thread == 0 || mp.profilehz == 0 || mp.blocked { + continue + } + stdcall1(_SuspendThread, thread) + if mp.profilehz != 0 && !mp.blocked { + profilem(mp) + } + stdcall1(_ResumeThread, thread) + } + } +} + +var cpuprofilerlock mutex + +func resetcpuprofiler(hz int32) { + lock(&cpuprofilerlock) + if profiletimer == 0 { + timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0) + atomicstoreuintptr(&profiletimer, timer) + thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0) + stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST) + stdcall1(_CloseHandle, thread) + } + unlock(&cpuprofilerlock) + + ms := int32(0) + due := ^int64(^uint64(1 << 63)) + if hz > 0 { + ms = 1000 / hz + if ms == 0 { + ms = 1 + } + due = int64(ms) * -10000 + } + stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0) + atomicstore((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) +} + +func memlimit() uintptr { + return 0 +} + +var ( + badsignalmsg [100]byte + badsignallen int32 +) + +func setBadSignalMsg() { + const msg = "runtime: signal received on thread not created by Go.\n" + for i, c := range msg { + badsignalmsg[i] = byte(c) + badsignallen++ + } +} + +func crash() { + // TODO: This routine should do whatever is needed + // to make the Windows program abort/crash as it + // would if Go was not intercepting signals. + // On Unix the routine would remove the custom signal + // handler and then raise a signal (like SIGABRT). + // Something like that should happen here. + // It's okay to leave this empty for now: if crash returns + // the ordinary exit-after-panic happens. +} diff --git a/src/runtime/os1_windows_386.go b/src/runtime/os1_windows_386.go new file mode 100644 index 000000000..0afef9156 --- /dev/null +++ b/src/runtime/os1_windows_386.go @@ -0,0 +1,118 @@ +// 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. + +package runtime + +import ( + "unsafe" +) + +var text struct{} + +func dumpregs(r *context) { + print("eax ", hex(r.eax), "\n") + print("ebx ", hex(r.ebx), "\n") + print("ecx ", hex(r.ecx), "\n") + print("edx ", hex(r.edx), "\n") + print("edi ", hex(r.edi), "\n") + print("esi ", hex(r.esi), "\n") + print("ebp ", hex(r.ebp), "\n") + print("esp ", hex(r.esp), "\n") + print("eip ", hex(r.eip), "\n") + print("eflags ", hex(r.eflags), "\n") + print("cs ", hex(r.segcs), "\n") + print("fs ", hex(r.segfs), "\n") + print("gs ", hex(r.seggs), "\n") +} + +func isgoexception(info *exceptionrecord, r *context) bool { + // Only handle exception if executing instructions in Go binary + // (not Windows library code). + if r.eip < uint32(uintptr(unsafe.Pointer(&text))) || uint32(uintptr(unsafe.Pointer(&etext))) < r.eip { + return false + } + + if issigpanic(info.exceptioncode) == 0 { + return false + } + + return true +} + +// Called by sigtramp from Windows VEH handler. +// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) +// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH). +func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { + if !isgoexception(info, r) { + return _EXCEPTION_CONTINUE_SEARCH + } + + // Make it look like a call to the signal func. + // Have to pass arguments out of band since + // augmenting the stack frame would break + // the unwinding code. + gp.sig = info.exceptioncode + gp.sigcode0 = uintptr(info.exceptioninformation[0]) + gp.sigcode1 = uintptr(info.exceptioninformation[1]) + gp.sigpc = uintptr(r.eip) + + // Only push runtime·sigpanic if r->eip != 0. + // If r->eip == 0, probably panicked because of a + // call to a nil func. Not pushing that onto sp will + // make the trace look like a call to runtime·sigpanic instead. + // (Otherwise the trace will end at runtime·sigpanic and we + // won't get to see who faulted.) + if r.eip != 0 { + sp := unsafe.Pointer(uintptr(r.esp)) + sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp-- + *((*uintptr)(sp)) = uintptr(r.eip) + r.esp = uint32(uintptr(sp)) + } + r.eip = uint32(funcPC(sigpanic)) + return _EXCEPTION_CONTINUE_EXECUTION +} + +// lastcontinuehandler is reached, because runtime cannot handle +// current exception. lastcontinuehandler will print crash info and exit. +func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 { + _g_ := getg() + + if panicking != 0 { // traceback already printed + exit(2) + } + panicking = 1 + + print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.eip), "\n") + + print("PC=", hex(r.eip), "\n") + if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { + print("signal arrived during cgo execution\n") + gp = _g_.m.lockedg + } + print("\n") + + var docrash bool + if gotraceback(&docrash) > 0 { + tracebacktrap(uintptr(r.eip), uintptr(r.esp), 0, gp) + tracebackothers(gp) + dumpregs(r) + } + + if docrash { + crash() + } + + exit(2) + return 0 // not reached +} + +func sigenable(sig uint32) { +} + +func sigdisable(sig uint32) { +} + +func dosigprof(r *context, gp *g, mp *m) { + sigprof((*byte)(unsafe.Pointer(uintptr(r.eip))), (*byte)(unsafe.Pointer(uintptr(r.esp))), nil, gp, mp) +} diff --git a/src/runtime/os1_windows_amd64.go b/src/runtime/os1_windows_amd64.go new file mode 100644 index 000000000..0d21b3881 --- /dev/null +++ b/src/runtime/os1_windows_amd64.go @@ -0,0 +1,137 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "unsafe" +) + +var text struct{} + +func dumpregs(r *context) { + print("rax ", hex(r.rax), "\n") + print("rbx ", hex(r.rbx), "\n") + print("rcx ", hex(r.rcx), "\n") + print("rdi ", hex(r.rdi), "\n") + print("rsi ", hex(r.rsi), "\n") + print("rbp ", hex(r.rbp), "\n") + print("rsp ", hex(r.rsp), "\n") + print("r8 ", hex(r.r8), "\n") + print("r9 ", hex(r.r9), "\n") + print("r10 ", hex(r.r10), "\n") + print("r11 ", hex(r.r11), "\n") + print("r12 ", hex(r.r12), "\n") + print("r13 ", hex(r.r13), "\n") + print("r14 ", hex(r.r14), "\n") + print("r15 ", hex(r.r15), "\n") + print("rip ", hex(r.rip), "\n") + print("rflags ", hex(r.eflags), "\n") + print("cs ", hex(r.segcs), "\n") + print("fs ", hex(r.segfs), "\n") + print("gs ", hex(r.seggs), "\n") +} + +func isgoexception(info *exceptionrecord, r *context) bool { + // Only handle exception if executing instructions in Go binary + // (not Windows library code). + if r.rip < uint64(uintptr(unsafe.Pointer(&text))) || uint64(uintptr(unsafe.Pointer(&etext))) < r.rip { + return false + } + + if issigpanic(info.exceptioncode) == 0 { + return false + } + + return true +} + +// Called by sigtramp from Windows VEH handler. +// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) +// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH). + +func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { + if !isgoexception(info, r) { + return _EXCEPTION_CONTINUE_SEARCH + } + + // Make it look like a call to the signal func. + // Have to pass arguments out of band since + // augmenting the stack frame would break + // the unwinding code. + gp.sig = info.exceptioncode + gp.sigcode0 = uintptr(info.exceptioninformation[0]) + gp.sigcode1 = uintptr(info.exceptioninformation[1]) + gp.sigpc = uintptr(r.rip) + + // Only push runtime·sigpanic if r->rip != 0. + // If r->rip == 0, probably panicked because of a + // call to a nil func. Not pushing that onto sp will + // make the trace look like a call to runtime·sigpanic instead. + // (Otherwise the trace will end at runtime·sigpanic and we + // won't get to see who faulted.) + if r.rip != 0 { + sp := unsafe.Pointer(uintptr(r.rsp)) + sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp-- + *((*uintptr)(sp)) = uintptr(r.rip) + r.rsp = uint64(uintptr(sp)) + } + r.rip = uint64(funcPC(sigpanic)) + return _EXCEPTION_CONTINUE_EXECUTION +} + +// It seems Windows searches ContinueHandler's list even +// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION. +// firstcontinuehandler will stop that search, +// if exceptionhandler did the same earlier. +func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { + if !isgoexception(info, r) { + return _EXCEPTION_CONTINUE_SEARCH + } + return _EXCEPTION_CONTINUE_EXECUTION +} + +// lastcontinuehandler is reached, because runtime cannot handle +// current exception. lastcontinuehandler will print crash info and exit. +func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 { + _g_ := getg() + + if panicking != 0 { // traceback already printed + exit(2) + } + panicking = 1 + + print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.rip), "\n") + + print("PC=", hex(r.rip), "\n") + if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { + print("signal arrived during cgo execution\n") + gp = _g_.m.lockedg + } + print("\n") + + var docrash bool + if gotraceback(&docrash) > 0 { + tracebacktrap(uintptr(r.rip), uintptr(r.rsp), 0, gp) + tracebackothers(gp) + dumpregs(r) + } + + if docrash { + crash() + } + + exit(2) + return 0 // not reached +} + +func sigenable(sig uint32) { +} + +func sigdisable(sig uint32) { +} + +func dosigprof(r *context, gp *g, mp *m) { + sigprof((*byte)(unsafe.Pointer(uintptr(r.rip))), (*byte)(unsafe.Pointer(uintptr(r.rsp))), nil, gp, mp) +} diff --git a/src/runtime/os2_nacl.go b/src/runtime/os2_nacl.go new file mode 100644 index 000000000..0c91e0f73 --- /dev/null +++ b/src/runtime/os2_nacl.go @@ -0,0 +1,154 @@ +// Copyright 2014 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 + +const ( + _NSIG = 32 + _SI_USER = 1 + + // native_client/src/trusted/service_runtime/include/sys/errno.h + // The errors are mainly copied from Linux. + _EPERM = 1 /* Operation not permitted */ + _ENOENT = 2 /* No such file or directory */ + _ESRCH = 3 /* No such process */ + _EINTR = 4 /* Interrupted system call */ + _EIO = 5 /* I/O error */ + _ENXIO = 6 /* No such device or address */ + _E2BIG = 7 /* Argument list too long */ + _ENOEXEC = 8 /* Exec format error */ + _EBADF = 9 /* Bad file number */ + _ECHILD = 10 /* No child processes */ + _EAGAIN = 11 /* Try again */ + _ENOMEM = 12 /* Out of memory */ + _EACCES = 13 /* Permission denied */ + _EFAULT = 14 /* Bad address */ + _EBUSY = 16 /* Device or resource busy */ + _EEXIST = 17 /* File exists */ + _EXDEV = 18 /* Cross-device link */ + _ENODEV = 19 /* No such device */ + _ENOTDIR = 20 /* Not a directory */ + _EISDIR = 21 /* Is a directory */ + _EINVAL = 22 /* Invalid argument */ + _ENFILE = 23 /* File table overflow */ + _EMFILE = 24 /* Too many open files */ + _ENOTTY = 25 /* Not a typewriter */ + _EFBIG = 27 /* File too large */ + _ENOSPC = 28 /* No space left on device */ + _ESPIPE = 29 /* Illegal seek */ + _EROFS = 30 /* Read-only file system */ + _EMLINK = 31 /* Too many links */ + _EPIPE = 32 /* Broken pipe */ + _ENAMETOOLONG = 36 /* File name too long */ + _ENOSYS = 38 /* Function not implemented */ + _EDQUOT = 122 /* Quota exceeded */ + _EDOM = 33 /* Math arg out of domain of func */ + _ERANGE = 34 /* Math result not representable */ + _EDEADLK = 35 /* Deadlock condition */ + _ENOLCK = 37 /* No record locks available */ + _ENOTEMPTY = 39 /* Directory not empty */ + _ELOOP = 40 /* Too many symbolic links */ + _ENOMSG = 42 /* No message of desired type */ + _EIDRM = 43 /* Identifier removed */ + _ECHRNG = 44 /* Channel number out of range */ + _EL2NSYNC = 45 /* Level 2 not synchronized */ + _EL3HLT = 46 /* Level 3 halted */ + _EL3RST = 47 /* Level 3 reset */ + _ELNRNG = 48 /* Link number out of range */ + _EUNATCH = 49 /* Protocol driver not attached */ + _ENOCSI = 50 /* No CSI structure available */ + _EL2HLT = 51 /* Level 2 halted */ + _EBADE = 52 /* Invalid exchange */ + _EBADR = 53 /* Invalid request descriptor */ + _EXFULL = 54 /* Exchange full */ + _ENOANO = 55 /* No anode */ + _EBADRQC = 56 /* Invalid request code */ + _EBADSLT = 57 /* Invalid slot */ + _EDEADLOCK = _EDEADLK /* File locking deadlock error */ + _EBFONT = 59 /* Bad font file fmt */ + _ENOSTR = 60 /* Device not a stream */ + _ENODATA = 61 /* No data (for no delay io) */ + _ETIME = 62 /* Timer expired */ + _ENOSR = 63 /* Out of streams resources */ + _ENONET = 64 /* Machine is not on the network */ + _ENOPKG = 65 /* Package not installed */ + _EREMOTE = 66 /* The object is remote */ + _ENOLINK = 67 /* The link has been severed */ + _EADV = 68 /* Advertise error */ + _ESRMNT = 69 /* Srmount error */ + _ECOMM = 70 /* Communication error on send */ + _EPROTO = 71 /* Protocol error */ + _EMULTIHOP = 72 /* Multihop attempted */ + _EDOTDOT = 73 /* Cross mount point (not really error) */ + _EBADMSG = 74 /* Trying to read unreadable message */ + _EOVERFLOW = 75 /* Value too large for defined data type */ + _ENOTUNIQ = 76 /* Given log. name not unique */ + _EBADFD = 77 /* f.d. invalid for this operation */ + _EREMCHG = 78 /* Remote address changed */ + _ELIBACC = 79 /* Can't access a needed shared lib */ + _ELIBBAD = 80 /* Accessing a corrupted shared lib */ + _ELIBSCN = 81 /* .lib section in a.out corrupted */ + _ELIBMAX = 82 /* Attempting to link in too many libs */ + _ELIBEXEC = 83 /* Attempting to exec a shared library */ + _EILSEQ = 84 + _EUSERS = 87 + _ENOTSOCK = 88 /* Socket operation on non-socket */ + _EDESTADDRREQ = 89 /* Destination address required */ + _EMSGSIZE = 90 /* Message too long */ + _EPROTOTYPE = 91 /* Protocol wrong type for socket */ + _ENOPROTOOPT = 92 /* Protocol not available */ + _EPROTONOSUPPORT = 93 /* Unknown protocol */ + _ESOCKTNOSUPPORT = 94 /* Socket type not supported */ + _EOPNOTSUPP = 95 /* Operation not supported on transport endpoint */ + _EPFNOSUPPORT = 96 /* Protocol family not supported */ + _EAFNOSUPPORT = 97 /* Address family not supported by protocol family */ + _EADDRINUSE = 98 /* Address already in use */ + _EADDRNOTAVAIL = 99 /* Address not available */ + _ENETDOWN = 100 /* Network interface is not configured */ + _ENETUNREACH = 101 /* Network is unreachable */ + _ENETRESET = 102 + _ECONNABORTED = 103 /* Connection aborted */ + _ECONNRESET = 104 /* Connection reset by peer */ + _ENOBUFS = 105 /* No buffer space available */ + _EISCONN = 106 /* Socket is already connected */ + _ENOTCONN = 107 /* Socket is not connected */ + _ESHUTDOWN = 108 /* Can't send after socket shutdown */ + _ETOOMANYREFS = 109 + _ETIMEDOUT = 110 /* Connection timed out */ + _ECONNREFUSED = 111 /* Connection refused */ + _EHOSTDOWN = 112 /* Host is down */ + _EHOSTUNREACH = 113 /* Host is unreachable */ + _EALREADY = 114 /* Socket already connected */ + _EINPROGRESS = 115 /* Connection already in progress */ + _ESTALE = 116 + _ENOTSUP = _EOPNOTSUPP /* Not supported */ + _ENOMEDIUM = 123 /* No medium (in tape drive) */ + _ECANCELED = 125 /* Operation canceled. */ + _ELBIN = 2048 /* Inode is remote (not really error) */ + _EFTYPE = 2049 /* Inappropriate file type or format */ + _ENMFILE = 2050 /* No more files */ + _EPROCLIM = 2051 + _ENOSHARE = 2052 /* No such host or network path */ + _ECASECLASH = 2053 /* Filename exists with different case */ + _EWOULDBLOCK = _EAGAIN /* Operation would block */ + + // native_client/src/trusted/service_runtime/include/bits/mman.h. + // NOTE: DO NOT USE native_client/src/shared/imc/nacl_imc_c.h. + // Those MAP_*values are different from these. + _PROT_NONE = 0x0 + _PROT_READ = 0x1 + _PROT_WRITE = 0x2 + _PROT_EXEC = 0x4 + + _MAP_SHARED = 0x1 + _MAP_PRIVATE = 0x2 + _MAP_FIXED = 0x10 + _MAP_ANON = 0x20 + + _MADV_FREE = 0 + _SIGFPE = 8 + _FPE_INTDIV = 0 +) + +type siginfo struct{} diff --git a/src/runtime/os2_netbsd.go b/src/runtime/os2_netbsd.go new file mode 100644 index 000000000..46576b9bc --- /dev/null +++ b/src/runtime/os2_netbsd.go @@ -0,0 +1,18 @@ +// Copyright 2010 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 + +const ( + _SS_DISABLE = 4 + _SIG_BLOCK = 1 + _SIG_UNBLOCK = 2 + _SIG_SETMASK = 3 + _NSIG = 33 + _SI_USER = 0 + + // From NetBSD's <sys/ucontext.h> + _UC_SIGMASK = 0x01 + _UC_CPU = 0x04 +) diff --git a/src/runtime/os2_plan9.go b/src/runtime/os2_plan9.go new file mode 100644 index 000000000..f64f4c8da --- /dev/null +++ b/src/runtime/os2_plan9.go @@ -0,0 +1,72 @@ +// Copyright 2010 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. + +// Plan 9-specific system calls + +package runtime + +// open +const ( + _OREAD = 0 + _OWRITE = 1 + _ORDWR = 2 + _OEXEC = 3 + _OTRUNC = 16 + _OCEXEC = 32 + _ORCLOSE = 64 + _OEXCL = 0x1000 +) + +// rfork +const ( + _RFNAMEG = 1 << 0 + _RFENVG = 1 << 1 + _RFFDG = 1 << 2 + _RFNOTEG = 1 << 3 + _RFPROC = 1 << 4 + _RFMEM = 1 << 5 + _RFNOWAIT = 1 << 6 + _RFCNAMEG = 1 << 10 + _RFCENVG = 1 << 11 + _RFCFDG = 1 << 12 + _RFREND = 1 << 13 + _RFNOMNT = 1 << 14 +) + +// notify +const ( + _NCONT = 0 + _NDFLT = 1 +) + +type uinptr _Plink + +type tos struct { + prof struct { // Per process profiling + pp *_Plink // known to be 0(ptr) + next *_Plink // known to be 4(ptr) + last *_Plink + first *_Plink + pid uint32 + what uint32 + } + cyclefreq uint64 // cycle clock frequency if there is one, 0 otherwise + kcycles int64 // cycles spent in kernel + pcycles int64 // cycles spent in process (kernel + user) + pid uint32 // might as well put the pid here + clock uint32 + // top of stack is here +} + +const ( + _NSIG = 14 // number of signals in sigtable array + _ERRMAX = 128 // max length of note string + + // Notes in runtime·sigtab that are handled by runtime·sigpanic. + _SIGRFAULT = 2 + _SIGWFAULT = 3 + _SIGINTDIV = 4 + _SIGFLOAT = 5 + _SIGTRAP = 6 +) diff --git a/src/runtime/os2_windows.go b/src/runtime/os2_windows.go new file mode 100644 index 000000000..d5b1f471f --- /dev/null +++ b/src/runtime/os2_windows.go @@ -0,0 +1,25 @@ +// 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. + +package runtime + +import "unsafe" + +// Call a Windows function with stdcall conventions, +// and switch to os stack during the call. +func asmstdcall(fn unsafe.Pointer) + +func getlasterror() uint32 +func setlasterror(err uint32) + +// Function to be called by windows CreateThread +// to start new os thread. +func tstart_stdcall(newm *m) uint32 + +func ctrlhandler(_type uint32) uint32 + +// TODO(brainman): should not need those +const ( + _NSIG = 65 +) diff --git a/src/runtime/os_android.h b/src/runtime/os_android.h deleted file mode 100644 index c7c1098e8..000000000 --- a/src/runtime/os_android.h +++ /dev/null @@ -1 +0,0 @@ -#include "os_linux.h" diff --git a/src/runtime/os_android.c b/src/runtime/os_android_arm.go index 5805f6871..132832236 100644 --- a/src/runtime/os_android.c +++ b/src/runtime/os_android_arm.go @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" +package runtime + +import _ "unsafe" // Export the runtime entry point symbol. // // Used by the app package to start the Go runtime after loading // a shared library via JNI. See golang.org/x/mobile/app. -void _rt0_arm_linux1(); -#pragma cgo_export_static _rt0_arm_linux1 -#pragma cgo_export_dynamic _rt0_arm_linux1 +//go:cgo_export_static _rt0_arm_linux1 +//go:cgo_export_dynamic _rt0_arm_linux1 diff --git a/src/runtime/os_nacl.c b/src/runtime/os_nacl.c deleted file mode 100644 index ad72cc7c6..000000000 --- a/src/runtime/os_nacl.c +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2010 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 "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "arch_GOARCH.h" -#include "textflag.h" -#include "stack.h" - -int8 *goos = "nacl"; -extern SigTab runtime·sigtab[]; - -void runtime·sigtramp(void); - -// Called to initialize a new m (including the bootstrap m). -// Called on the parent thread (main thread in case of bootstrap), can allocate memory. -void -runtime·mpreinit(M *mp) -{ - mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K - runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); - - mp->gsignal->m = mp; - runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the new thread, can not allocate memory. -void -runtime·minit(void) -{ - int32 ret; - - // Initialize signal handling - ret = runtime·nacl_exception_stack((byte*)g->m->gsignal->stack.lo, 32*1024); - if(ret < 0) - runtime·printf("runtime: nacl_exception_stack: error %d\n", -ret); - - ret = runtime·nacl_exception_handler(runtime·sigtramp, nil); - if(ret < 0) - runtime·printf("runtime: nacl_exception_handler: error %d\n", -ret); -} - -// Called from dropm to undo the effect of an minit. -void -runtime·unminit(void) -{ -} - -int8 runtime·sigtrampf[] = "runtime: signal at PC=%X AX=%X CX=%X DX=%X BX=%X DI=%X R15=%X *SP=%X\n"; -int8 runtime·sigtrampp[] = "runtime: sigtramp"; - -extern byte runtime·tls0[]; - -void -runtime·osinit(void) -{ - runtime·ncpu = 1; - g->m->procid = 2; -//runtime·nacl_exception_handler(runtime·sigtramp, nil); -} - -void -runtime·crash(void) -{ - *(int32*)0 = 0; -} - -#pragma textflag NOSPLIT -void -runtime·get_random_data(byte **rnd, int32 *rnd_len) -{ - *rnd = nil; - *rnd_len = 0; -} - -void -runtime·goenvs(void) -{ - runtime·goenvs_unix(); -} - -void -runtime·initsig(void) -{ -} - -#pragma textflag NOSPLIT -void -runtime·usleep(uint32 us) -{ - Timespec ts; - - ts.tv_sec = us/1000000; - ts.tv_nsec = (us%1000000)*1000; - runtime·nacl_nanosleep(&ts, nil); -} - -void runtime·mstart_nacl(void); - -void -runtime·newosproc(M *mp, void *stk) -{ - int32 ret; - void **tls; - - tls = (void**)mp->tls; - tls[0] = mp->g0; - tls[1] = mp; - ret = runtime·nacl_thread_create(runtime·mstart_nacl, stk, tls+2, 0); - if(ret < 0) { - runtime·printf("nacl_thread_create: error %d\n", -ret); - runtime·throw("newosproc"); - } -} - -static void -semacreate(void) -{ - int32 mu, cond; - - mu = runtime·nacl_mutex_create(0); - if(mu < 0) { - runtime·printf("nacl_mutex_create: error %d\n", -mu); - runtime·throw("semacreate"); - } - cond = runtime·nacl_cond_create(0); - if(cond < 0) { - runtime·printf("nacl_cond_create: error %d\n", -cond); - runtime·throw("semacreate"); - } - g->m->waitsemalock = mu; - g->m->scalararg[0] = cond; // assigned to m->waitsema -} - -#pragma textflag NOSPLIT -uint32 -runtime·semacreate(void) -{ - void (*fn)(void); - uint32 x; - - fn = semacreate; - runtime·onM(&fn); - x = g->m->scalararg[0]; - g->m->scalararg[0] = 0; - return x; -} - -static void -semasleep(void) -{ - int32 ret; - int64 ns; - - ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32; - g->m->scalararg[0] = 0; - g->m->scalararg[1] = 0; - - ret = runtime·nacl_mutex_lock(g->m->waitsemalock); - if(ret < 0) { - //runtime·printf("nacl_mutex_lock: error %d\n", -ret); - runtime·throw("semasleep"); - } - if(g->m->waitsemacount > 0) { - g->m->waitsemacount = 0; - runtime·nacl_mutex_unlock(g->m->waitsemalock); - g->m->scalararg[0] = 0; - return; - } - - while(g->m->waitsemacount == 0) { - if(ns < 0) { - ret = runtime·nacl_cond_wait(g->m->waitsema, g->m->waitsemalock); - if(ret < 0) { - //runtime·printf("nacl_cond_wait: error %d\n", -ret); - runtime·throw("semasleep"); - } - } else { - Timespec ts; - - ns += runtime·nanotime(); - ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec); - ret = runtime·nacl_cond_timed_wait_abs(g->m->waitsema, g->m->waitsemalock, &ts); - if(ret == -ETIMEDOUT) { - runtime·nacl_mutex_unlock(g->m->waitsemalock); - g->m->scalararg[0] = -1; - return; - } - if(ret < 0) { - //runtime·printf("nacl_cond_timed_wait_abs: error %d\n", -ret); - runtime·throw("semasleep"); - } - } - } - - g->m->waitsemacount = 0; - runtime·nacl_mutex_unlock(g->m->waitsemalock); - g->m->scalararg[0] = 0; -} - -#pragma textflag NOSPLIT -int32 -runtime·semasleep(int64 ns) -{ - int32 r; - void (*fn)(void); - - g->m->scalararg[0] = (uint32)ns; - g->m->scalararg[1] = (uint32)(ns>>32); - fn = semasleep; - runtime·onM(&fn); - r = g->m->scalararg[0]; - g->m->scalararg[0] = 0; - return r; -} - -static void -semawakeup(void) -{ - int32 ret; - M *mp; - - mp = g->m->ptrarg[0]; - g->m->ptrarg[0] = nil; - - ret = runtime·nacl_mutex_lock(mp->waitsemalock); - if(ret < 0) { - //runtime·printf("nacl_mutex_lock: error %d\n", -ret); - runtime·throw("semawakeup"); - } - if(mp->waitsemacount != 0) { - //runtime·printf("semawakeup: double wakeup\n"); - runtime·throw("semawakeup"); - } - mp->waitsemacount = 1; - runtime·nacl_cond_signal(mp->waitsema); - runtime·nacl_mutex_unlock(mp->waitsemalock); -} - -#pragma textflag NOSPLIT -void -runtime·semawakeup(M *mp) -{ - void (*fn)(void); - - g->m->ptrarg[0] = mp; - fn = semawakeup; - runtime·onM(&fn); -} - -uintptr -runtime·memlimit(void) -{ - runtime·printf("memlimit\n"); - return 0; -} - -#pragma dataflag NOPTR -static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n"; - -// This runs on a foreign stack, without an m or a g. No stack split. -#pragma textflag NOSPLIT -void -runtime·badsignal2(void) -{ - runtime·write(2, badsignal, sizeof badsignal - 1); - runtime·exit(2); -} - -void runtime·madvise(byte*, uintptr, int32) { } -void runtime·munmap(byte*, uintptr) {} - -void -runtime·resetcpuprofiler(int32 hz) -{ - USED(hz); -} - -void -runtime·sigdisable(uint32) -{ -} - -void -runtime·sigenable(uint32) -{ -} - -void -runtime·closeonexec(int32) -{ -} - -uint32 runtime·writelock; // test-and-set spin lock for runtime.write - -/* -An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s. - -void (*runtime·nacl_irt_query)(void); - -int8 runtime·nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1"; -void *runtime·nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf -int32 runtime·nacl_irt_basic_v0_1_size = sizeof(runtime·nacl_irt_basic_v0_1); - -int8 runtime·nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3"; -void *runtime·nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect -int32 runtime·nacl_irt_memory_v0_3_size = sizeof(runtime·nacl_irt_memory_v0_3); - -int8 runtime·nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1"; -void *runtime·nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice -int32 runtime·nacl_irt_thread_v0_1_size = sizeof(runtime·nacl_irt_thread_v0_1); -*/ diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go index 8dd43ff06..eff9ec30e 100644 --- a/src/runtime/os_nacl.go +++ b/src/runtime/os_nacl.go @@ -6,8 +6,8 @@ package runtime import "unsafe" -func nacl_exception_stack(p unsafe.Pointer, size int32) int32 -func nacl_exception_handler(fn, arg unsafe.Pointer) int32 +func nacl_exception_stack(p uintptr, size int32) int32 +func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32 func nacl_sem_create(flag int32) int32 func nacl_sem_wait(sem int32) int32 func nacl_sem_post(sem int32) int32 @@ -19,9 +19,20 @@ func nacl_cond_create(flag int32) int32 func nacl_cond_wait(cond, n int32) int32 func nacl_cond_signal(cond int32) int32 func nacl_cond_broadcast(cond int32) int32 -func nacl_cond_timed_wait_abs(cond, lock int32, ts unsafe.Pointer) int32 -func nacl_thread_create(fn, stk, tls, xx unsafe.Pointer) int32 -func nacl_nanosleep(ts, extra unsafe.Pointer) int32 + +//go:noescape +func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32 +func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32 + +//go:noescape +func nacl_nanosleep(ts, extra *timespec) int32 +func nanotime() int64 +func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer +func exit(code int32) +func osyield() + +//go:noescape +func write(fd uintptr, p unsafe.Pointer, n int32) int32 func os_sigpipe() { gothrow("too many writes on closed pipe") diff --git a/src/runtime/os_nacl.h b/src/runtime/os_nacl.h deleted file mode 100644 index 7c9d9c242..000000000 --- a/src/runtime/os_nacl.h +++ /dev/null @@ -1,162 +0,0 @@ -enum { - NSIG = 32, - SI_USER = 1, - - // native_client/src/trusted/service_runtime/include/sys/errno.h - // The errors are mainly copied from Linux. - EPERM = 1, /* Operation not permitted */ - ENOENT = 2, /* No such file or directory */ - ESRCH = 3, /* No such process */ - EINTR = 4, /* Interrupted system call */ - EIO = 5, /* I/O error */ - ENXIO = 6, /* No such device or address */ - E2BIG = 7, /* Argument list too long */ - ENOEXEC = 8, /* Exec format error */ - EBADF = 9, /* Bad file number */ - ECHILD = 10, /* No child processes */ - EAGAIN = 11, /* Try again */ - ENOMEM = 12, /* Out of memory */ - EACCES = 13, /* Permission denied */ - EFAULT = 14, /* Bad address */ - EBUSY = 16, /* Device or resource busy */ - EEXIST = 17, /* File exists */ - EXDEV = 18, /* Cross-device link */ - ENODEV = 19, /* No such device */ - ENOTDIR = 20, /* Not a directory */ - EISDIR = 21, /* Is a directory */ - EINVAL = 22, /* Invalid argument */ - ENFILE = 23, /* File table overflow */ - EMFILE = 24, /* Too many open files */ - ENOTTY = 25, /* Not a typewriter */ - EFBIG = 27, /* File too large */ - ENOSPC = 28, /* No space left on device */ - ESPIPE = 29, /* Illegal seek */ - EROFS = 30, /* Read-only file system */ - EMLINK = 31, /* Too many links */ - EPIPE = 32, /* Broken pipe */ - ENAMETOOLONG = 36, /* File name too long */ - ENOSYS = 38, /* Function not implemented */ - EDQUOT = 122, /* Quota exceeded */ - EDOM = 33, /* Math arg out of domain of func */ - ERANGE = 34, /* Math result not representable */ - EDEADLK = 35, /* Deadlock condition */ - ENOLCK = 37, /* No record locks available */ - ENOTEMPTY = 39, /* Directory not empty */ - ELOOP = 40, /* Too many symbolic links */ - ENOMSG = 42, /* No message of desired type */ - EIDRM = 43, /* Identifier removed */ - ECHRNG = 44, /* Channel number out of range */ - EL2NSYNC = 45, /* Level 2 not synchronized */ - EL3HLT = 46, /* Level 3 halted */ - EL3RST = 47, /* Level 3 reset */ - ELNRNG = 48, /* Link number out of range */ - EUNATCH = 49, /* Protocol driver not attached */ - ENOCSI = 50, /* No CSI structure available */ - EL2HLT = 51, /* Level 2 halted */ - EBADE = 52, /* Invalid exchange */ - EBADR = 53, /* Invalid request descriptor */ - EXFULL = 54, /* Exchange full */ - ENOANO = 55, /* No anode */ - EBADRQC = 56, /* Invalid request code */ - EBADSLT = 57, /* Invalid slot */ - EDEADLOCK = EDEADLK, /* File locking deadlock error */ - EBFONT = 59, /* Bad font file fmt */ - ENOSTR = 60, /* Device not a stream */ - ENODATA = 61, /* No data (for no delay io) */ - ETIME = 62, /* Timer expired */ - ENOSR = 63, /* Out of streams resources */ - ENONET = 64, /* Machine is not on the network */ - ENOPKG = 65, /* Package not installed */ - EREMOTE = 66, /* The object is remote */ - ENOLINK = 67, /* The link has been severed */ - EADV = 68, /* Advertise error */ - ESRMNT = 69, /* Srmount error */ - ECOMM = 70, /* Communication error on send */ - EPROTO = 71, /* Protocol error */ - EMULTIHOP = 72, /* Multihop attempted */ - EDOTDOT = 73, /* Cross mount point (not really error) */ - EBADMSG = 74, /* Trying to read unreadable message */ - EOVERFLOW = 75, /* Value too large for defined data type */ - ENOTUNIQ = 76, /* Given log. name not unique */ - EBADFD = 77, /* f.d. invalid for this operation */ - EREMCHG = 78, /* Remote address changed */ - ELIBACC = 79, /* Can't access a needed shared lib */ - ELIBBAD = 80, /* Accessing a corrupted shared lib */ - ELIBSCN = 81, /* .lib section in a.out corrupted */ - ELIBMAX = 82, /* Attempting to link in too many libs */ - ELIBEXEC = 83, /* Attempting to exec a shared library */ - EILSEQ = 84, - EUSERS = 87, - ENOTSOCK = 88, /* Socket operation on non-socket */ - EDESTADDRREQ = 89, /* Destination address required */ - EMSGSIZE = 90, /* Message too long */ - EPROTOTYPE = 91, /* Protocol wrong type for socket */ - ENOPROTOOPT = 92, /* Protocol not available */ - EPROTONOSUPPORT = 93, /* Unknown protocol */ - ESOCKTNOSUPPORT = 94, /* Socket type not supported */ - EOPNOTSUPP = 95, /* Operation not supported on transport endpoint */ - EPFNOSUPPORT = 96, /* Protocol family not supported */ - EAFNOSUPPORT = 97, /* Address family not supported by protocol family */ - EADDRINUSE = 98, /* Address already in use */ - EADDRNOTAVAIL = 99, /* Address not available */ - ENETDOWN = 100, /* Network interface is not configured */ - ENETUNREACH = 101, /* Network is unreachable */ - ENETRESET = 102, - ECONNABORTED = 103, /* Connection aborted */ - ECONNRESET = 104, /* Connection reset by peer */ - ENOBUFS = 105, /* No buffer space available */ - EISCONN = 106, /* Socket is already connected */ - ENOTCONN = 107, /* Socket is not connected */ - ESHUTDOWN = 108, /* Can't send after socket shutdown */ - ETOOMANYREFS = 109, - ETIMEDOUT = 110, /* Connection timed out */ - ECONNREFUSED = 111, /* Connection refused */ - EHOSTDOWN = 112, /* Host is down */ - EHOSTUNREACH = 113, /* Host is unreachable */ - EALREADY = 114, /* Socket already connected */ - EINPROGRESS = 115, /* Connection already in progress */ - ESTALE = 116, - ENOTSUP = EOPNOTSUPP, /* Not supported */ - ENOMEDIUM = 123, /* No medium (in tape drive) */ - ECANCELED = 125, /* Operation canceled. */ - ELBIN = 2048, /* Inode is remote (not really error) */ - EFTYPE = 2049, /* Inappropriate file type or format */ - ENMFILE = 2050, /* No more files */ - EPROCLIM = 2051, - ENOSHARE = 2052, /* No such host or network path */ - ECASECLASH = 2053, /* Filename exists with different case */ - EWOULDBLOCK = EAGAIN, /* Operation would block */ - - // native_client/src/trusted/service_runtime/include/bits/mman.h. - // NOTE: DO NOT USE native_client/src/shared/imc/nacl_imc_c.h. - // Those MAP_*values are different from these. - PROT_NONE = 0x0, - PROT_READ = 0x1, - PROT_WRITE = 0x2, - PROT_EXEC = 0x4, - - MAP_SHARED = 0x1, - MAP_PRIVATE = 0x2, - MAP_FIXED = 0x10, - MAP_ANON = 0x20, -}; -typedef byte* kevent_udata; - -int32 runtime·nacl_exception_stack(byte*, int32); -int32 runtime·nacl_exception_handler(void*, void*); -int32 runtime·nacl_sem_create(int32); -int32 runtime·nacl_sem_wait(int32); -int32 runtime·nacl_sem_post(int32); -int32 runtime·nacl_mutex_create(int32); -int32 runtime·nacl_mutex_lock(int32); -int32 runtime·nacl_mutex_trylock(int32); -int32 runtime·nacl_mutex_unlock(int32); -int32 runtime·nacl_cond_create(int32); -int32 runtime·nacl_cond_wait(int32, int32); -int32 runtime·nacl_cond_signal(int32); -int32 runtime·nacl_cond_broadcast(int32); -int32 runtime·nacl_cond_timed_wait_abs(int32, int32, Timespec*); -int32 runtime·nacl_thread_create(void*, void*, void*, void*); -int32 runtime·nacl_nanosleep(Timespec*, Timespec*); - -void runtime·sigpanic(void); diff --git a/src/runtime/os_nacl_arm.c b/src/runtime/os_nacl_arm.go index 1248ea644..a43e7c47b 100644 --- a/src/runtime/os_nacl_arm.c +++ b/src/runtime/os_nacl_arm.go @@ -2,23 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "textflag.h" +package runtime -void -runtime·checkgoarm(void) -{ - return; // NaCl/ARM only supports ARMv7 +func checkgoarm() { + return // NaCl/ARM only supports ARMv7 } -#pragma textflag NOSPLIT -int64 -runtime·cputicks(void) -{ +//go:nosplit +func cputicks() int64 { // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1(). // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. // TODO: need more entropy to better seed fastrand1. - return runtime·nanotime(); + return nanotime() } diff --git a/src/runtime/os_netbsd.c b/src/runtime/os_netbsd.c deleted file mode 100644 index 28929ea57..000000000 --- a/src/runtime/os_netbsd.c +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "signal_unix.h" -#include "stack.h" -#include "textflag.h" - -enum -{ - ESRCH = 3, - ENOTSUP = 91, - - // From NetBSD's <sys/time.h> - CLOCK_REALTIME = 0, - CLOCK_VIRTUAL = 1, - CLOCK_PROF = 2, - CLOCK_MONOTONIC = 3 -}; - -extern SigTab runtime·sigtab[]; - -static Sigset sigset_none; -static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, }; - -extern void runtime·getcontext(UcontextT *context); -extern int32 runtime·lwp_create(UcontextT *context, uintptr flags, void *lwpid); -extern void runtime·lwp_mcontext_init(void *mc, void *stack, M *mp, G *gp, void (*fn)(void)); -extern int32 runtime·lwp_park(Timespec *abstime, int32 unpark, void *hint, void *unparkhint); -extern int32 runtime·lwp_unpark(int32 lwp, void *hint); -extern int32 runtime·lwp_self(void); - -// From NetBSD's <sys/sysctl.h> -#define CTL_HW 6 -#define HW_NCPU 3 - -static int32 -getncpu(void) -{ - uint32 mib[2]; - uint32 out; - int32 ret; - uintptr nout; - - // Fetch hw.ncpu via sysctl. - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - nout = sizeof out; - out = 0; - ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0); - if(ret >= 0) - return out; - else - return 1; -} - -#pragma textflag NOSPLIT -uintptr -runtime·semacreate(void) -{ - return 1; -} - -static void -semasleep(void) -{ - int64 ns; - Timespec ts; - - ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32; - g->m->scalararg[0] = 0; - g->m->scalararg[1] = 0; - - // spin-mutex lock - while(runtime·xchg(&g->m->waitsemalock, 1)) - runtime·osyield(); - - for(;;) { - // lock held - if(g->m->waitsemacount == 0) { - // sleep until semaphore != 0 or timeout. - // thrsleep unlocks m->waitsemalock. - if(ns < 0) { - // TODO(jsing) - potential deadlock! - // - // There is a potential deadlock here since we - // have to release the waitsemalock mutex - // before we call lwp_park() to suspend the - // thread. This allows another thread to - // release the lock and call lwp_unpark() - // before the thread is actually suspended. - // If this occurs the current thread will end - // up sleeping indefinitely. Unfortunately - // the NetBSD kernel does not appear to provide - // a mechanism for unlocking the userspace - // mutex once the thread is actually parked. - runtime·atomicstore(&g->m->waitsemalock, 0); - runtime·lwp_park(nil, 0, &g->m->waitsemacount, nil); - } else { - ns = ns + runtime·nanotime(); - // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system. - ts.tv_nsec = 0; - ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec); - // TODO(jsing) - potential deadlock! - // See above for details. - runtime·atomicstore(&g->m->waitsemalock, 0); - runtime·lwp_park(&ts, 0, &g->m->waitsemacount, nil); - } - // reacquire lock - while(runtime·xchg(&g->m->waitsemalock, 1)) - runtime·osyield(); - } - - // lock held (again) - if(g->m->waitsemacount != 0) { - // semaphore is available. - g->m->waitsemacount--; - // spin-mutex unlock - runtime·atomicstore(&g->m->waitsemalock, 0); - g->m->scalararg[0] = 0; // semaphore acquired - return; - } - - // semaphore not available. - // if there is a timeout, stop now. - // otherwise keep trying. - if(ns >= 0) - break; - } - - // lock held but giving up - // spin-mutex unlock - runtime·atomicstore(&g->m->waitsemalock, 0); - g->m->scalararg[0] = -1; - return; -} - -#pragma textflag NOSPLIT -int32 -runtime·semasleep(int64 ns) -{ - int32 r; - void (*fn)(void); - - g->m->scalararg[0] = (uint32)ns; - g->m->scalararg[1] = (uint32)(ns>>32); - fn = semasleep; - runtime·onM(&fn); - r = g->m->scalararg[0]; - g->m->scalararg[0] = 0; - return r; -} - -static void badsemawakeup(void); - -#pragma textflag NOSPLIT -void -runtime·semawakeup(M *mp) -{ - uint32 ret; - void (*fn)(void); - void *oldptr; - uintptr oldscalar; - - // spin-mutex lock - while(runtime·xchg(&mp->waitsemalock, 1)) - runtime·osyield(); - mp->waitsemacount++; - // TODO(jsing) - potential deadlock, see semasleep() for details. - // Confirm that LWP is parked before unparking... - ret = runtime·lwp_unpark(mp->procid, &mp->waitsemacount); - if(ret != 0 && ret != ESRCH) { - // semawakeup can be called on signal stack. - // Save old ptrarg/scalararg so we can restore them. - oldptr = g->m->ptrarg[0]; - oldscalar = g->m->scalararg[0]; - g->m->ptrarg[0] = mp; - g->m->scalararg[0] = ret; - fn = badsemawakeup; - if(g == g->m->gsignal) - fn(); - else - runtime·onM(&fn); - g->m->ptrarg[0] = oldptr; - g->m->scalararg[0] = oldscalar; - } - // spin-mutex unlock - runtime·atomicstore(&mp->waitsemalock, 0); -} - -static void -badsemawakeup(void) -{ - M *mp; - int32 ret; - - mp = g->m->ptrarg[0]; - g->m->ptrarg[0] = nil; - ret = g->m->scalararg[0]; - g->m->scalararg[0] = 0; - - runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret); -} - -void -runtime·newosproc(M *mp, void *stk) -{ - UcontextT uc; - int32 ret; - - if(0) { - runtime·printf( - "newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n", - stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp); - } - - mp->tls[0] = mp->id; // so 386 asm can find it - - runtime·getcontext(&uc); - - uc.uc_flags = _UC_SIGMASK | _UC_CPU; - uc.uc_link = nil; - uc.uc_sigmask = sigset_all; - - runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp->g0, runtime·mstart); - - ret = runtime·lwp_create(&uc, 0, &mp->procid); - - if(ret < 0) { - runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret); - runtime·throw("runtime.newosproc"); - } -} - -void -runtime·osinit(void) -{ - runtime·ncpu = getncpu(); -} - -#pragma textflag NOSPLIT -void -runtime·get_random_data(byte **rnd, int32 *rnd_len) -{ - #pragma dataflag NOPTR - static byte urandom_data[HashRandomBytes]; - int32 fd; - fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0); - if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) { - *rnd = urandom_data; - *rnd_len = HashRandomBytes; - } else { - *rnd = nil; - *rnd_len = 0; - } - runtime·close(fd); -} - -void -runtime·goenvs(void) -{ - runtime·goenvs_unix(); -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the parent thread (main thread in case of bootstrap), can allocate memory. -void -runtime·mpreinit(M *mp) -{ - mp->gsignal = runtime·malg(32*1024); - runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); - - mp->gsignal->m = mp; - runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the new thread, can not allocate memory. -void -runtime·minit(void) -{ - g->m->procid = runtime·lwp_self(); - - // Initialize signal handling - runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024); - runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil); -} - -// Called from dropm to undo the effect of an minit. -void -runtime·unminit(void) -{ - runtime·signalstack(nil, 0); -} - -uintptr -runtime·memlimit(void) -{ - return 0; -} - -extern void runtime·sigtramp(void); - -typedef struct sigaction { - union { - void (*_sa_handler)(int32); - void (*_sa_sigaction)(int32, Siginfo*, void *); - } _sa_u; /* signal handler */ - uint32 sa_mask[4]; /* signal mask to apply */ - int32 sa_flags; /* see signal options below */ -} SigactionT; - -void -runtime·setsig(int32 i, GoSighandler *fn, bool restart) -{ - SigactionT sa; - - runtime·memclr((byte*)&sa, sizeof sa); - sa.sa_flags = SA_SIGINFO|SA_ONSTACK; - if(restart) - sa.sa_flags |= SA_RESTART; - sa.sa_mask[0] = ~0U; - sa.sa_mask[1] = ~0U; - sa.sa_mask[2] = ~0U; - sa.sa_mask[3] = ~0U; - if (fn == runtime·sighandler) - fn = (void*)runtime·sigtramp; - sa._sa_u._sa_sigaction = (void*)fn; - runtime·sigaction(i, &sa, nil); -} - -GoSighandler* -runtime·getsig(int32 i) -{ - SigactionT sa; - - runtime·memclr((byte*)&sa, sizeof sa); - runtime·sigaction(i, nil, &sa); - if((void*)sa._sa_u._sa_sigaction == runtime·sigtramp) - return runtime·sighandler; - return (void*)sa._sa_u._sa_sigaction; -} - -void -runtime·signalstack(byte *p, int32 n) -{ - StackT st; - - st.ss_sp = (void*)p; - st.ss_size = n; - st.ss_flags = 0; - if(p == nil) - st.ss_flags = SS_DISABLE; - runtime·sigaltstack(&st, nil); -} - -void -runtime·unblocksignals(void) -{ - runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil); -} - -#pragma textflag NOSPLIT -int8* -runtime·signame(int32 sig) -{ - return runtime·sigtab[sig].name; -} diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index f000c5e9f..a153bf2eb 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -6,15 +6,37 @@ package runtime import "unsafe" -func setitimer(mode int32, new, old unsafe.Pointer) -func sigaction(sig int32, new, old unsafe.Pointer) -func sigaltstack(new, old unsafe.Pointer) -func sigprocmask(mode int32, new, old unsafe.Pointer) +//go:noescape +func setitimer(mode int32, new, old *itimerval) + +//go:noescape +func sigaction(sig int32, new, old *sigactiont) + +//go:noescape +func sigaltstack(new, old *sigaltstackt) + +//go:noescape +func sigprocmask(mode int32, new, old *sigset) + +//go:noescape func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 + func lwp_tramp() + func raise(sig int32) + +//go:noescape func getcontext(ctxt unsafe.Pointer) + +//go:noescape func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32 -func lwp_park(abstime unsafe.Pointer, unpark int32, hint, unparkhint unsafe.Pointer) int32 + +//go:noescape +func lwp_park(abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32 + +//go:noescape func lwp_unpark(lwp int32, hint unsafe.Pointer) int32 + func lwp_self() int32 + +func osyield() diff --git a/src/runtime/os_netbsd.h b/src/runtime/os_netbsd.h deleted file mode 100644 index f95db325f..000000000 --- a/src/runtime/os_netbsd.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2010 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. - - -typedef uintptr kevent_udata; - -struct sigaction; - -void runtime·sigpanic(void); - -void runtime·setitimer(int32, Itimerval*, Itimerval*); -void runtime·sigaction(int32, struct sigaction*, struct sigaction*); -void runtime·sigaltstack(SigaltstackT*, SigaltstackT*); -void runtime·sigprocmask(int32, Sigset*, Sigset*); -void runtime·unblocksignals(void); -int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr); -extern void runtime·lwp_tramp(void); - -enum { - SS_DISABLE = 4, - SIG_BLOCK = 1, - SIG_UNBLOCK = 2, - SIG_SETMASK = 3, - NSIG = 33, - SI_USER = 0, - - // From NetBSD's <sys/ucontext.h> - _UC_SIGMASK = 0x01, - _UC_CPU = 0x04, -}; diff --git a/src/runtime/os_netbsd_386.c b/src/runtime/os_netbsd_386.c deleted file mode 100644 index 23e9db3c1..000000000 --- a/src/runtime/os_netbsd_386.c +++ /dev/null @@ -1,17 +0,0 @@ -// 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 "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" - -void -runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void)) -{ - mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp; - mc->__gregs[REG_UESP] = (uint32)stack; - mc->__gregs[REG_EBX] = (uint32)mp; - mc->__gregs[REG_EDX] = (uint32)gp; - mc->__gregs[REG_ESI] = (uint32)fn; -} diff --git a/src/runtime/os_netbsd_amd64.c b/src/runtime/os_netbsd_amd64.c deleted file mode 100644 index 226846cbb..000000000 --- a/src/runtime/os_netbsd_amd64.c +++ /dev/null @@ -1,18 +0,0 @@ -// 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 "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" - -void -runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void)) -{ - // Machine dependent mcontext initialisation for LWP. - mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp; - mc->__gregs[REG_RSP] = (uint64)stack; - mc->__gregs[REG_R8] = (uint64)mp; - mc->__gregs[REG_R9] = (uint64)gp; - mc->__gregs[REG_R12] = (uint64)fn; -} diff --git a/src/runtime/os_plan9.c b/src/runtime/os_plan9.c deleted file mode 100644 index 18460fc12..000000000 --- a/src/runtime/os_plan9.c +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright 2010 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 "os_GOOS.h" -#include "arch_GOARCH.h" -#include "textflag.h" -#include "malloc.h" - -int8 *goos = "plan9"; -extern SigTab runtime·sigtab[]; - -int32 runtime·postnote(int32, int8*); - -// Called to initialize a new m (including the bootstrap m). -// Called on the parent thread (main thread in case of bootstrap), can allocate memory. -void -runtime·mpreinit(M *mp) -{ - // Initialize stack and goroutine for note handling. - mp->gsignal = runtime·malg(32*1024); - runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); - - mp->gsignal->m = mp; - runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); - - mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan); - runtime·writebarrierptr_nostore(&mp->notesig, mp->notesig); - - // Initialize stack for handling strings from the - // errstr system call, as used in package syscall. - mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan); - runtime·writebarrierptr_nostore(&mp->errstr, mp->errstr); -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the new thread, can not allocate memory. -void -runtime·minit(void) -{ - // Mask all SSE floating-point exceptions - // when running on the 64-bit kernel. - runtime·setfpmasks(); -} - -// Called from dropm to undo the effect of an minit. -void -runtime·unminit(void) -{ -} - - -static int32 -getproccount(void) -{ - int32 fd, i, n, ncpu; - byte buf[2048]; - - fd = runtime·open("/dev/sysstat", OREAD, 0); - if(fd < 0) - return 1; - ncpu = 0; - for(;;) { - n = runtime·read(fd, buf, sizeof buf); - if(n <= 0) - break; - for(i = 0; i < n; i++) { - if(buf[i] == '\n') - ncpu++; - } - } - runtime·close(fd); - return ncpu > 0 ? ncpu : 1; -} - -static int32 -getpid(void) -{ - byte b[20], *c; - int32 fd; - - runtime·memclr(b, sizeof(b)); - fd = runtime·open("#c/pid", 0, 0); - if(fd >= 0) { - runtime·read(fd, b, sizeof(b)); - runtime·close(fd); - } - c = b; - while(*c == ' ' || *c == '\t') - c++; - return runtime·atoi(c); -} - -void -runtime·osinit(void) -{ - runtime·ncpu = getproccount(); - g->m->procid = getpid(); - runtime·notify(runtime·sigtramp); -} - -void -runtime·crash(void) -{ - runtime·notify(nil); - *(int32*)0 = 0; -} - -#pragma textflag NOSPLIT -void -runtime·get_random_data(byte **rnd, int32 *rnd_len) -{ - static byte random_data[HashRandomBytes]; - int32 fd; - - fd = runtime·open("/dev/random", 0 /* O_RDONLY */, 0); - if(runtime·read(fd, random_data, HashRandomBytes) == HashRandomBytes) { - *rnd = random_data; - *rnd_len = HashRandomBytes; - } else { - *rnd = nil; - *rnd_len = 0; - } - runtime·close(fd); -} - -void -runtime·goenvs(void) -{ -} - -void -runtime·initsig(void) -{ -} - -#pragma textflag NOSPLIT -void -runtime·osyield(void) -{ - runtime·sleep(0); -} - -#pragma textflag NOSPLIT -void -runtime·usleep(uint32 µs) -{ - uint32 ms; - - ms = µs/1000; - if(ms == 0) - ms = 1; - runtime·sleep(ms); -} - -#pragma textflag NOSPLIT -int64 -runtime·nanotime(void) -{ - int64 ns, scratch; - - ns = runtime·nsec(&scratch); - // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. - if(ns == 0) - return scratch; - return ns; -} - -#pragma textflag NOSPLIT -void -runtime·itoa(int32 n, byte *p, uint32 len) -{ - byte *q, c; - uint32 i; - - if(len <= 1) - return; - - runtime·memclr(p, len); - q = p; - - if(n==0) { - *q++ = '0'; - USED(q); - return; - } - if(n < 0) { - *q++ = '-'; - p++; - n = -n; - } - for(i=0; n > 0 && i < len; i++) { - *q++ = '0' + (n%10); - n = n/10; - } - for(q--; q >= p; ) { - c = *p; - *p++ = *q; - *q-- = c; - } -} - -void -runtime·goexitsall(int8 *status) -{ - int8 buf[ERRMAX]; - M *mp; - int32 pid; - - runtime·snprintf((byte*)buf, sizeof buf, "go: exit %s", status); - pid = getpid(); - for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink) - if(mp->procid != pid) - runtime·postnote(mp->procid, buf); -} - -int32 -runtime·postnote(int32 pid, int8* msg) -{ - int32 fd; - intgo len; - uint8 buf[128]; - uint8 tmp[16]; - uint8 *p, *q; - - runtime·memclr(buf, sizeof buf); - - /* build path string /proc/pid/note */ - q = tmp; - p = buf; - runtime·itoa(pid, tmp, sizeof tmp); - runtime·memmove((void*)p, (void*)"/proc/", 6); - for(p += 6; *p++ = *q++; ); - p--; - runtime·memmove((void*)p, (void*)"/note", 5); - - fd = runtime·open((int8*)buf, OWRITE, 0); - if(fd < 0) - return -1; - - len = runtime·findnull((byte*)msg); - if(runtime·write(fd, msg, len) != len) { - runtime·close(fd); - return -1; - } - runtime·close(fd); - return 0; -} - -static void exit(void); - -#pragma textflag NOSPLIT -void -runtime·exit(int32 e) -{ - void (*fn)(void); - - g->m->scalararg[0] = e; - fn = exit; - runtime·onM(&fn); -} - -static void -exit(void) -{ - int32 e; - byte tmp[16]; - int8 *status; - - e = g->m->scalararg[0]; - g->m->scalararg[0] = 0; - - if(e == 0) - status = ""; - else { - /* build error string */ - runtime·itoa(e, tmp, sizeof tmp); - status = (int8*)tmp; - } - - runtime·goexitsall(status); - runtime·exits(status); -} - -void -runtime·newosproc(M *mp, void *stk) -{ - int32 pid; - - if(0) - runtime·printf("newosproc mp=%p ostk=%p\n", mp, &mp); - - USED(stk); - if((pid = runtime·rfork(RFPROC|RFMEM|RFNOWAIT)) < 0) - runtime·throw("newosproc: rfork failed\n"); - if(pid == 0) - runtime·tstart_plan9(mp); -} - -#pragma textflag NOSPLIT -uintptr -runtime·semacreate(void) -{ - return 1; -} - -#pragma textflag NOSPLIT -int32 -runtime·semasleep(int64 ns) -{ - int32 ret; - int32 ms; - - if(ns >= 0) { - ms = runtime·timediv(ns, 1000000, nil); - if(ms == 0) - ms = 1; - ret = runtime·plan9_tsemacquire(&g->m->waitsemacount, ms); - if(ret == 1) - return 0; // success - return -1; // timeout or interrupted - } - - while(runtime·plan9_semacquire(&g->m->waitsemacount, 1) < 0) { - /* interrupted; try again (c.f. lock_sema.c) */ - } - return 0; // success -} - -#pragma textflag NOSPLIT -void -runtime·semawakeup(M *mp) -{ - runtime·plan9_semrelease(&mp->waitsemacount, 1); -} - -#pragma textflag NOSPLIT -int32 -runtime·read(int32 fd, void *buf, int32 nbytes) -{ - return runtime·pread(fd, buf, nbytes, -1LL); -} - -#pragma textflag NOSPLIT -int32 -runtime·write(uintptr fd, void *buf, int32 nbytes) -{ - return runtime·pwrite((int32)fd, buf, nbytes, -1LL); -} - -uintptr -runtime·memlimit(void) -{ - return 0; -} - -#pragma dataflag NOPTR -static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n"; - -// This runs on a foreign stack, without an m or a g. No stack split. -#pragma textflag NOSPLIT -void -runtime·badsignal2(void) -{ - runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL); - runtime·exits(badsignal); -} diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go index 20e47bf42..2dcdfc009 100644 --- a/src/runtime/os_plan9.go +++ b/src/runtime/os_plan9.go @@ -6,22 +6,49 @@ package runtime import "unsafe" +//go:noescape func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 + +//go:noescape func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 + func seek(fd int32, offset int64, whence int32) int64 + +//go:noescape func exits(msg *byte) + +//go:noescape func brk_(addr unsafe.Pointer) uintptr + func sleep(ms int32) int32 + func rfork(flags int32) int32 + +//go:noescape func plan9_semacquire(addr *uint32, block int32) int32 + +//go:noescape func plan9_tsemacquire(addr *uint32, ms int32) int32 + +//go:noescape func plan9_semrelease(addr *uint32, count int32) int32 + +//go:noescape func notify(fn unsafe.Pointer) int32 + func noted(mode int32) int32 + +//go:noescape func nsec(*int64) int64 + +//go:noescape func sigtramp(ureg, msg unsafe.Pointer) + func setfpmasks() + +//go:noescape func tstart_plan9(newm *m) + func errstr() string type _Plink uintptr diff --git a/src/runtime/os_plan9.h b/src/runtime/os_plan9.h deleted file mode 100644 index 6d1802483..000000000 --- a/src/runtime/os_plan9.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2010 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. - -// Plan 9-specific system calls -int32 runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset); -int32 runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset); -int64 runtime·seek(int32 fd, int64 offset, int32 whence); -void runtime·exits(int8* msg); -intptr runtime·brk_(void*); -int32 runtime·sleep(int32 ms); -int32 runtime·rfork(int32 flags); -int32 runtime·plan9_semacquire(uint32 *addr, int32 block); -int32 runtime·plan9_tsemacquire(uint32 *addr, int32 ms); -int32 runtime·plan9_semrelease(uint32 *addr, int32 count); -int32 runtime·notify(void (*fn)(void*, int8*)); -int32 runtime·noted(int32); -int64 runtime·nsec(int64*); -void runtime·sigtramp(void*, int8*); -void runtime·sigpanic(void); -void runtime·goexitsall(int8*); -void runtime·setfpmasks(void); -void runtime·tstart_plan9(M *newm); - -/* open */ -enum -{ - OREAD = 0, - OWRITE = 1, - ORDWR = 2, - OEXEC = 3, - OTRUNC = 16, - OCEXEC = 32, - ORCLOSE = 64, - OEXCL = 0x1000 -}; - -/* rfork */ -enum -{ - RFNAMEG = (1<<0), - RFENVG = (1<<1), - RFFDG = (1<<2), - RFNOTEG = (1<<3), - RFPROC = (1<<4), - RFMEM = (1<<5), - RFNOWAIT = (1<<6), - RFCNAMEG = (1<<10), - RFCENVG = (1<<11), - RFCFDG = (1<<12), - RFREND = (1<<13), - RFNOMNT = (1<<14) -}; - -/* notify */ -enum -{ - NCONT = 0, - NDFLT = 1 -}; - -typedef struct Tos Tos; -typedef intptr _Plink; - -struct Tos { - struct TosProf /* Per process profiling */ - { - _Plink *pp; /* known to be 0(ptr) */ - _Plink *next; /* known to be 4(ptr) */ - _Plink *last; - _Plink *first; - uint32 pid; - uint32 what; - } prof; - uint64 cyclefreq; /* cycle clock frequency if there is one, 0 otherwise */ - int64 kcycles; /* cycles spent in kernel */ - int64 pcycles; /* cycles spent in process (kernel + user) */ - uint32 pid; /* might as well put the pid here */ - uint32 clock; - /* top of stack is here */ -}; - -enum { - NSIG = 14, /* number of signals in runtime·SigTab array */ - ERRMAX = 128, /* max length of note string */ - - /* Notes in runtime·sigtab that are handled by runtime·sigpanic. */ - SIGRFAULT = 2, - SIGWFAULT = 3, - SIGINTDIV = 4, - SIGFLOAT = 5, - SIGTRAP = 6, -}; diff --git a/src/runtime/os_plan9_386.c b/src/runtime/os_plan9_386.c deleted file mode 100644 index 42c6d161c..000000000 --- a/src/runtime/os_plan9_386.c +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2010 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 "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "signals_GOOS.h" - -void -runtime·dumpregs(Ureg *u) -{ - runtime·printf("ax %x\n", u->ax); - runtime·printf("bx %x\n", u->bx); - runtime·printf("cx %x\n", u->cx); - runtime·printf("dx %x\n", u->dx); - runtime·printf("di %x\n", u->di); - runtime·printf("si %x\n", u->si); - runtime·printf("bp %x\n", u->bp); - runtime·printf("sp %x\n", u->sp); - runtime·printf("pc %x\n", u->pc); - runtime·printf("flags %x\n", u->flags); - runtime·printf("cs %x\n", u->cs); - runtime·printf("fs %x\n", u->fs); - runtime·printf("gs %x\n", u->gs); -} - -int32 -runtime·sighandler(void *v, int8 *note, G *gp) -{ - uintptr *sp; - SigTab *t; - bool crash; - Ureg *ureg; - intgo len, n; - int32 sig, flags; - - ureg = (Ureg*)v; - - // The kernel will never pass us a nil note or ureg so we probably - // made a mistake somewhere in runtime·sigtramp. - if(ureg == nil || note == nil) { - runtime·printf("sighandler: ureg %p note %p\n", ureg, note); - goto Throw; - } - - // Check that the note is no more than ERRMAX bytes (including - // the trailing NUL). We should never receive a longer note. - len = runtime·findnull((byte*)note); - if(len > ERRMAX-1) { - runtime·printf("sighandler: note is longer than ERRMAX\n"); - goto Throw; - } - - // See if the note matches one of the patterns in runtime·sigtab. - // Notes that do not match any pattern can be handled at a higher - // level by the program but will otherwise be ignored. - flags = SigNotify; - for(sig = 0; sig < nelem(runtime·sigtab); sig++) { - t = &runtime·sigtab[sig]; - n = runtime·findnull((byte*)t->name); - if(len < n) - continue; - if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) { - flags = t->flags; - break; - } - } - - if(flags & SigGoExit) - runtime·exits(note+9); // Strip "go: exit " prefix. - - if(flags & SigPanic) { - // Copy the error string from sigtramp's stack into m->notesig so - // we can reliably access it from the panic routines. - runtime·memmove(g->m->notesig, note, len+1); - - gp->sig = sig; - gp->sigpc = ureg->pc; - - // Only push runtime·sigpanic if PC != 0. - // - // If PC == 0, probably panicked because of a call to a nil func. - // Not pushing that onto SP will make the trace look like a call - // to runtime·sigpanic instead. (Otherwise the trace will end at - // runtime·sigpanic and we won't get to see who faulted). - if(ureg->pc != 0) { - sp = (uintptr*)ureg->sp; - *--sp = ureg->pc; - ureg->sp = (uint32)sp; - } - ureg->pc = (uintptr)runtime·sigpanic; - return NCONT; - } - - if(flags & SigNotify) { - // TODO(ality): See if os/signal wants it. - //if(runtime·sigsend(...)) - // return NCONT; - } - if(flags & SigKill) - goto Exit; - if(!(flags & SigThrow)) - return NCONT; - -Throw: - g->m->throwing = 1; - g->m->caughtsig = gp; - runtime·startpanic(); - - runtime·printf("%s\n", note); - runtime·printf("PC=%x\n", ureg->pc); - runtime·printf("\n"); - - if(runtime·gotraceback(&crash)) { - runtime·goroutineheader(gp); - runtime·tracebacktrap(ureg->pc, ureg->sp, 0, gp); - runtime·tracebackothers(gp); - runtime·printf("\n"); - runtime·dumpregs(ureg); - } - - if(crash) - runtime·crash(); - -Exit: - runtime·goexitsall(note); - runtime·exits(note); - return NDFLT; // not reached -} - -void -runtime·sigenable(uint32 sig) -{ - USED(sig); -} - -void -runtime·sigdisable(uint32 sig) -{ - USED(sig); -} - -void -runtime·resetcpuprofiler(int32 hz) -{ - // TODO: Enable profiling interrupts. - - g->m->profilehz = hz; -} diff --git a/src/runtime/os_plan9_386.go b/src/runtime/os_plan9_386.go new file mode 100644 index 000000000..7dda13931 --- /dev/null +++ b/src/runtime/os_plan9_386.go @@ -0,0 +1,131 @@ +// Copyright 2010 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 "unsafe" + +func dumpregs(u *ureg) { + print("ax ", hex(u.ax), "\n") + print("bx ", hex(u.bx), "\n") + print("cx ", hex(u.cx), "\n") + print("dx ", hex(u.dx), "\n") + print("di ", hex(u.di), "\n") + print("si ", hex(u.si), "\n") + print("bp ", hex(u.bp), "\n") + print("sp ", hex(u.sp), "\n") + print("pc ", hex(u.pc), "\n") + print("flags ", hex(u.flags), "\n") + print("cs ", hex(u.cs), "\n") + print("fs ", hex(u.fs), "\n") + print("gs ", hex(u.gs), "\n") +} + +func sighandler(_ureg *ureg, note *byte, gp *g) int { + _g_ := getg() + var t sigTabT + var docrash bool + var length int + var sig int + var flags int + + // The kernel will never pass us a nil note or ureg so we probably + // made a mistake somewhere in sigtramp. + if _ureg == nil || note == nil { + print("sighandler: ureg ", _ureg, " note ", note, "\n") + goto Throw + } + // Check that the note is no more than ERRMAX bytes (including + // the trailing NUL). We should never receive a longer note. + length = findnull(note) + if length > _ERRMAX-1 { + print("sighandler: note is longer than ERRMAX\n") + goto Throw + } + // See if the note matches one of the patterns in sigtab. + // Notes that do not match any pattern can be handled at a higher + // level by the program but will otherwise be ignored. + flags = _SigNotify + for sig, t = range sigtable { + n := len(t.name) + if length < n { + continue + } + if strncmp(note, &t.name[0], uintptr(n)) == 0 { + flags = t.flags + break + } + } + if flags&_SigGoExit != 0 { + exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix. + } + if flags&_SigPanic != 0 { + // Copy the error string from sigtramp's stack into m->notesig so + // we can reliably access it from the panic routines. + memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(length+1)) + gp.sig = uint32(sig) + gp.sigpc = uintptr(_ureg.pc) + // Only push sigpanic if PC != 0. + // + // If PC == 0, probably panicked because of a call to a nil func. + // Not pushing that onto SP will make the trace look like a call + // to sigpanic instead. (Otherwise the trace will end at + // sigpanic and we won't get to see who faulted). + if _ureg.pc != 0 { + sp := _ureg.sp + if regSize > ptrSize { + sp -= ptrSize + *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0 + } + sp -= ptrSize + *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(_ureg.pc) + _ureg.sp = sp + } + _ureg.pc = uint32(funcPC(sigpanic)) + return _NCONT + } + if flags&_SigNotify != 0 { + // TODO(ality): See if os/signal wants it. + //if(sigsend(...)) + // return _NCONT; + } + if flags&_SigKill != 0 { + goto Exit + } + if flags&_SigThrow == 0 { + return _NCONT + } +Throw: + _g_.m.throwing = 1 + _g_.m.caughtsig = gp + startpanic() + print(gostringnocopy(note), "\n") + print("PC=", hex(_ureg.pc), "\n") + print("\n") + if gotraceback(&docrash) > 0 { + goroutineheader(gp) + tracebacktrap(uintptr(_ureg.pc), uintptr(_ureg.sp), 0, gp) + tracebackothers(gp) + print("\n") + dumpregs(_ureg) + } + if docrash { + crash() + } +Exit: + goexitsall(note) + exits(note) + return _NDFLT // not reached +} + +func sigenable(sig uint32) { +} + +func sigdisable(sig uint32) { +} + +func resetcpuprofiler(hz int32) { + // TODO: Enable profiling interrupts. + getg().m.profilehz = hz +} diff --git a/src/runtime/os_plan9_amd64.c b/src/runtime/os_plan9_amd64.c deleted file mode 100644 index a9dc0eb96..000000000 --- a/src/runtime/os_plan9_amd64.c +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2010 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 "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "signals_GOOS.h" - -void -runtime·dumpregs(Ureg *u) -{ - runtime·printf("ax %X\n", u->ax); - runtime·printf("bx %X\n", u->bx); - runtime·printf("cx %X\n", u->cx); - runtime·printf("dx %X\n", u->dx); - runtime·printf("di %X\n", u->di); - runtime·printf("si %X\n", u->si); - runtime·printf("bp %X\n", u->bp); - runtime·printf("sp %X\n", u->sp); - runtime·printf("r8 %X\n", u->r8); - runtime·printf("r9 %X\n", u->r9); - runtime·printf("r10 %X\n", u->r10); - runtime·printf("r11 %X\n", u->r11); - runtime·printf("r12 %X\n", u->r12); - runtime·printf("r13 %X\n", u->r13); - runtime·printf("r14 %X\n", u->r14); - runtime·printf("r15 %X\n", u->r15); - runtime·printf("ip %X\n", u->ip); - runtime·printf("flags %X\n", u->flags); - runtime·printf("cs %X\n", (uint64)u->cs); - runtime·printf("fs %X\n", (uint64)u->fs); - runtime·printf("gs %X\n", (uint64)u->gs); -} - -int32 -runtime·sighandler(void *v, int8 *note, G *gp) -{ - uintptr *sp; - SigTab *t; - bool crash; - Ureg *ureg; - intgo len, n; - int32 sig, flags; - - ureg = (Ureg*)v; - - // The kernel will never pass us a nil note or ureg so we probably - // made a mistake somewhere in runtime·sigtramp. - if(ureg == nil || note == nil) { - runtime·printf("sighandler: ureg %p note %p\n", ureg, note); - goto Throw; - } - - // Check that the note is no more than ERRMAX bytes (including - // the trailing NUL). We should never receive a longer note. - len = runtime·findnull((byte*)note); - if(len > ERRMAX-1) { - runtime·printf("sighandler: note is longer than ERRMAX\n"); - goto Throw; - } - - // See if the note matches one of the patterns in runtime·sigtab. - // Notes that do not match any pattern can be handled at a higher - // level by the program but will otherwise be ignored. - flags = SigNotify; - for(sig = 0; sig < nelem(runtime·sigtab); sig++) { - t = &runtime·sigtab[sig]; - n = runtime·findnull((byte*)t->name); - if(len < n) - continue; - if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) { - flags = t->flags; - break; - } - } - - if(flags & SigGoExit) - runtime·exits(note+9); // Strip "go: exit " prefix. - - if(flags & SigPanic) { - // Copy the error string from sigtramp's stack into m->notesig so - // we can reliably access it from the panic routines. - runtime·memmove(g->m->notesig, note, len+1); - - gp->sig = sig; - gp->sigpc = ureg->ip; - - // Only push runtime·sigpanic if PC != 0. - // - // If PC == 0, probably panicked because of a call to a nil func. - // Not pushing that onto SP will make the trace look like a call - // to runtime·sigpanic instead. (Otherwise the trace will end at - // runtime·sigpanic and we won't get to see who faulted). - if(ureg->ip != 0) { - sp = (uintptr*)ureg->sp; - *--sp = ureg->ip; - ureg->sp = (uint64)sp; - } - ureg->ip = (uintptr)runtime·sigpanic; - return NCONT; - } - - if(flags & SigNotify) { - // TODO(ality): See if os/signal wants it. - //if(runtime·sigsend(...)) - // return NCONT; - } - if(flags & SigKill) - goto Exit; - if(!(flags & SigThrow)) - return NCONT; - -Throw: - g->m->throwing = 1; - g->m->caughtsig = gp; - runtime·startpanic(); - - runtime·printf("%s\n", note); - runtime·printf("PC=%X\n", ureg->ip); - runtime·printf("\n"); - - if(runtime·gotraceback(&crash)) { - runtime·goroutineheader(gp); - runtime·tracebacktrap(ureg->ip, ureg->sp, 0, gp); - runtime·tracebackothers(gp); - runtime·printf("\n"); - runtime·dumpregs(ureg); - } - - if(crash) - runtime·crash(); - -Exit: - runtime·goexitsall(note); - runtime·exits(note); - return NDFLT; // not reached -} - -void -runtime·sigenable(uint32 sig) -{ - USED(sig); -} - -void -runtime·sigdisable(uint32 sig) -{ - USED(sig); -} - -void -runtime·resetcpuprofiler(int32 hz) -{ - // TODO: Enable profiling interrupts. - - g->m->profilehz = hz; -} diff --git a/src/runtime/os_plan9_amd64.go b/src/runtime/os_plan9_amd64.go new file mode 100644 index 000000000..8727dcc20 --- /dev/null +++ b/src/runtime/os_plan9_amd64.go @@ -0,0 +1,139 @@ +// Copyright 2010 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 "unsafe" + +func dumpregs(u *ureg) { + print("ax ", hex(u.ax), "\n") + print("bx ", hex(u.bx), "\n") + print("cx ", hex(u.cx), "\n") + print("dx ", hex(u.dx), "\n") + print("di ", hex(u.di), "\n") + print("si ", hex(u.si), "\n") + print("bp ", hex(u.bp), "\n") + print("sp ", hex(u.sp), "\n") + print("r8 ", hex(u.r8), "\n") + print("r9 ", hex(u.r9), "\n") + print("r10 ", hex(u.r10), "\n") + print("r11 ", hex(u.r11), "\n") + print("r12 ", hex(u.r12), "\n") + print("r13 ", hex(u.r13), "\n") + print("r14 ", hex(u.r14), "\n") + print("r15 ", hex(u.r15), "\n") + print("ip ", hex(u.ip), "\n") + print("flags ", hex(u.flags), "\n") + print("cs ", hex(uint64(u.cs)), "\n") + print("fs ", hex(uint64(u.fs)), "\n") + print("gs ", hex(uint64(u.gs)), "\n") +} + +func sighandler(_ureg *ureg, note *byte, gp *g) int { + _g_ := getg() + var t sigTabT + var docrash bool + var length int + var sig int + var flags int + + // The kernel will never pass us a nil note or ureg so we probably + // made a mistake somewhere in sigtramp. + if _ureg == nil || note == nil { + print("sighandler: ureg ", _ureg, " note ", note, "\n") + goto Throw + } + // Check that the note is no more than ERRMAX bytes (including + // the trailing NUL). We should never receive a longer note. + length = findnull(note) + if length > _ERRMAX-1 { + print("sighandler: note is longer than ERRMAX\n") + goto Throw + } + // See if the note matches one of the patterns in sigtab. + // Notes that do not match any pattern can be handled at a higher + // level by the program but will otherwise be ignored. + flags = _SigNotify + for sig, t = range sigtable { + n := len(t.name) + if length < n { + continue + } + if strncmp(note, &t.name[0], uintptr(n)) == 0 { + flags = t.flags + break + } + } + if flags&_SigGoExit != 0 { + exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix. + } + if flags&_SigPanic != 0 { + // Copy the error string from sigtramp's stack into m->notesig so + // we can reliably access it from the panic routines. + memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(length+1)) + gp.sig = uint32(sig) + gp.sigpc = uintptr(_ureg.ip) + // Only push sigpanic if PC != 0. + // + // If PC == 0, probably panicked because of a call to a nil func. + // Not pushing that onto SP will make the trace look like a call + // to sigpanic instead. (Otherwise the trace will end at + // sigpanic and we won't get to see who faulted). + if _ureg.ip != 0 { + sp := _ureg.sp + if regSize > ptrSize { + sp -= ptrSize + *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0 + } + sp -= ptrSize + *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(_ureg.ip) + _ureg.sp = sp + } + _ureg.ip = uint64(funcPC(sigpanic)) + return _NCONT + } + if flags&_SigNotify != 0 { + // TODO(ality): See if os/signal wants it. + //if(sigsend(...)) + // return _NCONT; + } + if flags&_SigKill != 0 { + goto Exit + } + if flags&_SigThrow == 0 { + return _NCONT + } +Throw: + _g_.m.throwing = 1 + _g_.m.caughtsig = gp + startpanic() + print(gostringnocopy(note), "\n") + print("PC=", hex(_ureg.ip), "\n") + print("\n") + if gotraceback(&docrash) > 0 { + goroutineheader(gp) + tracebacktrap(uintptr(_ureg.ip), uintptr(_ureg.sp), 0, gp) + tracebackothers(gp) + print("\n") + dumpregs(_ureg) + } + if docrash { + crash() + } +Exit: + goexitsall(note) + exits(note) + return _NDFLT // not reached +} + +func sigenable(sig uint32) { +} + +func sigdisable(sig uint32) { +} + +func resetcpuprofiler(hz int32) { + // TODO: Enable profiling interrupts. + getg().m.profilehz = hz +} diff --git a/src/runtime/os_windows.c b/src/runtime/os_windows.c deleted file mode 100644 index b8b8eda5f..000000000 --- a/src/runtime/os_windows.c +++ /dev/null @@ -1,636 +0,0 @@ -// 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 "type.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "textflag.h" -#include "arch_GOARCH.h" -#include "malloc.h" - -#pragma dynimport runtime·AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll" -#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll" -#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll" -#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll" -#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll" -#pragma dynimport runtime·CryptAcquireContextW CryptAcquireContextW "advapi32.dll" -#pragma dynimport runtime·CryptGenRandom CryptGenRandom "advapi32.dll" -#pragma dynimport runtime·CryptReleaseContext CryptReleaseContext "advapi32.dll" -#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll" -#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll" -#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll" -#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll" -#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll" -#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll" -#pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll" -#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll" -#pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll" -#pragma dynimport runtime·LoadLibraryA LoadLibraryA "kernel32.dll" -#pragma dynimport runtime·NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll" -#pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll" -#pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll" -#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll" -#pragma dynimport runtime·SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll" -#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll" -#pragma dynimport runtime·SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll" -#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll" -#pragma dynimport runtime·Sleep Sleep "kernel32.dll" -#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll" -#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll" -#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll" -#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll" - -extern void *runtime·AddVectoredExceptionHandler; -extern void *runtime·CloseHandle; -extern void *runtime·CreateEvent; -extern void *runtime·CreateThread; -extern void *runtime·CreateWaitableTimer; -extern void *runtime·CryptAcquireContextW; -extern void *runtime·CryptGenRandom; -extern void *runtime·CryptReleaseContext; -extern void *runtime·DuplicateHandle; -extern void *runtime·ExitProcess; -extern void *runtime·FreeEnvironmentStringsW; -extern void *runtime·GetEnvironmentStringsW; -extern void *runtime·GetProcAddress; -extern void *runtime·GetStdHandle; -extern void *runtime·GetSystemInfo; -extern void *runtime·GetThreadContext; -extern void *runtime·LoadLibrary; -extern void *runtime·LoadLibraryA; -extern void *runtime·NtWaitForSingleObject; -extern void *runtime·ResumeThread; -extern void *runtime·SetConsoleCtrlHandler; -extern void *runtime·SetEvent; -extern void *runtime·SetProcessPriorityBoost; -extern void *runtime·SetThreadPriority; -extern void *runtime·SetUnhandledExceptionFilter; -extern void *runtime·SetWaitableTimer; -extern void *runtime·Sleep; -extern void *runtime·SuspendThread; -extern void *runtime·WaitForSingleObject; -extern void *runtime·WriteFile; -extern void *runtime·timeBeginPeriod; - -#pragma dataflag NOPTR -void *runtime·GetQueuedCompletionStatusEx; - -extern uintptr runtime·externalthreadhandlerp; -void runtime·externalthreadhandler(void); -void runtime·exceptiontramp(void); -void runtime·firstcontinuetramp(void); -void runtime·lastcontinuetramp(void); - -#pragma textflag NOSPLIT -uintptr -runtime·getLoadLibrary(void) -{ - return (uintptr)runtime·LoadLibrary; -} - -#pragma textflag NOSPLIT -uintptr -runtime·getGetProcAddress(void) -{ - return (uintptr)runtime·GetProcAddress; -} - -static int32 -getproccount(void) -{ - SystemInfo info; - - runtime·stdcall1(runtime·GetSystemInfo, (uintptr)&info); - return info.dwNumberOfProcessors; -} - -void -runtime·osinit(void) -{ - void *kernel32; - void *addVectoredContinueHandler; - - kernel32 = runtime·stdcall1(runtime·LoadLibraryA, (uintptr)"kernel32.dll"); - - runtime·externalthreadhandlerp = (uintptr)runtime·externalthreadhandler; - - runtime·stdcall2(runtime·AddVectoredExceptionHandler, 1, (uintptr)runtime·exceptiontramp); - addVectoredContinueHandler = nil; - if(kernel32 != nil) - addVectoredContinueHandler = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"AddVectoredContinueHandler"); - if(addVectoredContinueHandler == nil || sizeof(void*) == 4) { - // use SetUnhandledExceptionFilter for windows-386 or - // if VectoredContinueHandler is unavailable. - // note: SetUnhandledExceptionFilter handler won't be called, if debugging. - runtime·stdcall1(runtime·SetUnhandledExceptionFilter, (uintptr)runtime·lastcontinuetramp); - } else { - runtime·stdcall2(addVectoredContinueHandler, 1, (uintptr)runtime·firstcontinuetramp); - runtime·stdcall2(addVectoredContinueHandler, 0, (uintptr)runtime·lastcontinuetramp); - } - - runtime·stdcall2(runtime·SetConsoleCtrlHandler, (uintptr)runtime·ctrlhandler, 1); - - runtime·stdcall1(runtime·timeBeginPeriod, 1); - - runtime·ncpu = getproccount(); - - // Windows dynamic priority boosting assumes that a process has different types - // of dedicated threads -- GUI, IO, computational, etc. Go processes use - // equivalent threads that all do a mix of GUI, IO, computations, etc. - // In such context dynamic priority boosting does nothing but harm, so we turn it off. - runtime·stdcall2(runtime·SetProcessPriorityBoost, -1, 1); - - if(kernel32 != nil) { - runtime·GetQueuedCompletionStatusEx = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"GetQueuedCompletionStatusEx"); - } -} - -#pragma textflag NOSPLIT -void -runtime·get_random_data(byte **rnd, int32 *rnd_len) -{ - uintptr handle; - *rnd = nil; - *rnd_len = 0; - if(runtime·stdcall5(runtime·CryptAcquireContextW, (uintptr)&handle, (uintptr)nil, (uintptr)nil, - 1 /* PROV_RSA_FULL */, - 0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) { - static byte random_data[HashRandomBytes]; - if(runtime·stdcall3(runtime·CryptGenRandom, handle, HashRandomBytes, (uintptr)&random_data[0])) { - *rnd = random_data; - *rnd_len = HashRandomBytes; - } - runtime·stdcall2(runtime·CryptReleaseContext, handle, 0); - } -} - -void -runtime·goenvs(void) -{ - extern Slice runtime·envs; - - uint16 *env; - String *s; - int32 i, n; - uint16 *p; - - env = runtime·stdcall0(runtime·GetEnvironmentStringsW); - - n = 0; - for(p=env; *p; n++) - p += runtime·findnullw(p)+1; - - runtime·envs = runtime·makeStringSlice(n); - s = (String*)runtime·envs.array; - - p = env; - for(i=0; i<n; i++) { - s[i] = runtime·gostringw(p); - p += runtime·findnullw(p)+1; - } - - runtime·stdcall1(runtime·FreeEnvironmentStringsW, (uintptr)env); -} - -#pragma textflag NOSPLIT -void -runtime·exit(int32 code) -{ - runtime·stdcall1(runtime·ExitProcess, code); -} - -#pragma textflag NOSPLIT -int32 -runtime·write(uintptr fd, void *buf, int32 n) -{ - void *handle; - uint32 written; - - written = 0; - switch(fd) { - case 1: - handle = runtime·stdcall1(runtime·GetStdHandle, -11); - break; - case 2: - handle = runtime·stdcall1(runtime·GetStdHandle, -12); - break; - default: - // assume fd is real windows handle. - handle = (void*)fd; - break; - } - runtime·stdcall5(runtime·WriteFile, (uintptr)handle, (uintptr)buf, n, (uintptr)&written, 0); - return written; -} - -#define INFINITE ((uintptr)0xFFFFFFFF) - -#pragma textflag NOSPLIT -int32 -runtime·semasleep(int64 ns) -{ - // store ms in ns to save stack space - if(ns < 0) - ns = INFINITE; - else { - ns = runtime·timediv(ns, 1000000, nil); - if(ns == 0) - ns = 1; - } - if(runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)g->m->waitsema, ns) != 0) - return -1; // timeout - return 0; -} - -#pragma textflag NOSPLIT -void -runtime·semawakeup(M *mp) -{ - runtime·stdcall1(runtime·SetEvent, mp->waitsema); -} - -#pragma textflag NOSPLIT -uintptr -runtime·semacreate(void) -{ - return (uintptr)runtime·stdcall4(runtime·CreateEvent, 0, 0, 0, 0); -} - -#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000) - -void -runtime·newosproc(M *mp, void *stk) -{ - void *thandle; - - USED(stk); - - thandle = runtime·stdcall6(runtime·CreateThread, - (uintptr)nil, 0x20000, (uintptr)runtime·tstart_stdcall, (uintptr)mp, - STACK_SIZE_PARAM_IS_A_RESERVATION, (uintptr)nil); - if(thandle == nil) { - runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror()); - runtime·throw("runtime.newosproc"); - } -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the parent thread (main thread in case of bootstrap), can allocate memory. -void -runtime·mpreinit(M *mp) -{ - USED(mp); -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the new thread, can not allocate memory. -void -runtime·minit(void) -{ - uintptr thandle; - - // -1 = current process, -2 = current thread - runtime·stdcall7(runtime·DuplicateHandle, -1, -2, -1, (uintptr)&thandle, 0, 0, DUPLICATE_SAME_ACCESS); - runtime·atomicstoreuintptr(&g->m->thread, thandle); -} - -// Called from dropm to undo the effect of an minit. -void -runtime·unminit(void) -{ - runtime·stdcall1(runtime·CloseHandle, g->m->thread); - g->m->thread = 0; -} - -// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/ -typedef struct KSYSTEM_TIME { - uint32 LowPart; - int32 High1Time; - int32 High2Time; -} KSYSTEM_TIME; - -#pragma dataflag NOPTR -const KSYSTEM_TIME* INTERRUPT_TIME = (KSYSTEM_TIME*)0x7ffe0008; -#pragma dataflag NOPTR -const KSYSTEM_TIME* SYSTEM_TIME = (KSYSTEM_TIME*)0x7ffe0014; - -static void badsystime(void); - -#pragma textflag NOSPLIT -int64 -runtime·systime(KSYSTEM_TIME *timeaddr) -{ - KSYSTEM_TIME t; - int32 i; - void (*fn)(void); - - for(i = 1; i < 10000; i++) { - // these fields must be read in that order (see URL above) - t.High1Time = timeaddr->High1Time; - t.LowPart = timeaddr->LowPart; - t.High2Time = timeaddr->High2Time; - if(t.High1Time == t.High2Time) - return (int64)t.High1Time<<32 | t.LowPart; - if((i%100) == 0) - runtime·osyield(); - } - fn = badsystime; - runtime·onM(&fn); - return 0; -} - -#pragma textflag NOSPLIT -int64 -runtime·unixnano(void) -{ - return (runtime·systime(SYSTEM_TIME) - 116444736000000000LL) * 100LL; -} - -static void -badsystime(void) -{ - runtime·throw("interrupt/system time is changing too fast"); -} - -#pragma textflag NOSPLIT -int64 -runtime·nanotime(void) -{ - return runtime·systime(INTERRUPT_TIME) * 100LL; -} - -// Calling stdcall on os stack. -#pragma textflag NOSPLIT -static void* -stdcall(void *fn) -{ - g->m->libcall.fn = (uintptr)fn; - if(g->m->profilehz != 0) { - // leave pc/sp for cpu profiler - g->m->libcallg = g; - g->m->libcallpc = (uintptr)runtime·getcallerpc(&fn); - // sp must be the last, because once async cpu profiler finds - // all three values to be non-zero, it will use them - g->m->libcallsp = (uintptr)runtime·getcallersp(&fn); - } - runtime·asmcgocall(runtime·asmstdcall, &g->m->libcall); - g->m->libcallsp = 0; - return (void*)g->m->libcall.r1; -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall0(void *fn) -{ - g->m->libcall.n = 0; - g->m->libcall.args = (uintptr)&fn; // it's unused but must be non-nil, otherwise crashes - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall1(void *fn, uintptr a0) -{ - USED(a0); - g->m->libcall.n = 1; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall2(void *fn, uintptr a0, uintptr a1) -{ - USED(a0, a1); - g->m->libcall.n = 2; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2) -{ - USED(a0, a1, a2); - g->m->libcall.n = 3; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3) -{ - USED(a0, a1, a2, a3); - g->m->libcall.n = 4; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4) -{ - USED(a0, a1, a2, a3, a4); - g->m->libcall.n = 5; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5) -{ - USED(a0, a1, a2, a3, a4, a5); - g->m->libcall.n = 6; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -#pragma textflag NOSPLIT -void* -runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6) -{ - USED(a0, a1, a2, a3, a4, a5, a6); - g->m->libcall.n = 7; - g->m->libcall.args = (uintptr)&a0; - return stdcall(fn); -} - -extern void runtime·usleep1(uint32); - -#pragma textflag NOSPLIT -void -runtime·osyield(void) -{ - runtime·usleep1(1); -} - -#pragma textflag NOSPLIT -void -runtime·usleep(uint32 us) -{ - // Have 1us units; want 100ns units. - runtime·usleep1(10*us); -} - -uint32 -runtime·issigpanic(uint32 code) -{ - switch(code) { - case EXCEPTION_ACCESS_VIOLATION: - case EXCEPTION_INT_DIVIDE_BY_ZERO: - case EXCEPTION_INT_OVERFLOW: - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_UNDERFLOW: - case EXCEPTION_BREAKPOINT: - return 1; - } - return 0; -} - -void -runtime·initsig(void) -{ - // following line keeps these functions alive at link stage - // if there's a better way please write it here - void *e = runtime·exceptiontramp; - void *f = runtime·firstcontinuetramp; - void *l = runtime·lastcontinuetramp; - USED(e); - USED(f); - USED(l); -} - -uint32 -runtime·ctrlhandler1(uint32 type) -{ - int32 s; - - switch(type) { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - s = SIGINT; - break; - default: - return 0; - } - - if(runtime·sigsend(s)) - return 1; - runtime·exit(2); // SIGINT, SIGTERM, etc - return 0; -} - -extern void runtime·dosigprof(Context *r, G *gp, M *mp); -extern void runtime·profileloop(void); -#pragma dataflag NOPTR -static void *profiletimer; - -static void -profilem(M *mp) -{ - extern M runtime·m0; - extern uint32 runtime·tls0[]; - byte rbuf[sizeof(Context)+15]; - Context *r; - void *tls; - G *gp; - - tls = mp->tls; - if(mp == &runtime·m0) - tls = runtime·tls0; - gp = *(G**)tls; - - // align Context to 16 bytes - r = (Context*)((uintptr)(&rbuf[15]) & ~15); - r->ContextFlags = CONTEXT_CONTROL; - runtime·stdcall2(runtime·GetThreadContext, (uintptr)mp->thread, (uintptr)r); - runtime·dosigprof(r, gp, mp); -} - -void -runtime·profileloop1(void) -{ - M *mp, *allm; - uintptr thread; - - runtime·stdcall2(runtime·SetThreadPriority, -2, THREAD_PRIORITY_HIGHEST); - - for(;;) { - runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)profiletimer, -1); - allm = runtime·atomicloadp(&runtime·allm); - for(mp = allm; mp != nil; mp = mp->alllink) { - thread = runtime·atomicloaduintptr(&mp->thread); - // Do not profile threads blocked on Notes, - // this includes idle worker threads, - // idle timer thread, idle heap scavenger, etc. - if(thread == 0 || mp->profilehz == 0 || mp->blocked) - continue; - runtime·stdcall1(runtime·SuspendThread, (uintptr)thread); - if(mp->profilehz != 0 && !mp->blocked) - profilem(mp); - runtime·stdcall1(runtime·ResumeThread, (uintptr)thread); - } - } -} - -void -runtime·resetcpuprofiler(int32 hz) -{ - static Mutex lock; - void *timer, *thread; - int32 ms; - int64 due; - - runtime·lock(&lock); - if(profiletimer == nil) { - timer = runtime·stdcall3(runtime·CreateWaitableTimer, (uintptr)nil, (uintptr)nil, (uintptr)nil); - runtime·atomicstorep(&profiletimer, timer); - thread = runtime·stdcall6(runtime·CreateThread, - (uintptr)nil, (uintptr)nil, (uintptr)runtime·profileloop, (uintptr)nil, (uintptr)nil, (uintptr)nil); - runtime·stdcall2(runtime·SetThreadPriority, (uintptr)thread, THREAD_PRIORITY_HIGHEST); - runtime·stdcall1(runtime·CloseHandle, (uintptr)thread); - } - runtime·unlock(&lock); - - ms = 0; - due = 1LL<<63; - if(hz > 0) { - ms = 1000 / hz; - if(ms == 0) - ms = 1; - due = ms * -10000; - } - runtime·stdcall6(runtime·SetWaitableTimer, - (uintptr)profiletimer, (uintptr)&due, ms, (uintptr)nil, (uintptr)nil, (uintptr)nil); - runtime·atomicstore((uint32*)&g->m->profilehz, hz); -} - -uintptr -runtime·memlimit(void) -{ - return 0; -} - -#pragma dataflag NOPTR -int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n"; -int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1; - -void -runtime·crash(void) -{ - // TODO: This routine should do whatever is needed - // to make the Windows program abort/crash as it - // would if Go was not intercepting signals. - // On Unix the routine would remove the custom signal - // handler and then raise a signal (like SIGABRT). - // Something like that should happen here. - // It's okay to leave this empty for now: if crash returns - // the ordinary exit-after-panic happens. -} diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index fcd8f44cc..097b5d629 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -4,24 +4,8 @@ package runtime -import "unsafe" - type stdFunction *byte -func stdcall0(fn stdFunction) uintptr -func stdcall1(fn stdFunction, a0 uintptr) uintptr -func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr -func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr -func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr -func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr -func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr -func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr - -func asmstdcall(fn unsafe.Pointer) -func getlasterror() uint32 -func setlasterror(err uint32) -func usleep1(usec uint32) - func os_sigpipe() { gothrow("too many writes on closed pipe") } diff --git a/src/runtime/os_windows.h b/src/runtime/os_windows.h deleted file mode 100644 index d5d168d77..000000000 --- a/src/runtime/os_windows.h +++ /dev/null @@ -1,42 +0,0 @@ -// 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. - -extern void *runtime·LoadLibrary; -extern void *runtime·GetProcAddress; -extern void *runtime·GetQueuedCompletionStatusEx; - -// Call a Windows function with stdcall conventions, -// and switch to os stack during the call. -void runtime·asmstdcall(void *c); -void *runtime·stdcall0(void *fn); -void *runtime·stdcall1(void *fn, uintptr a0); -void *runtime·stdcall2(void *fn, uintptr a0, uintptr a1); -void *runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2); -void *runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3); -void *runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4); -void *runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5); -void *runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6); - -uint32 runtime·getlasterror(void); -void runtime·setlasterror(uint32 err); - -// Function to be called by windows CreateThread -// to start new os thread. -uint32 runtime·tstart_stdcall(M *newm); - -uint32 runtime·issigpanic(uint32); -void runtime·sigpanic(void); -uint32 runtime·ctrlhandler(uint32 type); - -// Windows dll function to go callback entry. -byte *runtime·compilecallback(Eface fn, bool cleanstack); -void *runtime·callbackasm(void); - -void runtime·install_exception_handler(void); -void runtime·remove_exception_handler(void); - -// TODO(brainman): should not need those -enum { - NSIG = 65, -}; diff --git a/src/runtime/os_windows_386.c b/src/runtime/os_windows_386.c deleted file mode 100644 index 9962f0dc2..000000000 --- a/src/runtime/os_windows_386.c +++ /dev/null @@ -1,128 +0,0 @@ -// 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 "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" - -void -runtime·dumpregs(Context *r) -{ - runtime·printf("eax %x\n", r->Eax); - runtime·printf("ebx %x\n", r->Ebx); - runtime·printf("ecx %x\n", r->Ecx); - runtime·printf("edx %x\n", r->Edx); - runtime·printf("edi %x\n", r->Edi); - runtime·printf("esi %x\n", r->Esi); - runtime·printf("ebp %x\n", r->Ebp); - runtime·printf("esp %x\n", r->Esp); - runtime·printf("eip %x\n", r->Eip); - runtime·printf("eflags %x\n", r->EFlags); - runtime·printf("cs %x\n", r->SegCs); - runtime·printf("fs %x\n", r->SegFs); - runtime·printf("gs %x\n", r->SegGs); -} - -bool -runtime·isgoexception(ExceptionRecord *info, Context *r) -{ - extern byte runtime·text[], runtime·etext[]; - - // Only handle exception if executing instructions in Go binary - // (not Windows library code). - if(r->Eip < (uint32)runtime·text || (uint32)runtime·etext < r->Eip) - return false; - - if(!runtime·issigpanic(info->ExceptionCode)) - return false; - - return true; -} - -// Called by sigtramp from Windows VEH handler. -// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) -// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH). -uint32 -runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp) -{ - uintptr *sp; - - if(!runtime·isgoexception(info, r)) - return EXCEPTION_CONTINUE_SEARCH; - - // Make it look like a call to the signal func. - // Have to pass arguments out of band since - // augmenting the stack frame would break - // the unwinding code. - gp->sig = info->ExceptionCode; - gp->sigcode0 = info->ExceptionInformation[0]; - gp->sigcode1 = info->ExceptionInformation[1]; - gp->sigpc = r->Eip; - - // Only push runtime·sigpanic if r->eip != 0. - // If r->eip == 0, probably panicked because of a - // call to a nil func. Not pushing that onto sp will - // make the trace look like a call to runtime·sigpanic instead. - // (Otherwise the trace will end at runtime·sigpanic and we - // won't get to see who faulted.) - if(r->Eip != 0) { - sp = (uintptr*)r->Esp; - *--sp = r->Eip; - r->Esp = (uintptr)sp; - } - r->Eip = (uintptr)runtime·sigpanic; - return EXCEPTION_CONTINUE_EXECUTION; -} - -// lastcontinuehandler is reached, because runtime cannot handle -// current exception. lastcontinuehandler will print crash info and exit. -uint32 -runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp) -{ - bool crash; - - if(runtime·panicking) // traceback already printed - runtime·exit(2); - runtime·panicking = 1; - - runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode, - (uintptr)info->ExceptionInformation[0], (uintptr)info->ExceptionInformation[1], (uintptr)r->Eip); - - runtime·printf("PC=%x\n", r->Eip); - if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) { - runtime·printf("signal arrived during cgo execution\n"); - gp = g->m->lockedg; - } - runtime·printf("\n"); - - if(runtime·gotraceback(&crash)){ - runtime·tracebacktrap(r->Eip, r->Esp, 0, gp); - runtime·tracebackothers(gp); - runtime·dumpregs(r); - } - - if(crash) - runtime·crash(); - - runtime·exit(2); - return 0; // not reached -} - -void -runtime·sigenable(uint32 sig) -{ - USED(sig); -} - -void -runtime·sigdisable(uint32 sig) -{ - USED(sig); -} - -void -runtime·dosigprof(Context *r, G *gp, M *mp) -{ - runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp, mp); -} diff --git a/src/runtime/os_windows_amd64.c b/src/runtime/os_windows_amd64.c deleted file mode 100644 index e4617e4ce..000000000 --- a/src/runtime/os_windows_amd64.c +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" - -void -runtime·dumpregs(Context *r) -{ - runtime·printf("rax %X\n", r->Rax); - runtime·printf("rbx %X\n", r->Rbx); - runtime·printf("rcx %X\n", r->Rcx); - runtime·printf("rdx %X\n", r->Rdx); - runtime·printf("rdi %X\n", r->Rdi); - runtime·printf("rsi %X\n", r->Rsi); - runtime·printf("rbp %X\n", r->Rbp); - runtime·printf("rsp %X\n", r->Rsp); - runtime·printf("r8 %X\n", r->R8 ); - runtime·printf("r9 %X\n", r->R9 ); - runtime·printf("r10 %X\n", r->R10); - runtime·printf("r11 %X\n", r->R11); - runtime·printf("r12 %X\n", r->R12); - runtime·printf("r13 %X\n", r->R13); - runtime·printf("r14 %X\n", r->R14); - runtime·printf("r15 %X\n", r->R15); - runtime·printf("rip %X\n", r->Rip); - runtime·printf("rflags %X\n", r->EFlags); - runtime·printf("cs %X\n", (uint64)r->SegCs); - runtime·printf("fs %X\n", (uint64)r->SegFs); - runtime·printf("gs %X\n", (uint64)r->SegGs); -} - -bool -runtime·isgoexception(ExceptionRecord *info, Context *r) -{ - extern byte runtime·text[], runtime·etext[]; - - // Only handle exception if executing instructions in Go binary - // (not Windows library code). - if(r->Rip < (uint64)runtime·text || (uint64)runtime·etext < r->Rip) - return false; - - if(!runtime·issigpanic(info->ExceptionCode)) - return false; - - return true; -} - -// Called by sigtramp from Windows VEH handler. -// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) -// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH). -uint32 -runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp) -{ - uintptr *sp; - - if(!runtime·isgoexception(info, r)) - return EXCEPTION_CONTINUE_SEARCH; - - // Make it look like a call to the signal func. - // Have to pass arguments out of band since - // augmenting the stack frame would break - // the unwinding code. - gp->sig = info->ExceptionCode; - gp->sigcode0 = info->ExceptionInformation[0]; - gp->sigcode1 = info->ExceptionInformation[1]; - gp->sigpc = r->Rip; - - // Only push runtime·sigpanic if r->rip != 0. - // If r->rip == 0, probably panicked because of a - // call to a nil func. Not pushing that onto sp will - // make the trace look like a call to runtime·sigpanic instead. - // (Otherwise the trace will end at runtime·sigpanic and we - // won't get to see who faulted.) - if(r->Rip != 0) { - sp = (uintptr*)r->Rsp; - *--sp = r->Rip; - r->Rsp = (uintptr)sp; - } - r->Rip = (uintptr)runtime·sigpanic; - return EXCEPTION_CONTINUE_EXECUTION; -} - -// It seems Windows searches ContinueHandler's list even -// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION. -// firstcontinuehandler will stop that search, -// if exceptionhandler did the same earlier. -uint32 -runtime·firstcontinuehandler(ExceptionRecord *info, Context *r, G *gp) -{ - USED(gp); - if(!runtime·isgoexception(info, r)) - return EXCEPTION_CONTINUE_SEARCH; - return EXCEPTION_CONTINUE_EXECUTION; -} - -// lastcontinuehandler is reached, because runtime cannot handle -// current exception. lastcontinuehandler will print crash info and exit. -uint32 -runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp) -{ - bool crash; - - if(runtime·panicking) // traceback already printed - runtime·exit(2); - runtime·panicking = 1; - - runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode, - info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip); - - - runtime·printf("PC=%X\n", r->Rip); - if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) { - runtime·printf("signal arrived during cgo execution\n"); - gp = g->m->lockedg; - } - runtime·printf("\n"); - - if(runtime·gotraceback(&crash)){ - runtime·tracebacktrap(r->Rip, r->Rsp, 0, gp); - runtime·tracebackothers(gp); - runtime·dumpregs(r); - } - - if(crash) - runtime·crash(); - - runtime·exit(2); - return 0; // not reached -} - -void -runtime·sigenable(uint32 sig) -{ - USED(sig); -} - -void -runtime·sigdisable(uint32 sig) -{ - USED(sig); -} - -void -runtime·dosigprof(Context *r, G *gp, M *mp) -{ - runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp, mp); -} diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 892946702..95e780b1d 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -162,7 +162,7 @@ func init() { // Allocate a Defer, usually using per-P pool. // Each defer must be released with freedefer. -// Note: runs on M stack +// Note: runs on g0 stack func newdefer(siz int32) *_defer { var d *_defer sc := deferclass(uintptr(siz)) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 12e2e71e9..64f6a3520 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -63,11 +63,13 @@ func main() { if _cgo_free == nil { gothrow("_cgo_free missing") } - if _cgo_setenv == nil { - gothrow("_cgo_setenv missing") - } - if _cgo_unsetenv == nil { - gothrow("_cgo_unsetenv missing") + if GOOS != "windows" { + if _cgo_setenv == nil { + gothrow("_cgo_setenv missing") + } + if _cgo_unsetenv == nil { + gothrow("_cgo_unsetenv missing") + } } } @@ -165,6 +167,7 @@ func acquireSudog() *sudog { gothrow("acquireSudog: found s.elem != nil in cache") } c.sudogcache = s.next + s.next = nil return s } @@ -193,6 +196,15 @@ func releaseSudog(s *sudog) { if s.selectdone != nil { gothrow("runtime: sudog with non-nil selectdone") } + if s.next != nil { + gothrow("runtime: sudog with non-nil next") + } + if s.prev != nil { + gothrow("runtime: sudog with non-nil prev") + } + if s.waitlink != nil { + gothrow("runtime: sudog with non-nil waitlink") + } gp := getg() if gp.param != nil { gothrow("runtime: releaseSudog with non-nil gp.param") diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go new file mode 100644 index 000000000..84f0acece --- /dev/null +++ b/src/runtime/race/race_unix_test.go @@ -0,0 +1,30 @@ +// Copyright 2014 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 race +// +build darwin freebsd linux + +package race_test + +import ( + "sync/atomic" + "syscall" + "testing" + "unsafe" +) + +// Test that race detector does not crash when accessing non-Go allocated memory (issue 9136). +func TestNonGoMemory(t *testing.T) { + data, err := syscall.Mmap(-1, 0, 4096, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) + if err != nil { + t.Fatalf("failed to mmap memory: %v", err) + } + p := (*uint32)(unsafe.Pointer(&data[0])) + atomic.AddUint32(p, 1) + (*p)++ + if *p != 2 { + t.Fatalf("data[0] = %v, expect 2", *p) + } + syscall.Munmap(data) +} diff --git a/src/runtime/race1.go b/src/runtime/race1.go index 4c580429c..2ec2bee65 100644 --- a/src/runtime/race1.go +++ b/src/runtime/race1.go @@ -81,6 +81,10 @@ var __tsan_go_ignore_sync_end byte //go:cgo_import_static __tsan_go_atomic32_compare_exchange //go:cgo_import_static __tsan_go_atomic64_compare_exchange +// start/end of global data (data+bss). +var racedatastart uintptr +var racedataend uintptr + // start/end of heap for race_amd64.s var racearenastart uintptr var racearenaend uintptr @@ -99,7 +103,7 @@ func racecall(*byte, uintptr, uintptr, uintptr, uintptr) //go:nosplit func isvalidaddr(addr unsafe.Pointer) bool { return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend || - uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(addr) && uintptr(addr) < uintptr(unsafe.Pointer(&enoptrbss)) + racedatastart <= uintptr(addr) && uintptr(addr) < racedataend } //go:nosplit @@ -113,9 +117,36 @@ func raceinit() uintptr { racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0) // Round data segment to page boundaries, because it's used in mmap(). - start := uintptr(unsafe.Pointer(&noptrdata)) &^ (_PageSize - 1) - size := round(uintptr(unsafe.Pointer(&enoptrbss))-start, _PageSize) + start := ^uintptr(0) + end := uintptr(0) + if start > uintptr(unsafe.Pointer(&noptrdata)) { + start = uintptr(unsafe.Pointer(&noptrdata)) + } + if start > uintptr(unsafe.Pointer(&data)) { + start = uintptr(unsafe.Pointer(&data)) + } + if start > uintptr(unsafe.Pointer(&noptrbss)) { + start = uintptr(unsafe.Pointer(&noptrbss)) + } + if start > uintptr(unsafe.Pointer(&bss)) { + start = uintptr(unsafe.Pointer(&bss)) + } + if end < uintptr(unsafe.Pointer(&enoptrdata)) { + end = uintptr(unsafe.Pointer(&enoptrdata)) + } + if end < uintptr(unsafe.Pointer(&edata)) { + end = uintptr(unsafe.Pointer(&edata)) + } + if end < uintptr(unsafe.Pointer(&enoptrbss)) { + end = uintptr(unsafe.Pointer(&enoptrbss)) + } + if end < uintptr(unsafe.Pointer(&ebss)) { + end = uintptr(unsafe.Pointer(&ebss)) + } + size := round(end-start, _PageSize) racecall(&__tsan_map_shadow, start, size, 0, 0) + racedatastart = start + racedataend = start + size return racectx } diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index a7f44870a..d54d9798f 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -139,17 +139,15 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0 get_tls(R12) MOVQ g(R12), R14 MOVQ g_racectx(R14), RARG0 // goroutine context - // Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss). + // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend). CMPQ RARG1, runtime·racearenastart(SB) JB data CMPQ RARG1, runtime·racearenaend(SB) JB call data: - MOVQ $runtime·noptrdata(SB), R13 - CMPQ RARG1, R13 + CMPQ RARG1, runtime·racedatastart(SB) JB ret - MOVQ $runtime·enoptrbss(SB), R13 - CMPQ RARG1, R13 + CMPQ RARG1, runtime·racedataend(SB) JAE ret call: MOVQ AX, AX // w/o this 6a miscompiles this function @@ -167,6 +165,7 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8 MOVQ callpc+0(FP), RARG1 // void __tsan_func_enter(ThreadState *thr, void *pc); MOVQ $__tsan_func_enter(SB), AX + // racecall<> preserves R15 CALL racecall<>(SB) MOVQ R15, DX // restore function entry context RET @@ -307,13 +306,45 @@ TEXT sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0 TEXT racecallatomic<>(SB), NOSPLIT, $0-0 // Trigger SIGSEGV early. MOVQ 16(SP), R12 - MOVL (R12), R12 + MOVL (R12), R13 + // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend). + CMPQ R12, runtime·racearenastart(SB) + JB racecallatomic_data + CMPQ R12, runtime·racearenaend(SB) + JB racecallatomic_ok +racecallatomic_data: + CMPQ R12, runtime·racedatastart(SB) + JB racecallatomic_ignore + CMPQ R12, runtime·racedataend(SB) + JAE racecallatomic_ignore +racecallatomic_ok: + // Addr is within the good range, call the atomic function. get_tls(R12) MOVQ g(R12), R14 MOVQ g_racectx(R14), RARG0 // goroutine context MOVQ 8(SP), RARG1 // caller pc MOVQ (SP), RARG2 // pc LEAQ 16(SP), RARG3 // arguments + JMP racecall<>(SB) // does not return +racecallatomic_ignore: + // Addr is outside the good range. + // Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op. + // An attempt to synchronize on the address would cause crash. + MOVQ AX, R15 // remember the original function + MOVQ $__tsan_go_ignore_sync_begin(SB), AX + MOVQ g(R12), R14 + MOVQ g_racectx(R14), RARG0 // goroutine context + CALL racecall<>(SB) + MOVQ R15, AX // restore the original function + // Call the atomic function. + MOVQ g_racectx(R14), RARG0 // goroutine context + MOVQ 8(SP), RARG1 // caller pc + MOVQ (SP), RARG2 // pc + LEAQ 16(SP), RARG3 // arguments + CALL racecall<>(SB) + // Call __tsan_go_ignore_sync_end. + MOVQ $__tsan_go_ignore_sync_end(SB), AX + MOVQ g_racectx(R14), RARG0 // goroutine context JMP racecall<>(SB) // void runtime·racecall(void(*f)(...), ...) diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 7625a2dd8..d18178d09 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -45,7 +45,13 @@ const ( _Pdead ) -// XXX inserting below here +// The next line makes 'go generate' write the zgen_*.go files with +// per-OS and per-arch information, including constants +// named goos_$GOOS and goarch_$GOARCH for every +// known GOOS and GOARCH. The constant is 1 on the +// current system, 0 otherwise; multiplying by them is +// useful for defining GOOS- or GOARCH-specific constants. +//go:generate go run gengoos.go type mutex struct { // Futex-based impl treats it as uint32 key, @@ -397,14 +403,6 @@ type itab struct { fun [0]uintptr } -const ( - // TODO: Generate in cmd/dist. - _NaCl = 0 - _Windows = 0 - _Solaris = 0 - _Plan9 = 0 -) - // Lock-free stack node. // // Also known to export_test.go. type lfnode struct { diff --git a/src/runtime/select.go b/src/runtime/select.go index e918b734a..5e5047bc1 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -399,6 +399,7 @@ loop: } } sgnext = sglist.waitlink + sglist.waitlink = nil releaseSudog(sglist) sglist = sgnext } @@ -636,6 +637,7 @@ func (q *waitq) dequeueSudoG(s *sudog) { if q.last == sgp { q.last = prevsgp } + s.next = nil return } l = &sgp.next diff --git a/src/runtime/sema.go b/src/runtime/sema.go index d2a028c01..26dbd30ea 100644 --- a/src/runtime/sema.go +++ b/src/runtime/sema.go @@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) { } unlock(&s.lock) if wake != nil { + wake.next = nil goready(wake.g) } } else { @@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) { if wake.releasetime != 0 { wake.releasetime = cputicks() } + wake.next = nil goready(wake.g) n-- } diff --git a/src/runtime/signal_android_386.h b/src/runtime/signal_android_386.h deleted file mode 100644 index 2a1bb4b3e..000000000 --- a/src/runtime/signal_android_386.h +++ /dev/null @@ -1 +0,0 @@ -#include "signal_linux_386.h" diff --git a/src/runtime/signal_android_arm.h b/src/runtime/signal_android_arm.h deleted file mode 100644 index 8a05e21e5..000000000 --- a/src/runtime/signal_android_arm.h +++ /dev/null @@ -1 +0,0 @@ -#include "signal_linux_arm.h" diff --git a/src/runtime/signal_linux_386.go b/src/runtime/signal_linux_386.go index 41eae80ea..085f66e89 100644 --- a/src/runtime/signal_linux_386.go +++ b/src/runtime/signal_linux_386.go @@ -26,7 +26,7 @@ func (c *sigctxt) cs() uint32 { return uint32(c.regs().cs) } func (c *sigctxt) fs() uint32 { return uint32(c.regs().fs) } func (c *sigctxt) gs() uint32 { return uint32(c.regs().gs) } func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) } -func (c *sigctxt) sigaddr() uint32 { return uint32(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) } +func (c *sigctxt) sigaddr() uint32 { return c.info.si_addr } func (c *sigctxt) set_eip(x uint32) { c.regs().eip = x } func (c *sigctxt) set_esp(x uint32) { c.regs().esp = x } diff --git a/src/runtime/signal_linux_amd64.go b/src/runtime/signal_linux_amd64.go index d94b19102..5e339b8a4 100644 --- a/src/runtime/signal_linux_amd64.go +++ b/src/runtime/signal_linux_amd64.go @@ -36,7 +36,7 @@ func (c *sigctxt) cs() uint64 { return uint64(c.regs().cs) } func (c *sigctxt) fs() uint64 { return uint64(c.regs().fs) } func (c *sigctxt) gs() uint64 { return uint64(c.regs().gs) } func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) } -func (c *sigctxt) sigaddr() uint64 { return uint64(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) } +func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr } func (c *sigctxt) set_rip(x uint64) { c.regs().rip = x } func (c *sigctxt) set_rsp(x uint64) { c.regs().rsp = x } diff --git a/src/runtime/signal_linux_arm.go b/src/runtime/signal_linux_arm.go index 4a5670e74..bdb4314fa 100644 --- a/src/runtime/signal_linux_arm.go +++ b/src/runtime/signal_linux_arm.go @@ -35,7 +35,7 @@ func (c *sigctxt) error() uint32 { return c.regs().error_code } func (c *sigctxt) oldmask() uint32 { return c.regs().oldmask } func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) } -func (c *sigctxt) sigaddr() uint32 { return uint32(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) } +func (c *sigctxt) sigaddr() uint32 { return c.info.si_addr } func (c *sigctxt) set_pc(x uint32) { c.regs().pc = x } func (c *sigctxt) set_sp(x uint32) { c.regs().sp = x } diff --git a/src/runtime/signal_linux_power64.h b/src/runtime/signal_linux_power64.h deleted file mode 100644 index 840648920..000000000 --- a/src/runtime/signal_linux_power64.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2014 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. - -#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs) - -#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0]) -#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1]) -#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2]) -#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3]) -#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4]) -#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5]) -#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6]) -#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7]) -#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8]) -#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9]) -#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10]) -#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11]) -#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12]) -#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13]) -#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14]) -#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15]) -#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16]) -#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17]) -#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18]) -#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19]) -#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20]) -#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21]) -#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22]) -#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23]) -#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24]) -#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25]) -#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26]) -#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27]) -#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28]) -#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29]) -#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30]) -#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31]) - -#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1]) -#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip) -#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap) -#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr) -#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link) -#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer) -#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr) - -#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code) -#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar) diff --git a/src/runtime/signal_linux_power64le.h b/src/runtime/signal_linux_power64le.h deleted file mode 100644 index 840648920..000000000 --- a/src/runtime/signal_linux_power64le.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2014 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. - -#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs) - -#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0]) -#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1]) -#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2]) -#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3]) -#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4]) -#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5]) -#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6]) -#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7]) -#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8]) -#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9]) -#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10]) -#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11]) -#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12]) -#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13]) -#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14]) -#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15]) -#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16]) -#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17]) -#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18]) -#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19]) -#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20]) -#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21]) -#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22]) -#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23]) -#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24]) -#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25]) -#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26]) -#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27]) -#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28]) -#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29]) -#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30]) -#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31]) - -#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1]) -#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip) -#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap) -#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr) -#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link) -#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer) -#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr) - -#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code) -#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar) diff --git a/src/runtime/signal_linux_power64x.go b/src/runtime/signal_linux_power64x.go new file mode 100644 index 000000000..0a406b31f --- /dev/null +++ b/src/runtime/signal_linux_power64x.go @@ -0,0 +1,71 @@ +// Copyright 2014 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 linux +// +build power64 power64le + +package runtime + +import "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *ptregs { return (*ucontext)(c.ctxt).uc_mcontext.regs } +func (c *sigctxt) r0() uint64 { return c.regs().gpr[0] } +func (c *sigctxt) r1() uint64 { return c.regs().gpr[1] } +func (c *sigctxt) r2() uint64 { return c.regs().gpr[2] } +func (c *sigctxt) r3() uint64 { return c.regs().gpr[3] } +func (c *sigctxt) r4() uint64 { return c.regs().gpr[4] } +func (c *sigctxt) r5() uint64 { return c.regs().gpr[5] } +func (c *sigctxt) r6() uint64 { return c.regs().gpr[6] } +func (c *sigctxt) r7() uint64 { return c.regs().gpr[7] } +func (c *sigctxt) r8() uint64 { return c.regs().gpr[8] } +func (c *sigctxt) r9() uint64 { return c.regs().gpr[9] } +func (c *sigctxt) r10() uint64 { return c.regs().gpr[10] } +func (c *sigctxt) r11() uint64 { return c.regs().gpr[11] } +func (c *sigctxt) r12() uint64 { return c.regs().gpr[12] } +func (c *sigctxt) r13() uint64 { return c.regs().gpr[13] } +func (c *sigctxt) r14() uint64 { return c.regs().gpr[14] } +func (c *sigctxt) r15() uint64 { return c.regs().gpr[15] } +func (c *sigctxt) r16() uint64 { return c.regs().gpr[16] } +func (c *sigctxt) r17() uint64 { return c.regs().gpr[17] } +func (c *sigctxt) r18() uint64 { return c.regs().gpr[18] } +func (c *sigctxt) r19() uint64 { return c.regs().gpr[19] } +func (c *sigctxt) r20() uint64 { return c.regs().gpr[20] } +func (c *sigctxt) r21() uint64 { return c.regs().gpr[21] } +func (c *sigctxt) r22() uint64 { return c.regs().gpr[22] } +func (c *sigctxt) r23() uint64 { return c.regs().gpr[23] } +func (c *sigctxt) r24() uint64 { return c.regs().gpr[24] } +func (c *sigctxt) r25() uint64 { return c.regs().gpr[25] } +func (c *sigctxt) r26() uint64 { return c.regs().gpr[26] } +func (c *sigctxt) r27() uint64 { return c.regs().gpr[27] } +func (c *sigctxt) r28() uint64 { return c.regs().gpr[28] } +func (c *sigctxt) r29() uint64 { return c.regs().gpr[29] } +func (c *sigctxt) r30() uint64 { return c.regs().gpr[30] } +func (c *sigctxt) r31() uint64 { return c.regs().gpr[31] } +func (c *sigctxt) sp() uint64 { return c.regs().gpr[1] } +func (c *sigctxt) pc() uint64 { return c.regs().nip } +func (c *sigctxt) trap() uint64 { return c.regs().trap } +func (c *sigctxt) ctr() uint64 { return c.regs().ctr } +func (c *sigctxt) link() uint64 { return c.regs().link } +func (c *sigctxt) xer() uint64 { return c.regs().xer } +func (c *sigctxt) ccr() uint64 { return c.regs().ccr } + +func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) } +func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr } +func (c *sigctxt) fault() uint64 { return c.regs().dar } + +func (c *sigctxt) set_r0(x uint64) { c.regs().gpr[0] = x } +func (c *sigctxt) set_r30(x uint64) { c.regs().gpr[30] = x } +func (c *sigctxt) set_pc(x uint64) { c.regs().nip = x } +func (c *sigctxt) set_sp(x uint64) { c.regs().gpr[1] = x } +func (c *sigctxt) set_link(x uint64) { c.regs().link = x } + +func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } +func (c *sigctxt) set_sigaddr(x uint64) { + *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x) +} diff --git a/src/runtime/signal_nacl.go b/src/runtime/signal_nacl.go new file mode 100644 index 000000000..122648bc3 --- /dev/null +++ b/src/runtime/signal_nacl.go @@ -0,0 +1,45 @@ +// 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. + +package runtime + +type sigTabT struct { + flags int32 + name string +} + +var sigtable = [...]sigTabT{ + /* 0 */ {0, "SIGNONE: no trap"}, + /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"}, + /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"}, + /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"}, + /* 4 */ {_SigThrow, "SIGILL: illegal instruction"}, + /* 5 */ {_SigThrow, "SIGTRAP: trace trap"}, + /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"}, + /* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"}, + /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"}, + /* 9 */ {0, "SIGKILL: kill"}, + /* 10 */ {_SigPanic, "SIGBUS: bus error"}, + /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"}, + /* 12 */ {_SigThrow, "SIGSYS: bad system call"}, + /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"}, + /* 14 */ {_SigNotify, "SIGALRM: alarm clock"}, + /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"}, + /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"}, + /* 17 */ {0, "SIGSTOP: stop"}, + /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"}, + /* 19 */ {0, "SIGCONT: continue after stop"}, + /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"}, + /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"}, + /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"}, + /* 23 */ {_SigNotify, "SIGIO: i/o now possible"}, + /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"}, + /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"}, + /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"}, + /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"}, + /* 28 */ {_SigNotify, "SIGWINCH: window size change"}, + /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"}, + /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"}, + /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"}, +} diff --git a/src/runtime/signal_nacl_386.go b/src/runtime/signal_nacl_386.go new file mode 100644 index 000000000..0a1e7c6ea --- /dev/null +++ b/src/runtime/signal_nacl_386.go @@ -0,0 +1,34 @@ +// Copyright 2013 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 "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *excregs386 { return &(*exccontext)(c.ctxt).regs } +func (c *sigctxt) eax() uint32 { return c.regs().eax } +func (c *sigctxt) ebx() uint32 { return c.regs().ebx } +func (c *sigctxt) ecx() uint32 { return c.regs().ecx } +func (c *sigctxt) edx() uint32 { return c.regs().edx } +func (c *sigctxt) edi() uint32 { return c.regs().edi } +func (c *sigctxt) esi() uint32 { return c.regs().esi } +func (c *sigctxt) ebp() uint32 { return c.regs().ebp } +func (c *sigctxt) esp() uint32 { return c.regs().esp } +func (c *sigctxt) eip() uint32 { return c.regs().eip } +func (c *sigctxt) eflags() uint32 { return c.regs().eflags } +func (c *sigctxt) cs() uint32 { return ^uint32(0) } +func (c *sigctxt) fs() uint32 { return ^uint32(0) } +func (c *sigctxt) gs() uint32 { return ^uint32(0) } +func (c *sigctxt) sigcode() uint32 { return ^uint32(0) } +func (c *sigctxt) sigaddr() uint32 { return 0 } + +func (c *sigctxt) set_eip(x uint32) { c.regs().eip = x } +func (c *sigctxt) set_esp(x uint32) { c.regs().esp = x } +func (c *sigctxt) set_sigcode(x uint32) {} +func (c *sigctxt) set_sigaddr(x uint32) {} diff --git a/src/runtime/signal_nacl_386.h b/src/runtime/signal_nacl_386.h deleted file mode 100644 index c9481b5f4..000000000 --- a/src/runtime/signal_nacl_386.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 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. - -#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs) - -#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax) -#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx) -#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx) -#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx) -#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi) -#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi) -#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp) -#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp) -#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip) -#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags) - -#define SIG_CS(info, ctxt) (~0) -#define SIG_FS(info, ctxt) (~0) -#define SIG_GS(info, ctxt) (~0) - -#define SIG_CODE0(info, ctxt) (~0) -#define SIG_CODE1(info, ctxt) (0) diff --git a/src/runtime/signal_nacl_amd64p32.go b/src/runtime/signal_nacl_amd64p32.go new file mode 100644 index 000000000..024cebadd --- /dev/null +++ b/src/runtime/signal_nacl_amd64p32.go @@ -0,0 +1,44 @@ +// Copyright 2014 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 "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *excregsamd64 { + return &(*exccontext)(c.ctxt).regs +} +func (c *sigctxt) rax() uint64 { return c.regs().rax } +func (c *sigctxt) rbx() uint64 { return c.regs().rbx } +func (c *sigctxt) rcx() uint64 { return c.regs().rcx } +func (c *sigctxt) rdx() uint64 { return c.regs().rdx } +func (c *sigctxt) rdi() uint64 { return c.regs().rdi } +func (c *sigctxt) rsi() uint64 { return c.regs().rsi } +func (c *sigctxt) rbp() uint64 { return c.regs().rbp } +func (c *sigctxt) rsp() uint64 { return c.regs().rsp } +func (c *sigctxt) r8() uint64 { return c.regs().r8 } +func (c *sigctxt) r9() uint64 { return c.regs().r9 } +func (c *sigctxt) r10() uint64 { return c.regs().r10 } +func (c *sigctxt) r11() uint64 { return c.regs().r11 } +func (c *sigctxt) r12() uint64 { return c.regs().r12 } +func (c *sigctxt) r13() uint64 { return c.regs().r13 } +func (c *sigctxt) r14() uint64 { return c.regs().r14 } +func (c *sigctxt) r15() uint64 { return c.regs().r15 } +func (c *sigctxt) rip() uint64 { return c.regs().rip } +func (c *sigctxt) rflags() uint64 { return uint64(c.regs().rflags) } +func (c *sigctxt) cs() uint64 { return ^uint64(0) } +func (c *sigctxt) fs() uint64 { return ^uint64(0) } +func (c *sigctxt) gs() uint64 { return ^uint64(0) } +func (c *sigctxt) sigcode() uint64 { return ^uint64(0) } +func (c *sigctxt) sigaddr() uint64 { return 0 } + +func (c *sigctxt) set_rip(x uint64) { c.regs().rip = x } +func (c *sigctxt) set_rsp(x uint64) { c.regs().rsp = x } +func (c *sigctxt) set_sigcode(x uint64) {} +func (c *sigctxt) set_sigaddr(x uint64) {} diff --git a/src/runtime/signal_nacl_amd64p32.h b/src/runtime/signal_nacl_amd64p32.h deleted file mode 100644 index f62305cb5..000000000 --- a/src/runtime/signal_nacl_amd64p32.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 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. - -#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs.regs64) - -#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax) -#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx) -#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx) -#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx) -#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi) -#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi) -#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp) -#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp) -#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8) -#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9) -#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10) -#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11) -#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12) -#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13) -#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14) -#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15) -#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip) -#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).rflags) - -#define SIG_CS(info, ctxt) (~0) -#define SIG_FS(info, ctxt) (~0) -#define SIG_GS(info, ctxt) (~0) - -#define SIG_CODE0(info, ctxt) (~0) -#define SIG_CODE1(info, ctxt) (0) diff --git a/src/runtime/signal_nacl_arm.go b/src/runtime/signal_nacl_arm.go new file mode 100644 index 000000000..1aeaa4e42 --- /dev/null +++ b/src/runtime/signal_nacl_arm.go @@ -0,0 +1,47 @@ +// Copyright 2014 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 "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *excregsarm { return &(*exccontext)(c.ctxt).regs } + +func (c *sigctxt) r0() uint32 { return c.regs().r0 } +func (c *sigctxt) r1() uint32 { return c.regs().r1 } +func (c *sigctxt) r2() uint32 { return c.regs().r2 } +func (c *sigctxt) r3() uint32 { return c.regs().r3 } +func (c *sigctxt) r4() uint32 { return c.regs().r4 } +func (c *sigctxt) r5() uint32 { return c.regs().r5 } +func (c *sigctxt) r6() uint32 { return c.regs().r6 } +func (c *sigctxt) r7() uint32 { return c.regs().r7 } +func (c *sigctxt) r8() uint32 { return c.regs().r8 } +func (c *sigctxt) r9() uint32 { return c.regs().r9 } +func (c *sigctxt) r10() uint32 { return c.regs().r10 } +func (c *sigctxt) fp() uint32 { return c.regs().r11 } +func (c *sigctxt) ip() uint32 { return c.regs().r12 } +func (c *sigctxt) sp() uint32 { return c.regs().sp } +func (c *sigctxt) lr() uint32 { return c.regs().lr } +func (c *sigctxt) pc() uint32 { return c.regs().pc } +func (c *sigctxt) cpsr() uint32 { return c.regs().cpsr } +func (c *sigctxt) fault() uint32 { return ^uint32(0) } +func (c *sigctxt) trap() uint32 { return ^uint32(0) } +func (c *sigctxt) error() uint32 { return ^uint32(0) } +func (c *sigctxt) oldmask() uint32 { return ^uint32(0) } + +func (c *sigctxt) sigcode() uint32 { return 0 } +func (c *sigctxt) sigaddr() uint32 { return 0 } + +func (c *sigctxt) set_pc(x uint32) { c.regs().pc = x } +func (c *sigctxt) set_sp(x uint32) { c.regs().sp = x } +func (c *sigctxt) set_lr(x uint32) { c.regs().lr = x } +func (c *sigctxt) set_r10(x uint32) { c.regs().r10 = x } + +func (c *sigctxt) set_sigcode(x uint32) {} +func (c *sigctxt) set_sigaddr(x uint32) {} diff --git a/src/runtime/signal_nacl_arm.h b/src/runtime/signal_nacl_arm.h deleted file mode 100644 index e5bbb211d..000000000 --- a/src/runtime/signal_nacl_arm.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 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. - -#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs) - -#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).r0) -#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).r1) -#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).r2) -#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).r3) -#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).r4) -#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).r5) -#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).r6) -#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).r7) -#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8) -#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9) -#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10) -#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).r11) -#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).r12) -#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).sp) -#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).lr) -#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).pc) -#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).cpsr) -#define SIG_FAULT(info, ctxt) (~0) -#define SIG_TRAP(info, ctxt) (~0) -#define SIG_ERROR(info, ctxt) (~0) -#define SIG_OLDMASK(info, ctxt) (~0) -#define SIG_CODE0(info, ctxt) (~0) diff --git a/src/runtime/signal_netbsd.go b/src/runtime/signal_netbsd.go new file mode 100644 index 000000000..78afc59ef --- /dev/null +++ b/src/runtime/signal_netbsd.go @@ -0,0 +1,46 @@ +// 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. + +package runtime + +type sigTabT struct { + flags int32 + name string +} + +var sigtable = [...]sigTabT{ + /* 0 */ {0, "SIGNONE: no trap"}, + /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"}, + /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"}, + /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"}, + /* 4 */ {_SigThrow, "SIGILL: illegal instruction"}, + /* 5 */ {_SigThrow, "SIGTRAP: trace trap"}, + /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"}, + /* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"}, + /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"}, + /* 9 */ {0, "SIGKILL: kill"}, + /* 10 */ {_SigPanic, "SIGBUS: bus error"}, + /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"}, + /* 12 */ {_SigThrow, "SIGSYS: bad system call"}, + /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"}, + /* 14 */ {_SigNotify, "SIGALRM: alarm clock"}, + /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"}, + /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"}, + /* 17 */ {0, "SIGSTOP: stop"}, + /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"}, + /* 19 */ {0, "SIGCONT: continue after stop"}, + /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"}, + /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"}, + /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"}, + /* 23 */ {_SigNotify, "SIGIO: i/o now possible"}, + /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"}, + /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"}, + /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"}, + /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"}, + /* 28 */ {_SigNotify, "SIGWINCH: window size change"}, + /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"}, + /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"}, + /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"}, + /* 32 */ {_SigNotify, "SIGTHR: reserved"}, +} diff --git a/src/runtime/signal_netbsd_386.go b/src/runtime/signal_netbsd_386.go new file mode 100644 index 000000000..6702336ab --- /dev/null +++ b/src/runtime/signal_netbsd_386.go @@ -0,0 +1,38 @@ +// Copyright 2013 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 "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *mcontextt { return &(*ucontextt)(c.ctxt).uc_mcontext } +func (c *sigctxt) eax() uint32 { return c.regs().__gregs[_REG_EAX] } +func (c *sigctxt) ebx() uint32 { return c.regs().__gregs[_REG_EBX] } +func (c *sigctxt) ecx() uint32 { return c.regs().__gregs[_REG_ECX] } +func (c *sigctxt) edx() uint32 { return c.regs().__gregs[_REG_EDX] } +func (c *sigctxt) edi() uint32 { return c.regs().__gregs[_REG_EDI] } +func (c *sigctxt) esi() uint32 { return c.regs().__gregs[_REG_ESI] } +func (c *sigctxt) ebp() uint32 { return c.regs().__gregs[_REG_EBP] } +func (c *sigctxt) esp() uint32 { return c.regs().__gregs[_REG_UESP] } +func (c *sigctxt) eip() uint32 { return c.regs().__gregs[_REG_EIP] } +func (c *sigctxt) eflags() uint32 { return c.regs().__gregs[_REG_EFL] } +func (c *sigctxt) cs() uint32 { return uint32(c.regs().__gregs[_REG_CS]) } +func (c *sigctxt) fs() uint32 { return uint32(c.regs().__gregs[_REG_FS]) } +func (c *sigctxt) gs() uint32 { return uint32(c.regs().__gregs[_REG_GS]) } +func (c *sigctxt) sigcode() uint32 { return uint32(c.info._code) } +func (c *sigctxt) sigaddr() uint32 { + return uint32(*(*uint32)(unsafe.Pointer(&c.info._reason[0]))) +} + +func (c *sigctxt) set_eip(x uint32) { c.regs().__gregs[_REG_EIP] = x } +func (c *sigctxt) set_esp(x uint32) { c.regs().__gregs[_REG_UESP] = x } +func (c *sigctxt) set_sigcode(x uint32) { c.info._code = int32(x) } +func (c *sigctxt) set_sigaddr(x uint32) { + *(*uint32)(unsafe.Pointer(&c.info._reason[0])) = x +} diff --git a/src/runtime/signal_netbsd_386.h b/src/runtime/signal_netbsd_386.h deleted file mode 100644 index d5a8a0c4b..000000000 --- a/src/runtime/signal_netbsd_386.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 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. - -#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext) - -#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EAX]) -#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBX]) -#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ECX]) -#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDX]) -#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDI]) -#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ESI]) -#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBP]) -#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_UESP]) -#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EIP]) -#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EFL]) - -#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS]) -#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS]) -#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS]) - -#define SIG_CODE0(info, ctxt) ((info)->_code) -#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0]) diff --git a/src/runtime/signal_netbsd_amd64.go b/src/runtime/signal_netbsd_amd64.go new file mode 100644 index 000000000..e22f4a724 --- /dev/null +++ b/src/runtime/signal_netbsd_amd64.go @@ -0,0 +1,48 @@ +// Copyright 2013 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 "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *mcontextt { + return (*mcontextt)(unsafe.Pointer(&(*ucontextt)(c.ctxt).uc_mcontext)) +} +func (c *sigctxt) rax() uint64 { return c.regs().__gregs[_REG_RAX] } +func (c *sigctxt) rbx() uint64 { return c.regs().__gregs[_REG_RBX] } +func (c *sigctxt) rcx() uint64 { return c.regs().__gregs[_REG_RCX] } +func (c *sigctxt) rdx() uint64 { return c.regs().__gregs[_REG_RDX] } +func (c *sigctxt) rdi() uint64 { return c.regs().__gregs[_REG_RDI] } +func (c *sigctxt) rsi() uint64 { return c.regs().__gregs[_REG_RSI] } +func (c *sigctxt) rbp() uint64 { return c.regs().__gregs[_REG_RBP] } +func (c *sigctxt) rsp() uint64 { return c.regs().__gregs[_REG_RSP] } +func (c *sigctxt) r8() uint64 { return c.regs().__gregs[_REG_R8] } +func (c *sigctxt) r9() uint64 { return c.regs().__gregs[_REG_R8] } +func (c *sigctxt) r10() uint64 { return c.regs().__gregs[_REG_R10] } +func (c *sigctxt) r11() uint64 { return c.regs().__gregs[_REG_R11] } +func (c *sigctxt) r12() uint64 { return c.regs().__gregs[_REG_R12] } +func (c *sigctxt) r13() uint64 { return c.regs().__gregs[_REG_R13] } +func (c *sigctxt) r14() uint64 { return c.regs().__gregs[_REG_R14] } +func (c *sigctxt) r15() uint64 { return c.regs().__gregs[_REG_R15] } +func (c *sigctxt) rip() uint64 { return c.regs().__gregs[_REG_RIP] } +func (c *sigctxt) rflags() uint64 { return c.regs().__gregs[_REG_RFLAGS] } +func (c *sigctxt) cs() uint64 { return c.regs().__gregs[_REG_CS] } +func (c *sigctxt) fs() uint64 { return c.regs().__gregs[_REG_FS] } +func (c *sigctxt) gs() uint64 { return c.regs().__gregs[_REG_GS] } +func (c *sigctxt) sigcode() uint64 { return uint64(c.info._code) } +func (c *sigctxt) sigaddr() uint64 { + return uint64(*(*uint64)(unsafe.Pointer(&c.info._reason[0]))) +} + +func (c *sigctxt) set_rip(x uint64) { c.regs().__gregs[_REG_RIP] = x } +func (c *sigctxt) set_rsp(x uint64) { c.regs().__gregs[_REG_RSP] = x } +func (c *sigctxt) set_sigcode(x uint64) { c.info._code = int32(x) } +func (c *sigctxt) set_sigaddr(x uint64) { + *(*uint64)(unsafe.Pointer(&c.info._reason[0])) = x +} diff --git a/src/runtime/signal_netbsd_amd64.h b/src/runtime/signal_netbsd_amd64.h deleted file mode 100644 index 7ec4cd98c..000000000 --- a/src/runtime/signal_netbsd_amd64.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 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. - -#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext) - -#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RAX]) -#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBX]) -#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RCX]) -#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDX]) -#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDI]) -#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSI]) -#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBP]) -#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSP]) -#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R8]) -#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R9]) -#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R10]) -#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R11]) -#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R12]) -#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R13]) -#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R14]) -#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R15]) -#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RIP]) -#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RFLAGS]) - -#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS]) -#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS]) -#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS]) - -#define SIG_CODE0(info, ctxt) ((info)->_code) -#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0]) diff --git a/src/runtime/signals_plan9.h b/src/runtime/signal_plan9.go index 4ee8e542c..37d24359b 100644 --- a/src/runtime/signals_plan9.h +++ b/src/runtime/signal_plan9.go @@ -2,62 +2,53 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include "textflag.h" +package runtime -#define N SigNotify -#define K SigKill -#define T SigThrow -#define P SigPanic -#define E SigGoExit +type sigTabT struct { + flags int + name []byte +} // Incoming notes are compared against this table using strncmp, so the // order matters: longer patterns must appear before their prefixes. -// There are #defined SIG constants in os_plan9.h for the table index of -// some of these. +// There are _SIG constants in os2_plan9.go for the table index of some +// of these. // // If you add entries to this table, you must respect the prefix ordering -// and also update the constant values is os_plan9.h. - -#pragma dataflag NOPTR -SigTab runtime·sigtab[] = { +// and also update the constant values is os2_plan9.go. +var sigtable = [...]sigTabT{ // Traps that we cannot be recovered. - T, "sys: trap: debug exception", - T, "sys: trap: invalid opcode", + {_SigThrow, []byte("sys: trap: debug exception")}, + {_SigThrow, []byte("sys: trap: invalid opcode")}, // We can recover from some memory errors in runtime·sigpanic. - P, "sys: trap: fault read addr", // SIGRFAULT - P, "sys: trap: fault write addr", // SIGWFAULT + {_SigPanic, []byte("sys: trap: fault read addr")}, // SIGRFAULT + {_SigPanic, []byte("sys: trap: fault write addr")}, // SIGWFAULT // We can also recover from math errors. - P, "sys: trap: divide error", // SIGINTDIV - P, "sys: fp:", // SIGFLOAT + {_SigPanic, []byte("sys: trap: divide error")}, // SIGINTDIV + {_SigPanic, []byte("sys: fp:")}, // SIGFLOAT // All other traps are normally handled as if they were marked SigThrow. // We mark them SigPanic here so that debug.SetPanicOnFault will work. - P, "sys: trap:", // SIGTRAP + {_SigPanic, []byte("sys: trap:")}, // SIGTRAP // Writes to a closed pipe can be handled if desired, otherwise they're ignored. - N, "sys: write on closed pipe", + {_SigNotify, []byte("sys: write on closed pipe")}, // Other system notes are more serious and cannot be recovered. - T, "sys:", + {_SigThrow, []byte("sys:")}, // Issued to all other procs when calling runtime·exit. - E, "go: exit ", + {_SigGoExit, []byte("go: exit ")}, // Kill is sent by external programs to cause an exit. - K, "kill", + {_SigKill, []byte("kill")}, // Interrupts can be handled if desired, otherwise they cause an exit. - N+K, "interrupt", - N+K, "hangup", + {_SigNotify + _SigKill, []byte("interrupt")}, + {_SigNotify + _SigKill, []byte("hangup")}, // Alarms can be handled if desired, otherwise they're ignored. - N, "alarm", -}; - -#undef N -#undef K -#undef T -#undef P -#undef E + {_SigNotify, []byte("alarm")}, +} diff --git a/src/runtime/signal_power64x.c b/src/runtime/signal_power64x.c deleted file mode 100644 index c0bf1c4a5..000000000 --- a/src/runtime/signal_power64x.c +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2014 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 linux -// +build power64 power64le - -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "signal_GOOS_GOARCH.h" -#include "signals_GOOS.h" - -void -runtime·dumpregs(Siginfo *info, void *ctxt) -{ - USED(info); USED(ctxt); - runtime·printf("r0 %X\t", SIG_R0(info, ctxt)); - runtime·printf("r1 %X\n", SIG_R1(info, ctxt)); - runtime·printf("r2 %X\t", SIG_R2(info, ctxt)); - runtime·printf("r3 %X\n", SIG_R3(info, ctxt)); - runtime·printf("r4 %X\t", SIG_R4(info, ctxt)); - runtime·printf("r5 %X\n", SIG_R5(info, ctxt)); - runtime·printf("r6 %X\t", SIG_R6(info, ctxt)); - runtime·printf("r7 %X\n", SIG_R7(info, ctxt)); - runtime·printf("r8 %X\t", SIG_R8(info, ctxt)); - runtime·printf("r9 %X\n", SIG_R9(info, ctxt)); - runtime·printf("r10 %X\t", SIG_R10(info, ctxt)); - runtime·printf("r11 %X\n", SIG_R11(info, ctxt)); - runtime·printf("r12 %X\t", SIG_R12(info, ctxt)); - runtime·printf("r13 %X\n", SIG_R13(info, ctxt)); - runtime·printf("r14 %X\t", SIG_R14(info, ctxt)); - runtime·printf("r15 %X\n", SIG_R15(info, ctxt)); - runtime·printf("r16 %X\t", SIG_R16(info, ctxt)); - runtime·printf("r17 %X\n", SIG_R17(info, ctxt)); - runtime·printf("r18 %X\t", SIG_R18(info, ctxt)); - runtime·printf("r19 %X\n", SIG_R19(info, ctxt)); - runtime·printf("r20 %X\t", SIG_R20(info, ctxt)); - runtime·printf("r21 %X\n", SIG_R21(info, ctxt)); - runtime·printf("r22 %X\t", SIG_R22(info, ctxt)); - runtime·printf("r23 %X\n", SIG_R23(info, ctxt)); - runtime·printf("r24 %X\t", SIG_R24(info, ctxt)); - runtime·printf("r25 %X\n", SIG_R25(info, ctxt)); - runtime·printf("r26 %X\t", SIG_R26(info, ctxt)); - runtime·printf("r27 %X\n", SIG_R27(info, ctxt)); - runtime·printf("r28 %X\t", SIG_R28(info, ctxt)); - runtime·printf("r29 %X\n", SIG_R29(info, ctxt)); - runtime·printf("r30 %X\t", SIG_R30(info, ctxt)); - runtime·printf("r31 %X\n", SIG_R31(info, ctxt)); - runtime·printf("pc %X\t", SIG_PC(info, ctxt)); - runtime·printf("ctr %X\n", SIG_CTR(info, ctxt)); - runtime·printf("link %X\t", SIG_LINK(info, ctxt)); - runtime·printf("xer %X\n", SIG_XER(info, ctxt)); - runtime·printf("ccr %X\t", SIG_CCR(info, ctxt)); - runtime·printf("trap %X\n", SIG_TRAP(info, ctxt)); -} - -void -runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) -{ - SigTab *t; - bool crash; - - if(sig == SIGPROF) { - runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LINK(info, ctxt), gp, g->m); - return; - } - t = &runtime·sigtab[sig]; - if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) { - // Make it look like a call to the signal func. - // Have to pass arguments out of band since - // augmenting the stack frame would break - // the unwinding code. - gp->sig = sig; - gp->sigcode0 = SIG_CODE0(info, ctxt); - gp->sigcode1 = SIG_FAULT(info, ctxt); - gp->sigpc = SIG_PC(info, ctxt); - - // We arrange link, and pc to pretend the panicking - // function calls sigpanic directly. - // Always save LINK to stack so that panics in leaf - // functions are correctly handled. This smashes - // the stack frame but we're not going back there - // anyway. - SIG_SP(info, ctxt) -= sizeof(uintptr); - *(uintptr*)SIG_SP(info, ctxt) = SIG_LINK(info, ctxt); - // Don't bother saving PC if it's zero, which is - // probably a call to a nil func: the old link register - // is more useful in the stack trace. - if(gp->sigpc != 0) - SIG_LINK(info, ctxt) = gp->sigpc; - // In case we are panicking from external C code - SIG_R0(info, ctxt) = 0; - SIG_R30(info, ctxt) = (uintptr)gp; - SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic; - return; - } - - if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify)) - if(runtime·sigsend(sig)) - return; - if(t->flags & SigKill) - runtime·exit(2); - if(!(t->flags & SigThrow)) - return; - - g->m->throwing = 1; - g->m->caughtsig = gp; - if(runtime·panicking) // traceback already printed - runtime·exit(2); - runtime·panicking = 1; - - if(sig < 0 || sig >= NSIG) - runtime·printf("Signal %d\n", sig); - else - runtime·printf("%s\n", runtime·sigtab[sig].name); - - runtime·printf("PC=%x\n", SIG_PC(info, ctxt)); - if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) { - runtime·printf("signal arrived during cgo execution\n"); - gp = g->m->lockedg; - } - runtime·printf("\n"); - - if(runtime·gotraceback(&crash)){ - runtime·goroutineheader(gp); - runtime·tracebacktrap(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(info, ctxt), gp); - runtime·tracebackothers(gp); - runtime·printf("\n"); - runtime·dumpregs(info, ctxt); - } - - if(crash) - runtime·crash(); - - runtime·exit(2); -} diff --git a/src/runtime/signal_power64x.go b/src/runtime/signal_power64x.go new file mode 100644 index 000000000..fc83beb1b --- /dev/null +++ b/src/runtime/signal_power64x.go @@ -0,0 +1,144 @@ +// Copyright 2014 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 linux +// +build power64 power64le + +package runtime + +import "unsafe" + +func dumpregs(c *sigctxt) { + print("r0 ", hex(c.r0()), "\t") + print("r1 ", hex(c.r1()), "\n") + print("r2 ", hex(c.r2()), "\t") + print("r3 ", hex(c.r3()), "\n") + print("r4 ", hex(c.r4()), "\t") + print("r5 ", hex(c.r5()), "\n") + print("r6 ", hex(c.r6()), "\t") + print("r7 ", hex(c.r7()), "\n") + print("r8 ", hex(c.r8()), "\t") + print("r9 ", hex(c.r9()), "\n") + print("r10 ", hex(c.r10()), "\t") + print("r11 ", hex(c.r11()), "\n") + print("r12 ", hex(c.r12()), "\t") + print("r13 ", hex(c.r13()), "\n") + print("r14 ", hex(c.r14()), "\t") + print("r15 ", hex(c.r15()), "\n") + print("r16 ", hex(c.r16()), "\t") + print("r17 ", hex(c.r17()), "\n") + print("r18 ", hex(c.r18()), "\t") + print("r19 ", hex(c.r19()), "\n") + print("r20 ", hex(c.r20()), "\t") + print("r21 ", hex(c.r21()), "\n") + print("r22 ", hex(c.r22()), "\t") + print("r23 ", hex(c.r23()), "\n") + print("r24 ", hex(c.r24()), "\t") + print("r25 ", hex(c.r25()), "\n") + print("r26 ", hex(c.r26()), "\t") + print("r27 ", hex(c.r27()), "\n") + print("r28 ", hex(c.r28()), "\t") + print("r29 ", hex(c.r29()), "\n") + print("r30 ", hex(c.r30()), "\t") + print("r31 ", hex(c.r31()), "\n") + print("pc ", hex(c.pc()), "\t") + print("ctr ", hex(c.ctr()), "\n") + print("link ", hex(c.link()), "\t") + print("xer ", hex(c.xer()), "\n") + print("ccr ", hex(c.ccr()), "\t") + print("trap ", hex(c.trap()), "\n") +} + +func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { + _g_ := getg() + c := &sigctxt{info, ctxt} + + if sig == _SIGPROF { + sigprof((*byte)(unsafe.Pointer(uintptr(c.pc()))), (*byte)(unsafe.Pointer(uintptr(c.sp()))), (*byte)(unsafe.Pointer(uintptr(c.link()))), gp, _g_.m) + return + } + flags := int32(_SigThrow) + if sig < uint32(len(sigtable)) { + flags = sigtable[sig].flags + } + if c.sigcode() != _SI_USER && flags&_SigPanic != 0 { + // Make it look like a call to the signal func. + // Have to pass arguments out of band since + // augmenting the stack frame would break + // the unwinding code. + gp.sig = sig + gp.sigcode0 = uintptr(c.sigcode()) + gp.sigcode1 = uintptr(c.fault()) + gp.sigpc = uintptr(c.pc()) + + // We arrange link, and pc to pretend the panicking + // function calls sigpanic directly. + // Always save LINK to stack so that panics in leaf + // functions are correctly handled. This smashes + // the stack frame but we're not going back there + // anyway. + sp := c.sp() - ptrSize + c.set_sp(sp) + *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link() + + // Don't bother saving PC if it's zero, which is + // probably a call to a nil func: the old link register + // is more useful in the stack trace. + if gp.sigpc != 0 { + c.set_link(uint64(gp.sigpc)) + } + + // In case we are panicking from external C code + c.set_r0(0) + c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) + c.set_pc(uint64(funcPC(sigpanic))) + return + } + + if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { + if sigsend(sig) { + return + } + } + + if flags&_SigKill != 0 { + exit(2) + } + + if flags&_SigThrow == 0 { + return + } + + _g_.m.throwing = 1 + _g_.m.caughtsig = gp + startpanic() + + if sig < uint32(len(sigtable)) { + print(sigtable[sig].name, "\n") + } else { + print("Signal ", sig, "\n") + } + + print("PC=", hex(c.pc()), "\n") + if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { + print("signal arrived during cgo execution\n") + gp = _g_.m.lockedg + } + print("\n") + + var docrash bool + if gotraceback(&docrash) > 0 { + goroutineheader(gp) + tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp) + tracebackothers(gp) + print("\n") + dumpregs(c) + } + + if docrash { + crash() + } + + exit(2) +} diff --git a/src/runtime/signals_android.h b/src/runtime/signals_android.h deleted file mode 100644 index 5140d8a18..000000000 --- a/src/runtime/signals_android.h +++ /dev/null @@ -1 +0,0 @@ -#include "signals_linux.h" diff --git a/src/runtime/signals_nacl.h b/src/runtime/signals_nacl.h deleted file mode 100644 index 8761e1bd9..000000000 --- a/src/runtime/signals_nacl.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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 "textflag.h" - -#define N SigNotify -#define K SigKill -#define T SigThrow -#define P SigPanic -#define D SigDefault - -#pragma dataflag NOPTR -SigTab runtime·sigtab[] = { - /* 0 */ 0, "SIGNONE: no trap", - /* 1 */ N+K, "SIGHUP: terminal line hangup", - /* 2 */ N+K, "SIGINT: interrupt", - /* 3 */ N+T, "SIGQUIT: quit", - /* 4 */ T, "SIGILL: illegal instruction", - /* 5 */ T, "SIGTRAP: trace trap", - /* 6 */ N+T, "SIGABRT: abort", - /* 7 */ T, "SIGEMT: emulate instruction executed", - /* 8 */ P, "SIGFPE: floating-point exception", - /* 9 */ 0, "SIGKILL: kill", - /* 10 */ P, "SIGBUS: bus error", - /* 11 */ P, "SIGSEGV: segmentation violation", - /* 12 */ T, "SIGSYS: bad system call", - /* 13 */ N, "SIGPIPE: write to broken pipe", - /* 14 */ N, "SIGALRM: alarm clock", - /* 15 */ N+K, "SIGTERM: termination", - /* 16 */ N, "SIGURG: urgent condition on socket", - /* 17 */ 0, "SIGSTOP: stop", - /* 18 */ N+D, "SIGTSTP: keyboard stop", - /* 19 */ 0, "SIGCONT: continue after stop", - /* 20 */ N, "SIGCHLD: child status has changed", - /* 21 */ N+D, "SIGTTIN: background read from tty", - /* 22 */ N+D, "SIGTTOU: background write to tty", - /* 23 */ N, "SIGIO: i/o now possible", - /* 24 */ N, "SIGXCPU: cpu limit exceeded", - /* 25 */ N, "SIGXFSZ: file size limit exceeded", - /* 26 */ N, "SIGVTALRM: virtual alarm clock", - /* 27 */ N, "SIGPROF: profiling alarm clock", - /* 28 */ N, "SIGWINCH: window size change", - /* 29 */ N, "SIGINFO: status request from keyboard", - /* 30 */ N, "SIGUSR1: user-defined signal 1", - /* 31 */ N, "SIGUSR2: user-defined signal 2", -}; - -#undef N -#undef K -#undef T -#undef P -#undef D diff --git a/src/runtime/signals_netbsd.h b/src/runtime/signals_netbsd.h deleted file mode 100644 index 950a2fe62..000000000 --- a/src/runtime/signals_netbsd.h +++ /dev/null @@ -1,54 +0,0 @@ -// 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 "textflag.h" - -#define N SigNotify -#define K SigKill -#define T SigThrow -#define P SigPanic -#define D SigDefault - -#pragma dataflag NOPTR -SigTab runtime·sigtab[] = { - /* 0 */ 0, "SIGNONE: no trap", - /* 1 */ N+K, "SIGHUP: terminal line hangup", - /* 2 */ N+K, "SIGINT: interrupt", - /* 3 */ N+T, "SIGQUIT: quit", - /* 4 */ T, "SIGILL: illegal instruction", - /* 5 */ T, "SIGTRAP: trace trap", - /* 6 */ N+T, "SIGABRT: abort", - /* 7 */ T, "SIGEMT: emulate instruction executed", - /* 8 */ P, "SIGFPE: floating-point exception", - /* 9 */ 0, "SIGKILL: kill", - /* 10 */ P, "SIGBUS: bus error", - /* 11 */ P, "SIGSEGV: segmentation violation", - /* 12 */ T, "SIGSYS: bad system call", - /* 13 */ N, "SIGPIPE: write to broken pipe", - /* 14 */ N, "SIGALRM: alarm clock", - /* 15 */ N+K, "SIGTERM: termination", - /* 16 */ N, "SIGURG: urgent condition on socket", - /* 17 */ 0, "SIGSTOP: stop", - /* 18 */ N+D, "SIGTSTP: keyboard stop", - /* 19 */ 0, "SIGCONT: continue after stop", - /* 20 */ N, "SIGCHLD: child status has changed", - /* 21 */ N+D, "SIGTTIN: background read from tty", - /* 22 */ N+D, "SIGTTOU: background write to tty", - /* 23 */ N, "SIGIO: i/o now possible", - /* 24 */ N, "SIGXCPU: cpu limit exceeded", - /* 25 */ N, "SIGXFSZ: file size limit exceeded", - /* 26 */ N, "SIGVTALRM: virtual alarm clock", - /* 27 */ N, "SIGPROF: profiling alarm clock", - /* 28 */ N, "SIGWINCH: window size change", - /* 29 */ N, "SIGINFO: status request from keyboard", - /* 30 */ N, "SIGUSR1: user-defined signal 1", - /* 31 */ N, "SIGUSR2: user-defined signal 2", - /* 32 */ N, "SIGTHR: reserved", -}; - -#undef N -#undef K -#undef T -#undef P -#undef D diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go index 57d0f8c65..c14347dbd 100644 --- a/src/runtime/stack1.go +++ b/src/runtime/stack1.go @@ -781,7 +781,7 @@ func shrinkstack(gp *g) { if gp.syscallsp != 0 { return } - if _Windows != 0 && gp.m != nil && gp.m.libcallsp != 0 { + if goos_windows != 0 && gp.m != nil && gp.m.libcallsp != 0 { return } diff --git a/src/runtime/stack2.go b/src/runtime/stack2.go index c3718c205..e50b32c78 100644 --- a/src/runtime/stack2.go +++ b/src/runtime/stack2.go @@ -59,7 +59,7 @@ const ( // to each stack below the usual guard area for OS-specific // purposes like signal handling. Used on Windows and on // Plan 9 because they do not use a separate stack. - _StackSystem = _Windows*512*ptrSize + _Plan9*512 + _StackSystem = goos_windows*512*ptrSize + goos_plan9*512 // The minimum size of stack used by Go code _StackMin = 2048 diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 4063e5434..4408e22bf 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -154,7 +154,7 @@ func setcallerpc(argp unsafe.Pointer, pc uintptr) // // func f(arg1, arg2, arg3 int) { // pc := getcallerpc(unsafe.Pointer(&arg1)) -// sp := getcallerpc(unsafe.Pointer(&arg2)) +// sp := getcallersp(unsafe.Pointer(&arg1)) // } // // These two lines find the PC and SP immediately following diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go index 526b3c569..60751dd34 100644 --- a/src/runtime/stubs2.go +++ b/src/runtime/stubs2.go @@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build !plan9 // +build !solaris +// +build !windows +// +build !nacl package runtime diff --git a/src/runtime/arch_power64.h b/src/runtime/stubs3.go index 7cfb9da2f..ffaa28775 100644 --- a/src/runtime/arch_power64.h +++ b/src/runtime/stubs3.go @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -enum { - thechar = '9', - BigEndian = 1, - CacheLineSize = 64, - RuntimeGogoBytes = 64, - PhysPageSize = 65536, - PCQuantum = 4, - Int64Align = 8 -}; +// +build plan9 +package runtime + +func close(fd int32) int32 + +//go:noescape +func open(name *byte, mode, perm int32) int32 diff --git a/src/runtime/sys_linux_power64x.s b/src/runtime/sys_linux_power64x.s index fb24d3e79..395f657bf 100644 --- a/src/runtime/sys_linux_power64x.s +++ b/src/runtime/sys_linux_power64x.s @@ -9,7 +9,8 @@ // System calls and other sys.stuff for Power64, Linux // -#include "zasm_GOOS_GOARCH.h" +#include "go_asm.h" +#include "go_tls.h" #include "textflag.h" #define SYS_exit 1 diff --git a/src/runtime/sys_power64x.c b/src/runtime/sys_power64x.c deleted file mode 100644 index 79d976255..000000000 --- a/src/runtime/sys_power64x.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 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 power64 power64le - -#include "runtime.h" - -// adjust Gobuf as if it executed a call to fn with context ctxt -// and then did an immediate Gosave. -void -runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt) -{ - if(gobuf->lr != 0) - runtime·throw("invalid use of gostartcall"); - gobuf->lr = gobuf->pc; - gobuf->pc = (uintptr)fn; - gobuf->ctxt = ctxt; -} - -// Called to rewind context saved during morestack back to beginning of function. -// To help us, the linker emits a jmp back to the beginning right after the -// call to morestack. We just have to decode and apply that jump. -void -runtime·rewindmorestack(Gobuf *gobuf) -{ - uint32 inst; - - inst = *(uint32*)gobuf->pc; - if((gobuf->pc&3) == 0 && (inst>>24) == 0x4b && (inst&3) == 0) { - //runtime·printf("runtime: rewind pc=%p to pc=%p\n", gobuf->pc, gobuf->pc + ((int32)(inst<<8)>>8)); - gobuf->pc += (int32)(inst<<8)>>8; - return; - } - runtime·printf("runtime: pc=%p %x\n", gobuf->pc, inst); - runtime·throw("runtime: misuse of rewindmorestack"); -} - diff --git a/src/runtime/sys_power64x.go b/src/runtime/sys_power64x.go new file mode 100644 index 000000000..90ebde7b4 --- /dev/null +++ b/src/runtime/sys_power64x.go @@ -0,0 +1,37 @@ +// Copyright 2014 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 power64 power64le + +package runtime + +import "unsafe" + +// adjust Gobuf as if it executed a call to fn with context ctxt +// and then did an immediate Gosave. +func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) { + if buf.lr != 0 { + gothrow("invalid use of gostartcall") + } + buf.lr = buf.pc + buf.pc = uintptr(fn) + buf.ctxt = ctxt +} + +// Called to rewind context saved during morestack back to beginning of function. +// To help us, the linker emits a jmp back to the beginning right after the +// call to morestack. We just have to decode and apply that jump. +func rewindmorestack(buf *gobuf) { + var inst uint32 + if buf.pc&3 == 0 && buf.pc != 0 { + inst = *(*uint32)(unsafe.Pointer(buf.pc)) + if inst>>26 == 18 && inst&3 == 0 { + //print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(uintptr(buf.pc + int32(inst<<6)>>6)), "\n"); + buf.pc += uintptr(int32(inst<<6) >> 6) + return + } + } + print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n") + gothrow("runtime: misuse of rewindmorestack") +} diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s index 2793e5221..c8a830cdf 100644 --- a/src/runtime/sys_windows_386.s +++ b/src/runtime/sys_windows_386.s @@ -44,7 +44,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$24 // stderr MOVL $-12, 0(SP) MOVL SP, BP - CALL *runtime·GetStdHandle(SB) + CALL *runtime·_GetStdHandle(SB) MOVL BP, SP MOVL AX, 0(SP) // handle @@ -56,7 +56,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$24 MOVL $0, 0(DX) MOVL DX, 12(SP) MOVL $0, 16(SP) // overlapped - CALL *runtime·WriteFile(SB) + CALL *runtime·_WriteFile(SB) MOVL BP, SI RET @@ -208,7 +208,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 MOVL BX, g_m(SP) LEAL -8192(SP), CX MOVL CX, (g_stack+stack_lo)(SP) - ADDL $const_StackGuard, CX + ADDL $const__StackGuard, CX MOVL CX, g_stackguard0(SP) MOVL CX, g_stackguard1(SP) MOVL DX, (g_stack+stack_hi)(SP) @@ -255,8 +255,8 @@ TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0 MOVL -4(BX)(AX*4), BX // extract callback context - MOVL cbctxt_gobody(BX), AX - MOVL cbctxt_argsize(BX), DX + MOVL wincallbackcontext_gobody(BX), AX + MOVL wincallbackcontext_argsize(BX), DX // preserve whatever's at the memory location that // the callback will use to store the return value @@ -266,7 +266,7 @@ TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0 ADDL $4, DX // remember how to restore stack on return - MOVL cbctxt_restorestack(BX), BX + MOVL wincallbackcontext_restorestack(BX), BX PUSHL BX // call target Go function @@ -314,7 +314,7 @@ TEXT runtime·tstart(SB),NOSPLIT,$0 MOVL AX, (g_stack+stack_hi)(DX) SUBL $(64*1024), AX // stack size MOVL AX, (g_stack+stack_lo)(DX) - ADDL $const_StackGuard, AX + ADDL $const__StackGuard, AX MOVL AX, g_stackguard0(DX) MOVL AX, g_stackguard1(DX) @@ -415,7 +415,7 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20 MOVL $0, alertable-16(SP) MOVL $-1, handle-20(SP) MOVL SP, BP - MOVL runtime·NtWaitForSingleObject(SB), AX + MOVL runtime·_NtWaitForSingleObject(SB), AX CALL AX MOVL BP, SP RET diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index 5e5c2e7f5..68f7cd392 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -66,7 +66,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48 // stderr MOVQ $-12, CX // stderr MOVQ CX, 0(SP) - MOVQ runtime·GetStdHandle(SB), AX + MOVQ runtime·_GetStdHandle(SB), AX CALL AX MOVQ AX, CX // handle @@ -79,7 +79,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48 MOVQ $0, 0(R9) MOVQ R9, 24(SP) MOVQ $0, 32(SP) // overlapped - MOVQ runtime·WriteFile(SB), AX + MOVQ runtime·_WriteFile(SB), AX CALL AX RET @@ -245,7 +245,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 LEAQ -8192(SP), CX MOVQ CX, (g_stack+stack_lo)(SP) - ADDQ $const_StackGuard, CX + ADDQ $const__StackGuard, CX MOVQ CX, g_stackguard0(SP) MOVQ CX, g_stackguard1(SP) MOVQ DX, (g_stack+stack_hi)(SP) @@ -294,8 +294,8 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0 MOVQ -8(CX)(AX*8), AX // extract callback context - MOVQ cbctxt_argsize(AX), DX - MOVQ cbctxt_gobody(AX), AX + MOVQ wincallbackcontext_argsize(AX), DX + MOVQ wincallbackcontext_gobody(AX), AX // preserve whatever's at the memory location that // the callback will use to store the return value @@ -355,7 +355,7 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 MOVQ AX, (g_stack+stack_hi)(DX) SUBQ $(64*1024), AX // stack size MOVQ AX, (g_stack+stack_lo)(DX) - ADDQ $const_StackGuard, AX + ADDQ $const__StackGuard, AX MOVQ AX, g_stackguard0(DX) MOVQ AX, g_stackguard1(DX) @@ -436,7 +436,7 @@ TEXT runtime·usleep2(SB),NOSPLIT,$16 MOVQ BX, (R8) MOVQ $-1, CX // handle MOVQ $0, DX // alertable - MOVQ runtime·NtWaitForSingleObject(SB), AX + MOVQ runtime·_NtWaitForSingleObject(SB), AX CALL AX MOVQ 8(SP), SP RET diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index efbcab510..661ee59d7 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -41,20 +41,20 @@ func callbackasmAddr(i int) uintptr { func compileCallback(fn eface, cleanstack bool) (code uintptr) { if fn._type == nil || (fn._type.kind&kindMask) != kindFunc { - panic("compilecallback: not a function") + panic("compileCallback: not a function") } ft := (*functype)(unsafe.Pointer(fn._type)) - if len(ft.out) != 1 { - panic("compilecallback: function must have one output parameter") + if ft.out.len != 1 { + panic("compileCallback: function must have one output parameter") } uintptrSize := unsafe.Sizeof(uintptr(0)) - if t := (**_type)(unsafe.Pointer(&ft.out[0])); (*t).size != uintptrSize { - panic("compilecallback: output parameter size is wrong") + if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize { + panic("compileCallback: output parameter size is wrong") } argsize := uintptr(0) - for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] { + for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] { if (*t).size > uintptrSize { - panic("compilecallback: input parameter size is wrong") + panic("compileCallback: input parameter size is wrong") } argsize += uintptrSize } @@ -87,8 +87,6 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) { return callbackasmAddr(n) } -func getLoadLibrary() uintptr - //go:nosplit func syscall_loadlibrary(filename *uint16) (handle, err uintptr) { var c libcall @@ -103,8 +101,6 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) { return } -func getGetProcAddress() uintptr - //go:nosplit func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) { var c libcall diff --git a/src/runtime/zgoarch_386.go b/src/runtime/zgoarch_386.go new file mode 100644 index 000000000..057a746bb --- /dev/null +++ b/src/runtime/zgoarch_386.go @@ -0,0 +1,12 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoarch = `386` + +const goarch_386 = 1 +const goarch_amd64 = 0 +const goarch_amd64p32 = 0 +const goarch_arm = 0 +const goarch_power64 = 0 +const goarch_power64le = 0 diff --git a/src/runtime/zgoarch_amd64.go b/src/runtime/zgoarch_amd64.go new file mode 100644 index 000000000..a71240726 --- /dev/null +++ b/src/runtime/zgoarch_amd64.go @@ -0,0 +1,12 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoarch = `amd64` + +const goarch_386 = 0 +const goarch_amd64 = 1 +const goarch_amd64p32 = 0 +const goarch_arm = 0 +const goarch_power64 = 0 +const goarch_power64le = 0 diff --git a/src/runtime/zgoarch_amd64p32.go b/src/runtime/zgoarch_amd64p32.go new file mode 100644 index 000000000..2b6a142bb --- /dev/null +++ b/src/runtime/zgoarch_amd64p32.go @@ -0,0 +1,12 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoarch = `amd64p32` + +const goarch_386 = 0 +const goarch_amd64 = 0 +const goarch_amd64p32 = 1 +const goarch_arm = 0 +const goarch_power64 = 0 +const goarch_power64le = 0 diff --git a/src/runtime/zgoarch_arm.go b/src/runtime/zgoarch_arm.go new file mode 100644 index 000000000..403021005 --- /dev/null +++ b/src/runtime/zgoarch_arm.go @@ -0,0 +1,12 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoarch = `arm` + +const goarch_386 = 0 +const goarch_amd64 = 0 +const goarch_amd64p32 = 0 +const goarch_arm = 1 +const goarch_power64 = 0 +const goarch_power64le = 0 diff --git a/src/runtime/zgoarch_power64.go b/src/runtime/zgoarch_power64.go new file mode 100644 index 000000000..cc361f050 --- /dev/null +++ b/src/runtime/zgoarch_power64.go @@ -0,0 +1,12 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoarch = `power64` + +const goarch_386 = 0 +const goarch_amd64 = 0 +const goarch_amd64p32 = 0 +const goarch_arm = 0 +const goarch_power64 = 1 +const goarch_power64le = 0 diff --git a/src/runtime/zgoarch_power64le.go b/src/runtime/zgoarch_power64le.go new file mode 100644 index 000000000..41294e61b --- /dev/null +++ b/src/runtime/zgoarch_power64le.go @@ -0,0 +1,12 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoarch = `power64le` + +const goarch_386 = 0 +const goarch_amd64 = 0 +const goarch_amd64p32 = 0 +const goarch_arm = 0 +const goarch_power64 = 0 +const goarch_power64le = 1 diff --git a/src/runtime/zgoos_android.go b/src/runtime/zgoos_android.go new file mode 100644 index 000000000..0590bd9ab --- /dev/null +++ b/src/runtime/zgoos_android.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `android` + +const goos_android = 1 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_darwin.go b/src/runtime/zgoos_darwin.go new file mode 100644 index 000000000..c0a7cd6e7 --- /dev/null +++ b/src/runtime/zgoos_darwin.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `darwin` + +const goos_android = 0 +const goos_darwin = 1 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_dragonfly.go b/src/runtime/zgoos_dragonfly.go new file mode 100644 index 000000000..008d6de81 --- /dev/null +++ b/src/runtime/zgoos_dragonfly.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `dragonfly` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 1 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_freebsd.go b/src/runtime/zgoos_freebsd.go new file mode 100644 index 000000000..247894035 --- /dev/null +++ b/src/runtime/zgoos_freebsd.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `freebsd` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 1 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_linux.go b/src/runtime/zgoos_linux.go new file mode 100644 index 000000000..c775ab538 --- /dev/null +++ b/src/runtime/zgoos_linux.go @@ -0,0 +1,19 @@ +// generated by gengoos.go using 'go generate' + +// +build !android + +package runtime + +const theGoos = `linux` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 1 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_nacl.go b/src/runtime/zgoos_nacl.go new file mode 100644 index 000000000..d9d88f450 --- /dev/null +++ b/src/runtime/zgoos_nacl.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `nacl` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 1 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_netbsd.go b/src/runtime/zgoos_netbsd.go new file mode 100644 index 000000000..ff2c5cb8f --- /dev/null +++ b/src/runtime/zgoos_netbsd.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `netbsd` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 1 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_openbsd.go b/src/runtime/zgoos_openbsd.go new file mode 100644 index 000000000..b071dc63a --- /dev/null +++ b/src/runtime/zgoos_openbsd.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `openbsd` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 1 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_plan9.go b/src/runtime/zgoos_plan9.go new file mode 100644 index 000000000..4306b0f1e --- /dev/null +++ b/src/runtime/zgoos_plan9.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `plan9` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 1 +const goos_solaris = 0 +const goos_windows = 0 diff --git a/src/runtime/zgoos_solaris.go b/src/runtime/zgoos_solaris.go new file mode 100644 index 000000000..10f9537d0 --- /dev/null +++ b/src/runtime/zgoos_solaris.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `solaris` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 1 +const goos_windows = 0 diff --git a/src/runtime/zgoos_windows.go b/src/runtime/zgoos_windows.go new file mode 100644 index 000000000..56f5c58ce --- /dev/null +++ b/src/runtime/zgoos_windows.go @@ -0,0 +1,17 @@ +// generated by gengoos.go using 'go generate' + +package runtime + +const theGoos = `windows` + +const goos_android = 0 +const goos_darwin = 0 +const goos_dragonfly = 0 +const goos_freebsd = 0 +const goos_linux = 0 +const goos_nacl = 0 +const goos_netbsd = 0 +const goos_openbsd = 0 +const goos_plan9 = 0 +const goos_solaris = 0 +const goos_windows = 1 |