]> rtime.felk.cvut.cz Git - arc.git/commitdiff
Initial checking of real sleep/semephore support
authormahi <devnull@localhost>
Sun, 24 Oct 2010 09:55:55 +0000 (11:55 +0200)
committermahi <devnull@localhost>
Sun, 24 Oct 2010 09:55:55 +0000 (11:55 +0200)
include/Os.h
system/kernel/counter.c
system/kernel/event.c
system/kernel/include/pcb.h
system/kernel/include/sys.h
system/kernel/init.c
system/kernel/makefile
system/kernel/semaphore.c [new file with mode: 0644]
system/kernel/sleep.c [new file with mode: 0644]
system/kernel/task.c

index 729498d80f2a186637a6b52721b5cbb638f7c424..3435e10cdf8bedbc95a337e5ad46aa5fde8eb37f 100644 (file)
@@ -141,8 +141,6 @@ StatusType GetEvent( TaskType TaskId, EventMaskRefType Mask);
 void InitOS( void );\r
 void StartOS( AppModeType Mode );\r
 \r
-\r
-\r
 ApplicationType GetApplicationID( void );\r
 ISRType GetISRID( void );\r
 StatusType GetActiveApplicationMode( AppModeType* mode);\r
@@ -288,6 +286,11 @@ void Os_SysTickStart(TickType period_ticks);
 TickType Os_SysTickGetValue( void );\r
 TickType Os_SysTickGetElapsedValue( TickType preValue );\r
 \r
+#if defined(USE_KERNEL_EXTRA)\r
+StatusType Sleep( TickType ticks );\r
+#endif\r
+\r
+\r
 /*-------------------------------------------------------------------\r
  * Schedule Tables\r
  *-----------------------------------------------------------------*/\r
