[RTEMS Project] #2180: _TOD_Get_with_nanoseconds() is broken on SMP
RTEMS trac
trac at rtems.org
Thu Dec 11 07:06:55 UTC 2014
#2180: _TOD_Get_with_nanoseconds() is broken on SMP
-----------------------------+------------------------------
Reporter: sebastian.huber | Owner: sebastian.huber
Type: defect | Status: assigned
Priority: normal | Milestone: 5.0
Component: cpukit | Version: 4.11
Severity: normal | Resolution:
Keywords: |
-----------------------------+------------------------------
Changes (by sebastian.huber):
* owner: joel.sherrill => sebastian.huber
* status: new => assigned
* milestone: 4.11 => 5.0
Old description:
> We have
>
> Timestamp_Control *_TOD_Get_with_nanoseconds(
> Timestamp_Control *snapshot,
> const Timestamp_Control *clock
> )
> {
> TOD_Control *tod = &_TOD;
> ISR_lock_Context lock_context;
> Timestamp_Control offset;
> Timestamp_Control now;
> uint32_t nanoseconds;
>
> _TOD_Acquire( tod, &lock_context );
> nanoseconds = ( *tod->nanoseconds_since_last_tick )();
> now = *clock;
> _TOD_Release( tod, &lock_context );
>
> _Timestamp_Set( &offset, 0, nanoseconds );
> _Timestamp_Add_to( &now, &offset );
>
> *snapshot = now;
>
> return snapshot;
> }
>
> and
>
> void _TOD_Tickle_ticks( void )
> {
> TOD_Control *tod = &_TOD;
> ISR_lock_Context lock_context;
> Timestamp_Control tick;
> uint32_t nanoseconds_per_tick;
>
> nanoseconds_per_tick = rtems_configuration_get_nanoseconds_per_tick();
>
> /* Convert the tick quantum to a timestamp */
> _Timestamp_Set( &tick, 0, nanoseconds_per_tick );
>
> /* Update the counter of ticks since boot */
> _Watchdog_Ticks_since_boot += 1;
>
> _TOD_Acquire( tod, &lock_context );
>
> /* Update the uptime */
> _Timestamp_Add_to( &tod->uptime, &tick );
>
> /* Update the current TOD */
> _Timestamp_Add_to( &tod->now, &tick );
>
> _TOD_Release( tod, &lock_context );
>
> _TOD.seconds_trigger += nanoseconds_per_tick;
> if ( _TOD.seconds_trigger >= 1000000000UL ) {
> _TOD.seconds_trigger -= 1000000000UL;
> _Watchdog_Tickle_seconds();
> }
> }
>
> and (standard Clock driver)
>
> #if defined(BSP_FEATURE_IRQ_EXTENSION) || \
> (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
> void Clock_isr(void *arg)
> {
> #else
> rtems_isr Clock_isr(rtems_vector_number vector);
> rtems_isr Clock_isr(
> rtems_vector_number vector
> )
> {
> #endif
> /*
> * Accurate count of ISRs
> */
> Clock_driver_ticks += 1;
>
> #if CLOCK_DRIVER_USE_FAST_IDLE
> do {
> rtems_clock_tick();
> } while (
> _Thread_Heir == _Thread_Executing
> && _Thread_Executing->Start.entry_point
> == rtems_configuration_get_idle_task()
> );
>
> Clock_driver_support_at_tick();
> return;
> #else
> /*
> * Do the hardware specific per-tick action.
> *
> * The counter/timer may or may not be set to automatically reload.
> */
> Clock_driver_support_at_tick();
>
> #if CLOCK_DRIVER_ISRS_PER_TICK
> /*
> * The driver is multiple ISRs per clock tick.
> */
> if ( !Clock_driver_isrs ) {
> rtems_clock_tick();
>
> Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
> }
> Clock_driver_isrs--;
> #else
> /*
> * The driver is one ISR per clock tick.
> */
> rtems_clock_tick();
> #endif
> #endif
> }
>
> Suppose we are between Clock_driver_support_at_tick() and
> _TOD_Tickle_ticks(). Now call _TOD_Get_with_nanoseconds() on another
> processor. With most nanoseconds extensions we observe now a serviced
> hardware clock interrupt and the old _TOD.uptime value.
New description:
We have
Timestamp_Control *_TOD_Get_with_nanoseconds(
Timestamp_Control *snapshot,
const Timestamp_Control *clock
)
{
TOD_Control *tod = &_TOD;
ISR_lock_Context lock_context;
Timestamp_Control offset;
Timestamp_Control now;
uint32_t nanoseconds;
_TOD_Acquire( tod, &lock_context );
nanoseconds = ( *tod->nanoseconds_since_last_tick )();
now = *clock;
_TOD_Release( tod, &lock_context );
_Timestamp_Set( &offset, 0, nanoseconds );
_Timestamp_Add_to( &now, &offset );
*snapshot = now;
return snapshot;
}
and
void _TOD_Tickle_ticks( void )
{
TOD_Control *tod = &_TOD;
ISR_lock_Context lock_context;
Timestamp_Control tick;
uint32_t nanoseconds_per_tick;
nanoseconds_per_tick = rtems_configuration_get_nanoseconds_per_tick();
/* Convert the tick quantum to a timestamp */
_Timestamp_Set( &tick, 0, nanoseconds_per_tick );
/* Update the counter of ticks since boot */
_Watchdog_Ticks_since_boot += 1;
_TOD_Acquire( tod, &lock_context );
/* Update the uptime */
_Timestamp_Add_to( &tod->uptime, &tick );
/* Update the current TOD */
_Timestamp_Add_to( &tod->now, &tick );
_TOD_Release( tod, &lock_context );
_TOD.seconds_trigger += nanoseconds_per_tick;
if ( _TOD.seconds_trigger >= 1000000000UL ) {
_TOD.seconds_trigger -= 1000000000UL;
_Watchdog_Tickle_seconds();
}
}
and (standard Clock driver)
#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
(CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
void Clock_isr(void *arg)
{
#else
rtems_isr Clock_isr(rtems_vector_number vector);
rtems_isr Clock_isr(
rtems_vector_number vector
)
{
#endif
/*
* Accurate count of ISRs
*/
Clock_driver_ticks += 1;
#if CLOCK_DRIVER_USE_FAST_IDLE
do {
rtems_clock_tick();
} while (
_Thread_Heir == _Thread_Executing
&& _Thread_Executing->Start.entry_point
== rtems_configuration_get_idle_task()
);
Clock_driver_support_at_tick();
return;
#else
/*
* Do the hardware specific per-tick action.
*
* The counter/timer may or may not be set to automatically reload.
*/
Clock_driver_support_at_tick();
#if CLOCK_DRIVER_ISRS_PER_TICK
/*
* The driver is multiple ISRs per clock tick.
*/
if ( !Clock_driver_isrs ) {
rtems_clock_tick();
Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
}
Clock_driver_isrs--;
#else
/*
* The driver is one ISR per clock tick.
*/
rtems_clock_tick();
#endif
#endif
}
Suppose we are between Clock_driver_support_at_tick() and
_TOD_Tickle_ticks(). Now call _TOD_Get_with_nanoseconds() on another
processor. With most nanoseconds extensions we observe now a serviced
hardware clock interrupt and the old _TOD.uptime value.
--
--
Ticket URL: <http://devel.rtems.org/ticket/2180#comment:2>
RTEMS Project <http://www.rtems.org/>
RTEMS Project
More information about the bugs
mailing list