[PATCH v2] Add TOD Hooks to allow BSP to take action when TOD is set
Chris Johns
chrisj at rtems.org
Thu Nov 14 23:29:15 UTC 2019
On 15/11/19 7:44 am, Joel Sherrill wrote:
> 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 | 67 +++++
> cpukit/score/src/coretodhookrun.c | 73 +++++
> cpukit/score/src/coretodhookunregister.c | 66 ++++
> 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, 758 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 );
Indented :)
> _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..b34d327
> --- /dev/null
> +++ b/cpukit/score/src/coretodhookregister.c
> @@ -0,0 +1,67 @@
> +/**
> + * @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(
Return type is bool ...
> + TOD_Hook *hook
> +)
> +{
> + ISR_lock_Context lock_context;
> +
> + /*
> + * 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() );
Is the _Assert always enabled or is it a configure option?
> +
> + if ( hook == NULL ) {
> + return FALSE;
FALSE or false?
> + }
> +
> + _TOD_Lock();
> + _TOD_Acquire( &lock_context );
> + _Chain_Append_unprotected( &_TOD_Hooks, &hook->Node );
> + _TOD_Unlock();
> + return true;
It is true here.
> +}
> +
> diff --git a/cpukit/score/src/coretodhookrun.c b/cpukit/score/src/coretodhookrun.c
> new file mode 100644
> index 0000000..0a82faa
> --- /dev/null
> +++ b/cpukit/score/src/coretodhookrun.c
> @@ -0,0 +1,73 @@
> +/**
> + * @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
> +)
> +{
> + ISR_lock_Context lock_context;
Used?
> + 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 0000000..a02edf5
> --- /dev/null
> +++ b/cpukit/score/src/coretodhookunregister.c
> @@ -0,0 +1,66 @@
> +/**
> + * @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;
> +
> + /*
> + * 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() );
> +
> + if ( hook == NULL ) {
> + return FALSE;
FALSE of false?
Is it an error to call unregister with NULL or should the test be in this
function, ie like free(NULL), rather then the callers?
Chris
> + }
> +
> + _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
>
More information about the devel
mailing list