clock_systimer: 64-bit timer accesses are not atomic. Noted by Freddie Chopin.

This commit is contained in:
Gregory Nutt 2016-01-22 12:24:36 -06:00
parent 7ead6b4972
commit 84d4cb007b
3 changed files with 33 additions and 9 deletions

View File

@ -207,8 +207,11 @@ extern "C"
#ifdef __HAVE_KERNEL_GLOBALS
EXTERN volatile systime_t g_system_timer;
#ifndef CONFIG_SYSTEM_TIME64
# define clock_systimer() g_system_timer
#endif
#endif
/****************************************************************************
* Public Function Prototypes
@ -253,7 +256,10 @@ void clock_synchronize(void);
* Return the current value of the 32/64-bit system timer counter.
* Indirect access to the system timer counter is required through this
* function if the execution environment does not have direct access to
* kernel globaldata
* kernel global data.
*
* Use of this function is also required to assue atomic access to the
* 64-bit system timer.
*
* Parameters:
* None
@ -265,7 +271,7 @@ void clock_synchronize(void);
*
****************************************************************************/
#ifndef __HAVE_KERNEL_GLOBALS
#if !defined(__HAVE_KERNEL_GLOBALS) || defined(CONFIG_SYSTEM_TIME64)
systime_t clock_systimer(void);
#endif

View File

@ -1,7 +1,7 @@
############################################################################
# sched/clock/Make.defs
#
# Copyright (C) 2014 Gregory Nutt. All rights reserved.
# Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without

View File

@ -80,7 +80,8 @@
systime_t clock_systimer(void)
{
#ifdef CONFIG_SCHED_TICKLESS
#ifdef CONFIG_SYSTEM_TIME64
# ifdef CONFIG_SYSTEM_TIME64
struct timespec ts;
/* Get the time from the platform specific hardware */
@ -90,7 +91,9 @@ systime_t clock_systimer(void)
/* Convert to a 64-bit value in microseconds, then in clock tick units */
return USEC2TICK(1000000 * (uint64_t)ts.tv_sec + (uint64_t)ts.tv_nsec / 1000);
#else
# else /* CONFIG_SYSTEM_TIME64 */
struct timespec ts;
uint64_t tmp;
@ -98,16 +101,31 @@ systime_t clock_systimer(void)
(void)up_timer_gettime(&ts);
/* Convert to a 64- then 32-bit value */
/* Convert to a 64- then a 32-bit value */
tmp = MSEC2TICK(1000 * (uint64_t)ts.tv_sec + (uint64_t)ts.tv_nsec / 1000000);
return (systime_t)(tmp & 0x00000000ffffffff);
#endif
#else
# endif /* CONFIG_SYSTEM_TIME64 */
#else /* CONFIG_SCHED_TICKLESS */
# ifdef CONFIG_SYSTEM_TIME64
irqstate_t flags;
systime_t sample;
/* 64-bit accesses are not atomic on most architectures. */
flags = irqsave();
sample = g_system_timer;
irqrestore(flags);
return sample;
# else /* CONFIG_SYSTEM_TIME64 */
/* Return the current system time */
return g_system_timer;
#endif
# endif /* CONFIG_SYSTEM_TIME64 */
#endif /* CONFIG_SCHED_TICKLESS */
}