implemented deadlien missed print for host
This commit is contained in:
parent
078116c7be
commit
e3c44fd27f
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <processthreadsapi.h>
|
#include <processthreadsapi.h>
|
||||||
|
#include <fsfw/osal/windows/winTaskHelpers.h>
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
@ -22,33 +23,11 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority,
|
|||||||
// It is propably possible to set task priorities by using the native
|
// It is propably possible to set task priorities by using the native
|
||||||
// task handles for Windows / Linux
|
// task handles for Windows / Linux
|
||||||
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
|
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
|
||||||
#if defined(WIN32)
|
#if defined(_WIN32)
|
||||||
/* List of possible priority classes:
|
tasks::setTaskPriority(reinterpret_cast<HANDLE>(mainThread.native_handle()), setPriority);
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/
|
tasks::insertTaskName(mainThread.get_id(), taskName);
|
||||||
* nf-processthreadsapi-setpriorityclass
|
#elif defined(__unix__)
|
||||||
* And respective thread priority numbers:
|
// TODO: We could reuse existing code here.
|
||||||
* https://docs.microsoft.com/en-us/windows/
|
|
||||||
* win32/procthread/scheduling-priorities */
|
|
||||||
int result = SetPriorityClass(
|
|
||||||
reinterpret_cast<HANDLE>(mainThread.native_handle()),
|
|
||||||
ABOVE_NORMAL_PRIORITY_CLASS);
|
|
||||||
if(result != 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
|
|
||||||
<< GetLastError() << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
result = SetThreadPriority(
|
|
||||||
reinterpret_cast<HANDLE>(mainThread.native_handle()),
|
|
||||||
THREAD_PRIORITY_NORMAL);
|
|
||||||
if(result != 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
|
|
||||||
<< GetLastError() << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#elif defined(LINUX)
|
|
||||||
// we can just copy and paste the code from linux here.
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
|
#include "../../tasks/TaskFactory.h"
|
||||||
#include "../../osal/host/FixedTimeslotTask.h"
|
#include "../../osal/host/FixedTimeslotTask.h"
|
||||||
#include "../../osal/host/PeriodicTask.h"
|
#include "../../osal/host/PeriodicTask.h"
|
||||||
#include "../../tasks/TaskFactory.h"
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#include "../windows/winTaskHelpers.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||||
|
|
||||||
// Will propably not be used for hosted implementation
|
// Not used for the host implementation for now because C++ thread abstraction is used
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
||||||
|
|
||||||
TaskFactory::TaskFactory() {
|
TaskFactory::TaskFactory() {
|
||||||
@ -49,8 +55,33 @@ ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TaskFactory::printMissedDeadline() {
|
void TaskFactory::printMissedDeadline() {
|
||||||
/* TODO: Implement */
|
#ifdef __unix__
|
||||||
return;
|
char name[20] = {0};
|
||||||
|
int status = pthread_getname_np(pthread_self(), name, sizeof(name));
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
if(status == 0) {
|
||||||
|
sif::warning << "TaskFactory::printMissedDeadline: " << name << "" << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::warning << "TaskFactory::printMissedDeadline: Unknown task name" << status <<
|
||||||
|
std::endl;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(status == 0) {
|
||||||
|
sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::printWarning("TaskFactory::printMissedDeadline: Unknown task name\n", name);
|
||||||
|
}
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
std::string name = tasks::getTaskName(std::this_thread::get_id());
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "TaskFactory::printMissedDeadline: " << name << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name);
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
#endif /* defined(_WIN32) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_):
|
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_):
|
||||||
thread(0),priority(priority_),stackSize(stackSize_) {
|
thread(0), priority(priority_), stackSize(stackSize_) {
|
||||||
name[0] = '\0';
|
name[0] = '\0';
|
||||||
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
|
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
|
||||||
}
|
}
|
||||||
@ -75,18 +75,18 @@ bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
|
|||||||
|
|
||||||
if (currentTime_ms < *prevoiusWakeTime_ms) {
|
if (currentTime_ms < *prevoiusWakeTime_ms) {
|
||||||
/* The tick count has overflowed since this function was
|
/* The tick count has overflowed since this function was
|
||||||
lasted called. In this case the only time we should ever
|
lasted called. In this case the only time we should ever
|
||||||
actually delay is if the wake time has also overflowed,
|
actually delay is if the wake time has also overflowed,
|
||||||
and the wake time is greater than the tick time. When this
|
and the wake time is greater than the tick time. When this
|
||||||
is the case it is as if neither time had overflowed. */
|
is the case it is as if neither time had overflowed. */
|
||||||
if ((nextTimeToWake_ms < *prevoiusWakeTime_ms)
|
if ((nextTimeToWake_ms < *prevoiusWakeTime_ms)
|
||||||
&& (nextTimeToWake_ms > currentTime_ms)) {
|
&& (nextTimeToWake_ms > currentTime_ms)) {
|
||||||
shouldDelay = true;
|
shouldDelay = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* The tick time has not overflowed. In this case we will
|
/* The tick time has not overflowed. In this case we will
|
||||||
delay if either the wake time has overflowed, and/or the
|
delay if either the wake time has overflowed, and/or the
|
||||||
tick time is less than the wake time. */
|
tick time is less than the wake time. */
|
||||||
if ((nextTimeToWake_ms < *prevoiusWakeTime_ms)
|
if ((nextTimeToWake_ms < *prevoiusWakeTime_ms)
|
||||||
|| (nextTimeToWake_ms > currentTime_ms)) {
|
|| (nextTimeToWake_ms > currentTime_ms)) {
|
||||||
shouldDelay = true;
|
shouldDelay = true;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
tcpipHelpers.cpp
|
tcpipHelpers.cpp
|
||||||
|
winTaskHelpers.cpp
|
||||||
)
|
)
|
||||||
|
130
osal/windows/winTaskHelpers.cpp
Normal file
130
osal/windows/winTaskHelpers.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include <fsfw/osal/windows/winTaskHelpers.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
std::mutex nameMapLock;
|
||||||
|
std::map<std::thread::id, std::string> taskNameMap;
|
||||||
|
|
||||||
|
TaskPriority tasks::makeWinPriority(PriorityClass prioClass, PriorityNumber prioNumber) {
|
||||||
|
return (static_cast<uint16_t>(prioClass) << 16) | static_cast<uint16_t> (prioNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tasks::getWinPriorityParameters(TaskPriority priority,
|
||||||
|
DWORD& priorityClass, int& priorityNumber) {
|
||||||
|
PriorityClass classInternal = static_cast<PriorityClass>(priority >> 16 & 0xff);
|
||||||
|
PriorityNumber numberInternal = static_cast<PriorityNumber>(priority & 0xff);
|
||||||
|
switch(classInternal) {
|
||||||
|
case(CLASS_IDLE): {
|
||||||
|
priorityClass = IDLE_PRIORITY_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(CLASS_BELOW_NORMAL): {
|
||||||
|
priorityClass = BELOW_NORMAL_PRIORITY_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(CLASS_NORMAL): {
|
||||||
|
priorityClass = NORMAL_PRIORITY_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(CLASS_ABOVE_NORMAL): {
|
||||||
|
priorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(CLASS_HIGH): {
|
||||||
|
priorityClass = HIGH_PRIORITY_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(CLASS_REALTIME): {
|
||||||
|
priorityClass = REALTIME_PRIORITY_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
priorityClass = NORMAL_PRIORITY_CLASS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(numberInternal) {
|
||||||
|
case(IDLE): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(LOWEST): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_LOWEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(BELOW_NORMAL): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_BELOW_NORMAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(NORMAL): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_NORMAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(ABOVE_NORMAL): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(HIGHEST): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_HIGHEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(CRITICAL): {
|
||||||
|
priorityNumber = THREAD_PRIORITY_TIME_CRITICAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
priorityNumber = THREAD_PRIORITY_NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t tasks::setTaskPriority(HANDLE nativeHandle, TaskPriority priority) {
|
||||||
|
/* List of possible priority classes:
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass
|
||||||
|
And respective thread priority numbers:
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities
|
||||||
|
*/
|
||||||
|
DWORD dwPriorityClass = 0;
|
||||||
|
int nPriorityNumber = 0;
|
||||||
|
tasks::getWinPriorityParameters(priority, dwPriorityClass, nPriorityNumber);
|
||||||
|
int result = SetPriorityClass(
|
||||||
|
reinterpret_cast<HANDLE>(nativeHandle),
|
||||||
|
dwPriorityClass);
|
||||||
|
if(result != 0) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
|
||||||
|
<< GetLastError() << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
result = SetThreadPriority(
|
||||||
|
reinterpret_cast<HANDLE>(nativeHandle),
|
||||||
|
nPriorityNumber);
|
||||||
|
if(result != 0) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
|
||||||
|
<< GetLastError() << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) {
|
||||||
|
std::lock_guard<std::mutex> lg(nameMapLock);
|
||||||
|
auto returnPair = taskNameMap.emplace(threadId, taskName);
|
||||||
|
if(not returnPair.second) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tasks::getTaskName(std::thread::id threadId) {
|
||||||
|
std::lock_guard<std::mutex> lg(nameMapLock);
|
||||||
|
auto resultIter = taskNameMap.find(threadId);
|
||||||
|
if(resultIter != taskNameMap.end()) {
|
||||||
|
return resultIter->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "Unknown task";
|
||||||
|
}
|
||||||
|
}
|
40
osal/windows/winTaskHelpers.h
Normal file
40
osal/windows/winTaskHelpers.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "../../tasks/TaskFactory.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
namespace tasks {
|
||||||
|
|
||||||
|
enum PriorityClass: uint16_t {
|
||||||
|
CLASS_IDLE,
|
||||||
|
CLASS_BELOW_NORMAL,
|
||||||
|
CLASS_NORMAL,
|
||||||
|
CLASS_ABOVE_NORMAL,
|
||||||
|
CLASS_HIGH,
|
||||||
|
CLASS_REALTIME
|
||||||
|
};
|
||||||
|
enum PriorityNumber: uint16_t {
|
||||||
|
IDLE,
|
||||||
|
LOWEST,
|
||||||
|
BELOW_NORMAL,
|
||||||
|
NORMAL,
|
||||||
|
ABOVE_NORMAL,
|
||||||
|
HIGHEST,
|
||||||
|
CRITICAL
|
||||||
|
};
|
||||||
|
TaskPriority makeWinPriority(PriorityClass prioClass = PriorityClass::CLASS_NORMAL,
|
||||||
|
PriorityNumber prioNumber = PriorityNumber::NORMAL);
|
||||||
|
void getWinPriorityParameters(TaskPriority priority, DWORD& priorityClass,
|
||||||
|
int& priorityNumber);
|
||||||
|
|
||||||
|
ReturnValue_t setTaskPriority(HANDLE nativeHandle, TaskPriority priority);
|
||||||
|
|
||||||
|
ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName);
|
||||||
|
std::string getTaskName(std::thread::id threadId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -22,9 +22,23 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Creates a new periodic task and returns the interface pointer.
|
* Creates a new periodic task and returns the interface pointer.
|
||||||
* @param name_ Name of the task
|
* @param name_ Name of the task
|
||||||
* @param taskPriority_ Priority of the task
|
* @param taskPriority_
|
||||||
|
* Priority of the task. This value might have different ranges for the various OSALs.
|
||||||
|
* Linux: Value ranging from 0 to 99 with 99 being the highest value.
|
||||||
|
* Host: Value can be retrieved by using the #tasks::makeWinPriority function.
|
||||||
|
* FreeRTOS: Value depends on the FreeRTOS configuration, higher number means higher priority
|
||||||
|
* RTEMS: Values ranging from 0 to 99 with 99 being the highest value.
|
||||||
|
*
|
||||||
* @param stackSize_ Stack Size of the task
|
* @param stackSize_ Stack Size of the task
|
||||||
|
* This value might have different recommended ranges for the various OSALs.
|
||||||
|
* Linux: Lowest limit is the PeriodicTaskIF::MINIMUM_STACK_SIZE value
|
||||||
|
* Host: Value is ignored for now because the C++ threading abstraction layer is used.
|
||||||
|
* FreeRTOS: Stack size in bytes. It is recommended to specify at least 1kB of stack for
|
||||||
|
* FSFW tasks, but the lowest possible size is specified in the FreeRTOSConfig.h file.
|
||||||
|
* RTEMS: Lowest limit is the PeriodicTaskIF::MINIMUM_STACK_SIZE value.
|
||||||
|
*
|
||||||
* @param period_ Period of the task
|
* @param period_ Period of the task
|
||||||
|
*
|
||||||
* @param deadLineMissedFunction_ Function to be called if a deadline was missed
|
* @param deadLineMissedFunction_ Function to be called if a deadline was missed
|
||||||
* @return PeriodicTaskIF* Pointer to the newly created Task
|
* @return PeriodicTaskIF* Pointer to the newly created Task
|
||||||
*/
|
*/
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define FRAMEWORK_TASKS_TYPEDEF_H_
|
#define FRAMEWORK_TASKS_TYPEDEF_H_
|
||||||
|
|
||||||
typedef const char* TaskName;
|
typedef const char* TaskName;
|
||||||
typedef uint8_t TaskPriority;
|
typedef uint32_t TaskPriority;
|
||||||
typedef size_t TaskStackSize;
|
typedef size_t TaskStackSize;
|
||||||
typedef double TaskPeriod;
|
typedef double TaskPeriod;
|
||||||
typedef void (*TaskDeadlineMissedFunction)();
|
typedef void (*TaskDeadlineMissedFunction)();
|
||||||
|
Loading…
Reference in New Issue
Block a user