From 99b35052ae1437dd17477152a6e04fa2e7e89c26 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 7 Aug 2013 15:35:47 +0200 Subject: smp: Add Deterministic Priority SMP Scheduler --- 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 | 212 +++++++++++++++++++++ cpukit/score/src/schedulerpriorityupdate.c | 10 +- 7 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 cpukit/score/include/rtems/score/schedulerprioritysmp.h create mode 100644 cpukit/score/src/schedulerprioritysmp.c (limited to 'cpukit') diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h index 31d28acec1..dc4fb5e415 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 @@ -658,6 +660,26 @@ const rtems_libio_helper rtems_fs_init_helper = _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) ) #endif +/* + * If the Deterministic Priority SMP Scheduler is selected, then configure for + * it. + */ +#if defined(CONFIGURE_SCHEDULER_PRIORITY_SMP) + #include + #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. */ diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index c5af9c7380..c9d2d477d3 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 9f45f21fcd..1c851505d4 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 0000000000..f19f1de3fa --- /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 + * + * + * 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 +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup ScoreSchedulerPrioritySMP Deterministic Priority SMP Scheduler + * + * @ingroup ScoreScheduler + * + * This is an implementation of the global fixed priority scheduler (G-FP). 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 4e645f4b48..79a18b5dd1 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 0000000000..fed94b11e2 --- /dev/null +++ b/cpukit/score/src/schedulerprioritysmp.c @@ -0,0 +1,212 @@ +/** + * @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 + * + * + * 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 +#include +#include +#include + +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_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 de3f02615c..062b36913c 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 ); } -- cgit v1.2.3