[PATCH 2/3] Add hook for BSP to act when time is set

Chris Johns chrisj at rtems.org
Fri Oct 4 02:44:52 UTC 2019


On 4/10/19 8:08 am, Joel Sherrill wrote:
> This hook is only enabled when paravirtualized. It allows
> the application running on RTEMS in a paravirtualized
> environment to have its set time operations impact
> the hosting environment. This requires support specific
> to the paravirtualized environment. The hosting environment
> may refuse to let the paravirtualized application set the
> time and this is reflected to the application as a
> permissions or not owner of resource issue.
> ---
>  cpukit/headers.am                    |  1 +
>  cpukit/include/rtems/score/tod.h     | 51 ++++++++++++++++++++++++++++++++++++
>  cpukit/include/rtems/score/todimpl.h |  8 +++++-
>  cpukit/posix/src/clocksettime.c      |  6 ++++-
>  cpukit/rtems/src/clockset.c          |  6 ++++-
>  cpukit/score/src/coretodadjust.c     |  2 +-
>  cpukit/score/src/coretodset.c        | 15 ++++++++++-
>  7 files changed, 84 insertions(+), 5 deletions(-)
>  create mode 100644 cpukit/include/rtems/score/tod.h
> 
> diff --git a/cpukit/headers.am b/cpukit/headers.am
> index 008b7cc..3386f77 100644
> --- a/cpukit/headers.am
> +++ b/cpukit/headers.am
> @@ -399,6 +399,7 @@ include_rtems_score_HEADERS += include/rtems/score/timespec.h
>  include_rtems_score_HEADERS += include/rtems/score/timestamp.h
>  include_rtems_score_HEADERS += include/rtems/score/timestampimpl.h
>  include_rtems_score_HEADERS += include/rtems/score/tls.h
> +include_rtems_score_HEADERS += include/rtems/score/tod.h
>  include_rtems_score_HEADERS += include/rtems/score/todimpl.h
>  include_rtems_score_HEADERS += include/rtems/score/userext.h
>  include_rtems_score_HEADERS += include/rtems/score/userextdata.h
> diff --git a/cpukit/include/rtems/score/tod.h b/cpukit/include/rtems/score/tod.h
> new file mode 100644
> index 0000000..3b06642
> --- /dev/null
> +++ b/cpukit/include/rtems/score/tod.h
> @@ -0,0 +1,51 @@
> +/**
> + * @file
> + *
> + * @ingroup ScoreTOD
> + *
> + * @brief Time of Day Handler API
> + */
> +
> +/*
> + *  COPYRIGHT (c) 1989-2009.
> + *  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.org/license/LICENSE.
> + */
> +
> +#ifndef _RTEMS_SCORE_TOD_H
> +#define _RTEMS_SCORE_TOD_H
> +
> +#include <sys/timespec.h>
> +
> +#include <rtems/score/basedefs.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#if defined(RTEMS_PARAVIRT)
> +/**
> + * @brief Method Invoked When TOD is Set
> + *
> + * This method is invoked when the TOD is set. It can be overridden
> + * by the BSP 

How is it overridden?

> to allow it to set the TOD in the host in a paravirtualized
> + * environment.
> + *
> + * @param tod points to the new TOD
> + *
> + * @note This is invoked with the TOD locked.
> + */
> +bool _TOD_Set_hook(

I initially read this as setting the "hook" and not the "set hook".

> +  const struct timespec *tod
> +);
> +#endif
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> +/* end of include file */
> diff --git a/cpukit/include/rtems/score/todimpl.h b/cpukit/include/rtems/score/todimpl.h
> index 0d4faac..25bb979 100644
> --- a/cpukit/include/rtems/score/todimpl.h
> +++ b/cpukit/include/rtems/score/todimpl.h
> @@ -183,8 +183,14 @@ 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.
> + *
> + * @note This method currently always returns true in non-paravirtualized
> + *       configuration. In a paravirtualized envivonment, it may fail if
> + *       the container does not have permission to set the time.
> + *
> + * @return This method returns true if successful and false otherwise.
>   */
> -void _TOD_Set(
> +bool _TOD_Set(

Why bool? Would returning an `int` let the BSP determine the error code returned?

>    const struct timespec *tod,
>    ISR_lock_Context      *lock_context
>  );
> diff --git a/cpukit/posix/src/clocksettime.c b/cpukit/posix/src/clocksettime.c
> index a0fdd91..387de4e 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 rc;
> +
>    if ( !tp )
>      rtems_set_errno_and_return_minus_one( EINVAL );
>  
> @@ -43,8 +45,10 @@ int clock_settime(
>  
>      _TOD_Lock();
>      _TOD_Acquire( &lock_context );
> -    _TOD_Set( tp, &lock_context );
> +    rc = _TOD_Set( tp, &lock_context );
>      _TOD_Unlock();
> +    if (rc == false)
> +      rtems_set_errno_and_return_minus_one( EPERM );

ie is this the only error that can ever be returned for type of call? What about
 EIO, EACCES, EINVAL, etc.

>    }
>  #ifdef _POSIX_CPUTIME
>    else if ( clock_id == CLOCK_PROCESS_CPUTIME_ID )
> diff --git a/cpukit/rtems/src/clockset.c b/cpukit/rtems/src/clockset.c
> index d772682..9acb8d7 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 rc;
> +
>    if ( !tod )
>      return RTEMS_INVALID_ADDRESS;
>  
> @@ -39,8 +41,10 @@ rtems_status_code rtems_clock_set(
>  
>      _TOD_Lock();
>      _TOD_Acquire( &lock_context );
> -    _TOD_Set( &tod_as_timespec, &lock_context );
> +    rc = _TOD_Set( &tod_as_timespec, &lock_context );
>      _TOD_Unlock();
> +    if (rc == false)
> +      return RTEMS_NOT_OWNER_OF_RESOURCE;
>  
>      return RTEMS_SUCCESSFUL;
>    }
> diff --git a/cpukit/score/src/coretodadjust.c b/cpukit/score/src/coretodadjust.c
> index accb99b..b420c85 100644
> --- a/cpukit/score/src/coretodadjust.c
> +++ b/cpukit/score/src/coretodadjust.c
> @@ -39,6 +39,6 @@ void _TOD_Adjust(
>    _TOD_Acquire( &lock_context );
>    _TOD_Get( &tod );
>    _Timespec_Add_to( &tod, delta );
> -  _TOD_Set( &tod, &lock_context );
> +  (void) _TOD_Set( &tod, &lock_context );
>    _TOD_Unlock();
>  }
> diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c
> index b021a58..95bf162 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
>  )
> @@ -35,6 +35,18 @@ void _TOD_Set(
>    _Assert( _TOD_Is_owner() );
>  
>    timespec2bintime( tod, &tod_as_bintime );
> +
> +#if defined(RTEMS_PARAVIRT)
> +  /*
> +   * If in a paravirtualized environment, attempt to set the TOD in
> +   * the hosting environment. This may fail due to a permission error
> +   * if this guest is not allowed to set the TOD.
> +   */
> +  if (_TOD_Set_hook( tod ) == false) {
> +    return false;
> +  }
> +#endif

Is this only useful for virtual BSPs and is it always a requirement to implement
this call in those environments?

Would this call be useful to a non-virtual BSP, for example one with a battery
backed RTC device?

Would a hook API along the lines of ....

typedef int (*_TOD_Set_Handler)(const struct timespec *tod);
 _TOD_Set_Handler _TOD_Set_hook(_TOD_Set_Handler handler);

... be more flexible?

Chris


More information about the devel mailing list