diff --git a/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.cpp b/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.cpp index 341557a32d..bfa4000903 100644 --- a/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.cpp +++ b/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.cpp @@ -401,8 +401,7 @@ namespace Drv { startReadThread(NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, NATIVE_INT_TYPE cpuAffinity) { Os::TaskString task("SerReader"); - Os::Task::TaskStatus stat = this->m_readTask.start(task, 0, priority, stackSize, - serialReadTaskEntry, this, cpuAffinity); + Os::Task::TaskStatus stat = this->m_readTask.start(task, serialReadTaskEntry, this, priority, stackSize, cpuAffinity); FW_ASSERT(stat == Os::Task::TASK_OK, stat); } diff --git a/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.hpp b/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.hpp index 47977b2c38..7be2f1d3ba 100644 --- a/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.hpp +++ b/Drv/LinuxSerialDriver/LinuxSerialDriverComponentImpl.hpp @@ -70,7 +70,7 @@ namespace Drv { //! start the serial poll thread. //! buffSize is the max receive buffer size //! - void startReadThread(NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, NATIVE_INT_TYPE cpuAffinity = -1); + void startReadThread(NATIVE_INT_TYPE priority = -1, NATIVE_INT_TYPE stackSize = -1, NATIVE_INT_TYPE cpuAffinity = -1); //! Quit thread void quitReadThread(void); diff --git a/Drv/SocketIpDriver/SocketIpDriverComponentImpl.cpp b/Drv/SocketIpDriver/SocketIpDriverComponentImpl.cpp index 0dec97c436..0c64491100 100644 --- a/Drv/SocketIpDriver/SocketIpDriverComponentImpl.cpp +++ b/Drv/SocketIpDriver/SocketIpDriverComponentImpl.cpp @@ -112,8 +112,7 @@ namespace Drv { Fw::Logger::logMsg("Unable to open socket: %d\n",stat); } } - Os::Task::TaskStatus stat = m_recvTask.start(name, 0, priority, stack, - SocketIpDriverComponentImpl::readTask, this, cpuAffinity); + Os::Task::TaskStatus stat = m_recvTask.start(name, SocketIpDriverComponentImpl::readTask, this, priority, stack, cpuAffinity); FW_ASSERT(Os::Task::TASK_OK == stat, static_cast(stat)); } } diff --git a/Fw/Comp/ActiveComponentBase.cpp b/Fw/Comp/ActiveComponentBase.cpp index b80c0b5e54..e67acd151b 100644 --- a/Fw/Comp/ActiveComponentBase.cpp +++ b/Fw/Comp/ActiveComponentBase.cpp @@ -50,7 +50,13 @@ namespace Fw { #endif void ActiveComponentBase::start(NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, NATIVE_INT_TYPE cpuAffinity) { + this->start(static_cast(priority), static_cast(stackSize), + ((cpuAffinity == -1) ? Os::Task::TASK_DEFAULT : static_cast(cpuAffinity)), + static_cast(identifier)); + } + void ActiveComponentBase::start(NATIVE_UINT_TYPE priority_in, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE cpuAffinity, NATIVE_UINT_TYPE identifier) { + NATIVE_INT_TYPE priority = static_cast(priority_in); Os::TaskString taskName; #if FW_OBJECT_NAMES == 1 @@ -63,10 +69,11 @@ namespace Fw { // If running with the baremetal scheduler, use a variant of the task-loop that // does not loop internal, but waits for an external iteration call. #if FW_BAREMETAL_SCHEDULER == 1 - Os::Task::TaskStatus status = this->m_task.start(taskName, identifier, priority, stackSize, this->s_baseBareTask, this, cpuAffinity); + Os::Task::taskRoutine routine = this->s_baseBareTask; #else - Os::Task::TaskStatus status = this->m_task.start(taskName, this->s_baseTask, this, priority, stackSize, cpuAffinity, identifier); + Os::Task::taskRoutine routine = this->s_baseTask; #endif + Os::Task::TaskStatus status = this->m_task.start(taskName, routine, this, priority, stackSize, cpuAffinity, identifier); FW_ASSERT(status == Os::Task::TASK_OK,(NATIVE_INT_TYPE)status); } diff --git a/Fw/Comp/ActiveComponentBase.hpp b/Fw/Comp/ActiveComponentBase.hpp index 1a7376b2c5..bbc4d5783e 100644 --- a/Fw/Comp/ActiveComponentBase.hpp +++ b/Fw/Comp/ActiveComponentBase.hpp @@ -14,12 +14,15 @@ #include #include #include - +#include namespace Fw { class ActiveComponentBase : public QueuedComponentBase { public: - void start(NATIVE_INT_TYPE identifier = 0, NATIVE_INT_TYPE priority = -1, NATIVE_INT_TYPE stackSize = -1, NATIVE_INT_TYPE cpuAffinity = -1); //!< called by instantiator when task is to be started + void start(NATIVE_UINT_TYPE priority = Os::Task::TASK_DEFAULT, NATIVE_UINT_TYPE stackSize = Os::Task::TASK_DEFAULT, NATIVE_UINT_TYPE cpuAffinity = Os::Task::TASK_DEFAULT, NATIVE_UINT_TYPE identifier = Os::Task::TASK_DEFAULT); //!< called by instantiator when task is to be started + + DEPRECATED(void start(NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, NATIVE_INT_TYPE cpuAffinity = -1), + "Please switch to start(NATIVE_UINT_TYPE priority, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE cpuAffinity, NATIVE_UINT_TYPE identifier)"); //!< called by instantiator when task is to be started void exit(void); //!< exit task in active component Os::Task::TaskStatus join(void **value_ptr); //!< provide return value of thread if value_ptr is not NULL diff --git a/Fw/Deprecate.hpp b/Fw/Deprecate.hpp new file mode 100644 index 0000000000..c378a1c033 --- /dev/null +++ b/Fw/Deprecate.hpp @@ -0,0 +1,15 @@ +// deprecate.hpp: +// +// An minor implementation of compile-time deprecation for the fprime framework. + +#ifndef FW_DEPRECATE_HPP +#define FW_DEPRECATE_HPP + +#ifdef __GNUC__ + #define DEPRECATED(func, message) func __attribute__ ((deprecated(message))) +#else + #warning "No implementation of DEPRECATED for given compiler. Pleas check for use of DEPRECATED() functions" + #define DEPRECATED(func) func +#endif + +#endif // REF_DEPRECATE_HPP diff --git a/Os/Baremetal/Task.cpp b/Os/Baremetal/Task.cpp index c36fa9d10b..cfb20088f4 100644 --- a/Os/Baremetal/Task.cpp +++ b/Os/Baremetal/Task.cpp @@ -13,7 +13,7 @@ Task::Task() : m_suspendedOnPurpose(false) {} -Task::TaskStatus Task::start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void* arg, NATIVE_INT_TYPE cpuAffinity) { +Task::TaskStatus Task::start(const Fw::StringBase &name, taskRoutine routine, void* arg, NATIVE_UINT_TYPE priority, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE cpuAffinity, NATIVE_UINT_TYPE identifier) { //Get a task handle, and set it up BareTaskHandle* handle = new BareTaskHandle(); if (handle == NULL) { diff --git a/Os/Posix/Task.cpp b/Os/Posix/Task.cpp index db2f06797b..1c20e8f9a2 100644 --- a/Os/Posix/Task.cpp +++ b/Os/Posix/Task.cpp @@ -6,10 +6,14 @@ #include #include +#include #include #include #include #include +#include + +static const NATIVE_INT_TYPE SCHED_POLICY = SCHED_RR; typedef void* (*pthread_func_ptr)(void*); @@ -24,27 +28,33 @@ void* pthread_entry_wrapper(void* arg) { namespace Os { void validate_arguments(NATIVE_INT_TYPE& priority, NATIVE_INT_TYPE& stack, NATIVE_INT_TYPE& affinity, bool expect_perm) { + const NATIVE_INT_TYPE min_priority = sched_get_priority_min(SCHED_POLICY); + const NATIVE_INT_TYPE max_priority = sched_get_priority_max(SCHED_POLICY); + // Check to ensure that these calls worked + if (min_priority == -1 or max_priority == -1) { + Fw::Logger::logMsg("[WARNING] Unable to determine min/max priority with error %s. Discarding priority. ", reinterpret_cast(strerror(errno))); + } // Check priority attributes if (!expect_perm and priority != -1) { - Fw::Logger::logMsg("[WARNING] task priority set and permissions unavailable. Discarding priority.\n"); + Fw::Logger::logMsg("[WARNING] Task priority set and permissions unavailable. Discarding priority.\n"); priority = -1; } - if (priority != -1 and priority < 1) { - Fw::Logger::logMsg("[WARNING] low task priority of %d being clamped to 1\n", priority); - priority = 1; + if (priority != -1 and priority < min_priority) { + Fw::Logger::logMsg("[WARNING] Low task priority of %d being clamped to %d\n", priority, min_priority); + priority = min_priority; } - if (priority != -1 and priority > 99) { - Fw::Logger::logMsg("[WARNING] high task priority of %d being clamped to 99\n", priority); - priority = 99; + if (priority != -1 and priority > max_priority) { + Fw::Logger::logMsg("[WARNING] High task priority of %d being clamped to %d\n", priority, max_priority); + priority = max_priority; } // Check the stack if (stack != -1 and stack < PTHREAD_STACK_MIN) { - Fw::Logger::logMsg("[WARNING] stack size %d too small, setting to minimum of %d\n", stack, PTHREAD_STACK_MIN); + Fw::Logger::logMsg("[WARNING] Stack size %d too small, setting to minimum of %d\n", stack, PTHREAD_STACK_MIN); stack = PTHREAD_STACK_MIN; } // Check CPU affinity if (!expect_perm and affinity != -1) { - Fw::Logger::logMsg("[WARNING] cpu affinity set and permissions unavailable. Discarding affinity.\n"); + Fw::Logger::logMsg("[WARNING] Cpu affinity set and permissions unavailable. Discarding affinity.\n"); affinity = -1; } } @@ -63,7 +73,7 @@ namespace Os { Task::TaskStatus set_priority_params(pthread_attr_t& att, NATIVE_INT_TYPE priority) { if (priority != -1) { - I32 stat = pthread_attr_setschedpolicy(&att, SCHED_FIFO); + I32 stat = pthread_attr_setschedpolicy(&att, SCHED_POLICY); if (stat != 0) { Fw::Logger::logMsg("pthread_attr_setschedpolicy: %s\n", reinterpret_cast(strerror(stat))); return Task::TASK_INVALID_PARAMS; @@ -90,6 +100,7 @@ namespace Os { Task::TaskStatus set_cpu_affinity(pthread_attr_t& att, NATIVE_INT_TYPE cpuAffinity) { if (cpuAffinity != -1) { +#ifdef TGT_OS_TYPE_LINUX cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(cpuAffinity, &cpuset); @@ -100,6 +111,9 @@ namespace Os { reinterpret_cast(strerror(stat))); return Task::TASK_INVALID_PARAMS; } +#else + Fw::Logger::logMsg("[WARNING] Setting CPU affinity is only available on Linux\n"); +#endif } return Task::TASK_OK; } @@ -174,7 +188,7 @@ namespace Os { Task::Task() : m_handle(0), m_identifier(0), m_affinity(-1), m_started(false), m_suspendedOnPurpose(false), m_routineWrapper() { } - Task::TaskStatus Task::start(const Fw::StringBase &name, taskRoutine routine, void* arg, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, NATIVE_INT_TYPE cpuAffinity, NATIVE_INT_TYPE identifier) { + Task::TaskStatus Task::start(const Fw::StringBase &name, taskRoutine routine, void* arg, NATIVE_UINT_TYPE priority, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE cpuAffinity, NATIVE_UINT_TYPE identifier) { FW_ASSERT(routine); this->m_name = "TP_"; @@ -186,13 +200,13 @@ namespace Os { pthread_t* tid; // Try to create a permissioned thread - TaskStatus status = create_pthread(priority, stackSize, cpuAffinity, tid, &this->m_routineWrapper, true); + TaskStatus status = create_pthread(static_cast(priority), static_cast(stackSize), static_cast(cpuAffinity), tid, &this->m_routineWrapper, true); // Failure dur to permission automatically retried if (status == TASK_ERROR_PERMISSION) { Fw::Logger::logMsg("[WARNING] Insufficient permissions to create a prioritized tasks or specify CPU affinities. Attempting to fallback to tasks without priority.\n"); Fw::Logger::logMsg("[WARNING] Please use no-argument .start() calls or ensure executing user has correct permissions for your operating system.\n"); Fw::Logger::logMsg("[WARNING] Note: this fallback to tasks without priority will be removed and will fail in future fprime releases.\n"); - status = create_pthread(priority, stackSize, cpuAffinity, tid, &this->m_routineWrapper, false); // Fallback with no permission + status = create_pthread(static_cast(priority), static_cast(stackSize), static_cast(cpuAffinity), tid, &this->m_routineWrapper, false); // Fallback with no permission } // Check for non-zero error code if (status != TASK_OK) { diff --git a/Os/Posix/TaskRoot.cpp b/Os/Posix/TaskRoot.cpp deleted file mode 100644 index a9f6689ebd..0000000000 --- a/Os/Posix/TaskRoot.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#include -#include - - -#ifdef TGT_OS_TYPE_VXWORKS - #include - #include // need it for VX_FP_TASK -#else - #include - #include -#endif - -#include - -#include -#include -#include -#include -#include - -//#define DEBUG_PRINT(x,...) Fw::Logger::logMsg(x,##__VA_ARGS__); -#define DEBUG_PRINT(x,...) - -typedef void* (*pthread_func_ptr)(void*); - -namespace Os { - Task::Task() : m_handle(0), m_identifier(0), m_affinity(-1), m_started(false), m_suspendedOnPurpose(false) { - } - - Task::TaskStatus Task::start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void* arg, NATIVE_INT_TYPE cpuAffinity) { - - // for linux, task names can only be of length 15, so just setting it to the name: - this->m_name = name; - this->m_identifier = identifier; - - Task::TaskStatus tStat = TASK_OK; - - pthread_attr_t att; - // clear att; can cause issues - memset(&att,0,sizeof(att)); - - I32 stat = pthread_attr_init(&att); - if (stat != 0) { - Fw::Logger::logMsg("pthread_attr_init: (%d)(%d): %s\n",stat,errno,strerror(stat)); - return TASK_INVALID_PARAMS; - } - - stat = pthread_attr_setstacksize(&att,stackSize); - if (stat != 0) { - return TASK_INVALID_STACK; - } - - stat = pthread_attr_setschedpolicy(&att,SCHED_RR); - - if (stat != 0) { - Fw::Logger::logMsg("pthread_attr_setschedpolicy: %s\n",strerror(errno)); - return TASK_INVALID_PARAMS; - } - stat = pthread_attr_setinheritsched(&att,PTHREAD_EXPLICIT_SCHED); // may not need this - if (stat != 0) { - Fw::Logger::logMsg("pthread_attr_setinheritsched: %s\n",strerror(errno)); - return TASK_INVALID_PARAMS; - } - sched_param schedParam; - memset(&schedParam,0,sizeof(sched_param)); - schedParam.sched_priority = priority; - stat = pthread_attr_setschedparam(&att,&schedParam); - if (stat != 0) { - Fw::Logger::logMsg("pthread_attr_setschedparam: %s\n",strerror(errno)); - return TASK_INVALID_PARAMS; - } - - // Set affinity before creating thread: - if (cpuAffinity != -1) { - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(cpuAffinity,&cpuset); - - stat = pthread_attr_setaffinity_np(&att, sizeof(cpu_set_t), &cpuset); - if (stat != 0) { - Fw::Logger::logMsg("pthread_setaffinity_np: %i %s\n",cpuAffinity,strerror(stat)); - return TASK_INVALID_PARAMS; - } - } - - // If a registry has been registered, register task - if (Task::s_taskRegistry) { - Task::s_taskRegistry->addTask(this); - } - - pthread_t* tid = new pthread_t; - - stat = pthread_create(tid,&att,(pthread_func_ptr)routine,arg); - - switch (stat) { - case 0: - this->m_handle = (POINTER_CAST)tid; - Task::s_numTasks++; - break; - case EINVAL: - delete tid; - Fw::Logger::logMsg("pthread_create: %s\n",strerror(errno)); - tStat = TASK_INVALID_PARAMS; - break; - default: - delete tid; - tStat = TASK_UNKNOWN_ERROR; - break; - } - - if (tStat == TASK_OK) { - - stat = pthread_setname_np(*tid,(char*)this->m_name.toChar()); - if (stat != 0) { - Fw::Logger::logMsg("pthread_setname_np: %s %s\n",this->m_name.toChar(),strerror(stat)); - delete tid; - tStat = TASK_INVALID_PARAMS; - } - } - - (void)pthread_attr_destroy(&att); - - return tStat; - } - - Task::TaskStatus Task::delay(NATIVE_UINT_TYPE milliseconds) - { - timespec time1; - - time1.tv_sec = milliseconds/1000; - time1.tv_nsec = (milliseconds%1000)*1000000; - - timespec time2; - time2.tv_sec = 0; - time2.tv_nsec = 0; - - timespec* sleepTimePtr = &time1; - timespec* remTimePtr = &time2; - - while (true) { - int stat = nanosleep(sleepTimePtr,remTimePtr); - if (0 == stat) { - return TASK_OK; - } else { // check errno - if (EINTR == errno) { // swap pointers - timespec* temp = remTimePtr; - remTimePtr = sleepTimePtr; - sleepTimePtr = temp; - continue; // if interrupted, just continue - } else { - return TASK_DELAY_ERROR; - } - } - } - - return TASK_OK; // for coverage analysis - - } - - - Task::~Task() { - if (this->m_handle) { - delete (pthread_t*)this->m_handle; - } - // If a registry has been registered, remove task - if (Task::s_taskRegistry) { - Task::s_taskRegistry->removeTask(this); - } - - } - - // FIXME: Need to find out how to do this for Posix threads - - void Task::suspend(bool onPurpose) { - FW_ASSERT(0); - } - - void Task::resume(void) { - FW_ASSERT(0); - } - - bool Task::isSuspended(void) { - FW_ASSERT(0); - return false; - } - - Task::TaskStatus Task::join(void **value_ptr) { - NATIVE_INT_TYPE stat = 0; - if (!(this->m_handle)) { - return TASK_JOIN_ERROR; - } - stat = pthread_join(*((pthread_t*) this->m_handle), value_ptr); - - if (stat != 0) { - DEBUG_PRINT("join: %s\n", strerror(errno)); - return TASK_JOIN_ERROR; - } - else { - return TASK_OK; - } - } -} diff --git a/Os/Task.hpp b/Os/Task.hpp index 580c35680d..80ee6fb2a3 100644 --- a/Os/Task.hpp +++ b/Os/Task.hpp @@ -7,13 +7,15 @@ #include #include +#include +#include namespace Os { class TaskRegistry; //!< forward declaration class Task { public: - + static const NATIVE_UINT_TYPE TASK_DEFAULT; typedef enum { TASK_OK, //!< message sent/received okay TASK_INVALID_PARAMS, //!< started task with invalid parameters @@ -35,9 +37,12 @@ namespace Os { Task(); //!< constructor virtual ~Task(); //!< destructor - // Priority is based on Posix priorities - 0 lowest, 255 highest - TaskStatus start(const Fw::StringBase &name, taskRoutine routine, void* arg, NATIVE_INT_TYPE priority = -1, NATIVE_INT_TYPE stackSize = -1, NATIVE_INT_TYPE cpuAffinity = -1, NATIVE_INT_TYPE identifier = -1); //!< start the task - TaskStatus start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void* arg, NATIVE_INT_TYPE cpuAffinity = -1); //!< start the task + + TaskStatus start(const Fw::StringBase &name, taskRoutine routine, void* arg, NATIVE_UINT_TYPE priority = TASK_DEFAULT, NATIVE_UINT_TYPE stackSize = TASK_DEFAULT, NATIVE_UINT_TYPE cpuAffinity = TASK_DEFAULT, NATIVE_UINT_TYPE identifier = TASK_DEFAULT); //!< start the task + + // Deprecated: only the name, routine, and argument are **required** parameters. This ordering of parameters is therefore inappropriate and will be removed in the future + DEPRECATED(TaskStatus start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void* arg, NATIVE_INT_TYPE cpuAffinity = TASK_DEFAULT), + "Please switch to start(Fw::StringBase &name, taskRoutine routine, void* arg, NATIVE_UINT_TYPE priority, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE cpuAffinity, NATIVE_UINT_TYPE identifier)"); //!< start the task I32 getIdentifier(void); //!< get the identifier for the task static TaskId getOsIdentifier(void); //Gets the Os Task ID. Useful for passive components. diff --git a/Os/TaskCommon.cpp b/Os/TaskCommon.cpp index 0b31d18968..d973fa3219 100644 --- a/Os/TaskCommon.cpp +++ b/Os/TaskCommon.cpp @@ -2,8 +2,10 @@ #include #include #include +#include namespace Os { + const NATIVE_UINT_TYPE Task::TASK_DEFAULT = std::numeric_limits::max(); TaskRegistry* Task::s_taskRegistry = 0; NATIVE_INT_TYPE Task::s_numTasks = 0; @@ -43,8 +45,6 @@ namespace Os { } Task::TaskStatus Task::start(const Fw::StringBase &name, NATIVE_INT_TYPE identifier, NATIVE_INT_TYPE priority, NATIVE_INT_TYPE stackSize, taskRoutine routine, void* arg, NATIVE_INT_TYPE cpuAffinity) { - Fw::Logger::logMsg("[WARNING] Os::Task.start(name, identifier, priority, stackSize, routine, arg, cpuAffinity) is deprecated.\n"); - Fw::Logger::logMsg("[WARNING] Please migrate to the form: Os::Task.start(name, routine, arg, priority, stackSize, cpuAffinity, identifier).\n"); return this->start(name, routine, arg, priority, stackSize, cpuAffinity, identifier); }