Hi,
Hopefully the ascii graphics underneath renders correctly. Here's an example
where timer API without cancel status (return value) is causing, not only
potential implementation inefficiency, but an application failure.
An application has created multiple timers (t0, t1, ...). It sets t0 to expire
in e.g. 10ms. The timer HW is set, t0 expires and the timeout is sent out. Core
B receives the tmo, checks the status, status is fresh, it starts tmo
processing. A bit later core A cancels t0 and reuses it for another timeout
(e.g. again 10ms). Timer HW is set for t0 expiration. Core B continues
processing and holds tmo for e.g. 100ms (a long time relative to the reused t0
expiration time). HW timer expires, but tmo for t0 has not returned yet.
Eventually core B returns tmo for t0 and the new timeout for t0 can be
delivered.
Application used all timer API calls correctly and everything "succeeded", but
the second tmo was delivered e.g. 90ms late!
If cancel would have returned status code ("too late"), application on core A
would not have reused t0, but used the next "free timer" instead (e.g. t1). The
tmo buffer for that would have been available and tmo delivered in time (e.g.
received and processed by core C). From application point of view, a "free
timer" is one that has been successfully cancelled or the pending tmo have been
handled.
The problem is build from the combination of:
- timer_set_xxx cannot fail => timer cannot allocate a new tmo buffer when
application holds previous one
- cancel cannot fail => application does not need to care about timer status
when reusing a timer
- application may hold a tmo for long time (as it should be able to do)
The special nature of tmo buffer is also problematic. It's a buffer (of timer
timeout type) but cannot be e.g. stored or forwarded to other queues (for
arbitrary time) - otherwise the original timer is stuck until application
returns the buffer.
Did I miss something in the API logic?
-Petri
timer_t t0, t1, ...
Core A Core B Timer
HW/implementation
timer_set_rel(t0, 10ms) set t0
t0 expired
send timeout for t0
tmo = sched()
tmo_status(tmo) == FRESH
start processing tmo
cancel(t0)
timer_set_rel(t0, 10ms) set t0
t0 expired
no tmo buffer for t0
no tmo buffer for t0 ...
e.g. after 100ms
finished processing tmo
return_tmo(tmo) return
tmo buffer for t0
send timeout for t0
tmo = sched()
tmo_status(tmo) == FRESH
TMO RECEIVED 90ms LATE!
_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp