From 2145853b009e939dfbe14869b710133f50500a26 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 23 Dec 2015 07:29:47 +0100 Subject: score: Fix simple timecounter support Close #2502. --- cpukit/rtems/src/clocktick.c | 6 ++++- cpukit/sapi/include/rtems/timecounter.h | 35 +++++++++++++++++++++----- cpukit/score/include/rtems/score/timecounter.h | 27 ++++++++++++++++++-- cpukit/score/src/kern_tc.c | 16 ++++++------ 4 files changed, 67 insertions(+), 17 deletions(-) (limited to 'cpukit') diff --git a/cpukit/rtems/src/clocktick.c b/cpukit/rtems/src/clocktick.c index e2cd35f5fc..a6bf26d1a4 100644 --- a/cpukit/rtems/src/clocktick.c +++ b/cpukit/rtems/src/clocktick.c @@ -23,9 +23,13 @@ rtems_status_code rtems_clock_tick( void ) { + ISR_lock_Context lock_context; + + _Timecounter_Acquire( &lock_context ); _Timecounter_Tick_simple( rtems_configuration_get_microseconds_per_tick(), - 0 + 0, + &lock_context ); return RTEMS_SUCCESSFUL; diff --git a/cpukit/sapi/include/rtems/timecounter.h b/cpukit/sapi/include/rtems/timecounter.h index 04bc534d55..db0a7eee72 100644 --- a/cpukit/sapi/include/rtems/timecounter.h +++ b/cpukit/sapi/include/rtems/timecounter.h @@ -93,6 +93,13 @@ typedef struct { uint32_t binary_interval; } rtems_timecounter_simple; +/** + * @brief At tick handling done under protection of the timecounter lock. + */ +typedef void rtems_timecounter_simple_at_tick( + rtems_timecounter_simple *tc +); + /** * @brief Returns the current value of a simple timecounter. */ @@ -199,20 +206,28 @@ RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_scale( * * @param[in] tc The simple timecounter. * @param[in] get The method to get the value of the simple timecounter. + * @param[in] at_tick The method to perform work under timecounter lock + * protection at this tick, e.g. clear a pending flag. */ RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_downcounter_tick( - rtems_timecounter_simple *tc, - rtems_timecounter_simple_get get + rtems_timecounter_simple *tc, + rtems_timecounter_simple_get get, + rtems_timecounter_simple_at_tick at_tick ) { + ISR_lock_Context lock_context; uint32_t current; + _Timecounter_Acquire( &lock_context ); + + ( *at_tick )( tc ); + current = rtems_timecounter_simple_scale( tc, tc->real_interval - ( *get )( tc ) ); - _Timecounter_Tick_simple( tc->binary_interval, current ); + _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context ); } /** @@ -220,17 +235,25 @@ RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_downcounter_tick( * * @param[in] tc The simple timecounter. * @param[in] get The method to get the value of the simple timecounter. + * @param[in] at_tick The method to perform work under timecounter lock + * protection at this tick, e.g. clear a pending flag. */ RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_upcounter_tick( - rtems_timecounter_simple *tc, - rtems_timecounter_simple_get get + rtems_timecounter_simple *tc, + rtems_timecounter_simple_get get, + rtems_timecounter_simple_at_tick at_tick ) { + ISR_lock_Context lock_context; uint32_t current; + _Timecounter_Acquire( &lock_context ); + + ( *at_tick )( tc ); + current = rtems_timecounter_simple_scale( tc, ( *get )( tc ) ); - _Timecounter_Tick_simple( tc->binary_interval, current ); + _Timecounter_Tick_simple( tc->binary_interval, current, &lock_context ); } /** diff --git a/cpukit/score/include/rtems/score/timecounter.h b/cpukit/score/include/rtems/score/timecounter.h index 0d17cc7ce3..33de269ec8 100644 --- a/cpukit/score/include/rtems/score/timecounter.h +++ b/cpukit/score/include/rtems/score/timecounter.h @@ -26,6 +26,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -160,6 +162,21 @@ void _Timecounter_Install( struct timecounter *tc ); */ void _Timecounter_Tick( void ); +/** + * @brief Lock to protect the timecounter mechanic. + */ +ISR_LOCK_DECLARE( extern, _Timecounter_Lock ) + +/** + * @brief Acquires the timecounter lock. + * + * @param[in] lock_context The lock context. + * + * See _Timecounter_Tick_simple(). + */ +#define _Timecounter_Acquire( lock_context ) \ + _ISR_lock_ISR_disable_and_acquire( &_Timecounter_Lock, lock_context ) + /** * @brief Performs a simple timecounter tick. * @@ -169,8 +186,14 @@ void _Timecounter_Tick( void ); * @param[in] delta The time in timecounter ticks elapsed since the last call * to _Timecounter_Tick_simple(). * @param[in] offset The current value of the timecounter. - */ -void _Timecounter_Tick_simple( uint32_t delta, uint32_t offset ); + * @param[in] lock_context The lock context of the corresponding + * _Timecounter_Acquire(). + */ +void _Timecounter_Tick_simple( + uint32_t delta, + uint32_t offset, + ISR_lock_Context *lock_context +); /** * @brief The wall clock time in seconds. diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c index f6a1136d31..4257533455 100644 --- a/cpukit/score/src/kern_tc.c +++ b/cpukit/score/src/kern_tc.c @@ -64,7 +64,9 @@ __FBSDID("$FreeBSD r284178 2015-06-09T11:49:56Z$"); #ifdef __rtems__ #include #include -ISR_LOCK_DEFINE(static, _Timecounter_Lock, "Timecounter"); +ISR_LOCK_DEFINE(, _Timecounter_Lock, "Timecounter") +#define _Timecounter_Release(lock_context) \ + _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, lock_context) #define hz rtems_clock_get_ticks_per_second() #define printf(...) #define log(...) @@ -1383,7 +1385,7 @@ tc_windup(void) #ifdef __rtems__ ISR_lock_Context lock_context; - _ISR_lock_ISR_disable_and_acquire(&_Timecounter_Lock, &lock_context); + _Timecounter_Acquire(&lock_context); #endif /* __rtems__ */ /* @@ -1538,7 +1540,7 @@ tc_windup(void) timekeep_push_vdso(); #endif /* __rtems__ */ #ifdef __rtems__ - _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, &lock_context); + _Timecounter_Release(&lock_context); #endif /* __rtems__ */ } @@ -1963,14 +1965,12 @@ _Timecounter_Tick(void) } #ifdef __rtems__ void -_Timecounter_Tick_simple(uint32_t delta, uint32_t offset) +_Timecounter_Tick_simple(uint32_t delta, uint32_t offset, + ISR_lock_Context *lock_context) { struct bintime bt; struct timehands *th; uint32_t ogen; - ISR_lock_Context lock_context; - - _ISR_lock_ISR_disable_and_acquire(&_Timecounter_Lock, &lock_context); th = timehands; ogen = th->th_generation; @@ -1997,7 +1997,7 @@ _Timecounter_Tick_simple(uint32_t delta, uint32_t offset) time_second = th->th_microtime.tv_sec; time_uptime = th->th_offset.sec; - _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, &lock_context); + _Timecounter_Release(lock_context); _Watchdog_Tick(); } -- cgit v1.2.3