|  | #pragma once | 
|  | #include "FreeRTOS.h" | 
|  | #include "thread.h" | 
|  | #include <locks.h> | 
|  | #define INC_TASK_H | 
|  |  | 
|  | /** | 
|  | * Initialise a timeout with the current number of elapsed ticks.  This is used | 
|  | * in a blocking function in conjunction with `xTaskCheckForTimeOut()`.  The | 
|  | * value returned here should be passed as the first argument of | 
|  | * `xTaskCheckForTimeOut()`. | 
|  | */ | 
|  | static inline void vTaskSetTimeOutState(TimeOut_t *timeout) | 
|  | { | 
|  | SystickReturn ret = thread_systemtick_get(); | 
|  | *timeout          = ((uint64_t)ret.hi << 32) | ret.lo; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return whether a timeout has expired.  The first argument should be a | 
|  | * pointer to the value returned by `vTaskSetTimeOutState()` before any | 
|  | * blocking operations.  The second argument is the number of ticks to wait. | 
|  | * This function returns `pdTRUE` if the timeout has expired, or `pdFALSE` if | 
|  | * the timeout has not expired, and updates the arguments to reflect the | 
|  | * remaining time to wait. | 
|  | */ | 
|  | static inline BaseType_t xTaskCheckForTimeOut(TimeOut_t  *pxTimeOut, | 
|  | TickType_t *pxTicksToWait) | 
|  | { | 
|  | BaseType_t xReturn; | 
|  | uint64_t   timeBlock; | 
|  | TickType_t xElapsedTime; | 
|  |  | 
|  | vTaskSetTimeOutState(&timeBlock); | 
|  |  | 
|  | xElapsedTime = timeBlock - *pxTimeOut; | 
|  | if (xElapsedTime < *pxTicksToWait) | 
|  | { | 
|  | *pxTicksToWait -= xElapsedTime; | 
|  | *pxTimeOut = timeBlock; | 
|  | xReturn    = pdFALSE; | 
|  | } | 
|  | else | 
|  | { | 
|  | *pxTicksToWait = (TickType_t)0; | 
|  | xReturn        = pdTRUE; | 
|  | } | 
|  |  | 
|  | return xReturn; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Block the current thread for a given number of ticks. | 
|  | */ | 
|  | static inline void vTaskDelay(const TickType_t xTicksToDelay) | 
|  | { | 
|  | struct Timeout timeout = {0, xTicksToDelay}; | 
|  | thread_sleep(&timeout, ThreadSleepNoEarlyWake); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the number of ticks elapsed since the system booted.  This is | 
|  | * truncated to a 32-bit value. | 
|  | */ | 
|  | static inline TickType_t xTaskGetTickCount(void) | 
|  | { | 
|  | return thread_systemtick_get().lo; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the current thread ID. | 
|  | */ | 
|  | static inline TaskHandle_t xTaskGetCurrentTaskHandle(void) | 
|  | { | 
|  | return thread_id_get(); | 
|  | } | 
|  |  | 
|  | __BEGIN_DECLS | 
|  |  | 
|  | /** | 
|  | * Lock used to simulate disabling interrupts in `taskENTER_CRITICAL` and | 
|  | * `taskEXIT_CRITICAL`.  Code using these APIs must provide a definition to | 
|  | * accompany this declaration. | 
|  | */ | 
|  | extern struct RecursiveMutexState __CriticalSectionFlagLock; | 
|  |  | 
|  | /** | 
|  | * Lock used to simulate disabling interrupts in `vTaskSuspendAll` and | 
|  | * `xTaskResumeAll`.  Code using these APIs must provide a definition to | 
|  | * accompany this declaration. | 
|  | */ | 
|  | extern struct RecursiveMutexState __SuspendFlagLock; | 
|  |  | 
|  | __END_DECLS | 
|  |  | 
|  | /** | 
|  | * Critical section.  This acquires a recursive mutex.  In FreeRTOS, this | 
|  | * disables interrupts.  The CHERIoT RTOS security model does not permit | 
|  | * interrupts to be arbitrarily disabled, only for designated scopes.  Callers | 
|  | * of this should be carefully audited to ensure that they are safe. | 
|  | */ | 
|  | static inline void taskENTER_CRITICAL(void) | 
|  | { | 
|  | Timeout t = {0, UnlimitedTimeout}; | 
|  | recursivemutex_trylock(&t, &__CriticalSectionFlagLock); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Exit a critical section entered with `taskENTER_CRITICAL`. | 
|  | */ | 
|  | static inline void taskEXIT_CRITICAL(void) | 
|  | { | 
|  | recursivemutex_unlock(&__CriticalSectionFlagLock); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Critical section.  This acquires a recursive mutex.  In FreeRTOS, this | 
|  | * disables interrupts.  The CHERIoT RTOS security model does not permit | 
|  | * interrupts to be arbitrarily disabled, only for designated scopes.  Callers | 
|  | * of this should be carefully audited to ensure that they are safe. | 
|  | */ | 
|  | static inline void vTaskSuspendAll(void) | 
|  | { | 
|  | Timeout t = {0, UnlimitedTimeout}; | 
|  | recursivemutex_trylock(&t, &__SuspendFlagLock); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Exit a critical section entered with `vTaskSuspendAll`. | 
|  | */ | 
|  | static inline BaseType_t xTaskResumeAll(void) | 
|  | { | 
|  | recursivemutex_unlock(&__SuspendFlagLock); | 
|  | return pdTRUE; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Exit a critical section entered with `vTaskSuspendAll`. | 
|  | */ | 
|  | static inline void vTaskResumeAll(void) | 
|  | { | 
|  | recursivemutex_unlock(&__SuspendFlagLock); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Task creation API.  CHERIoT RTOS does not permit dynamic thread creation and | 
|  | * so this simply provides a warning so that ported code can be modified to | 
|  | * avoid the API. | 
|  | */ | 
|  | #define xTaskCreate(...)                                                       \ | 
|  | _Pragma("GCC warning \"Dynamic thread creation is not supported\"")(       \ | 
|  | TaskHandle_t) -                                                          \ | 
|  | 1 | 
|  |  | 
|  | /** | 
|  | * Task creation API.  CHERIoT RTOS does not permit dynamic thread creation and | 
|  | * so this simply provides a warning so that ported code can be modified to | 
|  | * avoid the API. | 
|  | */ | 
|  | #define xTaskCreateStatic(...)                                                 \ | 
|  | _Pragma("GCC warning \"Dynamic thread creation is not supported\"")(       \ | 
|  | TaskHandle_t) -                                                          \ | 
|  | 1 |