From b6e1e7acdc1d4a6e15742b2222450e470d218bd2 Mon Sep 17 00:00:00 2001 From: Petr Benes Date: Thu, 24 Mar 2011 12:57:05 +0100 Subject: [PATCH] Task 2 added and pluggable EDF scheduler base for RTEMS added. The EDF does not fire yet, necessary to readjust the rbtree. Sorry for this huge commit. --- rtems-omk-template/appfoo/Makefile.omk | 2 +- rtems-omk-template/appfoo/app_def.h | 8 + rtems-omk-template/appfoo/init.c | 22 +- rtems-omk-template/appfoo/rbtree.c | 365 ++++++++++++++++ rtems-omk-template/appfoo/rbtree.h | 32 ++ rtems-omk-template/appfoo/scheduler_edf.c | 125 ++++++ rtems-omk-template/appfoo/scheduler_edf.h | 139 +++++++ .../appfoo/scheduler_priority.c | 393 ++++++++++++++++++ .../appfoo/scheduler_priority.h | 194 +++++++++ rtems-omk-template/appfoo/system.h | 43 ++ rtems-omk-template/appfoo/task_2.c | 30 ++ 11 files changed, 1351 insertions(+), 2 deletions(-) create mode 100644 rtems-omk-template/appfoo/rbtree.c create mode 100644 rtems-omk-template/appfoo/rbtree.h create mode 100644 rtems-omk-template/appfoo/scheduler_edf.c create mode 100644 rtems-omk-template/appfoo/scheduler_edf.h create mode 100644 rtems-omk-template/appfoo/scheduler_priority.c create mode 100644 rtems-omk-template/appfoo/scheduler_priority.h create mode 100644 rtems-omk-template/appfoo/task_2.c diff --git a/rtems-omk-template/appfoo/Makefile.omk b/rtems-omk-template/appfoo/Makefile.omk index 135b758..ed000fe 100644 --- a/rtems-omk-template/appfoo/Makefile.omk +++ b/rtems-omk-template/appfoo/Makefile.omk @@ -7,7 +7,7 @@ bin_PROGRAMS = appfoo #include_HEADERS = -appfoo_SOURCES += init.c task_1.c +appfoo_SOURCES += init.c task_1.c task_2.c scheduler_edf.c scheduler_priority.c rbtree.c #appfoo_EMBEDTARFILES = rootfs diff --git a/rtems-omk-template/appfoo/app_def.h b/rtems-omk-template/appfoo/app_def.h index 6527316..3e07a26 100644 --- a/rtems-omk-template/appfoo/app_def.h +++ b/rtems-omk-template/appfoo/app_def.h @@ -16,9 +16,16 @@ extern "C" { COND_EXTERN rtems_id Task_1_id; /* Task 1 id */ COND_EXTERN rtems_name Task_1_name; /* Task 1 name */ +COND_EXTERN rtems_id Task_2_id; /* Task 2 id */ +COND_EXTERN rtems_name Task_2_name; /* Task 2 name */ + + rtems_task Task_1( rtems_task_argument argument ); +rtems_task Task_2( + rtems_task_argument argument +); void bad_rtems_status(rtems_status_code status, int fail_level, const char *text); @@ -30,6 +37,7 @@ void check_rtems_status(rtems_status_code status, int fail_level, const char *te } #define TASK_1_PRIORITY 30 +#define TASK_2_PRIORITY 40 #define SHELL_TASK_PRIORITY 50 #ifdef __cplusplus diff --git a/rtems-omk-template/appfoo/init.c b/rtems-omk-template/appfoo/init.c index f7037f2..ed6ab84 100644 --- a/rtems-omk-template/appfoo/init.c +++ b/rtems-omk-template/appfoo/init.c @@ -30,6 +30,7 @@ #include #include + #define BUILD_VERSION_STRING(major,minor,patch) \ __XSTRING(major) "." __XSTRING(minor) "." __XSTRING(patch) @@ -80,6 +81,7 @@ rtems_task Init( "\n" ); 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, @@ -89,11 +91,29 @@ rtems_task Init( RTEMS_DEFAULT_ATTRIBUTES, &Task_1_id ); + + check_rtems_status(status, 0, "rtems_task_create of Task_1"); + + status = rtems_task_create( + Task_2_name, + TASK_2_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE+0x10000, + RTEMS_DEFAULT_MODES /*& ~(RTEMS_TIMESLICE_MASK) | RTEMS_TIMESLICE*/, + RTEMS_DEFAULT_ATTRIBUTES, + &Task_2_id + ); + + 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); @@ -105,6 +125,6 @@ rtems_task Init( status = rtems_task_delete( RTEMS_SELF ); - printf( "*** END OF TEST2 ***\n" ); + printf( "*** END OF TEST3 ***\n" ); exit( 0 ); } diff --git a/rtems-omk-template/appfoo/rbtree.c b/rtems-omk-template/appfoo/rbtree.c new file mode 100644 index 0000000..cd9840c --- /dev/null +++ b/rtems-omk-template/appfoo/rbtree.c @@ -0,0 +1,365 @@ +#include +#include +#include "edf_types.h" + + +static void _Rotate_Left( + EDF_Chain_Control *chain, + EDF_Node *node +) +{ + EDF_Node *right = node->right; + + if ((node->right = right->left)) + right->left->parent = node; + right->left = node; + if ((right->parent = node->parent)) + { + if (node == node->parent->left) + node->parent->left = right; + else + node->parent->right = right; + } + else + chain->root = right; + node->parent = right; +} + +static void _Rotate_Right( + EDF_Chain_Control *chain, + EDF_Node *node +) +{ + EDF_Node *left = node->left; + + if ((node->left = left->right)) + left->right->parent = node; + left->right = node; + + if ((left->parent = node->parent)) + { + if (node == node->parent->right) + node->parent->right = left; + else + node->parent->left = left; + } + else + chain->root = left; + node->parent = left; +} + +void _RBT_Insert( + EDF_Chain_Control *chain, + EDF_Node *node +) +{ + EDF_Node *parent, *child, *uncle, *gparent, *tmp; + + parent = NULL; + child = chain->root; + + /* Insert new node into tree */ + + while (child) + { + parent = child; + child = ( node->abs_deadline < child->abs_deadline ) \ + ? child->left : child->right; + } + + node->parent = parent; + node->left = NULL; + node->right = NULL; + node->color = RED; + + if (parent) + { + if ( node->abs_deadline < parent->abs_deadline ) + { + parent->left = node; + if ( parent == chain->first ) chain->first = node; + } + else parent->right = node; + } else + { + chain->root = node; + chain->first = node; + } + + /* Insert_FixUp */ + /* check and fix red-back properties eventually */ + while ((parent = node->parent) && parent->color == RED) + { + gparent = parent->parent; + + if (parent == gparent->left) + { + uncle = gparent->right; + + if ( uncle && uncle->color == RED) + { + parent->color = BLACK; + uncle->color = BLACK; + gparent->color = RED; + node = gparent; + continue; + } + + if (node == parent->right) + { + _Rotate_Left(chain,parent); + tmp = parent; + parent = node; + node = tmp; + } + + parent->color = BLACK; + gparent->color = RED; + _Rotate_Right(chain, gparent); + + } else { + uncle = gparent->left; + + if (uncle && uncle->color == RED ) + { + parent->color = BLACK; + uncle->color = BLACK; + gparent->color = RED; + node = parent->parent; + continue; + } + + if (node == parent->left) + { + _Rotate_Right(chain, parent); + tmp = parent; + parent = node; + node = tmp; + + } + + parent->color = BLACK; + gparent->color = RED; + _Rotate_Left(chain, gparent); + } + } + + chain->root->color = BLACK; +} + +static void _RBT_Delete_Fixup( + EDF_Chain_Control *chain, + EDF_Node *node, + EDF_Node *parent +) +{ + EDF_Node *other, *o_child; + + while ((!node || node->color == BLACK) && node != chain->root) + { + if (parent->left == node) + { + other = parent->right; + if (other->color == RED) + { + other->color = BLACK; + parent->color = RED; + _Rotate_Left(chain, parent); + other = parent->right; + } + if ((!other->left || + other->left->color == BLACK) + && (!other->right || + other->right->color == BLACK)) + { + other->color = RED; + node = parent; + parent = node->parent; + } + else + { + if (!other->right || + other->right->color == BLACK) + { + if ((o_child = other->left)) + o_child->color = BLACK; + other->color = RED; + _Rotate_Right(chain,other); + other = parent->right; + } + other->color = parent->color; + parent->color = BLACK; + if (other->right) + other->right->color = BLACK; + _Rotate_Left(chain,parent); + node = chain->root; + break; + } + } + else + { + other = parent->left; + if (other->color == RED) + { + other->color = BLACK; + parent->color = RED; + _Rotate_Right(chain,parent); + other = parent->left; + } + if ((!other->left || + other->left->color == BLACK) + && (!other->right || + other->right->color == BLACK)) + { + other->color = RED; + node = parent; + parent = node->parent; + } + else + { + if (!other->left || + other->left->color == BLACK) + { + register struct rb_node *o_right; + if ((o_child = other->right)) + o_child->color = BLACK; + other->color = RED; + _Rotate_Left(chain,other); + other = parent->left; + } + other->color = parent->color; + parent->color = BLACK; + if (other->left) + other->left->color = BLACK; + _Rotate_Right(chain,parent); + node = chain->root; + break; + } + } + } + if (node) + node->color = BLACK; +} + + +void _RBT_Extract( + EDF_Chain_Control *chain, + EDF_Node *node +) +{ + EDF_Node *child, *parent; + int color; + + if ( chain->first == node ) + { + if ( chain->first->right) chain->first = chain->first->right; + else chain->first = chain->first->parent; + } + + if (!node->left) + child = node->right; + else if (!node->right) + child = node->left; + else + { + /* this will never happen since only the first node + * is being removed every time + */ + + EDF_Node *old = node, *left; + + node = node->right; + while ((left = node->left) != NULL) + node = left; + child = node->right; + parent = node->parent; + color = node->color; + + if (child) + child->parent = parent; + if (parent) + { + if (parent->left == node) + parent->left = child; + else + parent->right = child; + } + else + chain->root = child; + + if (node->parent == old) + parent = node; + node->parent = old->parent; + node->color = old->color; + node->right = old->right; + node->left = old->left; + + if (old->parent) + { + if (old->parent->left == old) + old->parent->left = node; + else + old->parent->right = node; + } else + chain->root = node; + + old->left->parent = node; + if (old->right) + old->right->parent = node; + goto color; + } + + parent = node->parent; + color = node->color; + + if (child) + child->parent = parent; + if (parent) + { + if (parent->left == node) + parent->left = child; + else + parent->right = child; + } + else + chain->root = child; + + color: + if (color == BLACK) + _RBT_Delete_Fixup(chain,child,parent); +} + +/* + * TRUE if there is only one node in tree + */ + +boolean _RBT_Has_only_one_node( + EDF_Chain_Control *chain +) +{ + if ( !chain->root ) return 0; + return ( chain->root->left == chain->root->right == NULL ) ; +} + +/* + * Returns node with specific absolute deadline + */ + +EDF_Node* _RBT_Search( + EDF_Chain_Control *chain, + Deadline_Control absdeadline +) +{ + EDF_Node *current; + + current = chain->root; + while (current != NULL) { + if ( absdeadline == current->abs_deadline) return current; + else { + current = (absdeadline < current->abs_deadline) ? + current->left : current->right; + } + } + return NULL; +} + diff --git a/rtems-omk-template/appfoo/rbtree.h b/rtems-omk-template/appfoo/rbtree.h new file mode 100644 index 0000000..77e77ab --- /dev/null +++ b/rtems-omk-template/appfoo/rbtree.h @@ -0,0 +1,32 @@ +#ifndef __RBTREE_h +#define __RBTREE_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include "edf_types.h" + +// This struct will be embedded into the Thread_Control control +// as scheduler_info +typedef struct RBT_node_struct { + Deadline_Control abs_deadline; + Deadline_Control rel_deadline; + EDF_Node *left; + EDF_Node *right; + EDF_Node *parent; + Node_Color color; + EDF_Chain_Control *ready_chain; +} RBT_Node; + +void _RBT_Insert(EDF_Chain_Control *chain,EDF_Node *node); +void _RBT_Extract(EDF_Chain_Control *chain,EDF_Node *node); +EDF_Node* _RBT_Search(EDF_Chain_Control *chain,Deadline_Control absdeadline); +boolean _RBT_Has_only_one_node(EDF_Chain_Control *chain); + + +#ifdef __cplusplus +} +#endif + +#endif /* __RBTREE_h */ diff --git a/rtems-omk-template/appfoo/scheduler_edf.c b/rtems-omk-template/appfoo/scheduler_edf.c new file mode 100644 index 0000000..35cfd4e --- /dev/null +++ b/rtems-omk-template/appfoo/scheduler_edf.c @@ -0,0 +1,125 @@ +#include "scheduler_edf.h" +#include "rbtree.h" +#include +#include +#include + +/* let the scheduler talk */ +//#define SCHED_VERBOSE + + +void _Scheduler_edf_Initialize(void) { + #ifdef SCHED_VERBOSE + printf("Sched: Initialize"); + #endif + // nainicializovat strom + _Thread_Ready_EDF_chain.root = NULL; + _Thread_Ready_EDF_chain.first = NULL; +} + +void _Scheduler_edf_Block( Thread_Control *the_thread ) { + #ifdef SCHED_VERBOSE + printf("Sched: Block"); + #endif + _Scheduler_edf_Extract(the_thread); +} + +void _Scheduler_edf_Schedule(void) { + #ifdef SCHED_VERBOSE + printf("Sched: Schedule"); + #endif + // hastavit heir + _Thread_Heir = (Thread_Control *) _Thread_Ready_EDF_chain.first; +} + +void * _Scheduler_edf_Allocate( Thread_Control *the_thread) { + #ifdef SCHED_VERBOSE + printf("Sched: Allocate"); + #endif + void * sched; + mem = _Workspace_Allocate (sizeof(RBT_node)); + the_thread->scheduler_info = (RBT_node *) sched; + return mem; +} + +void _Scheduler_edf_Free( Thread_Control *the_thread) { + #ifdef SCHED_VERBOSE + printf("Sched: Free"); + #endif + _Workspace_Free (the_thread->scheduler_info); +} + +void _Scheduler_edf_Update( Thread_Control *the_thread) { + #ifdef SCHED_VERBOSE + printf("Sched: Update"); + #endif + // after a priority changes, just extract and insert again + //in case it is in the tree + _Scheduler_edf_Extract(the_thread); + _Scheduler_edf_Enqueue(the_thread); +} + +void _Scheduler_edf_Unblock( Thread_Control *the_thread ) { + #ifdef SCHED_VERBOSE + printf("Sched: Unblock"); + #endif + _Scheduler_edf_Enqueue(the_thread); +} + +void _Scheduler_edf_Yield( void ) { + #ifdef SCHED_VERBOSE + printf("Sched: Yield"); + #endif + + RBT_node *sched_info; + ISR_Level level; + Thread_Control *executing; + EDF_Chain_Control *ready; + + executing = _Thread_Executing; + sched_info = (RBT_node *) executing->scheduler_info; + ready = sched_info->ready_chain; + _ISR_Disable( level ); + if ( !_RBT_Has_only_one_node( ready ) ) { + _RBT_Extract(ready,executing); + _RBT_Insert(ready,executing); + + _ISR_Flash( level ); + + if ( _Thread_Is_heir( executing ) ) + _Thread_Heir = (Thread_Control *) ready->first; + _Thread_Dispatch_necessary = true; + } + else if ( !_Thread_Is_heir( executing ) ) + _Thread_Dispatch_necessary = true; + + _ISR_Enable( level ); + +} + +void _Scheduler_edf_Enqueue( Thread_Control *the_thread) { + #ifdef SCHED_VERBOSE + printf("Sched: Enqueue"); + #endif + // insert do stromu + EDF_Chain_Control* chain = the_thread->scheduler_info->ready_chain; + _RBT_Insert(chain,the_thread); +} + +void _Scheduler_edf_Enqueue_first( Thread_Control *the_thread) { + #ifdef SCHED_VERBOSE + printf("Sched: Enqueue_first"); + #endif + // FIXME: force first position + EDF_Chain_Control* chain = the_thread->scheduler_info->ready_chain; + _RBT_Insert(chain,the_thread); +} + +void _Scheduler_edf_Extract( Thread_Control *the_thread) { + #ifdef SCHED_VERBOSE + printf("Sched: Extract"); + #endif + EDF_Chain_Control* chain = the_thread->scheduler_info->ready_chain; + _RBT_Extract(chain,the_thread); +} + diff --git a/rtems-omk-template/appfoo/scheduler_edf.h b/rtems-omk-template/appfoo/scheduler_edf.h new file mode 100644 index 0000000..dcad0ba --- /dev/null +++ b/rtems-omk-template/appfoo/scheduler_edf.h @@ -0,0 +1,139 @@ +#ifndef _SCHEDULER_EDF_H +#define _SCHEDULER_EDF_H + +#include +#include +#include +#include "edf_types.h" + +// keeps the ready queue for EDF +EDF_Chain_Control _Thread_Ready_EDF_chain; + +#define SCHEDULER_EDF_ENTRY_POINTS \ + { \ + _Scheduler_edf_Initialize, /* initialize entry point */ \ + _Scheduler_edf_Schedule, /* schedule entry point */ \ + _Scheduler_edf_Yield, /* yield entry point */ \ + _Scheduler_edf_Block, /* block entry point */ \ + _Scheduler_edf_Unblock, /* unblock entry point */ \ + _Scheduler_edf_Allocate, /* allocate entry point */ \ + _Scheduler_edf_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 */ \ + } + + + +/** + * This routine initializes the priority scheduler. + */ +void _Scheduler_edf_Initialize(void); + +/** + * This routine removes @a the_thread from the scheduling decision, + * that is, removes it from the ready queue. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_edf_Block( + Thread_Control *the_thread +); + +/** + * This kernel routine sets the heir thread to be the next ready thread + * by invoking the_scheduler->ready_queue->operations->first(). + */ +void _Scheduler_edf_Schedule(void); + +/** + * This routine allocates @a the_thread->scheduler. + * + * @param[in] the_thread is the thread the scheduler is allocating + * management memory for + */ +void * _Scheduler_edf_Allocate( + Thread_Control *the_thread +); + +/** + * This routine frees @a the_thread->scheduler. + * + * @param[in] the_thread is the thread whose scheduler specific information + * will be deallocated. + */ +void _Scheduler_edf_Free( + Thread_Control *the_thread +); + +/** + * This routine updates @a the_thread->scheduler based on @a the_scheduler + * structures and thread state. + * + * @param[in] the_thread will have its scheduler specific information + * structure updated. + */ +void _Scheduler_edf_Update( + Thread_Control *the_thread +); + +/** + * This routine adds @a the_thread to the scheduling decision, + * that is, adds it to the ready queue and + * updates any appropriate scheduling variables, for example the heir thread. + * + * @param[in] the_thread will be unblocked + */ +void _Scheduler_edf_Unblock( + Thread_Control *the_thread +); + +/** + * This routine is invoked when a thread wishes to voluntarily + * transfer control of the processor to another thread in the queue. + * + * This routine will remove the running THREAD from the ready queue + * and place it immediately at the rear of this chain. Reset timeslice + * and yield the processor functions both use this routine, therefore if + * reset is true and this is the only thread on the queue then the + * timeslice counter is reset. The heir THREAD will be updated if the + * running is also the currently the heir. + */ +void _Scheduler_edf_Yield( void ); + +/** + * 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_edf_Enqueue( + Thread_Control *the_thread +); + +/** + * 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_edf_Enqueue_first( + Thread_Control *the_thread +); + +/** + * 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( + Thread_Control *the_thread +); + + + +#endif /*_SCHEDULER_EDF_H*/ \ No newline at end of file diff --git a/rtems-omk-template/appfoo/scheduler_priority.c b/rtems-omk-template/appfoo/scheduler_priority.c new file mode 100644 index 0000000..d2a0c88 --- /dev/null +++ b/rtems-omk-template/appfoo/scheduler_priority.c @@ -0,0 +1,393 @@ +// ===================================================================================== +// ===================================================================================== +// ===================================================================================== + +/* + * Scheduler Priority Handler / Allocate + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityallocate.c,v 1.1 2011/02/18 15:12:43 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +void* _Scheduler_priority_Allocate ( + Thread_Control *the_thread +) +{ + void *sched; + + sched = _Workspace_Allocate( sizeof(Scheduler_priority_Per_thread) ); + + the_thread->scheduler_info = (Scheduler_priority_Per_thread*) sched; + + return sched; +} +/* + * Scheduler Handler + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityblock.c,v 1.4 2011/02/18 15:12:43 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void _Scheduler_priority_Block( + Thread_Control *the_thread +) +{ + _Scheduler_priority_Ready_queue_extract( the_thread ); + + /* TODO: flash critical section? */ + + if ( _Thread_Is_heir( the_thread ) ) + _Scheduler_priority_Schedule_body(); + + if ( _Thread_Is_executing( the_thread ) ) + _Thread_Dispatch_necessary = true; + +} +/* + * Scheduler Handler + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriority.c,v 1.5 2011/02/28 00:10:38 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +/* Instantiate any global variables needed by the priority scheduler */ +volatile Priority_bit_map_Control _Priority_Major_bit_map; + +Priority_bit_map_Control _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT; + +void _Scheduler_priority_Initialize(void) +{ + _Scheduler_priority_Ready_queue_initialize(); + _Priority_bit_map_Handler_initialization(); +} +/* + * COPYRIGHT (c) 2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityenqueue.c,v 1.1 2011/02/18 15:12:44 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +void _Scheduler_priority_Enqueue( + Thread_Control *the_thread +) +{ + _Scheduler_priority_Ready_queue_enqueue( the_thread ); +} +/* + * COPYRIGHT (c) 2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityenqueuefirst.c,v 1.1 2011/02/18 15:12:44 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +void _Scheduler_priority_Enqueue_first( + Thread_Control *the_thread +) +{ + _Scheduler_priority_Ready_queue_enqueue_first( the_thread ); +} + +/* Scheduler Simple Handler / Extract + * + * COPYRIGHT (c) 2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityextract.c,v 1.2 2011/02/28 00:10:38 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +void _Scheduler_priority_Extract( + Thread_Control *the_thread +) +{ + _Scheduler_priority_Ready_queue_extract( the_thread ); +} +/* + * Scheduler Handler + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityfree.c,v 1.1 2011/02/18 15:12:44 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +void _Scheduler_priority_Free ( + Thread_Control *the_thread +) +{ + _Workspace_Free( the_thread->scheduler_info ); +} +/* + * Scheduler Handler / Scheduler + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityschedule.c,v 1.4 2011/02/18 15:12:44 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +void _Scheduler_priority_Schedule(void) +{ + _Scheduler_priority_Schedule_body(); +} +/* + * Scheduler Handler + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityunblock.c,v 1.4 2011/02/18 15:12:44 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +void _Scheduler_priority_Unblock ( + Thread_Control *the_thread +) +{ + _Scheduler_priority_Ready_queue_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; + } +} +/* + * Scheduler Handler + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityupdate.c,v 1.2 2011/02/28 00:10:38 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +void _Scheduler_priority_Update( + Thread_Control *the_thread +) +{ + Scheduler_priority_Per_thread *sched_info; + Chain_Control *rq; + + sched_info = (Scheduler_priority_Per_thread *) the_thread->scheduler_info; + rq = (Chain_Control *) _Scheduler.information; + + sched_info->ready_chain = &rq[ the_thread->current_priority ]; + + _Priority_bit_map_Initialize_information( + &sched_info->Priority_map, + the_thread->current_priority + ); +} +/* + * Scheduler Priority Handler / Yield + * + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriorityyield.c,v 1.6 2011/02/18 15:12:44 joel Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +/* + * INTERRUPT LATENCY: + * ready chain + * select heir + */ + +void _Scheduler_priority_Yield(void) +{ + Scheduler_priority_Per_thread *sched_info; + ISR_Level level; + Thread_Control *executing; + Chain_Control *ready; + + executing = _Thread_Executing; + sched_info = (Scheduler_priority_Per_thread *) executing->scheduler_info; + ready = sched_info->ready_chain; + _ISR_Disable( level ); + if ( !_Chain_Has_only_one_node( ready ) ) { + _Chain_Extract_unprotected( &executing->Object.Node ); + _Chain_Append_unprotected( ready, &executing->Object.Node ); + + _ISR_Flash( level ); + + if ( _Thread_Is_heir( executing ) ) + _Thread_Heir = (Thread_Control *) _Chain_First( ready ); + _Thread_Dispatch_necessary = true; + } + else if ( !_Thread_Is_heir( executing ) ) + _Thread_Dispatch_necessary = true; + + _ISR_Enable( level ); +} diff --git a/rtems-omk-template/appfoo/scheduler_priority.h b/rtems-omk-template/appfoo/scheduler_priority.h new file mode 100644 index 0000000..3a75dee --- /dev/null +++ b/rtems-omk-template/appfoo/scheduler_priority.h @@ -0,0 +1,194 @@ +/** + * @file rtems/score/schedulerpriority.h + * + * This include file contains all the constants and structures associated + * with the manipulation of threads for the priority-based scheduler. + */ + +/* + * Copryight (c) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id: schedulerpriority.h,v 1.8 2011/03/08 19:27:35 joel Exp $ + */ + +#ifndef _RTEMS_SCORE_SCHEDULERPRIORITY_H +#define _RTEMS_SCORE_SCHEDULERPRIORITY_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup ScoreScheduler + * + */ +/**@{*/ + +/** + * Entry points for the Deterministic Priority Based Scheduler. + */ +#define SCHEDULER_PRIORITY_ENTRY_POINTS \ + { \ + _Scheduler_priority_Initialize, /* initialize entry point */ \ + _Scheduler_priority_Schedule, /* schedule entry point */ \ + _Scheduler_priority_Yield, /* yield entry point */ \ + _Scheduler_priority_Block, /* block entry point */ \ + _Scheduler_priority_Unblock, /* unblock entry point */ \ + _Scheduler_priority_Allocate, /* allocate entry point */ \ + _Scheduler_priority_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 */ \ + } + +/** + * Per-thread data related to the _Scheduler_PRIORITY scheduling policy. + */ +typedef struct { + /** This field points to the Ready FIFO for this thread's priority. */ + Chain_Control *ready_chain; + + /** This field contains precalculated priority map indices. */ + Priority_bit_map_Information Priority_map; +} Scheduler_priority_Per_thread; + +/** + * This routine initializes the priority scheduler. + */ +void _Scheduler_priority_Initialize(void); + +/** + * This routine removes @a the_thread from the scheduling decision, + * that is, removes it from the ready queue. It performs + * any necessary scheduling operations including the selection of + * a new heir thread. + * + * @param[in] the_thread is the thread to be blocked + */ +void _Scheduler_priority_Block( + Thread_Control *the_thread +); + +/** + * This kernel routine sets the heir thread to be the next ready thread + * by invoking the_scheduler->ready_queue->operations->first(). + */ +void _Scheduler_priority_Schedule(void); + +/** + * This routine allocates @a the_thread->scheduler. + * + * @param[in] the_thread is the thread the scheduler is allocating + * management memory for + */ +void * _Scheduler_priority_Allocate( + Thread_Control *the_thread +); + +/** + * This routine frees @a the_thread->scheduler. + * + * @param[in] the_thread is the thread whose scheduler specific information + * will be deallocated. + */ +void _Scheduler_priority_Free( + Thread_Control *the_thread +); + +/** + * This routine updates @a the_thread->scheduler based on @a the_scheduler + * structures and thread state. + * + * @param[in] the_thread will have its scheduler specific information + * structure updated. + */ +void _Scheduler_priority_Update( + Thread_Control *the_thread +); + +/** + * This routine adds @a the_thread to the scheduling decision, + * that is, adds it to the ready queue and + * updates any appropriate scheduling variables, for example the heir thread. + * + * @param[in] the_thread will be unblocked + */ +void _Scheduler_priority_Unblock( + Thread_Control *the_thread +); + +/** + * This routine is invoked when a thread wishes to voluntarily + * transfer control of the processor to another thread in the queue. + * + * This routine will remove the running THREAD from the ready queue + * and place it immediately at the rear of this chain. Reset timeslice + * and yield the processor functions both use this routine, therefore if + * reset is true and this is the only thread on the queue then the + * timeslice counter is reset. The heir THREAD will be updated if the + * running is also the currently the heir. + */ +void _Scheduler_priority_Yield( void ); + +/** + * 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( + Thread_Control *the_thread +); + +/** + * 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( + Thread_Control *the_thread +); + +/** + * 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( + Thread_Control *the_thread +); + +/** + * This is the major bit map. + */ +extern volatile Priority_bit_map_Control _Priority_Major_bit_map; + +/** + * This is the minor bit map. + */ +extern Priority_bit_map_Control _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT; + +#ifndef __RTEMS_APPLICATION__ +#include +#endif + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ diff --git a/rtems-omk-template/appfoo/system.h b/rtems-omk-template/appfoo/system.h index 7279551..7d72501 100644 --- a/rtems-omk-template/appfoo/system.h +++ b/rtems-omk-template/appfoo/system.h @@ -61,6 +61,49 @@ rtems_task Init( RTEMS_NO_ASR | \ RTEMS_INTERRUPT_LEVEL(0)) + + +/* + * Scheduler configuration. + * + * The scheduler configuration allows an application to select the + * scheduling policy to use. The supported configurations are: + * CONFIGURE_SCHEDULER_USER - user provided scheduler + * CONFIGURE_SCHEDULER_PRIORITY - Deterministic Priority Scheduler + * + * If no configuration is specified by the application, then + * CONFIGURE_SCHEDULER_PRIORITY is assumed to be the default. + * + * An application can define its own scheduling policy by defining + * CONFIGURE_SCHEDULER_USER and the following: + * - CONFIGURE_SCHEDULER_ENTRY_POINTS + * - CONFIGURE_MEMORY_FOR_SCHEDULER - base memory + * - CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER - per task memory + */ + +// to enable our own scheduler +#define CONFIGURE_SCHEDULER_USER + +/** + * Entry points for a edf Scheduler. + */ +#define CONFIGURE_SCHEDULER_USER_ENTRY_POINTS +// EDF +#include "scheduler_edf.h" +#define SCHEDULER_ENTRY_POINTS SCHEDULER_EDF_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) + + + + #include + + + /* end of include file */ diff --git a/rtems-omk-template/appfoo/task_2.c b/rtems-omk-template/appfoo/task_2.c new file mode 100644 index 0000000..4101717 --- /dev/null +++ b/rtems-omk-template/appfoo/task_2.c @@ -0,0 +1,30 @@ +#include +#include "system.h" +#include "app_def.h" +#include +#include +#include +#include +#include +#include + + +rtems_task Task_2( + rtems_task_argument argument +) +{ + int i; + int s; + rtems_status_code status; + printf("*** Starting up Task_2 ***\n"); + + while(1){ + printf("Task_2 woken and calculating\n"); + for (i=0; i<10000; i++) { + s = i + i; + } + status = rtems_task_wake_after( TICKS_PER_SECOND*2 ); + check_rtems_status( status, 0, "rtems_task_wake_after" ); + } +} + -- 2.39.2