[PATCH 15/19] score: Avoid Giant lock for set time of day
Sebastian Huber
sebastian.huber at embedded-brains.de
Fri Apr 29 09:13:15 UTC 2016
Update #2555.
Update #2630.
---
cpukit/posix/src/adjtime.c | 2 +-
cpukit/posix/src/clocksettime.c | 6 +--
cpukit/rtems/src/clockset.c | 17 ++++----
cpukit/score/include/rtems/score/timecounterimpl.h | 5 ++-
cpukit/score/include/rtems/score/todimpl.h | 34 ++++++++++++++--
cpukit/score/src/coretodadjust.c | 22 ++++------
cpukit/score/src/coretodset.c | 14 +++----
cpukit/score/src/kern_tc.c | 47 +++++++++++++---------
8 files changed, 89 insertions(+), 58 deletions(-)
diff --git a/cpukit/posix/src/adjtime.c b/cpukit/posix/src/adjtime.c
index 1ebecce..32d1992 100644
--- a/cpukit/posix/src/adjtime.c
+++ b/cpukit/posix/src/adjtime.c
@@ -82,7 +82,7 @@ int adjtime(
/*
* Now apply the adjustment
*/
- _TOD_Adjust( delta_as_timestamp );
+ _TOD_Adjust( &delta_as_timestamp );
return 0;
}
diff --git a/cpukit/posix/src/clocksettime.c b/cpukit/posix/src/clocksettime.c
index 4d3be3b..8eb616c 100644
--- a/cpukit/posix/src/clocksettime.c
+++ b/cpukit/posix/src/clocksettime.c
@@ -19,9 +19,7 @@
#endif
#include <time.h>
-#include <errno.h>
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
#include <rtems/seterr.h>
@@ -41,9 +39,7 @@ int clock_settime(
if ( tp->tv_sec < TOD_SECONDS_1970_THROUGH_1988 )
rtems_set_errno_and_return_minus_one( EINVAL );
- _Thread_Disable_dispatch();
- _TOD_Set_with_timespec( tp );
- _Thread_Enable_dispatch();
+ _TOD_Set_with_timespec( tp );
}
#ifdef _POSIX_CPUTIME
else if ( clock_id == CLOCK_PROCESS_CPUTIME_ID )
diff --git a/cpukit/rtems/src/clockset.c b/cpukit/rtems/src/clockset.c
index 8d065b4..f0300cc 100644
--- a/cpukit/rtems/src/clockset.c
+++ b/cpukit/rtems/src/clockset.c
@@ -19,7 +19,6 @@
#endif
#include <rtems/rtems/clock.h>
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
#include <rtems/config.h>
@@ -32,15 +31,19 @@ rtems_status_code rtems_clock_set(
if ( _TOD_Validate( tod ) ) {
Timestamp_Control tod_as_timestamp;
- uint32_t seconds = _TOD_To_seconds( tod );
- uint32_t nanoseconds = tod->ticks
- * rtems_configuration_get_nanoseconds_per_tick();
+ uint32_t seconds;
+ uint32_t nanoseconds;
+ ISR_lock_Context lock_context;
+ seconds = _TOD_To_seconds( tod );
+ nanoseconds = tod->ticks
+ * rtems_configuration_get_nanoseconds_per_tick();
_Timestamp_Set( &tod_as_timestamp, seconds, nanoseconds );
- _Thread_Disable_dispatch();
- _TOD_Set( &tod_as_timestamp );
- _Thread_Enable_dispatch();
+ _TOD_Lock();
+ _TOD_Acquire( &lock_context );
+ _TOD_Set( &tod_as_timestamp, &lock_context );
+ _TOD_Unlock();
return RTEMS_SUCCESSFUL;
}
diff --git a/cpukit/score/include/rtems/score/timecounterimpl.h b/cpukit/score/include/rtems/score/timecounterimpl.h
index 82ade23..a48ac70 100644
--- a/cpukit/score/include/rtems/score/timecounterimpl.h
+++ b/cpukit/score/include/rtems/score/timecounterimpl.h
@@ -36,7 +36,10 @@ extern "C" {
* @{
*/
-void _Timecounter_Set_clock( const struct timespec *ts );
+void _Timecounter_Set_clock(
+ const struct bintime *bt,
+ ISR_lock_Context *lock_context
+);
/** @} */
diff --git a/cpukit/score/include/rtems/score/todimpl.h b/cpukit/score/include/rtems/score/todimpl.h
index 2b07823..f53e365 100644
--- a/cpukit/score/include/rtems/score/todimpl.h
+++ b/cpukit/score/include/rtems/score/todimpl.h
@@ -19,6 +19,7 @@
#define _RTEMS_SCORE_TODIMPL_H
#include <rtems/score/tod.h>
+#include <rtems/score/apimutex.h>
#include <rtems/score/timestamp.h>
#include <rtems/score/timecounterimpl.h>
#include <rtems/score/watchdog.h>
@@ -142,14 +143,36 @@ typedef struct {
extern TOD_Control _TOD;
+static inline void _TOD_Lock( void )
+{
+ /* FIXME: https://devel.rtems.org/ticket/2630 */
+ _API_Mutex_Lock( _Once_Mutex );
+}
+
+static inline void _TOD_Unlock( void )
+{
+ _API_Mutex_Unlock( _Once_Mutex );
+}
+
+static inline void _TOD_Acquire( ISR_lock_Context *lock_context )
+{
+ _Timecounter_Acquire( lock_context );
+}
+
/**
* @brief Sets the time of day.
*
+ * The caller must be the owner of the TOD lock.
+ *
* @param tod_as_timestamp The new time of day in timestamp format representing
* the time since UNIX Epoch.
+ * @param lock_context The ISR lock context used for the corresponding
+ * _TOD_Acquire(). The caller must be the owner of the TOD lock. This
+ * function will release the TOD lock.
*/
void _TOD_Set(
- const Timestamp_Control *tod_as_timestamp
+ const Timestamp_Control *tod_as_timestamp,
+ ISR_lock_Context *lock_context
);
/**
@@ -164,13 +187,18 @@ static inline void _TOD_Set_with_timespec(
)
{
Timestamp_Control tod_as_timestamp;
+ ISR_lock_Context lock_context;
_Timestamp_Set(
&tod_as_timestamp,
tod_as_timespec->tv_sec,
tod_as_timespec->tv_nsec
);
- _TOD_Set( &tod_as_timestamp );
+
+ _TOD_Lock();
+ _TOD_Acquire( &lock_context );
+ _TOD_Set( &tod_as_timestamp, &lock_context );
+ _TOD_Unlock();
}
/**
@@ -296,7 +324,7 @@ RTEMS_INLINE_ROUTINE void _TOD_Get_timeval(
* @param[in] delta is the amount to adjust
*/
void _TOD_Adjust(
- const Timestamp_Control timestamp
+ const Timestamp_Control *delta
);
/**
diff --git a/cpukit/score/src/coretodadjust.c b/cpukit/score/src/coretodadjust.c
index 51c10ec..5996565 100644
--- a/cpukit/score/src/coretodadjust.c
+++ b/cpukit/score/src/coretodadjust.c
@@ -18,14 +18,14 @@
#include "config.h"
#endif
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
void _TOD_Adjust(
- const Timestamp_Control delta
+ const Timestamp_Control *delta
)
{
Timestamp_Control tod;
+ ISR_lock_Context lock_context;
/*
* Currently, RTEMS does the adjustment in one movement.
@@ -35,16 +35,10 @@ void _TOD_Adjust(
* adjustment.
*/
- /*
- * This prevents context switches while we are adjusting the TOD
- */
- _Thread_Disable_dispatch();
-
- _TOD_Get( &tod );
-
- _Timestamp_Add_to( &tod, &delta );
-
- _TOD_Set( &tod );
-
- _Thread_Enable_dispatch();
+ _TOD_Lock();
+ _TOD_Acquire( &lock_context );
+ _TOD_Get( &tod );
+ _Timestamp_Add_to( &tod, delta );
+ _TOD_Set( &tod, &lock_context );
+ _TOD_Unlock();
}
diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c
index e11f47c..f1d2e36 100644
--- a/cpukit/score/src/coretodset.c
+++ b/cpukit/score/src/coretodset.c
@@ -19,11 +19,12 @@
#endif
#include <rtems/score/todimpl.h>
-#include <rtems/score/threaddispatch.h>
+#include <rtems/score/assert.h>
#include <rtems/score/watchdogimpl.h>
void _TOD_Set(
- const Timestamp_Control *tod_as_timestamp
+ const Timestamp_Control *tod_as_timestamp,
+ ISR_lock_Context *lock_context
)
{
struct timespec tod_as_timespec;
@@ -31,12 +32,11 @@ void _TOD_Set(
uint32_t cpu_count;
uint32_t cpu_index;
- _Timestamp_To_timespec( tod_as_timestamp, &tod_as_timespec );
-
- _Thread_Disable_dispatch();
+ _Assert( _API_Mutex_Is_owner( _Once_Mutex ) );
- _Timecounter_Set_clock( &tod_as_timespec );
+ _Timecounter_Set_clock( tod_as_timestamp, lock_context );
+ _Timestamp_To_timespec( tod_as_timestamp, &tod_as_timespec );
tod_as_ticks = _Watchdog_Ticks_from_timespec( &tod_as_timespec );
cpu_count = _SMP_Get_processor_count();
@@ -47,6 +47,4 @@ void _TOD_Set(
}
_TOD.is_set = true;
-
- _Thread_Enable_dispatch();
}
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index b9ea608..03d0997 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -33,6 +33,7 @@
#define time_uptime _Timecounter_Time_uptime
#define boottimebin _Timecounter_Boottimebin
#include <rtems/score/timecounterimpl.h>
+#include <rtems/score/smp.h>
#include <rtems/score/todimpl.h>
#include <rtems/score/watchdogimpl.h>
#endif /* __rtems__ */
@@ -215,6 +216,8 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, alloweddeviation,
static void tc_windup(void);
#ifndef __rtems__
static void cpu_tick_calibrate(int);
+#else /* __rtems__ */
+static void _Timecounter_Windup(ISR_lock_Context *lock_context);
#endif /* __rtems__ */
void dtrace_getnanotime(struct timespec *tsp);
@@ -1344,12 +1347,12 @@ tc_getfrequency(void)
* when we booted.
* XXX: not locked.
*/
-#ifndef __rtems__
void
+#ifndef __rtems__
tc_setclock(struct timespec *ts)
#else /* __rtems__ */
-void
-_Timecounter_Set_clock(const struct timespec *ts)
+_Timecounter_Set_clock(const struct bintime *_bt,
+ ISR_lock_Context *lock_context)
#endif /* __rtems__ */
{
#ifndef __rtems__
@@ -1360,19 +1363,19 @@ _Timecounter_Set_clock(const struct timespec *ts)
#ifndef __rtems__
cpu_tick_calibrate(1);
nanotime(&tbef);
-#endif /* __rtems__ */
timespec2bintime(ts, &bt);
+#else /* __rtems__ */
+ bt = *_bt;
+#endif /* __rtems__ */
binuptime(&bt2);
bintime_sub(&bt, &bt2);
bintime_add(&bt2, &boottimebin);
boottimebin = bt;
#ifndef __rtems__
bintime2timeval(&bt, &boottime);
-#endif /* __rtems__ */
/* XXX fiddle all the little crinkly bits around the fiords... */
tc_windup();
-#ifndef __rtems__
nanotime(&taft);
if (timestepwarnings) {
log(LOG_INFO,
@@ -1382,6 +1385,8 @@ _Timecounter_Set_clock(const struct timespec *ts)
(intmax_t)ts->tv_sec, ts->tv_nsec);
}
cpu_tick_calibrate(1);
+#else /* __rtems__ */
+ _Timecounter_Windup(lock_context);
#endif /* __rtems__ */
}
@@ -1392,6 +1397,17 @@ _Timecounter_Set_clock(const struct timespec *ts)
*/
static void
tc_windup(void)
+#ifdef __rtems__
+{
+ ISR_lock_Context lock_context;
+
+ _Timecounter_Acquire(&lock_context);
+ _Timecounter_Windup(&lock_context);
+}
+
+static void
+_Timecounter_Windup(ISR_lock_Context *lock_context)
+#endif /* __rtems__ */
{
struct bintime bt;
struct timehands *th, *tho;
@@ -1399,11 +1415,6 @@ tc_windup(void)
uint32_t delta, ncount, ogen;
int i;
time_t t;
-#ifdef __rtems__
- ISR_lock_Context lock_context;
-
- _Timecounter_Acquire(&lock_context);
-#endif /* __rtems__ */
/*
* Make the next timehands a copy of the current one, but do not
@@ -1565,7 +1576,7 @@ tc_windup(void)
timekeep_push_vdso();
#endif /* __rtems__ */
#ifdef __rtems__
- _Timecounter_Release(&lock_context);
+ _Timecounter_Release(lock_context);
#endif /* __rtems__ */
}
@@ -1978,23 +1989,21 @@ tc_ticktock(int cnt)
if (count < tc_tick)
return;
count = 0;
+ tc_windup();
+}
#else /* __rtems__ */
-#include <rtems/score/smp.h>
void
_Timecounter_Tick(void)
{
Per_CPU_Control *cpu_self = _Per_CPU_Get();
if (_Per_CPU_Is_boot_processor(cpu_self)) {
-#endif /* __rtems__ */
- tc_windup();
-#ifdef __rtems__
- };
+ tc_windup();
+ }
_Watchdog_Tick(cpu_self);
-#endif /* __rtems__ */
}
-#ifdef __rtems__
+
void
_Timecounter_Tick_simple(uint32_t delta, uint32_t offset,
ISR_lock_Context *lock_context)
--
1.8.4.5
More information about the devel
mailing list