[rtems commit] score: Optimize timehand updates for non-SMP
Jan Sommer
jan at rtems.org
Tue Nov 30 14:41:00 UTC 2021
Module: rtems
Branch: 5
Commit: 780b4688456b3121d6c6dcf933fc290fa3f4ea94
Changeset: http://git.rtems.org/rtems/commit/?id=780b4688456b3121d6c6dcf933fc290fa3f4ea94
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Mon Oct 11 17:10:29 2021 +0200
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.
---
cpukit/score/src/kern_tc.c | 44 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 0064560..1161463 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -390,7 +390,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. */
@@ -421,7 +425,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 { \
@@ -556,7 +564,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 timecounter *tc;
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;
@@ -1710,6 +1723,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.
@@ -1717,6 +1731,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
@@ -2209,27 +2226,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;
More information about the vc
mailing list