diff --git a/src/runtime/gc_blocks.go b/src/runtime/gc_blocks.go index 71e88e4a..462097f6 100644 --- a/src/runtime/gc_blocks.go +++ b/src/runtime/gc_blocks.go @@ -277,6 +277,10 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer { size += align(unsafe.Sizeof(layout)) } + if interrupt.In() { + runtimePanic("alloc in interrupt") + } + gcTotalAlloc += uint64(size) gcMallocs++ diff --git a/src/runtime/interrupt/interrupt_avr.go b/src/runtime/interrupt/interrupt_avr.go index 25c8caa0..0af71a89 100644 --- a/src/runtime/interrupt/interrupt_avr.go +++ b/src/runtime/interrupt/interrupt_avr.go @@ -34,3 +34,12 @@ func Restore(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 +} diff --git a/src/runtime/interrupt/interrupt_cortexm.go b/src/runtime/interrupt/interrupt_cortexm.go index a7127c3e..a34dff78 100644 --- a/src/runtime/interrupt/interrupt_cortexm.go +++ b/src/runtime/interrupt/interrupt_cortexm.go @@ -50,3 +50,13 @@ func Disable() (state State) { func Restore(state 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 +} diff --git a/src/runtime/interrupt/interrupt_gameboyadvance.go b/src/runtime/interrupt/interrupt_gameboyadvance.go index 72f2a819..b14f8059 100644 --- a/src/runtime/interrupt/interrupt_gameboyadvance.go +++ b/src/runtime/interrupt/interrupt_gameboyadvance.go @@ -2,6 +2,8 @@ package interrupt +// This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm + import ( "runtime/volatile" "unsafe" @@ -36,8 +38,11 @@ func (irq Interrupt) Enable() { regInterruptEnable.SetBits(1 << uint(irq.num)) } +var inInterrupt bool + //export handleInterrupt func handleInterrupt() { + inInterrupt = true flags := regInterruptRequestFlags.Get() for i := 0; i < 14; i++ { if flags&(1<