summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/schedulersimplesmp.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-06-06 15:41:00 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-06-14 16:26:08 +0200
commita936aa49b5171915aee6c7cecc0b84a3912fd692 (patch)
treeec2c8adb89b3659a583e2c208c69dba3d4558073 /cpukit/score/src/schedulersimplesmp.c
parentscheduler: Simplify simple scheduler (diff)
downloadrtems-a936aa49b5171915aee6c7cecc0b84a3912fd692.tar.bz2
scheduler: New simple SMP scheduler implementation
The new Simple SMP Scheduler allocates a processor for the processor count highest priority ready threads. The thread priority and position in the ready chain are the only information to determine the scheduling decision. Threads with an allocated processor are in the scheduled chain. After initialization the scheduled chain has exactly processor count nodes. Each processor has exactly one allocated thread after initialization. All enqueue and extract operations may exchange threads with the scheduled chain. One thread will be added and another will be removed. The scheduled and ready chain is ordered according to the thread priority order. The chain insert operations are O(count of ready threads), thus this scheduler is unsuitable for most real-time applications. The thread preempt mode will be ignored.
Diffstat (limited to 'cpukit/score/src/schedulersimplesmp.c')
-rw-r--r--cpukit/score/src/schedulersimplesmp.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
new file mode 100644
index 0000000000..ec1b0e27f4
--- /dev/null
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -0,0 +1,182 @@
+/**
+ * @file
+ *
+ * @brief Simple SMP Scheduler Implementation
+ *
+ * @ingroup ScoreSchedulerSMP
+ */
+
+/*
+ * Copyright (c) 2013 embedded brains GmbH.
+ *
+ * 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/schedulersimplesmp.h>
+
+static Scheduler_simple_smp_Control *_Scheduler_simple_smp_Instance( void )
+{
+ return _Scheduler.information;
+}
+
+void _Scheduler_simple_smp_Initialize( void )
+{
+ Scheduler_simple_smp_Control *self =
+ _Workspace_Allocate_or_fatal_error( sizeof( *self ) );
+
+ _Chain_Initialize_empty( &self->ready );
+ _Chain_Initialize_empty( &self->scheduled );
+
+ _Scheduler.information = self;
+}
+
+static void _Scheduler_simple_smp_Allocate_processor(
+ Thread_Control *scheduled,
+ Thread_Control *victim
+)
+{
+ Per_CPU_Control *cpu_of_scheduled = scheduled->cpu;
+ Per_CPU_Control *cpu_of_victim = victim->cpu;
+ Thread_Control *heir;
+
+ scheduled->is_scheduled = true;
+ victim->is_scheduled = false;
+
+ if ( scheduled->is_executing ) {
+ heir = cpu_of_scheduled->heir;
+ cpu_of_scheduled->heir = scheduled;
+ } else {
+ heir = scheduled;
+ }
+
+ if ( heir != victim ) {
+ heir->cpu = cpu_of_victim;
+ cpu_of_victim->heir = heir;
+ cpu_of_victim->dispatch_necessary = true;
+ }
+}
+
+static void _Scheduler_simple_smp_Move_from_scheduled_to_ready(
+ Chain_Control *ready_chain,
+ Thread_Control *scheduled_to_ready
+)
+{
+ _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
+ _Scheduler_simple_Insert_priority_lifo( ready_chain, scheduled_to_ready );
+}
+
+static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
+ Chain_Control *scheduled_chain,
+ Thread_Control *ready_to_scheduled
+)
+{
+ _Chain_Extract_unprotected( &ready_to_scheduled->Object.Node );
+ _Scheduler_simple_Insert_priority_fifo( scheduled_chain, ready_to_scheduled );
+}
+
+static void _Scheduler_simple_smp_Insert(
+ Chain_Control *chain,
+ Thread_Control *thread,
+ Chain_Node_order order
+)
+{
+ _Chain_Insert_ordered_unprotected( chain, &thread->Object.Node, order );
+}
+
+static void _Scheduler_simple_smp_Enqueue_ordered(
+ Thread_Control *thread,
+ Chain_Node_order order
+)
+{
+ Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance();
+
+ /*
+ * The scheduled chain has exactly processor count nodes after
+ * initialization, thus the lowest priority scheduled thread exists.
+ */
+ Thread_Control *lowest_scheduled =
+ (Thread_Control *) _Chain_Last( &self->scheduled );
+
+ if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
+ _Scheduler_simple_smp_Allocate_processor( thread, lowest_scheduled );
+
+ _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
+
+ _Scheduler_simple_smp_Move_from_scheduled_to_ready(
+ &self->ready,
+ lowest_scheduled
+ );
+ } else {
+ _Scheduler_simple_smp_Insert( &self->ready, thread, order );
+ }
+}
+
+void _Scheduler_simple_smp_Enqueue_priority_lifo( Thread_Control *thread )
+{
+ _Scheduler_simple_smp_Enqueue_ordered(
+ thread,
+ _Scheduler_simple_Insert_priority_lifo_order
+ );
+}
+
+void _Scheduler_simple_smp_Enqueue_priority_fifo( Thread_Control *thread )
+{
+ _Scheduler_simple_smp_Enqueue_ordered(
+ thread,
+ _Scheduler_simple_Insert_priority_fifo_order
+ );
+}
+
+void _Scheduler_simple_smp_Extract( Thread_Control *thread )
+{
+ Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance();
+
+ _Chain_Extract_unprotected( &thread->Object.Node );
+
+ if ( thread->is_scheduled ) {
+ Thread_Control *highest_ready =
+ (Thread_Control *) _Chain_First( &self->ready );
+
+ _Scheduler_simple_smp_Allocate_processor( highest_ready, thread );
+
+ _Scheduler_simple_smp_Move_from_ready_to_scheduled(
+ &self->scheduled,
+ highest_ready
+ );
+ }
+}
+
+void _Scheduler_simple_smp_Yield( Thread_Control *thread )
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ _Scheduler_simple_smp_Extract( thread );
+ _Scheduler_simple_smp_Enqueue_priority_fifo( thread );
+
+ _ISR_Enable( level );
+}
+
+void _Scheduler_simple_smp_Schedule( void )
+{
+ /* Nothing to do */
+}
+
+void _Scheduler_simple_smp_Start_idle(
+ Thread_Control *thread,
+ Per_CPU_Control *cpu
+)
+{
+ Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance();
+
+ thread->is_scheduled = true;
+ thread->cpu = cpu;
+ _Chain_Append_unprotected( &self->scheduled, &thread->Object.Node );
+}