mirror of
https://github.com/apache/nuttx.git
synced 2026-05-19 20:06:24 +08:00
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:
@@ -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 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user