@@ -506,20 +506,48 @@ static odp_buffer_t timer_cancel(odp_timer_pool *tp,
return old_buf;
}
+static int post_timeout_to_queue(odp_queue_t queue, odp_buffer_t tmo_buf,
+ uint64_t exp_tck)
+{
+ odp_timeout_hdr_t *tmo_hdr;
+ int rc;
+
+ if (odp_unlikely(tmo_buf == ODP_BUFFER_INVALID))
+ return 0;
+
+ /* Fill in expiration tick if timeout event */
+ if (_odp_buffer_type(tmo_buf) == ODP_EVENT_TIMEOUT) {
+ /* Convert from buffer to timeout hdr */
+ tmo_hdr = timeout_hdr_from_buf(tmo_buf);
+ tmo_hdr->expiration = exp_tck;
+ /* timer and user_ptr fields filled in when timer was set */
+ }
+ /* Else ignore events of other types.
+ * Post the timeout to the destination queue. */
+ rc = odp_queue_enq(queue, odp_buffer_to_event(tmo_buf));
+ if (odp_unlikely(rc != 0))
+ ODP_ABORT("Failed to enqueue timeout buffer (%d)\n",
+ rc);
+ return 1;
+}
+
+
+#ifdef ODP_ATOMIC_U128
static unsigned timer_expire(odp_timer_pool *tp, uint32_t idx, uint64_t tick)
{
odp_timer *tim = &tp->timers[idx];
tick_buf_t *tb = &tp->tick_buf[idx];
odp_buffer_t tmo_buf = ODP_BUFFER_INVALID;
uint64_t exp_tck;
-#ifdef ODP_ATOMIC_U128
+ int rc;
+ tick_buf_t new, old;
+
/* Atomic re-read for correctness */
exp_tck = _odp_atomic_u64_load_mm(&tb->exp_tck, _ODP_MEMMODEL_RLX);
/* Re-check exp_tck */
if (odp_likely(exp_tck <= tick)) {
/* Attempt to grab timeout buffer, replace with inactive timer
* and invalid buffer */
- tick_buf_t new, old;
old.exp_tck.v = exp_tck;
old.tmo_buf = tb->tmo_buf;
TB_SET_PAD(old);
@@ -529,65 +557,57 @@ static unsigned timer_expire(odp_timer_pool *tp, uint32_t idx, uint64_t tick)
new.exp_tck.v = exp_tck | TMO_INACTIVE;
new.tmo_buf = ODP_BUFFER_INVALID;
TB_SET_PAD(new);
- int succ = _odp_atomic_u128_cmp_xchg_mm(
+ rc = _odp_atomic_u128_cmp_xchg_mm(
(_odp_atomic_u128_t *)tb,
(_uint128_t *)&old, (_uint128_t *)&new,
_ODP_MEMMODEL_RLS, _ODP_MEMMODEL_RLX);
- if (succ)
+ if (rc)
tmo_buf = old.tmo_buf;
/* Else CAS failed, something changed => skip timer
* this tick, it will be checked again next tick */
+ } else {
+ /* Else false positive, ignore */
}
- /* Else false positive, ignore */
+
+ return post_timeout_to_queue(tim->queue, tmo_buf, exp_tck);
+}
#else
+static unsigned timer_expire(odp_timer_pool *tp, uint32_t idx, uint64_t tick)
+{
+ odp_timer *tim = &tp->timers[idx];
+ tick_buf_t *tb = &tp->tick_buf[idx];
+ odp_buffer_t tmo_buf = ODP_BUFFER_INVALID;
+ uint64_t exp_tck;
+
/* Take a related lock */
while (_odp_atomic_flag_tas(IDX2LOCK(idx)))
/* While lock is taken, spin using relaxed loads */
while (_odp_atomic_flag_load(IDX2LOCK(idx)))
odp_spin();
+
/* Proper check for timer expired */
exp_tck = tb->exp_tck.v;
- if (odp_likely(exp_tck <= tick)) {
- /* Verify that there is a timeout buffer */
- if (odp_likely(tb->tmo_buf != ODP_BUFFER_INVALID)) {
- /* Grab timeout buffer, replace with inactive timer
- * and invalid buffer */
- tmo_buf = tb->tmo_buf;
- tb->tmo_buf = ODP_BUFFER_INVALID;
- /* Set the inactive/expired bit keeping the expiration
- * tick so that we can check against the expiration
- * tick of the timeout when it is received */
- tb->exp_tck.v |= TMO_INACTIVE;
- }
+
+ /* Check that tick expired and verify that there is a timeout buffer */
+ if (odp_likely((exp_tck <= tick) && (tb->tmo_buf != ODP_BUFFER_INVALID))) {
+ /* Grab timeout buffer, replace with inactive timer
+ * and invalid buffer */
+ tmo_buf = tb->tmo_buf;
+ tb->tmo_buf = ODP_BUFFER_INVALID;
+ /* Set the inactive/expired bit keeping the expiration
+ * tick so that we can check against the expiration
+ * tick of the timeout when it is received */
+ tb->exp_tck.v |= TMO_INACTIVE;
+ } else {
/* Else somehow active timer without user buffer */
+ /* Else false positive, ignore */
}
- /* Else false positive, ignore */
/* Release the lock */
_odp_atomic_flag_clear(IDX2LOCK(idx));
-#endif
- if (odp_likely(tmo_buf != ODP_BUFFER_INVALID)) {
- /* Fill in expiration tick if timeout event */
- if (_odp_buffer_type(tmo_buf) == ODP_EVENT_TIMEOUT) {
- /* Convert from buffer to timeout hdr */
- odp_timeout_hdr_t *tmo_hdr =
- timeout_hdr_from_buf(tmo_buf);
- tmo_hdr->expiration = exp_tck;
- /* timer and user_ptr fields filled in when timer
- * was set */
- }
- /* Else ignore events of other types */
- /* Post the timeout to the destination queue */
- int rc = odp_queue_enq(tim->queue,
- odp_buffer_to_event(tmo_buf));
- if (odp_unlikely(rc != 0))
- ODP_ABORT("Failed to enqueue timeout buffer (%d)\n",
- rc);
- return 1;
- } else {
- /* Else false positive, ignore */
- return 0;
- }
+
+ return post_timeout_to_queue(tim->queue, tmo_buf, exp_tck);
}
+#endif
static unsigned odp_timer_pool_expire(odp_timer_pool_t tpid, uint64_t tick)
{
Current timer_expire() function implementation for linux-generic is too long and complex. This patch makes it simple to read. No functional changes. Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> --- platform/linux-generic/odp_timer.c | 102 ++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 41 deletions(-)