summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-30 14:08:18 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-07-01 11:51:49 +0200
commitc0bd0064ac41f0602c0abfe494dbe140d7c5282f (patch)
treeaaa200033234cf2d3833305f13565171521b0d26 /cpukit
parentscore: Workaround for #2751 (diff)
downloadrtems-c0bd0064ac41f0602c0abfe494dbe140d7c5282f.tar.bz2
rtems: Fix rtems_task_set_scheduler() API
Task priorities are only valid within a scheduler instance. The rtems_task_set_scheduler() directive moves a task from one scheduler instance to another using the current priority of the thread. However, the current task priority of the source scheduler instance is undefined in the target scheduler instance. Add a third parameter to specify the priority. Close #2749.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/rtems/include/rtems/rtems/tasks.h23
-rw-r--r--cpukit/rtems/src/tasksetscheduler.c21
-rw-r--r--cpukit/score/include/rtems/score/schedulerimpl.h101
-rw-r--r--cpukit/score/include/rtems/score/status.h2
4 files changed, 89 insertions, 58 deletions
diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h
index 6273228f85..e690e60557 100644
--- a/cpukit/rtems/include/rtems/rtems/tasks.h
+++ b/cpukit/rtems/include/rtems/rtems/tasks.h
@@ -448,23 +448,32 @@ rtems_status_code rtems_task_get_scheduler(
);
/**
- * @brief Sets the scheduler of a task.
+ * @brief Sets the scheduler instance of a task.
*
- * The scheduler of a task is initialized to the scheduler of the task that
- * created it.
+ * Initially, the scheduler instance of a task is set to the scheduler instance
+ * of the task that created it. This directive allows to move a task from its
+ * current scheduler instance to another specified by the scheduler identifier.
*
* @param[in] task_id Identifier of the task. Use @ref RTEMS_SELF to select
- * the executing task.
- * @param[in] scheduler_id Identifier of the scheduler.
+ * the executing task.
+ * @param[in] scheduler_id Identifier of the scheduler instance.
+ * @param[in] priority The task priority with respect to the new scheduler
+ * instance. The real and initial priority of the task is set to this value.
+ * The initial priority is used by rtems_task_restart() for example.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_ILLEGAL_ON_REMOTE_OBJECT Directive is illegal on remote tasks.
* @retval RTEMS_INVALID_ID Invalid task or scheduler identifier.
+ * @retval RTEMS_INVALID_PRIORITY Invalid priority.
+ * @retval RTEMS_RESOURCE_IN_USE The task owns resources which deny a scheduler
+ * change.
*
* @see rtems_scheduler_ident().
*/
rtems_status_code rtems_task_set_scheduler(
- rtems_id task_id,
- rtems_id scheduler_id
+ rtems_id task_id,
+ rtems_id scheduler_id,
+ rtems_task_priority priority
);
/**
diff --git a/cpukit/rtems/src/tasksetscheduler.c b/cpukit/rtems/src/tasksetscheduler.c
index 36fb46d629..175f235f02 100644
--- a/cpukit/rtems/src/tasksetscheduler.c
+++ b/cpukit/rtems/src/tasksetscheduler.c
@@ -16,12 +16,14 @@
#include "config.h"
#endif
-#include <rtems/rtems/tasks.h>
+#include <rtems/rtems/tasksimpl.h>
+#include <rtems/rtems/statusimpl.h>
#include <rtems/score/schedulerimpl.h>
rtems_status_code rtems_task_set_scheduler(
- rtems_id task_id,
- rtems_id scheduler_id
+ rtems_id task_id,
+ rtems_id scheduler_id,
+ rtems_task_priority priority
)
{
const Scheduler_Control *scheduler;
@@ -30,12 +32,19 @@ rtems_status_code rtems_task_set_scheduler(
ISR_lock_Context state_lock_context;
Per_CPU_Control *cpu_self;
void *lock;
- bool ok;
+ bool valid;
+ Priority_Control core_priority;
+ Status_Control status;
if ( !_Scheduler_Get_by_id( scheduler_id, &scheduler ) ) {
return RTEMS_INVALID_ID;
}
+ core_priority = _RTEMS_Priority_To_core( scheduler, priority, &valid );
+ if ( !valid ) {
+ return RTEMS_INVALID_PRIORITY;
+ }
+
the_thread = _Thread_Get( task_id, &lock_context );
if ( the_thread == NULL ) {
@@ -54,10 +63,10 @@ rtems_status_code rtems_task_set_scheduler(
lock = _Thread_Lock_acquire( the_thread, &lock_context );
_Thread_State_acquire_critical( the_thread, &state_lock_context );
- ok = _Scheduler_Set( scheduler, the_thread );
+ status = _Scheduler_Set( scheduler, the_thread, core_priority );
_Thread_State_release_critical( the_thread, &state_lock_context );
_Thread_Lock_release( lock, &lock_context );
_Thread_Dispatch_enable( cpu_self );
- return ok ? RTEMS_SUCCESSFUL : RTEMS_INCORRECT_STATE;
+ return _Status_Get( status );
}
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 9885adf210..2007b30b9d 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -23,6 +23,7 @@
#include <rtems/score/scheduler.h>
#include <rtems/score/cpusetimpl.h>
#include <rtems/score/smpimpl.h>
+#include <rtems/score/status.h>
#include <rtems/score/threadimpl.h>
#ifdef __cplusplus
@@ -580,51 +581,6 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_Has_processor_ownership(
#endif
}
-RTEMS_INLINE_ROUTINE bool _Scheduler_Set(
- const Scheduler_Control *scheduler,
- Thread_Control *the_thread
-)
-{
-#if defined(RTEMS_SMP)
- const Scheduler_Control *current_scheduler;
- States_Control current_state;
-
- current_scheduler = _Scheduler_Get( the_thread );
-
- if ( current_scheduler == scheduler ) {
- return true;
- }
-
- if ( _Thread_Owns_resources( the_thread ) ) {
- return false;
- }
-
- current_state = the_thread->current_state;
-
- if ( _States_Is_ready( current_state ) ) {
- _Scheduler_Block( the_thread );
- }
-
- _Scheduler_Node_destroy( current_scheduler, the_thread );
- the_thread->Scheduler.own_control = scheduler;
- the_thread->Scheduler.control = scheduler;
- _Scheduler_Node_initialize(
- scheduler,
- the_thread,
- the_thread->current_priority
- );
-
- if ( _States_Is_ready( current_state ) ) {
- _Scheduler_Unblock( the_thread );
- }
-
- return true;
-#else
- (void) scheduler;
- return true;
-#endif
-}
-
#if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
RTEMS_INLINE_ROUTINE void _Scheduler_Get_processor_set(
@@ -1472,6 +1428,61 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir(
}
}
+RTEMS_INLINE_ROUTINE Status_Control _Scheduler_Set(
+ const Scheduler_Control *new_scheduler,
+ Thread_Control *the_thread,
+ Priority_Control priority
+)
+{
+ Scheduler_Node *own_node;
+
+ if (
+ _Thread_Owns_resources( the_thread )
+ || the_thread->Wait.queue != NULL
+ ) {
+ return STATUS_RESOURCE_IN_USE;
+ }
+
+ the_thread->current_priority = priority;
+ the_thread->real_priority = priority;
+ the_thread->Start.initial_priority = priority;
+
+ own_node = _Scheduler_Thread_get_own_node( the_thread );
+
+#if defined(RTEMS_SMP)
+ {
+ const Scheduler_Control *old_scheduler;
+
+ old_scheduler = _Scheduler_Get( the_thread );
+
+ if ( old_scheduler != new_scheduler ) {
+ States_Control current_state;
+
+ current_state = the_thread->current_state;
+
+ if ( _States_Is_ready( current_state ) ) {
+ _Scheduler_Block( the_thread );
+ }
+
+ _Scheduler_Node_destroy( old_scheduler, the_thread );
+ the_thread->Scheduler.own_control = new_scheduler;
+ the_thread->Scheduler.control = new_scheduler;
+ _Scheduler_Node_initialize( new_scheduler, the_thread, priority );
+
+ if ( _States_Is_ready( current_state ) ) {
+ _Scheduler_Unblock( the_thread );
+ }
+
+ return STATUS_SUCCESSFUL;
+ }
+ }
+#endif
+
+ _Scheduler_Node_set_priority( own_node, priority, false );
+ _Scheduler_Update_priority( the_thread );
+ return STATUS_SUCCESSFUL;
+}
+
/** @} */
#ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/status.h b/cpukit/score/include/rtems/score/status.h
index d30f731a70..a4b2de9d26 100644
--- a/cpukit/score/include/rtems/score/status.h
+++ b/cpukit/score/include/rtems/score/status.h
@@ -83,6 +83,8 @@ typedef enum {
STATUS_BUILD( STATUS_CLASSIC_INCORRECT_STATE, EDEADLK ),
STATUS_FLUSHED =
STATUS_BUILD( STATUS_CLASSIC_UNSATISFIED, EAGAIN ),
+ STATUS_INCORRECT_STATE =
+ STATUS_BUILD( STATUS_CLASSIC_INCORRECT_STATE, EINVAL ),
STATUS_INTERRUPTED =
STATUS_BUILD( STATUS_CLASSIC_INTERNAL_ERROR, EINTR ),
STATUS_INVALID_NUMBER =