mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 06:14:27 +08:00
score: Simplify _Thread_Change_priority()
The function to change a thread priority was too complex. Simplify it with a new scheduler operation. This increases the average case performance due to the simplified logic. The interrupt disabled critical section is a bit prolonged since now the extract, update and enqueue steps are executed atomically. This should however not impact the worst-case interrupt latency since at least for the Deterministic Priority Scheduler this sequence can be carried out with a wee bit of instructions and no loops. Add _Scheduler_Change_priority() to replace the sequence of - _Thread_Set_transient(), - _Scheduler_Extract(), - _Scheduler_Enqueue(), and - _Scheduler_Enqueue_first(). Delete STATES_TRANSIENT, _States_Is_transient() and _Thread_Set_transient() since this state is now superfluous. With this change it is possible to get rid of the SCHEDULER_SMP_NODE_IN_THE_AIR state. This considerably simplifies the implementation of the new SMP locking protocols.
This commit is contained in:
@@ -913,8 +913,7 @@ rtems_capture_switch_task (rtems_tcb* current_task,
|
||||
rtems_capture_task_t* ht;
|
||||
|
||||
|
||||
if (_States_Is_transient (current_task->current_state)
|
||||
|| _States_Is_dormant (current_task->current_state))
|
||||
if (_States_Is_dormant (current_task->current_state))
|
||||
{
|
||||
rtems_id ct_id = current_task->Object.id;
|
||||
|
||||
|
||||
@@ -116,7 +116,6 @@ rtems_monitor_dump_priority(rtems_task_priority priority)
|
||||
static const rtems_assoc_t rtems_monitor_state_assoc[] = {
|
||||
{ "DORM", STATES_DORMANT, 0 },
|
||||
{ "SUSP", STATES_SUSPENDED, 0 },
|
||||
{ "TRANS", STATES_TRANSIENT, 0 },
|
||||
{ "DELAY", STATES_DELAYING, 0 },
|
||||
{ "Wtime", STATES_WAITING_FOR_TIME, 0 },
|
||||
{ "Wbuf", STATES_WAITING_FOR_BUFFER, 0 },
|
||||
|
||||
@@ -54,10 +54,7 @@ void _POSIX_Thread_Exit(
|
||||
*(void **)unblocked->Wait.return_argument = value_ptr;
|
||||
} while ( (unblocked = _Thread_queue_Dequeue( &api->Join_List )) );
|
||||
} else {
|
||||
_Thread_Set_state(
|
||||
the_thread,
|
||||
STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT
|
||||
);
|
||||
_Thread_Set_state( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT );
|
||||
_Thread_Enable_dispatch();
|
||||
/* now waiting for thread to arrive */
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
@@ -61,13 +61,9 @@ on_EINTR:
|
||||
* Put ourself on the threads join list
|
||||
*/
|
||||
|
||||
if ( the_thread->current_state ==
|
||||
(STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT) ) {
|
||||
if ( the_thread->current_state == STATES_WAITING_FOR_JOIN_AT_EXIT ) {
|
||||
return_pointer = the_thread->Wait.return_argument;
|
||||
_Thread_Clear_state(
|
||||
the_thread,
|
||||
(STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT)
|
||||
);
|
||||
_Thread_Clear_state( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT );
|
||||
} else {
|
||||
executing->Wait.return_argument = &return_pointer;
|
||||
_Thread_queue_Enter_critical_section( &api->Join_List );
|
||||
|
||||
@@ -208,9 +208,7 @@ libscore_a_SOURCES += src/schedulerdefaultupdate.c
|
||||
## SCHEDULERPRIORITY_C_FILES
|
||||
libscore_a_SOURCES += src/schedulerpriority.c \
|
||||
src/schedulerpriorityblock.c \
|
||||
src/schedulerpriorityenqueue.c \
|
||||
src/schedulerpriorityenqueuefirst.c \
|
||||
src/schedulerpriorityextract.c \
|
||||
src/schedulerprioritychangepriority.c \
|
||||
src/schedulerpriorityprioritycompare.c \
|
||||
src/schedulerpriorityschedule.c \
|
||||
src/schedulerpriorityunblock.c \
|
||||
@@ -220,11 +218,7 @@ libscore_a_SOURCES += src/schedulerpriority.c \
|
||||
## SCHEDULERSIMPLE_C_FILES
|
||||
libscore_a_SOURCES += src/schedulersimple.c \
|
||||
src/schedulersimpleblock.c \
|
||||
src/schedulersimpleenqueue.c \
|
||||
src/schedulersimpleenqueuefirst.c \
|
||||
src/schedulersimpleextract.c \
|
||||
src/schedulersimplereadyqueueenqueue.c \
|
||||
src/schedulersimplereadyqueueenqueuefirst.c \
|
||||
src/schedulersimplechangepriority.c \
|
||||
src/schedulersimpleschedule.c \
|
||||
src/schedulersimpleunblock.c \
|
||||
src/schedulersimpleyield.c
|
||||
@@ -233,9 +227,7 @@ libscore_a_SOURCES += src/schedulersimple.c \
|
||||
libscore_a_SOURCES += src/scheduleredf.c \
|
||||
src/scheduleredfallocate.c \
|
||||
src/scheduleredfblock.c \
|
||||
src/scheduleredfenqueue.c \
|
||||
src/scheduleredfenqueuefirst.c \
|
||||
src/scheduleredfextract.c \
|
||||
src/scheduleredfchangepriority.c \
|
||||
src/scheduleredfprioritycompare.c \
|
||||
src/scheduleredfreleasejob.c \
|
||||
src/scheduleredfschedule.c \
|
||||
@@ -282,7 +274,7 @@ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
|
||||
src/threadget.c src/threadhandler.c src/threadinitialize.c \
|
||||
src/threadloadenv.c src/threadready.c \
|
||||
src/threadrestart.c src/threadsetpriority.c \
|
||||
src/threadsetstate.c src/threadsettransient.c \
|
||||
src/threadsetstate.c \
|
||||
src/threadstackallocate.c src/threadstackfree.c src/threadstart.c \
|
||||
src/threadstartmultitasking.c src/iterateoverthreads.c \
|
||||
src/threadblockingoperationcancel.c
|
||||
|
||||
@@ -63,6 +63,14 @@ typedef struct {
|
||||
/** @see _Scheduler_Unblock() */
|
||||
void ( *unblock )( const Scheduler_Control *, Thread_Control * );
|
||||
|
||||
/** @see _Scheduler_Change_priority() */
|
||||
void ( *change_priority )(
|
||||
const Scheduler_Control *,
|
||||
Thread_Control *,
|
||||
Priority_Control,
|
||||
bool
|
||||
);
|
||||
|
||||
/** @see _Scheduler_Allocate() */
|
||||
bool ( *allocate )( const Scheduler_Control *, Thread_Control * );
|
||||
|
||||
@@ -72,15 +80,6 @@ typedef struct {
|
||||
/** @see _Scheduler_Update() */
|
||||
void ( *update )( const Scheduler_Control *, Thread_Control * );
|
||||
|
||||
/** @see _Scheduler_Enqueue() */
|
||||
void ( *enqueue )( const Scheduler_Control *, Thread_Control * );
|
||||
|
||||
/** @see _Scheduler_Enqueue_first() */
|
||||
void ( *enqueue_first )( const Scheduler_Control *, Thread_Control * );
|
||||
|
||||
/** @see _Scheduler_Extract() */
|
||||
void ( *extract )( const Scheduler_Control *, Thread_Control * );
|
||||
|
||||
/** @see _Scheduler_Priority_compare() */
|
||||
int ( *priority_compare )(
|
||||
Priority_Control,
|
||||
|
||||
@@ -52,12 +52,10 @@ extern "C" {
|
||||
_Scheduler_EDF_Yield, /* yield entry point */ \
|
||||
_Scheduler_EDF_Block, /* block entry point */ \
|
||||
_Scheduler_CBS_Unblock, /* unblock entry point */ \
|
||||
_Scheduler_EDF_Change_priority, /* change priority entry point */ \
|
||||
_Scheduler_CBS_Allocate, /* allocate entry point */ \
|
||||
_Scheduler_default_Free, /* free entry point */ \
|
||||
_Scheduler_EDF_Update, /* update entry point */ \
|
||||
_Scheduler_EDF_Enqueue, /* enqueue entry point */ \
|
||||
_Scheduler_EDF_Enqueue_first, /* enqueue_first entry point */ \
|
||||
_Scheduler_EDF_Extract, /* extract entry point */ \
|
||||
_Scheduler_EDF_Priority_compare, /* compares two priorities */ \
|
||||
_Scheduler_CBS_Release_job, /* new period of task */ \
|
||||
_Scheduler_default_Tick, /* tick entry point */ \
|
||||
|
||||
@@ -45,12 +45,10 @@ extern "C" {
|
||||
_Scheduler_EDF_Yield, /* yield entry point */ \
|
||||
_Scheduler_EDF_Block, /* block entry point */ \
|
||||
_Scheduler_EDF_Unblock, /* unblock entry point */ \
|
||||
_Scheduler_EDF_Change_priority, /* change priority entry point */ \
|
||||
_Scheduler_EDF_Allocate, /* allocate entry point */ \
|
||||
_Scheduler_default_Free, /* free entry point */ \
|
||||
_Scheduler_EDF_Update, /* update entry point */ \
|
||||
_Scheduler_EDF_Enqueue, /* enqueue entry point */ \
|
||||
_Scheduler_EDF_Enqueue_first, /* enqueue_first entry point */ \
|
||||
_Scheduler_EDF_Extract, /* extract entry point */ \
|
||||
_Scheduler_EDF_Priority_compare, /* compares two priorities */ \
|
||||
_Scheduler_EDF_Release_job, /* new period of task */ \
|
||||
_Scheduler_default_Tick, /* tick entry point */ \
|
||||
@@ -187,6 +185,13 @@ void _Scheduler_EDF_Unblock(
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
void _Scheduler_EDF_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief invoked when a thread wishes to voluntarily
|
||||
* transfer control of the processor to another thread
|
||||
@@ -207,45 +212,6 @@ void _Scheduler_EDF_Yield(
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Put @a the_thread to the rbtree ready queue.
|
||||
*
|
||||
* This routine puts @a the_thread to the rbtree ready queue.
|
||||
*
|
||||
* @param[in] the_thread will be enqueued to the ready queue.
|
||||
*/
|
||||
void _Scheduler_EDF_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Enqueue a thread to the ready queue.
|
||||
*
|
||||
* This routine puts @a the_thread to the rbtree ready queue.
|
||||
* For the EDF scheduler this is the same as @a _Scheduler_EDF_Enqueue.
|
||||
*
|
||||
* @param[in] the_thread will be enqueued to the ready queue.
|
||||
*/
|
||||
void _Scheduler_EDF_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Remove a specific thread from the scheduler's set
|
||||
* of ready threads.
|
||||
*
|
||||
* This routine removes a specific thread from the scheduler's set
|
||||
* of ready threads.
|
||||
*
|
||||
* @param[in] the_thread will be extracted from the ready set.
|
||||
*/
|
||||
void _Scheduler_EDF_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Explicitly compare absolute dedlines (priorities) of threads.
|
||||
*
|
||||
|
||||
@@ -44,6 +44,31 @@ RTEMS_INLINE_ROUTINE Scheduler_EDF_Node *_Scheduler_EDF_Node_get(
|
||||
return (Scheduler_EDF_Node *) _Scheduler_Node_get( the_thread );
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_EDF_Context *context =
|
||||
_Scheduler_EDF_Get_context( scheduler );
|
||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread );
|
||||
|
||||
_RBTree_Insert( &context->Ready, &node->Node );
|
||||
node->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES;
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_EDF_Context *context =
|
||||
_Scheduler_EDF_Get_context( scheduler );
|
||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread );
|
||||
|
||||
_RBTree_Extract( &context->Ready, &node->Node );
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
|
||||
@@ -143,6 +143,35 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Unblock(
|
||||
( *scheduler->Operations.unblock )( scheduler, the_thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Propagates a priority change of a thread to the scheduler.
|
||||
*
|
||||
* The caller must ensure that the thread is in the ready state. The caller
|
||||
* must ensure that the priority value actually changed and is not equal to the
|
||||
* current priority value.
|
||||
*
|
||||
* @param[in] scheduler The scheduler instance.
|
||||
* @param[in] the_thread The thread changing its priority.
|
||||
* @param[in] new_priority The new thread priority.
|
||||
* @param[in] prepend_it In case this is true, then enqueue the thread as the
|
||||
* first of its priority group, otherwise enqueue the thread as the last of its
|
||||
* priority group.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
( *scheduler->Operations.change_priority )(
|
||||
scheduler,
|
||||
the_thread,
|
||||
new_priority,
|
||||
prepend_it
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scheduler allocate.
|
||||
*
|
||||
@@ -182,47 +211,6 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Update(
|
||||
( *scheduler->Operations.update )( scheduler, the_thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enqueues a thread as the last of its priority group.
|
||||
*
|
||||
* @param[in] scheduler The scheduler instance.
|
||||
* @param[in] the_thread The thread to enqueue.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
( *scheduler->Operations.enqueue )( scheduler, the_thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enqueues a thread as the first of its priority group.
|
||||
*
|
||||
* @param[in] scheduler The scheduler instance.
|
||||
* @param[in] the_thread The thread to enqueue.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
( *scheduler->Operations.enqueue_first )( scheduler, the_thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scheduler extract.
|
||||
*
|
||||
* This routine extract @a the_thread->scheduler
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
( *scheduler->Operations.extract )( scheduler, the_thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two priority values.
|
||||
*
|
||||
|
||||
@@ -52,12 +52,10 @@ extern "C" {
|
||||
_Scheduler_priority_Yield, /* yield entry point */ \
|
||||
_Scheduler_priority_Block, /* block entry point */ \
|
||||
_Scheduler_priority_Unblock, /* unblock entry point */ \
|
||||
_Scheduler_default_Allocate, /* allocate entry point */ \
|
||||
_Scheduler_default_Free, /* free entry point */ \
|
||||
_Scheduler_priority_Change_priority, /* change priority entry point */ \
|
||||
_Scheduler_default_Allocate, /* allocate entry point */ \
|
||||
_Scheduler_default_Free, /* free entry point */ \
|
||||
_Scheduler_priority_Update, /* update entry point */ \
|
||||
_Scheduler_priority_Enqueue, /* enqueue entry point */ \
|
||||
_Scheduler_priority_Enqueue_first, /* enqueue_first entry point */ \
|
||||
_Scheduler_priority_Extract, /* extract entry point */ \
|
||||
_Scheduler_priority_Priority_compare, /* compares two priorities */ \
|
||||
_Scheduler_default_Release_job, /* new period of task */ \
|
||||
_Scheduler_default_Tick, /* tick entry point */ \
|
||||
@@ -167,6 +165,13 @@ void _Scheduler_priority_Unblock(
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief The specified THREAD yields.
|
||||
*
|
||||
@@ -191,45 +196,6 @@ void _Scheduler_priority_Yield(
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Puts @a the_thread on to the priority-based ready queue.
|
||||
*
|
||||
* This routine puts @a the_thread on to the priority-based ready queue.
|
||||
*
|
||||
* @param[in] the_thread will be enqueued at the TAIL of its priority.
|
||||
*/
|
||||
void _Scheduler_priority_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Puts @a the_thread to the head of the ready queue.
|
||||
*
|
||||
* This routine puts @a the_thread to the head of the ready queue.
|
||||
* For priority-based ready queues, the thread will be the first thread
|
||||
* at its priority level.
|
||||
*
|
||||
* @param[in] the_thread will be enqueued at the HEAD of its priority.
|
||||
*/
|
||||
void _Scheduler_priority_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Remove a specific thread from scheduler.
|
||||
*
|
||||
* This routine removes a specific thread from the scheduler's set
|
||||
* of ready threads.
|
||||
*
|
||||
* @param[in] the_thread will be extracted from the ready set.
|
||||
*/
|
||||
void _Scheduler_priority_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Compare two priorities.
|
||||
*
|
||||
|
||||
@@ -53,13 +53,11 @@ extern "C" {
|
||||
_Scheduler_priority_SMP_Schedule, \
|
||||
_Scheduler_priority_SMP_Yield, \
|
||||
_Scheduler_priority_SMP_Block, \
|
||||
_Scheduler_priority_SMP_Enqueue_fifo, \
|
||||
_Scheduler_priority_SMP_Unblock, \
|
||||
_Scheduler_priority_SMP_Change_priority, \
|
||||
_Scheduler_priority_affinity_SMP_Allocate, \
|
||||
_Scheduler_default_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, \
|
||||
|
||||
@@ -196,28 +196,27 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the specified ready queue data according to the current
|
||||
* priority of the thread.
|
||||
* @brief Updates the specified ready queue data according to the new priority
|
||||
* value.
|
||||
*
|
||||
* @param[in] the_thread The thread.
|
||||
* @param[in] ready_queue The ready queue.
|
||||
* @param[in] new_priority The new priority.
|
||||
* @param[in] bit_map The priority bit map of the scheduler instance.
|
||||
* @param[in] ready_queues The ready queues of the scheduler instance.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_update(
|
||||
Thread_Control *the_thread,
|
||||
Scheduler_priority_Ready_queue *ready_queue,
|
||||
Priority_Control new_priority,
|
||||
Priority_bit_map_Control *bit_map,
|
||||
Chain_Control *ready_queues
|
||||
)
|
||||
{
|
||||
Priority_Control priority = the_thread->current_priority;
|
||||
ready_queue->ready_chain = &ready_queues[ priority ];
|
||||
ready_queue->ready_chain = &ready_queues[ new_priority ];
|
||||
|
||||
_Priority_bit_map_Initialize_information(
|
||||
bit_map,
|
||||
&ready_queue->Priority_map,
|
||||
priority
|
||||
new_priority
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 embedded brains GmbH. All rights reserved.
|
||||
* Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
@@ -82,13 +82,11 @@ typedef struct {
|
||||
_Scheduler_priority_SMP_Schedule, \
|
||||
_Scheduler_priority_SMP_Yield, \
|
||||
_Scheduler_priority_SMP_Block, \
|
||||
_Scheduler_priority_SMP_Enqueue_fifo, \
|
||||
_Scheduler_priority_SMP_Unblock, \
|
||||
_Scheduler_priority_SMP_Change_priority, \
|
||||
_Scheduler_priority_SMP_Allocate, \
|
||||
_Scheduler_default_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, \
|
||||
@@ -114,26 +112,23 @@ void _Scheduler_priority_SMP_Block(
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Unblock(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Update(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Enqueue_fifo(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Enqueue_lifo(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_priority_SMP_Yield(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
|
||||
@@ -42,12 +42,10 @@ extern "C" {
|
||||
_Scheduler_simple_Yield, /* yield entry point */ \
|
||||
_Scheduler_simple_Block, /* block entry point */ \
|
||||
_Scheduler_simple_Unblock, /* unblock entry point */ \
|
||||
_Scheduler_simple_Change_priority, /* change priority entry point */ \
|
||||
_Scheduler_default_Allocate, /* allocate entry point */ \
|
||||
_Scheduler_default_Free, /* free entry point */ \
|
||||
_Scheduler_default_Update, /* update entry point */ \
|
||||
_Scheduler_simple_Enqueue, /* enqueue entry point */ \
|
||||
_Scheduler_simple_Enqueue_first, /* enqueue_first entry point */ \
|
||||
_Scheduler_simple_Extract, /* extract entry point */ \
|
||||
_Scheduler_priority_Priority_compare, /* compares two priorities */ \
|
||||
_Scheduler_default_Release_job, /* new period of task */ \
|
||||
_Scheduler_default_Tick, /* tick entry point */ \
|
||||
@@ -136,70 +134,11 @@ void _Scheduler_simple_Unblock(
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Removes a simple-priority-based thread from a simple queue.
|
||||
*
|
||||
* This routine removes a specific thread from the specified
|
||||
* simple-based ready queue.
|
||||
*
|
||||
* @param[in] the_thread is the thread to be blocked
|
||||
*/
|
||||
void _Scheduler_simple_Extract(
|
||||
void _Scheduler_simple_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Puts simple-priority-based thread onto the ready queue.
|
||||
*
|
||||
* This routine puts @a the_thread on to the ready queue.
|
||||
*
|
||||
* @param[in] the_thread is the thread to be enqueued
|
||||
*/
|
||||
void _Scheduler_simple_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Put simple-priority-based @a the_thread to
|
||||
* the head of the ready queue.
|
||||
*
|
||||
* This routine puts @a the_thread to the head of the ready queue.
|
||||
* The thread will be the first thread at its priority level.
|
||||
*
|
||||
* @param[in] the_thread is the thread to be blocked
|
||||
*/
|
||||
void _Scheduler_simple_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* _Scheduler_simple_Ready_queue_enqueue
|
||||
*
|
||||
* This routine puts @a the_thread on the ready queue
|
||||
* at the end of its priority group.
|
||||
*
|
||||
* @param[in] the_thread - pointer to a thread control block
|
||||
*/
|
||||
void _Scheduler_simple_Ready_queue_enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Puts simple-priority-based @a the_thread on to the ready queue
|
||||
* at the beginning of its priority group.
|
||||
*
|
||||
* This routine puts @a the_thread on to the ready queue
|
||||
* at the beginning of its priority group.
|
||||
*
|
||||
* @param[in] the_thread - pointer to a thread control block
|
||||
*/
|
||||
void _Scheduler_simple_Ready_queue_enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
);
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -38,24 +38,6 @@ RTEMS_INLINE_ROUTINE Scheduler_simple_Context *
|
||||
return (Scheduler_simple_Context *) _Scheduler_Get_context( scheduler );
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine puts @a the_thread on to the ready queue.
|
||||
*
|
||||
* @param[in] the_ready_queue is a pointer to the ready queue head
|
||||
* @param[in] the_thread is the thread to be blocked
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_simple_Ready_queue_requeue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
/* extract */
|
||||
_Chain_Extract_unprotected( &the_thread->Object.Node );
|
||||
|
||||
/* enqueue */
|
||||
_Scheduler_simple_Ready_queue_enqueue( scheduler, the_thread );
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE bool _Scheduler_simple_Insert_priority_lifo_order(
|
||||
const Chain_Node *to_insert,
|
||||
const Chain_Node *next
|
||||
@@ -102,6 +84,16 @@ RTEMS_INLINE_ROUTINE void _Scheduler_simple_Insert_priority_fifo(
|
||||
);
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_simple_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
(void) scheduler;
|
||||
|
||||
_Chain_Extract_unprotected( &the_thread->Object.Node );
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _Scheduler_simple_Schedule_body(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
|
||||
@@ -63,13 +63,11 @@ typedef struct {
|
||||
_Scheduler_simple_SMP_Schedule, \
|
||||
_Scheduler_simple_SMP_Yield, \
|
||||
_Scheduler_simple_SMP_Block, \
|
||||
_Scheduler_simple_SMP_Enqueue_priority_fifo, \
|
||||
_Scheduler_simple_SMP_Unblock, \
|
||||
_Scheduler_simple_SMP_Change_priority, \
|
||||
_Scheduler_simple_SMP_Allocate, \
|
||||
_Scheduler_default_Free, \
|
||||
_Scheduler_default_Update, \
|
||||
_Scheduler_simple_SMP_Enqueue_priority_fifo, \
|
||||
_Scheduler_simple_SMP_Enqueue_priority_lifo, \
|
||||
_Scheduler_simple_SMP_Extract, \
|
||||
_Scheduler_priority_Priority_compare, \
|
||||
_Scheduler_default_Release_job, \
|
||||
_Scheduler_default_Tick, \
|
||||
@@ -90,19 +88,16 @@ void _Scheduler_simple_SMP_Block(
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_simple_SMP_Enqueue_priority_fifo(
|
||||
void _Scheduler_simple_SMP_Unblock(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_simple_SMP_Enqueue_priority_lifo(
|
||||
void _Scheduler_simple_SMP_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
);
|
||||
|
||||
void _Scheduler_simple_SMP_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
);
|
||||
|
||||
void _Scheduler_simple_SMP_Yield(
|
||||
|
||||
@@ -69,8 +69,8 @@ typedef enum {
|
||||
*
|
||||
* A scheduler node is scheduled if the corresponding thread is ready and the
|
||||
* scheduler allocated a processor for it. A scheduled node is assigned to
|
||||
* exactly one processor. The sum of scheduled and in the air nodes equals
|
||||
* the processor count owned by a scheduler instance.
|
||||
* exactly one processor. The count of scheduled nodes in this scheduler
|
||||
* instance equals the processor count owned by the scheduler instance.
|
||||
*/
|
||||
SCHEDULER_SMP_NODE_SCHEDULED,
|
||||
|
||||
@@ -80,22 +80,7 @@ typedef enum {
|
||||
* A scheduler node is ready if the corresponding thread is ready and the
|
||||
* scheduler did not allocate a processor for it.
|
||||
*/
|
||||
SCHEDULER_SMP_NODE_READY,
|
||||
|
||||
/**
|
||||
* @brief This scheduler node is in the air.
|
||||
*
|
||||
* A scheduled node is in the air if it has an allocated processor and the
|
||||
* corresponding thread is in a transient state. Such a node is not an
|
||||
* element of the set of scheduled nodes. The extract operation on a
|
||||
* scheduled node will produce a scheduler node in the air (see also
|
||||
* _Thread_Set_transient()). The next enqueue or schedule operation will
|
||||
* decide what to do based on this state indication. It can either place the
|
||||
* scheduler node back on the set of scheduled nodes and the thread can keep
|
||||
* its allocated processor, or it can take the processor away from the thread
|
||||
* and give the processor to another thread of higher priority.
|
||||
*/
|
||||
SCHEDULER_SMP_NODE_IN_THE_AIR
|
||||
SCHEDULER_SMP_NODE_READY
|
||||
} Scheduler_SMP_Node_state;
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,14 +37,12 @@ extern "C" {
|
||||
*
|
||||
* The scheduler nodes can be in four states
|
||||
* - @ref SCHEDULER_SMP_NODE_BLOCKED,
|
||||
* - @ref SCHEDULER_SMP_NODE_SCHEDULED,
|
||||
* - @ref SCHEDULER_SMP_NODE_READY, and
|
||||
* - @ref SCHEDULER_SMP_NODE_IN_THE_AIR.
|
||||
* - @ref SCHEDULER_SMP_NODE_SCHEDULED, and
|
||||
* - @ref SCHEDULER_SMP_NODE_READY.
|
||||
*
|
||||
* State transitions are triggered via basic three operations
|
||||
* - _Scheduler_SMP_Enqueue_ordered(),
|
||||
* - _Scheduler_SMP_Extract(), and
|
||||
* - _Scheduler_SMP_Schedule().
|
||||
* State transitions are triggered via basic operations
|
||||
* - _Scheduler_SMP_Enqueue_ordered(), and
|
||||
* - _Scheduler_SMP_Block().
|
||||
*
|
||||
* @dot
|
||||
* digraph {
|
||||
@@ -53,39 +51,26 @@ extern "C" {
|
||||
* bs [label="BLOCKED"];
|
||||
* ss [label="SCHEDULED", fillcolor="green"];
|
||||
* rs [label="READY", fillcolor="red"];
|
||||
* as [label="IN THE AIR", fillcolor="orange"];
|
||||
*
|
||||
* edge [label="enqueue"];
|
||||
* edge [fontcolor="darkgreen", color="darkgreen"];
|
||||
*
|
||||
* bs -> ss;
|
||||
* as -> ss;
|
||||
*
|
||||
* edge [label="enqueue"];
|
||||
* edge [fontcolor="red", color="red"];
|
||||
*
|
||||
* bs -> rs;
|
||||
* as -> rs;
|
||||
*
|
||||
* edge [label="enqueue other"];
|
||||
*
|
||||
* ss -> rs;
|
||||
*
|
||||
* edge [label="schedule"];
|
||||
* edge [fontcolor="black", color="black"];
|
||||
*
|
||||
* as -> bs;
|
||||
*
|
||||
* edge [label="extract"];
|
||||
* edge [fontcolor="brown", color="brown"];
|
||||
*
|
||||
* ss -> as;
|
||||
*
|
||||
* edge [label="block"];
|
||||
* edge [fontcolor="black", color="black"];
|
||||
*
|
||||
* rs -> bs;
|
||||
*
|
||||
* edge [label="enqueue other\nschedule other"];
|
||||
* edge [label="block other"];
|
||||
* edge [fontcolor="darkgreen", color="darkgreen"];
|
||||
*
|
||||
* rs -> ss;
|
||||
@@ -216,38 +201,7 @@ extern "C" {
|
||||
* }
|
||||
* @enddot
|
||||
*
|
||||
* Lets do something with A. This can be a blocking operation or a priority
|
||||
* change. For this an extract operation is performed first.
|
||||
*
|
||||
* @dot
|
||||
* digraph {
|
||||
* node [style="filled"];
|
||||
* edge [dir="none"];
|
||||
*
|
||||
* subgraph {
|
||||
* rank = same;
|
||||
*
|
||||
* b [label="B (2)", fillcolor="green"];
|
||||
* a [label="A (1)", fillcolor="orange"];
|
||||
* c [label="C (3)", fillcolor="red"];
|
||||
* i [label="I (5)", fillcolor="red"];
|
||||
* j [label="J (5)", fillcolor="red"];
|
||||
* c -> i -> j;
|
||||
* }
|
||||
*
|
||||
* subgraph {
|
||||
* rank = same;
|
||||
*
|
||||
* p0 [label="PROCESSOR 0", shape="box"];
|
||||
* p1 [label="PROCESSOR 1", shape="box"];
|
||||
* }
|
||||
*
|
||||
* b -> p0;
|
||||
* a -> p1;
|
||||
* }
|
||||
* @enddot
|
||||
*
|
||||
* Lets change the priority of thread A to 4 and enqueue it.
|
||||
* Lets change the priority of thread A to 4.
|
||||
*
|
||||
* @dot
|
||||
* digraph {
|
||||
@@ -278,8 +232,9 @@ extern "C" {
|
||||
* }
|
||||
* @enddot
|
||||
*
|
||||
* Alternatively we can also do a blocking operation with thread A. In this
|
||||
* case schedule will be called.
|
||||
* Now perform a blocking operation with thread B. Please note that thread A
|
||||
* migrated now from processor 0 to processor 1 and thread C still executes on
|
||||
* processor 1.
|
||||
*
|
||||
* @dot
|
||||
* digraph {
|
||||
@@ -289,12 +244,12 @@ extern "C" {
|
||||
* subgraph {
|
||||
* rank = same;
|
||||
*
|
||||
* b [label="B (2)", fillcolor="green"];
|
||||
* c [label="C (3)", fillcolor="green"];
|
||||
* a [label="A (4)", fillcolor="green"];
|
||||
* i [label="I (5)", fillcolor="red"];
|
||||
* j [label="J (5)", fillcolor="red"];
|
||||
* a [label="A (1)"];
|
||||
* b -> c;
|
||||
* b [label="B (2)"];
|
||||
* c -> a;
|
||||
* i -> j;
|
||||
* }
|
||||
*
|
||||
@@ -305,7 +260,7 @@ extern "C" {
|
||||
* p1 [label="PROCESSOR 1", shape="box"];
|
||||
* }
|
||||
*
|
||||
* b -> p0;
|
||||
* a -> p0;
|
||||
* c -> p1;
|
||||
* }
|
||||
* @enddot
|
||||
@@ -332,6 +287,18 @@ typedef void ( *Scheduler_SMP_Move )(
|
||||
Thread_Control *thread_to_move
|
||||
);
|
||||
|
||||
typedef void ( *Scheduler_SMP_Update )(
|
||||
Scheduler_Context *context,
|
||||
Scheduler_Node *node,
|
||||
Priority_Control new_priority
|
||||
);
|
||||
|
||||
typedef void ( *Scheduler_SMP_Enqueue )(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread_to_enqueue,
|
||||
bool has_processor_allocated
|
||||
);
|
||||
|
||||
static inline Scheduler_SMP_Context *_Scheduler_SMP_Get_self(
|
||||
Scheduler_Context *context
|
||||
)
|
||||
@@ -360,7 +327,7 @@ static inline void _Scheduler_SMP_Node_initialize(
|
||||
node->state = SCHEDULER_SMP_NODE_BLOCKED;
|
||||
}
|
||||
|
||||
extern const bool _Scheduler_SMP_Node_valid_state_changes[ 4 ][ 4 ];
|
||||
extern const bool _Scheduler_SMP_Node_valid_state_changes[ 3 ][ 3 ];
|
||||
|
||||
static inline void _Scheduler_SMP_Node_change_state(
|
||||
Scheduler_SMP_Node *node,
|
||||
@@ -467,6 +434,7 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
|
||||
*
|
||||
* @param[in] context The scheduler instance context.
|
||||
* @param[in] thread The thread to enqueue.
|
||||
* @param[in] has_processor_allocated The thread has a processor allocated.
|
||||
* @param[in] order The order function.
|
||||
* @param[in] get_highest_ready Function to get the highest ready node.
|
||||
* @param[in] insert_ready Function to insert a node into the set of ready
|
||||
@@ -481,6 +449,7 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
|
||||
static inline void _Scheduler_SMP_Enqueue_ordered(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated,
|
||||
Chain_Node_order order,
|
||||
Scheduler_SMP_Get_highest_ready get_highest_ready,
|
||||
Scheduler_SMP_Insert insert_ready,
|
||||
@@ -492,19 +461,18 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
|
||||
Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
|
||||
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
|
||||
|
||||
if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) {
|
||||
if ( has_processor_allocated) {
|
||||
Thread_Control *highest_ready = ( *get_highest_ready )( &self->Base );
|
||||
|
||||
_Assert( highest_ready != NULL);
|
||||
|
||||
/*
|
||||
* The thread has been extracted from the scheduled chain. We have to
|
||||
* place it now on the scheduled or ready chain.
|
||||
*
|
||||
* NOTE: Do not exchange parameters to do the negation of the order check.
|
||||
*/
|
||||
if (
|
||||
highest_ready != NULL
|
||||
&& !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
|
||||
) {
|
||||
if ( !( *order )( &thread->Object.Node, &highest_ready->Object.Node ) ) {
|
||||
_Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
|
||||
_Scheduler_SMP_Allocate_processor( self, highest_ready, thread );
|
||||
( *insert_ready )( &self->Base, thread );
|
||||
@@ -517,14 +485,9 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
|
||||
Thread_Control *lowest_scheduled =
|
||||
_Scheduler_SMP_Get_lowest_scheduled( self );
|
||||
|
||||
/*
|
||||
* The scheduled chain is empty if nested interrupts change the priority of
|
||||
* all scheduled threads. These threads are in the air.
|
||||
*/
|
||||
if (
|
||||
lowest_scheduled != NULL
|
||||
&& ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
|
||||
) {
|
||||
_Assert( lowest_scheduled != NULL);
|
||||
|
||||
if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
|
||||
Scheduler_SMP_Node *lowest_scheduled_node =
|
||||
_Scheduler_SMP_Node_get( lowest_scheduled );
|
||||
|
||||
@@ -542,6 +505,11 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _Scheduler_SMP_Extract_from_scheduled( Thread_Control *thread )
|
||||
{
|
||||
_Chain_Extract_unprotected( &thread->Object.Node );
|
||||
}
|
||||
|
||||
static inline void _Scheduler_SMP_Schedule_highest_ready(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *victim,
|
||||
@@ -558,25 +526,31 @@ static inline void _Scheduler_SMP_Schedule_highest_ready(
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finalize a scheduling operation.
|
||||
* @brief Blocks a thread.
|
||||
*
|
||||
* @param[in] context The scheduler instance context.
|
||||
* @param[in] thread The thread of the scheduling operation.
|
||||
* @param[in] extract_from_ready Function to extract a node from the set of
|
||||
* ready nodes.
|
||||
* @param[in] get_highest_ready Function to get the highest ready node.
|
||||
* @param[in] move_from_ready_to_scheduled Function to move a node from the set
|
||||
* of ready nodes to the set of scheduled nodes.
|
||||
*/
|
||||
static inline void _Scheduler_SMP_Schedule(
|
||||
static inline void _Scheduler_SMP_Block(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
Scheduler_SMP_Extract extract_from_ready,
|
||||
Scheduler_SMP_Get_highest_ready get_highest_ready,
|
||||
Scheduler_SMP_Move move_from_ready_to_scheduled
|
||||
)
|
||||
{
|
||||
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
|
||||
bool is_scheduled = node->state == SCHEDULER_SMP_NODE_SCHEDULED;
|
||||
|
||||
if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) {
|
||||
_Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
|
||||
_Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
|
||||
|
||||
if ( is_scheduled ) {
|
||||
_Scheduler_SMP_Extract_from_scheduled( thread );
|
||||
|
||||
_Scheduler_SMP_Schedule_highest_ready(
|
||||
context,
|
||||
@@ -584,42 +558,38 @@ static inline void _Scheduler_SMP_Schedule(
|
||||
get_highest_ready,
|
||||
move_from_ready_to_scheduled
|
||||
);
|
||||
} else {
|
||||
( *extract_from_ready )( context, thread );
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _Scheduler_SMP_Block(
|
||||
static inline void _Scheduler_SMP_Change_priority(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
Scheduler_SMP_Extract extract,
|
||||
Scheduler_SMP_Get_highest_ready get_highest_ready,
|
||||
Scheduler_SMP_Move move_from_ready_to_scheduled
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it,
|
||||
Scheduler_SMP_Extract extract_from_ready,
|
||||
Scheduler_SMP_Update update,
|
||||
Scheduler_SMP_Enqueue enqueue_fifo,
|
||||
Scheduler_SMP_Enqueue enqueue_lifo
|
||||
)
|
||||
{
|
||||
( *extract )( context, thread );
|
||||
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
|
||||
bool has_processor_allocated = node->state == SCHEDULER_SMP_NODE_SCHEDULED;
|
||||
|
||||
_Scheduler_SMP_Schedule(
|
||||
context,
|
||||
thread,
|
||||
get_highest_ready,
|
||||
move_from_ready_to_scheduled
|
||||
);
|
||||
}
|
||||
if ( has_processor_allocated ) {
|
||||
_Scheduler_SMP_Extract_from_scheduled( thread );
|
||||
} else {
|
||||
( *extract_from_ready )( context, thread );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extracts a thread from the set of scheduled or ready nodes.
|
||||
*
|
||||
* @param[in] context The scheduler instance context.
|
||||
* @param[in] thread The thread to extract.
|
||||
* @param[in] extract Function to extract a node from the set of scheduled or
|
||||
* ready nodes.
|
||||
*/
|
||||
static inline void _Scheduler_SMP_Extract(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
Scheduler_SMP_Extract extract
|
||||
)
|
||||
{
|
||||
( *extract )( context, thread );
|
||||
( *update )( context, &node->Base, new_priority );
|
||||
|
||||
if ( prepend_it ) {
|
||||
( *enqueue_lifo )( context, thread, has_processor_allocated );
|
||||
} else {
|
||||
( *enqueue_fifo )( context, thread, has_processor_allocated );
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _Scheduler_SMP_Insert_scheduled_lifo(
|
||||
|
||||
@@ -42,8 +42,6 @@ extern "C" {
|
||||
#define STATES_DORMANT 0x00001
|
||||
/** This macro corresponds to a task being suspended. */
|
||||
#define STATES_SUSPENDED 0x00002
|
||||
/** This macro corresponds to a task being in an internal state transition. */
|
||||
#define STATES_TRANSIENT 0x00004
|
||||
/** This macro corresponds to a task which is waiting for a timeout. */
|
||||
#define STATES_DELAYING 0x00008
|
||||
/** This macro corresponds to a task waiting until a specific TOD. */
|
||||
@@ -214,21 +212,6 @@ RTEMS_INLINE_ROUTINE bool _States_Is_suspended (
|
||||
return (the_states & STATES_SUSPENDED);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns true if the TRANSIENT state is set in
|
||||
* the_states, and false otherwise.
|
||||
*
|
||||
* @param[in] the_states is the task state set to test
|
||||
*
|
||||
* @return This method returns true if the desired state condition is set.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE bool _States_Is_transient (
|
||||
States_Control the_states
|
||||
)
|
||||
{
|
||||
return (the_states & STATES_TRANSIENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns true if the DELAYING state is set in
|
||||
* the_states, and false otherwise.
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulercbsimpl.h>
|
||||
#include <rtems/score/scheduleredfimpl.h>
|
||||
#include <rtems/score/schedulerimpl.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
|
||||
+5
-3
@@ -20,9 +20,11 @@
|
||||
|
||||
#include <rtems/score/scheduleredfimpl.h>
|
||||
|
||||
void _Scheduler_EDF_Extract(
|
||||
void _Scheduler_EDF_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
Scheduler_EDF_Context *context =
|
||||
@@ -30,5 +32,5 @@ void _Scheduler_EDF_Extract(
|
||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread );
|
||||
|
||||
_RBTree_Extract( &context->Ready, &node->Node );
|
||||
node->queue_state = SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY;
|
||||
_RBTree_Insert( &context->Ready, &node->Node );
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Scheduler EDF Enqueue
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/scheduleredfimpl.h>
|
||||
|
||||
void _Scheduler_EDF_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_EDF_Context *context =
|
||||
_Scheduler_EDF_Get_context( scheduler );
|
||||
Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread );
|
||||
|
||||
_RBTree_Insert( &context->Ready, &node->Node );
|
||||
node->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Enqueues a thread to the ready queue
|
||||
*
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/config.h>
|
||||
#include <rtems/score/scheduleredf.h>
|
||||
|
||||
void _Scheduler_EDF_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
_Scheduler_EDF_Enqueue( scheduler, the_thread );
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/scheduleredf.h>
|
||||
#include <rtems/score/scheduleredfimpl.h>
|
||||
#include <rtems/score/schedulerimpl.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Removes Thread from Thread Queue
|
||||
*
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulerpriorityimpl.h>
|
||||
|
||||
void _Scheduler_priority_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
Scheduler_priority_Context *context =
|
||||
_Scheduler_priority_Get_context( scheduler );
|
||||
Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread );
|
||||
|
||||
_Scheduler_priority_Ready_queue_extract(
|
||||
the_thread,
|
||||
&node->Ready_queue,
|
||||
&context->Bit_map
|
||||
);
|
||||
|
||||
_Scheduler_priority_Ready_queue_update(
|
||||
&node->Ready_queue,
|
||||
new_priority,
|
||||
&context->Bit_map,
|
||||
&context->Ready[ 0 ]
|
||||
);
|
||||
|
||||
if ( prepend_it ) {
|
||||
_Scheduler_priority_Ready_queue_enqueue_first(
|
||||
the_thread,
|
||||
&node->Ready_queue,
|
||||
&context->Bit_map
|
||||
);
|
||||
} else {
|
||||
_Scheduler_priority_Ready_queue_enqueue(
|
||||
the_thread,
|
||||
&node->Ready_queue,
|
||||
&context->Bit_map
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Scheduler Priority Enqueue
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulerpriorityimpl.h>
|
||||
|
||||
void _Scheduler_priority_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_priority_Context *context =
|
||||
_Scheduler_priority_Get_context( scheduler );
|
||||
Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread );
|
||||
|
||||
_Scheduler_priority_Ready_queue_enqueue(
|
||||
the_thread,
|
||||
&node->Ready_queue,
|
||||
&context->Bit_map
|
||||
);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Scheduler Priority Enqueue First
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulerpriorityimpl.h>
|
||||
|
||||
void _Scheduler_priority_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_priority_Context *context =
|
||||
_Scheduler_priority_Get_context( scheduler );
|
||||
Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread );
|
||||
|
||||
_Scheduler_priority_Ready_queue_enqueue_first(
|
||||
the_thread,
|
||||
&node->Ready_queue,
|
||||
&context->Bit_map
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Removes Thread from Thread Queue
|
||||
*
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulerpriorityimpl.h>
|
||||
|
||||
void _Scheduler_priority_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
_Scheduler_priority_Extract_body( scheduler, the_thread );
|
||||
}
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <rtems/score/schedulerprioritysmp.h>
|
||||
#include <rtems/score/schedulerpriorityimpl.h>
|
||||
#include <rtems/score/schedulersmpimpl.h>
|
||||
#include <rtems/score/wkspace.h>
|
||||
|
||||
static Scheduler_priority_SMP_Context *
|
||||
_Scheduler_priority_SMP_Get_context( const Scheduler_Control *scheduler )
|
||||
@@ -48,6 +47,13 @@ static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_get(
|
||||
return (Scheduler_priority_SMP_Node *) _Scheduler_Node_get( thread );
|
||||
}
|
||||
|
||||
static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_downcast(
|
||||
Scheduler_Node *node
|
||||
)
|
||||
{
|
||||
return (Scheduler_priority_SMP_Node *) node;
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler )
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
@@ -70,22 +76,34 @@ bool _Scheduler_priority_SMP_Allocate(
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _Scheduler_priority_SMP_Do_update(
|
||||
Scheduler_Context *context,
|
||||
Scheduler_Node *base_node,
|
||||
Priority_Control new_priority
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_self( context );
|
||||
Scheduler_priority_SMP_Node *node =
|
||||
_Scheduler_priority_SMP_Node_downcast( base_node );
|
||||
|
||||
_Scheduler_priority_Ready_queue_update(
|
||||
&node->Ready_queue,
|
||||
new_priority,
|
||||
&self->Bit_map,
|
||||
&self->Ready[ 0 ]
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Update(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
Scheduler_priority_SMP_Node *node =
|
||||
_Scheduler_priority_SMP_Node_get( thread );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
Scheduler_Node *node = _Scheduler_Node_get( thread );
|
||||
|
||||
_Scheduler_priority_Ready_queue_update(
|
||||
thread,
|
||||
&node->Ready_queue,
|
||||
&self->Bit_map,
|
||||
&self->Ready[ 0 ]
|
||||
);
|
||||
_Scheduler_priority_SMP_Do_update( context, node, thread->current_priority );
|
||||
}
|
||||
|
||||
static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
|
||||
@@ -94,16 +112,11 @@ static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_self( context );
|
||||
Thread_Control *highest_ready = NULL;
|
||||
|
||||
if ( !_Priority_bit_map_Is_empty( &self->Bit_map ) ) {
|
||||
highest_ready = _Scheduler_priority_Ready_queue_first(
|
||||
&self->Bit_map,
|
||||
&self->Ready[ 0 ]
|
||||
);
|
||||
}
|
||||
|
||||
return highest_ready;
|
||||
return _Scheduler_priority_Ready_queue_first(
|
||||
&self->Bit_map,
|
||||
&self->Ready[ 0 ]
|
||||
);
|
||||
}
|
||||
|
||||
static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
|
||||
@@ -179,7 +192,7 @@ static void _Scheduler_priority_SMP_Insert_ready_fifo(
|
||||
);
|
||||
}
|
||||
|
||||
static void _Scheduler_priority_SMP_Do_extract(
|
||||
static void _Scheduler_priority_SMP_Extract_from_ready(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread
|
||||
)
|
||||
@@ -189,23 +202,11 @@ static void _Scheduler_priority_SMP_Do_extract(
|
||||
Scheduler_priority_SMP_Node *node =
|
||||
_Scheduler_priority_SMP_Node_get( thread );
|
||||
|
||||
if ( node->Base.state == SCHEDULER_SMP_NODE_SCHEDULED ) {
|
||||
_Scheduler_SMP_Node_change_state(
|
||||
&node->Base,
|
||||
SCHEDULER_SMP_NODE_IN_THE_AIR
|
||||
);
|
||||
_Chain_Extract_unprotected( &thread->Object.Node );
|
||||
} else {
|
||||
_Scheduler_SMP_Node_change_state(
|
||||
&node->Base,
|
||||
SCHEDULER_SMP_NODE_BLOCKED
|
||||
);
|
||||
_Scheduler_priority_Ready_queue_extract(
|
||||
thread,
|
||||
&node->Ready_queue,
|
||||
&self->Bit_map
|
||||
);
|
||||
}
|
||||
_Scheduler_priority_Ready_queue_extract(
|
||||
thread,
|
||||
&node->Ready_queue,
|
||||
&self->Bit_map
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Block(
|
||||
@@ -213,13 +214,12 @@ void _Scheduler_priority_SMP_Block(
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Block(
|
||||
&self->Base.Base,
|
||||
context,
|
||||
thread,
|
||||
_Scheduler_priority_SMP_Do_extract,
|
||||
_Scheduler_priority_SMP_Extract_from_ready,
|
||||
_Scheduler_priority_SMP_Get_highest_ready,
|
||||
_Scheduler_priority_SMP_Move_from_ready_to_scheduled
|
||||
);
|
||||
@@ -228,6 +228,7 @@ void _Scheduler_priority_SMP_Block(
|
||||
static void _Scheduler_priority_SMP_Enqueue_ordered(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated,
|
||||
Chain_Node_order order,
|
||||
Scheduler_SMP_Insert insert_ready,
|
||||
Scheduler_SMP_Insert insert_scheduled
|
||||
@@ -236,6 +237,7 @@ static void _Scheduler_priority_SMP_Enqueue_ordered(
|
||||
_Scheduler_SMP_Enqueue_ordered(
|
||||
context,
|
||||
thread,
|
||||
has_processor_allocated,
|
||||
order,
|
||||
_Scheduler_priority_SMP_Get_highest_ready,
|
||||
insert_ready,
|
||||
@@ -245,52 +247,66 @@ static void _Scheduler_priority_SMP_Enqueue_ordered(
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Enqueue_lifo(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
static void _Scheduler_priority_SMP_Enqueue_lifo(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
|
||||
_Scheduler_priority_SMP_Enqueue_ordered(
|
||||
&self->Base.Base,
|
||||
context,
|
||||
thread,
|
||||
has_processor_allocated,
|
||||
_Scheduler_simple_Insert_priority_lifo_order,
|
||||
_Scheduler_priority_SMP_Insert_ready_lifo,
|
||||
_Scheduler_SMP_Insert_scheduled_lifo
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Enqueue_fifo(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
static void _Scheduler_priority_SMP_Enqueue_fifo(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
|
||||
_Scheduler_priority_SMP_Enqueue_ordered(
|
||||
&self->Base.Base,
|
||||
context,
|
||||
thread,
|
||||
has_processor_allocated,
|
||||
_Scheduler_simple_Insert_priority_fifo_order,
|
||||
_Scheduler_priority_SMP_Insert_ready_fifo,
|
||||
_Scheduler_SMP_Insert_scheduled_fifo
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Extract(
|
||||
void _Scheduler_priority_SMP_Unblock(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Extract(
|
||||
&self->Base.Base,
|
||||
_Scheduler_priority_SMP_Enqueue_fifo( context, thread, false );
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Change_priority(
|
||||
context,
|
||||
thread,
|
||||
_Scheduler_priority_SMP_Do_extract
|
||||
new_priority,
|
||||
prepend_it,
|
||||
_Scheduler_priority_SMP_Extract_from_ready,
|
||||
_Scheduler_priority_SMP_Do_update,
|
||||
_Scheduler_priority_SMP_Enqueue_fifo,
|
||||
_Scheduler_priority_SMP_Enqueue_lifo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -299,12 +315,13 @@ void _Scheduler_priority_SMP_Yield(
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
_Scheduler_priority_SMP_Extract( scheduler, thread );
|
||||
_Scheduler_priority_SMP_Enqueue_fifo( scheduler, thread );
|
||||
_Scheduler_SMP_Extract_from_scheduled( thread );
|
||||
_Scheduler_priority_SMP_Enqueue_fifo( context, thread, true );
|
||||
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
@@ -314,15 +331,8 @@ void _Scheduler_priority_SMP_Schedule(
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Schedule(
|
||||
&self->Base.Base,
|
||||
thread,
|
||||
_Scheduler_priority_SMP_Get_highest_ready,
|
||||
_Scheduler_priority_SMP_Move_from_ready_to_scheduled
|
||||
);
|
||||
(void) scheduler;
|
||||
(void) thread;
|
||||
}
|
||||
|
||||
void _Scheduler_priority_SMP_Start_idle(
|
||||
@@ -331,8 +341,7 @@ void _Scheduler_priority_SMP_Start_idle(
|
||||
Per_CPU_Control *cpu
|
||||
)
|
||||
{
|
||||
Scheduler_priority_SMP_Context *self =
|
||||
_Scheduler_priority_SMP_Get_context( scheduler );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Start_idle( &self->Base.Base, thread, cpu );
|
||||
_Scheduler_SMP_Start_idle( context, thread, cpu );
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ void _Scheduler_priority_Update(
|
||||
Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread );
|
||||
|
||||
_Scheduler_priority_Ready_queue_update(
|
||||
the_thread,
|
||||
&node->Ready_queue,
|
||||
the_thread->current_priority,
|
||||
&context->Bit_map,
|
||||
&context->Ready[ 0 ]
|
||||
);
|
||||
|
||||
+13
-4
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Scheduler Simple Priority Enqueue Ready Thread
|
||||
* @brief Removes a Thread from the Simple Queue
|
||||
*
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
@@ -20,13 +21,21 @@
|
||||
|
||||
#include <rtems/score/schedulersimpleimpl.h>
|
||||
|
||||
void _Scheduler_simple_Ready_queue_enqueue(
|
||||
void _Scheduler_simple_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
Thread_Control *the_thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
Scheduler_simple_Context *context =
|
||||
_Scheduler_simple_Get_context( scheduler );
|
||||
|
||||
_Scheduler_simple_Insert_priority_fifo( &context->Ready, the_thread );
|
||||
_Scheduler_simple_Extract( scheduler, the_thread );
|
||||
|
||||
if ( prepend_it ) {
|
||||
_Scheduler_simple_Insert_priority_lifo( &context->Ready, the_thread );
|
||||
} else {
|
||||
_Scheduler_simple_Insert_priority_fifo( &context->Ready, the_thread );
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Puts Thread onto the Ready Queue
|
||||
*
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulersimpleimpl.h>
|
||||
|
||||
void _Scheduler_simple_Enqueue(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
_Scheduler_simple_Ready_queue_enqueue( scheduler, the_thread );
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Scheduler Simple Enqueue First
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulersimple.h>
|
||||
|
||||
void _Scheduler_simple_Enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
_Scheduler_simple_Ready_queue_enqueue_first( scheduler, the_thread );
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Removes a Thread from the Simple Queue
|
||||
*
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulersimpleimpl.h>
|
||||
|
||||
void _Scheduler_simple_Extract(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
(void) scheduler;
|
||||
|
||||
_Chain_Extract_unprotected( &the_thread->Object.Node );
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Scheduler Simple Ready Queue Enqueue First
|
||||
* @ingroup ScoreScheduler
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/schedulersimpleimpl.h>
|
||||
|
||||
void _Scheduler_simple_Ready_queue_enqueue_first(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_simple_Context *context =
|
||||
_Scheduler_simple_Get_context( scheduler );
|
||||
|
||||
_Scheduler_simple_Insert_priority_lifo( &context->Ready, the_thread );
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <rtems/score/schedulersimplesmp.h>
|
||||
#include <rtems/score/schedulersmpimpl.h>
|
||||
#include <rtems/score/wkspace.h>
|
||||
|
||||
static Scheduler_simple_SMP_Context *
|
||||
_Scheduler_simple_SMP_Get_context( const Scheduler_Control *scheduler )
|
||||
@@ -55,20 +54,25 @@ bool _Scheduler_simple_SMP_Allocate(
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _Scheduler_simple_SMP_Do_update(
|
||||
Scheduler_Context *context,
|
||||
Scheduler_Node *node,
|
||||
Priority_Control new_priority
|
||||
)
|
||||
{
|
||||
(void) context;
|
||||
(void) node;
|
||||
(void) new_priority;
|
||||
}
|
||||
|
||||
static Thread_Control *_Scheduler_simple_SMP_Get_highest_ready(
|
||||
Scheduler_Context *context
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_self( context );
|
||||
Thread_Control *highest_ready = NULL;
|
||||
Chain_Control *ready = &self->Ready;
|
||||
|
||||
if ( !_Chain_Is_empty( ready ) ) {
|
||||
highest_ready = (Thread_Control *) _Chain_First( ready );
|
||||
}
|
||||
|
||||
return highest_ready;
|
||||
return (Thread_Control *) _Chain_First( &self->Ready );
|
||||
}
|
||||
|
||||
static void _Scheduler_simple_SMP_Move_from_scheduled_to_ready(
|
||||
@@ -131,21 +135,13 @@ static void _Scheduler_simple_SMP_Insert_ready_fifo(
|
||||
);
|
||||
}
|
||||
|
||||
static void _Scheduler_simple_SMP_Do_extract(
|
||||
static void _Scheduler_simple_SMP_Extract_from_ready(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
|
||||
|
||||
(void) context;
|
||||
|
||||
if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
|
||||
_Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_IN_THE_AIR );
|
||||
} else {
|
||||
_Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
|
||||
}
|
||||
|
||||
_Chain_Extract_unprotected( &thread->Object.Node );
|
||||
}
|
||||
|
||||
@@ -154,13 +150,12 @@ void _Scheduler_simple_SMP_Block(
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_context( scheduler );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Block(
|
||||
&self->Base.Base,
|
||||
context,
|
||||
thread,
|
||||
_Scheduler_simple_SMP_Do_extract,
|
||||
_Scheduler_simple_SMP_Extract_from_ready,
|
||||
_Scheduler_simple_SMP_Get_highest_ready,
|
||||
_Scheduler_simple_SMP_Move_from_ready_to_scheduled
|
||||
);
|
||||
@@ -169,6 +164,7 @@ void _Scheduler_simple_SMP_Block(
|
||||
static void _Scheduler_simple_SMP_Enqueue_ordered(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated,
|
||||
Chain_Node_order order,
|
||||
Scheduler_SMP_Insert insert_ready,
|
||||
Scheduler_SMP_Insert insert_scheduled
|
||||
@@ -177,6 +173,7 @@ static void _Scheduler_simple_SMP_Enqueue_ordered(
|
||||
_Scheduler_SMP_Enqueue_ordered(
|
||||
context,
|
||||
thread,
|
||||
has_processor_allocated,
|
||||
order,
|
||||
_Scheduler_simple_SMP_Get_highest_ready,
|
||||
insert_ready,
|
||||
@@ -186,52 +183,66 @@ static void _Scheduler_simple_SMP_Enqueue_ordered(
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_simple_SMP_Enqueue_priority_lifo(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
static void _Scheduler_simple_SMP_Enqueue_lifo(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_context( scheduler );
|
||||
|
||||
_Scheduler_simple_SMP_Enqueue_ordered(
|
||||
&self->Base.Base,
|
||||
context,
|
||||
thread,
|
||||
has_processor_allocated,
|
||||
_Scheduler_simple_Insert_priority_lifo_order,
|
||||
_Scheduler_simple_SMP_Insert_ready_lifo,
|
||||
_Scheduler_SMP_Insert_scheduled_lifo
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_simple_SMP_Enqueue_priority_fifo(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
static void _Scheduler_simple_SMP_Enqueue_fifo(
|
||||
Scheduler_Context *context,
|
||||
Thread_Control *thread,
|
||||
bool has_processor_allocated
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_context( scheduler );
|
||||
|
||||
_Scheduler_simple_SMP_Enqueue_ordered(
|
||||
&self->Base.Base,
|
||||
context,
|
||||
thread,
|
||||
has_processor_allocated,
|
||||
_Scheduler_simple_Insert_priority_fifo_order,
|
||||
_Scheduler_simple_SMP_Insert_ready_fifo,
|
||||
_Scheduler_SMP_Insert_scheduled_fifo
|
||||
);
|
||||
}
|
||||
|
||||
void _Scheduler_simple_SMP_Extract(
|
||||
void _Scheduler_simple_SMP_Unblock(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_context( scheduler );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Extract(
|
||||
&self->Base.Base,
|
||||
_Scheduler_simple_SMP_Enqueue_fifo( context, thread, false );
|
||||
}
|
||||
|
||||
void _Scheduler_simple_SMP_Change_priority(
|
||||
const Scheduler_Control *scheduler,
|
||||
Thread_Control *thread,
|
||||
Priority_Control new_priority,
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Change_priority(
|
||||
context,
|
||||
thread,
|
||||
_Scheduler_simple_SMP_Do_extract
|
||||
new_priority,
|
||||
prepend_it,
|
||||
_Scheduler_simple_SMP_Extract_from_ready,
|
||||
_Scheduler_simple_SMP_Do_update,
|
||||
_Scheduler_simple_SMP_Enqueue_fifo,
|
||||
_Scheduler_simple_SMP_Enqueue_lifo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -240,12 +251,13 @@ void _Scheduler_simple_SMP_Yield(
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
_Scheduler_simple_SMP_Extract( scheduler, thread );
|
||||
_Scheduler_simple_SMP_Enqueue_priority_fifo( scheduler, thread );
|
||||
_Scheduler_SMP_Extract_from_scheduled( thread );
|
||||
_Scheduler_simple_SMP_Enqueue_fifo( context, thread, true );
|
||||
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
@@ -255,15 +267,8 @@ void _Scheduler_simple_SMP_Schedule(
|
||||
Thread_Control *thread
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Schedule(
|
||||
&self->Base.Base,
|
||||
thread,
|
||||
_Scheduler_simple_SMP_Get_highest_ready,
|
||||
_Scheduler_simple_SMP_Move_from_ready_to_scheduled
|
||||
);
|
||||
(void) scheduler;
|
||||
(void) thread;
|
||||
}
|
||||
|
||||
void _Scheduler_simple_SMP_Start_idle(
|
||||
@@ -272,8 +277,7 @@ void _Scheduler_simple_SMP_Start_idle(
|
||||
Per_CPU_Control *cpu
|
||||
)
|
||||
{
|
||||
Scheduler_simple_SMP_Context *self =
|
||||
_Scheduler_simple_SMP_Get_context( scheduler );
|
||||
Scheduler_Context *context = _Scheduler_Get_context( scheduler );
|
||||
|
||||
_Scheduler_SMP_Start_idle( &self->Base.Base, thread, cpu );
|
||||
_Scheduler_SMP_Start_idle( context, thread, cpu );
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ void _Scheduler_simple_Unblock(
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
_Scheduler_simple_Ready_queue_enqueue( scheduler, the_thread );
|
||||
Scheduler_simple_Context *context =
|
||||
_Scheduler_simple_Get_context( scheduler );
|
||||
|
||||
_Scheduler_simple_Insert_priority_fifo( &context->Ready, the_thread );
|
||||
|
||||
/*
|
||||
* If the thread that was unblocked is more important than the heir,
|
||||
|
||||
@@ -26,11 +26,14 @@ void _Scheduler_simple_Yield(
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Scheduler_simple_Context *context =
|
||||
_Scheduler_simple_Get_context( scheduler );
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
_Scheduler_simple_Ready_queue_requeue( scheduler, the_thread );
|
||||
_Chain_Extract_unprotected( &the_thread->Object.Node );
|
||||
_Scheduler_simple_Insert_priority_fifo( &context->Ready, the_thread );
|
||||
|
||||
_ISR_Flash( level );
|
||||
|
||||
|
||||
@@ -30,10 +30,9 @@
|
||||
* Table with all valid state transitions. It is used in
|
||||
* _Scheduler_SMP_Node_change_state() in case RTEMS_DEBUG is defined.
|
||||
*/
|
||||
const bool _Scheduler_SMP_Node_valid_state_changes[ 4 ][ 4 ] = {
|
||||
/* BLOCKED SCHEDULED READY IN THE AIR */
|
||||
/* BLOCKED */ { false, true, true, false },
|
||||
/* SCHEDULED */ { false, false, true, true },
|
||||
/* READY */ { true, true, false, false },
|
||||
/* IN THE AIR */ { true, true, true, false }
|
||||
const bool _Scheduler_SMP_Node_valid_state_changes[ 3 ][ 3 ] = {
|
||||
/* FROM / TO BLOCKED SCHEDULED READY */
|
||||
/* BLOCKED */ { false, true, true },
|
||||
/* SCHEDULED */ { true, false, true },
|
||||
/* READY */ { true, true, false }
|
||||
};
|
||||
|
||||
@@ -29,79 +29,40 @@ void _Thread_Change_priority(
|
||||
bool prepend_it
|
||||
)
|
||||
{
|
||||
const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
|
||||
ISR_Level level;
|
||||
States_Control state, original_state;
|
||||
|
||||
/*
|
||||
* Save original state
|
||||
*/
|
||||
original_state = the_thread->current_state;
|
||||
|
||||
/*
|
||||
* Set a transient state for the thread so it is pulled off the Ready chains.
|
||||
* This will prevent it from being scheduled no matter what happens in an
|
||||
* ISR.
|
||||
*/
|
||||
_Thread_Set_transient( the_thread );
|
||||
|
||||
/*
|
||||
* Do not bother recomputing all the priority related information if
|
||||
* we are not REALLY changing priority.
|
||||
*/
|
||||
if ( the_thread->current_priority != new_priority )
|
||||
_Thread_Set_priority( the_thread, new_priority );
|
||||
if ( the_thread->current_priority != new_priority ) {
|
||||
ISR_Level level;
|
||||
const Scheduler_Control *scheduler;
|
||||
|
||||
_ISR_Disable( level );
|
||||
_ISR_Disable( level );
|
||||
|
||||
/*
|
||||
* If the thread has more than STATES_TRANSIENT set, then it is blocked,
|
||||
* If it is blocked on a thread queue, then we need to requeue it.
|
||||
*/
|
||||
state = the_thread->current_state;
|
||||
if ( state != STATES_TRANSIENT ) {
|
||||
/* 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 );
|
||||
scheduler = _Scheduler_Get( the_thread );
|
||||
the_thread->current_priority = new_priority;
|
||||
|
||||
/*
|
||||
* 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( scheduler, the_thread );
|
||||
if ( _States_Is_ready( the_thread->current_state ) ) {
|
||||
_Scheduler_Change_priority(
|
||||
scheduler,
|
||||
the_thread,
|
||||
new_priority,
|
||||
prepend_it
|
||||
);
|
||||
|
||||
_ISR_Enable( level );
|
||||
if ( _States_Is_waiting_on_thread_queue( state ) ) {
|
||||
_Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
|
||||
_ISR_Flash( level );
|
||||
|
||||
/*
|
||||
* 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 = _Scheduler_Get( the_thread );
|
||||
_Scheduler_Schedule( scheduler, the_thread );
|
||||
} else {
|
||||
_Scheduler_Update( scheduler, the_thread );
|
||||
}
|
||||
return;
|
||||
_ISR_Enable( level );
|
||||
|
||||
_Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
|
||||
}
|
||||
|
||||
/* Only clear the transient state if it wasn't set already */
|
||||
if ( ! _States_Is_transient( original_state ) ) {
|
||||
/*
|
||||
* Interrupts are STILL disabled.
|
||||
* We now know the thread will be in the READY state when we remove
|
||||
* the TRANSIENT state. So we have to place it on the appropriate
|
||||
* Ready Queue with interrupts off.
|
||||
*/
|
||||
the_thread->current_state = _States_Clear( STATES_TRANSIENT, state );
|
||||
|
||||
if ( prepend_it )
|
||||
_Scheduler_Enqueue_first( scheduler, the_thread );
|
||||
else
|
||||
_Scheduler_Enqueue( scheduler, the_thread );
|
||||
}
|
||||
|
||||
_ISR_Flash( level );
|
||||
|
||||
/*
|
||||
* 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, the_thread );
|
||||
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Sets the Transient State for a Thread
|
||||
*
|
||||
* @ingroup ScoreThread
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 1989-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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/isrlevel.h>
|
||||
#include <rtems/score/schedulerimpl.h>
|
||||
|
||||
void _Thread_Set_transient(
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
uint32_t old_state;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
old_state = the_thread->current_state;
|
||||
the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state );
|
||||
|
||||
if ( _States_Is_ready( old_state ) ) {
|
||||
_Scheduler_Extract( _Scheduler_Get( the_thread ), the_thread );
|
||||
}
|
||||
|
||||
_ISR_Enable( level );
|
||||
|
||||
}
|
||||
@@ -278,11 +278,6 @@ access an active object.
|
||||
A special low priority task which assumes
|
||||
control of the CPU when no other task is able to execute.
|
||||
|
||||
@item in the air task
|
||||
A task is @dfn{in the air} if it is in a transient state and has a processor
|
||||
assigned. The next scheduler operation will turn it into a blocked, ready or
|
||||
scheduled task. This state is specific to SMP configurations.
|
||||
|
||||
@item interface
|
||||
A specification of the methodology used
|
||||
to connect multiple independent subsystems.
|
||||
|
||||
@@ -50,7 +50,6 @@ _SUBDIRS += sptls02
|
||||
endif
|
||||
_SUBDIRS += sptls01
|
||||
_SUBDIRS += spintrcritical20
|
||||
_SUBDIRS += spintrcritical19
|
||||
_SUBDIRS += spcontext01
|
||||
_SUBDIRS += spfatal26
|
||||
_SUBDIRS += speventtransient01
|
||||
|
||||
@@ -50,7 +50,6 @@ spcpucounter01/Makefile
|
||||
sptls02/Makefile
|
||||
sptls01/Makefile
|
||||
spintrcritical20/Makefile
|
||||
spintrcritical19/Makefile
|
||||
spcontext01/Makefile
|
||||
spfatal26/Makefile
|
||||
spinternalerror02/Makefile
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
rtems_tests_PROGRAMS = spintrcritical19
|
||||
spintrcritical19_SOURCES = init.c ../spintrcritical_support/intrcritical.c
|
||||
|
||||
dist_rtems_tests_DATA = spintrcritical19.scn spintrcritical19.doc
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../automake/compile.am
|
||||
include $(top_srcdir)/../automake/leaf.am
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/spintrcritical_support
|
||||
|
||||
LINK_OBJS = $(spintrcritical19_OBJECTS)
|
||||
LINK_LIBS = $(spintrcritical19_LDLIBS)
|
||||
|
||||
spintrcritical19$(EXEEXT): $(spintrcritical19_OBJECTS) $(spintrcritical19_DEPENDENCIES)
|
||||
@rm -f spintrcritical19$(EXEEXT)
|
||||
$(make-exe)
|
||||
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <tmacros.h>
|
||||
#include <intrcritical.h>
|
||||
#include <rtems/score/statesimpl.h>
|
||||
|
||||
const char rtems_test_name[] = "SPINTRCRITICAL 19";
|
||||
|
||||
#define PRIORITY_RED 1
|
||||
|
||||
#define PRIORITY_GREEN 2
|
||||
|
||||
#define PRIORITY_RESUMER 3
|
||||
|
||||
typedef struct {
|
||||
rtems_id master_task;
|
||||
rtems_id resumer_task;
|
||||
Thread_Control *master_task_tcb;
|
||||
bool test_case_hit;
|
||||
} test_context;
|
||||
|
||||
static test_context ctx_instance;
|
||||
|
||||
static void resumer_task(rtems_task_argument arg)
|
||||
{
|
||||
test_context *ctx = (test_context *) arg;
|
||||
|
||||
while (true) {
|
||||
rtems_status_code sc = rtems_task_resume(ctx->master_task);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
}
|
||||
}
|
||||
|
||||
static void suspend_master_task(rtems_id timer, void *arg)
|
||||
{
|
||||
/* The arg is NULL */
|
||||
test_context *ctx = &ctx_instance;
|
||||
rtems_status_code sc;
|
||||
|
||||
if (_States_Is_transient(ctx->master_task_tcb->current_state)) {
|
||||
ctx->test_case_hit = true;
|
||||
}
|
||||
|
||||
sc = rtems_task_suspend(ctx->master_task);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
}
|
||||
|
||||
static void Init(rtems_task_argument ignored)
|
||||
{
|
||||
test_context *ctx = &ctx_instance;
|
||||
rtems_task_priority priority = PRIORITY_RED;
|
||||
int resets = 0;
|
||||
rtems_status_code sc;
|
||||
|
||||
TEST_BEGIN();
|
||||
|
||||
ctx->master_task = rtems_task_self();
|
||||
ctx->master_task_tcb = _Thread_Get_executing();
|
||||
|
||||
sc = rtems_task_create(
|
||||
rtems_build_name('R', 'E', 'S', 'U'),
|
||||
PRIORITY_RESUMER,
|
||||
RTEMS_MINIMUM_STACK_SIZE,
|
||||
RTEMS_DEFAULT_MODES,
|
||||
RTEMS_DEFAULT_ATTRIBUTES,
|
||||
&ctx->resumer_task
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
sc = rtems_task_start(
|
||||
ctx->resumer_task,
|
||||
resumer_task,
|
||||
(rtems_task_argument) ctx
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
interrupt_critical_section_test_support_initialize(
|
||||
suspend_master_task
|
||||
);
|
||||
|
||||
while (resets < 3 && !ctx->test_case_hit) {
|
||||
if (interrupt_critical_section_test_support_delay()) {
|
||||
++resets;
|
||||
}
|
||||
|
||||
sc = rtems_task_set_priority(RTEMS_SELF, priority, &priority);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_assert(_States_Is_ready(ctx->master_task_tcb->current_state));
|
||||
}
|
||||
|
||||
rtems_test_assert(ctx->test_case_hit);
|
||||
|
||||
sc = rtems_task_delete(ctx->resumer_task);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
TEST_END();
|
||||
|
||||
rtems_test_exit(0);
|
||||
}
|
||||
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
|
||||
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
#define CONFIGURE_MAXIMUM_TIMERS 1
|
||||
|
||||
#define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_GREEN
|
||||
#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
|
||||
#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
|
||||
|
||||
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
#define CONFIGURE_INIT
|
||||
|
||||
#include <rtems/confdefs.h>
|
||||
@@ -1,13 +0,0 @@
|
||||
This file describes the directives and concepts tested by this test set.
|
||||
|
||||
test set name: spintrcritical19
|
||||
|
||||
directives:
|
||||
|
||||
- rtems_task_suspend()
|
||||
- rtems_task_set_priority()
|
||||
|
||||
concepts:
|
||||
|
||||
- Ensure that a priority change works during suspend requests from an
|
||||
interrupt service routine.
|
||||
@@ -1,4 +0,0 @@
|
||||
*** TEST INTERRUPT CRITICAL SECTION 19 ***
|
||||
|
||||
Support - rtems_timer_create - creating timer 1
|
||||
*** END OF TEST INTERRUPT CRITICAL SECTION 19 ***
|
||||
Reference in New Issue
Block a user