[PATCH] smp: Add Deterministic Priority SMP Scheduler

Joel Sherrill joel.sherrill at OARcorp.com
Mon Aug 19 15:19:21 UTC 2013


Still needs an addition to the Configuring a System chapter.

Thanks for providing more details in the comments.

On 8/19/2013 10:12 AM, Sebastian Huber wrote:
> ---
>   cpukit/sapi/include/confdefs.h                     |   24 ++-
>   cpukit/score/Makefile.am                           |    2 +
>   .../include/rtems/score/schedulerpriorityimpl.h    |   17 ++
>   .../include/rtems/score/schedulerprioritysmp.h     |   94 +++++++++
>   cpukit/score/preinstall.am                         |    4 +
>   cpukit/score/src/schedulerprioritysmp.c            |  217 ++++++++++++++++++++
>   cpukit/score/src/schedulerpriorityupdate.c         |   10 +-
>   .../smptests/smpmigration01/smpmigration01.scn     |   24 +-
>   8 files changed, 370 insertions(+), 22 deletions(-)
>   create mode 100644 cpukit/score/include/rtems/score/schedulerprioritysmp.h
>   create mode 100644 cpukit/score/src/schedulerprioritysmp.c
>
> diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
> index 31d28ac..dc4fb5e 100644
> --- a/cpukit/sapi/include/confdefs.h
> +++ b/cpukit/sapi/include/confdefs.h
> @@ -606,6 +606,7 @@ const rtems_libio_helper rtems_fs_init_helper =
>    * scheduling policy to use.  The supported configurations are:
>    *  CONFIGURE_SCHEDULER_USER       - user provided scheduler
>    *  CONFIGURE_SCHEDULER_PRIORITY   - Deterministic Priority Scheduler
> + *  CONFIGURE_SCHEDULER_PRIORITY_SMP - Deterministic Priority SMP Scheduler
>    *  CONFIGURE_SCHEDULER_SIMPLE     - Light-weight Priority Scheduler
>    *  CONFIGURE_SCHEDULER_SIMPLE_SMP - Simple SMP Priority Scheduler
>    *  CONFIGURE_SCHEDULER_EDF        - EDF Scheduler
> @@ -629,12 +630,13 @@ const rtems_libio_helper rtems_fs_init_helper =
>   /* If no scheduler is specified, the priority scheduler is default. */
>   #if !defined(CONFIGURE_SCHEDULER_USER) && \
>       !defined(CONFIGURE_SCHEDULER_PRIORITY) && \
> +    !defined(CONFIGURE_SCHEDULER_PRIORITY_SMP) && \
>       !defined(CONFIGURE_SCHEDULER_SIMPLE) && \
>       !defined(CONFIGURE_SCHEDULER_SIMPLE_SMP) && \
>       !defined(CONFIGURE_SCHEDULER_EDF) && \
>       !defined(CONFIGURE_SCHEDULER_CBS)
>     #if defined(RTEMS_SMP) && defined(CONFIGURE_SMP_APPLICATION)
> -    #define CONFIGURE_SCHEDULER_SIMPLE_SMP
> +    #define CONFIGURE_SCHEDULER_PRIORITY_SMP
>     #else
>       #define CONFIGURE_SCHEDULER_PRIORITY
>     #endif
> @@ -659,6 +661,26 @@ const rtems_libio_helper rtems_fs_init_helper =
>   #endif
>
>   /*
> + * If the Deterministic Priority SMP Scheduler is selected, then configure for
> + * it.
> + */
> +#if defined(CONFIGURE_SCHEDULER_PRIORITY_SMP)
> +  #include <rtems/score/schedulerprioritysmp.h>
> +  #define CONFIGURE_SCHEDULER_ENTRY_POINTS SCHEDULER_PRIORITY_SMP_ENTRY_POINTS
> +
> +  /**
> +   * This defines the memory used by the priority scheduler.
> +   */
> +  #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
> +    _Configure_From_workspace( \
> +      sizeof(Scheduler_SMP_Control) +  \
> +      ((CONFIGURE_MAXIMUM_PRIORITY) * sizeof(Chain_Control)) ) \
> +  )
> +  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
> +    _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
> +#endif
> +
> +/*
>    * If the Simple Priority Scheduler is selected, then configure for it.
>    */
>   #if defined(CONFIGURE_SCHEDULER_SIMPLE)
> diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
> index c5af9c7..c9d2d47 100644
> --- a/cpukit/score/Makefile.am
> +++ b/cpukit/score/Makefile.am
> @@ -53,6 +53,7 @@ include_rtems_score_HEADERS += include/rtems/score/scheduleredf.h
>   include_rtems_score_HEADERS += include/rtems/score/scheduleredfimpl.h
>   include_rtems_score_HEADERS += include/rtems/score/schedulerpriority.h
>   include_rtems_score_HEADERS += include/rtems/score/schedulerpriorityimpl.h
> +include_rtems_score_HEADERS += include/rtems/score/schedulerprioritysmp.h
>   include_rtems_score_HEADERS += include/rtems/score/schedulersimple.h
>   include_rtems_score_HEADERS += include/rtems/score/schedulersimpleimpl.h
>   include_rtems_score_HEADERS += include/rtems/score/schedulersmp.h
> @@ -119,6 +120,7 @@ libscore_a_SOURCES += src/mpci.c src/objectmp.c src/threadmp.c
>   endif
>
>   if HAS_SMP
> +libscore_a_SOURCES += src/schedulerprioritysmp.c
>   libscore_a_SOURCES += src/schedulersimplesmp.c
>   libscore_a_SOURCES += src/schedulersmpstartidle.c
>   libscore_a_SOURCES += src/smp.c
> diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
> index 9f45f21..1c85150 100644
> --- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
> +++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
> @@ -186,6 +186,23 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(
>     _Scheduler_Update_heir( heir, force_dispatch );
>   }
>
> +RTEMS_INLINE_ROUTINE void _Scheduler_priority_Update_body(
> +  Thread_Control *thread,
> +  Chain_Control *ready_queues
> +)
> +{
> +  Scheduler_priority_Per_thread *sched_info_of_thread =
> +    _Scheduler_priority_Get_scheduler_info( thread );
> +
> +  sched_info_of_thread->ready_chain =
> +    &ready_queues[ thread->current_priority ];
> +
> +  _Priority_bit_map_Initialize_information(
> +    &sched_info_of_thread->Priority_map,
> +    thread->current_priority
> +  );
> +}
> +
>   /**
>    * @brief Priority comparison.
>    *
> diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmp.h b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
> new file mode 100644
> index 0000000..6eaf9fa
> --- /dev/null
> +++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
> @@ -0,0 +1,94 @@
> +/**
> + * @file
> + *
> + * @ingroup ScoreSchedulerPrioritySMP
> + *
> + * @brief Deterministic Priority SMP Scheduler API
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * 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.
> + */
> +
> +#ifndef _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H
> +#define _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H
> +
> +#include <rtems/score/scheduler.h>
> +#include <rtems/score/schedulerpriority.h>
> +#include <rtems/score/schedulersmp.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +/**
> + * @defgroup ScoreSchedulerPrioritySMP Deterministic Priority SMP Scheduler
> + *
> + * @ingroup ScoreScheduler
> + *
> + * This is an implementation of the global job-level fixed priority scheduler
> + * (G-JLFP).  It uses one ready chain per priority to ensure constant time
> + * insert operations.  The scheduled chain uses linear insert operations and
> + * has at most processor count entries.  Since the processor and priority count
> + * are constants all scheduler operations complete in a bounded execution time.
> + *
> + * The thread preempt mode will be ignored.
> + *
> + * @{
> + */
> +
> +/**
> + * @brief Entry points for the Simple SMP Scheduler.
> + */
> +#define SCHEDULER_PRIORITY_SMP_ENTRY_POINTS \
> +  { \
> +    _Scheduler_priority_SMP_Initialize, \
> +    _Scheduler_priority_SMP_Schedule, \
> +    _Scheduler_priority_SMP_Yield, \
> +    _Scheduler_priority_SMP_Block, \
> +    _Scheduler_priority_SMP_Enqueue_fifo, \
> +    _Scheduler_priority_Allocate, \
> +    _Scheduler_priority_Free, \
> +    _Scheduler_priority_SMP_Update, \
> +    _Scheduler_priority_SMP_Enqueue_fifo, \
> +    _Scheduler_priority_SMP_Enqueue_lifo, \
> +    _Scheduler_priority_SMP_Extract, \
> +    _Scheduler_priority_Priority_compare, \
> +    _Scheduler_default_Release_job, \
> +    _Scheduler_default_Tick, \
> +    _Scheduler_SMP_Start_idle \
> +  }
> +
> +void _Scheduler_priority_SMP_Initialize( void );
> +
> +void _Scheduler_priority_SMP_Schedule( Thread_Control *thread );
> +
> +void _Scheduler_priority_SMP_Block( Thread_Control *thread );
> +
> +void _Scheduler_priority_SMP_Update( Thread_Control *thread );
> +
> +void _Scheduler_priority_SMP_Enqueue_fifo( Thread_Control *thread );
> +
> +void _Scheduler_priority_SMP_Enqueue_lifo( Thread_Control *thread );
> +
> +void _Scheduler_priority_SMP_Extract( Thread_Control *thread );
> +
> +void _Scheduler_priority_SMP_Yield( Thread_Control *thread );
> +
> +/** @} */
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H */
> diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
> index 4e645f4..79a18b5 100644
> --- a/cpukit/score/preinstall.am
> +++ b/cpukit/score/preinstall.am
> @@ -195,6 +195,10 @@ $(PROJECT_INCLUDE)/rtems/score/schedulerpriorityimpl.h: include/rtems/score/sche
>          $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulerpriorityimpl.h
>   PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulerpriorityimpl.h
>
> +$(PROJECT_INCLUDE)/rtems/score/schedulerprioritysmp.h: include/rtems/score/schedulerprioritysmp.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulerprioritysmp.h
> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulerprioritysmp.h
> +
>   $(PROJECT_INCLUDE)/rtems/score/schedulersimple.h: include/rtems/score/schedulersimple.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
>          $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulersimple.h
>   PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulersimple.h
> diff --git a/cpukit/score/src/schedulerprioritysmp.c b/cpukit/score/src/schedulerprioritysmp.c
> new file mode 100644
> index 0000000..4a868cd
> --- /dev/null
> +++ b/cpukit/score/src/schedulerprioritysmp.c
> @@ -0,0 +1,217 @@
> +/**
> + * @file
> + *
> + * @brief Deterministic Priority SMP Scheduler Implementation
> + *
> + * @ingroup ScoreSchedulerSMP
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * 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.
> + */
> +
> +#if HAVE_CONFIG_H
> +  #include "config.h"
> +#endif
> +
> +#include <rtems/score/schedulerprioritysmp.h>
> +#include <rtems/score/schedulerpriorityimpl.h>
> +#include <rtems/score/schedulersmpimpl.h>
> +#include <rtems/score/wkspace.h>
> +
> +static Scheduler_SMP_Control *_Scheduler_priority_SMP_Instance( void )
> +{
> +  return _Scheduler.information;
> +}
> +
> +void _Scheduler_priority_SMP_Initialize( void )
> +{
> +  Scheduler_SMP_Control *self = _Workspace_Allocate_or_fatal_error(
> +    sizeof( *self ) + PRIORITY_MAXIMUM * sizeof( Chain_Control )
> +  );
> +
> +  _Chain_Initialize_empty( &self->scheduled );
> +  _Scheduler_priority_Ready_queue_initialize( &self->ready[ 0 ] );
> +
> +  _Scheduler.information = self;
> +}
> +
> +void _Scheduler_priority_SMP_Update( Thread_Control *thread )
> +{
> +  Scheduler_SMP_Control *self = _Scheduler_priority_SMP_Instance();
> +
> +  _Scheduler_priority_Update_body( thread, &self->ready[ 0 ] );
> +}
> +
> +static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
> +  Scheduler_SMP_Control *self
> +)
> +{
> +  Thread_Control *highest_ready = NULL;
> +
> +  if ( !_Priority_bit_map_Is_empty() ) {
> +    highest_ready = _Scheduler_priority_Ready_queue_first( &self->ready[ 0 ] );
> +  }
> +
> +  return highest_ready;
> +}
> +
> +static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
> +  Scheduler_SMP_Control *self,
> +  Thread_Control *scheduled_to_ready
> +)
> +{
> +  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
> +  _Scheduler_priority_Ready_queue_enqueue_first( scheduled_to_ready );
> +}
> +
> +static void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
> +  Scheduler_SMP_Control *self,
> +  Thread_Control *ready_to_scheduled
> +)
> +{
> +  _Scheduler_priority_Ready_queue_extract( ready_to_scheduled );
> +  _Scheduler_simple_Insert_priority_fifo(
> +    &self->scheduled,
> +    ready_to_scheduled
> +  );
> +}
> +
> +static void _Scheduler_priority_SMP_Insert_ready_lifo(
> +  Scheduler_SMP_Control *self,
> +  Thread_Control *thread
> +)
> +{
> +  _Scheduler_priority_Ready_queue_enqueue( thread );
> +}
> +
> +static void _Scheduler_priority_SMP_Insert_ready_fifo(
> +  Scheduler_SMP_Control *self,
> +  Thread_Control *thread
> +)
> +{
> +  _Scheduler_priority_Ready_queue_enqueue_first( thread );
> +}
> +
> +static void _Scheduler_priority_SMP_Do_extract(
> +  Scheduler_SMP_Control *self,
> +  Thread_Control *thread
> +)
> +{
> +  bool is_scheduled = thread->is_scheduled;
> +
> +  ( void ) self;
> +
> +  thread->is_in_the_air = is_scheduled;
> +  thread->is_scheduled = false;
> +
> +  if ( is_scheduled ) {
> +    _Chain_Extract_unprotected( &thread->Object.Node );
> +  } else {
> +    _Scheduler_priority_Ready_queue_extract( thread );
> +  }
> +}
> +
> +void _Scheduler_priority_SMP_Block( Thread_Control *thread )
> +{
> +  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
> +
> +  _Scheduler_SMP_Block(
> +    self,
> +    thread,
> +    _Scheduler_priority_SMP_Do_extract,
> +    _Scheduler_priority_SMP_Get_highest_ready,
> +    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
> +  );
> +}
> +
> +static void _Scheduler_priority_SMP_Enqueue_ordered(
> +  Scheduler_SMP_Control *self,
> +  Thread_Control *thread,
> +  Chain_Node_order order,
> +  Scheduler_SMP_Insert insert_ready,
> +  Scheduler_SMP_Insert insert_scheduled
> +)
> +{
> +  _Scheduler_SMP_Enqueue_ordered(
> +    self,
> +    thread,
> +    order,
> +    _Scheduler_priority_SMP_Get_highest_ready,
> +    insert_ready,
> +    insert_scheduled,
> +    _Scheduler_priority_SMP_Move_from_ready_to_scheduled,
> +    _Scheduler_priority_SMP_Move_from_scheduled_to_ready
> +  );
> +}
> +
> +void _Scheduler_priority_SMP_Enqueue_lifo( Thread_Control *thread )
> +{
> +  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
> +
> +  _Scheduler_priority_SMP_Enqueue_ordered(
> +    self,
> +    thread,
> +    _Scheduler_simple_Insert_priority_lifo_order,
> +    _Scheduler_priority_SMP_Insert_ready_lifo,
> +    _Scheduler_SMP_Insert_scheduled_lifo
> +  );
> +}
> +
> +void _Scheduler_priority_SMP_Enqueue_fifo( Thread_Control *thread )
> +{
> +  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
> +
> +  _Scheduler_priority_SMP_Enqueue_ordered(
> +    self,
> +    thread,
> +    _Scheduler_simple_Insert_priority_fifo_order,
> +    _Scheduler_priority_SMP_Insert_ready_fifo,
> +    _Scheduler_SMP_Insert_scheduled_fifo
> +  );
> +}
> +
> +void _Scheduler_priority_SMP_Extract( Thread_Control *thread )
> +{
> +  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
> +
> +  _Scheduler_SMP_Extract(
> +    self,
> +    thread,
> +    _Scheduler_priority_SMP_Do_extract
> +  );
> +}
> +
> +void _Scheduler_priority_SMP_Yield( Thread_Control *thread )
> +{
> +  ISR_Level level;
> +
> +  _ISR_Disable( level );
> +
> +  _Scheduler_priority_SMP_Extract( thread );
> +  _Scheduler_priority_SMP_Enqueue_fifo( thread );
> +
> +  _ISR_Enable( level );
> +}
> +
> +void _Scheduler_priority_SMP_Schedule( Thread_Control *thread )
> +{
> +  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
> +
> +  _Scheduler_SMP_Schedule(
> +    self,
> +    thread,
> +    _Scheduler_priority_SMP_Get_highest_ready,
> +    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
> +  );
> +}
> diff --git a/cpukit/score/src/schedulerpriorityupdate.c b/cpukit/score/src/schedulerpriorityupdate.c
> index de3f026..062b369 100644
> --- a/cpukit/score/src/schedulerpriorityupdate.c
> +++ b/cpukit/score/src/schedulerpriorityupdate.c
> @@ -25,15 +25,7 @@ void _Scheduler_priority_Update(
>     Thread_Control    *the_thread
>   )
>   {
> -  Scheduler_priority_Per_thread *sched_info_of_thread =
> -    _Scheduler_priority_Get_scheduler_info( the_thread );
>     Chain_Control *ready_queues = _Scheduler_priority_Get_ready_queues();
>
> -  sched_info_of_thread->ready_chain =
> -    &ready_queues[ the_thread->current_priority ];
> -
> -  _Priority_bit_map_Initialize_information(
> -    &sched_info_of_thread->Priority_map,
> -    the_thread->current_priority
> -  );
> +  _Scheduler_priority_Update_body( the_thread, ready_queues );
>   }
> diff --git a/testsuites/smptests/smpmigration01/smpmigration01.scn b/testsuites/smptests/smpmigration01/smpmigration01.scn
> index c5a2106..b2b56ff 100644
> --- a/testsuites/smptests/smpmigration01/smpmigration01.scn
> +++ b/testsuites/smptests/smpmigration01/smpmigration01.scn
> @@ -1,17 +1,17 @@
>   *** TEST SMPMIGRATION 1 ***
>   runner 0
> -        cpu 0 tokens 530399
> -        cpu 0 cycles 10077490
> -        cpu 1 tokens 530399
> -        cpu 1 cycles 10071429
> +        cpu 0 tokens 453284
> +        cpu 0 cycles 14955317
> +        cpu 1 tokens 453283
> +        cpu 1 cycles 14978390
>   runner 1
> -        cpu 0 tokens 530399
> -        cpu 0 cycles 5978212
> -        cpu 1 tokens 530399
> -        cpu 1 cycles 7951897
> +        cpu 0 tokens 453283
> +        cpu 0 cycles 21302793
> +        cpu 1 tokens 453283
> +        cpu 1 cycles 21318817
>   runner 2
> -        cpu 0 tokens 530399
> -        cpu 0 cycles 10070929
> -        cpu 1 tokens 530398
> -        cpu 1 cycles 10106437
> +        cpu 0 tokens 453283
> +        cpu 0 cycles 19973312
> +        cpu 1 tokens 453283
> +        cpu 1 cycles 21315227
>   *** END OF TEST SMPMIGRATION 1 ***
> --
> 1.7.7
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel


-- 
Joel Sherrill, Ph.D.             Director of Research & Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
Support Available                (256) 722-9985




More information about the devel mailing list