]> rtime.felk.cvut.cz Git - rtems-pluggable-edf.git/commitdiff
Task 2 added and pluggable EDF scheduler base for RTEMS added.
authorPetr Benes <benesp16@fel.cvut.cz>
Thu, 24 Mar 2011 11:57:05 +0000 (12:57 +0100)
committerPetr Benes <benesp16@fel.cvut.cz>
Thu, 24 Mar 2011 11:57:05 +0000 (12:57 +0100)
The EDF does not fire yet, necessary to readjust the rbtree.
Sorry for this huge commit.

rtems-omk-template/appfoo/Makefile.omk
rtems-omk-template/appfoo/app_def.h
rtems-omk-template/appfoo/init.c
rtems-omk-template/appfoo/rbtree.c [new file with mode: 0644]
rtems-omk-template/appfoo/rbtree.h [new file with mode: 0644]
rtems-omk-template/appfoo/scheduler_edf.c [new file with mode: 0644]
rtems-omk-template/appfoo/scheduler_edf.h [new file with mode: 0644]
rtems-omk-template/appfoo/scheduler_priority.c [new file with mode: 0644]
rtems-omk-template/appfoo/scheduler_priority.h [new file with mode: 0644]
rtems-omk-template/appfoo/system.h
rtems-omk-template/appfoo/task_2.c [new file with mode: 0644]

index 135b758243ad2f487fa2a0616ca6af41e7f2c04b..ed000fec8dd322b6358633f5d900319556c3593a 100644 (file)
@@ -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
 
index 6527316f7d6068b68585b820aa9fedb00d00d5ea..3e07a262ae746c9cc2898a4e808e3c8e1035a49c 100644 (file)
@@ -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
index f7037f247850b13e01b8b1377e4df7ddbbb6a077..ed6ab84b61ec58efeabe1288350da83638a546be 100644 (file)
@@ -30,6 +30,7 @@
 #include <rtems/monitor.h>
 #include <rtems/shell.h>
 
+
 #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 (file)
index 0000000..cd9840c
--- /dev/null
@@ -0,0 +1,365 @@
+#include <rtems/score/rbtree.h>
+#include <rtems/score/thread.h>
+#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 (file)
index 0000000..77e77ab
--- /dev/null
@@ -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 (file)
index 0000000..35cfd4e
--- /dev/null
@@ -0,0 +1,125 @@
+#include "scheduler_edf.h"
+#include "rbtree.h"
+#include <stdio.h>
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+
+/* 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 (file)
index 0000000..dcad0ba
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef _SCHEDULER_EDF_H
+#define _SCHEDULER_EDF_H
+
+#include <rtems/score/scheduler.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+#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 (file)
index 0000000..d2a0c88
--- /dev/null
@@ -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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/wkspace.h>
+
+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 <rtems/system.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+
+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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/prioritybitmap.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+/* 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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/schedulerpriority.h>
+
+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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/schedulerpriority.h>
+
+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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/wkspace.h>
+
+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 <rtems/system.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+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 <rtems/system.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+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 <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/prioritybitmap.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+
+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 <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+
+/*
+ *  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 (file)
index 0000000..3a75dee
--- /dev/null
@@ -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 <rtems/score/chain.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+
+#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 <rtems/score/schedulerpriority.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+
+#endif
+/* end of include file */
index 727955121fbe7e1f8f16c86dec744a09dd35b071..7d725015e4610a0d8c740bd990b08c60b91ced44 100644 (file)
@@ -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 <rtems/confdefs.h>
 
+
+
+
 /* 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 (file)
index 0000000..4101717
--- /dev/null
@@ -0,0 +1,30 @@
+#include <system_def.h>
+#include "system.h"
+#include "app_def.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <rtems/untar.h>
+#include <rtems/error.h>
+#include <rtems/mw_uid.h>
+#include <errno.h>
+
+
+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" );
+  }
+}
+