fprime/Os/Posix/Task.hpp
Will MacCormack b9a7059667
Set the Name of Fprime Tasks on Linux (#4428)
* Set the Name of Fprime Tasks on Linux

* prefix thread name w/ process name

* Revert "prefix thread name w/ process name"

This reverts commit 5867602f135c69022469c985b6de13458686e6a2.

* Add `setname` to spelling expected list

* Format My Changes

* Add in opt-out configuration

* Enable POSIX_THREADS_ENABLE_NAMES and fix ut

* Remove warning when flag set off

* UT thread names

* Add tmate session setup to build workflow

* Disable thread names on Ip UTs

* Use random thread ids in UTs

* Fix race condition

* Fix improper string set

---------

Co-authored-by: M Starch <LeStarch@googlemail.com>
Co-authored-by: Michael D Starch <Michael.D.Starch@jpl.nasa.gov>
2025-12-01 10:15:35 -08:00

127 lines
4.7 KiB
C++

// ======================================================================
// \title Os/Posix/Task.hpp
// \brief definitions of Posix implementation of Os::Task
// ======================================================================
#ifndef Os_Posix_Task_hpp_
#define Os_Posix_Task_hpp_
#include <pthread.h>
#include <Os/Task.hpp>
#include <atomic>
#include <Fw/Deprecate.hpp>
#include <Fw/FPrimeBasicTypes.hpp>
#include <Fw/Types/Serializable.hpp>
#include <Os/Mutex.hpp>
#include <Os/TaskString.hpp>
namespace Os {
namespace Posix {
namespace Task {
//! TaskHandle class definition for posix implementations.
//!
struct PosixTaskHandle : public TaskHandle {
static constexpr FwSizeType PTHREAD_NAME_LENGTH = 16; //!< Length of pthread name
static constexpr int SUCCESS = 0;
//! Posix task descriptor
pthread_t m_task_descriptor;
//! Is the above descriptor valid
bool m_is_valid = false;
#if defined(POSIX_THREADS_ENABLE_NAMES) && POSIX_THREADS_ENABLE_NAMES
char m_name[PosixTaskHandle::PTHREAD_NAME_LENGTH];
#endif
};
//! Posix task implementation as driven by pthreads implementation
class PosixTask : public TaskInterface {
public:
//! Enumeration of permission expectations
enum PermissionExpectation {
EXPECT_PERMISSION, //!< Expect that you hold necessary permissions
EXPECT_NO_PERMISSION //!< Expect that you do not hold necessary permissions
};
//! \brief default constructor
PosixTask() = default;
//! \brief default virtual destructor
~PosixTask() = default;
//! \brief copy constructor is forbidden
PosixTask(const PosixTask& other) = delete;
//! \brief assignment operator is forbidden
PosixTask& operator=(const PosixTask& other) = delete;
//! \brief perform required task start actions
void onStart() override;
//! \brief start the task
//!
//! Starts the task given the supplied arguments. This is done via a task routine wrapper intermediary that
//! ensures that `setStarted` is called once the task has actually started to run. The task then runs the user
//! routine. This function may return before the new task begins to run.
//
//! It is illegal for arguments.m_routine to be null.
//!
//! \param arguments: arguments supplied to the task start call
//! \return status of the task start
Status start(const Arguments& arguments) override;
//! \brief block until the task has ended
//!
//! Blocks the current (calling) task until this task execution has ended. Callers should ensure that any
//! signals required to stop this task have already been emitted or will be emitted by another task.
//!
//! \return status of the block
Status join() override; //!< Wait for task to finish
//! \brief suspend the task given the suspension type
//!
//! Suspends the task. Some implementations track if the suspension of a task was intentional or
//! unintentional. The supplied `suspensionType` parameter indicates that this was intentional or
//! unintentional. The type of suspension is also returned when calling `isSuspended`.
//!
//! \param suspensionType intentionality of the suspension
void suspend(SuspensionType suspensionType) override;
//! \brief resume a suspended task
//!
//! Resumes this task. Not started, running, and exited tasks take no action.
//!
void resume() override;
//! \brief delay the current task
//!
//! Delays, or sleeps, the current task by the supplied time interval. In non-preempting os implementations
//! the task will resume no earlier than expected but an exact wake-up time is not guaranteed.
//!
//! \param interval: delay time
//! \return status of the delay
Status _delay(Fw::TimeInterval interval) override;
//! \brief return the underlying task handle (implementation specific)
//! \return internal task handle representation
TaskHandle* getHandle() override;
private:
//! \brief create a configured pthread
//!
//! Creates, and configures, but does not start a pthread. This may be called twice, once to try setting
//! permissions and once to fallback to no permissions.
//!
//! \param arguments: arguments used to set priority, affinity, etc
//! \param permissions: whether to expect permissions or not
//! \return OP_OK on success, or an error
Status create(const Os::Task::Arguments& arguments, const PosixTask::PermissionExpectation permissions);
PosixTaskHandle m_handle; //!< Posix task tracking
static std::atomic<bool> s_permissions_reported; //!< Permission errors have been reported
};
} // end namespace Task
} // end namespace Posix
} // end namespace Os
#endif