14#ifdef TGT_OS_TYPE_LINUX
20typedef 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);
79 I32 stat = pthread_attr_setschedpolicy(&att,
SCHED_POLICY);
85 stat = pthread_attr_setinheritsched(&att, PTHREAD_EXPLICIT_SCHED);
92 sched_param schedParam;
93 memset(&schedParam, 0,
sizeof(sched_param));
94 schedParam.sched_priority = priority;
95 stat = pthread_attr_setschedparam(&att, &schedParam);
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);
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);
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);
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) {
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;
PlatformPointerCastType POINTER_CAST
PlatformIntType NATIVE_INT_TYPE
PlatformUIntType NATIVE_UINT_TYPE
void * pthread_entry_wrapper(void *arg)
static const NATIVE_INT_TYPE SCHED_POLICY
static void logMsg(const char *fmt, POINTER_CAST a0=0, POINTER_CAST a1=0, POINTER_CAST a2=0, POINTER_CAST a3=0, POINTER_CAST a4=0, POINTER_CAST a5=0, POINTER_CAST a6=0, POINTER_CAST a7=0, POINTER_CAST a8=0, POINTER_CAST a9=0)
static const NATIVE_UINT_TYPE TASK_DEFAULT
@ TASK_ERROR_PERMISSION
permissions error setting-up tasks
@ TASK_OK
message sent/received okay
@ TASK_INVALID_STACK
started with invalid stack size
@ TASK_INVALID_PARAMS
started task with invalid parameters
@ TASK_ERROR_RESOURCES
unable to allocate more tasks
@ TASK_UNKNOWN_ERROR
unexpected error return value
void validate_arguments(NATIVE_UINT_TYPE &priority, NATIVE_UINT_TYPE &stack, NATIVE_UINT_TYPE &affinity, bool expect_perm)
Task::TaskStatus set_cpu_affinity(pthread_attr_t &att, NATIVE_UINT_TYPE cpuAffinity)
Task::TaskStatus set_stack_size(pthread_attr_t &att, NATIVE_UINT_TYPE stack)
Task::TaskStatus set_priority_params(pthread_attr_t &att, NATIVE_UINT_TYPE priority)
Task::TaskStatus create_pthread(NATIVE_UINT_TYPE priority, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE cpuAffinity, pthread_t *&tid, void *arg, bool expect_perm)
taskRoutine routine
contains the task entrypoint
void * arg
contains the task entrypoint pointer