scheduler_none.mx raw

   1  //go:build scheduler.none
   2  
   3  package runtime
   4  
   5  import (
   6  	"internal/task"
   7  	"runtime/interrupt"
   8  )
   9  
  10  const hasScheduler = false
  11  
  12  // No goroutines — single-threaded event dispatch.
  13  const hasParallelism = false
  14  
  15  // Set to true after main.main returns.
  16  var mainExited bool
  17  
  18  // dummy flag, not used without scheduler
  19  var schedulerExit bool
  20  
  21  // run is called by the program entry point to execute the go program.
  22  func run() {
  23  	initRand()
  24  	initHeap()
  25  	initAll()
  26  	callMain()
  27  	mainExited = true
  28  }
  29  
  30  //go:linkname sleep time.Sleep
  31  func sleep(duration int64) {
  32  	if duration <= 0 {
  33  		return
  34  	}
  35  
  36  	// Sleep in chunks, firing expired timers between chunks.
  37  	target := ticks() + nanosecondsToTicks(duration)
  38  	for {
  39  		now := ticks()
  40  		remaining := target - now
  41  		if remaining <= 0 {
  42  			break
  43  		}
  44  
  45  		// If a timer fires before our target, only sleep until that timer.
  46  		if timerQueue != nil {
  47  			nextTimer := timerQueue.whenTicks() - now
  48  			if nextTimer < remaining {
  49  				remaining = nextTimer
  50  			}
  51  		}
  52  
  53  		if remaining > 0 {
  54  			sleepTicks(remaining)
  55  		}
  56  
  57  		// Fire all expired timers.
  58  		fireTimers()
  59  	}
  60  
  61  	// Final timer check after sleep completes.
  62  	fireTimers()
  63  }
  64  
  65  // fireTimers runs callbacks for all expired timers.
  66  func fireTimers() {
  67  	now := ticks()
  68  	for timerQueue != nil && timerQueue.whenTicks() <= now {
  69  		tn := timerQueue
  70  		timerQueue = tn.next
  71  		tn.next = nil
  72  		tn.callback(tn, int64(ticksToNanoseconds(now-tn.whenTicks())))
  73  	}
  74  }
  75  
  76  // addTimer adds a timer to the queue. Timers fire during sleep or
  77  // at explicit yield points.
  78  func addTimer(tim *timerNode) {
  79  	mask := interrupt.Disable()
  80  	timerQueueAdd(tim)
  81  	interrupt.Restore(mask)
  82  }
  83  
  84  // removeTimer removes a timer from the queue.
  85  func removeTimer(tim *timer) *timerNode {
  86  	mask := interrupt.Disable()
  87  	n := timerQueueRemove(tim)
  88  	interrupt.Restore(mask)
  89  	return n
  90  }
  91  
  92  func deadlock() {
  93  	runtimePanic("all goroutines are asleep - deadlock!")
  94  }
  95  
  96  func scheduleTask(t *task.Task) {
  97  	// Single-threaded: no task scheduling. Channel operations
  98  	// that would block will deadlock (by design).
  99  }
 100  
 101  func Gosched() {
 102  	// Single-threaded: fire pending timers as a yield point.
 103  	fireTimers()
 104  }
 105  
 106  func scheduler(returnAtDeadlock bool) {
 107  	runtimePanic("unreachable: scheduler must not be called without goroutines")
 108  }
 109  
 110  func schedulerRunQueue() *task.Queue {
 111  	runtimePanic("unreachable: no runqueue without goroutines")
 112  	return nil
 113  }
 114  
 115  // NumCPU returns the number of logical CPUs usable by the current process.
 116  func NumCPU() int {
 117  	return 1
 118  }
 119  
 120  func lockAtomics() interrupt.State {
 121  	return interrupt.Disable()
 122  }
 123  
 124  func unlockAtomics(mask interrupt.State) {
 125  	interrupt.Restore(mask)
 126  }
 127  
 128  func printlock() {
 129  	// nothing to do
 130  }
 131  
 132  func printunlock() {
 133  	// nothing to do
 134  }
 135  
 136  // eventLoopTick runs one iteration of the single-threaded event loop.
 137  // Called from internal/task when blocking operations need to poll for
 138  // I/O events and timers without a scheduler.
 139  func eventLoopTick() {
 140  	if hasPoll {
 141  		netpollBlock(1) // 1ms poll
 142  	}
 143  	fireTimers()
 144  }
 145