mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-06 15:43:15 +00:00
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.
This commit is contained in:
@@ -407,7 +407,11 @@ bintime_off(struct bintime *bt, u_int off)
|
|||||||
delta = tc_delta(th);
|
delta = tc_delta(th);
|
||||||
large_delta = th->th_large_delta;
|
large_delta = th->th_large_delta;
|
||||||
atomic_thread_fence_acq();
|
atomic_thread_fence_acq();
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
} while (gen == 0 || gen != th->th_generation);
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
#else
|
||||||
|
} while (gen != th->th_generation);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (__predict_false(delta >= large_delta)) {
|
if (__predict_false(delta >= large_delta)) {
|
||||||
/* Avoid overflow for scale * 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);
|
gen = atomic_load_acq_int(&th->th_generation);
|
||||||
memcpy(out, (char *)th + off, out_size);
|
memcpy(out, (char *)th + off, out_size);
|
||||||
atomic_thread_fence_acq();
|
atomic_thread_fence_acq();
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
} while (gen == 0 || gen != th->th_generation);
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
#else
|
||||||
|
} while (gen != th->th_generation);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#define GETTHMEMBER(dst, member) \
|
#define GETTHMEMBER(dst, member) \
|
||||||
do { \
|
do { \
|
||||||
@@ -573,7 +581,11 @@ _Timecounter_Sbinuptime(void)
|
|||||||
delta = tc_delta(th);
|
delta = tc_delta(th);
|
||||||
large_delta = th->th_large_delta;
|
large_delta = th->th_large_delta;
|
||||||
atomic_thread_fence_acq();
|
atomic_thread_fence_acq();
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
} while (gen == 0 || gen != th->th_generation);
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
#else
|
||||||
|
} while (gen != th->th_generation);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (__predict_false(delta >= large_delta)) {
|
if (__predict_false(delta >= large_delta)) {
|
||||||
/* Avoid overflow for scale * delta. */
|
/* Avoid overflow for scale * delta. */
|
||||||
@@ -1604,7 +1616,10 @@ _Timecounter_Windup(struct bintime *new_boottimebin,
|
|||||||
struct bintime bt;
|
struct bintime bt;
|
||||||
struct timecounter *tc;
|
struct timecounter *tc;
|
||||||
struct timehands *th, *tho;
|
struct timehands *th, *tho;
|
||||||
uint32_t delta, ncount, ogen;
|
uint32_t delta, ncount;
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
|
u_int ogen;
|
||||||
|
#endif
|
||||||
int i;
|
int i;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
@@ -1620,14 +1635,12 @@ _Timecounter_Windup(struct bintime *new_boottimebin,
|
|||||||
tho = timehands;
|
tho = timehands;
|
||||||
#if defined(RTEMS_SMP)
|
#if defined(RTEMS_SMP)
|
||||||
th = tho->th_next;
|
th = tho->th_next;
|
||||||
#else
|
|
||||||
th = tho;
|
|
||||||
#endif
|
|
||||||
ogen = th->th_generation;
|
ogen = th->th_generation;
|
||||||
th->th_generation = 0;
|
th->th_generation = 0;
|
||||||
atomic_thread_fence_rel();
|
atomic_thread_fence_rel();
|
||||||
#if defined(RTEMS_SMP)
|
|
||||||
memcpy(th, tho, offsetof(struct timehands, th_generation));
|
memcpy(th, tho, offsetof(struct timehands, th_generation));
|
||||||
|
#else
|
||||||
|
th = tho;
|
||||||
#endif
|
#endif
|
||||||
if (new_boottimebin != NULL)
|
if (new_boottimebin != NULL)
|
||||||
th->th_boottime = *new_boottimebin;
|
th->th_boottime = *new_boottimebin;
|
||||||
@@ -1727,6 +1740,7 @@ _Timecounter_Windup(struct bintime *new_boottimebin,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
/*
|
/*
|
||||||
* Now that the struct timehands is again consistent, set the new
|
* Now that the struct timehands is again consistent, set the new
|
||||||
* generation number, making sure to not make it zero.
|
* generation number, making sure to not make it zero.
|
||||||
@@ -1734,6 +1748,9 @@ _Timecounter_Windup(struct bintime *new_boottimebin,
|
|||||||
if (++ogen == 0)
|
if (++ogen == 0)
|
||||||
ogen = 1;
|
ogen = 1;
|
||||||
atomic_store_rel_int(&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. */
|
/* Go live with the new struct timehands. */
|
||||||
#ifdef FFCLOCK
|
#ifdef FFCLOCK
|
||||||
@@ -2226,27 +2243,38 @@ _Timecounter_Tick_simple(uint32_t delta, uint32_t offset,
|
|||||||
{
|
{
|
||||||
struct bintime bt;
|
struct bintime bt;
|
||||||
struct timehands *th;
|
struct timehands *th;
|
||||||
uint32_t ogen;
|
#if defined(RTEMS_SMP)
|
||||||
|
u_int ogen;
|
||||||
|
#endif
|
||||||
|
|
||||||
th = timehands;
|
th = timehands;
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
ogen = th->th_generation;
|
ogen = th->th_generation;
|
||||||
|
th->th_generation = 0;
|
||||||
|
atomic_thread_fence_rel();
|
||||||
|
#endif
|
||||||
|
|
||||||
th->th_offset_count = offset;
|
th->th_offset_count = offset;
|
||||||
bintime_addx(&th->th_offset, th->th_scale * delta);
|
bintime_addx(&th->th_offset, th->th_scale * delta);
|
||||||
|
|
||||||
bt = th->th_offset;
|
bt = th->th_offset;
|
||||||
bintime_add(&bt, &th->th_boottime);
|
bintime_add(&bt, &th->th_boottime);
|
||||||
|
|
||||||
/* Update the UTC timestamps used by the get*() functions. */
|
/* Update the UTC timestamps used by the get*() functions. */
|
||||||
th->th_bintime = bt;
|
th->th_bintime = bt;
|
||||||
bintime2timeval(&bt, &th->th_microtime);
|
bintime2timeval(&bt, &th->th_microtime);
|
||||||
bintime2timespec(&bt, &th->th_nanotime);
|
bintime2timespec(&bt, &th->th_nanotime);
|
||||||
|
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
/*
|
/*
|
||||||
* Now that the struct timehands is again consistent, set the new
|
* Now that the struct timehands is again consistent, set the new
|
||||||
* generation number, making sure to not make it zero.
|
* generation number, making sure to not make it zero.
|
||||||
*/
|
*/
|
||||||
if (++ogen == 0)
|
if (++ogen == 0)
|
||||||
ogen = 1;
|
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. */
|
/* Go live with the new struct timehands. */
|
||||||
time_second = th->th_microtime.tv_sec;
|
time_second = th->th_microtime.tv_sec;
|
||||||
|
|||||||
Reference in New Issue
Block a user