[rtems commit] score: Avoid Giant lock for set time of day

Sebastian Huber sebh at rtems.org
Mon May 2 10:08:36 UTC 2016


Module:    rtems
Branch:    master
Commit:    1ef8e4a8e93a848e2a68f37e029039300f1c936b
Changeset: http://git.rtems.org/rtems/commit/?id=1ef8e4a8e93a848e2a68f37e029039300f1c936b

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Apr 27 22:07:56 2016 +0200

score: Avoid Giant lock for set time of day

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)




More information about the vc mailing list