OP-1734 replace double with qreal
[librepilot.git] / flight / pios / common / pios_task_monitor.c
blob958a744a6590a4e7ba5fa31db28d3240d53c8dc2
1 /**
2 ******************************************************************************
3 * @addtogroup OpenPilotSystem OpenPilot System
4 * @{
5 * @addtogroup OpenPilotLibraries OpenPilot System Libraries
6 * @{
7 * @file pios_task_monitor.h
8 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
9 * @brief Task monitoring functions
10 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <pios.h>
30 #ifdef PIOS_INCLUDE_TASK_MONITOR
32 // Private variables
33 static xSemaphoreHandle mLock;
34 static xTaskHandle *mTaskHandles;
35 static uint32_t mLastMonitorTime;
36 static uint32_t mLastIdleMonitorTime;
37 static uint16_t mMaxTasks;
39 /**
40 * Initialize the Task Monitor
42 int32_t PIOS_TASK_MONITOR_Initialize(uint16_t max_tasks)
44 mLock = xSemaphoreCreateRecursiveMutex();
45 if (!mLock) {
46 return -1;
49 mTaskHandles = (xTaskHandle *)pios_malloc(max_tasks * sizeof(xTaskHandle));
50 if (!mTaskHandles) {
51 return -1;
53 memset(mTaskHandles, 0, max_tasks * sizeof(xTaskHandle));
55 mMaxTasks = max_tasks;
56 #if (configGENERATE_RUN_TIME_STATS == 1)
57 mLastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
58 mLastIdleMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
59 #else
60 mLastMonitorTime = 0;
61 mLastIdleMonitorTime = 0;
62 #endif
63 return 0;
66 /**
67 * Register a task handle
69 int32_t PIOS_TASK_MONITOR_RegisterTask(uint16_t task_id, xTaskHandle handle)
71 if (mTaskHandles && task_id < mMaxTasks) {
72 xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
73 mTaskHandles[task_id] = handle;
74 xSemaphoreGiveRecursive(mLock);
75 return 0;
76 } else {
77 return -1;
81 /**
82 * Unregister a task handle
84 int32_t PIOS_TASK_MONITOR_UnregisterTask(uint16_t task_id)
86 if (mTaskHandles && task_id < mMaxTasks) {
87 xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
88 mTaskHandles[task_id] = 0;
89 xSemaphoreGiveRecursive(mLock);
90 return 0;
91 } else {
92 return -1;
96 /**
97 * Query if a task is running
99 bool PIOS_TASK_MONITOR_IsRunning(uint16_t task_id)
101 return mTaskHandles && task_id <= mMaxTasks && mTaskHandles[task_id];
105 * Tell the caller the status of all tasks via a task-by-task callback
107 void PIOS_TASK_MONITOR_ForEachTask(TaskMonitorTaskInfoCallback callback, void *context)
109 if (!mTaskHandles) {
110 return;
113 xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
115 #if (configGENERATE_RUN_TIME_STATS == 1)
116 /* Calculate the amount of elapsed run time between the last time we
117 * measured and now. Scale so that we can convert task run times
118 * directly to percentages. */
119 uint32_t currentTime = portGET_RUN_TIME_COUNTER_VALUE();
120 /* avoid divide-by-zero if the interval is too small */
121 uint32_t deltaTime = ((currentTime - mLastMonitorTime) / 100) ? : 1;
122 mLastMonitorTime = currentTime;
123 #endif
124 /* Update all task information */
125 for (uint16_t n = 0; n < mMaxTasks; ++n) {
126 struct pios_task_info info;
127 if (mTaskHandles[n]) {
128 info.is_running = true;
129 #if defined(ARCH_POSIX) || defined(ARCH_WIN32)
130 info.stack_remaining = 10000;
131 #else
132 info.stack_remaining = uxTaskGetStackHighWaterMark(mTaskHandles[n]) * 4;
133 #endif
134 #if (configGENERATE_RUN_TIME_STATS == 1)
135 /* Generate run time percentage stats */
136 info.running_time_percentage = uxTaskGetRunTime(mTaskHandles[n]) / deltaTime;
137 #else
138 info.running_time_percentage = 0;
139 #endif
140 } else {
141 info.is_running = false;
142 info.stack_remaining = 0;
143 info.running_time_percentage = 0;
145 /* Pass the information for this task back to the caller */
146 callback(n, &info, context);
149 xSemaphoreGiveRecursive(mLock);
152 uint8_t PIOS_TASK_MONITOR_GetIdlePercentage()
154 #if defined(ARCH_POSIX) || defined(ARCH_WIN32)
155 return 50;
157 #elif (configGENERATE_RUN_TIME_STATS == 1)
158 xSemaphoreTakeRecursive(mLock, portMAX_DELAY);
160 uint32_t currentTime = portGET_RUN_TIME_COUNTER_VALUE();
162 /* avoid divide-by-zero if the interval is too small */
163 uint32_t deltaTime = ((currentTime - mLastIdleMonitorTime) / 100) ? : 1;
164 mLastIdleMonitorTime = currentTime;
165 uint8_t running_time_percentage = 0;
167 /* Generate idle time percentage stats */
168 running_time_percentage = uxTaskGetRunTime(xTaskGetIdleTaskHandle()) / deltaTime;
169 xSemaphoreGiveRecursive(mLock);
170 return running_time_percentage;
172 #else
173 return 0;
175 #endif
179 #endif // PIOS_INCLUDE_TASK_MONITOR