* ActivateTask()\r
* WaitEvent()\r
* TerminateTask()\r
+ * ChainTask()\r
*\r
* @param force Force a re-scheduling\r
*\r
// We come here from\r
// - os_init\r
\r
-volatile static int a1, b1, c1;\r
-volatile static OsPcbType *o1;\r
-volatile static OsPcbType *n1;\r
-\r
-void hej(int a, int b, int c, OsPcbType *o, OsPcbType *n) {\r
- a1 = a;\r
- b1 = b;\r
- c1 = c;\r
- o1 = o;\r
- n1 = n;\r
-}\r
-\r
/**\r
* Called when a task is to be run for the first time.\r
*/\r
void Os_TaskSwapContextTo(OsPcbType *old_pcb, OsPcbType *new_pcb ) {\r
\r
- hej(1, 2, 3, old_pcb, new_pcb);\r
-\r
Os_ArchSwapContextTo(old_pcb,new_pcb);\r
/* TODO: When do we return here ?? */\r
}\r
goto err; \\r
}\r
\r
+static inline void Os_Arc_SetCleanContext( OsPcbType *pcb ) {\r
+ if (pcb->proc_type == PROC_EXTENDED) {\r
+ /** @req OSEK ActivateTask Cleanup events\r
+ * OSEK,ActivateTask, When an extended task is transferred from suspended\r
+ * state into ready state all its events are cleared.*/\r
+ pcb->ev_set = 0;\r
+ pcb->ev_wait = 0;\r
+ }\r
+ Os_StackSetup(pcb);\r
+ Os_ArchSetTaskEntry(pcb);\r
+ Os_ArchSetupContext(pcb);\r
+}\r
\r
/**\r
* The task <TaskID> is transferred from the suspended state into\r
\r
if( os_pcb_get_state(pcb) == ST_SUSPENDED ) {\r
pcb->activations++;\r
- if (pcb->proc_type == PROC_EXTENDED) {\r
- /** @req OSEK ActivateTask Cleanup events\r
- * OSEK,ActivateTask, When an extended task is transferred from suspended\r
- * state into ready state all its events are cleared.*/\r
- pcb->ev_set = 0;\r
- pcb->ev_wait = 0;\r
- }\r
- Os_StackSetup(pcb);\r
- Os_ArchSetTaskEntry(pcb);\r
- Os_ArchSetupContext(pcb);\r
+ Os_Arc_SetCleanContext(pcb);\r
Os_TaskMakeReady(pcb);\r
} else {\r
\r
} else {\r
/* We need to add ourselves to the ready list again,\r
* with a startup context. */\r
+\r
+ /* We are already in ready list..\r
+ * This should give us a clean start /tojo */\r
+ Os_Arc_SetCleanContext(curr_pcb);\r
}\r
\r
// Os_ContextReInit(curr_pcb);\r
}\r
\r
StatusType ChainTask( TaskType TaskId ) {\r
- StatusType rv;\r
+ OsPcbType *curr_pcb = Os_TaskGetCurrent();\r
+ StatusType rv = E_OK;\r
uint32_t flags;\r
\r
#if (OS_STATUS_EXTENDED == STD_ON )\r
rv = E_OS_CALLEVEL;\r
goto err;\r
}\r
+\r
+ if( Os_ResourceCheckAndRelease(curr_pcb) == 1 ) {\r
+ rv = E_OS_RESOURCE;\r
+ goto err;\r
+ }\r
#endif\r
+ OsPcbType *pcb = os_get_pcb(TaskId);\r
\r
Irq_Save(flags);\r
- rv = ActivateTask(TaskId);\r
- /* TODO: more more here..*/\r
- TerminateTask();\r
+\r
+ if (curr_pcb == pcb) {\r
+ /* If we are chaining same task just make a clean start */\r
+ /* TODO: Is it allowed to chain same task if extended? */\r
+ Os_Arc_SetCleanContext(curr_pcb);\r
+\r
+ /* Force the dispatcher to find something, even if its us */\r
+ Os_Dispatch(1);\r
+\r
+ Irq_Restore(flags);\r
+ /* It must find something here...otherwise something is very wrong.. */\r
+ assert(0);\r
+\r
+ } else {\r
+ /* We are chaining another task\r
+ * We need to make sure it is in valid state */\r
+ if( os_pcb_get_state(pcb) != ST_SUSPENDED ) {\r
+ if( pcb->proc_type == PROC_EXTENDED ) {\r
+ /** @req OSEK Activate task.\r
+ * An extended task be activated once. See Chapter 4.3 in OSEK */\r
+ rv = E_OS_LIMIT;\r
+ goto err;\r
+ }\r
+\r
+ /** @req OSEK_? Too many task activations */\r
+ if( pcb->activations == pcb->activationLimit ) {\r
+ rv=E_OS_LIMIT;\r
+ goto err;\r
+ }\r
+ }\r
+\r
+ // Terminate current task\r
+ --curr_pcb->activations;\r
+ if( curr_pcb->activations <= 0 ) {\r
+ curr_pcb->activations = 0;\r
+ Os_TaskMakeSuspended(curr_pcb);\r
+ }\r
+\r
+ rv = ActivateTask(TaskId);\r
+ // we return here only if something is wrong\r
+ }\r
+\r
Irq_Restore(flags);\r
\r
if (rv != E_OK) goto err;\r