1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
16 /* ----------------------------[includes]------------------------------------*/
\r
21 #include "application.h"
\r
22 #include "internal.h"
\r
28 /* ----------------------------[private define]------------------------------*/
\r
29 /* ----------------------------[private macro]-------------------------------*/
\r
30 /* ----------------------------[private typedef]-----------------------------*/
\r
31 /* ----------------------------[private function prototypes]-----------------*/
\r
32 /* ----------------------------[private variables]---------------------------*/
\r
34 OsTaskVarType Os_TaskVarList[OS_TASK_CNT];
\r
37 /* ----------------------------[private functions]---------------------------*/
\r
39 static inline void Os_TaskRunningToReady( OsTaskVarType *pcb ) {
\r
40 assert(pcb->state == ST_RUNNING );
\r
41 pcb->state = ST_READY;
\r
45 // ActivateTask(pid)
\r
47 void Os_TaskMakeReady( OsTaskVarType *pcb ) {
\r
48 if( !( pcb->state & ( ST_READY | ST_RUNNING )) ) {
\r
49 pcb->state = ST_READY;
\r
50 TAILQ_INSERT_TAIL(& Os_Sys.ready_head,pcb,ready_list);
\r
51 OS_DEBUG(D_TASK,"Added %s to ready list\n",pcb->constPtr->name);
\r
56 void Os_TaskMakeWaiting( OsTaskVarType *pcb )
\r
58 assert( pcb->state & (ST_READY|ST_RUNNING) );
\r
60 pcb->state = ST_WAITING;
\r
61 TAILQ_REMOVE(&Os_Sys.ready_head,pcb,ready_list);
\r
62 OS_DEBUG(D_TASK,"Removed %s from ready list\n",pcb->constPtr->name);
\r
66 #if defined(USE_KERNEL_EXTRA)
\r
67 static inline void Os_TaskMakeSleeping( OsTaskVarType *pcb )
\r
69 assert( pcb->state & (ST_READY|ST_RUNNING) );
\r
71 pcb->state = ST_WAITING | ST_SLEEPING;
\r
72 TAILQ_REMOVE(&Os_Sys.ready_head,pcb,ready_list);
\r
73 OS_DEBUG(D_TASK,"Removed %s from ready list\n",pcb->constPtr->name);
\r
77 static inline void Os_TaskMakeWaitingOnSem( OsTaskVarType *pcb )
\r
79 assert( pcb->state & (ST_READY|ST_RUNNING) );
\r
81 pcb->state = ST_WAITING_SEM;
\r
82 TAILQ_REMOVE(&Os_Sys.ready_head,pcb,ready_list);
\r
83 OS_DEBUG(D_TASK,"Removed %s from ready list\n",pcb->constPtr->name);
\r
90 static inline void Os_TaskMakeSuspended( OsTaskVarType *pcb )
\r
92 assert( pcb->state & (ST_READY|ST_RUNNING) );
\r
93 pcb->state = ST_SUSPENDED;
\r
94 TAILQ_REMOVE(&Os_Sys.ready_head,pcb,ready_list);
\r
95 OS_DEBUG(D_TASK,"Removed %s from ready list\n",pcb->constPtr->name);
\r
99 /* ----------------------------[public functions]----------------------------*/
\r
105 _Bool os_pcb_pid_valid( OsTaskVarType *restrict pcb ) {
\r
106 return ( pcb->constPtr->pid > OS_TASK_CNT ) ? 0 : 1;
\r
109 * Start an extended task.
\r
111 * - Grab the internal resource for the process
\r
112 * - Set it running state.
\r
113 * - Start to execute the process
\r
116 void Os_TaskStartExtended( void ) {
\r
118 OsTaskVarType *pcb;
\r
120 pcb = Os_SysTaskGetCurr();
\r
122 Os_ResourceGetInternal();
\r
123 Os_TaskMakeRunning(pcb);
\r
128 Os_ArchFirstCall();
\r
130 /* We got back without any TerminateTask() or ChainTask()
\r
133 * Each task shall terminate itself at the end of its code.
\r
134 * Ending the task without a call to TerminateTask or ChainTask
\r
135 * is strictly forbidden and causes undefined behaviour.
\r
138 * OS052, OS069, OS070 and OS239
\r
143 if( Os_SysIntAnyDisabled() ) {
\r
144 Os_SysIntClearAll();
\r
148 if( Os_TaskOccupiesResources(pcb) ) {
\r
149 Os_TaskResourceFreeAll(pcb);
\r
153 ERRORHOOK(E_OS_MISSINGEND);
\r
160 * Start an basic task.
\r
161 * See extended task.
\r
164 void Os_TaskStartBasic( void ) {
\r
166 OsTaskVarType *pcb;
\r
168 pcb = Os_SysTaskGetCurr();
\r
170 Os_ResourceGetInternal();
\r
171 Os_TaskMakeRunning(pcb);
\r
176 Os_ArchFirstCall();
\r
180 if( Os_SysIntAnyDisabled() ) {
\r
181 Os_SysIntClearAll();
\r
185 if( Os_TaskOccupiesResources(pcb) ) {
\r
186 Os_TaskResourceFreeAll(pcb);
\r
190 ERRORHOOK(E_OS_MISSINGEND);
\r
197 static void Os_StackSetup( OsTaskVarType *pcbPtr ) {
\r
200 /* Find bottom of the stack so that we can place the
\r
203 * stack bottom = high address. stack top = low address
\r
205 bottom = (uint8_t *)pcbPtr->stack.top + pcbPtr->stack.size;
\r
206 pcbPtr->stack.curr = bottom;
\r
207 // TODO: alignments here..
\r
208 // TODO :use function os_arch_get_call_size() ??
\r
210 // Make some space for back-chain.
\r
212 // Set the current stack so that it points to the context
\r
213 pcbPtr->stack.curr = bottom - Os_ArchGetScSize();
\r
215 Os_StackSetEndmark(pcbPtr);
\r
219 * Fill the stack with a predefined pattern
\r
221 * @param pcbPtr Pointer to the pcb to fill with pattern
\r
223 static void Os_StackFill(OsTaskVarType *pcbPtr) {
\r
224 uint8_t *p = pcbPtr->stack.curr;
\r
226 assert(pcbPtr->stack.curr > pcbPtr->stack.top);
\r
228 while (p > (uint8_t *) pcbPtr->stack.top) {
\r
230 *p = STACK_PATTERN;
\r
239 static void Os_TaskSetEntry(OsTaskVarType *pcbPtr ) {
\r
246 * Setup the context for a pcb. The context differs for different arch's
\r
247 * so we call the arch dependent functions also.
\r
248 * The context at setup is always a small context.
\r
250 * @param pcb Ptr to the pcb to setup context for.
\r
252 void Os_TaskContextInit( OsTaskVarType *pcb ) {
\r
254 if( pcb->constPtr->autostart ) {
\r
255 Os_TaskMakeReady(pcb);
\r
257 pcb->state = ST_SUSPENDED;
\r
260 Os_StackSetup(pcb);
\r
262 Os_ArchSetTaskEntry(pcb);
\r
264 Os_ArchSetupContext(pcb);
\r
271 void Os_ContextReInit( OsTaskVarType *pcbPtr ) {
\r
272 Os_StackSetup(pcbPtr);
\r
277 * Search for a specific task in the pcb list.
\r
279 * @param tid The task id to search for
\r
280 * @return Ptr to the found pcb or NULL
\r
282 OsTaskVarType *Os_TaskGet( TaskType tid ) {
\r
283 OsTaskVarType *i_pcb;
\r
284 TAILQ_FOREACH(i_pcb,& Os_Sys.pcb_head,pcb_list) {
\r
285 if(i_pcb->constPtr->pid == tid ) {
\r
297 * Adds a pcb to the list of pcb's
\r
300 TaskType Os_AddTask( OsTaskVarType *pcb ) {
\r
303 Irq_Save(msr); // Save irq status and disable interrupts
\r
305 pcb->pid = Os_Sys.task_cnt;
\r
306 // Add to list of PCB's
\r
307 TAILQ_INSERT_TAIL(& Os_Sys.pcb_head,pcb,pcb_list);
\r
311 Irq_Restore(msr); // Restore interrupts
\r
317 #define PRIO_ILLEGAL -100
\r
320 * Find the top priority task. Even the running task is included.
\r
321 * TODO: There should be a priority queue (using a heap?) here instead.
\r
322 * giving O(log n) for instertions and (1) for getting the top
\r
323 * prio task. The curerent implementation is ehhhh bad.
\r
327 OsTaskVarType *Os_TaskGetTop( void ){
\r
328 OsTaskVarType *i_pcb;
\r
329 OsTaskVarType *top_prio_pcb = NULL;
\r
330 OsPriorityType top_prio = PRIO_ILLEGAL;
\r
332 // OS_DEBUG(D_TASK,"os_find_top_prio_proc\n");
\r
334 TAILQ_FOREACH(i_pcb,& Os_Sys.ready_head,ready_list) {
\r
335 // all ready task are canidates
\r
336 if( i_pcb->state & (ST_READY|ST_RUNNING)) {
\r
337 if( top_prio != PRIO_ILLEGAL ) {
\r
338 if( i_pcb->activePriority > top_prio ) {
\r
339 top_prio = i_pcb->activePriority;
\r
340 top_prio_pcb = i_pcb;
\r
343 top_prio = i_pcb->activePriority;
\r
344 top_prio_pcb = i_pcb;
\r
351 assert(top_prio_pcb!=NULL);
\r
353 OS_DEBUG(D_TASK,"Found %s\n",top_prio_pcb->constPtr->name);
\r
355 return top_prio_pcb;
\r
359 #define USE_LDEBUG_PRINTF
\r
362 // we come here from
\r
364 // old_pcb -> WAITING
\r
365 // new_pcb -> READY(RUNNING)
\r
367 // old_pcb -> READY
\r
368 // new_pcb -> READY/RUNNING
\r
372 * 1. When running ->
\r
373 * - remove from ready queue
\r
374 * - set state == ST_RUNNING
\r
376 * 2. When running ->
\r
377 * * leave in ready queue
\r
378 * * set state == ST_RUNNING
\r
379 * - ready queue and ST_READY not the same
\r
380 * + No need to remove the running process from ready queue
\r
383 OsTaskVarType *Os_FindTopPrioTask( void ) {
\r
390 * Tries to Dispatch.
\r
398 * @param force Force a re-scheduling
\r
401 void Os_Dispatch( uint32_t op ) {
\r
402 OsTaskVarType *pcbPtr;
\r
403 OsTaskVarType *currPcbPtr = Os_SysTaskGetCurr();
\r
405 assert(Os_Sys.intNestCnt == 0);
\r
406 assert(Os_SchedulerResourceIsFree());
\r
408 /* When calling post hook we must still be in ST_RUNNING */
\r
409 assert( currPcbPtr->state & ST_RUNNING );
\r
412 /* Go the correct state for running task */
\r
413 if( op & ( OP_SET_EVENT | OP_SCHEDULE | OP_RELEASE_RESOURCE )) {
\r
414 Os_TaskRunningToReady(currPcbPtr);
\r
415 } else if( op & (OP_WAIT_EVENT) ) {
\r
416 Os_TaskMakeWaiting(currPcbPtr);
\r
417 #if defined(USE_KERNEL_EXTRA)
\r
418 } else if( op & OP_WAIT_SEMAPHORE) {
\r
419 Os_TaskMakeWaitingOnSem(currPcbPtr);
\r
420 } else if( op & OP_SIGNAL_SEMAPHORE) {
\r
421 Os_TaskRunningToReady(currPcbPtr);
\r
423 } else if( op & (OP_SLEEP )) {
\r
424 Os_TaskMakeSleeping(currPcbPtr);
\r
426 } else if( op & OP_ACTIVATE_TASK ) {
\r
427 Os_TaskMakeReady(currPcbPtr);
\r
428 } else if( op & OP_CHAIN_TASK ) {
\r
429 assert( Os_Sys.chainedPcbPtr != NULL );
\r
431 /* # from chain top
\r
432 * ----------------------------------------------------------
\r
433 * 1 1 1 1 1->RUNNING
\r
434 * 2 1 1 2 1->READY, 2->RUNNING
\r
435 * 3 1 2 2 1->SUSPENDED/READY*, 2->RUNNING
\r
436 * 4 1 2 3 1->SUSPENDED/READY*, 2->READY , 3-RUNNING
\r
438 * *) Depends on the number of activations.
\r
440 * - Chained task is always READY when coming from ChainTask()
\r
442 if( currPcbPtr != Os_Sys.chainedPcbPtr ) {
\r
444 --currPcbPtr->activations;
\r
445 if( currPcbPtr->activations <= 0 ) {
\r
446 currPcbPtr->activations = 0;
\r
447 Os_TaskMakeSuspended(currPcbPtr);
\r
449 Os_TaskRunningToReady(currPcbPtr);
\r
451 /* Chained task is already in READY */
\r
453 Os_Sys.chainedPcbPtr = NULL;
\r
455 } else if( op & OP_TERMINATE_TASK ) {
\r
456 /*@req OSEK TerminateTask
\r
457 * In case of tasks with multiple activation requests,
\r
458 * terminating the current instance of the task automatically puts the next
\r
459 * instance of the same task into the ready state
\r
461 --currPcbPtr->activations;
\r
463 if( currPcbPtr->activations <= 0 ) {
\r
464 currPcbPtr->activations = 0;
\r
465 Os_TaskMakeSuspended(currPcbPtr);
\r
471 pcbPtr = Os_TaskGetTop();
\r
475 /* Swap if we found any process or are forced (multiple activations)*/
\r
476 if( pcbPtr != currPcbPtr ) {
\r
478 if( (op & OP_CHAIN_TASK) && ( currPcbPtr == Os_Sys.chainedPcbPtr ) ) {
\r
480 Os_TaskRunningToReady(currPcbPtr);
\r
485 assert(pcbPtr!=NULL);
\r
487 Os_ResourceReleaseInternal();
\r
489 #if (OS_STACK_MONITORING == 1)
\r
490 if( !Os_StackIsEndmarkOk(currPcbPtr) ) {
\r
491 #if ( OS_SC1 == STD_ON) || ( OS_SC2 == STD_ON )
\r
493 ShutdownOS(E_OS_STACKFAULT);
\r
496 * If a stack fault is detected by stack monitoring AND the configured scalability
\r
497 * class is 3 or 4, the Operating System module shall call the ProtectionHook() with
\r
498 * the status E_OS_STACKFAULT.
\r
500 PROTECTIONHOOK(E_OS_STACKFAULT);
\r
504 OS_DEBUG(D_TASK,"Swapping to: %s\n",pcbPtr->constPtr->name);
\r
505 Os_TaskSwapContext(currPcbPtr,pcbPtr);
\r
507 OS_DEBUG(D_TASK,"Continuing task %s\n",pcbPtr->constPtr->name);
\r
508 /* Setup the stack again, and just call the basic task */
\r
509 Os_StackSetup(pcbPtr);
\r
510 /* TODO: release and get the internal resource ? */
\r
511 Os_TaskMakeRunning(pcbPtr);
\r
513 Os_ArchSetSpAndCall(pcbPtr->stack.curr,Os_TaskStartBasic);
\r
520 * Thoughts on task switching and memory protection
\r
522 * If we would have had memory protection:
\r
523 * - Applications have their own MMU settings.
\r
524 * - Swapping between tasks in same Application does NOT involve the MMU.
\r
525 * - When running a non-trusted Application I need will have to:
\r
526 * - Run kernel in supervisor mode.
\r
527 * - Trap the start of each task
\r
528 * - All calls to the kernel will have a trap interface, i.e. Os_ResourceGetInternal(ActivateTask(TASK_ID_foo);
\r
530 * - The interupt is taken, the kernel runs in supervisor mode
\r
531 * - If the ISR2 activates
\r
534 * ALT1: 1 kernel stack...
\r
537 * Do we need virtual memory??
\r
540 void Os_TaskSwapContext(OsTaskVarType *old_pcb, OsTaskVarType *new_pcb ) {
\r
541 Os_SysTaskSetCurr(new_pcb);
\r
542 #if (OS_USE_APPLICATIONS == STD_ON)
\r
543 Os_Sys.currApplId = new_pcb->constPtr->applOwnerId;
\r
545 Os_ResourceGetInternal();
\r
546 Os_TaskMakeRunning(new_pcb);
\r
547 /* TODO: The pretask hook is not called with the right stack
\r
548 * (it's called on the old task stack, not the new ) */
\r
550 Os_ArchSwapContext(old_pcb,new_pcb);
\r
553 void Os_TaskSwapContextTo(OsTaskVarType *old_pcb, OsTaskVarType *new_pcb ) {
\r
554 Os_SysTaskSetCurr(new_pcb);
\r
555 #if (OS_USE_APPLICATIONS == STD_ON)
\r
556 Os_Sys.currApplId = new_pcb->constPtr->applOwnerId;
\r
558 Os_ResourceGetInternal();
\r
559 Os_TaskMakeRunning(new_pcb);
\r
561 Os_ArchSwapContextTo(old_pcb,new_pcb);
\r
566 void Os_Arc_GetStackInfo( TaskType task, StackInfoType *s) {
\r
567 OsTaskVarType *pcb = Os_TaskGet(task);
\r
569 s->curr = Os_ArchGetStackPtr();
\r
570 s->top = pcb->stack.top;
\r
571 s->at_swap = pcb->stack.curr;
\r
572 s->size = pcb->stack.size;
\r
573 s->usage = (void *)Os_StackGetUsage(pcb);
\r
577 #define TASK_CHECK_ID(x) \
\r
578 if( (x) > OS_TASK_CNT) { \
\r
585 * Returns the state of a task (running, ready, waiting, suspended)
\r
586 * at the time of calling GetTaskState.
\r
588 * @param TaskId Task reference
\r
589 * @param State Reference to the state of the task
\r
592 StatusType GetTaskState(TaskType TaskId, TaskStateRefType State) {
\r
593 state_t curr_state;
\r
594 StatusType rv = E_OK;
\r
596 TASK_CHECK_ID(TaskId);
\r
598 curr_state = os_pcb_get_state(Os_TaskGet(TaskId));
\r
600 // TODO: Lazy impl. for now */
\r
601 switch(curr_state) {
\r
602 case ST_RUNNING: *State = TASK_STATE_RUNNING; break;
\r
603 case ST_WAITING: *State = TASK_STATE_WAITING; break;
\r
604 case ST_SUSPENDED: *State = TASK_STATE_SUSPENDED; break;
\r
605 case ST_READY: *State = TASK_STATE_READY; break;
\r
608 // Prevent label warning. Remove when proper error handling is implemented.
\r
611 OS_STD_END_2(OSServiceId_GetTaskState,TaskId, State);
\r
616 * GetTaskID returns the information about the TaskID of the task
\r
617 * which is currently running.
\r
619 * @param task_id Reference to the task which is currently running
\r
622 StatusType GetTaskID( TaskRefType TaskID ) {
\r
623 StatusType rv = E_OK;
\r
624 *TaskID = INVALID_TASK;
\r
626 /* Test specification say return CALLEVEL if in ISR
\r
627 * but impl. spec says otherwise */
\r
628 if( Os_Sys.intNestCnt == 0 ) {
\r
629 if( Os_Sys.currTaskPtr->state & ST_RUNNING ) {
\r
630 *TaskID = Os_Sys.currTaskPtr->constPtr->pid;
\r
632 /* This is not a real error since this could
\r
633 * be the case when called from ErrorHook */
\r
642 * This service returns the identifier of the currently executing ISR
\r
644 * If its caller is not a category 2 ISR (or Hook routines called
\r
645 * inside a category 2 ISR), GetISRID() shall return INVALID_ISR.
\r
649 ISRType GetISRID( void ) {
\r
652 if(Os_Sys.intNestCnt == 0 ) {
\r
653 return INVALID_ISR;
\r
657 return (ISRType)Os_SysTaskGetCurr()->constPtr->pid;
\r
660 static inline void Os_Arc_SetCleanContext( OsTaskVarType *pcb ) {
\r
661 if (pcb->constPtr->proc_type == PROC_EXTENDED) {
\r
662 /** @req OSEK ActivateTask Cleanup events
\r
663 * OSEK,ActivateTask, When an extended task is transferred from suspended
\r
664 * state into ready state all its events are cleared.*/
\r
668 Os_StackSetup(pcb);
\r
669 Os_ArchSetTaskEntry(pcb);
\r
670 Os_ArchSetupContext(pcb);
\r
674 * The task <TaskID> is transferred from the suspended state into
\r
675 * the ready state. The operating system ensures that the task
\r
676 * code is being executed from the first statement.
\r
678 * The service may be called from interrupt level and from task
\r
679 * level (see Figure 12-1).
\r
680 * Rescheduling after the call to ActivateTask depends on the
\r
681 * place it is called from (ISR, non preemptable task, preemptable
\r
684 * If E_OS_LIMIT is returned the activation is ignored.
\r
685 * When an extended task is transferred from suspended state
\r
686 * into ready state all its events are cleared.
\r
689 * ActivateTask will not immediately change the state of the task
\r
690 * in case of multiple activation requests. If the task is not
\r
691 * suspended, the activation will only be recorded and performed later.
\r
698 StatusType ActivateTask( TaskType TaskID ) {
\r
700 OsTaskVarType *pcb = Os_TaskGet(TaskID);
\r
701 StatusType rv = E_OK;
\r
703 OS_DEBUG(D_TASK,"# ActivateTask %s\n",pcb->constPtr->name);
\r
705 #if (OS_STATUS_EXTENDED == STD_ON )
\r
707 TASK_CHECK_ID(TaskID);
\r
712 #if (OS_APPLICATION_CNT > 1)
\r
714 rv = Os_ApplHaveAccess( pcb->constPtr->accessingApplMask );
\r
721 /* @req OS093 ActivateTask */
\r
722 if( Os_SysIntAnyDisabled() ) {
\r
724 rv = E_OS_DISABLEDINT;
\r
728 pcb->activations++;
\r
729 if( os_pcb_get_state(pcb) != ST_SUSPENDED ) {
\r
730 /** @req OSEK_? Too many task activations */
\r
731 if( pcb->activations >= (pcb->constPtr->activationLimit + 1) ) {
\r
735 --pcb->activations;
\r
739 /* We have a suspended task, make it ready for use */
\r
740 assert( pcb->activations == 1 );
\r
741 Os_Arc_SetCleanContext(pcb);
\r
742 Os_TaskMakeReady(pcb);
\r
745 /* Preempt only if we are preemptable and target has higher prio than us */
\r
746 if( (Os_SysTaskGetCurr()->constPtr->scheduling == FULL) &&
\r
747 (Os_Sys.intNestCnt == 0) &&
\r
748 (pcb->activePriority > Os_SysTaskGetCurr()->activePriority) &&
\r
749 (Os_SchedulerResourceIsFree()))
\r
751 Os_Dispatch(OP_ACTIVATE_TASK);
\r
756 OS_STD_END_1(OSServiceId_ActivateTask,TaskID);
\r
760 * This service causes the termination of the calling task. The
\r
761 * calling task is transferred from the running state into the
\r
764 * An internal resource assigned to the calling task is automatically
\r
765 * released. Other resources occupied by the task shall have been
\r
766 * released before the call to TerminateTask. If a resource is still
\r
767 * occupied in standard status the behaviour is undefined.
\r
769 * If the call was successful, TerminateTask does not return to the
\r
770 * call level and the status can not be evaluated.
\r
772 * If the version with extended status is used, the service returns
\r
773 * in case of error, and provides a status which can be evaluated
\r
774 * in the application.
\r
776 * If the service TerminateTask is called successfully, it enforces a
\r
779 * [ Ending a task function without call to TerminateTask
\r
780 * or ChainTask is strictly forbidden and may leave the system in an
\r
781 * undefined state. ]
\r
783 * [] is an OSEK requirement and is overridden by OS052
\r
788 StatusType TerminateTask( void ) {
\r
789 OsTaskVarType *curr_pcb = Os_SysTaskGetCurr();
\r
790 StatusType rv = E_OK;
\r
793 OS_DEBUG(D_TASK,"# TerminateTask %s\n",curr_pcb->constPtr->name);
\r
795 #if (OS_STATUS_EXTENDED == STD_ON )
\r
798 if( Os_Sys.intNestCnt != 0 ) {
\r
799 rv = E_OS_CALLEVEL;
\r
804 if ( Os_SchedulerResourceIsOccupied() ) {
\r
805 rv = E_OS_RESOURCE;
\r
810 if( Os_TaskOccupiesResources(curr_pcb) ) {
\r
811 /* Note! Do NOT release the resource here */
\r
812 rv = E_OS_RESOURCE;
\r
819 /* Force the dispatcher to find something, even if its us */
\r
820 Os_Dispatch(OP_TERMINATE_TASK);
\r
824 OS_STD_END(OSServiceId_TerminateTask);
\r
827 StatusType ChainTask( TaskType TaskId ) {
\r
828 OsTaskVarType *curr_pcb = Os_SysTaskGetCurr();
\r
829 StatusType rv = E_OK;
\r
831 OsTaskVarType *pcb = Os_TaskGet(TaskId);
\r
834 OS_DEBUG(D_TASK,"# ChainTask %s\n",curr_pcb->constPtr->name);
\r
836 #if (OS_STATUS_EXTENDED == STD_ON )
\r
838 TASK_CHECK_ID(TaskId);
\r
840 if( Os_Sys.intNestCnt != 0 ) {
\r
842 rv = E_OS_CALLEVEL;
\r
850 #if (OS_STATUS_EXTENDED == STD_ON )
\r
852 if ( Os_SchedulerResourceIsOccupied() ) {
\r
854 rv = E_OS_RESOURCE;
\r
855 Irq_Restore(flags);
\r
860 if( Os_TaskOccupiesResources(curr_pcb) ) {
\r
862 rv = E_OS_RESOURCE;
\r
863 Irq_Restore(flags);
\r
868 // if( os_pcb_get_state(pcb) != ST_SUSPENDED ) {
\r
869 if (curr_pcb != pcb) {
\r
870 /** @req OSEK_? Too many task activations */
\r
871 if( (pcb->activations + 1) > pcb->constPtr->activationLimit ) {
\r
874 Irq_Restore(flags);
\r
878 if( os_pcb_get_state(pcb) == ST_SUSPENDED ) {
\r
879 assert( pcb->activations == 0 );
\r
880 Os_Arc_SetCleanContext(pcb);
\r
881 Os_TaskMakeReady(pcb);
\r
884 pcb->activations++;
\r
888 Os_Sys.chainedPcbPtr = pcb;
\r
890 Os_Dispatch(OP_CHAIN_TASK);
\r
894 OS_STD_END_1(OSServiceId_ChainTask,TaskId);
\r
898 * If a higher-priority task is ready, the internal resource of the task
\r
899 * is released, the current task is put into the ready state, its
\r
900 * context is saved and the higher-priority task is executed.
\r
901 * Otherwise the calling task is continued.
\r
903 * TODO: The OSEK spec says a lot of strange things under "particulareties"
\r
904 * that I don't understand
\r
906 * See OSEK/VDX 13.2.3.4
\r
909 StatusType Schedule( void ) {
\r
910 StatusType rv = E_OK;
\r
912 OsTaskVarType *curr_pcb = Os_SysTaskGetCurr();
\r
914 OS_DEBUG(D_TASK,"# Schedule %s\n",curr_pcb->constPtr->name);
\r
916 /* Check that we are not calling from interrupt context */
\r
917 if( Os_Sys.intNestCnt != 0 ) {
\r
918 rv = E_OS_CALLEVEL;
\r
922 if ( Os_TaskOccupiesResources(curr_pcb) ) {
\r
923 rv = E_OS_RESOURCE;
\r
927 assert( Os_SysTaskGetCurr()->state & ST_RUNNING );
\r
929 /* We need to figure out if we have an internal resource,
\r
930 * otherwise no re-scheduling.
\r
931 * NON - Have internal resource prio OS_RES_SCHEDULER_PRIO (32+)
\r
932 * FULL - Assigned internal resource OR
\r
933 * No assigned internal resource.
\r
935 if( Os_SysTaskGetCurr()->constPtr->scheduling != NON ) {
\r
940 OsTaskVarType* top_pcb = Os_TaskGetTop();
\r
941 /* only dispatch if some other ready task has higher prio */
\r
942 if (top_pcb->activePriority > Os_SysTaskGetCurr()->activePriority) {
\r
943 Os_Dispatch(OP_SCHEDULE);
\r
946 Irq_Restore(flags);
\r
947 // Prevent label warning. Remove this when proper error handling is implemented.
\r
950 OS_STD_END(OSServiceId_Schedule);
\r