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