1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00
LibrePilot/flight/pios/common/pios_task_monitor.c
2014-06-11 22:15:40 +02:00

180 lines
5.2 KiB
C

/**
******************************************************************************
* @addtogroup OpenPilotSystem OpenPilot System
* @{
* @addtogroup OpenPilotLibraries OpenPilot System Libraries
* @{
* @file pios_task_monitor.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Task monitoring functions
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pios.h>
#ifdef PIOS_INCLUDE_TASK_MONITOR
// Private variables
static xSemaphoreHandle mLock;
static xTaskHandle *mTaskHandles;
static uint32_t mLastMonitorTime;
static uint32_t mLastIdleMonitorTime;
static uint16_t mMaxTasks;
/**
* Initialize the Task Monitor
*/
int32_t PIOS_TASK_MONITOR_Initialize(uint16_t max_tasks)
{
mLock = xSemaphoreCreateRecursiveMutex();
if (!mLock) {
return -1;
}
mTaskHandles = (xTaskHandle *)pios_malloc(max_tasks * sizeof(xTaskHandle));
if (!mTaskHandles) {
return -1;
}
memset(mTaskHandles, 0, max_tasks * sizeof(xTaskHandle));
mMaxTasks = max_tasks;
#if (configGENERATE_RUN_TIME_STATS == 1)
mLastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
mLastIdleMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
#else
mLastMonitorTime = 0;
mLastIdleMonitorTime = 0;
#endif
return 0;
}
/**
* Register a task handle
*/
int32_t PIOS_TASK_MONITOR_RegisterTask(uint16_t task_id, xTaskHandle handle)
{
if (mTaskHandles && task_id < mMaxTasks) {
xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
mTaskHandles[task_id] = handle;
xSemaphoreGiveRecursive(mLock);
return 0;
} else {
return -1;
}
}
/**
* Unregister a task handle
*/
int32_t PIOS_TASK_MONITOR_UnregisterTask(uint16_t task_id)
{
if (mTaskHandles && task_id < mMaxTasks) {
xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
mTaskHandles[task_id] = 0;
xSemaphoreGiveRecursive(mLock);
return 0;
} else {
return -1;
}
}
/**
* Query if a task is running
*/
bool PIOS_TASK_MONITOR_IsRunning(uint16_t task_id)
{
return mTaskHandles && task_id <= mMaxTasks && mTaskHandles[task_id];
}
/**
* Tell the caller the status of all tasks via a task-by-task callback
*/
void PIOS_TASK_MONITOR_ForEachTask(TaskMonitorTaskInfoCallback callback, void *context)
{
if (!mTaskHandles) {
return;
}
xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
#if (configGENERATE_RUN_TIME_STATS == 1)
/* Calculate the amount of elapsed run time between the last time we
* measured and now. Scale so that we can convert task run times
* directly to percentages. */
uint32_t currentTime = portGET_RUN_TIME_COUNTER_VALUE();
/* avoid divide-by-zero if the interval is too small */
uint32_t deltaTime = ((currentTime - mLastMonitorTime) / 100) ? : 1;
mLastMonitorTime = currentTime;
#endif
/* Update all task information */
for (uint16_t n = 0; n < mMaxTasks; ++n) {
struct pios_task_info info;
if (mTaskHandles[n]) {
info.is_running = true;
#if defined(ARCH_POSIX) || defined(ARCH_WIN32)
info.stack_remaining = 10000;
#else
info.stack_remaining = uxTaskGetStackHighWaterMark(mTaskHandles[n]) * 4;
#endif
#if (configGENERATE_RUN_TIME_STATS == 1)
/* Generate run time percentage stats */
info.running_time_percentage = uxTaskGetRunTime(mTaskHandles[n]) / deltaTime;
#else
info.running_time_percentage = 0;
#endif
} else {
info.is_running = false;
info.stack_remaining = 0;
info.running_time_percentage = 0;
}
/* Pass the information for this task back to the caller */
callback(n, &info, context);
}
xSemaphoreGiveRecursive(mLock);
}
uint8_t PIOS_TASK_MONITOR_GetIdlePercentage()
{
#if defined(ARCH_POSIX) || defined(ARCH_WIN32)
return 50;
#elif (configGENERATE_RUN_TIME_STATS == 1)
xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
uint32_t currentTime = portGET_RUN_TIME_COUNTER_VALUE();
/* avoid divide-by-zero if the interval is too small */
uint32_t deltaTime = ((currentTime - mLastIdleMonitorTime) / 100) ? : 1;
mLastIdleMonitorTime = currentTime;
uint8_t running_time_percentage = 0;
/* Generate idle time percentage stats */
running_time_percentage = uxTaskGetRunTime(xTaskGetIdleTaskHandle()) / deltaTime;
xSemaphoreGiveRecursive(mLock);
return running_time_percentage;
#else
return 0;
#endif
}
#endif // PIOS_INCLUDE_TASK_MONITOR