From: Petr Benes Date: Tue, 29 Mar 2011 17:30:22 +0000 (+0200) Subject: EDF pluggable scheduler running! X-Git-Url: https://rtime.felk.cvut.cz/gitweb/rtems-pluggable-edf.git/commitdiff_plain/e9a60ef11ae3b01f4e927b6005bd59cea462c329 EDF pluggable scheduler running! The period/deadline is taken over from the priority number. There is a better API for EDF required. A minor hack involving the idle task has been made in order to take into account it's lowest priority. This should be somehow extended for all eventual tasks having no specific deadline. --- diff --git a/rtems-omk-template/appfoo/init.c b/rtems-omk-template/appfoo/init.c index ed6ab84..76cbc2e 100644 --- a/rtems-omk-template/appfoo/init.c +++ b/rtems-omk-template/appfoo/init.c @@ -79,10 +79,10 @@ rtems_task Init( printf( "Starting application " SW_VER_ID " v " BUILD_VERSION_STRING(SW_VER_MAJOR,SW_VER_MINOR,SW_VER_PATCH) "\n" ); - + +// Task 1 ============================================== Task_1_name = rtems_build_name( 'T', 'S', 'K', '1' ); - Task_2_name = rtems_build_name( 'T', 'S', 'K', '2' ); - + status = rtems_task_create( Task_1_name, TASK_1_PRIORITY, @@ -91,11 +91,14 @@ rtems_task Init( RTEMS_DEFAULT_ATTRIBUTES, &Task_1_id ); - - check_rtems_status(status, 0, "rtems_task_create of Task_1"); + status = rtems_task_start( Task_1_id, Task_1, 0 ); + check_rtems_status(status, 0, "rtems_task_start of Task_1\n"); +// Task 2 ============================================== + Task_2_name = rtems_build_name( 'T', 'S', 'K', '2' ); + status = rtems_task_create( Task_2_name, TASK_2_PRIORITY, @@ -107,13 +110,12 @@ rtems_task Init( check_rtems_status(status, 0, "rtems_task_create of Task_2"); - status = rtems_task_start( Task_1_id, Task_1, 0 ); - check_rtems_status(status, 0, "rtems_task_start of Task_1\n"); status = rtems_task_start( Task_2_id, Task_2, 0 ); check_rtems_status(status, 0, "rtems_task_start of Task_2\n"); - +// ==================================================== + rtems_shell_init("SHLL",RTEMS_MINIMUM_STACK_SIZE+0x1000, SHELL_TASK_PRIORITY,"/dev/console",1,0, NULL); diff --git a/rtems-omk-template/appfoo/scheduler_edf.c b/rtems-omk-template/appfoo/scheduler_edf.c index 2cbd8b3..90ce44d 100644 --- a/rtems-omk-template/appfoo/scheduler_edf.c +++ b/rtems-omk-template/appfoo/scheduler_edf.c @@ -5,9 +5,10 @@ #include #include #include +#include /* let the scheduler talk */ -#define SCHED_VERBOSE +//#define SCHED_VERBOSE void _Scheduler_edf_Initialize(void) { @@ -25,7 +26,15 @@ void _Scheduler_edf_Block( Thread_Control *the_thread ) { #ifdef SCHED_VERBOSE printf("Sched: Block"); #endif - _Scheduler_edf_Extract(the_thread); + _Scheduler_edf_Extract(the_thread); + + /* TODO: flash critical section? */ + + if ( _Thread_Is_heir( the_thread ) ) + _Scheduler_edf_Schedule(); + + if ( _Thread_Is_executing( the_thread ) ) + _Thread_Dispatch_necessary = true; } void _Scheduler_edf_Schedule(void) { @@ -33,7 +42,7 @@ void _Scheduler_edf_Schedule(void) { printf("Sched: Schedule"); #endif // set the heir - _Thread_Heir = (Thread_Control *) _Thread_Ready_EDF_chain.first; + _Thread_Heir = (Thread_Control *) _Thread_Ready_EDF_chain.first; } void * _Scheduler_edf_Allocate( Thread_Control *the_thread) { @@ -44,10 +53,10 @@ void * _Scheduler_edf_Allocate( Thread_Control *the_thread) { RBT_Node *schinfo; sched = _Workspace_Allocate (sizeof(RBT_Node)); the_thread->scheduler_info = (RBT_Node *) sched; - the_thread->real_priority = ABS_DEADLINE_MAXIMUM - _Watchdog_Ticks_since_boot-2; - the_thread->is_preemptible = TRUE; - the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; - the_thread->budget_callout = NULL; + //the_thread->real_priority = ABS_DEADLINE_MAXIMUM - _Watchdog_Ticks_since_boot-2; + //the_thread->is_preemptible = TRUE; + //the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; + //the_thread->budget_callout = NULL; schinfo = (RBT_Node *)(the_thread->scheduler_info); schinfo->rel_deadline = the_thread->real_priority; @@ -56,7 +65,7 @@ void * _Scheduler_edf_Allocate( Thread_Control *the_thread) { schinfo->right = NULL; schinfo->parent = NULL; schinfo->ready_chain = &_Thread_Ready_EDF_chain; - + return sched; } @@ -73,16 +82,35 @@ void _Scheduler_edf_Update( Thread_Control *the_thread) { #endif // after a priority changes, just extract and insert again //in case it is in the tree - EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain; - _RBT_Extract(chain, the_thread); - _RBT_Insert(chain, the_thread); // preserve the abs_deadline +// EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain; +// _RBT_Extract(chain, the_thread); +// _RBT_Insert(chain, the_thread); // preserve the abs_deadline } void _Scheduler_edf_Unblock( Thread_Control *the_thread ) { #ifdef SCHED_VERBOSE printf("Sched: Unblock"); #endif - _Scheduler_edf_Enqueue(the_thread); + _Scheduler_edf_Enqueue(the_thread); + /* TODO: flash critical section? */ + + /* + * If the thread that was unblocked is more important than the heir, + * then we have a new heir. This may or may not result in a + * context switch. + * + * Normal case: + * If the current thread is preemptible, then we need to do + * a context switch. + * Pseudo-ISR case: + * Even if the thread isn't preemptible, if the new heir is + * a pseudo-ISR system task, we need to do a context switch. + */ + if ( the_thread->current_priority < _Thread_Heir->current_priority ) { + _Thread_Heir = the_thread; + if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 ) + _Thread_Dispatch_necessary = true; + } } void _Scheduler_edf_Yield( void ) { @@ -113,7 +141,6 @@ void _Scheduler_edf_Yield( void ) { _Thread_Dispatch_necessary = TRUE; _ISR_Enable( level ); - // -------------------------------- } @@ -123,8 +150,12 @@ void _Scheduler_edf_Enqueue( Thread_Control *the_thread) { #endif RBT_Node *node = (RBT_Node*)the_thread->scheduler_info; EDF_Chain_Control *chain = node->ready_chain; - node->abs_deadline = _Watchdog_Ticks_since_boot + node->rel_deadline; + if (node->rel_deadline == 255) //hack for idle task + node->abs_deadline = ABS_DEADLINE_MAXIMUM; + else + node->abs_deadline = _Watchdog_Ticks_since_boot + node->rel_deadline; _RBT_Insert(chain,the_thread); + } void _Scheduler_edf_Enqueue_first( Thread_Control *the_thread) { @@ -132,15 +163,14 @@ void _Scheduler_edf_Enqueue_first( Thread_Control *the_thread) { printf("Sched: Enqueue_first"); #endif // FIXME: force first position - EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain; - _RBT_Insert(chain,the_thread); + _Scheduler_edf_Enqueue(the_thread); } void _Scheduler_edf_Extract( Thread_Control *the_thread) { #ifdef SCHED_VERBOSE printf("Sched: Extract"); #endif - EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain; - _RBT_Extract(chain,the_thread); + EDF_Chain_Control* chain = ((RBT_Node*)the_thread->scheduler_info)->ready_chain; + _RBT_Extract(chain,the_thread); } diff --git a/rtems-omk-template/appfoo/system.h b/rtems-omk-template/appfoo/system.h index 4bff97e..bccc673 100644 --- a/rtems-omk-template/appfoo/system.h +++ b/rtems-omk-template/appfoo/system.h @@ -90,13 +90,14 @@ rtems_task Init( #define CONFIGURE_SCHEDULER_USER_ENTRY_POINTS // EDF #include "scheduler_edf.h" +#include "rbtree.h" #define SCHEDULER_ENTRY_POINTS SCHEDULER_EDF_ENTRY_POINTS -// Priority -//#include "scheduler_priority.h" -//#define SCHEDULER_ENTRY_POINTS SCHEDULER_PRIORITY_ENTRY_POINTS + // Priority + //#include "scheduler_priority.h" + //#define SCHEDULER_ENTRY_POINTS SCHEDULER_PRIORITY_ENTRY_POINTS -#define CONFIGURE_MEMORY_FOR_SCHEDULER (1024) -#define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER (256) +#define CONFIGURE_MEMORY_FOR_SCHEDULER (_Configure_From_workspace(sizeof(EDF_Chain_Control))) +#define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER (_Configure_From_workspace(sizeof(RBT_Node))) diff --git a/rtems-omk-template/appfoo/task_2.c b/rtems-omk-template/appfoo/task_2.c index 4101717..160ff6c 100644 --- a/rtems-omk-template/appfoo/task_2.c +++ b/rtems-omk-template/appfoo/task_2.c @@ -23,7 +23,7 @@ rtems_task Task_2( for (i=0; i<10000; i++) { s = i + i; } - status = rtems_task_wake_after( TICKS_PER_SECOND*2 ); + status = rtems_task_wake_after( TICKS_PER_SECOND*1.5 ); check_rtems_status( status, 0, "rtems_task_wake_after" ); } }