summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-11 17:10:29 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-11-15 08:56:54 +0100
commitb936ce5a8c736974fb8cc166ccbf76ebe9b4115c (patch)
tree89cf3c46593e0b02c9a79387b77bdd38654c7a5e /cpukit/score
parentscore: Port large time delta support to RTEMS (diff)
downloadrtems-b936ce5a8c736974fb8cc166ccbf76ebe9b4115c.tar.bz2
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.
Diffstat (limited to 'cpukit/score')
-rw-r--r--cpukit/score/src/kern_tc.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 5544b9ecde..42318d1c80 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -407,7 +407,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. */
@@ -438,7 +442,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 { \
@@ -573,7 +581,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. */
@@ -1604,7 +1616,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;
@@ -1620,14 +1635,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;
@@ -1727,6 +1740,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.
@@ -1734,6 +1748,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
@@ -2226,27 +2243,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;