mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 03:53:42 +00:00
432ebe13ed
The threads scheduler handled runtime.Goexit using the generic deadlock path, which parked the current pthread forever. Add a scheduler-specific goexit hook so it can remove the current task and exit the pthread while ordinary blocking deadlocks still block. Track main goroutine Goexit so the last remaining goroutine reports the expected deadlock instead of letting the process exit successfully. Expand the crash coverage with the Goexit cases covered by Big Go's runtime tests.
103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
//go:build scheduler.none
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"internal/task"
|
|
"runtime/interrupt"
|
|
)
|
|
|
|
const hasScheduler = false
|
|
|
|
// No goroutines are allowed, so there's no parallelism anywhere.
|
|
const hasParallelism = false
|
|
|
|
// Set to true after main.main returns.
|
|
var mainExited bool
|
|
|
|
// dummy flag, not used without scheduler
|
|
var schedulerExit bool
|
|
|
|
// run is called by the program entry point to execute the go program.
|
|
// With the "none" scheduler, init and the main function are invoked directly.
|
|
func run() {
|
|
initRand()
|
|
initHeap()
|
|
initAll()
|
|
callMain()
|
|
mainExited = true
|
|
}
|
|
|
|
//go:linkname sleep time.Sleep
|
|
func sleep(duration int64) {
|
|
if duration <= 0 {
|
|
return
|
|
}
|
|
|
|
sleepTicks(nanosecondsToTicks(duration))
|
|
}
|
|
|
|
func deadlock() {
|
|
// The only goroutine available is deadlocked.
|
|
runtimePanic("all goroutines are asleep - deadlock!")
|
|
}
|
|
|
|
func goexit() {
|
|
deadlock()
|
|
}
|
|
|
|
func scheduleTask(t *task.Task) {
|
|
// Pause() will panic, so this should not be reachable.
|
|
}
|
|
|
|
func Gosched() {
|
|
// There are no other goroutines, so there's nothing to schedule.
|
|
}
|
|
|
|
// NumCPU returns the number of logical CPUs usable by the current process.
|
|
func NumCPU() int {
|
|
return 1
|
|
}
|
|
|
|
func addTimer(tim *timerNode) {
|
|
runtimePanic("timers not supported without a scheduler")
|
|
}
|
|
|
|
func reAddTimer(tn *timerNode) {
|
|
runtimePanic("timers not supported without a scheduler")
|
|
}
|
|
|
|
func removeTimer(tim *timer) *timerNode {
|
|
runtimePanic("timers not supported without a scheduler")
|
|
return nil
|
|
}
|
|
|
|
func schedulerRunQueue() *task.Queue {
|
|
// This function is not actually used, it is only called when hasScheduler
|
|
// is true.
|
|
runtimePanic("unreachable: no runqueue without a scheduler")
|
|
return nil
|
|
}
|
|
|
|
func scheduler(returnAtDeadlock bool) {
|
|
// The scheduler should never be run when using -scheduler=none. Meaning,
|
|
// this code should be unreachable.
|
|
runtimePanic("unreachable: scheduler must not be called with the 'none' scheduler")
|
|
}
|
|
|
|
func lockAtomics() interrupt.State {
|
|
return interrupt.Disable()
|
|
}
|
|
|
|
func unlockAtomics(mask interrupt.State) {
|
|
interrupt.Restore(mask)
|
|
}
|
|
|
|
func printlock() {
|
|
// nothing to do
|
|
}
|
|
|
|
func printunlock() {
|
|
// nothing to do
|
|
}
|