|
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 |
|
18 |
|
19 #ifndef PROFILER_MEM_SAMPLER_H |
|
20 #define PROFILER_MEM_SAMPLER_H |
|
21 |
|
22 #include "GeneralsConfig.h" |
|
23 |
|
24 #include <kern_priv.h> |
|
25 |
|
26 #include <piprofiler/ProfilerGenericClassesKrn.h> |
|
27 #include <piprofiler/ProfilerTraces.h> |
|
28 #include "GppSamplerImpl.h" |
|
29 #include "MemoryEventHandler.h" |
|
30 #include <e32btrace.h> |
|
31 |
|
32 |
|
33 // constants |
|
34 // defines the maximum thread amount that is assumed to |
|
35 // be possible with MEM trace |
|
36 const TInt KSampleBufferSize = 257; |
|
37 const TInt KProfilerMaxThreadsAmount = 512; |
|
38 const TInt KProfilerMaxChunksAmount = 1024; |
|
39 const TInt KProfilerMaxLibrariesAmount = 1024; |
|
40 const TInt KProfilerTotalMemorySamplePeriod = 100; |
|
41 |
|
42 // flags |
|
43 #define MEM_EVENT_HANDLER |
|
44 //#define MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
45 |
|
46 /* |
|
47 * |
|
48 * MEM sampler definition |
|
49 * |
|
50 */ |
|
51 |
|
52 class DMemoryEventHandler; |
|
53 |
|
54 class DMemSamplerImpl //: public DBase |
|
55 { |
|
56 public: |
|
57 enum EProcessingState |
|
58 { |
|
59 EStartingToProcess, |
|
60 EProcessingNames, |
|
61 EProcessingData, |
|
62 ENothingToProcess |
|
63 }; |
|
64 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
65 enum ESampleType |
|
66 { |
|
67 ESampleChunks, |
|
68 ESampleThreads, |
|
69 ESampleLibraries |
|
70 }; |
|
71 #endif |
|
72 |
|
73 DMemSamplerImpl(); |
|
74 ~DMemSamplerImpl(); |
|
75 |
|
76 TInt CreateFirstSample(); |
|
77 TInt SampleImpl(); |
|
78 TBool SampleNeeded(); |
|
79 void Reset(); |
|
80 TInt ProcessChunks(); |
|
81 TInt ProcessThreads(); |
|
82 TInt GatherChunks(); |
|
83 TInt GatherThreads(); |
|
84 |
|
85 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
86 TInt GatherLibraries(); |
|
87 TInt ProcessLibraries(); |
|
88 #endif |
|
89 |
|
90 TInt EncodeChunkData(DChunk& chunk); |
|
91 TInt EncodeChunkName(DChunk& chunk); |
|
92 TInt EncodeChunkData(DThread& thread); |
|
93 TInt EncodeChunkName(DThread& thread); |
|
94 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
95 TInt EncodeChunkData(DLibrary& library); |
|
96 TInt EncodeChunkName(DLibrary& library); |
|
97 #endif |
|
98 |
|
99 TInt EncodeTotalMemoryName(); |
|
100 TInt EncodeTotalMemory(); |
|
101 |
|
102 TInt EncodeNameCode(); |
|
103 TInt EncodeDataCode(); |
|
104 |
|
105 DChunk* heapChunksToSample[KProfilerMaxChunksAmount]; |
|
106 DChunk* heapChunkNamesToReport[KProfilerMaxChunksAmount]; |
|
107 TInt iCount; |
|
108 TInt iChunkCount; |
|
109 TInt iNewChunkCount; |
|
110 TBuf8<0x50> name; |
|
111 DThread* threadsToSample[KProfilerMaxThreadsAmount]; |
|
112 DThread* threadNamesToReport[KProfilerMaxThreadsAmount]; |
|
113 TInt iThreadCount; |
|
114 TInt iNewThreadCount; |
|
115 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
116 DLibrary* librariesToSample[KProfilerMaxLibrariesAmount]; |
|
117 DLibrary* libraryNamesToReport[KProfilerMaxLibrariesAmount]; |
|
118 TInt iLibraryCount; |
|
119 TInt iNewLibraryCount; |
|
120 TInt iLibrariesProcessing; |
|
121 #endif |
|
122 |
|
123 TInt iChunksProcessing; |
|
124 TInt iThreadsProcessing; |
|
125 TInt iMemSamplingPeriod; |
|
126 TInt iMemSamplingPeriodDiv2; |
|
127 TInt iMemSamplingPeriodDiv3; |
|
128 |
|
129 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
130 ESampleType iSampleType; |
|
131 #else |
|
132 TBool iSampleThreads; |
|
133 #endif |
|
134 |
|
135 TBool iTimeToSample; |
|
136 |
|
137 TBool iTotalMemoryOk; |
|
138 TBool iTotalMemoryNameOk; |
|
139 |
|
140 TUint8 sample[KSampleBufferSize]; |
|
141 TPtr8 sampleDescriptor; |
|
142 |
|
143 // test |
|
144 #ifdef MEM_EVENT_HANDLER |
|
145 // DMemoryEventHandler* iEventHandler; |
|
146 TBool iChunksGathered; |
|
147 TBool iThreadsGathered; |
|
148 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
149 TBool iLibrariesGathered; |
|
150 #endif |
|
151 #endif |
|
152 }; |
|
153 |
|
154 |
|
155 template <int BufferSize> |
|
156 class DProfilerMemSampler : public DProfilerGenericSampler<BufferSize> |
|
157 { |
|
158 public: |
|
159 DProfilerMemSampler(struct TProfilerGppSamplerData*, TInt id); |
|
160 ~DProfilerMemSampler(); |
|
161 |
|
162 void Sample(); |
|
163 TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); |
|
164 TInt PostSample(); |
|
165 TBool PostSampleNeeded(); |
|
166 |
|
167 private: |
|
168 #ifdef MEM_EVENT_HANDLER |
|
169 DMemoryEventHandler* iEventHandler; |
|
170 #endif |
|
171 DMemSamplerImpl memSamplerImpl; |
|
172 struct TProfilerGppSamplerData* gppSamplerData; |
|
173 TBool sampleNeeded; |
|
174 }; |
|
175 |
|
176 /* |
|
177 * |
|
178 * MEM sampler implementation |
|
179 * |
|
180 */ |
|
181 |
|
182 template <int BufferSize> |
|
183 DProfilerMemSampler<BufferSize>::DProfilerMemSampler(struct TProfilerGppSamplerData* gppSamplerDataIn, TInt id) : |
|
184 DProfilerGenericSampler<BufferSize>(PROFILER_MEM_SAMPLER_ID) |
|
185 { |
|
186 LOGSTRING2("DProfilerMemSampler<%d>::CProfilerMemSampler",BufferSize); |
|
187 this->gppSamplerData = gppSamplerDataIn; |
|
188 this->iSamplingPeriod = 3000; // set default setting |
|
189 } |
|
190 |
|
191 template <int BufferSize> |
|
192 TInt DProfilerMemSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) |
|
193 { |
|
194 //#ifdef MEM_EVENT_HANDLER |
|
195 // Kern::Printf("DProfilerMemSampler<%d>::Reset - calling superclass reset",BufferSize); |
|
196 |
|
197 //#endif |
|
198 // check if reset called in stop (by driver) |
|
199 if(aSyncOffset != 999999) |
|
200 { |
|
201 DProfilerGenericSampler<BufferSize>::Reset(aStream); |
|
202 memSamplerImpl.Reset(); |
|
203 |
|
204 #ifdef MEM_EVENT_HANDLER |
|
205 // reset member variables |
|
206 this->memSamplerImpl.iThreadsGathered = false; |
|
207 this->memSamplerImpl.iChunksGathered = false; |
|
208 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
209 this->memSamplerImpl.iLibrariesGathered = false; |
|
210 #endif |
|
211 |
|
212 // memory event handler |
|
213 if(iEventHandler) |
|
214 { |
|
215 // stop previous sampling if still running |
|
216 // Kern::Printf("Stopping DMemoryEventHandler"); |
|
217 iEventHandler->Stop(); |
|
218 iEventHandler->Close(); |
|
219 iEventHandler = NULL; |
|
220 } |
|
221 |
|
222 // Kern::Printf("Initiating DMemoryEventHandler"); |
|
223 iEventHandler = new DMemoryEventHandler(this->iSampleBuffer); |
|
224 if(iEventHandler) |
|
225 { |
|
226 // Kern::Printf("Creating DMemoryEventHandler"); |
|
227 TInt err(iEventHandler->Create()); |
|
228 if(err != KErrNone) |
|
229 { |
|
230 Kern::Printf("Error in creation of DMemoryEventHandler, error %d", err); |
|
231 return err; |
|
232 } |
|
233 } |
|
234 else |
|
235 { |
|
236 Kern::Printf("Could not initiate DMemoryEventHandler"); |
|
237 return KErrGeneral; |
|
238 } |
|
239 |
|
240 // set first chunk&thread memory lookup at the 5 ms, should be enough |
|
241 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
242 this->memSamplerImpl.iMemSamplingPeriod = 45; |
|
243 #else |
|
244 this->memSamplerImpl.iMemSamplingPeriod = 10; |
|
245 #endif |
|
246 |
|
247 #else |
|
248 this->memSamplerImpl.iMemSamplingPeriod = this->iSamplingPeriod; |
|
249 #endif |
|
250 this->memSamplerImpl.iMemSamplingPeriodDiv2 = (TInt)(this->memSamplerImpl.iMemSamplingPeriod / 2); |
|
251 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
252 this->memSamplerImpl.iMemSamplingPeriodDiv3 = (TInt)(this->memSamplerImpl.iMemSamplingPeriod / 3); |
|
253 #endif |
|
254 |
|
255 LOGSTRING3("CProfilerMemSampler<%d>::Reset - set mem sampling period to %d", |
|
256 BufferSize,this->memSamplerImpl.iMemSamplingPeriod); |
|
257 } |
|
258 else |
|
259 { |
|
260 LOGSTRING2("DProfilerMemSampler<%d>::Reset - reset in stop", BufferSize); |
|
261 #ifdef MEM_EVENT_HANDLER |
|
262 // destroy memory event handler |
|
263 if(iEventHandler) |
|
264 { |
|
265 // stop previous sampling if still running |
|
266 // Kern::Printf("Stopping DMemoryEventHandler"); |
|
267 iEventHandler->Stop(); |
|
268 iEventHandler->Close(); |
|
269 iEventHandler = NULL; |
|
270 } |
|
271 #endif |
|
272 return KErrNone; // return if reset called in stop |
|
273 } |
|
274 |
|
275 // add MEM sample header |
|
276 TInt length(memSamplerImpl.CreateFirstSample()); |
|
277 this->iSampleBuffer->AddSample(memSamplerImpl.sample,length); |
|
278 |
|
279 this->sampleNeeded = false; |
|
280 LOGSTRING("DProfilerMemSampler::Reset - exit"); |
|
281 return KErrNone; |
|
282 } |
|
283 |
|
284 template <int BufferSize> |
|
285 TInt DProfilerMemSampler<BufferSize>::PostSample() |
|
286 { |
|
287 this->sampleNeeded = false; |
|
288 |
|
289 LOGSTRING3("DProfilerMemSampler<%d>::PostSample - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); |
|
290 |
|
291 #ifdef MEM_EVENT_HANDLER |
|
292 // check if all threads and chunks (and libraries) are gathered |
|
293 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
294 if(!memSamplerImpl.iThreadsGathered || !memSamplerImpl.iChunksGathered || !memSamplerImpl.iLibrariesGathered) |
|
295 #else |
|
296 if(!memSamplerImpl.iThreadsGathered || !memSamplerImpl.iChunksGathered) |
|
297 #endif |
|
298 { |
|
299 #endif |
|
300 // disable interrupts for checking the kernel containers (EChunk, EThread) |
|
301 // TInt interruptLevel(NKern::DisableInterrupts(0)); |
|
302 |
|
303 // first collect chunk data |
|
304 TInt length(this->memSamplerImpl.SampleImpl()); |
|
305 if(length != 0) |
|
306 { |
|
307 // then, encode the sample to the buffer until no further data available |
|
308 while(length > 0) |
|
309 { |
|
310 this->iSampleBuffer->AddSample(memSamplerImpl.sample,length); |
|
311 length = this->memSamplerImpl.SampleImpl(); |
|
312 |
|
313 // indicate that the whole MEM sample ends by having a 0x00 in the end |
|
314 if(length == 0) |
|
315 { |
|
316 TUint8 number(0); |
|
317 LOGSTRING("MEM sampler PostSample - all samples generated!"); |
|
318 |
|
319 this->iSampleBuffer->AddSample(&number,1); |
|
320 LOGSTRING2("MEM sampler PostSample - end mark added, time: %d", gppSamplerData->sampleNumber); |
|
321 } |
|
322 } |
|
323 } |
|
324 // restore interrupts and continue normal execution |
|
325 // NKern::RestoreInterrupts(interruptLevel); |
|
326 #ifdef MEM_EVENT_HANDLER |
|
327 } |
|
328 // check if all threads and chunks are gathered |
|
329 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
330 if(memSamplerImpl.iThreadsGathered && memSamplerImpl.iChunksGathered && memSamplerImpl.iLibrariesGathered) |
|
331 #else |
|
332 if(memSamplerImpl.iThreadsGathered && memSamplerImpl.iChunksGathered) |
|
333 #endif |
|
334 { |
|
335 // start memory event tracking after checking the current memory status |
|
336 if(!iEventHandler->Tracking()) |
|
337 { |
|
338 iEventHandler->Start(); |
|
339 // Kern::Printf("DProfilerMemSampler<%d>::PostSample - memory event handler started",BufferSize); |
|
340 } |
|
341 |
|
342 } |
|
343 #endif |
|
344 |
|
345 LOGSTRING2("MEM sampler PostSample - finished sampling, time: %d", gppSamplerData->sampleNumber); |
|
346 |
|
347 // finally perform superclass postsample |
|
348 TInt i(this->DProfilerGenericSampler<BufferSize>::PostSample()); |
|
349 return i; |
|
350 } |
|
351 |
|
352 template <int BufferSize> |
|
353 TBool DProfilerMemSampler<BufferSize>::PostSampleNeeded() |
|
354 { |
|
355 LOGSTRING3("DProfilerMemSampler<%d>::PostSampleNeeded - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); |
|
356 |
|
357 TUint32 status(this->iSampleBuffer->iBufferStatus); |
|
358 |
|
359 if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull || this->sampleNeeded == true) |
|
360 { |
|
361 return true; |
|
362 } |
|
363 |
|
364 return false; |
|
365 } |
|
366 |
|
367 template <int BufferSize> |
|
368 void DProfilerMemSampler<BufferSize>::Sample() |
|
369 { |
|
370 LOGSTRING2("DProfilerMemSampler<%d>::Sample",BufferSize); |
|
371 |
|
372 // check if sample is needed, i.e. the sampling interval is met |
|
373 if(memSamplerImpl.SampleNeeded()) |
|
374 { |
|
375 // set the flag for post sampling |
|
376 this->sampleNeeded = true; |
|
377 |
|
378 // start the MEM sample with the sample time |
|
379 TUint8 number(4); // mem sampler id |
|
380 this->iSampleBuffer->AddSample(&number,1); |
|
381 this->iSampleBuffer->AddSample((TUint8*)&(gppSamplerData->sampleNumber),4); |
|
382 |
|
383 // leave the rest of the processing for PostSample() |
|
384 } |
|
385 |
|
386 #ifdef MEM_EVENT_HANDLER |
|
387 // call this to increase the time stamp |
|
388 else if(iEventHandler->SampleNeeded()) |
|
389 { |
|
390 // set the flag for post sampling |
|
391 this->sampleNeeded = true; |
|
392 } |
|
393 |
|
394 // // check if time stamp is divibable with |
|
395 // if((memSamplerImpl.iCount % KProfilerTotalMemorySamplePeriod) == 0 && |
|
396 // memSamplerImpl.iCount > 0) |
|
397 // { |
|
398 // // sample total memory once per 100 ms |
|
399 // memSamplerImpl.EncodeTotalMemory(); |
|
400 // |
|
401 // // add end mark |
|
402 // TUint8 number(0); |
|
403 // this->iSampleBuffer->AddSample(&number,1); |
|
404 // } |
|
405 #endif |
|
406 |
|
407 LOGSTRING2("CProfilerMemSampler<%d>::Sample",BufferSize); |
|
408 return; |
|
409 } |
|
410 |
|
411 template <int BufferSize> |
|
412 DProfilerMemSampler<BufferSize>::~DProfilerMemSampler() |
|
413 { |
|
414 LOGSTRING2("CProfilerMemSampler<%d>::~CProfilerMemSampler",BufferSize); |
|
415 #ifdef MEM_EVENT_HANDLER |
|
416 // memory event handler |
|
417 if(iEventHandler) |
|
418 { |
|
419 // stop previous sampling if still running |
|
420 // Kern::Printf("Stopping DMemoryEventHandler"); |
|
421 iEventHandler->Stop(); |
|
422 iEventHandler->Close(); |
|
423 iEventHandler = NULL; |
|
424 } |
|
425 #endif |
|
426 } |
|
427 #endif |