[PATCH] score: PR2136: Fix _Thread_Change_priority()
Sebastian Huber
sebastian.huber at embedded-brains.de
Thu Aug 8 13:47:23 UTC 2013
Add call to _Scheduler_Schedule() in missing path after
_Thread_Set_transient() in _Thread_Change_priority(). See also
sptests/spintrcritical19.
Add thread parameter to _Scheduler_Schedule(). This parameter is
currently unused but may be used in future SMP schedulers.
Do heir selection in _Scheduler_Schedule(). Use
_Scheduler_Update_heir() for this in the particular scheduler
implementation.
---
cpukit/score/Makefile.am | 1 +
cpukit/score/include/rtems/score/scheduler.h | 2 +-
cpukit/score/include/rtems/score/scheduleredf.h | 2 +-
.../score/include/rtems/score/scheduleredfimpl.h | 56 ++++++++++++++++++++
cpukit/score/include/rtems/score/schedulerimpl.h | 20 ++++++-
.../score/include/rtems/score/schedulerpriority.h | 2 +-
.../include/rtems/score/schedulerpriorityimpl.h | 12 ++++-
cpukit/score/include/rtems/score/schedulersimple.h | 2 +-
.../include/rtems/score/schedulersimpleimpl.h | 16 +++++-
.../score/include/rtems/score/schedulersimplesmp.h | 2 +-
cpukit/score/include/rtems/score/threadimpl.h | 10 ----
cpukit/score/preinstall.am | 4 ++
cpukit/score/src/scheduleredfblock.c | 10 +---
cpukit/score/src/scheduleredfschedule.c | 12 +---
cpukit/score/src/scheduleredfyield.c | 9 +---
cpukit/score/src/schedulerpriorityblock.c | 9 +---
cpukit/score/src/schedulerpriorityschedule.c | 4 +-
cpukit/score/src/schedulersimpleblock.c | 10 +---
cpukit/score/src/schedulersimpleschedule.c | 9 +--
cpukit/score/src/schedulersimplesmp.c | 4 +-
cpukit/score/src/schedulersimpleyield.c | 5 +--
cpukit/score/src/threadchangepriority.c | 14 ++++--
22 files changed, 140 insertions(+), 75 deletions(-)
create mode 100644 cpukit/score/include/rtems/score/scheduleredfimpl.h
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index f3f76c5..584c53d 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -50,6 +50,7 @@ include_rtems_score_HEADERS += include/rtems/score/scheduler.h
include_rtems_score_HEADERS += include/rtems/score/schedulerimpl.h
include_rtems_score_HEADERS += include/rtems/score/schedulercbs.h
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
diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h
index a34387d..10a2a97 100644
--- a/cpukit/score/include/rtems/score/scheduler.h
+++ b/cpukit/score/include/rtems/score/scheduler.h
@@ -46,7 +46,7 @@ typedef struct {
void ( *initialize )(void);
/** Implements the scheduling decision logic (policy). */
- void ( *schedule )(void);
+ void ( *schedule )( Thread_Control *thread );
/**
* @brief Voluntarily yields the processor per the scheduling policy.
diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h
index b28bed1..01f91e6 100644
--- a/cpukit/score/include/rtems/score/scheduleredf.h
+++ b/cpukit/score/include/rtems/score/scheduleredf.h
@@ -129,7 +129,7 @@ void _Scheduler_EDF_Block(
* This kernel routine sets the heir thread to be the next ready thread
* in the rbtree ready queue.
*/
-void _Scheduler_EDF_Schedule( void );
+void _Scheduler_EDF_Schedule( Thread_Control *thread );
/**
* @brief Allocates EDF specific information of @a the_thread.
diff --git a/cpukit/score/include/rtems/score/scheduleredfimpl.h b/cpukit/score/include/rtems/score/scheduleredfimpl.h
new file mode 100644
index 0000000..04201bc
--- /dev/null
+++ b/cpukit/score/include/rtems/score/scheduleredfimpl.h
@@ -0,0 +1,56 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSchedulerEDF
+ *
+ * @brief EDF Scheduler Implementation
+ */
+
+/*
+ * Copryight (c) 2011 Petr Benes.
+ * Copyright (C) 2011 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.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_SCHEDULEREDFIMPL_H
+#define _RTEMS_SCORE_SCHEDULEREDFIMPL_H
+
+#include <rtems/score/scheduleredf.h>
+#include <rtems/score/schedulerimpl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup ScoreSchedulerEDF EDF
+ *
+ * @{
+ */
+
+RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
+ Thread_Control *thread,
+ bool force_dispatch
+)
+{
+ RBTree_Node *first = _RBTree_First(&_Scheduler_EDF_Ready_queue, RBT_LEFT);
+ Scheduler_EDF_Per_thread *sched_info =
+ _RBTree_Container_of(first, Scheduler_EDF_Per_thread, Node);
+ Thread_Control *heir = (Thread_Control *) sched_info->thread;
+
+ ( void ) thread;
+
+ _Scheduler_Update_heir( heir, force_dispatch );
+}
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 5ea4bb8..d40d22f 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -20,6 +20,7 @@
#define _RTEMS_SCORE_SCHEDULERIMPL_H
#include <rtems/score/scheduler.h>
+#include <rtems/score/threadimpl.h>
#ifdef __cplusplus
extern "C" {
@@ -59,10 +60,12 @@ void _Scheduler_Handler_initialization( void );
*
* This kernel routine implements the scheduling decision logic for
* the scheduler. It does NOT dispatch.
+ *
+ * @param[in] thread The thread which state changed previously.
*/
-RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( void )
+RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( Thread_Control *thread )
{
- _Scheduler.Operations.schedule();
+ _Scheduler.Operations.schedule( thread );
}
/**
@@ -237,6 +240,19 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Start_idle(
( *_Scheduler.Operations.start_idle )( thread, processor );
}
+RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir(
+ Thread_Control *heir,
+ bool force_dispatch
+)
+{
+ Thread_Control *executing = _Thread_Executing;
+
+ _Thread_Heir = heir;
+
+ if ( executing != heir && ( force_dispatch || executing->is_preemptible ) )
+ _Thread_Dispatch_necessary = true;
+}
+
/**
* Macro testing whether @a p1 has lower priority than @a p2
* in the intuitive sense of priority.
diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h
index 6964943..cbe0066 100644
--- a/cpukit/score/include/rtems/score/schedulerpriority.h
+++ b/cpukit/score/include/rtems/score/schedulerpriority.h
@@ -93,7 +93,7 @@ void _Scheduler_priority_Block(
* This kernel routine sets the heir thread to be the next ready thread
* by invoking the_scheduler->ready_queue->operations->first().
*/
-void _Scheduler_priority_Schedule(void);
+void _Scheduler_priority_Schedule( Thread_Control *thread );
/**
* @brief Allocates @a the_thread->scheduler.
diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
index b69a910..6c57952 100644
--- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
@@ -23,6 +23,7 @@
#include <rtems/score/schedulerpriority.h>
#include <rtems/score/chainimpl.h>
#include <rtems/score/prioritybitmapimpl.h>
+#include <rtems/score/schedulerimpl.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
@@ -188,11 +189,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_requeue(
* This kernel routine implements scheduling decision logic
* for priority-based scheduling.
*/
-RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(void)
+RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(
+ Thread_Control *thread,
+ bool force_dispatch
+)
{
- _Thread_Heir = _Scheduler_priority_Ready_queue_first(
+ Thread_Control *heir = _Scheduler_priority_Ready_queue_first(
(Chain_Control *) _Scheduler.information
);
+
+ ( void ) thread;
+
+ _Scheduler_Update_heir( heir, force_dispatch );
}
/**
diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h
index 5180d36..477ea2c 100644
--- a/cpukit/score/include/rtems/score/schedulersimple.h
+++ b/cpukit/score/include/rtems/score/schedulersimple.h
@@ -66,7 +66,7 @@ void _Scheduler_simple_Initialize( void );
* on the ready queue by getting the first node in the scheduler
* information.
*/
-void _Scheduler_simple_Schedule( void );
+void _Scheduler_simple_Schedule( Thread_Control *thread );
/**
* @brief Invoked when a thread wishes to voluntarily
diff --git a/cpukit/score/include/rtems/score/schedulersimpleimpl.h b/cpukit/score/include/rtems/score/schedulersimpleimpl.h
index 076d1a9..51d3774 100644
--- a/cpukit/score/include/rtems/score/schedulersimpleimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersimpleimpl.h
@@ -21,7 +21,7 @@
#include <rtems/score/schedulersimple.h>
#include <rtems/score/chainimpl.h>
-#include <rtems/score/thread.h>
+#include <rtems/score/schedulerimpl.h>
#ifdef __cplusplus
extern "C" {
@@ -96,6 +96,20 @@ RTEMS_INLINE_ROUTINE void _Scheduler_simple_Insert_priority_fifo(
);
}
+RTEMS_INLINE_ROUTINE void _Scheduler_simple_Schedule_body(
+ Thread_Control *thread,
+ bool force_dispatch
+)
+{
+ Thread_Control *heir = (Thread_Control *) _Chain_First(
+ (Chain_Control *) _Scheduler.information
+ );
+
+ ( void ) thread;
+
+ _Scheduler_Update_heir( heir, force_dispatch );
+}
+
/** @} */
#ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h
index 1b827cb..6cc87f3 100644
--- a/cpukit/score/include/rtems/score/schedulersimplesmp.h
+++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h
@@ -85,7 +85,7 @@ void _Scheduler_simple_smp_Extract( Thread_Control *thread );
void _Scheduler_simple_smp_Yield( Thread_Control *thread );
-void _Scheduler_simple_smp_Schedule( void );
+void _Scheduler_simple_smp_Schedule( Thread_Control *thread );
void _Scheduler_simple_smp_Start_idle(
Thread_Control *thread,
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 06d4ee6..a3b6904 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -498,16 +498,6 @@ RTEMS_INLINE_ROUTINE bool _Thread_Is_heir (
}
/**
- * This function returns true if the currently executing thread
- * is also the heir thread, and false otherwise.
- */
-
-RTEMS_INLINE_ROUTINE bool _Thread_Is_executing_also_the_heir( void )
-{
- return ( _Thread_Executing == _Thread_Heir );
-}
-
-/**
* This routine clears any blocking state for the_thread. It performs
* any necessary scheduling operations including the selection of
* a new heir thread.
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 509d1dd..e79b8bb 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -183,6 +183,10 @@ $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h: include/rtems/score/scheduleredf.
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h
+$(PROJECT_INCLUDE)/rtems/score/scheduleredfimpl.h: include/rtems/score/scheduleredfimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/scheduleredfimpl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/scheduleredfimpl.h
+
$(PROJECT_INCLUDE)/rtems/score/schedulerpriority.h: include/rtems/score/schedulerpriority.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulerpriority.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulerpriority.h
diff --git a/cpukit/score/src/scheduleredfblock.c b/cpukit/score/src/scheduleredfblock.c
index 4ad767d..c9e004f 100644
--- a/cpukit/score/src/scheduleredfblock.c
+++ b/cpukit/score/src/scheduleredfblock.c
@@ -19,8 +19,7 @@
#include "config.h"
#endif
-#include <rtems/score/scheduleredf.h>
-#include <rtems/score/threadimpl.h>
+#include <rtems/score/scheduleredfimpl.h>
void _Scheduler_EDF_Block(
Thread_Control *the_thread
@@ -30,9 +29,6 @@ void _Scheduler_EDF_Block(
/* TODO: flash critical section? */
- if ( _Thread_Is_heir( the_thread ) )
- _Scheduler_EDF_Schedule();
-
- if ( _Thread_Is_executing( the_thread ) )
- _Thread_Dispatch_necessary = true;
+ if ( _Thread_Is_executing( the_thread) || _Thread_Is_heir( the_thread ) )
+ _Scheduler_EDF_Schedule_body( the_thread, true );
}
diff --git a/cpukit/score/src/scheduleredfschedule.c b/cpukit/score/src/scheduleredfschedule.c
index dbe21dc..a71a5b5 100644
--- a/cpukit/score/src/scheduleredfschedule.c
+++ b/cpukit/score/src/scheduleredfschedule.c
@@ -18,15 +18,9 @@
#include "config.h"
#endif
-#include <rtems/system.h>
-#include <rtems/score/scheduler.h>
-#include <rtems/score/scheduleredf.h>
+#include <rtems/score/scheduleredfimpl.h>
-void _Scheduler_EDF_Schedule(void)
+void _Scheduler_EDF_Schedule( Thread_Control *thread )
{
- RBTree_Node *first = _RBTree_First(&_Scheduler_EDF_Ready_queue, RBT_LEFT);
- Scheduler_EDF_Per_thread *sched_info =
- _RBTree_Container_of(first, Scheduler_EDF_Per_thread, Node);
-
- _Thread_Heir = (Thread_Control *) sched_info->thread;
+ _Scheduler_EDF_Schedule_body( thread, false );
}
diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c
index 4ba9f79..fc5b13a 100644
--- a/cpukit/score/src/scheduleredfyield.c
+++ b/cpukit/score/src/scheduleredfyield.c
@@ -19,11 +19,7 @@
#include "config.h"
#endif
-#include <rtems/system.h>
-#include <rtems/score/isr.h>
-#include <rtems/score/scheduler.h>
-#include <rtems/score/scheduleredf.h>
-#include <rtems/score/thread.h>
+#include <rtems/score/scheduleredfimpl.h>
void _Scheduler_EDF_Yield( Thread_Control *thread )
{
@@ -44,8 +40,7 @@ void _Scheduler_EDF_Yield( Thread_Control *thread )
_ISR_Flash( level );
- _Scheduler_EDF_Schedule();
- _Thread_Dispatch_necessary = true;
+ _Scheduler_EDF_Schedule_body( thread, false );
_ISR_Enable( level );
}
diff --git a/cpukit/score/src/schedulerpriorityblock.c b/cpukit/score/src/schedulerpriorityblock.c
index 9e48101..982dcc2 100644
--- a/cpukit/score/src/schedulerpriorityblock.c
+++ b/cpukit/score/src/schedulerpriorityblock.c
@@ -21,7 +21,6 @@
#endif
#include <rtems/score/schedulerpriorityimpl.h>
-#include <rtems/score/threadimpl.h>
void _Scheduler_priority_Block(
Thread_Control *the_thread
@@ -31,10 +30,6 @@ void _Scheduler_priority_Block(
/* TODO: flash critical section? */
- if ( _Thread_Is_heir( the_thread ) )
- _Scheduler_priority_Schedule_body();
-
- if ( _Thread_Is_executing( the_thread ) )
- _Thread_Dispatch_necessary = true;
-
+ if ( _Thread_Is_executing( the_thread) || _Thread_Is_heir( the_thread ) )
+ _Scheduler_priority_Schedule_body( the_thread, true );
}
diff --git a/cpukit/score/src/schedulerpriorityschedule.c b/cpukit/score/src/schedulerpriorityschedule.c
index 22ed5f4..42647e6 100644
--- a/cpukit/score/src/schedulerpriorityschedule.c
+++ b/cpukit/score/src/schedulerpriorityschedule.c
@@ -20,7 +20,7 @@
#include <rtems/score/schedulerpriorityimpl.h>
-void _Scheduler_priority_Schedule(void)
+void _Scheduler_priority_Schedule( Thread_Control *thread )
{
- _Scheduler_priority_Schedule_body();
+ _Scheduler_priority_Schedule_body( thread, false );
}
diff --git a/cpukit/score/src/schedulersimpleblock.c b/cpukit/score/src/schedulersimpleblock.c
index b9753b5..450f1cc 100644
--- a/cpukit/score/src/schedulersimpleblock.c
+++ b/cpukit/score/src/schedulersimpleblock.c
@@ -19,8 +19,7 @@
#include "config.h"
#endif
-#include <rtems/score/schedulersimple.h>
-#include <rtems/score/threadimpl.h>
+#include <rtems/score/schedulersimpleimpl.h>
void _Scheduler_simple_Block(
Thread_Control *the_thread
@@ -28,9 +27,6 @@ void _Scheduler_simple_Block(
{
_Scheduler_simple_Extract(the_thread);
- if ( _Thread_Is_heir( the_thread ) )
- _Scheduler_simple_Schedule();
-
- if ( _Thread_Is_executing( the_thread ) )
- _Thread_Dispatch_necessary = true;
+ if ( _Thread_Is_executing( the_thread) || _Thread_Is_heir( the_thread ) )
+ _Scheduler_simple_Schedule_body( the_thread, true );
}
diff --git a/cpukit/score/src/schedulersimpleschedule.c b/cpukit/score/src/schedulersimpleschedule.c
index b60f096..5018e0b 100644
--- a/cpukit/score/src/schedulersimpleschedule.c
+++ b/cpukit/score/src/schedulersimpleschedule.c
@@ -18,12 +18,9 @@
#include "config.h"
#endif
-#include <rtems/score/schedulersimple.h>
-#include <rtems/score/chainimpl.h>
+#include <rtems/score/schedulersimpleimpl.h>
-void _Scheduler_simple_Schedule(void)
+void _Scheduler_simple_Schedule( Thread_Control *thread )
{
- _Thread_Heir = (Thread_Control *) _Chain_First(
- (Chain_Control *) _Scheduler.information
- );
+ _Scheduler_simple_Schedule_body( thread, false );
}
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
index db08b96..e261510 100644
--- a/cpukit/score/src/schedulersimplesmp.c
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -182,9 +182,9 @@ void _Scheduler_simple_smp_Yield( Thread_Control *thread )
_ISR_Enable( level );
}
-void _Scheduler_simple_smp_Schedule( void )
+void _Scheduler_simple_smp_Schedule( Thread_Control *thread )
{
- /* Nothing to do */
+ ( void ) thread;
}
void _Scheduler_simple_smp_Start_idle(
diff --git a/cpukit/score/src/schedulersimpleyield.c b/cpukit/score/src/schedulersimpleyield.c
index cb8dc6f..43784d6 100644
--- a/cpukit/score/src/schedulersimpleyield.c
+++ b/cpukit/score/src/schedulersimpleyield.c
@@ -32,10 +32,7 @@ void _Scheduler_simple_Yield( Thread_Control *thread )
_ISR_Flash( level );
- _Scheduler_simple_Schedule();
-
- if ( !_Thread_Is_heir( thread ) )
- _Thread_Dispatch_necessary = true;
+ _Scheduler_simple_Schedule_body( thread, false );
_ISR_Enable( level );
}
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
index b443731..b3d7984 100644
--- a/cpukit/score/src/threadchangepriority.c
+++ b/cpukit/score/src/threadchangepriority.c
@@ -62,6 +62,15 @@ void _Thread_Change_priority(
/* Only clear the transient state if it wasn't set already */
if ( ! _States_Is_transient( original_state ) )
the_thread->current_state = _States_Clear( STATES_TRANSIENT, state );
+
+ /*
+ * The thread may have new blocking states added by interrupt service
+ * routines after the change into the transient state. This will not
+ * result in a _Scheduler_Block() operation. Make sure we select an heir
+ * now.
+ */
+ _Scheduler_Schedule( the_thread );
+
_ISR_Enable( level );
if ( _States_Is_waiting_on_thread_queue( state ) ) {
_Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
@@ -91,10 +100,7 @@ void _Thread_Change_priority(
* We altered the set of thread priorities. So let's figure out
* who is the heir and if we need to switch to them.
*/
- _Scheduler_Schedule();
+ _Scheduler_Schedule( the_thread );
- if ( !_Thread_Is_executing_also_the_heir() &&
- _Thread_Executing->is_preemptible )
- _Thread_Dispatch_necessary = true;
_ISR_Enable( level );
}
--
1.7.7
More information about the devel
mailing list