diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-10-11 17:10:29 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-10-28 11:35:23 +0200 |
commit | 46573347414661c179ce36e54607d48c54a62ecd (patch) | |
tree | 7438f17d81cbb1e6154eed3a19d4c62a6eb1fe1c | |
parent | ae659035a53c48bcf58fbef5aab2ebeceb785e72 (diff) |
score: Optimize timehand updates for non-SMP
In uniprocessor configurations, the timehand updates are done with
interrupts disabled. So, it is impossible to observe a generation
number of zero.
-rw-r--r-- | cpukit/score/src/kern_tc.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c index e5ad232f71..c1f15d7430 100644 --- a/cpukit/score/src/kern_tc.c +++ b/cpukit/score/src/kern_tc.c @@ -396,7 +396,11 @@ bintime_off(struct bintime *bt, u_int off) delta = tc_delta(th); large_delta = th->th_large_delta; atomic_thread_fence_acq(); +#if defined(RTEMS_SMP) } while (gen == 0 || gen != th->th_generation); +#else + } while (gen != th->th_generation); +#endif if (__predict_false(delta >= large_delta)) { /* Avoid overflow for scale * delta. */ @@ -427,7 +431,11 @@ getthmember(void *out, size_t out_size, u_int off) gen = atomic_load_acq_int(&th->th_generation); memcpy(out, (char *)th + off, out_size); atomic_thread_fence_acq(); +#if defined(RTEMS_SMP) } while (gen == 0 || gen != th->th_generation); +#else + } while (gen != th->th_generation); +#endif } #define GETTHMEMBER(dst, member) \ do { \ @@ -562,7 +570,11 @@ _Timecounter_Sbinuptime(void) delta = tc_delta(th); large_delta = th->th_large_delta; atomic_thread_fence_acq(); +#if defined(RTEMS_SMP) } while (gen == 0 || gen != th->th_generation); +#else + } while (gen != th->th_generation); +#endif if (__predict_false(delta >= large_delta)) { /* Avoid overflow for scale * delta. */ @@ -1587,7 +1599,10 @@ _Timecounter_Windup(struct bintime *new_boottimebin, { struct bintime bt; struct timehands *th, *tho; - uint32_t delta, ncount, ogen; + uint32_t delta, ncount; +#if defined(RTEMS_SMP) + u_int ogen; +#endif int i; time_t t; @@ -1603,14 +1618,12 @@ _Timecounter_Windup(struct bintime *new_boottimebin, tho = timehands; #if defined(RTEMS_SMP) th = tho->th_next; -#else - th = tho; -#endif ogen = th->th_generation; th->th_generation = 0; atomic_thread_fence_rel(); -#if defined(RTEMS_SMP) memcpy(th, tho, offsetof(struct timehands, th_generation)); +#else + th = tho; #endif if (new_boottimebin != NULL) th->th_boottime = *new_boottimebin; @@ -1709,6 +1722,7 @@ _Timecounter_Windup(struct bintime *new_boottimebin, #endif } +#if defined(RTEMS_SMP) /* * Now that the struct timehands is again consistent, set the new * generation number, making sure to not make it zero. @@ -1716,6 +1730,9 @@ _Timecounter_Windup(struct bintime *new_boottimebin, if (++ogen == 0) ogen = 1; atomic_store_rel_int(&th->th_generation, ogen); +#else + atomic_store_rel_int(&th->th_generation, th->th_generation + 1); +#endif /* Go live with the new struct timehands. */ #ifdef FFCLOCK @@ -2197,27 +2214,38 @@ _Timecounter_Tick_simple(uint32_t delta, uint32_t offset, { struct bintime bt; struct timehands *th; - uint32_t ogen; +#if defined(RTEMS_SMP) + u_int ogen; +#endif th = timehands; +#if defined(RTEMS_SMP) ogen = th->th_generation; + th->th_generation = 0; + atomic_thread_fence_rel(); +#endif + th->th_offset_count = offset; bintime_addx(&th->th_offset, th->th_scale * delta); - bt = th->th_offset; bintime_add(&bt, &th->th_boottime); + /* Update the UTC timestamps used by the get*() functions. */ th->th_bintime = bt; bintime2timeval(&bt, &th->th_microtime); bintime2timespec(&bt, &th->th_nanotime); +#if defined(RTEMS_SMP) /* * Now that the struct timehands is again consistent, set the new * generation number, making sure to not make it zero. */ if (++ogen == 0) ogen = 1; - th->th_generation = ogen; + atomic_store_rel_int(&th->th_generation, ogen); +#else + atomic_store_rel_int(&th->th_generation, th->th_generation + 1); +#endif /* Go live with the new struct timehands. */ time_second = th->th_microtime.tv_sec; |