| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title Os/Posix/Task.hpp | ||
| 3 | // \brief definitions of Posix implementation of Os::Task | ||
| 4 | // ====================================================================== | ||
| 5 | #ifndef Os_Posix_Task_hpp_ | ||
| 6 | #define Os_Posix_Task_hpp_ | ||
| 7 | |||
| 8 | #include <pthread.h> | ||
| 9 | #include <Os/Task.hpp> | ||
| 10 | #include <atomic> | ||
| 11 | |||
| 12 | #include <Fw/Deprecate.hpp> | ||
| 13 | #include <Fw/FPrimeBasicTypes.hpp> | ||
| 14 | #include <Fw/Types/Serializable.hpp> | ||
| 15 | #include <Os/Mutex.hpp> | ||
| 16 | #include <Os/Posix/Models/FppConstantsAc.hpp> | ||
| 17 | #include <Os/TaskString.hpp> | ||
| 18 | |||
| 19 | namespace Os { | ||
| 20 | namespace Posix { | ||
| 21 | namespace Task { | ||
| 22 | |||
| 23 | //! TaskHandle class definition for posix implementations. | ||
| 24 | //! | ||
| 25 | struct PosixTaskHandle : public TaskHandle { | ||
| 26 | static constexpr FwSizeType PTHREAD_NAME_LENGTH = 16; //!< Length of pthread name | ||
| 27 | static constexpr int SUCCESS = 0; | ||
| 28 | |||
| 29 | //! Posix task descriptor | ||
| 30 | pthread_t m_task_descriptor; | ||
| 31 | //! Is the above descriptor valid | ||
| 32 | bool m_is_valid = false; | ||
| 33 | #if defined(POSIX_THREADS_ENABLE_NAMES) && POSIX_THREADS_ENABLE_NAMES | ||
| 34 | char m_name[PosixTaskHandle::PTHREAD_NAME_LENGTH]; | ||
| 35 | #endif | ||
| 36 | }; | ||
| 37 | |||
| 38 | //! Posix task implementation as driven by pthreads implementation | ||
| 39 | class PosixTask : public TaskInterface { | ||
| 40 | public: | ||
| 41 | //! Enumeration of permission expectations | ||
| 42 | enum PermissionExpectation { | ||
| 43 | EXPECT_PERMISSION, //!< Expect that you hold necessary permissions | ||
| 44 | EXPECT_NO_PERMISSION //!< Expect that you do not hold necessary permissions | ||
| 45 | }; | ||
| 46 | |||
| 47 | //! Sentinel priority: run the task under SCHED_OTHER (non-realtime) rather than SCHED_RR | ||
| 48 | static constexpr FwTaskPriorityType TASK_PRIORITY_NON_REALTIME = | ||
| 49 | static_cast<FwTaskPriorityType>(Os::Posix::TASK_PRIORITY_NON_REALTIME); | ||
| 50 | static_assert(TASK_PRIORITY_NON_REALTIME != Os::Task::TASK_PRIORITY_DEFAULT, | ||
| 51 | "TASK_PRIORITY_NON_REALTIME must not alias TASK_PRIORITY_DEFAULT"); | ||
| 52 | |||
| 53 | //! \brief default constructor | ||
| 54 | 3284 | PosixTask() = default; | |
| 55 | |||
| 56 | //! \brief default virtual destructor | ||
| 57 | 6568 | ~PosixTask() = default; | |
| 58 | |||
| 59 | //! \brief copy constructor is forbidden | ||
| 60 | PosixTask(const PosixTask& other) = delete; | ||
| 61 | |||
| 62 | //! \brief assignment operator is forbidden | ||
| 63 | PosixTask& operator=(const PosixTask& other) = delete; | ||
| 64 | |||
| 65 | //! \brief perform required task start actions | ||
| 66 | void onStart() override; | ||
| 67 | |||
| 68 | //! \brief start the task | ||
| 69 | //! | ||
| 70 | //! Starts the task given the supplied arguments. This is done via a task routine wrapper intermediary that | ||
| 71 | //! ensures that `setStarted` is called once the task has actually started to run. The task then runs the user | ||
| 72 | //! routine. This function may return before the new task begins to run. | ||
| 73 | // | ||
| 74 | //! It is illegal for arguments.m_routine to be null. | ||
| 75 | //! | ||
| 76 | //! \param arguments: arguments supplied to the task start call | ||
| 77 | //! \return status of the task start | ||
| 78 | Status start(const Arguments& arguments) override; | ||
| 79 | |||
| 80 | //! \brief block until the task has ended | ||
| 81 | //! | ||
| 82 | //! Blocks the current (calling) task until this task execution has ended. Callers should ensure that any | ||
| 83 | //! signals required to stop this task have already been emitted or will be emitted by another task. | ||
| 84 | //! | ||
| 85 | //! \return status of the block | ||
| 86 | Status join() override; //!< Wait for task to finish | ||
| 87 | |||
| 88 | //! \brief suspend the task given the suspension type | ||
| 89 | //! | ||
| 90 | //! Suspends the task. Some implementations track if the suspension of a task was intentional or | ||
| 91 | //! unintentional. The supplied `suspensionType` parameter indicates that this was intentional or | ||
| 92 | //! unintentional. The type of suspension is also returned when calling `isSuspended`. | ||
| 93 | //! | ||
| 94 | //! \param suspensionType intentionality of the suspension | ||
| 95 | void suspend(SuspensionType suspensionType) override; | ||
| 96 | |||
| 97 | //! \brief resume a suspended task | ||
| 98 | //! | ||
| 99 | //! Resumes this task. Not started, running, and exited tasks take no action. | ||
| 100 | //! | ||
| 101 | void resume() override; | ||
| 102 | |||
| 103 | //! \brief delay the current task | ||
| 104 | //! | ||
| 105 | //! Delays, or sleeps, the current task by the supplied time interval. In non-preempting os implementations | ||
| 106 | //! the task will resume no earlier than expected but an exact wake-up time is not guaranteed. | ||
| 107 | //! | ||
| 108 | //! \param interval: delay time | ||
| 109 | //! \return status of the delay | ||
| 110 | Status _delay(const Fw::TimeInterval& interval) override; | ||
| 111 | |||
| 112 | //! \brief return the underlying task handle (implementation specific) | ||
| 113 | //! \return internal task handle representation | ||
| 114 | TaskHandle* getHandle() override; | ||
| 115 | |||
| 116 | private: | ||
| 117 | //! \brief create a configured pthread | ||
| 118 | //! | ||
| 119 | //! Creates, and configures, but does not start a pthread. This may be called twice, once to try setting | ||
| 120 | //! permissions and once to fallback to no permissions. | ||
| 121 | //! | ||
| 122 | //! \param arguments: arguments used to set priority, affinity, etc | ||
| 123 | //! \param permissions: whether to expect permissions or not | ||
| 124 | //! \return OP_OK on success, or an error | ||
| 125 | Status create(const Os::Task::Arguments& arguments, const PosixTask::PermissionExpectation permissions); | ||
| 126 | |||
| 127 | PosixTaskHandle m_handle; //!< Posix task tracking | ||
| 128 | static std::atomic<bool> s_permissions_reported; //!< Permission errors have been reported | ||
| 129 | }; | ||
| 130 | } // end namespace Task | ||
| 131 | } // end namespace Posix | ||
| 132 | } // end namespace Os | ||
| 133 | #endif | ||
| 134 |