void Os_ResourceReleaseInternal( void ) { OsTaskVarType *pcbPtr = Os_SysTaskGetCurr(); OsResourceType *rt = pcbPtr->constPtr->resourceIntPtr; if( rt != NULL ) { OS_DEBUG(D_RESOURCE,"Rel IR proc:%s prio:%u old_task_prio:%u\n", Os_SysTaskGetCurr()->constPtr->name, (unsigned)rt->ceiling_priority, (unsigned)rt->old_task_prio); Os_TaskResourceRemove(rt,pcbPtr); } }
StatusType ReleaseResource( ResourceType ResID) { StatusType rv = E_OK; OsTaskVarType *pcbPtr = Os_SysTaskGetCurr(); OsResourceType *rPtr; uint32_t flags; Irq_Save(flags); if( ResID == RES_SCHEDULER ) { rPtr = &Os_Sys.resScheduler; } else { /* Check we can access it */ if( (pcbPtr->constPtr->resourceAccess & (1<< ResID)) == 0 ) { rv = E_OS_ID; goto err; } rPtr = Os_ResourceGet(ResID); } /* Check for invalid configuration */ if( rPtr->owner == NO_TASK_OWNER) { rv = E_OS_NOFUNC; Irq_Restore(flags); goto err; } if( (pcbPtr->activePriority < rPtr->ceiling_priority)) { rv = E_OS_ACCESS; Irq_Restore(flags); goto err; } Os_TaskResourceRemove(rPtr,pcbPtr); /* do a rescheduling (in some cases) (see OSEK OS 4.6.1) */ if ( (pcbPtr->constPtr->scheduling == FULL) && (Os_Sys.intNestCnt == 0) && (Os_SchedulerResourceIsFree()) ) { OsTaskVarType* top_pcb = Os_TaskGetTop(); /* only dispatch if some other ready task has higher prio */ if (top_pcb->activePriority > Os_SysTaskGetCurr()->activePriority) { Os_Dispatch(OP_RELEASE_RESOURCE); } } Irq_Restore(flags); OS_STD_END_1(OSServiceId_ReleaseResource,ResID); }
/** * Increase the semaphore value by 1. If * * @param semPtr */ void SignalSemaphore( OsSemaphoreType *semPtr ) { uint32_t flags; OsTaskVarType *taskPtr; Irq_Save(flags); assert( semPtr != NULL ); ++semPtr->val; /* Remove the first task that waits at the semaphore */ if( semPtr->val <= 0 ) { taskPtr = STAILQ_FIRST(&semPtr->taskHead); /* Make the first task ready */ Os_TaskMakeReady(taskPtr); /* Release the first task in queue */ STAILQ_REMOVE_HEAD(&semPtr->taskHead,semEntry); if( taskPtr->activePriority > Os_SysTaskGetCurr()->activePriority ) { Os_Dispatch(OP_SIGNAL_SEMAPHORE); } } Irq_Restore(flags); }
StatusType WaitSemaphore( OsSemaphoreType *semPtr, TickType tmo ) { OsTaskVarType *pcbPtr; uint32_t flags; StatusType rv = E_OK; (void)tmo; Irq_Save(flags); --semPtr->val; pcbPtr = Os_SysTaskGetCurr(); assert(OS_SYS_PTR->intNestCnt == 0 ); if (pcbPtr->constPtr->proc_type != PROC_EXTENDED) { return E_OS_ACCESS; } if(semPtr->val < 0 ) { /* To WAITING state */ if( tmo == 0 ) { /* Failed to acquire the semaphore */ rv = E_NOT_OK; } else { /* Add this task to the semaphore */ STAILQ_INSERT_TAIL(&semPtr->taskHead,pcbPtr,semEntry); Os_Dispatch(OP_WAIT_SEMAPHORE); } } else { /* We got the semaphore */ if( tmo == 0 ) { rv = E_NOT_OK; } else { /* * Wait for the semaphore to be signaled or timeout */ if ( Os_SchedulerResourceIsFree() ) { /* Set the timeout */ if( tmo != TICK_MAX ) { TAILQ_INSERT_TAIL(&OS_SYS_PTR->timerHead,pcbPtr,timerEntry); pcbPtr->timerDec = tmo; } Os_Dispatch(OP_WAIT_SEMAPHORE); } else { /* We hold RES_SCHEDULER */ rv = E_NOT_OK; } } } Irq_Restore(flags); return rv; }
StatusType WaitEvent( EventMaskType Mask ) { OsTaskVarType *curr_pcb = Os_SysTaskGetCurr(); StatusType rv = E_OK; imask_t state; OS_DEBUG(D_EVENT,"# WaitEvent %s\n",Os_SysTaskGetCurr()->constPtr->name); OS_VALIDATE( OS_SYS_PTR->intNestCnt == 0, E_OS_CALLEVEL); OS_VALIDATE( curr_pcb->constPtr->proc_type == PROC_EXTENDED,E_OS_ACCESS); OS_VALIDATE( !Os_TaskOccupiesResources(curr_pcb),E_OS_RESOURCE); #if (OS_NUM_CORES > 1) OS_VALIDATE( !Os_TaskOccupiesSpinlocks(curr_pcb) != 0,E_OS_SPINLOCK); /* @req 4.1.2/SWS_Os_00622 */ #endif /* Remove from ready queue */ Irq_Save(state); // OSEK/VDX footnote 5. The call of WaitEvent does not lead to a waiting state if one of the events passed in the event mask to // WaitEvent is already set. In this case WaitEvent does not lead to a rescheduling. if( !(curr_pcb->ev_set & Mask) ) { curr_pcb->ev_wait = Mask; if ( Os_SchedulerResourceIsFree() ) { // Os_TaskMakeWaiting(currTaskPtr); Os_Dispatch(OP_WAIT_EVENT); assert( curr_pcb->state & ST_RUNNING ); } else { Os_TaskMakeWaiting(curr_pcb); } } Irq_Restore(state); // The following line disables the unused label warning. Remove when // proper error handling is implemented. if (0) goto err; OS_STD_END_1(OSServiceId_WaitEvent,Mask); }
/** @req OS383 */ StatusType GetCounterValue( CounterType counter_id , TickRefType tick_ref) { StatusType rv = E_OK; OsCounterType *cPtr; cPtr = Os_CounterGet(counter_id); #if (OS_SC3==STD_ON) || (OS_SC4==STD_ON) OsTaskVarType *currPcbPtr = Os_SysTaskGetCurr(); if( currPcbPtr->constPtr->applOwnerId != cPtr->applOwnerId ) { /* @req SWS_Os_00056 */ APPL_CHECK_STATE(cPtr->applOwnerId); APPL_CHECK_ACCESS(currPcbPtr->constPtr->applOwnerId, cPtr->accessingApplMask); #if (OS_NUM_CORES > 1) if (Os_ApplGetCore(cPtr->applOwnerId) != GetCoreID()) { StatusType status = Os_NotifyCore(Os_ApplGetCore(cPtr->applOwnerId), OSServiceId_GetCounterValue, counter_id, (uint32_t)tick_ref, 0); return status; } #endif } #endif OS_VALIDATE(IsCounterValid(counter_id),E_OS_ID); /* @req 4.1.2/SWS_Os_00376 */ /** @req OS377 */ if( cPtr->type == COUNTER_TYPE_HARD ) { if( cPtr->driver == NULL ) { /* It's OSINTERNAL */ *tick_ref = OS_SYS_PTR->tick; } else { #if 0 /* We support only GPT for now */ *tick_ref = (TickType)Gpt_GetTimeElapsed(cPtr->driver.OsGptChannelRef); #endif } } else { *tick_ref = cPtr->val; } COUNTER_STD_END; }
/** @req OS399 */ StatusType IncrementCounter( CounterType counter_id ) { StatusType rv = E_OK; OsCounterType *cPtr; uint32_t flags; #if (OS_SC3==STD_ON) || (OS_SC4==STD_ON) OsTaskVarType *currPcbPtr; #endif OS_VALIDATE( IsCounterValid(counter_id), E_OS_ID ); cPtr = Os_CounterGet(counter_id); OS_VALIDATE( !( ( cPtr->type != COUNTER_TYPE_SOFT ) || ( counter_id >= OS_COUNTER_CNT )), E_OS_ID ); #if (OS_SC3==STD_ON) || (OS_SC4==STD_ON) currPcbPtr = Os_SysTaskGetCurr(); if( currPcbPtr->constPtr->applOwnerId != cPtr->applOwnerId ) { /* @req SWS_Os_00056 */ APPL_CHECK_STATE(cPtr->applOwnerId); APPL_CHECK_ACCESS(currPcbPtr->constPtr->applOwnerId, cPtr->accessingApplMask); #if (OS_CORE_CNT > 1) OS_EXT_VALIDATE( Os_ApplGetCore(cPtr->applOwnerId) != GetCoreID(), E_OS_ACCESS ); #endif } #endif Irq_Save(flags); /** @req OS286 */ cPtr->val = Os_CounterAdd( cPtr->val, Os_CounterGetMaxValue(cPtr), 1 ); #if OS_ALARM_CNT!=0 Os_AlarmCheck(cPtr); #endif #if OS_SCHTBL_CNT!=0 Os_SchTblCheck(cPtr); #endif Irq_Restore(flags); /** @req OS321 */ COUNTER_STD_END; }
/** * The events of the extended task calling ClearEvent are cleared * according to the event mask <Mask>. * * * @param Mask * @return */ StatusType ClearEvent( EventMaskType Mask) { StatusType rv = E_OK; OsTaskVarType *pcb = Os_SysTaskGetCurr(); imask_t flags; OS_VALIDATE( OS_SYS_PTR->intNestCnt == 0,E_OS_CALLEVEL); OS_VALIDATE(pcb->constPtr->proc_type == PROC_EXTENDED,E_OS_ACCESS); Irq_Save(flags); pcb->ev_set &= ~Mask; Irq_Restore(flags); if (0) goto err; OS_STD_END_1(OSServiceId_ClearEvent,Mask); }
StatusType GetResource( ResourceType ResID ) { StatusType rv = E_OK; OsResourceType *rPtr; uint32_t flags; #if (OS_APPLICATION_CNT > 1) if (ResID != RES_SCHEDULER) { rv = Os_ApplHaveAccess( Os_ResourceGet(ResID)->accessingApplMask ); if( rv != E_OK ) { goto err; } } #endif Irq_Save(flags); if( Os_Sys.intNestCnt != 0 ) { /* For interrupts to the scheduler resource seems just dumb to get */ OsIsrVarType *isrPtr = Os_SysIsrGetCurr(); /* Check we can access it */ if( ((isrPtr->constPtr->resourceMask & (1<< ResID)) == 0) || ( ResID == RES_SCHEDULER ) ) { rv = E_OS_ID; goto err; } rPtr = Os_ResourceGet(ResID); /* ceiling prio for ISR seems strange...so no */ if( rPtr->owner != NO_TASK_OWNER ) { rv = E_OS_ACCESS; Irq_Restore(flags); goto err; } /* Add the resource to the list of resources held by this isr */ Os_IsrResourceAdd(rPtr,isrPtr); } else { OsTaskVarType *taskPtr = Os_SysTaskGetCurr(); if( ResID == RES_SCHEDULER ) { rPtr = &Os_Sys.resScheduler; } else { /* Check we can access it */ if( (taskPtr->constPtr->resourceAccess & (1<< ResID)) == 0 ) { rv = E_OS_ID; goto err; } rPtr = Os_ResourceGet(ResID); } /* Check for invalid configuration */ if( (rPtr->owner != NO_TASK_OWNER) || (taskPtr->activePriority > rPtr->ceiling_priority) ) { rv = E_OS_ACCESS; Irq_Restore(flags); goto err; } /* Add the resource to the list of resources held by this task */ Os_TaskResourceAdd(rPtr,taskPtr); } Irq_Restore(flags); if (rv != E_OK) goto err; OS_STD_END_1(OSServiceId_GetResource,ResID); }
StatusType SetEvent( TaskType TaskID, EventMaskType Mask ) { StatusType rv = E_OK; OsTaskVarType *destPcbPtr; OsTaskVarType *currPcbPtr; uint32_t flags; OS_DEBUG(D_EVENT,"# SetEvent %s\n",Os_SysTaskGetCurr()->constPtr->name); TASK_CHECK_ID(TaskID); destPcbPtr = Os_TaskGet(TaskID); currPcbPtr = Os_SysTaskGetCurr(); #if (OS_SC3==STD_ON) || (OS_SC4==STD_ON) if( destPcbPtr->constPtr->applOwnerId != OS_SYS_PTR->currApplId ) { ApplicationType appId; APPL_CHECK_STATE(destPcbPtr->constPtr->applOwnerId); /* Do we have access to the task we are activating */ if(OS_SYS_PTR->intNestCnt == 0 ) { appId = currPcbPtr->constPtr->applOwnerId; } else { appId = Os_SysIsrGetCurr()->constPtr->appOwner; } APPL_CHECK_ACCESS( appId , destPcbPtr->constPtr->accessingApplMask); #if (OS_NUM_CORES > 1) if (Os_ApplGetCore(destPcbPtr->constPtr->applOwnerId) != GetCoreID()) { StatusType status = Os_NotifyCore(Os_ApplGetCore(destPcbPtr->constPtr->applOwnerId), OSServiceId_SetEvent, TaskID, Mask, 0); return status; #endif } #endif OS_VALIDATE( destPcbPtr->constPtr->proc_type == PROC_EXTENDED, E_OS_ACCESS ); OS_VALIDATE( !(destPcbPtr->state & ST_SUSPENDED ), E_OS_STATE); Irq_Save(flags); /* Calling SetEvent causes the task <TaskID> to be transferred * to the ready state, if it was waiting for at least one of the * events specified in <Mask>. * * OSEK/VDX 4.6.1, rescheduling is performed in all of the following cases: * .. * Setting an event to a waiting task at task level (e.g. system service SetEvent, * see chapter 13.5.3.1, message notification mechanism, alarm expiration, if event setting * defined, see chapter 9.2) * ... */ destPcbPtr->ev_set |= Mask; if( (Mask & destPcbPtr->ev_wait) ) { /* We have an event match */ if( destPcbPtr->state & ST_WAITING) { Os_TaskMakeReady(destPcbPtr); currPcbPtr = Os_SysTaskGetCurr(); /* Checking "4.6.2 Non preemptive scheduling" it does not dispatch if NON */ if( (OS_SYS_PTR->intNestCnt == 0) && (currPcbPtr->constPtr->scheduling == FULL) && (destPcbPtr->activePriority > currPcbPtr->activePriority) && (Os_SchedulerResourceIsFree()) ) { Os_Dispatch(OP_SET_EVENT); } } else if(destPcbPtr->state & (ST_READY|ST_RUNNING|ST_SLEEPING) ) { /* Hmm, we do nothing */ } else { assert( 0 ); } } Irq_Restore(flags); OS_STD_END_2(OSServiceId_SetEvent,TaskID, Mask); } /** * This service returns the current state of all event bits of the task * <TaskID>, not the events that the task is waiting for. * The service may be called from interrupt service routines, task * level and some hook routines (see Figure 12-1). * The current status of the event mask of task <TaskID> is copied * to <Event>. * * @param TaskId Task whose event mask is to be returned. * @param Mask Reference to the memory of the return data. * @return */ StatusType GetEvent( TaskType TaskId, EventMaskRefType Mask) { OsTaskVarType *destPcbPtr; StatusType rv = E_OK; TASK_CHECK_ID(TaskId); destPcbPtr = Os_TaskGet(TaskId); OS_VALIDATE( (destPcbPtr->constPtr->proc_type == PROC_EXTENDED) ,E_OS_ACCESS); OS_VALIDATE( !(destPcbPtr->state & ST_SUSPENDED),E_OS_STATE); *Mask = destPcbPtr->ev_set; if (0) goto err; OS_STD_END_2(OSServiceId_GetEvent,TaskId, Mask); }