2 #include <Fw/Types/Assert.hpp>
14 #ifdef TGT_OS_TYPE_LINUX
20 typedef void* (*pthread_func_ptr)(
void*);
36 if (min_priority < 0 or max_priority < 0) {
37 Fw::Logger::logMsg(
"[WARNING] Unable to determine min/max priority with error %s. Discarding priority.\n",
reinterpret_cast<POINTER_CAST
>(strerror(errno)));
42 Fw::Logger::logMsg(
"[WARNING] Task priority set and permissions unavailable. Discarding priority.\n");
46 Fw::Logger::logMsg(
"[WARNING] Low task priority of %d being clamped to %d\n", priority, min_priority);
47 priority = min_priority;
50 Fw::Logger::logMsg(
"[WARNING] High task priority of %d being clamped to %d\n", priority, max_priority);
51 priority = max_priority;
55 Fw::Logger::logMsg(
"[WARNING] Stack size %d too small, setting to minimum of %d\n", stack, PTHREAD_STACK_MIN);
56 stack = PTHREAD_STACK_MIN;
60 Fw::Logger::logMsg(
"[WARNING] Cpu affinity set and permissions unavailable. Discarding affinity.\n");
68 I32 stat = pthread_attr_setstacksize(&att, stack);
70 Fw::Logger::logMsg(
"pthread_attr_setstacksize: %s\n",
reinterpret_cast<POINTER_CAST
>(strerror(stat)));
79 I32 stat = pthread_attr_setschedpolicy(&att,
SCHED_POLICY);
81 Fw::Logger::logMsg(
"pthread_attr_setschedpolicy: %s\n",
reinterpret_cast<POINTER_CAST
>(strerror(stat)));
85 stat = pthread_attr_setinheritsched(&att, PTHREAD_EXPLICIT_SCHED);
88 reinterpret_cast<POINTER_CAST
>(strerror(stat)));
92 sched_param schedParam;
93 memset(&schedParam, 0,
sizeof(sched_param));
94 schedParam.sched_priority = priority;
95 stat = pthread_attr_setschedparam(&att, &schedParam);
97 Fw::Logger::logMsg(
"pthread_attr_setschedparam: %s\n",
reinterpret_cast<POINTER_CAST
>(strerror(stat)));
106 #if TGT_OS_TYPE_LINUX && __GLIBC__
109 CPU_SET(cpuAffinity, &cpuset);
111 I32 stat = pthread_attr_setaffinity_np(&att,
sizeof(cpu_set_t), &cpuset);
114 reinterpret_cast<POINTER_CAST
>(strerror(stat)));
117 #elif TGT_OS_TYPE_LINUX
118 Fw::Logger::logMsg(
"[WARNING] Setting CPU affinity is only available on Linux with glibc\n");
130 memset(&att,0,
sizeof(att));
133 I32 stat = pthread_attr_init(&att);
135 Fw::Logger::logMsg(
"pthread_attr_init: (%d): %s\n", stat,
reinterpret_cast<POINTER_CAST
>(strerror(stat)));
159 const char* message =
nullptr;
167 message =
"Invalid thread attributes specified";
171 message =
"Insufficient permissions to create thread. May not set thread priority without permission";
175 message =
"Unable to allocate thread. Increase thread ulimit.";
179 message =
"Unknown error";
183 (void)pthread_attr_destroy(&att);
185 (void)pthread_join(*tid,
nullptr);
188 Fw::Logger::logMsg(
"pthread_create: %s. %s\n",
reinterpret_cast<POINTER_CAST
>(message),
reinterpret_cast<POINTER_CAST
>(strerror(stat)));
194 Task::Task() : m_handle(reinterpret_cast<POINTER_CAST>(nullptr)), m_identifier(0), m_affinity(-1), m_started(false), m_suspendedOnPurpose(false), m_routineWrapper() {
200 this->m_name =
"TP_";
201 this->m_name += name;
202 this->m_identifier = identifier;
204 this->m_routineWrapper.routine = routine;
205 this->m_routineWrapper.arg = arg;
209 TaskStatus status =
create_pthread(priority, stackSize, cpuAffinity, tid, &this->m_routineWrapper,
true);
211 if (status == TASK_ERROR_PERMISSION) {
213 Fw::Logger::logMsg(
"[WARNING] Insufficient permissions to set task priority or set task CPU affinity on task %s. Creating task without priority nor affinity.\n",
reinterpret_cast<POINTER_CAST
>(m_name.toChar()));
214 Fw::Logger::logMsg(
"[WARNING] Please use no-argument <component>.start() calls, set priority/affinity to TASK_DEFAULT or ensure user has correct permissions for operating system.\n");
215 Fw::Logger::logMsg(
"[WARNING] Note: future releases of fprime will fail when setting priority/affinity without sufficient permissions \n");
217 status =
create_pthread(priority, stackSize, cpuAffinity, tid, &this->m_routineWrapper,
false);
220 if (status != TASK_OK) {
226 this->m_handle =
reinterpret_cast<POINTER_CAST
>(tid);
229 if (Task::s_taskRegistry) {
230 Task::s_taskRegistry->addTask(
this);
239 time1.tv_sec = milliseconds/1000;
240 time1.tv_nsec = (milliseconds%1000)*1000000;
246 timespec* sleepTimePtr = &time1;
247 timespec* remTimePtr = &time2;
250 int stat = nanosleep(sleepTimePtr,remTimePtr);
254 if (EINTR == errno) {
255 timespec* temp = remTimePtr;
256 remTimePtr = sleepTimePtr;
260 return TASK_DELAY_ERROR;
269 if (this->m_handle) {
270 delete reinterpret_cast<pthread_t*
>(this->m_handle);
273 if (Task::s_taskRegistry) {
274 Task::s_taskRegistry->removeTask(
this);
282 void Task::suspend(
bool onPurpose) {
286 void Task::resume() {
290 bool Task::isSuspended() {
302 if (!(this->m_handle)) {
303 return TASK_JOIN_ERROR;
305 stat = pthread_join(*
reinterpret_cast<pthread_t*
>(this->m_handle), value_ptr);
308 return TASK_JOIN_ERROR;