F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
Task.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title Os/Task.cpp
3 // \brief common function implementation for Os::Task
4 // ======================================================================
5 #include <Os/Task.hpp>
6 #include <Fw/Types/Assert.hpp>
7 
8 namespace Os {
9 
11  void * const routine_argument, const FwSizeType priority,
12  const FwSizeType stackSize, const FwSizeType cpuAffinity,
13  const PlatformUIntType identifier) :
14  m_name(name),
15  m_routine(routine),
16  m_routine_argument(routine_argument),
17  m_priority(priority),
18  m_stackSize(stackSize),
19  m_cpuAffinity(cpuAffinity),
20  m_identifier(identifier)
21 {
22  FW_ASSERT(routine != nullptr);
23 }
24 
26 
27 void Task::TaskRoutineWrapper::run(void* wrapper_pointer) {
28  FW_ASSERT(wrapper_pointer != nullptr);
29  TaskRoutineWrapper& wrapper = *reinterpret_cast<TaskRoutineWrapper*>(wrapper_pointer);
30  FW_ASSERT(wrapper.m_user_function != nullptr);
31 
32  wrapper.m_task.m_lock.lock();
33  Task::State state = wrapper.m_task.m_state;
34  wrapper.m_task.m_lock.unlock();
35 
36  // Run once start code
37  if (state == Task::State::NOT_STARTED) {
38  wrapper.m_task.m_lock.lock();
39  wrapper.m_task.m_state = Task::State::RUNNING;
40  wrapper.m_task.m_lock.unlock();
41  wrapper.m_task.onStart();
42  }
43 
44  // Call user function supplying the user argument
45  wrapper.m_user_function(wrapper.m_user_argument);
46 }
47 
50 }
51 
52 TaskRegistry* Task::s_taskRegistry = nullptr;
53 FwSizeType Task::s_numTasks = 0;
54 Mutex Task::s_taskMutex = Mutex();
55 
57  return false;
58 }
59 
60 Task::Task() : m_wrapper(*this), m_handle_storage(), m_delegate(*TaskInterface::getDelegate(m_handle_storage)) {}
61 
63  // If a registry has been registered and the task has been started then remove task from the registry
64  if ((Task::s_taskRegistry != nullptr) && this->m_registered) {
65  Task::s_taskRegistry->removeTask(this);
66  }
67  m_delegate.~TaskInterface();
68 }
69 
70 void Task::suspend() {
71  this->suspend(Task::SuspensionType::UNINTENTIONAL);
72 }
73 
75  Task::State state;
76  this->m_lock.lock();
77  state = this->m_state;
78  this->m_lock.unlock();
79  return state;
80 }
81 
82 Task::Status Task::start(const Fw::StringBase &name, const taskRoutine routine, void* const arg,
83  const ParamType priority, const ParamType stackSize, const ParamType cpuAffinity,
84  const ParamType identifier) {
85  FW_ASSERT(routine != nullptr);
86  return this->start(Task::Arguments(name, routine, arg,
87  priority,
88  stackSize,
89  cpuAffinity,
90  static_cast<PlatformUIntType>(identifier)));
91 }
92 
93 
94 Task::Status Task::start(const Task::Arguments& arguments) {
95  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
96  FW_ASSERT(arguments.m_routine != nullptr);
97  this->m_name = arguments.m_name;
98 
99  Arguments wrapped_arguments = arguments;
100  // Intercept routine and argument with the local wrapper
101  this->m_wrapper.m_user_function = arguments.m_routine;
102  this->m_wrapper.m_user_argument = arguments.m_routine_argument;
103  wrapped_arguments.m_routine = Task::TaskRoutineWrapper::run;
104  wrapped_arguments.m_routine_argument = &this->m_wrapper;
105 
106  Task::Status status = this->m_delegate.start(wrapped_arguments);
107  if (status == Task::Status::OP_OK) {
108  Task::s_taskMutex.lock();
109  Task::s_numTasks++;
110  Task::s_taskMutex.unlock();
111 
112  // If a registry has been registered, register task to it
113  if (Task::s_taskRegistry) {
114  Task::s_taskRegistry->addTask(this);
115  this->m_registered = true;
116  }
117  }
118  return status;
119 }
120 
122  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
123  this->m_delegate.onStart();
124 }
125 
127  this->m_wrapper.invoke();
128 }
129 
131  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
132  Task::Status status = Task::Status::INVALID_STATE;
133  Task::State state = this->getState();
134  if (state == Task::RUNNING) {
135  status = this->m_delegate.join();
136  this->m_lock.lock();
137  if (status == Task::Status::OP_OK) {
138  this->m_state = Task::State::EXITED;
139  } else {
140  this->m_state = Task::State::UNKNOWN;
141  }
142  this->m_lock.unlock();
143  }
144  return status;
145 }
146 
147 void Task::suspend(Task::SuspensionType suspensionType) {
148  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
149  this->m_delegate.suspend(suspensionType);
150  this->m_lock.lock();
151  this->m_state = (suspensionType == Task::SuspensionType::INTENTIONAL) ? State::SUSPENDED_INTENTIONALLY : State::SUSPENDED_UNINTENTIONALLY;
152  this->m_lock.unlock();
153 }
154 
155 void Task::resume() {
156  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
157  this->m_delegate.resume();
158 }
159 
161  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
162  return this->m_delegate.isCooperative();
163 }
164 
166  FW_ASSERT(&this->m_delegate == reinterpret_cast<TaskInterface*>(&this->m_handle_storage[0]));
167  return this->m_delegate.getHandle();
168 }
169 
171  Task::s_taskMutex.lock();
172  FwSizeType num_tasks = Task::s_numTasks;
173  Task::s_taskMutex.unlock();
174  return num_tasks;
175 }
176 
178  Task::s_taskRegistry = registry;
179 }
180 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
unsigned int PlatformUIntType
PlatformSizeType FwSizeType
Definition: FpConfig.h:30
void unlock()
alias for unLock to meet BasicLockable requirements
Definition: Mutex.hpp:16
void lock()
lock the mutex
Definition: Mutex.cpp:12
Wrapper for task routine that ensures onStart() is called once the task actually begins.
Definition: Task.hpp:198
void invoke()
invoke the run method with "self" as argument
Definition: Task.cpp:48
static void run(void *task_pointer)
run the task routine wrapper
Definition: Task.cpp:27
void * m_user_argument
Argument to user function.
Definition: Task.hpp:214
TaskRoutineWrapper(Task &self)
Definition: Task.cpp:25
Task & m_task
Reference to owning task.
Definition: Task.hpp:212
taskRoutine m_user_function
User function to run once started.
Definition: Task.hpp:213
Task handle representation.
Definition: Task.hpp:24
static FwSizeType getNumTasks()
get the current number of tasks
Definition: Task.cpp:170
bool isCooperative() override
determine if the task is cooperative multitasking (implementation specific)
Definition: Task.cpp:160
Task()
default constructor
Definition: Task.cpp:60
TaskHandle * getHandle() override
return the underlying task handle (implementation specific)
Definition: Task.cpp:165
State getState()
get the task's state
Definition: Task.cpp:74
FwSizeType ParamType
backwards-compatible parameter type
Definition: Task.hpp:218
void resume() override
resume a suspended task
Definition: Task.cpp:155
void onStart() override
perform delegate's required task start actions
Definition: Task.cpp:121
void invokeRoutine()
invoke the task's routine
Definition: Task.cpp:126
void suspend()
suspend the current task
Definition: Task.cpp:70
static void registerTaskRegistry(TaskRegistry *registry)
register a task registry to track Threads
Definition: Task.cpp:177
Status start(const Arguments &arguments) override
start the task
Definition: Task.cpp:82
~Task() final
default virtual destructor
Definition: Task.cpp:62
Status join() override
block until the task has ended
Definition: Task.cpp:130
Arguments(const Fw::StringBase &name, const taskRoutine routine, void *const routine_argument=nullptr, const FwSizeType priority=TASK_DEFAULT, const FwSizeType stackSize=TASK_DEFAULT, const FwSizeType cpuAffinity=TASK_DEFAULT, const PlatformUIntType identifier=static_cast< PlatformUIntType >(TASK_DEFAULT))
construct a set of arguments to start a task
Definition: Task.cpp:10
const Os::TaskString m_name
Definition: Task.hpp:82
virtual TaskHandle * getHandle()=0
return the underlying task handle (implementation specific)
static TaskInterface * getDelegate(HandleStorage &aligned_placement_new_memory)
provide a pointer to a task delegate object
Definition: DefaultTask.cpp:41
virtual Status start(const Arguments &arguments)=0
start the task
virtual void suspend(SuspensionType suspensionType)=0
suspend the task given the suspension type
virtual Status join()=0
block until the task has ended
virtual void resume()=0
resume a suspended task
virtual ~TaskInterface()=default
default virtual destructor
void(* taskRoutine)(void *ptr)
Prototype for task routine started in task context.
Definition: Task.hpp:58
virtual void onStart()=0
perform required task start actions
virtual bool isCooperative()
determine if the task requires cooperative multitasking
Definition: Task.cpp:56
virtual void addTask(Task *task)=0
add supplied task to the registry
virtual void removeTask(Task *task)=0
remove supplied task to the registry
@ OP_OK
Operation was successful.
Definition: FileSystem.hpp:15