|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include <memspy/engine/memspydevicewideoperations.h> |
|
18 |
|
19 // Engine includes |
|
20 #include <memspy/engine/memspyengine.h> |
|
21 #include <memspy/engine/memspyengineoutputsink.h> |
|
22 #include <memspy/engine/memspyengineobjectthread.h> |
|
23 #include <memspy/engine/memspyengineobjectthread.h> |
|
24 #include <memspy/engine/memspyengineobjectprocess.h> |
|
25 #include <memspy/engine/memspyengineobjectcontainer.h> |
|
26 #include <memspy/engine/memspyengineobjectthreadinfocontainer.h> |
|
27 #include <memspy/engine/memspyenginehelperchunk.h> |
|
28 #include <memspy/engine/memspyenginehelpercodesegment.h> |
|
29 #include <memspy/engine/memspyenginehelperheap.h> |
|
30 #include <memspy/engine/memspyenginehelperstack.h> |
|
31 #include <memspy/engine/memspyenginehelperthread.h> |
|
32 #include <memspy/engine/memspyenginehelperprocess.h> |
|
33 |
|
34 // Driver includes |
|
35 #include <memspy/driver/memspydriverenumerationsshared.h> |
|
36 |
|
37 // Literal constants |
|
38 _LIT( KMemSpyUiThreadNameKernel, "Kernel" ); |
|
39 _LIT( KMemSpyUiCompactHeap, "Compact Heap" ); |
|
40 _LIT( KMemSpyUiCompactStack, "Compact Stack" ); |
|
41 |
|
42 |
|
43 |
|
44 CMemSpyDeviceWideOperations::CMemSpyDeviceWideOperations( CMemSpyEngine& aEngine, MMemSpyDeviceWideOperationsObserver& aObserver, TOperation aOperation ) |
|
45 : CActive( EPriorityIdle ), iEngine( aEngine ), iObserver( aObserver ), iOperation( aOperation ) |
|
46 { |
|
47 CActiveScheduler::Add( this ); |
|
48 } |
|
49 |
|
50 |
|
51 EXPORT_C CMemSpyDeviceWideOperations::~CMemSpyDeviceWideOperations() |
|
52 { |
|
53 #ifdef _DEBUG |
|
54 RDebug::Printf("CMemSpyDeviceWideOperations::~CMemSpyDeviceWideOperations() - START - iOperationCancelled: %d", iOperationCancelled ); |
|
55 #endif |
|
56 |
|
57 Cancel(); |
|
58 |
|
59 #ifdef _DEBUG |
|
60 RDebug::Printf("CMemSpyDeviceWideOperations::~CMemSpyDeviceWideOperations() - END" ); |
|
61 #endif |
|
62 } |
|
63 |
|
64 |
|
65 void CMemSpyDeviceWideOperations::ConstructL() |
|
66 { |
|
67 #ifdef _DEBUG |
|
68 RDebug::Printf("CMemSpyDeviceWideOperations::ConstructL() - START" ); |
|
69 #endif |
|
70 |
|
71 // Set engine sink time stamp, which will cause the data to be written to a |
|
72 // uniquely named folder (if we're using a file sink) |
|
73 TTime now; |
|
74 now.HomeTime(); |
|
75 iEngine.Sink().DataStreamTimeStampBeginL( now ); |
|
76 |
|
77 const TInt processCountUser = iEngine.Container().Count(); |
|
78 const TInt threadCountUser = TotalNumberOfThreads(); |
|
79 const TInt threadCountIncludingKernelSupervisor = threadCountUser + 1; // includes kernel supervisor thread |
|
80 |
|
81 // Decide what the maximum progress bar value is... |
|
82 // If we're performing a detailed operation, then skip straight to the end because |
|
83 // the entire operation is performed in one go. |
|
84 iTotalOperationSize = 0; |
|
85 switch( iOperation ) |
|
86 { |
|
87 // Only applicable to user-threads |
|
88 default: |
|
89 case EPerEntityGeneralSummary: |
|
90 case EPerEntityGeneralDetailed: |
|
91 case EPerEntityGeneralHandles: |
|
92 case EPerEntityHeapCellListing: |
|
93 case EPerEntityStackInfo: |
|
94 case EPerEntityStackDataUser: |
|
95 case EPerEntityStackDataKernel: |
|
96 iTotalOperationSize = threadCountUser; |
|
97 break; |
|
98 // Applies to user and kernel threads |
|
99 case EPerEntityHeapInfo: |
|
100 iTotalOperationSize = threadCountIncludingKernelSupervisor; |
|
101 break; |
|
102 // Operation is performed in one go |
|
103 case EEntireDeviceHeapInfoCompact: |
|
104 case EEntireDeviceStackInfoCompact: |
|
105 iProcessIndex = processCountUser; |
|
106 iTotalOperationSize = 1; |
|
107 break; |
|
108 } |
|
109 |
|
110 #ifdef _DEBUG |
|
111 RDebug::Printf("CMemSpyDeviceWideOperations::ConstructL() - op. count: %d", iTotalOperationSize ); |
|
112 #endif |
|
113 |
|
114 // Report total amount of work to observer |
|
115 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationSized, iTotalOperationSize, KNullDesC ); |
|
116 |
|
117 // Start the process rolling... |
|
118 CompleteSelf( KErrNone ); |
|
119 |
|
120 // Indicate that we're now starting the operation |
|
121 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationStarting, 0, KNullDesC ); |
|
122 |
|
123 #ifdef _DEBUG |
|
124 RDebug::Printf("CMemSpyDeviceWideOperations::ConstructL() - END" ); |
|
125 #endif |
|
126 } |
|
127 |
|
128 |
|
129 EXPORT_C CMemSpyDeviceWideOperations* CMemSpyDeviceWideOperations::NewL( CMemSpyEngine& aEngine, MMemSpyDeviceWideOperationsObserver& aObserver, TOperation aOperation ) |
|
130 { |
|
131 CMemSpyDeviceWideOperations* self = new(ELeave) CMemSpyDeviceWideOperations( aEngine, aObserver, aOperation ); |
|
132 CleanupStack::PushL( self ); |
|
133 self->ConstructL(); |
|
134 #ifdef _DEBUG |
|
135 RDebug::Printf("CMemSpyDeviceWideOperations::NewL() - about to pop..." ); |
|
136 #endif |
|
137 CleanupStack::Pop( self ); |
|
138 #ifdef _DEBUG |
|
139 RDebug::Printf("CMemSpyDeviceWideOperations::NewL() - popped" ); |
|
140 #endif |
|
141 return self; |
|
142 } |
|
143 |
|
144 |
|
145 EXPORT_C void CMemSpyDeviceWideOperations::Cancel() |
|
146 { |
|
147 #ifdef _DEBUG |
|
148 RDebug::Printf("CMemSpyDeviceWideOperations::Cancel() - START - IsActive: %d", IsActive() ); |
|
149 #endif |
|
150 |
|
151 if ( IsActive() ) |
|
152 { |
|
153 CActive::Cancel(); |
|
154 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationCancelled, 0, KNullDesC ); |
|
155 } |
|
156 |
|
157 #ifdef _DEBUG |
|
158 RDebug::Printf("CMemSpyDeviceWideOperations::Cancel() - END" ); |
|
159 #endif |
|
160 } |
|
161 |
|
162 |
|
163 EXPORT_C TInt CMemSpyDeviceWideOperations::TotalOperationSize() const |
|
164 { |
|
165 #ifdef _DEBUG |
|
166 RDebug::Printf("CMemSpyDeviceWideOperations::TotalOperationSize::Cancel() - ret: %d", iTotalOperationSize ); |
|
167 #endif |
|
168 return iTotalOperationSize; |
|
169 } |
|
170 |
|
171 |
|
172 void CMemSpyDeviceWideOperations::RunL() |
|
173 { |
|
174 #ifdef _DEBUG |
|
175 RDebug::Printf( "CMemSpyDeviceWideOperations::RunL() - START - iStatus: %d, iOperationCancelled: %d, iThreadIndex: %03d, iOperation: %d", iStatus.Int(), iOperationCancelled, iThreadIndex, iOperation ); |
|
176 #endif |
|
177 |
|
178 User::LeaveIfError( iStatus.Int() ); |
|
179 User::ResetInactivityTime(); |
|
180 |
|
181 if ( iOperationCancelled ) |
|
182 { |
|
183 #ifdef _DEBUG |
|
184 RDebug::Printf( "CMemSpyDeviceWideOperations::RunL() - operation was cancelled whilst running... => Finished" ); |
|
185 #endif |
|
186 SetFinished(); |
|
187 } |
|
188 else |
|
189 { |
|
190 // Get the current process |
|
191 CMemSpyEngineObjectContainer& container = iEngine.Container(); |
|
192 const TInt processCount = container.Count(); |
|
193 // |
|
194 if ( iProcessIndex < processCount ) |
|
195 { |
|
196 PerformNextStepL(); |
|
197 } |
|
198 else |
|
199 { |
|
200 // We're done - RunL will not be called again |
|
201 TRAP_IGNORE( PerformFinalOperationL() ); |
|
202 SetFinished(); |
|
203 } |
|
204 } |
|
205 |
|
206 #ifdef _DEBUG |
|
207 RDebug::Printf("CMemSpyDeviceWideOperations::RunL() - END" ); |
|
208 #endif |
|
209 } |
|
210 |
|
211 |
|
212 void CMemSpyDeviceWideOperations::DoCancel() |
|
213 { |
|
214 #ifdef _DEBUG |
|
215 RDebug::Printf( "CMemSpyDeviceWideOperations::DoCancel() - START" ); |
|
216 #endif |
|
217 |
|
218 // Nothing to do here |
|
219 iOperationCancelled = ETrue; |
|
220 |
|
221 #ifdef _DEBUG |
|
222 RDebug::Printf( "CMemSpyDeviceWideOperations::DoCancel() - END" ); |
|
223 #endif |
|
224 } |
|
225 |
|
226 |
|
227 TInt CMemSpyDeviceWideOperations::RunError( TInt aError ) |
|
228 { |
|
229 #ifdef _DEBUG |
|
230 RDebug::Printf( "CMemSpyDeviceWideOperations::RunError() - START - iOperationCancelled: %d, aError: %d", iOperationCancelled, aError ); |
|
231 #endif |
|
232 |
|
233 // KErrNotFound can come when trying to suspend a process or thread that no longer exists. |
|
234 if ( !( aError == KErrDied || aError == KErrNotFound ) ) |
|
235 { |
|
236 #ifdef _DEBUG |
|
237 RDebug::Printf( "CMemSpyDeviceWideOperations::RunError() - fatal error - cancelling..." ); |
|
238 #endif |
|
239 Cancel(); |
|
240 } |
|
241 // |
|
242 #ifdef _DEBUG |
|
243 RDebug::Printf( "CMemSpyDeviceWideOperations::RunError() - END - iOperationCancelled: %d, aError: %d", iOperationCancelled, aError ); |
|
244 #endif |
|
245 return KErrNone; |
|
246 } |
|
247 |
|
248 |
|
249 void CMemSpyDeviceWideOperations::CompleteSelf( TInt aError ) |
|
250 { |
|
251 TRequestStatus* status = &iStatus; |
|
252 User::RequestComplete( status, aError ); |
|
253 SetActive(); |
|
254 } |
|
255 |
|
256 |
|
257 void CMemSpyDeviceWideOperations::PerformFinalOperationL() |
|
258 { |
|
259 #ifdef _DEBUG |
|
260 RDebug::Printf( "CMemSpyDeviceWideOperations::PerformFinalOperationL() - START" ); |
|
261 #endif |
|
262 |
|
263 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationCompleting, 0, KNullDesC ); |
|
264 |
|
265 // Carry out any remaining final one-shot operation |
|
266 TPtrC pType( KNullDesC ); |
|
267 switch( iOperation ) |
|
268 { |
|
269 case EEntireDeviceHeapInfoCompact: |
|
270 // Entire operation is performed here |
|
271 pType.Set( KMemSpyUiCompactHeap ); |
|
272 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType ); |
|
273 iEngine.HelperHeap().OutputHeapInfoForDeviceL(); |
|
274 break; |
|
275 case EEntireDeviceStackInfoCompact: |
|
276 // Entire operation is performed here |
|
277 pType.Set( KMemSpyUiCompactStack ); |
|
278 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType ); |
|
279 iEngine.HelperStack().OutputStackInfoForDeviceL(); |
|
280 break; |
|
281 case EPerEntityHeapInfo: |
|
282 // Complete op by outputting kernel heap summary |
|
283 pType.Set( KMemSpyUiThreadNameKernel ); |
|
284 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType ); |
|
285 iEngine.HelperHeap().OutputHeapInfoKernelL(); |
|
286 break; |
|
287 case EPerEntityHeapData: |
|
288 // Complete op by outputting kernel heap data |
|
289 pType.Set( KMemSpyUiThreadNameKernel ); |
|
290 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pType ); |
|
291 iEngine.HelperHeap().OutputHeapDataKernelL(); |
|
292 break; |
|
293 default: |
|
294 break; |
|
295 } |
|
296 |
|
297 // Report progress |
|
298 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressEnd, 1, pType ); |
|
299 |
|
300 #ifdef _DEBUG |
|
301 RDebug::Print( _L("CMemSpyDeviceWideOperations::PerformFinalOperationL() - END - pType: %S"), &pType ); |
|
302 #endif |
|
303 } |
|
304 |
|
305 |
|
306 void CMemSpyDeviceWideOperations::PerformNextStepL() |
|
307 { |
|
308 #ifdef _DEBUG |
|
309 RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - START - iProcessIndex: %d, iThreadIndex: %d", iProcessIndex, iThreadIndex ); |
|
310 #endif |
|
311 |
|
312 // Get the current process |
|
313 CMemSpyEngineObjectContainer& container = iEngine.Container(); |
|
314 const TInt processCount = container.Count(); |
|
315 CMemSpyProcess& process = container.At( iProcessIndex ); |
|
316 const TInt threadCount = process.Count(); |
|
317 |
|
318 #ifdef _DEBUG |
|
319 RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - threadCount: %d, processCount: %d", threadCount, processCount ); |
|
320 #endif |
|
321 |
|
322 // Get current thread |
|
323 if ( iThreadIndex < threadCount ) |
|
324 { |
|
325 CMemSpyThread& thread = process.At( iThreadIndex++ ); |
|
326 const TPtrC pName( thread.Name() ); |
|
327 |
|
328 #ifdef _DEBUG |
|
329 RDebug::Print( _L("CMemSpyDeviceWideOperations::PerformNextStepL() - thread: %S"), &pName ); |
|
330 #endif |
|
331 |
|
332 // Report progress |
|
333 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressStart, 0, pName ); |
|
334 |
|
335 TInt progressAmount = 1; |
|
336 TRAP_IGNORE( |
|
337 |
|
338 switch(iOperation) |
|
339 { |
|
340 case EPerEntityGeneralSummary: |
|
341 case EPerEntityGeneralDetailed: |
|
342 if ( iOperation == EPerEntityGeneralSummary ) |
|
343 { |
|
344 iEngine.HelperProcess().OutputProcessInfoL( process ); |
|
345 } |
|
346 else |
|
347 { |
|
348 iEngine.HelperProcess().OutputProcessInfoDetailedL( process ); |
|
349 } |
|
350 |
|
351 // Process specific item, so do this only once per perocess |
|
352 progressAmount = threadCount; |
|
353 iThreadIndex = threadCount; |
|
354 break; |
|
355 case EPerEntityGeneralHandles: |
|
356 thread.InfoContainerForceSyncronousConstructionL().PrintL(); |
|
357 break; |
|
358 case EPerEntityHeapInfo: |
|
359 // Output user thread summary here, kernel thread summary will be |
|
360 // handled when dialog dismissed |
|
361 iEngine.HelperHeap().OutputHeapInfoUserL( thread ); |
|
362 break; |
|
363 case EPerEntityHeapCellListing: |
|
364 iEngine.HelperHeap().OutputCellListingUserL( thread ); |
|
365 break; |
|
366 case EPerEntityHeapData: |
|
367 iEngine.HelperHeap().OutputHeapDataUserL( thread ); |
|
368 break; |
|
369 case EPerEntityStackInfo: |
|
370 iEngine.HelperStack().OutputStackInfoL( thread ); |
|
371 break; |
|
372 case EPerEntityStackDataUser: |
|
373 iEngine.HelperStack().OutputStackDataL( thread, EMemSpyDriverDomainUser ); |
|
374 break; |
|
375 case EPerEntityStackDataKernel: |
|
376 iEngine.HelperStack().OutputStackDataL( thread, EMemSpyDriverDomainKernel ); |
|
377 break; |
|
378 default: |
|
379 break; |
|
380 } |
|
381 ); |
|
382 |
|
383 // Report progress |
|
384 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationProgressEnd, progressAmount, pName ); |
|
385 } |
|
386 else |
|
387 { |
|
388 // This process is exhausted - move on to the next |
|
389 ++iProcessIndex; |
|
390 iThreadIndex = 0; |
|
391 |
|
392 #ifdef _DEBUG |
|
393 RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - move to next process..." ); |
|
394 #endif |
|
395 } |
|
396 |
|
397 // Request RunL be called again... |
|
398 CompleteSelf( KErrNone ); |
|
399 |
|
400 #ifdef _DEBUG |
|
401 RDebug::Printf( "CMemSpyDeviceWideOperations::PerformNextStepL() - END" ); |
|
402 #endif |
|
403 } |
|
404 |
|
405 |
|
406 void CMemSpyDeviceWideOperations::SetFinished() |
|
407 { |
|
408 #ifdef _DEBUG |
|
409 RDebug::Printf("CMemSpyDeviceWideOperations::SetFinished() - START" ); |
|
410 #endif |
|
411 |
|
412 // Cancel sink time stamp |
|
413 iEngine.Sink().DataStreamTimeStampEnd(); |
|
414 |
|
415 iObserver.HandleDeviceWideOperationEvent( MMemSpyDeviceWideOperationsObserver::EOperationCompleted, 0, KNullDesC ); |
|
416 |
|
417 #ifdef _DEBUG |
|
418 RDebug::Printf("CMemSpyDeviceWideOperations::SetFinished() - END" ); |
|
419 #endif |
|
420 } |
|
421 |
|
422 |
|
423 TInt CMemSpyDeviceWideOperations::TotalNumberOfThreads() const |
|
424 { |
|
425 TInt count = 0; |
|
426 // |
|
427 const CMemSpyEngineObjectContainer& container = iEngine.Container(); |
|
428 const TInt processCount = container.Count(); |
|
429 // |
|
430 for(TInt i=0; i<processCount; i++) |
|
431 { |
|
432 const CMemSpyProcess& process = container.At( i ); |
|
433 count += process.Count(); |
|
434 } |
|
435 // |
|
436 #ifdef _DEBUG |
|
437 RDebug::Printf("CMemSpyDeviceWideOperations::TotalNumberOfThreads() - count: %d", count ); |
|
438 #endif |
|
439 return count; |
|
440 } |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 |