[PATCH] Add TOD Hooks to allow BSP to take action when TOD is set

Joel Sherrill joel at rtems.org
Wed Nov 13 13:46:41 UTC 2019


Two use cases were envisioned for this.

1) a BSP or application which desires to update a real-time clock
   when the RTEMS TOD is set.

2) a paravirtualized BSP can use this to propagate setting the time
   in an RTEMS application to the hosting environment. This enables
   the entire set of applications in the virtualized environments
   to have a single consistent TOD.
---
 cpukit/Makefile.am                                 |   4 +
 cpukit/include/rtems/score/todimpl.h               |  97 +++++-
 cpukit/posix/src/clocksettime.c                    |  16 +-
 cpukit/rtems/src/clockset.c                        |   9 +-
 cpukit/score/src/coretodhookdata.c                 |  45 +++
 cpukit/score/src/coretodhookregister.c             |  60 ++++
 cpukit/score/src/coretodhookrun.c                  |  69 +++++
 cpukit/score/src/coretodhookunregister.c           |  59 ++++
 cpukit/score/src/coretodset.c                      |  10 +-
 testsuites/sptests/Makefile.am                     |   9 +
 testsuites/sptests/configure.ac                    |   1 +
 testsuites/sptests/spclock_todhook01/init.c        | 334 +++++++++++++++++++++
 .../spclock_todhook01/spclock_todhook01.doc        |  35 +++
 .../spclock_todhook01/spclock_todhook01.scn        |   0
 14 files changed, 740 insertions(+), 8 deletions(-)
 create mode 100644 cpukit/score/src/coretodhookdata.c
 create mode 100644 cpukit/score/src/coretodhookregister.c
 create mode 100644 cpukit/score/src/coretodhookrun.c
 create mode 100644 cpukit/score/src/coretodhookunregister.c
 create mode 100644 testsuites/sptests/spclock_todhook01/init.c
 create mode 100644 testsuites/sptests/spclock_todhook01/spclock_todhook01.doc
 create mode 100644 testsuites/sptests/spclock_todhook01/spclock_todhook01.scn

diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 7698fe5..8cf5fb8 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -981,6 +981,10 @@ librtemscpu_a_SOURCES += score/src/coretodset.c
 librtemscpu_a_SOURCES += score/src/coretodtickspersec.c
 librtemscpu_a_SOURCES += score/src/coretodadjust.c
 librtemscpu_a_SOURCES += score/src/watchdoginsert.c
+librtemscpu_a_SOURCES += score/src/coretodhookdata.c
+librtemscpu_a_SOURCES += score/src/coretodhookregister.c
+librtemscpu_a_SOURCES += score/src/coretodhookrun.c
+librtemscpu_a_SOURCES += score/src/coretodhookunregister.c
 librtemscpu_a_SOURCES += score/src/watchdogremove.c
 librtemscpu_a_SOURCES += score/src/watchdogtick.c
 librtemscpu_a_SOURCES += score/src/watchdogtickssinceboot.c
diff --git a/cpukit/include/rtems/score/todimpl.h b/cpukit/include/rtems/score/todimpl.h
index 0d4faac..36e66a0 100644
--- a/cpukit/include/rtems/score/todimpl.h
+++ b/cpukit/include/rtems/score/todimpl.h
@@ -141,6 +141,9 @@ typedef struct {
   bool is_set;
 } TOD_Control;
 
+/**
+ * @brief TOD Management information
+ */
 extern TOD_Control _TOD;
 
 /**
@@ -183,8 +186,11 @@ static inline void _TOD_Acquire( ISR_lock_Context *lock_context )
  * @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.
+ *
+ * @retval true on success
+ * @retval false on failure
  */
