[rtems commit] score: Optimize timehand updates for non-SMP

Sebastian Huber sebh at rtems.org
Mon Nov 15 08:15:17 UTC 2021


Module:    rtems
Branch:    master
Commit:    b936ce5a8c736974fb8cc166ccbf76ebe9b4115c
Changeset: http://git.rtems.org/rtems/commit/?id=b936ce5a8c736974fb8cc166ccbf76ebe9b4115c

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 5544b9e..42318d1 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;



More information about the vc mailing list