You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
machine: [rp2] discount scheduling delays in I2C timeouts (#4876)
The `gosched` call introduce arbitrary long delays in general, and in
TinyGo particular because the goroutine scheduler is cooperative and
doesn't preempt busy (e.g. compute-heavy) goroutines.
Before this change, the timeout logic would read, simplified:
deadline := now() + timeout
startTX()
for !txDone() {
if now() > deadline { return timeoutError }
gosched() // (1)
}
startRx() // (2)
for !rxDone() {
// (3)
if now() > deadline { return timeoutError }
gosched()
}
What could happen in a busy system is:
- The gosched marked (1) would push now() to be > than deadline.
- startRx is called (2), but the call to rxDone immediately after would
report it not yet done.
- The check marked (3) would fail, even though only a miniscule amount
of time has passed between startRx and the check.
This change ensures that the timeout clock discounts time spent in
`gosched`. The logic now reads, around every call to `gosched`:
deadline := now() + timeout
startTX()
for !txDone() {
if now() > deadline { return timeoutError }
before := now()
gosched()
deadline += now() - before
}
I tested this change by simulating a busy goroutine:
go func() {
for {
// Busy.
before := time.Now()
for time.Since(before) < 100*time.Millisecond {
}
// Sleep.
time.Sleep(100 * time.Millisecond)
}
}()
and testing that I2C transfers would no longer time out.
0 commit comments