-void _TOD_Set(
+bool _TOD_Set(
   const struct timespec *tod,
   ISR_lock_Context      *lock_context
 );
@@ -320,6 +326,95 @@ RTEMS_INLINE_ROUTINE bool _TOD_Is_set( void )
 
 /** @} */
 
+/**
+ * @defgroup RTEMSScoreTODHooks Time of Day Handler Action Hooks
+ *
+ * @ingroup RTEMSScoreTOD
+ *
+ * @brief Time of Day Handler Action Hooks
+ *
+ * The following support registering a hook which is invoked
+ * when the TOD is set. These can be used by a paravirtualized
+ * BSP to mirror time changes to the hosting environment or a
+ * regular BSP to program a real-time clock when the RTEMS TOD
+ * is set.
+ *
+ * @{
+ */
+
+/**
+ *  @brief Possible actions where a registered hook could be invoked
+ */
+typedef enum {
+  /**
+   *  @brief Constant to indicate the TOD is being set.
+   */
+  TOD_ACTION_SET_CLOCK
+} TOD_Action;
+
+/**
+ * @brief Structure to manage each TOD action hook
+ */
+typedef struct TOD_Hook {
+  /** This is the chain node portion of an object. */
+  Chain_Node Node;
+
+  /** This is the TOD action hook that is invoked. */
+  bool (*handler)(TOD_Action, const struct timespec *);
+} TOD_Hook;
+
+/**
+ * @brief Set of registered methods for TOD Actions
+ */
+extern Chain_Control _TOD_Hooks;
+
+/**
+ * @brief Add a TOD Action Hook
+ *
+ * This method is used to add a hook to the TOD action set.
+ *
+ * @brief hook is the action hook to register.
+ *
+ * @retval true if the hook is added. 
+ * @retval false if the hook cannot be added. 
+ */
+bool _TOD_Hook_Register(
+  TOD_Hook *hook
+);
+
+/**
+ * @brief Remove a TOD Action Hook
+ *
+ * This method is used to remove a hook from the TOD action set.
+ *
+ * @brief hook is the action hook to unregister.
+ *
+ * @retval true if the hook is unregister. 
+ * @retval false if the hook cannot be unregister. 
+ */
+bool _TOD_Hook_Unregister(
+  TOD_Hook *hook
+);
+
+/**
+ * @brief Run the TOD Action Hooks
+ *
+ * This method is used to invoke the set of TOD action hooks.
+ *
+ * @brief action is the action which triggered this run.
+ * @brief tod is the current tod
+ *
+ * @retval true if the hooks can be run. 
+ * @retval false if the hook cannot be run. 
+ */
+bool _TOD_Hook_Run(
+  TOD_Action             action,
+  const struct timespec *tod
+);
+
+
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/posix/src/clocksettime.c b/cpukit/posix/src/clocksettime.c
index a0fdd91..bfae46f 100644
--- a/cpukit/posix/src/clocksettime.c
+++ b/cpukit/posix/src/clocksettime.c
@@ -32,6 +32,8 @@ int clock_settime(
   const struct timespec *tp
 )
 {
+  bool  retval;
+
   if ( !tp )
     rtems_set_errno_and_return_minus_one( EINVAL );
 
@@ -43,19 +45,25 @@ int clock_settime(
 
     _TOD_Lock();
     _TOD_Acquire( &lock_context );
-    _TOD_Set( tp, &lock_context );
+      retval = _TOD_Set( tp, &lock_context );
     _TOD_Unlock();
+    if ( retval == false ) {
+      rtems_set_errno_and_return_minus_one( EPERM );
+    }
   }
 #ifdef _POSIX_CPUTIME
-  else if ( clock_id == CLOCK_PROCESS_CPUTIME_ID )
+  else if ( clock_id == CLOCK_PROCESS_CPUTIME_ID ) {
     rtems_set_errno_and_return_minus_one( ENOSYS );
+  }
 #endif
 #ifdef _POSIX_THREAD_CPUTIME
-  else if ( clock_id == CLOCK_THREAD_CPUTIME_ID )
+  else if ( clock_id == CLOCK_THREAD_CPUTIME_ID ) {
     rtems_set_errno_and_return_minus_one( ENOSYS );
+  }
 #endif
-  else
+  else {
     rtems_set_errno_and_return_minus_one( EINVAL );
+  }
 
   return 0;
 }
diff --git a/cpukit/rtems/src/clockset.c b/cpukit/rtems/src/clockset.c
index d772682..a885fe1 100644
--- a/cpukit/rtems/src/clockset.c
+++ b/cpukit/rtems/src/clockset.c
@@ -26,6 +26,8 @@ rtems_status_code rtems_clock_set(
   const rtems_time_of_day *tod
 )
 {
+  bool retval;
+
   if ( !tod )
     return RTEMS_INVALID_ADDRESS;
 
@@ -39,10 +41,13 @@ rtems_status_code rtems_clock_set(
 
     _TOD_Lock();
     _TOD_Acquire( &lock_context );
-    _TOD_Set( &tod_as_timespec, &lock_context );
+    retval = _TOD_Set( &tod_as_timespec, &lock_context );
     _TOD_Unlock();
 
-    return RTEMS_SUCCESSFUL;
+    if ( retval == true ) {
+      return RTEMS_SUCCESSFUL;
+    }
+    return RTEMS_IO_ERROR;
   }
 
   return RTEMS_INVALID_CLOCK;
diff --git a/cpukit/score/src/coretodhookdata.c b/cpukit/score/src/coretodhookdata.c
new file mode 100644
index 0000000..6e7bcff
--- /dev/null
+++ b/cpukit/score/src/coretodhookdata.c
@@ -0,0 +1,45 @@
+/**
+ * @file
+ *
+ * @brief TOD Hook Set
+ *
+ * @ingroup RTEMSScoreTODHooks
+ */
+
+/*
+ *  SPDX-License-Identifier: BSD-2-Clause
+ *
+ *  COPYRIGHT (c) 2019.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/todimpl.h>
+#include <rtems/score/chainimpl.h>
+ 
+Chain_Control _TOD_Hooks = CHAIN_INITIALIZER_EMPTY(_TOD_Hooks);
+
diff --git a/cpukit/score/src/coretodhookregister.c b/cpukit/score/src/coretodhookregister.c
new file mode 100644
index 0000000..64cfdc9
--- /dev/null
+++ b/cpukit/score/src/coretodhookregister.c
@@ -0,0 +1,60 @@
+/**
+ * @file
+ *
+ * @brief Register Hook to be in TOD Hook Set
+ *
+ * @ingroup RTEMSScoreTODHooks
+ */
+
+/*
+ *  SPDX-License-Identifier: BSD-2-Clause
+ *
+ *  COPYRIGHT (c) 2019.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/todimpl.h>
+#include <rtems/score/chainimpl.h>
+ 
+bool _TOD_Hook_Register(
+  TOD_Hook *hook
+)
+{
+  ISR_lock_Context lock_context;
+
+  if ( hook == NULL ) {
+    return FALSE;
+  }
+
+  _TOD_Lock();
+  _TOD_Acquire( &lock_context );
+    _Chain_Append_unprotected( &_TOD_Hooks, &hook->Node );
+  _TOD_Unlock();
+  return true;
+}
+
diff --git a/cpukit/score/src/coretodhookrun.c b/cpukit/score/src/coretodhookrun.c
new file mode 100644
index 0000000..731dd9c
--- /dev/null
+++ b/cpukit/score/src/coretodhookrun.c
@@ -0,0 +1,69 @@
+/**
+ * @file
+ *
+ * @brief Run TOD Hook Set
+ *
+ * @ingroup RTEMSScoreTODHooks
+ */
+
+/*
+ *  SPDX-License-Identifier: BSD-2-Clause
+ *
+ *  COPYRIGHT (c) 2019.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/todimpl.h>
+#include <rtems/score/chainimpl.h>
+
+bool _TOD_Hook_Run(
+  TOD_Action             action,
+  const struct timespec *tod
+)
+{
+  ISR_lock_Context   lock_context;
+  Chain_Node        *the_node;
+  bool               retval = true;
+
+  _TOD_Lock();
+  _TOD_Acquire( &lock_context );
+    for ( the_node = _Chain_First( &_TOD_Hooks );
+	  !_Chain_Is_tail( &_TOD_Hooks, the_node ) ;
+	  the_node = the_node->next ) {
+      TOD_Hook *the_hook = (TOD_Hook *) the_node;
+   
+      retval = (the_hook->handler)( action, tod );
+      if ( retval == false ) {
+        break;
+      }
+    }
+  _TOD_Unlock();
+
+  return retval;
+}
+
diff --git a/cpukit/score/src/coretodhookunregister.c b/cpukit/score/src/coretodhookunregister.c
new file mode 100644
index 0000000..a766c46
--- /dev/null
+++ b/cpukit/score/src/coretodhookunregister.c
@@ -0,0 +1,59 @@
+/**
+ * @file
+ *
+ * @brief Remove Hook from TOD Hook Set
+ *
+ * @ingroup RTEMSScoreTODHooks
+ */
+
+/*
+ *  SPDX-License-Identifier: BSD-2-Clause
+ *
+ *  COPYRIGHT (c) 2019.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/todimpl.h>
+#include <rtems/score/chainimpl.h>
+ 
+bool _TOD_Hook_Unregister(
+  TOD_Hook *hook
+)
+{
+  ISR_lock_Context lock_context;
+
+  if ( hook == NULL ) {
+    return FALSE;
+  }
+
+  _TOD_Lock();
+  _TOD_Acquire( &lock_context );
+    _Chain_Extract_unprotected( &hook->Node );
+  _TOD_Unlock();
+  return true;
+}
diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c
index b021a58..744d0e4 100644
--- a/cpukit/score/src/coretodset.c
+++ b/cpukit/score/src/coretodset.c
@@ -22,7 +22,7 @@
 #include <rtems/score/assert.h>
 #include <rtems/score/watchdogimpl.h>
 
-void _TOD_Set(
+bool _TOD_Set(
   const struct timespec *tod,
   ISR_lock_Context      *lock_context
 )
@@ -31,9 +31,15 @@ void _TOD_Set(
   uint64_t        tod_as_ticks;
   uint32_t        cpu_max;
   uint32_t        cpu_index;
+  bool            retval;
 
   _Assert( _TOD_Is_owner() );
 
+  retval = _TOD_Hook_Run( TOD_ACTION_SET_CLOCK, tod );
+  if ( retval == false ) {
+    return false;
+  }
+
   timespec2bintime( tod, &tod_as_bintime );
   _Timecounter_Set_clock( &tod_as_bintime, lock_context );
 
@@ -67,4 +73,6 @@ void _TOD_Set(
   }
 
   _TOD.is_set = true;
+
+  return true;
 }
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 09751b6..f127c2b 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -707,6 +707,15 @@ spclock_err02_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_spclock_err02) \
 	$(support_includes)
 endif
 
+if TEST_spclock_todhook01
+sp_tests += spclock_todhook01
+sp_screens += spclock_todhook01/spclock_todhook01.scn
+sp_docs += spclock_todhook01/spclock_todhook01.doc
+spclock_todhook01_SOURCES = spclock_todhook01/init.c
+spclock_todhook01_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_spclock_todhook01) \
+	$(support_includes)
+endif
+
 if TEST_spconfig01
 sp_tests += spconfig01
 sp_screens += spconfig01/spconfig01.scn
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 3222196..2ad0c61 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -117,6 +117,7 @@ RTEMS_TEST_CHECK([spcbssched03])
 RTEMS_TEST_CHECK([spchain])
 RTEMS_TEST_CHECK([spclock_err01])
 RTEMS_TEST_CHECK([spclock_err02])
+RTEMS_TEST_CHECK([spclock_todhook01])
 RTEMS_TEST_CHECK([spconfig01])
 RTEMS_TEST_CHECK([spconfig02])
 RTEMS_TEST_CHECK([spconsole01])
diff --git a/testsuites/sptests/spclock_todhook01/init.c b/testsuites/sptests/spclock_todhook01/init.c
new file mode 100644
index 0000000..5bbb51a
--- /dev/null
+++ b/testsuites/sptests/spclock_todhook01/init.c
@@ -0,0 +1,334 @@
+/**
+ * @file
+ *
+ * @brief Test TOD Set Hook
+ *
+ * @ingroup sptests
+ */
+
+/*
+ *  SPDX-License-Identifier: BSD-2-Clause
+ *
+ *  COPYRIGHT (c) 2019.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <rtems.h>
+#include <rtems/score/todimpl.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+#include "tmacros.h"
+
+/* #define TEST_DEBUG */
+
+const char rtems_test_name[] = "SPCLOCK TOD HOOK 1";
+
+typedef struct test_case {
+  bool       do_settime; 
+  bool       use_posix; 
+  bool       do_hook1; 
+  bool       do_hook2; 
+  struct tm  tm;
+} testcase_t;
+
+testcase_t Cases[] = {
+  /* should not trigger hooks when time not set */
+  { false, false, false, false, { 0, 0, 9, 31, 11, 88 } },
+  { false, false, true,  true,  { 0, 0, 9, 24, 5,  95 }  },
+  /* should trigger hook when time is set with Classic API rtems_clock_set */
+  { true,  false, false, false, { 0, 0, 9, 24, 5,   95 }  },
+  { true,  false, false, false, { 0, 0, 9, 31, 11,  88 }  },
+  { true,  false, true,  false, { 0, 0, 9, 31, 11,  88 }  },
+  { true,  false, true,  true,  { 0, 0, 9, 24, 5,  105 }  },
+  /* should trigger hook when time is set with POSIX API clock_settime */
+  { true,  true,  false, false, { 0, 0, 9, 24, 5,   95 }  },
+  { true,  true,  false, false, { 0, 9, 6, 14, 2,  114 }  },
+  { true,  true,  true,  false, { 0, 0, 9, 31, 11,  88 }  },
+  { true,  true,  true,  true,  { 0, 0, 9, 24, 5,  105 }  },
+};
+
+#define NUM_CASES (sizeof(Cases)/sizeof(testcase_t))
+
+static struct timespec tod_set;
+
+static bool hook1_executed;
+static bool hook2_executed;
+
+static bool tod_hook1(
+  TOD_Action             action,
+  const struct timespec *tod
+)
+{
+  rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
+
+  rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
+  rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
+
+  hook1_executed = true;
+
+  return true;
+}
+
+static bool tod_hook2(
+  TOD_Action             action,
+  const struct timespec *tod
+)
+{
+  rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
+
+  rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
+  rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
+
+  hook2_executed = true;
+
+  return true;
+}
+
+/*
+ * Execute one positive test case.
+ *
+ * Assume no hooks registered at begining. Unregister if needed at the end.
+ */
+static void do_positive_case(int i)
+{
+  testcase_t  *testcase = &Cases[i];
+  bool         bc;
+  TOD_Hook     hook1;
+  TOD_Hook     hook2;
+
+  #ifdef TEST_DEBUG
+    printf(
+      "%d: do_settime=%d use_posix=%d do_hook1=%d do_hook2=%d\n",
+      i,
+      testcase->do_settime,
+      testcase->use_posix,
+      testcase->do_hook1,
+      testcase->do_hook2
+    );
+  #endif
+
+  hook1.handler = tod_hook1;
+  hook2.handler = tod_hook2;
+
+  hook1_executed = false;
+  hook2_executed = false;
+
+  /*
+   * Register the TOD Hooks
+   */
+  if ( testcase->do_hook1 == true ) {
+    bc =_TOD_Hook_Register( &hook1 );
+    rtems_test_assert( bc == true ); 
+  }
+
+  if ( testcase->do_hook2 == true ) {
+    bc =_TOD_Hook_Register( &hook2 );
+    rtems_test_assert( bc == true ); 
+  }
+
+  /*
+   * Now set the time and if registered, let the handlers fire
+   */
+  if ( testcase->do_settime == true ) {
+    rtems_time_of_day   time;
+    rtems_status_code   status;
+    struct tm          *tm = &testcase->tm;
+
+    tod_set.tv_sec = mktime( tm );
+    tod_set.tv_nsec = 0;
+
+    if ( testcase->use_posix == false ) {
+      build_time(
+        &time,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_year + 1900,
+        tm->tm_hour,
+        tm->tm_min,
+        0,
+        0
+      );
+      status = rtems_clock_set( &time );
+      directive_failed( status, "rtems_clock_set" );
+    } else {
+      int rc;
+
+      rc = clock_settime( CLOCK_REALTIME, &tod_set );
+      rtems_test_assert( rc == 0 ); 
+    }
+  }
+
+  /*
+   * Unregister the TOD hooks 
+   */
+  if ( testcase->do_hook1 == true ) {
+    bc =_TOD_Hook_Unregister( &hook1 );
+    rtems_test_assert( bc == true ); 
+  }
+
+  if ( testcase->do_hook2 == true ) {
+    bc =_TOD_Hook_Unregister( &hook2 );
+    rtems_test_assert( bc == true ); 
+  }
+
+  #ifdef TEST_DEBUG
+    printf(
+      "    hook1_executed=%d hook2_executed=%d\n",
+      hook1_executed,
+      hook2_executed
+    );
+  #endif
+
+  /*
+   * Check expected results
+   */
+  if ( testcase->do_hook1 == true ) {
+    rtems_test_assert( testcase->do_settime == hook1_executed );
+  } else {
+    rtems_test_assert( hook1_executed == false );
+  }
+
+  if ( testcase->do_hook2 == true ) {
+    rtems_test_assert( testcase->do_settime == hook2_executed );
+  } else {
+    rtems_test_assert( hook2_executed == false );
+  }
+}
+
+static bool hook_error_executed;
+
+static bool tod_hook_error(
+  TOD_Action             action,
+  const struct timespec *tod
+)
+{
+  rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
+
+  rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
+  rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
+
+  hook_error_executed = true;
+
+  return false;
+}
+/*
+ * Execute one negative test case.
+ *
+ * Assume no hooks registered at begining. Unregister if needed at the end.
+ */
+static void do_negative_case(bool use_posix)
+{
+  bool                bc;
+  TOD_Hook            hook_error;
+  rtems_time_of_day   time;
+  rtems_status_code   status;
+  struct tm          *tm = &Cases[0].tm;
+
+
+  hook_error.handler = tod_hook_error;
+
+  hook_error_executed = false;
+
+  /*
+   * Register the TOD Hooks
+   */
+  bc =_TOD_Hook_Register( &hook_error );
+  rtems_test_assert( bc == true ); 
+
+  /*
+   * Now set the time and if registered, let the handlers fire
+   */
+  tod_set.tv_sec = mktime( tm );
+  tod_set.tv_nsec = 0;
+
+  if ( use_posix == false ) {
+    build_time(
+      &time,
+      tm->tm_mon + 1,
+      tm->tm_mday,
+      tm->tm_year + 1900,
+      tm->tm_hour,
+      tm->tm_min,
+      0,
+      0
+    );
+    status = rtems_clock_set( &time );
+    rtems_test_assert( status == RTEMS_IO_ERROR );
+  } else {
+    int rc;
+
+    rc = clock_settime( CLOCK_REALTIME, &tod_set );
+    rtems_test_assert( rc == -1 ); 
+    rtems_test_assert( errno == EPERM ); 
+  }
+
+  /*
+   * Unregister the TOD hooks 
+   */
+  bc =_TOD_Hook_Unregister( &hook_error );
+  rtems_test_assert( bc == true ); 
+
+  /*
+   * Check expected results
+   */
+  rtems_test_assert( hook_error_executed == true );
+}
+
+
+static rtems_task Init(rtems_task_argument ignored)
+{
+  // rtems_status_code status;
+  int               i;
+
+  TEST_BEGIN();
+
+  // test positive cases
+  for (i=0 ; i < NUM_CASES ; i++) {
+    do_positive_case( i );
+  }
+
+  // test error cases
+  do_negative_case(false);
+  do_negative_case(true);
+
+  TEST_END();
+
+  rtems_test_exit(0);
+}
+
+/* configuration information */
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
diff --git a/testsuites/sptests/spclock_todhook01/spclock_todhook01.doc b/testsuites/sptests/spclock_todhook01/spclock_todhook01.doc
new file mode 100644
index 0000000..0be564e
--- /dev/null
+++ b/testsuites/sptests/spclock_todhook01/spclock_todhook01.doc
@@ -0,0 +1,35 @@
+#  COPYRIGHT (c) 1989-2014.
+#  On-Line Applications Research Corporation (OAR).
+#
+#  The license and distribution terms for this file may be
+#  found in the file LICENSE in this distribution or at
+#  http://www.rtems.com/license/LICENSE.
+#
+
+
+This file describes the directives and concepts tested by this test set.
+
+test set name:  spclock_todhook01
+
+directives:
+  _TOD_Hook_Register
+  _TOD_Hook_Unregister
+  rtems_clock_set 
+  clock_settime 
+  
+
+concepts:
+
+- Verifies that TOD Hooks can be registered
+
+- Verifies that TOD Hooks can be unregistered
+
+- Verifies that an empty TOD Hooks set is properly processed when the TOD is set
+
+- Verifies that TOD Hooks are executed when the TOD is set
+
+- Verifies that a TOD Hook returning an error is properly reported by
+  rtems_clock_set
+
+- Verifies that a TOD Hook returning an error is properly reported by
+  clock_settime
diff --git a/testsuites/sptests/spclock_todhook01/spclock_todhook01.scn b/testsuites/sptests/spclock_todhook01/spclock_todhook01.scn
new file mode 100644
index 0000000..e69de29
-- 
1.8.3.1



More information about the devel mailing list