runtime: check for heap allocations inside interrupts
This is unsafe and should never be done.
Этот коммит содержится в:
родитель
e066e67baf
коммит
f41b6a3b96
9 изменённых файлов: 77 добавлений и 0 удалений
|
@ -277,6 +277,10 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
|
||||||
size += align(unsafe.Sizeof(layout))
|
size += align(unsafe.Sizeof(layout))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if interrupt.In() {
|
||||||
|
runtimePanic("alloc in interrupt")
|
||||||
|
}
|
||||||
|
|
||||||
gcTotalAlloc += uint64(size)
|
gcTotalAlloc += uint64(size)
|
||||||
gcMallocs++
|
gcMallocs++
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,12 @@ func Restore(state State) {
|
||||||
"state": state,
|
"state": state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
//
|
||||||
|
// Warning: this always returns false on AVR, as there does not appear to be a
|
||||||
|
// reliable way to determine whether we're currently running inside an interrupt
|
||||||
|
// handler.
|
||||||
|
func In() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -50,3 +50,13 @@ func Disable() (state State) {
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
arm.EnableInterrupts(uintptr(state))
|
arm.EnableInterrupts(uintptr(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
func In() bool {
|
||||||
|
// The VECTACTIVE field gives the instruction vector that is currently
|
||||||
|
// active (in handler mode), or 0 if not in an interrupt.
|
||||||
|
// Documentation:
|
||||||
|
// https://developer.arm.com/documentation/dui0497/a/cortex-m0-peripherals/system-control-block/interrupt-control-and-state-register
|
||||||
|
vectactive := uint8(arm.SCB.ICSR.Get())
|
||||||
|
return vectactive != 0
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
package interrupt
|
package interrupt
|
||||||
|
|
||||||
|
// This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime/volatile"
|
"runtime/volatile"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -36,8 +38,11 @@ func (irq Interrupt) Enable() {
|
||||||
regInterruptEnable.SetBits(1 << uint(irq.num))
|
regInterruptEnable.SetBits(1 << uint(irq.num))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inInterrupt bool
|
||||||
|
|
||||||
//export handleInterrupt
|
//export handleInterrupt
|
||||||
func handleInterrupt() {
|
func handleInterrupt() {
|
||||||
|
inInterrupt = true
|
||||||
flags := regInterruptRequestFlags.Get()
|
flags := regInterruptRequestFlags.Get()
|
||||||
for i := 0; i < 14; i++ {
|
for i := 0; i < 14; i++ {
|
||||||
if flags&(1<<uint(i)) != 0 {
|
if flags&(1<<uint(i)) != 0 {
|
||||||
|
@ -45,6 +50,7 @@ func handleInterrupt() {
|
||||||
callInterruptHandler(i)
|
callInterruptHandler(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inInterrupt = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pseudo function call that is replaced by the compiler with the actual
|
// Pseudo function call that is replaced by the compiler with the actual
|
||||||
|
@ -115,3 +121,8 @@ func Restore(state State) {
|
||||||
// Restore interrupts to the previous state.
|
// Restore interrupts to the previous state.
|
||||||
regGlobalInterruptEnable.Set(uint16(state))
|
regGlobalInterruptEnable.Set(uint16(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
func In() bool {
|
||||||
|
return inInterrupt
|
||||||
|
}
|
||||||
|
|
|
@ -23,3 +23,9 @@ func Disable() (state State) {
|
||||||
// calling Disable, this will not re-enable interrupts, allowing for nested
|
// calling Disable, this will not re-enable interrupts, allowing for nested
|
||||||
// cricital sections.
|
// cricital sections.
|
||||||
func Restore(state State) {}
|
func Restore(state State) {}
|
||||||
|
|
||||||
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
func In() bool {
|
||||||
|
// There are no interrupts, so it can't be in one.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -27,3 +27,12 @@ func Disable() (state State) {
|
||||||
func Restore(state State) {
|
func Restore(state State) {
|
||||||
riscv.EnableInterrupts(uintptr(state))
|
riscv.EnableInterrupts(uintptr(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
func In() bool {
|
||||||
|
// There is one exception that has the value 0 (instruction address
|
||||||
|
// misaligned), but it's not very likely and even if it happens, it's not
|
||||||
|
// really something that can be recovered from. Therefore I think it's safe
|
||||||
|
// to ignore it. It's handled specially (in handleException).
|
||||||
|
return riscv.MCAUSE.Get() != 0
|
||||||
|
}
|
||||||
|
|
|
@ -29,3 +29,11 @@ func Restore(state State) {
|
||||||
"state": state,
|
"state": state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In returns whether the system is currently in an interrupt.
|
||||||
|
//
|
||||||
|
// Warning: interrupts have not been implemented for Xtensa yet so this always
|
||||||
|
// returns false.
|
||||||
|
func In() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,12 @@ func main() {
|
||||||
// Zero the threshold value to allow all priorities of interrupts.
|
// Zero the threshold value to allow all priorities of interrupts.
|
||||||
sifive.PLIC.THRESHOLD.Set(0)
|
sifive.PLIC.THRESHOLD.Set(0)
|
||||||
|
|
||||||
|
// Zero MCAUSE, which is set to the reset reason on reset. It must be zeroed
|
||||||
|
// to make interrupt.In() work.
|
||||||
|
// This would also be a good time to save the reset reason, but that hasn't
|
||||||
|
// been implemented yet.
|
||||||
|
riscv.MCAUSE.Set(0)
|
||||||
|
|
||||||
// Set the interrupt address.
|
// Set the interrupt address.
|
||||||
// Note that this address must be aligned specially, otherwise the MODE bits
|
// Note that this address must be aligned specially, otherwise the MODE bits
|
||||||
// of MTVEC won't be zero.
|
// of MTVEC won't be zero.
|
||||||
|
@ -73,6 +79,10 @@ func handleInterrupt() {
|
||||||
// misaligned loads). However, for now we'll just print a fatal error.
|
// misaligned loads). However, for now we'll just print a fatal error.
|
||||||
handleException(code)
|
handleException(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zero MCAUSE so that it can later be used to see whether we're in an
|
||||||
|
// interrupt or not.
|
||||||
|
riscv.MCAUSE.Set(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initPeripherals configures periperhals the way the runtime expects them.
|
// initPeripherals configures periperhals the way the runtime expects them.
|
||||||
|
|
|
@ -31,6 +31,12 @@ func main() {
|
||||||
kendryte.PLIC.PRIORITY[i].Set(0)
|
kendryte.PLIC.PRIORITY[i].Set(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zero MCAUSE, which is set to the reset reason on reset. It must be zeroed
|
||||||
|
// to make interrupt.In() work.
|
||||||
|
// This would also be a good time to save the reset reason, but that hasn't
|
||||||
|
// been implemented yet.
|
||||||
|
riscv.MCAUSE.Set(0)
|
||||||
|
|
||||||
// Set the interrupt address.
|
// Set the interrupt address.
|
||||||
// Note that this address must be aligned specially, otherwise the MODE bits
|
// Note that this address must be aligned specially, otherwise the MODE bits
|
||||||
// of MTVEC won't be zero.
|
// of MTVEC won't be zero.
|
||||||
|
@ -93,6 +99,10 @@ func handleInterrupt() {
|
||||||
// misaligned loads). However, for now we'll just print a fatal error.
|
// misaligned loads). However, for now we'll just print a fatal error.
|
||||||
handleException(code)
|
handleException(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zero MCAUSE so that it can later be used to see whether we're in an
|
||||||
|
// interrupt or not.
|
||||||
|
riscv.MCAUSE.Set(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initPeripherals configures periperhals the way the runtime expects them.
|
// initPeripherals configures periperhals the way the runtime expects them.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче