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