index b17936cdaf983e4b79c958523b4c4a3968b95334..259152e086ba0ee00305fe4f5ae513465b135bda 100644 (file)
@@ -187,12 +187,26 @@ void OsTick( void ) {
        if (Os_Arc_OsTickCounter >= 0) {\r
 \r
                OsCounterType *cPtr = Os_CfgGetCounter(Os_Arc_OsTickCounter);\r
+#if defined(USE_KERNEL_EXTRA)\r
+               OsPcbType *pcbPtr;\r
+#endif\r
 \r
                os_sys.tick++;\r
 \r
                cPtr->val = Os_CounterAdd( cPtr->val, Os_CounterGetMaxValue(cPtr), 1 );\r
 \r
-       //      os_sys.tick = cPtr->val;\r
+#if defined(USE_KERNEL_EXTRA)\r
+               /* Check sleep() (ST_WAITING) tasks */\r
+               TAILQ_FOREACH(pcbPtr, &os_sys.timerHead, timerEntry ) {\r
+                       --pcbPtr->timerDec;\r
+                       if( pcbPtr->timerDec <= 0 ) {\r
+                               /* Remove from the timer queue */\r
+                               TAILQ_REMOVE(&os_sys.timerHead, pcbPtr, timerEntry);\r
+                               /* ... and add to the ready queue */\r
+                               Os_TaskMakeReady(pcbPtr);\r
+                       }\r
+               }\r
+#endif\r
 \r
                Os_AlarmCheck(cPtr);\r
                Os_SchTblCheck(cPtr);\r
index e022f2c588c27afba6dd5a026e5b8e56db17aa29..b4d8b908e905727b5751ac61d372e23d85adfd0c 100644 (file)
@@ -56,7 +56,8 @@ StatusType WaitEvent( EventMaskType Mask ) {
                goto err;\r
        }\r
 \r
-       if ( Os_TaskOccupiesResources(curr_pcb) ) {\r
+       if ( Os_TaskOccupiesResources(curr_pcb) ||\r
+                !Os_SchedulerResourceIsFree() ) {\r
                rv = E_OS_RESOURCE;\r
                goto err;\r
        }\r
@@ -70,13 +71,8 @@ StatusType WaitEvent( EventMaskType Mask ) {
 \r
                curr_pcb->ev_wait = Mask;\r
 \r
-               if ( Os_SchedulerResourceIsFree() ) {\r
-                       // Os_TaskMakeWaiting(curr_pcb);\r
-                       Os_Dispatch(OP_WAIT_EVENT);\r
-                       assert( curr_pcb->state & ST_RUNNING );\r
-               } else {\r
-                       Os_TaskMakeWaiting(curr_pcb);\r
-               }\r
+               Os_Dispatch(OP_WAIT_EVENT);\r
+               assert( curr_pcb->state & ST_RUNNING );\r
        }\r
 \r
        Irq_Enable();\r
@@ -141,25 +137,25 @@ StatusType SetEvent( TaskType TaskID, EventMaskType Mask ) {
 \r
        dest_pcb->ev_set |= Mask;\r
 \r
-       if( (Mask & dest_pcb->ev_wait) ) {\r
-               /* We have an event match */\r
-               if( dest_pcb->state & ST_WAITING) {\r
-                       Os_TaskMakeReady(dest_pcb);\r
-\r
-                       currPcbPtr = Os_TaskGetCurrent();\r
-                       /* Checking "4.6.2  Non preemptive scheduling" it does not dispatch if NON  */\r
-                       if( (os_sys.int_nest_cnt == 0) &&\r
-                               (currPcbPtr->scheduling == FULL) &&\r
-                               (dest_pcb->prio > currPcbPtr->prio) &&\r
-                               (Os_SchedulerResourceIsFree()) )\r
-                       {\r
-                               Os_Dispatch(OP_SET_EVENT);\r
-                       }\r
-\r
-               }  else if(dest_pcb->state & (ST_READY|ST_RUNNING) ) {\r
-                       /* Hmm, we do nothing */\r
-               } else {\r
-                       assert( 0 );\r
+       if( (Mask & dest_pcb->ev_wait)\r
+#if defined(USE_KERNEL_EXTRA)\r
+                       /* Don't dispatch if target task is sleeping */\r
+                       && !(dest_pcb->state & ST_SLEEPING)\r
+#endif\r
+\r
+       ) {\r
+               assert(dest_pcb->state & ST_WAITING );\r
+\r
+               Os_TaskMakeReady(dest_pcb);\r
+\r
+               currPcbPtr = Os_TaskGetCurrent();\r
+               /* Checking "4.6.2  Non preemptive scheduling" it does not dispatch if NON  */\r
+               if( (os_sys.int_nest_cnt == 0) &&\r
+                       (currPcbPtr->scheduling == FULL) &&\r
+                       (dest_pcb->prio > currPcbPtr->prio) &&\r
+                       (Os_SchedulerResourceIsFree()) )\r
+               {\r
+                       Os_Dispatch(OP_SET_EVENT);\r
                }\r
        }\r
 \r
index 9be3c253164c636518c9baa5fb5f88e6ee959bb6..1b766846448167a3cf319408b20073cf0ad3d55e 100644 (file)
@@ -26,6 +26,7 @@ struct OsRomPcb;
 #define ST_SUSPENDED           (1<<2)\r
 #define ST_RUNNING                     (1<<3)\r
 #define ST_NOT_STARTED         (1<<4)\r
+#define ST_SLEEPING            (1<<5)\r
 \r
 typedef uint16_t state_t;\r
 \r
@@ -172,6 +173,10 @@ typedef struct OsPcb {
 \r
        /* TODO: Arch specific regs .. make space for them later...*/\r
        uint32_t        regs[16];                               // TASK\r
+#if defined(USE_KERNEL_EXTRA)\r
+       TAILQ_ENTRY(OsPcb) timerEntry;          // TASK\r
+       int32_t            timerDec;\r
+#endif\r
        /* List of PCB's */\r
        TAILQ_ENTRY(OsPcb) pcb_list;            // TASK\r
        /* ready list */\r
index 4ac360c40d795687d86dc180123dca5f8486d525..9b72c5ccdbe0e0affbe144b6e8974df49fba0d5c 100644 (file)
@@ -26,6 +26,7 @@ typedef enum  {
        OP_SCHEDULE = 16,\r
        OP_CHAIN_TASK = 32,\r
        OP_RELEASE_RESOURCE = 64,\r
+       OP_SLEEP = 128,\r
 } OpType ;\r
 \r
 typedef struct sys_s {\r
@@ -61,6 +62,12 @@ typedef struct sys_s {
 //     uint32_t flags;\r
 \r
        uint32_t task_cnt;\r
+\r
+#if defined(USE_KERNEL_EXTRA)\r
+       /* List of PCB's to be put in ready list when timeout */\r
+       TAILQ_HEAD(,OsPcb) timerHead;           // TASK\r
+#endif\r
+\r
        /* List of all pcb's,\r
         * Only needed for non-static configuration of the kernel\r
         */\r
index 6cc513f0fff2231e8af7c7f6204573a7ad825769..2cbb6fb557c006b1c3fbd66a9d6e9c053c456336 100644 (file)
@@ -100,6 +100,9 @@ void InitOS( void ) {
        os_sys.pcb_list = pcb_list;
        TAILQ_INIT(& os_sys.ready_head);
        TAILQ_INIT(& os_sys.pcb_head);
+#if defined(USE_KERNEL_EXTRA)
+       TAILQ_INIT(& os_sys.timerHead);
+#endif
 
        // Calc interrupt stack
        Os_CfgGetInterruptStackInfo(&int_stack);
index 9ab1ff07cca41844e8197c5f8491e460f5c012fb..5f6af2df82c9fbafa661f08b03b9f4aa21dc9117 100644 (file)
@@ -2,7 +2,7 @@
 \r
 #VPATH += $(ROOTDIR)/arch/arm/arm_cm3/kernel\r
 vpath-y += $(ARCH_PATH-y)/kernel\r
-obj-y += asm_sample.o\r
+#obj-y += asm_sample.o\r
 #CFLAGS_asm_sample.o += -O3\r
 obj-y += arch_krn.o\r
 obj-$(CFG_HCS12D) += arch_irq.o\r
@@ -27,6 +27,9 @@ obj-y += sys_tick.o
 obj-y += isr.o\r
 obj-y += os_arctest.o\r
 obj-y += application.o\r
+obj-y += arc.o\r
+obj-$(USE_KERNEL_EXTRA) += sleep.o\r
+#obj-$(USE_KERNEL_EXTRA) += semaphore.o\r
 \r
 \r
 # These are VERY cpu dependent.. remove\r
diff --git a/system/kernel/semaphore.c b/system/kernel/semaphore.c
new file mode 100644 (file)
index 0000000..dd1933b
--- /dev/null
@@ -0,0 +1,109 @@
+/*\r
+ * semaphore.c\r
+ *\r
+ *  Created on: 13 okt 2010\r
+ *      Author: mahi\r
+ *\r
+ * Mutex usage:\r
+ * - Serialized access to a global resource. The same task\r
+ *   ALWAYS first use Os_WaitMutex() and the Os_ReleaseMutex()\r
+ *   Should mutex be as GetResource()/ReleaseResource() be able to\r
+ *   tinker with priotities..\r
+ *\r
+ *\r
+ *   Task1:\r
+ *     Os_WaitMutex(my_mutex)\r
+ *     ..\r
+ *     Os_ReleaseMutex(my_mutex)\r
+\r
+ *   Task2\r
+ *     Os_WaitMutex(my_mutex)\r
+ *     ..\r
+ *     Os_ReleaseMutex(my_mutex)\r
+ *\r
+ * Semaphore usage:\r
+ * - Producer and consumer problems.\r
+ *   Os_WaitSemaphore() and Os_SignalSemaphore().\r
+ *\r
+ *   ISR:\r
+ *     Os_SignalSemaphore(my_semaphore)\r
+\r
+ *   Task:\r
+ *     Os_WaitSemaphore(my_semaphore)\r
+ *\r
+ */\r
+\r
+StatusType WaitSemaphore( OsSemaphore *semPtr ) {\r
+       uint32_t flags;\r
+\r
+       Irq_Save(flags);\r
+\r
+       --semPtr->val;\r
+\r
+       if(semPtr->val < 0 ) {\r
+               /* Wait for the semaphore to be signaled */\r
+               Os_Dispatch(OP_WAIT_SEMAPHORE);\r
+       }\r
+\r
+       Irq_Restore(flags);\r
+\r
+       return E_OK;\r
+}\r
+\r
+/**\r
+ * Increate the semaphore value by 1.\r
+ *
+ * @param semPtr
+ */\r
+void SignalSemaphore( OsSemaphore *semPtr ) {\r
+       uint32_t flags;\r
+\r
+       Irq_Save(flags);\r
+\r
+       assert( semPtr != NULL );\r
+\r
+       ++semPtr->val;\r
+\r
+       if(semPtr->val <= 0 ) {\r
+               Os_Dispatch(OP_SIGNAL_SEMAPHORE);\r
+       }\r
+\r
+       Irq_Restore(flags);\r
+\r
+       return E_OK;\r
+}\r
+\r
+\r
+/*\r
+ * Usage:
+ */\r
+StatusType CreateSemaphore( OsSemaphore *, int initialCount  ) {\r
+\r
+\r
+}\r
+\r
+\r
+/* With priority inheretance */\r
+StatusType CreateMutex( OsMutex *mutexPtr ) {\r
+\r
+\r
+}\r
+\r
+StatusType WaitMutex( OsMutex *mutexPtr ) {\r
+\r
+\r
+}\r
+\r
+StatusType Os_ReleaseMutex( OsMutex *mutexPtr ) {\r
+\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/system/kernel/sleep.c b/system/kernel/sleep.c
new file mode 100644 (file)
index 0000000..1b6396e
--- /dev/null
@@ -0,0 +1,48 @@
+\r
+#include "Os.h"\r
+#include "internal.h"\r
+#include <assert.h>\r
+#include <string.h>\r
+\r
+/**\r
+ * Will sleep for sleep ticks. This works only for extended\r
+ * tasks. If sleep is 0 it will just call the dispatcher to\r
+ * see if there is anything with higher priority to run.\r
+ *\r
+ *\r
+ *
+ * @param sleep
+ * @return E_OS_ACCESS if called from a basic task\r
+ *         E_OS_RESOURCE called while holding a resource\r
+ *
+ */\r
+\r
+StatusType Sleep( TickType sleep ) {\r
+       OsPcbType *pcbPtr = Os_TaskGetCurrent();\r
+       uint32_t flags;\r
+\r
+       Irq_Save(flags);\r
+\r
+\r
+       if (pcbPtr->proc_type != PROC_EXTENDED) {\r
+               return E_OS_ACCESS;\r
+       }\r
+\r
+       if ( Os_TaskOccupiesResources(pcbPtr) ) {\r
+               return E_OS_RESOURCE;\r
+       }\r
+\r
+       if ( Os_SchedulerResourceIsFree() ) {\r
+               if( sleep != 0 ) {\r
+                       TAILQ_INSERT_TAIL(&os_sys.timerHead,pcbPtr,timerEntry);\r
+                       pcbPtr->timerDec = sleep;\r
+                       Os_Dispatch(OP_SLEEP);\r
+               } else {\r
+                       Os_Dispatch(OP_SCHEDULE);\r
+               }\r
+\r
+       }\r
+\r
+       Irq_Restore(flags);\r
+       return E_OK;\r
+}\r
index 13b5235272a86e9b8d82422842aa345f7c2bdeda..6332bd4376d6a2f4fbd0c00b60d6a645527eadf0 100644 (file)
@@ -328,8 +328,10 @@ void Os_Dispatch( uint32_t op ) {
        /* Go the correct state for running task */\r
        if( op  & ( OP_SET_EVENT | OP_SCHEDULE | OP_RELEASE_RESOURCE )) {\r
                Os_TaskRunningToReady(currPcbPtr);\r
-       } else if( op & OP_WAIT_EVENT ) {\r
+       } else if( op & (OP_WAIT_EVENT )) {\r
                Os_TaskMakeWaiting(currPcbPtr);\r
+       } else if( op & (OP_SLEEP )) {\r
+               Os_TaskMakeSleeping(currPcbPtr);\r
        } else if( op & OP_ACTIVATE_TASK ) {\r
                Os_TaskMakeReady(currPcbPtr);\r
        } else if( op & OP_CHAIN_TASK ) {\r