mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-22 21:39:01 +00:00
runtime: implement timers for Go 1.23
There were a number of changes in time.Timer/time.Ticker that need a separate implementation for Go 1.22 and Go 1.23.
This commit is contained in:
committed by
Ron Evans
parent
db2a06a9bb
commit
e865db232b
@@ -181,12 +181,13 @@ func scheduler() {
|
|||||||
// Check for expired timers to trigger.
|
// Check for expired timers to trigger.
|
||||||
if timerQueue != nil && now >= timerQueue.whenTicks() {
|
if timerQueue != nil && now >= timerQueue.whenTicks() {
|
||||||
scheduleLog("--- timer awoke")
|
scheduleLog("--- timer awoke")
|
||||||
|
delay := ticksToNanoseconds(now - timerQueue.whenTicks())
|
||||||
// Pop timer from queue.
|
// Pop timer from queue.
|
||||||
tn := timerQueue
|
tn := timerQueue
|
||||||
timerQueue = tn.next
|
timerQueue = tn.next
|
||||||
tn.next = nil
|
tn.next = nil
|
||||||
// Run the callback stored in this timer node.
|
// Run the callback stored in this timer node.
|
||||||
tn.callback(tn)
|
tn.callback(tn, delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
t := runqueue.Pop()
|
t := runqueue.Pop()
|
||||||
|
|||||||
+3
-27
@@ -4,7 +4,7 @@ package runtime
|
|||||||
type timerNode struct {
|
type timerNode struct {
|
||||||
next *timerNode
|
next *timerNode
|
||||||
timer *timer
|
timer *timer
|
||||||
callback func(*timerNode)
|
callback func(node *timerNode, delta int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// whenTicks returns the (absolute) time when this timer should trigger next.
|
// whenTicks returns the (absolute) time when this timer should trigger next.
|
||||||
@@ -12,17 +12,6 @@ func (t *timerNode) whenTicks() timeUnit {
|
|||||||
return nanosecondsToTicks(t.timer.when)
|
return nanosecondsToTicks(t.timer.when)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defined in the time package, implemented here in the runtime.
|
|
||||||
//
|
|
||||||
//go:linkname startTimer time.startTimer
|
|
||||||
func startTimer(tim *timer) {
|
|
||||||
addTimer(&timerNode{
|
|
||||||
timer: tim,
|
|
||||||
callback: timerCallback,
|
|
||||||
})
|
|
||||||
scheduleLog("adding timer")
|
|
||||||
}
|
|
||||||
|
|
||||||
// timerCallback is called when a timer expires. It makes sure to call the
|
// timerCallback is called when a timer expires. It makes sure to call the
|
||||||
// callback in the time package and to re-add the timer to the queue if this is
|
// callback in the time package and to re-add the timer to the queue if this is
|
||||||
// a ticker (repeating timer).
|
// a ticker (repeating timer).
|
||||||
@@ -32,11 +21,11 @@ func startTimer(tim *timer) {
|
|||||||
// dependency causes timerQueue not to get optimized away.
|
// dependency causes timerQueue not to get optimized away.
|
||||||
// If timerQueue doesn't get optimized away, small programs (that don't call
|
// If timerQueue doesn't get optimized away, small programs (that don't call
|
||||||
// time.NewTimer etc) would still pay the cost of these timers.
|
// time.NewTimer etc) would still pay the cost of these timers.
|
||||||
func timerCallback(tn *timerNode) {
|
func timerCallback(tn *timerNode, delta int64) {
|
||||||
// Run timer function (implemented in the time package).
|
// Run timer function (implemented in the time package).
|
||||||
// The seq parameter to the f function is not used in the time
|
// The seq parameter to the f function is not used in the time
|
||||||
// package so is left zero.
|
// package so is left zero.
|
||||||
tn.timer.f(tn.timer.arg, 0)
|
tn.timer.callCallback(delta)
|
||||||
|
|
||||||
// If this is a periodic timer (a ticker), re-add it to the queue.
|
// If this is a periodic timer (a ticker), re-add it to the queue.
|
||||||
if tn.timer.period != 0 {
|
if tn.timer.period != 0 {
|
||||||
@@ -44,16 +33,3 @@ func timerCallback(tn *timerNode) {
|
|||||||
addTimer(tn)
|
addTimer(tn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname stopTimer time.stopTimer
|
|
||||||
func stopTimer(tim *timer) bool {
|
|
||||||
return removeTimer(tim)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname resetTimer time.resetTimer
|
|
||||||
func resetTimer(tim *timer, when int64) bool {
|
|
||||||
tim.when = when
|
|
||||||
removed := removeTimer(tim)
|
|
||||||
startTimer(tim)
|
|
||||||
return removed
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
|
//go:build !go1.23
|
||||||
|
|
||||||
// Portions copyright 2009 The Go Authors. All rights reserved.
|
// Portions copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
// Time functions for Go 1.22 and below.
|
||||||
|
|
||||||
type puintptr uintptr
|
type puintptr uintptr
|
||||||
|
|
||||||
// Package time knows the layout of this structure.
|
// Package time knows the layout of this structure.
|
||||||
@@ -31,3 +35,31 @@ type timer struct {
|
|||||||
// The status field holds one of the values below.
|
// The status field holds one of the values below.
|
||||||
status uint32
|
status uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tim *timer) callCallback(delta int64) {
|
||||||
|
tim.f(tim.arg, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defined in the time package, implemented here in the runtime.
|
||||||
|
//
|
||||||
|
//go:linkname startTimer time.startTimer
|
||||||
|
func startTimer(tim *timer) {
|
||||||
|
addTimer(&timerNode{
|
||||||
|
timer: tim,
|
||||||
|
callback: timerCallback,
|
||||||
|
})
|
||||||
|
scheduleLog("adding timer")
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname stopTimer time.stopTimer
|
||||||
|
func stopTimer(tim *timer) bool {
|
||||||
|
return removeTimer(tim)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname resetTimer time.resetTimer
|
||||||
|
func resetTimer(tim *timer, when int64) bool {
|
||||||
|
tim.when = when
|
||||||
|
removed := removeTimer(tim)
|
||||||
|
startTimer(tim)
|
||||||
|
return removed
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//go:build go1.23
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// Time functions for Go 1.23 and above.
|
||||||
|
|
||||||
|
// This is the timer that's used internally inside the runtime.
|
||||||
|
type timer struct {
|
||||||
|
// When to call the timer, and the interval for the ticker.
|
||||||
|
when int64
|
||||||
|
period int64
|
||||||
|
|
||||||
|
// Callback from the time package.
|
||||||
|
f func(arg any, seq uintptr, delta int64)
|
||||||
|
arg any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tim *timer) callCallback(delta int64) {
|
||||||
|
tim.f(tim.arg, 0, delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the struct used internally in the runtime. The first two fields are
|
||||||
|
// the same as time.Timer and time.Ticker so it can be used as-is in the time
|
||||||
|
// package.
|
||||||
|
type timeTimer struct {
|
||||||
|
c unsafe.Pointer // <-chan time.Time
|
||||||
|
init bool
|
||||||
|
timer
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname newTimer time.newTimer
|
||||||
|
func newTimer(when, period int64, f func(arg any, seq uintptr, delta int64), arg any, c unsafe.Pointer) *timeTimer {
|
||||||
|
tim := &timeTimer{
|
||||||
|
c: c,
|
||||||
|
init: true,
|
||||||
|
timer: timer{
|
||||||
|
when: when,
|
||||||
|
period: period,
|
||||||
|
f: f,
|
||||||
|
arg: arg,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
scheduleLog("new timer")
|
||||||
|
addTimer(&timerNode{
|
||||||
|
timer: &tim.timer,
|
||||||
|
callback: timerCallback,
|
||||||
|
})
|
||||||
|
return tim
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname stopTimer time.stopTimer
|
||||||
|
func stopTimer(tim *timeTimer) bool {
|
||||||
|
return removeTimer(&tim.timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname resetTimer time.resetTimer
|
||||||
|
func resetTimer(t *timeTimer, when, period int64) bool {
|
||||||
|
t.timer.when = when
|
||||||
|
t.timer.period = period
|
||||||
|
removed := removeTimer(&t.timer)
|
||||||
|
addTimer(&timerNode{
|
||||||
|
timer: &t.timer,
|
||||||
|
callback: timerCallback,
|
||||||
|
})
|
||||||
|
return removed
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user