clock: adjust clock function to support tick

When CONFIG_SCHED_TICKLESS_TICK_ARGUMENT enabled, we can
use up_timer_gettick to get ticks for better performance.
This commit is contained in:
zhangyuan21
2022-09-26 10:11:16 +08:00
committed by Xiang Xiao
parent b118083c35
commit 8512ca74b1
2 changed files with 62 additions and 118 deletions
+58 -55
View File
@@ -75,67 +75,70 @@
clock_t clock_systime_ticks(void)
{
#ifdef CONFIG_SCHED_TICKLESS
# ifdef CONFIG_SYSTEM_TIME64
#ifdef CONFIG_RTC_HIRES
/* Do we have a high-resolution RTC that can provide us with the time? */
struct timespec ts;
/* Get the time from the platform specific hardware */
clock_systime_timespec(&ts);
/* Convert to a 64-bit value in microseconds, then in clock tick units */
return USEC2TICK(1000000 * (uint64_t)ts.tv_sec + ts.tv_nsec / 1000);
# else /* CONFIG_SYSTEM_TIME64 */
struct timespec ts;
uint64_t tmp;
/* Get the time from the platform specific hardware */
clock_systime_timespec(&ts);
/* Convert to a 64- then a 32-bit value */
tmp = USEC2TICK(1000000 * (uint64_t)ts.tv_sec + ts.tv_nsec / 1000);
return (clock_t)(tmp & TIMER_MASK32);
# endif /* CONFIG_SYSTEM_TIME64 */
#else /* CONFIG_SCHED_TICKLESS */
# ifdef CONFIG_SYSTEM_TIME64
clock_t sample;
clock_t verify;
/* 64-bit accesses are not atomic on most architectures. The following
* loop samples the 64-bit timer twice and loops in the rare event that
* there was 32-bit rollover between samples.
*
* If there is no 32-bit rollover, then:
*
* - The MS 32-bits of each sample will be the same, and
* - The LS 32-bits of the second sample will be greater than or equal to
* the LS 32-bits for the first sample.
*/
do
if (g_rtc_enabled)
{
verify = g_system_ticks;
sample = g_system_ticks;
struct timespec ts;
/* Get the time from the platform specific hardware */
clock_systime_timespec(&ts);
/* Convert to a 64-bit value in microseconds,
* then in clock tick units.
*/
return timespec_to_tick(&ts);
}
while ((sample & TIMER_MASK32) < (verify & TIMER_MASK32) ||
(sample & ~TIMER_MASK32) != (verify & ~TIMER_MASK32));
else
#endif
{
/* In tickless mode, all timing is controlled by platform-specific
* code. Let the platform timer do the work.
*/
return sample;
#if defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT)
clock_t ticks;
up_timer_gettick(&ticks);
return ticks;
#elif defined(CONFIG_SCHED_TICKLESS)
struct timespec ts;
up_timer_gettime(&ts);
return timespec_to_tick(&ts);
#elif defined(CONFIG_SYSTEM_TIME64)
# else /* CONFIG_SYSTEM_TIME64 */
clock_t sample;
clock_t verify;
/* Return the current system time */
/* 64-bit accesses are not atomic on most architectures. The following
* loop samples the 64-bit timer twice and loops in the rare event that
* there was 32-bit rollover between samples.
*
* If there is no 32-bit rollover, then:
*
* - The MS 32-bits of each sample will be the same, and
* - The LS 32-bits of the second sample will be greater than or equal
* to the LS 32-bits for the first sample.
*/
return g_system_ticks;
do
{
verify = g_system_ticks;
sample = g_system_ticks;
}
while ((sample & TIMER_MASK32) < (verify & TIMER_MASK32) ||
(sample & ~TIMER_MASK32) != (verify & ~TIMER_MASK32));
# endif /* CONFIG_SYSTEM_TIME64 */
#endif /* CONFIG_SCHED_TICKLESS */
return sample;
#else /* CONFIG_SYSTEM_TIME64 */
/* Return the current system time */
return g_system_ticks;
#endif /* CONFIG_SYSTEM_TIME64 */
}
}
+4 -63
View File
@@ -109,84 +109,25 @@ int clock_systime_timespec(FAR struct timespec *ts)
else
#endif
{
#if defined(CONFIG_SCHED_TICKLESS)
/* In tickless mode, all timing is controlled by platform-specific
* code. Let the platform timer do the work.
*/
#ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
#if defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT)
clock_t ticks;
int ret;
ret = up_timer_gettick(&ticks);
timespec_from_tick(ts, ticks);
return ret;
#else
#elif defined(CONFIG_SCHED_TICKLESS)
return up_timer_gettime(ts);
#endif
#elif defined(CONFIG_HAVE_LONG_LONG) && (CONFIG_USEC_PER_TICK % 1000) != 0
#else
/* 64-bit microsecond calculations should improve our accuracy
* when the clock period is in units of microseconds.
*/
uint64_t usecs;
uint64_t secs;
uint64_t nsecs;
/* Get the time since power-on in seconds and microseconds.
* NOTE that overflow is still possible if we use a 64-bit
* timer.
*/
usecs = (uint64_t)TICK2USEC(clock_systime_ticks());
secs = usecs / USEC_PER_SEC;
/* Return the elapsed time in seconds and nanoseconds */
nsecs = (usecs - (secs * USEC_PER_SEC)) * NSEC_PER_USEC;
ts->tv_sec = (time_t)secs;
ts->tv_nsec = (long)nsecs;
return OK;
#else
/* We know that the clock rate is in units of milliseconds
* show we should be able to do the calculations with less
* chance of overflow.
*
* 32-bit millisecond calculations should be just fine in
* most cases. For a 32-bit system timer and a clock period
* of 10 milliseconds, the msecs value will overflow at about
* 49.7 days.
*
* So.. we will still use 64-bit calculations if we have them
* in order to avoid that limitation.
*/
#ifdef CONFIG_HAVE_LONG_LONG
uint64_t msecs;
uint64_t secs;
uint64_t nsecs;
#define WIDE_CAST (uint64_t)
#else
clock_t msecs;
clock_t secs;
clock_t nsecs;
#define WIDE_CAST
#endif
/* Get the time since power-on in seconds and milliseconds */
msecs = TICK2MSEC(WIDE_CAST clock_systime_ticks());
secs = msecs / MSEC_PER_SEC;
/* Return the elapsed time in seconds and nanoseconds */
nsecs = (msecs - (secs * MSEC_PER_SEC)) * NSEC_PER_MSEC;
ts->tv_sec = (time_t)secs;
ts->tv_nsec = (long)nsecs;
timespec_from_tick(ts, clock_systime_ticks());
return OK;
#endif
}