|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
5 ** |
|
6 ** This file is part of the examples of the Qt Toolkit. |
|
7 ** |
|
8 ** $QT_BEGIN_LICENSE:LGPL$ |
|
9 ** No Commercial Usage |
|
10 ** This file contains pre-release code and may not be distributed. |
|
11 ** You may use this file in accordance with the terms and conditions |
|
12 ** contained in the either Technology Preview License Agreement or the |
|
13 ** Beta Release License Agreement. |
|
14 ** |
|
15 ** GNU Lesser General Public License Usage |
|
16 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
17 ** General Public License version 2.1 as published by the Free Software |
|
18 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
19 ** packaging of this file. Please review the following information to |
|
20 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
22 ** |
|
23 ** In addition, as a special exception, Nokia gives you certain |
|
24 ** additional rights. These rights are described in the Nokia Qt LGPL |
|
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this |
|
26 ** package. |
|
27 ** |
|
28 ** GNU General Public License Usage |
|
29 ** Alternatively, this file may be used under the terms of the GNU |
|
30 ** General Public License version 3.0 as published by the Free Software |
|
31 ** Foundation and appearing in the file LICENSE.GPL included in the |
|
32 ** packaging of this file. Please review the following information to |
|
33 ** ensure the GNU General Public License version 3.0 requirements will be |
|
34 ** met: http://www.gnu.org/copyleft/gpl.html. |
|
35 ** |
|
36 ** If you are unsure which license is appropriate for your use, please |
|
37 ** contact the sales department at http://qt.nokia.com/contact. |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <QtGui> |
|
43 #include "resourcemonplugin.h" |
|
44 |
|
45 #if defined Q_OS_SYMBIAN |
|
46 #include <HAL.H> |
|
47 #include <hal_data.h> |
|
48 #endif |
|
49 |
|
50 #if defined Q_OS_LINUX |
|
51 // Parses first, cpu summary line and calculates total and busy jiffies |
|
52 static int get_cpu_load(uint64_t *t, uint64_t *b) |
|
53 { |
|
54 uint64_t user, nice, sys, idle, iowait, irq, softirq, steal; |
|
55 char cpu[20]; |
|
56 int n; |
|
57 FILE *f; |
|
58 |
|
59 f = fopen("/proc/stat", "r"); |
|
60 if (!f) |
|
61 return -1; |
|
62 |
|
63 n = fscanf(f, "%s %llu %llu %llu %llu %llu %llu %llu %llu", cpu, |
|
64 &user, &nice, &sys, &idle, &iowait, &irq, &softirq, &steal); |
|
65 if (n != 9 || strcmp(cpu, "cpu")) { |
|
66 fclose(f); |
|
67 return -1; |
|
68 } |
|
69 |
|
70 fclose(f); |
|
71 |
|
72 *t = user + nice + sys + idle + iowait + irq + softirq + steal; |
|
73 *b = *t - idle - iowait; |
|
74 return 0; |
|
75 } |
|
76 #endif |
|
77 |
|
78 ResourceMonitorPlugin::~ResourceMonitorPlugin() |
|
79 { |
|
80 #if defined Q_OS_SYMBIAN |
|
81 iSysThread.Close(); |
|
82 iAppThread.Close(); |
|
83 #endif |
|
84 } |
|
85 |
|
86 bool ResourceMonitorPlugin::Prepare(QString applicationThreadName) |
|
87 { |
|
88 bool result = false; |
|
89 #if defined Q_OS_SYMBIAN |
|
90 //Locate ekern null thread |
|
91 TFindProcess kernelProc(_L("ekern.exe*")); |
|
92 TFullName kernelProcName; |
|
93 |
|
94 if (kernelProc.Next(kernelProcName) == KErrNone) |
|
95 { |
|
96 kernelProcName.Append(_L("::Null")); |
|
97 |
|
98 TFindThread kernelNullThread(kernelProcName); |
|
99 TFullName kernelThreadName; |
|
100 |
|
101 if (kernelNullThread.Next(kernelThreadName) == KErrNone) |
|
102 { |
|
103 if (iSysThread.Open(kernelThreadName) == KErrNone) |
|
104 { |
|
105 //Set prev values so first call to CPU usage won't fail at first call |
|
106 iSysThread.GetCpuTime(iPrevSystemCpuTime); |
|
107 iPrevSampleTime.HomeTime(); |
|
108 result = true; |
|
109 } |
|
110 } |
|
111 } |
|
112 |
|
113 //Locate app thread, append asterisk if needed |
|
114 if(applicationThreadName.indexOf("*") == -1) |
|
115 applicationThreadName.append('*'); |
|
116 |
|
117 TPtrC appName (reinterpret_cast<const TText*>(applicationThreadName.constData()),applicationThreadName.length()); |
|
118 TFindThread appThread(appName); |
|
119 TFullName appThreadFullName; |
|
120 |
|
121 if(appThread.Next(appThreadFullName) == KErrNone) |
|
122 { |
|
123 if(iAppThread.Open(appThreadFullName) == KErrNone) |
|
124 { |
|
125 //Get CPU Time for app thread |
|
126 iAppThread.GetCpuTime(iPrevAppCpuTime); |
|
127 result = result && true; |
|
128 } |
|
129 } |
|
130 #endif |
|
131 #if defined Q_OS_LINUX |
|
132 Q_UNUSED(applicationThreadName); |
|
133 |
|
134 //Get resource usage for the process |
|
135 struct rusage usage; |
|
136 int res = getrusage(RUSAGE_SELF, &usage); |
|
137 if (res == -1) { |
|
138 return false; |
|
139 } |
|
140 |
|
141 //Init CPU jiffies |
|
142 res = get_cpu_load(&iPrevTotalJiffies, &iPrevBusyJiffies); |
|
143 if (res == -1) { |
|
144 return false; |
|
145 } |
|
146 |
|
147 //Init process CPU time, system functions time and user code time altogether |
|
148 timeradd(&(usage.ru_stime), &(usage.ru_utime), &iPrevAppCpuTime); |
|
149 |
|
150 result = true; |
|
151 #endif |
|
152 return result; |
|
153 } |
|
154 |
|
155 ResourceMonitorInterface::CpuUsage ResourceMonitorPlugin::CPULoad() |
|
156 { |
|
157 ResourceMonitorInterface::CpuUsage cpuUsage; |
|
158 #if defined Q_OS_SYMBIAN |
|
159 //Get current time |
|
160 TTime currentTime; |
|
161 currentTime.HomeTime(); |
|
162 |
|
163 TTimeIntervalMicroSeconds systemCpuTime; |
|
164 TTimeIntervalMicroSeconds appCpuTime; |
|
165 |
|
166 //Get CPU times |
|
167 TInt result = iSysThread.GetCpuTime(systemCpuTime); |
|
168 result = iAppThread.GetCpuTime(appCpuTime); |
|
169 |
|
170 //Calculate Total CPU usage |
|
171 TTimeIntervalMicroSeconds totalDelta = currentTime.MicroSecondsFrom(iPrevSampleTime); |
|
172 if(totalDelta.Int64() == 0) |
|
173 return cpuUsage; //return empty cpuUsage |
|
174 |
|
175 TInt64 totalUsage = ( systemCpuTime.Int64() - iPrevSystemCpuTime.Int64() ) * 1000000 / totalDelta.Int64(); |
|
176 TInt64 appUsage = ( appCpuTime.Int64() - iPrevAppCpuTime.Int64() ) * 1000000 / totalDelta.Int64(); |
|
177 |
|
178 //Convert usage (us) to percentage |
|
179 cpuUsage.systemUsage = 100.0 - ( totalUsage / 10000.0); |
|
180 cpuUsage.appTreadUsage = (appUsage / 10000.0); |
|
181 |
|
182 //update prev values |
|
183 iPrevSampleTime = currentTime; |
|
184 iPrevSystemCpuTime = systemCpuTime; |
|
185 iPrevAppCpuTime = appCpuTime; |
|
186 #endif |
|
187 #if defined Q_OS_LINUX |
|
188 struct rusage usage; |
|
189 int res = getrusage(RUSAGE_SELF, &usage); |
|
190 if (res == -1) { |
|
191 return cpuUsage; |
|
192 } |
|
193 |
|
194 uint64_t totalJiffies, busyJiffies; |
|
195 res = get_cpu_load(&totalJiffies, &busyJiffies); |
|
196 if (res == -1) { |
|
197 return cpuUsage; |
|
198 } |
|
199 |
|
200 struct timeval appTime; |
|
201 timeradd(&(usage.ru_stime), &(usage.ru_utime), &appTime); |
|
202 |
|
203 struct timeval appDelta; |
|
204 timersub(&appTime, &iPrevAppCpuTime, &appDelta); |
|
205 |
|
206 //"systemUsage" means here busy time percentage in relation to CPUs summary |
|
207 cpuUsage.systemUsage = (busyJiffies - iPrevBusyJiffies) * 100.0 / (totalJiffies - iPrevTotalJiffies); |
|
208 //"appTreadUsage" means here calling process time percentage in relation to CPUs summary |
|
209 cpuUsage.appTreadUsage = (appDelta.tv_sec*10000.0 + appDelta.tv_usec/100.0) / (totalJiffies - iPrevTotalJiffies); |
|
210 |
|
211 iPrevBusyJiffies = busyJiffies; |
|
212 iPrevTotalJiffies = totalJiffies; |
|
213 iPrevAppCpuTime = appTime; |
|
214 #endif |
|
215 return cpuUsage; |
|
216 } |
|
217 |
|
218 ResourceMonitorInterface::MemoryAllocation ResourceMonitorPlugin::MemoryLoad() |
|
219 { |
|
220 ResourceMonitorInterface::MemoryAllocation allocation; |
|
221 #if defined Q_OS_SYMBIAN |
|
222 TInt allocInCells = 0; |
|
223 TInt numberOfCells = 0; |
|
224 TInt largestFreeBlock = 0; |
|
225 TInt availableInHeap = 0; |
|
226 TInt totalMemory = 0; |
|
227 TInt availableSysMemory = 0; |
|
228 |
|
229 numberOfCells = User::AllocSize(allocInCells); |
|
230 availableInHeap = User::Available(largestFreeBlock); |
|
231 |
|
232 TInt result = KErrNone; |
|
233 result = HAL::Get(HALData::EMemoryRAMFree, availableSysMemory); |
|
234 result = HAL::Get(HALData::EMemoryRAM, totalMemory); |
|
235 |
|
236 allocation.allocatedInAppThread = allocInCells; |
|
237 allocation.numberOfAllocatedCellsInAppThread = numberOfCells; |
|
238 allocation.availableMemoryInAppThreadHeap = availableInHeap; |
|
239 allocation.availableMemoryInSystem = availableSysMemory; |
|
240 allocation.totalMemoryInSystem = totalMemory; |
|
241 #endif |
|
242 #if defined Q_OS_LINUX |
|
243 struct mallinfo info = mallinfo(); |
|
244 allocation.allocatedInAppThread = info.uordblks; //bytes |
|
245 allocation.numberOfAllocatedCellsInAppThread = info.ordblks; //free chunks |
|
246 allocation.availableMemoryInAppThreadHeap = info.fordblks; //bytes |
|
247 allocation.availableMemoryInSystem = (long long)sysconf(_SC_AVPHYS_PAGES) * (long long)sysconf(_SC_PAGESIZE); //bytes |
|
248 allocation.totalMemoryInSystem = (long long)sysconf(_SC_PHYS_PAGES) * (long long)sysconf(_SC_PAGESIZE); //bytes |
|
249 #endif |
|
250 return allocation; |
|
251 } |
|
252 |
|
253 void ResourceMonitorPlugin::BeginMeasureMemoryLoad() |
|
254 { |
|
255 //Store current memory values. |
|
256 iMemoryAtStart = MemoryLoad(); |
|
257 } |
|
258 |
|
259 ResourceMonitorInterface::MemoryAllocation ResourceMonitorPlugin::EndMeasureMemoryLoad() |
|
260 { |
|
261 //Get current memory consumption |
|
262 ResourceMonitorInterface::MemoryAllocation current = MemoryLoad(); |
|
263 //Calculate delta values for heap allocation and heap cell allocation |
|
264 current.allocatedInAppThread = current.allocatedInAppThread - iMemoryAtStart.allocatedInAppThread; |
|
265 current.numberOfAllocatedCellsInAppThread = current.numberOfAllocatedCellsInAppThread - iMemoryAtStart.numberOfAllocatedCellsInAppThread; |
|
266 #if defined Q_OS_LINUX |
|
267 current.numberOfAllocatedCellsInAppThread = -current.numberOfAllocatedCellsInAppThread; |
|
268 #endif |
|
269 return current; |
|
270 } |
|
271 |
|
272 void ResourceMonitorPlugin::BeginMeasureCPULoad() |
|
273 { |
|
274 //Reset CPU load measuring |
|
275 CPULoad(); |
|
276 } |
|
277 |
|
278 ResourceMonitorInterface::CpuUsage ResourceMonitorPlugin::EndMeasureCPULoad() |
|
279 { |
|
280 //return CPU load |
|
281 return CPULoad(); |
|
282 } |
|
283 |
|
284 Q_EXPORT_PLUGIN2(resourcemonplugin, ResourceMonitorPlugin); |