Skip to content

Commit 687b0da

Browse files
Merge pull request #15 from bitcoin3us/fix/task-handler-fairness
task_handler: keep the main thread alive under heavy UI load (stacked on #13)
2 parents 276aec7 + 6f5cff6 commit 687b0da

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

‎api_drivers/common_api_drivers/frozen/other/task_handler.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ def __init__(
5858
self.max_scheduled = max_scheduled
5959

6060
self._last_tick = time.ticks_ms() # NOQA
61+
# Fairness: how long the last handler pass took and when it ended,
62+
# so the timer can leave the main thread a share of the CPU.
63+
self._last_run_ms = 0
64+
self._last_end = self._last_tick
6165
self._timer.init(
6266
mode=Timer.PERIODIC,
6367
period=self.duration,
@@ -102,6 +106,7 @@ def is_running(cls):
102106
return cls._current_instance is not None
103107

104108
def _task_handler(self, _):
109+
run_start = time.ticks_ms() # NOQA
105110
try:
106111
self._scheduled -= 1
107112

@@ -159,6 +164,11 @@ def _task_handler(self, _):
159164
if self.exception_hook:
160165
self.exception_hook(e)
161166

167+
finally:
168+
end = time.ticks_ms() # NOQA
169+
self._last_run_ms = time.ticks_diff(end, run_start) # NOQA
170+
self._last_end = end
171+
162172
def _timer_cb(self, _):
163173
# The only place LVGL time advances. Feed it the real elapsed time
164174
# rather than the nominal period: timer callbacks are delivered via the
@@ -170,6 +180,15 @@ def _timer_cb(self, _):
170180
if self._running:
171181
return
172182

183+
# Fairness: a handler pass that outlasts the timer period would
184+
# otherwise be rescheduled back-to-back, starving everything else on
185+
# the main thread (the REPL, touch and app tasks). Wait until at
186+
# least a quarter of the last pass's duration has elapsed since it
187+
# ended, so the main thread always keeps ~20% of the CPU.
188+
gap = self._last_run_ms >> 2
189+
if gap > self.duration and time.ticks_diff(now, self._last_end) < gap: # NOQA
190+
return
191+
173192
if self._scheduled < self.max_scheduled:
174193
try:
175194
micropython.schedule(self._task_handler_ref, 0)

0 commit comments

Comments
 (0)