diff options
-rw-r--r-- | cpukit/Makefile.am | 4 | ||||
-rw-r--r-- | cpukit/include/rtems/score/timecounter.h | 10 | ||||
-rw-r--r-- | cpukit/include/rtems/score/todimpl.h | 107 | ||||
-rw-r--r-- | cpukit/posix/src/clocksettime.c | 16 | ||||
-rw-r--r-- | cpukit/rtems/src/clockset.c | 9 | ||||
-rw-r--r-- | cpukit/score/src/coretodhookdata.c | 45 | ||||
-rw-r--r-- | cpukit/score/src/coretodhookregister.c | 61 | ||||
-rw-r--r-- | cpukit/score/src/coretodhookrun.c | 72 | ||||
-rw-r--r-- | cpukit/score/src/coretodhookunregister.c | 60 | ||||
-rw-r--r-- | cpukit/score/src/coretodset.c | 11 | ||||
-rw-r--r-- | testsuites/sptests/Makefile.am | 9 | ||||
-rw-r--r-- | testsuites/sptests/configure.ac | 1 | ||||
-rw-r--r-- | testsuites/sptests/spclock_todhook01/init.c | 330 | ||||
-rw-r--r-- | testsuites/sptests/spclock_todhook01/spclock_todhook01.doc | 35 | ||||
-rw-r--r-- | testsuites/sptests/spclock_todhook01/spclock_todhook01.scn | 2 |
15 files changed, 764 insertions, 8 deletions
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 71daca821a..0b0bede2ad 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -982,6 +982,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/timecounter.h b/cpukit/include/rtems/score/timecounter.h index 78f5dfa53b..b71ccd3948 100644 --- a/cpukit/include/rtems/score/timecounter.h +++ b/cpukit/include/rtems/score/timecounter.h @@ -202,6 +202,16 @@ ISR_LOCK_DECLARE( extern, _Timecounter_Lock ) _ISR_lock_ISR_disable_and_acquire( &_Timecounter_Lock, lock_context ) /** + * @brief Releases the timecounter lock. + * + * @param lock_context The lock context. + * + * See _Timecounter_Tick_simple(). + */ +#define _Timecounter_Release(lock_context) \ + _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, lock_context) + +/** * @brief Performs a simple timecounter tick. * * This is a special purpose tick function for simple timecounter to support diff --git a/cpukit/include/rtems/score/todimpl.h b/cpukit/include/rtems/score/todimpl.h index 0d4faac6b2..5287c976f5 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; /** @@ -174,6 +177,16 @@ static inline void _TOD_Acquire( ISR_lock_Context *lock_context ) } /** + * @brief Releases the lock context for the timecounter. + * + * @param lock_context The lock to release. + */ +static inline void _TOD_Release( ISR_lock_Context *lock_context ) +{ + _Timecounter_Release( lock_context ); +} + +/** * @brief Sets the time of day. * * The caller must be the owner of the TOD lock. @@ -183,8 +196,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 +336,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. + */ +void _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. + */ +void _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 a0fdd9109f..bfae46feee 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 d77268211b..a885fe1169 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 0000000000..6e7bcff494 --- /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 0000000000..69996a2b06 --- /dev/null +++ b/cpukit/score/src/coretodhookregister.c @@ -0,0 +1,61 @@ +/** + * @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> + +void _TOD_Hook_Register( + TOD_Hook *hook +) +{ + /* + * At this time, this method does NOT have a Classic or POSIX API + * that exports it. Any use of this method will be a direct call. + * It should only be called while NOT holding the TOD lock. + */ + _Assert( !_TOD_Is_owner() ); + + _Assert( hook != NULL ); + + _TOD_Lock(); + _Chain_Append_unprotected( &_TOD_Hooks, &hook->Node ); + _TOD_Unlock(); +} + diff --git a/cpukit/score/src/coretodhookrun.c b/cpukit/score/src/coretodhookrun.c new file mode 100644 index 0000000000..ae9cf66dfc --- /dev/null +++ b/cpukit/score/src/coretodhookrun.c @@ -0,0 +1,72 @@ +/** + * @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/assert.h> +#include <rtems/score/chainimpl.h> + +bool _TOD_Hook_Run( + TOD_Action action, + const struct timespec *tod +) +{ + Chain_Node *the_node; + bool retval = true; + + /* + * This is assumed to be called only from _TOD_Set() which is supposed + * to be called only while holding the TOD lock. + */ + _Assert( _TOD_Is_owner() ); + + 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; + } + } + + return retval; +} + diff --git a/cpukit/score/src/coretodhookunregister.c b/cpukit/score/src/coretodhookunregister.c new file mode 100644 index 0000000000..ce978e8e81 --- /dev/null +++ b/cpukit/score/src/coretodhookunregister.c @@ -0,0 +1,60 @@ +/** + * @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> + +void _TOD_Hook_Unregister( + TOD_Hook *hook +) +{ + /* + * At this time, this method does NOT have a Classic or POSIX API + * that exports it. Any use of this method will be a direct call. + * It should only be called while NOT holding the TOD lock. + */ + _Assert( !_TOD_Is_owner() ); + + _Assert( hook != NULL ); + + _TOD_Lock(); + _Chain_Extract_unprotected( &hook->Node ); + _TOD_Unlock(); +} diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c index b021a58dc6..94ecd0b322 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,16 @@ 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 ) { + _TOD_Release( lock_context ); + return false; + } + timespec2bintime( tod, &tod_as_bintime ); _Timecounter_Set_clock( &tod_as_bintime, lock_context ); @@ -67,4 +74,6 @@ void _TOD_Set( } _TOD.is_set = true; + + return true; } diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index 09751b6d58..f127c2b2e8 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 467d2417f5..d8816d80f0 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -116,6 +116,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 0000000000..26f0ff9b48 --- /dev/null +++ b/testsuites/sptests/spclock_todhook01/init.c @@ -0,0 +1,330 @@ +/** + * @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]; + 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 + + _Chain_Initialize_node( &hook1.Node ); + hook1.handler = tod_hook1; + + _Chain_Initialize_node( &hook2.Node ); + hook2.handler = tod_hook2; + + hook1_executed = false; + hook2_executed = false; + + /* + * Register the TOD Hooks + */ + if ( testcase->do_hook1 == true ) { + _TOD_Hook_Register( &hook1 ); + } + + if ( testcase->do_hook2 == true ) { + _TOD_Hook_Register( &hook2 ); + } + + /* + * 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 ) { + _TOD_Hook_Unregister( &hook1 ); + } + + if ( testcase->do_hook2 == true ) { + _TOD_Hook_Unregister( &hook2 ); + } + + #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) +{ + TOD_Hook hook_error; + rtems_time_of_day time; + rtems_status_code status; + struct tm *tm = &Cases[0].tm; + + + _Chain_Initialize_node( &hook_error.Node ); + hook_error.handler = tod_hook_error; + + hook_error_executed = false; + + /* + * Register the TOD Hooks + */ + _TOD_Hook_Register( &hook_error ); + + /* + * 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 + */ + _TOD_Hook_Unregister( &hook_error ); + + /* + * 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 0000000000..0be564edb6 --- /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 0000000000..b54c10e317 --- /dev/null +++ b/testsuites/sptests/spclock_todhook01/spclock_todhook01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST SPCLOCK TOD HOOK 1 *** +*** END OF TEST SPCLOCK TOD HOOK 1 *** |