INT8U OSSemPost(BRTOS_Sem *pont_event) { OS_SR_SAVE_VAR INT8U iPriority = (INT8U)0; #if (VERBOSE == 1) INT8U TaskSelect = 0; #endif #if (ERROR_CHECK == 1) // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section #if (NESTING_INT == 0) if (!iNesting) #endif OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section #if (NESTING_INT == 0) if (!iNesting) #endif OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) if(!iNesting){ #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, SEMPOST); #else Update_OSTrace(ContextTask[currentTask].Priority, SEMPOST); #endif }else{ Update_OSTrace(0, SEMPOST); } #endif // See if any task is waiting for semaphore if (pont_event->OSEventWait != 0) { // Selects the highest priority task iPriority = SAScheduler(pont_event->OSEventWaitList); // Remove the selected task from the semaphore wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the semaphore wait list counter pont_event->OSEventWait--; // Put the selected task into Ready List #if (VERBOSE == 1) TaskSelect = PriorityVector[iPriority]; ContextTask[TaskSelect].State = READY; #endif OSReadyList = OSReadyList | (PriorityMask[iPriority]); // If outside of an interrupt service routine, change context to the highest priority task // If inside of an interrupt, the interrupt itself will change the context to the highest priority task if (!iNesting) { // Verify if there is a higher priority task ready to run ChangeContext(); } // Exit Critical Section #if (NESTING_INT == 0) if (!iNesting) #endif OSExitCritical(); return OK; } // Make sure semaphore will not overflow if (pont_event->OSEventCount < 255) { // Increment semaphore count pont_event->OSEventCount++; // Exit Critical Section #if (NESTING_INT == 0) if (!iNesting) #endif OSExitCritical(); return OK; } else { // Exit Critical Section #if (NESTING_INT == 0) if (!iNesting) #endif OSExitCritical(); // Indicates semaphore overflow return ERR_SEM_OVF; } }
INT8U OSSemPend (BRTOS_Sem *pont_event, INT16U time_wait) { OS_SR_SAVE_VAR INT8U iPriority = 0; INT32U timeout; ContextType *Task; #if (ERROR_CHECK == 1) // Can not use semaphore pend function from interrupt handling code if(iNesting > 0) { return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, SEMPEND); #else Update_OSTrace(ContextTask[currentTask].Priority, SEMPEND); #endif #endif // Verify if there was a post if (pont_event->OSEventCount > 0) { // Decreases semaphore count pont_event->OSEventCount--; // Exit Critical Section OSExitCritical(); return OK; } Task = (ContextType*)&ContextTask[currentTask]; // Copy task priority to local scope iPriority = Task->Priority; // Increases the semaphore wait list counter pont_event->OSEventWait++; // Allocates the current task on the semaphore wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList | (PriorityMask[iPriority]); // Task entered suspended state, waiting for semaphore post #if (VERBOSE == 1) Task->State = SUSPENDED; Task->SuspendedType = SEMAPHORE; #endif // Remove current task from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Set timeout overflow if (time_wait) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { Task->TimeToWait = (INT16U)(timeout - TICK_COUNT_OVERFLOW); } else { Task->TimeToWait = (INT16U)timeout; } // Put task into delay list IncludeTaskIntoDelayList(); } else { Task->TimeToWait = NO_TIMEOUT; } // Change Context - Returns on time overflow or semaphore post ChangeContext(); if (time_wait) { /* Edited by Carlos H. Barriquello */ /* Moved critical region to inside test region */ // Exit Critical Section OSExitCritical(); // Enter Critical Section OSEnterCritical(); /* End of edition */ // Verify if the reason of task wake up was queue timeout if(Task->TimeToWait == EXIT_BY_TIMEOUT) { // Test if both timeout and post have occured before arrive here if ((pont_event->OSEventWaitList & PriorityMask[iPriority])) { // Remove the task from the queue wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the queue wait list counter pont_event->OSEventWait--; // Exit Critical Section OSExitCritical(); // Indicates queue timeout return TIMEOUT; } } else { // Remove the time to wait condition Task->TimeToWait = NO_TIMEOUT; // Remove from delay list RemoveFromDelayList(); } } // Exit Critical Section OSExitCritical(); return OK; }
// Atraso em passos de TickCount uint8_t OSDelayTask(ostick_t time_wait) { OS_SR_SAVE_VAR osdtick_t timeout; ContextType *Task = (ContextType*)&ContextTask[currentTask]; if (iNesting > 0) { // See if caller is an interrupt return(IRQ_PEND_ERR); // Can't be blocked by interrupt } if (currentTask) { if (time_wait > 0) { OSEnterCritical(); // BRTOS TRACE SUPPORT #if (OSTRACE == 1) #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, DELAYTASK); #else Update_OSTrace(Task->Priority, DELAYTASK); #endif #endif timeout = (osdtick_t)((osdtick_t)OSTickCounter + (osdtick_t)time_wait); if (sizeof_ostick_t < 8){ if (timeout >= TICK_COUNT_OVERFLOW) { Task->TimeToWait = (ostick_t)(timeout - TICK_COUNT_OVERFLOW); } else { Task->TimeToWait = (ostick_t)timeout; } }else{ Task->TimeToWait = (ostick_t)timeout; } // Put task into delay list IncludeTaskIntoDelayList(); #if (VERBOSE == 1) Task->State = SUSPENDED; Task->SuspendedType = DELAY; #endif OSReadyList = OSReadyList & ~(PriorityMask[Task->Priority]); // Change context // Return to task when occur delay overflow ChangeContext(); OSExitCritical(); return OK; } else { return NO_TASK_DELAY; } } else { return NOT_VALID_TASK; } }
INT8U OSMutexRelease(BRTOS_Mutex *pont_event) { OS_SR_SAVE_VAR INT8U iPriority = (INT8U)0; #if (VERBOSE == 1) INT8U TaskSelect = 0; #endif #if (ERROR_CHECK == 1) /// Can not use mutex pend function from interrupt handling code if(iNesting > 0) { return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) if(!iNesting){ #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, MUTEXPOST); #else Update_OSTrace(ContextTask[currentTask].Priority, MUTEXPOST); #endif }else{ Update_OSTrace(0, MUTEXPOST); } #endif // Verify Mutex Owner if (pont_event->OSEventOwner != currentTask) { OSExitCritical(); return ERR_EVENT_OWNER; } // Returns to the original priority, if needed // Copy backuped original priority to the task context iPriority = ContextTask[currentTask].Priority; if (iPriority != pont_event->OSOriginalPriority) { // Since current task is executing with another priority, reallocate its priority to the original // into the Ready List // Remove "max priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Put the "original priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSOriginalPriority]); ContextTask[currentTask].Priority = pont_event->OSOriginalPriority; } // See if any task is waiting for mutex release if (pont_event->OSEventWait != 0) { // Selects the highest priority task iPriority = SAScheduler(pont_event->OSEventWaitList); // Remove the selected task from the mutex wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the mutex wait list counter pont_event->OSEventWait--; // Indicates that selected task is ready to run #if (VERBOSE == 1) TaskSelect = PriorityVector[iPriority]; ContextTask[TaskSelect].State = READY; #endif // Put the selected task into Ready List OSReadyList = OSReadyList | (PriorityMask[iPriority]); // Verify if there is a higher priority task ready to run ChangeContext(); // Exit Critical Section OSExitCritical(); return OK; } // Release Mutex pont_event->OSEventState = AVAILABLE_RESOURCE; PriorityVector[pont_event->OSMaxPriority] = MUTEX_PRIO; // Exit Critical Section OSExitCritical(); return OK; }
INT8U OSMutexAcquire(BRTOS_Mutex *pont_event) { OS_SR_SAVE_VAR INT8U iPriority = 0; #if (ERROR_CHECK == 1) /// Can not use mutex acquire function from interrupt handling code if(iNesting > 0) { return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, MUTEXPEND); #else Update_OSTrace(ContextTask[currentTask].Priority, MUTEXPEND); #endif #endif // Verify if the shared resource is available if (pont_event->OSEventState == AVAILABLE_RESOURCE) { // Set shared resource busy pont_event->OSEventState = BUSY_RESOURCE; // Current task becomes the temporary owner of the mutex pont_event->OSEventOwner = currentTask; /////////////////////////////////////////////////////////////////////////////// // Performs the temporary exchange of mutex owner priority, if needed // /////////////////////////////////////////////////////////////////////////////// // Backup the original task priority pont_event->OSOriginalPriority = ContextTask[currentTask].Priority; if (pont_event->OSMaxPriority > ContextTask[currentTask].Priority) { // Receives the priority ceiling temporarily ContextTask[currentTask].Priority = pont_event->OSMaxPriority; // Priority vector change PriorityVector[pont_event->OSMaxPriority] = currentTask; // Remove "original priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[pont_event->OSOriginalPriority]); // Put the "max priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSMaxPriority]); } OSExitCritical(); return OK; } else { // Copy task priority to local scope iPriority = ContextTask[currentTask].Priority; // Increases the mutex wait list counter pont_event->OSEventWait++; // Allocates the current task on the mutex wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList | (PriorityMask[iPriority]); // Task entered suspended state, waiting for mutex release #if (VERBOSE == 1) ContextTask[currentTask].State = SUSPENDED; ContextTask[currentTask].SuspendedType = MUTEX; #endif // Remove current task from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Change Context - Returns on mutex release ChangeContext(); // Exit Critical Section OSExitCritical(); // Enter Critical Section OSEnterCritical(); // Current task becomes the temporary owner of the mutex pont_event->OSEventOwner = currentTask; /////////////////////////////////////////////////////////////////////////////// // Performs the temporary exchange of mutex owner priority, if needed // /////////////////////////////////////////////////////////////////////////////// // Backup the original task priority pont_event->OSOriginalPriority = iPriority; if (pont_event->OSMaxPriority > iPriority) { // Receives the priority ceiling temporarily ContextTask[currentTask].Priority = pont_event->OSMaxPriority; // Priority vector change PriorityVector[pont_event->OSMaxPriority] = currentTask; // Remove "original priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Put the "max priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSMaxPriority]); } OSExitCritical(); return OK; } }
INT8U OSMutexAcquire(BRTOS_Mutex *pont_event, INT16U time_wait) { OS_SR_SAVE_VAR INT8U iPriority = 0; INT32U timeout; ContextType *Task; #if (ERROR_CHECK == 1) /// Can not use mutex acquire function from interrupt handling code if(iNesting > 0) { return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, MUTEXPEND); #else Update_OSTrace(ContextTask[currentTask].Priority, MUTEXPEND); #endif #endif // Verifies if the task is trying to acquire the mutex again if (currentTask == pont_event->OSEventOwner) { // It is already the mutex owner OSExitCritical(); return OK; } Task = (ContextType*)&ContextTask[currentTask]; // Verify if the shared resource is available if (pont_event->OSEventState == AVAILABLE_RESOURCE) { // Set shared resource busy pont_event->OSEventState = BUSY_RESOURCE; // Current task becomes the temporary owner of the mutex pont_event->OSEventOwner = currentTask; /////////////////////////////////////////////////////////////////////////////// // Performs the temporary exchange of mutex owner priority, if needed // /////////////////////////////////////////////////////////////////////////////// // Backup the original task priority pont_event->OSOriginalPriority = ContextTask[currentTask].Priority; if (pont_event->OSMaxPriority > ContextTask[currentTask].Priority) { // Receives the priority ceiling temporarily Task->Priority = pont_event->OSMaxPriority; // Priority vector change PriorityVector[pont_event->OSMaxPriority] = currentTask; // Remove "original priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[pont_event->OSOriginalPriority]); // Put the "max priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSMaxPriority]); } OSExitCritical(); return OK; } else { // If no timeout is used and the mutex is not available, exit the mutex with an error if (time_wait == NO_TIMEOUT) { // Exit Critical Section OSExitCritical(); return EXIT_BY_NO_RESOURCE_AVAILABLE; } // Copy task priority to local scope iPriority = Task->Priority; // Increases the mutex wait list counter pont_event->OSEventWait++; // Allocates the current task on the mutex wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList | (PriorityMask[iPriority]); // Task entered suspended state, waiting for mutex release #if (VERBOSE == 1) ContextTask[currentTask].State = SUSPENDED; ContextTask[currentTask].SuspendedType = MUTEX; #endif // Remove current task from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Set timeout overflow if (time_wait) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { Task->TimeToWait = (INT16U)(timeout - TICK_COUNT_OVERFLOW); } else { Task->TimeToWait = (INT16U)timeout; } // Put task into delay list IncludeTaskIntoDelayList(); } else { Task->TimeToWait = NO_TIMEOUT; } // Change Context - Returns on mutex release ChangeContext(); // Exit Critical Section OSExitCritical(); // Enter Critical Section OSEnterCritical(); if (time_wait) { // Verify if the reason of task wake up was queue timeout if(Task->TimeToWait == EXIT_BY_TIMEOUT) { // Test if both timeout and post have occured before arrive here if ((pont_event->OSEventWaitList & PriorityMask[iPriority])) { // Remove the task from the queue wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the queue wait list counter pont_event->OSEventWait--; // Exit Critical Section OSExitCritical(); // Indicates resource not available return EXIT_BY_NO_RESOURCE_AVAILABLE; } } else { // Remove the time to wait condition Task->TimeToWait = NO_TIMEOUT; // Remove from delay list RemoveFromDelayList(); } } // Backup the original task priority pont_event->OSOriginalPriority = iPriority; if (pont_event->OSMaxPriority > iPriority) { // Receives the priority ceiling temporarily Task->Priority = pont_event->OSMaxPriority; // Priority vector change PriorityVector[pont_event->OSMaxPriority] = currentTask; // Remove "original priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Put the "max priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSMaxPriority]); } OSExitCritical(); return OK; } }