[PATCH] score: RTEMS_PREDICT_TRUE(), RTEMS_PREDICT_FALSE()

Joel Sherrill joel at rtems.org
Tue Jul 24 12:14:55 UTC 2018


On Tue, Jul 24, 2018, 2:03 AM Sebastian Huber <
sebastian.huber at embedded-brains.de> wrote:

> Add RTEMS_PREDICT_TRUE() and RTEMS_PREDICT_FALSE() for static branch
> prediction hints.
>
> Close #3475.
> ---
>  cpukit/include/rtems/score/basedefs.h | 28 ++++++++++++++++++++++++++++
>  cpukit/posix/src/sempost.c            |  4 ++--
>  cpukit/posix/src/semtimedwait.c       |  2 +-
>  cpukit/posix/src/semtrywait.c         |  2 +-
>  cpukit/score/src/condition.c          |  4 +++-
>  cpukit/score/src/futex.c              |  2 +-
>  cpukit/score/src/mutex.c              | 16 ++++++++--------
>  cpukit/score/src/semaphore.c          | 10 +++++-----
>  testsuites/sptests/spmisc01/init.c    | 25 +++++++++++++++++++++++++
>  9 files changed, 74 insertions(+), 19 deletions(-)
>
> diff --git a/cpukit/include/rtems/score/basedefs.h
> b/cpukit/include/rtems/score/basedefs.h
> index 8169f6db8c..7a52de895d 100644
> --- a/cpukit/include/rtems/score/basedefs.h
> +++ b/cpukit/include/rtems/score/basedefs.h
> @@ -281,6 +281,34 @@
>    #define RTEMS_DEFINE_GLOBAL_SYMBOL( _name, _value )
>  #endif
>
> +/**
> + * @brief Returns the value of the specified integral expressen and tells
> the
>

Spelling error here and in the other comment block. Search to make sure it
isn't elsewhere.

+ * compiler that the predicted value is true (1).
> + *
> + * @param[in] _exp The expression.
> + *
> + * @return The value of the expression.
> + */
> +#if defined(__GNUC__)
> +  #define RTEMS_PREDICT_TRUE( _exp ) __builtin_expect( ( _exp ), 1 )
> +#else
> +  #define RTEMS_PREDICT_TRUE( _exp ) ( _exp )
> +#endif
> +
> +/**
> + * @brief Returns the value of the specified integral expressen and tells
> the
> + * compiler that the predicted value is false (0).
> + *
> + * @param[in] _exp The expression.
> + *
> + * @return The value of the expression.
> + */
> +#if defined(__GNUC__)
> +  #define RTEMS_PREDICT_FALSE( _exp ) __builtin_expect( ( _exp ), 0 )
> +#else
> +  #define RTEMS_PREDICT_FALSE( _exp ) ( _exp )
> +#endif
> +
>  #if __cplusplus >= 201103L
>    #define RTEMS_STATIC_ASSERT(cond, msg) \
>      static_assert(cond, # msg)
> diff --git a/cpukit/posix/src/sempost.c b/cpukit/posix/src/sempost.c
> index de0ae71fc7..d750c1178c 100644
> --- a/cpukit/posix/src/sempost.c
> +++ b/cpukit/posix/src/sempost.c
> @@ -40,13 +40,13 @@ int sem_post( sem_t *_sem )
>    heads = sem->Queue.Queue.heads;
>    count = sem->count;
>
> -  if ( __predict_true( heads == NULL && count < SEM_VALUE_MAX ) ) {
> +  if ( RTEMS_PREDICT_TRUE( heads == NULL && count < SEM_VALUE_MAX ) ) {
>      sem->count = count + 1;
>      _Sem_Queue_release( sem, level, &queue_context );
>      return 0;
>    }
>
> -  if ( __predict_true( heads != NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( heads != NULL ) ) {
>      const Thread_queue_Operations *operations;
>      Thread_Control *first;
>
> diff --git a/cpukit/posix/src/semtimedwait.c
> b/cpukit/posix/src/semtimedwait.c
> index 9e7bb466dd..16d0c24c9f 100644
> --- a/cpukit/posix/src/semtimedwait.c
> +++ b/cpukit/posix/src/semtimedwait.c
> @@ -46,7 +46,7 @@ int sem_timedwait(
>    executing = _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    count = sem->count;
> -  if ( __predict_true( count > 0 ) ) {
> +  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
>      sem->count = count - 1;
>      _Sem_Queue_release( sem, level, &queue_context );
>      return 0;
> diff --git a/cpukit/posix/src/semtrywait.c b/cpukit/posix/src/semtrywait.c
> index 673343d4b4..759744ec8e 100644
> --- a/cpukit/posix/src/semtrywait.c
> +++ b/cpukit/posix/src/semtrywait.c
> @@ -35,7 +35,7 @@ int sem_trywait( sem_t *_sem )
>    _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    count = sem->count;
> -  if ( __predict_true( count > 0 ) ) {
> +  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
>      sem->count = count - 1;
>      _Sem_Queue_release( sem, level, &queue_context );
>      return 0;
> diff --git a/cpukit/score/src/condition.c b/cpukit/score/src/condition.c
> index 9913d86d34..892245baf5 100644
> --- a/cpukit/score/src/condition.c
> +++ b/cpukit/score/src/condition.c
> @@ -279,7 +279,9 @@ static void _Condition_Wake( struct _Condition_Control
> *_condition, int count )
>     * In common uses cases of condition variables there are normally no
> threads
>     * on the queue, so check this condition early.
>     */
> -  if ( __predict_true( _Thread_queue_Is_empty( &condition->Queue.Queue )
> ) ) {
> +  if (
> +    RTEMS_PREDICT_TRUE( _Thread_queue_Is_empty( &condition->Queue.Queue )
> )
> +  ) {
>      _Condition_Queue_release( condition, &context.Base );
>      return;
>    }
> diff --git a/cpukit/score/src/futex.c b/cpukit/score/src/futex.c
> index 6487882819..f32a13c449 100644
> --- a/cpukit/score/src/futex.c
> +++ b/cpukit/score/src/futex.c
> @@ -151,7 +151,7 @@ int _Futex_Wake( struct _Futex_Control *_futex, int
> count )
>     * called in the fast path.  Normally there are no threads on the
> queue, so
>     * check this condition early.
>     */
> -  if ( __predict_true( _Thread_queue_Is_empty( &futex->Queue.Queue ) ) ) {
> +  if ( RTEMS_PREDICT_TRUE( _Thread_queue_Is_empty( &futex->Queue.Queue )
> ) ) {
>      _Futex_Queue_release( futex, level, &context.Base );
>      return 0;
>    }
> diff --git a/cpukit/score/src/mutex.c b/cpukit/score/src/mutex.c
> index e2f5bb52fc..8cc47f28bb 100644
> --- a/cpukit/score/src/mutex.c
> +++ b/cpukit/score/src/mutex.c
> @@ -128,7 +128,7 @@ static void _Mutex_Release_critical(
>    mutex->Queue.Queue.owner = NULL;
>    _Thread_Resource_count_decrement( executing );
>
> -  if ( __predict_true( heads == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
>      _Mutex_Queue_release( mutex, level, queue_context );
>    } else {
>      _Thread_queue_Context_set_ISR_level( queue_context, level );
> @@ -157,7 +157,7 @@ void _Mutex_Acquire( struct _Mutex_Control *_mutex )
>
>    owner = mutex->Queue.Queue.owner;
>
> -  if ( __predict_true( owner == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
>      mutex->Queue.Queue.owner = executing;
>      _Thread_Resource_count_increment( executing );
>      _Mutex_Queue_release( mutex, level, &queue_context );
> @@ -185,7 +185,7 @@ int _Mutex_Acquire_timed(
>
>    owner = mutex->Queue.Queue.owner;
>
> -  if ( __predict_true( owner == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
>      mutex->Queue.Queue.owner = executing;
>      _Thread_Resource_count_increment( executing );
>      _Mutex_Queue_release( mutex, level, &queue_context );
> @@ -218,7 +218,7 @@ int _Mutex_Try_acquire( struct _Mutex_Control *_mutex )
>
>    owner = mutex->Queue.Queue.owner;
>
> -  if ( __predict_true( owner == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
>      mutex->Queue.Queue.owner = executing;
>      _Thread_Resource_count_increment( executing );
>      eno = 0;
> @@ -270,7 +270,7 @@ void _Mutex_recursive_Acquire( struct
> _Mutex_recursive_Control *_mutex )
>
>    owner = mutex->Mutex.Queue.Queue.owner;
>
> -  if ( __predict_true( owner == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
>      mutex->Mutex.Queue.Queue.owner = executing;
>      _Thread_Resource_count_increment( executing );
>      _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
> @@ -301,7 +301,7 @@ int _Mutex_recursive_Acquire_timed(
>
>    owner = mutex->Mutex.Queue.Queue.owner;
>
> -  if ( __predict_true( owner == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
>      mutex->Mutex.Queue.Queue.owner = executing;
>      _Thread_Resource_count_increment( executing );
>      _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
> @@ -339,7 +339,7 @@ int _Mutex_recursive_Try_acquire( struct
> _Mutex_recursive_Control *_mutex )
>
>    owner = mutex->Mutex.Queue.Queue.owner;
>
> -  if ( __predict_true( owner == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( owner == NULL ) ) {
>      mutex->Mutex.Queue.Queue.owner = executing;
>      _Thread_Resource_count_increment( executing );
>      eno = 0;
> @@ -372,7 +372,7 @@ void _Mutex_recursive_Release( struct
> _Mutex_recursive_Control *_mutex )
>
>    nest_level = mutex->nest_level;
>
> -  if ( __predict_true( nest_level == 0 ) ) {
> +  if ( RTEMS_PREDICT_TRUE( nest_level == 0 ) ) {
>      _Mutex_Release_critical( &mutex->Mutex, executing, level,
> &queue_context );
>    } else {
>      mutex->nest_level = nest_level - 1;
> diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c
> index f76ee332a4..f9b8b48fe1 100644
> --- a/cpukit/score/src/semaphore.c
> +++ b/cpukit/score/src/semaphore.c
> @@ -53,7 +53,7 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem )
>    executing = _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    count = sem->count;
> -  if ( __predict_true( count > 0 ) ) {
> +  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
>      sem->count = count - 1;
>      _Sem_Queue_release( sem, level, &queue_context );
>    } else {
> @@ -86,7 +86,7 @@ int _Semaphore_Wait_timed_ticks( struct
> _Semaphore_Control *_sem, uint32_t ticks
>    executing = _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    count = sem->count;
> -  if ( __predict_true( count > 0 ) ) {
> +  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
>      sem->count = count - 1;
>      _Sem_Queue_release( sem, level, &queue_context );
>      return 0;
> @@ -121,7 +121,7 @@ int _Semaphore_Try_wait( struct _Semaphore_Control
> *_sem )
>    _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    count = sem->count;
> -  if ( __predict_true( count > 0 ) ) {
> +  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
>      sem->count = count - 1;
>      eno = 0;
>    } else {
> @@ -145,7 +145,7 @@ void _Semaphore_Post( struct _Semaphore_Control *_sem )
>    _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    heads = sem->Queue.Queue.heads;
> -  if ( __predict_true( heads == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
>      ++sem->count;
>      _Sem_Queue_release( sem, level, &queue_context );
>    } else {
> @@ -178,7 +178,7 @@ void _Semaphore_Post_binary( struct _Semaphore_Control
> *_sem )
>    _Sem_Queue_acquire_critical( sem, &queue_context );
>
>    heads = sem->Queue.Queue.heads;
> -  if ( __predict_true( heads == NULL ) ) {
> +  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
>      sem->count = 1;
>      _Sem_Queue_release( sem, level, &queue_context );
>    } else {
> diff --git a/testsuites/sptests/spmisc01/init.c
> b/testsuites/sptests/spmisc01/init.c
> index 4fab3f0e84..c406cd07aa 100644
> --- a/testsuites/sptests/spmisc01/init.c
> +++ b/testsuites/sptests/spmisc01/init.c
> @@ -229,6 +229,31 @@ static void Init(rtems_task_argument arg)
>    rtems_test_assert(RTEMS_XCONCAT(CON, CAT)() == 91);
>    rtems_test_assert(strcmp(RTEMS_STRING(str), "str") == 0);
>    rtems_test_assert(strcmp(RTEMS_XSTRING(STR), "ing") == 0);
> +
> +  if (RTEMS_PREDICT_TRUE(true)) {
> +    rtems_test_assert(true);
> +  } else {
> +    rtems_test_assert(false);
> +  }
> +
> +  if (RTEMS_PREDICT_FALSE(true)) {
> +    rtems_test_assert(true);
> +  } else {
> +    rtems_test_assert(false);
> +  }
> +
> +  if (RTEMS_PREDICT_TRUE(false)) {
> +    rtems_test_assert(false);
> +  } else {
> +    rtems_test_assert(true);
> +  }
> +
> +  if (RTEMS_PREDICT_FALSE(false)) {
> +    rtems_test_assert(false);
> +  } else {
> +    rtems_test_assert(true);
> +  }
> +
>    TEST_END();
>    rtems_test_exit(0);
>  }
> --
> 2.13.7
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20180724/0fea55ac/attachment-0002.html>


More information about the devel mailing list