116 this->sampleDescriptor.Zero(); |
116 this->sampleDescriptor.Zero(); |
117 this->sampleDescriptor.Append(_L8("Bappea_V")); |
117 this->sampleDescriptor.Append(_L8("Bappea_V")); |
118 this->sampleDescriptor.Append(KMemVersion); |
118 this->sampleDescriptor.Append(KMemVersion); |
119 this->sampleDescriptor.Append(_L8("_MEM")); |
119 this->sampleDescriptor.Append(_L8("_MEM")); |
120 |
120 |
121 sample[0] = this->sampleDescriptor.Size(); |
121 LOGSTRING2("timestamp : 0x%04x", iCount); |
122 |
122 |
123 LOGSTRING("MemSamplerImpl::CreateFirstSample - exit"); |
123 LOGSTRING("MemSamplerImpl::CreateFirstSample - exit"); |
124 |
124 sample[0] = this->sampleDescriptor.Size(); |
125 return (TInt)(sample[0]+1); |
125 |
126 } |
126 return (TInt)(sample[0]+1); |
127 |
127 } |
128 TBool DMemSamplerImpl::SampleNeeded() |
128 |
129 { |
129 TBool DMemSamplerImpl::SampleNeeded(TUint32 sampleNum) |
130 iCount++; |
130 { |
|
131 TBool ret(false); |
|
132 iCount = sampleNum; |
131 #ifdef MEM_EVENT_HANDLER |
133 #ifdef MEM_EVENT_HANDLER |
132 // make the collection of chunks/threads only once, rest will be collected with mem event handler |
134 // make the collection of chunks/threads only once, rest will be collected with mem event handler |
133 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
135 |
134 if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv3) == 0)) |
136 // #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
135 #else |
137 // if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv3) == 0)) |
136 if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0)) |
138 // #else |
137 #endif |
139 if (iCount % iMemSamplingPeriod == 0) |
|
140 // #endif |
|
141 |
138 #else |
142 #else |
139 if ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0) |
143 if ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0) |
140 #endif |
144 #endif |
141 { |
145 { |
142 LOGSTRING2("MemSamplerImpl::SampleNeeded - time: %d", iCount); |
146 LOGSTRING2("MemSamplerImpl::SampleNeeded - time: %d", iCount); |
143 iTimeToSample = true; |
147 ret= true; |
144 return true; |
148 } |
145 } |
149 else |
146 else |
|
147 { |
150 { |
148 return false; |
151 ret=false; |
149 } |
152 } |
150 |
153 return ret; |
151 } |
154 } |
152 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
155 |
153 TInt DMemSamplerImpl::SampleImpl() |
156 /* |
154 { |
157 * When returns 0, means that all samples done. |
155 // Sample threads: |
158 * Should return length of sample available in iSample |
156 if( iSampleType == ESampleThreads ) |
159 */ |
157 { |
160 TInt DMemSamplerImpl::SampleImpl(TUint32 sampleNum) |
158 if(this->iThreadsProcessing == ENothingToProcess ) |
161 { |
159 { |
162 if(iTimeToSample) |
160 if(!iTimeToSample) |
163 { |
161 { |
164 // Sample threads: |
162 return 0; |
165 if( iSampleType == ESampleThreads && !iThreadsGathered ) |
|
166 { |
|
167 if(this->iThreadsProcessing == ENothingToProcess ) |
|
168 { |
|
169 // gather first all thread stacks |
|
170 return GatherThreads(); |
163 } |
171 } |
164 else |
172 else |
165 { |
173 { |
166 iTimeToSample = false; |
174 // process now thread stack list |
167 // gather first all thread stacks |
175 TInt length = this->ProcessThreads(); |
168 return GatherThreads(); |
176 if(length == 0) |
169 } |
177 { |
170 } |
178 this->iThreadsProcessing = ENothingToProcess; |
171 else |
179 // switch to collect chunk data |
172 { |
180 iSampleType = ESampleChunks; |
173 // process now thread stack list |
181 iThreadsGathered = ETrue; |
174 TInt length = this->ProcessThreads(); |
182 } |
175 |
183 return length; |
176 if(length == 0) |
184 } |
177 { |
185 } |
178 this->iThreadsProcessing = ENothingToProcess; |
186 // Sample chunks: |
179 // switch to collect chunk data |
187 else if( iSampleType == ESampleChunks && !iChunksGathered) |
180 iSampleType = ESampleChunks; |
188 { |
181 } |
189 if(this->iChunksProcessing == ENothingToProcess) |
182 return length; |
190 { |
183 } |
|
184 } |
|
185 |
|
186 // Sample chunks: |
|
187 if( iSampleType == ESampleChunks ) |
|
188 { |
|
189 if(this->iChunksProcessing == ENothingToProcess) |
|
190 { |
|
191 if(!iTimeToSample) |
|
192 { |
|
193 return 0; |
|
194 } |
|
195 else |
|
196 { |
|
197 iTimeToSample = false; |
|
198 // gather first all chunks |
191 // gather first all chunks |
199 return GatherChunks(); |
192 return GatherChunks(); |
200 } |
193 } |
201 } |
|
202 else |
|
203 { |
|
204 // still something to go through in lists |
|
205 TInt length = this->ProcessChunks(); |
|
206 |
|
207 if(length == 0) |
|
208 { |
|
209 this->iChunksProcessing = ENothingToProcess; |
|
210 // switch to collect library data |
|
211 iSampleType = ESampleLibraries; |
|
212 //iSampleThreads = true; |
|
213 } |
|
214 return length; |
|
215 } |
|
216 } |
|
217 |
|
218 // Sample libraries: |
|
219 if( iSampleType == ESampleLibraries ) |
|
220 { |
|
221 if(this->iLibrariesProcessing == ENothingToProcess ) |
|
222 { |
|
223 if(!iTimeToSample) |
|
224 { |
|
225 return 0; |
|
226 } |
|
227 else |
194 else |
228 { |
195 { |
229 iTimeToSample = false; |
196 // still something to go through in lists |
|
197 TInt length = this->ProcessChunks(); |
|
198 if(length == 0) |
|
199 { |
|
200 this->iChunksProcessing = ENothingToProcess; |
|
201 // switch to collect library data |
|
202 iSampleType = ESampleLibraries; |
|
203 iChunksGathered = ETrue; |
|
204 iThreadsGathered = ETrue; |
|
205 //iSampleThreads = true; |
|
206 } |
|
207 return length; |
|
208 } |
|
209 } |
|
210 |
|
211 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
|
212 // Sample libraries: |
|
213 else if( iSampleType == ESampleLibraries ) |
|
214 { |
|
215 if(this->iLibrariesProcessing == ENothingToProcess ) |
|
216 { |
230 // gather libraries |
217 // gather libraries |
231 return GatherLibraries(); |
218 return GatherLibraries(); |
232 } |
219 } |
233 } |
220 else |
|
221 { |
|
222 // process now thread stack list |
|
223 TInt length = this->ProcessLibraries(); |
|
224 if(length == 0) |
|
225 { |
|
226 this->iLibrariesProcessing = ENothingToProcess; |
|
227 // switch to collect chunk data |
|
228 iSampleType = ESampleThreads; |
|
229 iLibrariesGathered = ETrue; |
|
230 } |
|
231 return length; |
|
232 } |
|
233 } |
|
234 #endif |
234 else |
235 else |
235 { |
236 { |
236 // process now thread stack list |
237 // Will not be executed. Ever. PostSample handles the state change and starting of |
237 TInt length = this->ProcessLibraries(); |
238 // memory event handler. |
238 if(length == 0) |
239 iChunksGathered = ETrue; |
239 { |
240 iThreadsGathered = ETrue; |
240 this->iLibrariesProcessing = ENothingToProcess; |
241 iTimeToSample = false; |
241 // switch to collect chunk data |
242 Kern::Printf("MEM sampler - all initial samples generated but we should not be here...!"); |
242 iSampleType = ESampleThreads; |
243 } |
243 } |
244 } |
244 return length; |
245 else // not time to sample |
245 } |
246 { |
246 } |
247 LOGSTRING("MEM sampler - not time to sample!"); |
247 |
248 } |
248 // should not reach this point... |
249 // should not reach this point... |
249 return 0; |
250 return 0; |
250 } |
251 } |
251 #else |
252 |
252 TInt DMemSamplerImpl::SampleImpl() |
|
253 { |
|
254 // check if either chunk or thread lists have unprocessed items |
|
255 if(this->iChunksProcessing == ENothingToProcess && !iSampleThreads) |
|
256 { |
|
257 if(!iTimeToSample) |
|
258 { |
|
259 return 0; |
|
260 } |
|
261 else |
|
262 { |
|
263 iTimeToSample = false; |
|
264 // gather first all chunks |
|
265 return GatherChunks(); |
|
266 } |
|
267 } |
|
268 else if(!iSampleThreads) |
|
269 { |
|
270 // still something to go through in lists |
|
271 TInt length = this->ProcessChunks(); |
|
272 |
|
273 if(length == 0) |
|
274 { |
|
275 this->iChunksProcessing = ENothingToProcess; |
|
276 // switch to collect thread data |
|
277 iSampleThreads = true; |
|
278 } |
|
279 return length; |
|
280 } |
|
281 |
|
282 if(this->iThreadsProcessing == ENothingToProcess && iSampleThreads) |
|
283 { |
|
284 if(!iTimeToSample) |
|
285 { |
|
286 return 0; |
|
287 } |
|
288 else |
|
289 { |
|
290 iTimeToSample = false; |
|
291 // gather first all thread stacks |
|
292 return GatherThreads(); |
|
293 } |
|
294 } |
|
295 |
|
296 else if(iSampleThreads) |
|
297 { |
|
298 // process now thread stack list |
|
299 TInt length = this->ProcessThreads(); |
|
300 |
|
301 if(length == 0) |
|
302 { |
|
303 this->iThreadsProcessing = ENothingToProcess; |
|
304 // switch to collect chunk data |
|
305 iSampleThreads = false; |
|
306 } |
|
307 return length; |
|
308 } |
|
309 |
|
310 // should not reach this point... |
|
311 return 0; |
|
312 } |
|
313 #endif |
|
314 |
253 |
315 inline TInt DMemSamplerImpl::GatherChunks() |
254 inline TInt DMemSamplerImpl::GatherChunks() |
316 { |
255 { |
317 // encode a process binary |
256 // encode a process binary |
318 name.Zero(); |
257 name.Zero(); |
319 |
|
320 NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex |
258 NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex |
321 DObjectCon& chunks = *Kern::Containers()[EChunk]; |
259 DObjectCon& chunks = *Kern::Containers()[EChunk]; |
322 chunks.Wait(); // Obtain the container mutex so the list does get changed under us |
260 chunks.Wait(); // Obtain the container mutex so the list does get changed under us |
323 |
261 |
324 this->iChunkCount = 0; |
262 this->iChunkCount = 0; |
325 this->iNewChunkCount = 0; |
263 this->iNewChunkCount = 0; |
326 this->iTotalMemoryOk = false; |
264 this->iTotalMemoryOk = false; |
327 TInt totalChunkCount(chunks.Count()); |
265 TInt totalChunkCount(chunks.Count()); |
328 DChunk* c; |
266 DChunk* c; |
329 |
267 LOGSTRING2("DMemSamplerImpl::GatherChunks() chunk count %d",totalChunkCount); |
330 for(TInt i(0);i<totalChunkCount;i++) |
268 for(TInt i(0);i<totalChunkCount;i++) |
331 { |
269 { |
332 c = (DChunk*)(chunks)[i]; |
270 c = (DChunk*)(chunks)[i]; |
333 |
271 |
334 LOGSTRING3("Processing chunk %d, tag: 0x%x",i,TAG(c)); |
272 //LOGSTRING3("Processing chunk %d, tag: 0x%x",i,TAG(c)); |
335 |
273 |
336 if( (TAG(c) & 0x0000ffff) != PROFILER_CHUNK_MARK) |
274 if( (TAG(c) & 0x0000ffff) != PROFILER_CHUNK_MARK) |
337 { |
275 { |
338 LOGSTRING4("Marking chunk %d/%d, old tag 0x%x",i,(totalChunkCount-1), TAG(c)); |
276 //LOGSTRING4("Marking chunk %d/%d, old tag 0x%x",i,(totalChunkCount-1), TAG(c)); |
339 // this chunk has not been tagged yet |
277 // this chunk has not been tagged yet |
340 name.Zero(); |
278 name.Zero(); |
341 c->TraceAppendName(name,false); |
279 c->TraceAppendName(name,false); |
342 |
280 |
343 TAG(c) = (PROFILER_CHUNK_MARK); |
281 TAG(c) = (PROFILER_CHUNK_MARK); |
375 } |
312 } |
376 |
313 |
377 inline TInt DMemSamplerImpl::GatherThreads() |
314 inline TInt DMemSamplerImpl::GatherThreads() |
378 { |
315 { |
379 // The thread memory consumption |
316 // The thread memory consumption |
380 |
|
381 NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex |
317 NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex |
382 DObjectCon& threads = *Kern::Containers()[EThread]; |
318 DObjectCon& threads = *Kern::Containers()[EThread]; |
383 threads.Wait(); // Obtain the container mutex so the list does get changed under us |
319 threads.Wait(); // Obtain the container mutex so the list does get changed under us |
384 |
320 |
385 this->iThreadCount = 0; |
321 this->iThreadCount = 0; |
386 this->iNewThreadCount = 0; |
322 this->iNewThreadCount = 0; |
387 this->iTotalMemoryOk = false; |
323 this->iTotalMemoryOk = false; |
388 |
324 |
389 TInt totalThreadCount = threads.Count(); |
325 TInt totalThreadCount = threads.Count(); |
390 |
326 LOGSTRING2("DMemSamplerImpl::GatherThreads() thread count %d",totalThreadCount); |
391 for(TInt i(0);i<totalThreadCount;i++) |
327 for(TInt i(0);i<totalThreadCount;i++) |
392 { |
328 { |
393 DThread* t = (DThread*)(threads)[i]; |
329 DThread* t = (DThread*)(threads)[i]; |
394 |
330 |
395 LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t)); |
331 //LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t)); |
396 |
332 |
397 if( (TAG(t) & PROFILER_MEM_THREAD_MARK) == 0) |
333 if( (TAG(t) & PROFILER_MEM_THREAD_MARK) == 0) |
398 { |
334 { |
399 LOGSTRING4("Marking thread %d/%d, old tag 0x%x",i,(totalThreadCount-1), TAG(t)); |
335 //LOGSTRING4("Marking thread %d/%d, old tag 0x%x",i,(totalThreadCount-1), TAG(t)); |
400 // this thread's chunk has not been reported yet |
336 // this thread's chunk has not been reported yet |
401 this->threadNamesToReport[iNewThreadCount] = t; |
337 this->threadNamesToReport[iNewThreadCount] = t; |
402 iNewThreadCount++; |
338 iNewThreadCount++; |
403 // tag the thread |
339 // tag the thread |
404 TAG(t) |= PROFILER_MEM_THREAD_MARK; |
340 TAG(t) |= PROFILER_MEM_THREAD_MARK; |
405 } |
341 } |
406 |
342 |
407 // the chunk has been tagged, add heap chunks to the list |
343 // the chunk has been tagged, add heap chunks to the list |
408 this->threadsToSample[this->iThreadCount] = t; |
344 this->threadsToSample[this->iThreadCount] = t; |
409 this->iThreadCount++; |
345 this->iThreadCount++; |
410 LOGSTRING2("Added thread %d to threads to sample",i); |
346 //LOGSTRING2("Added thread %d to threads to sample",i); |
411 } |
347 } |
412 |
348 |
|
349 LOGSTRING3("Added %d threads. ithreadcount %d",totalThreadCount, iThreadCount); |
|
350 |
413 if(this->iThreadCount > 0 || this->iNewThreadCount > 0) |
351 if(this->iThreadCount > 0 || this->iNewThreadCount > 0) |
414 { |
352 { |
415 this->iThreadsProcessing = EStartingToProcess; |
353 this->iThreadsProcessing = EStartingToProcess; |
416 |
354 // process the first sample |
417 // process the first sample |
|
418 TInt length = this->ProcessThreads(); |
355 TInt length = this->ProcessThreads(); |
419 |
|
420 if(length == 0) |
356 if(length == 0) |
421 { |
357 { |
422 this->iThreadsProcessing = ENothingToProcess; |
358 this->iThreadsProcessing = ENothingToProcess; |
423 } |
359 } |
424 threads.Signal(); // Release the container mutex |
360 threads.Signal(); // Release the container mutex |
425 NKern::ThreadLeaveCS(); // End of critical section |
361 NKern::ThreadLeaveCS(); // End of critical section |
426 return length; |
362 return length; |
427 } |
363 } |
428 |
364 |
429 LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); |
365 LOGTEXT("DMemSamplerImpl::GatherThreads() - Error, no threads"); |
430 threads.Signal(); // Release the container mutex |
366 threads.Signal(); // Release the container mutex |
431 NKern::ThreadLeaveCS(); // End of critical section |
367 NKern::ThreadLeaveCS(); // End of critical section |
432 return 0; |
368 return 0; |
433 } |
369 } |
434 |
370 |
498 } |
434 } |
499 #endif |
435 #endif |
500 |
436 |
501 inline TInt DMemSamplerImpl::ProcessChunks() |
437 inline TInt DMemSamplerImpl::ProcessChunks() |
502 { |
438 { |
503 if(iNewChunkCount > 0) |
439 if(iHandledChunks < 50) |
504 { |
440 { |
505 if(this->iChunksProcessing == EStartingToProcess) |
441 if(iNewChunkCount > 0) |
506 { |
442 { |
507 // this is the first sample, encode a code for names |
443 if(this->iChunksProcessing == EStartingToProcess) |
508 this->iChunksProcessing = EProcessingNames; |
444 { |
509 return EncodeNameCode(); |
445 // this is the first sample, encode a code for names |
510 } |
446 this->iChunksProcessing = EProcessingNames; |
511 |
447 iHandledChunks++; |
512 if(iTotalMemoryNameOk == false) |
448 return EncodeNameCode(); |
513 { |
449 } |
514 return EncodeTotalMemoryName(); |
450 |
515 } |
451 if(iTotalMemoryNameOk == false) |
516 |
452 { |
517 // there are new chunk names to report |
453 iHandledChunks++; |
518 iNewChunkCount--; |
454 return EncodeTotalMemoryName(); |
519 DChunk* c = this->heapChunkNamesToReport[iNewChunkCount]; |
455 } |
520 return EncodeChunkName(*c); |
456 iNewChunkCount--; |
521 |
457 DChunk* c = this->heapChunkNamesToReport[iNewChunkCount]; |
522 } |
458 iHandledChunks++; |
523 else if(iChunkCount > 0) |
459 return EncodeChunkName(*c); |
524 { |
460 } |
525 if(this->iChunksProcessing == EProcessingNames || this->iChunksProcessing == EStartingToProcess) |
461 else if(iChunkCount > 0) |
526 { |
462 { |
527 // this is the first data sample, encode a code for data |
463 if(this->iChunksProcessing == EProcessingNames || this->iChunksProcessing == EStartingToProcess) |
528 this->iChunksProcessing = EProcessingData; |
464 { |
529 return EncodeDataCode(); |
465 // this is the first data sample, encode a code for data |
530 } |
466 this->iChunksProcessing = EProcessingData; |
531 |
467 iHandledChunks++; |
532 if(this->iTotalMemoryOk == false) |
468 return EncodeDataCode(); |
533 { |
469 } |
534 return EncodeTotalMemory(); |
470 |
535 } |
471 if(this->iTotalMemoryOk == false) |
536 |
472 { |
537 // there are no new chunks to report |
473 iHandledChunks++; |
538 // thus generate the real report |
474 return EncodeTotalMemory(); |
539 iChunkCount--; |
475 } |
540 DChunk* c = this->heapChunksToSample[iChunkCount]; |
476 |
541 return EncodeChunkData(*c); |
477 // there are no new chunks to report |
|
478 // thus generate the real report |
|
479 iChunkCount--; |
|
480 DChunk* c = this->heapChunksToSample[iChunkCount]; |
|
481 iHandledChunks++; |
|
482 return EncodeChunkData(*c); |
|
483 } |
|
484 else |
|
485 { |
|
486 // everything is processed |
|
487 LOGSTRING2("MemSamplerImpl::ProcessChunks() Chunks processed! Chunk count = %d", iChunkCount); |
|
488 #ifdef MEM_EVENT_HANDLER |
|
489 this->iChunksGathered = ETrue; |
|
490 LOGSTRING2("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount); |
|
491 #endif |
|
492 return 0; |
|
493 } |
542 } |
494 } |
543 else |
495 else |
544 { |
496 { |
545 // everything is processed |
497 LOGSTRING("MemSamplerImpl::ProcessChunks() 0"); |
546 LOGSTRING2(" Chunks processed! Chunk count = %d", iChunkCount); |
498 iHandledChunks =0; |
|
499 } |
|
500 return -1; |
|
501 } |
|
502 |
|
503 inline TInt DMemSamplerImpl::ProcessThreads() |
|
504 { |
|
505 if(iHandledThreads < 50) |
|
506 { |
|
507 if(iNewThreadCount > 0) |
|
508 { |
|
509 if(this->iThreadsProcessing == EStartingToProcess) |
|
510 { |
|
511 // this is the first sample, encode a code for names |
|
512 this->iThreadsProcessing = EProcessingNames; |
|
513 iHandledThreads++; |
|
514 return EncodeNameCode(); |
|
515 } |
|
516 |
|
517 if(iTotalMemoryNameOk == false) |
|
518 { |
|
519 LOGSTRING("MemSamplerImpl::ProcessThreads() Encoding total memory name!"); |
|
520 iHandledThreads++; |
|
521 return EncodeTotalMemoryName(); |
|
522 } |
|
523 iNewThreadCount--; |
|
524 DThread* t = this->threadNamesToReport[iNewThreadCount]; |
|
525 iHandledThreads++; |
|
526 return EncodeChunkName(*t); |
|
527 } |
|
528 else if(iThreadCount > 0) |
|
529 { |
|
530 if(this->iThreadsProcessing == EProcessingNames || this->iThreadsProcessing == EStartingToProcess) |
|
531 { |
|
532 // this is the first data sample, encode a code for data |
|
533 this->iThreadsProcessing = EProcessingData; |
|
534 iHandledThreads++; |
|
535 return EncodeDataCode(); |
|
536 } |
|
537 |
|
538 if(this->iTotalMemoryOk == false) |
|
539 { |
|
540 iHandledThreads++; |
|
541 return EncodeTotalMemory(); |
|
542 } |
|
543 |
|
544 // there are no new threads to report |
|
545 // thus generate the real report |
|
546 iThreadCount--; |
|
547 DThread* t = this->threadsToSample[iThreadCount]; |
|
548 iHandledThreads++; |
|
549 return EncodeChunkData(*t); |
|
550 } |
|
551 else |
|
552 { |
|
553 // everything is processed |
|
554 LOGSTRING2("MemSamplerImpl::ProcessThreads() Threads processed! Thread count = %d", iThreadCount); |
547 #ifdef MEM_EVENT_HANDLER |
555 #ifdef MEM_EVENT_HANDLER |
548 this->iChunksGathered = true; |
556 this->iThreadsGathered = true; |
549 Kern::Printf("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount); |
557 LOGSTRING2("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount); |
550 #endif |
558 #endif |
551 return 0; |
559 return 0; |
552 } |
560 } |
553 } |
|
554 |
|
555 inline TInt DMemSamplerImpl::ProcessThreads() |
|
556 { |
|
557 |
|
558 if(iNewThreadCount > 0) |
|
559 { |
|
560 if(this->iThreadsProcessing == EStartingToProcess) |
|
561 { |
|
562 // this is the first sample, encode a code for names |
|
563 this->iThreadsProcessing = EProcessingNames; |
|
564 return EncodeNameCode(); |
|
565 } |
|
566 |
|
567 if(iTotalMemoryNameOk == false) |
|
568 { |
|
569 return EncodeTotalMemoryName(); |
|
570 } |
|
571 |
|
572 iNewThreadCount--; |
|
573 DThread* t = this->threadNamesToReport[iNewThreadCount]; |
|
574 return EncodeChunkName(*t); |
|
575 } |
|
576 else if(iThreadCount > 0) |
|
577 { |
|
578 if(this->iThreadsProcessing == EProcessingNames || this->iThreadsProcessing == EStartingToProcess) |
|
579 { |
|
580 // this is the first data sample, encode a code for data |
|
581 this->iThreadsProcessing = EProcessingData; |
|
582 return EncodeDataCode(); |
|
583 } |
|
584 |
|
585 if(this->iTotalMemoryOk == false) |
|
586 { |
|
587 return EncodeTotalMemory(); |
|
588 } |
|
589 |
|
590 // there are no new threads to report |
|
591 // thus generate the real report |
|
592 iThreadCount--; |
|
593 DThread* t = this->threadsToSample[iThreadCount]; |
|
594 return EncodeChunkData(*t); |
|
595 } |
561 } |
596 else |
562 else |
597 { |
563 { |
598 // everything is processed |
564 LOGSTRING("MemSamplerImpl::ProcessThreads() 0"); |
599 LOGSTRING2(" Threads processed! Thread count = %d", iThreadCount); |
565 iHandledThreads=0; |
600 #ifdef MEM_EVENT_HANDLER |
566 } |
601 this->iThreadsGathered = true; |
567 return -1; |
602 Kern::Printf("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount); |
568 } |
603 #endif |
569 |
604 return 0; |
|
605 } |
|
606 } |
|
607 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
570 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
608 inline TInt DMemSamplerImpl::ProcessLibraries() |
571 inline TInt DMemSamplerImpl::ProcessLibraries() |
609 { |
572 { |
610 LOGTEXT("ProcessLibraries - entry"); |
573 LOGTEXT("ProcessLibraries - entry"); |
611 if(iNewLibraryCount > 0) |
574 |
|
575 if(iHandledLibs < 50) |
|
576 { |
|
577 if(iNewLibraryCount > 0) |
612 { |
578 { |
613 if(this->iLibrariesProcessing == EStartingToProcess) |
579 if(this->iLibrariesProcessing == EStartingToProcess) |
614 { |
580 { |
615 // this is the first sample, encode a code for names |
581 // this is the first sample, encode a code for names |
616 this->iLibrariesProcessing = EProcessingNames; |
582 this->iLibrariesProcessing = EProcessingNames; |
|
583 iHandledLibs++; |
617 return EncodeNameCode(); |
584 return EncodeNameCode(); |
618 } |
585 } |
619 |
586 |
620 if(iTotalMemoryNameOk == false) |
587 if(iTotalMemoryNameOk == false) |
621 { |
588 { |
|
589 iHandledLibs++; |
622 return EncodeTotalMemoryName(); |
590 return EncodeTotalMemoryName(); |
623 } |
591 } |
624 |
592 |
625 // there are new library names to report |
593 // there are new library names to report |
626 iNewLibraryCount--; |
594 iNewLibraryCount--; |
627 DLibrary* l = this->libraryNamesToReport[iNewLibraryCount]; |
595 DLibrary* l = this->libraryNamesToReport[iNewLibraryCount]; |
|
596 iHandledLibs++; |
628 return EncodeChunkName(*l); |
597 return EncodeChunkName(*l); |
629 |
598 |
630 } |
599 } |
631 else if(iLibraryCount > 0) |
600 else if(iLibraryCount > 0) |
632 { |
601 { |
633 if(this->iLibrariesProcessing == EProcessingNames || this->iLibrariesProcessing == EStartingToProcess) |
602 if(this->iLibrariesProcessing == EProcessingNames || this->iLibrariesProcessing == EStartingToProcess) |
634 { |
603 { |
635 // this is the first data sample, encode a code for data |
604 // this is the first data sample, encode a code for data |
636 this->iLibrariesProcessing = EProcessingData; |
605 this->iLibrariesProcessing = EProcessingData; |
|
606 iHandledLibs++; |
637 return EncodeDataCode(); |
607 return EncodeDataCode(); |
638 } |
608 } |
639 |
609 |
640 if(this->iTotalMemoryOk == false) |
610 if(this->iTotalMemoryOk == false) |
641 { |
611 { |
|
612 iHandledLibs++; |
642 return EncodeTotalMemory(); |
613 return EncodeTotalMemory(); |
643 } |
614 } |
644 |
615 |
645 // there are no new libraries to report |
616 // there are no new libraries to report |
646 // thus generate the real report |
617 // thus generate the real report |
647 iLibraryCount--; |
618 iLibraryCount--; |
648 DLibrary* l = this->librariesToSample[iLibraryCount]; |
619 DLibrary* l = this->librariesToSample[iLibraryCount]; |
|
620 iHandledLibs++; |
649 return EncodeChunkData(*l); |
621 return EncodeChunkData(*l); |
650 } |
622 } |
651 else |
623 else |
652 { |
624 { |
653 // everything is processed |
625 // everything is processed |
654 LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount); |
626 LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount); |
655 |
627 |
656 this->iLibrariesGathered = true; |
628 this->iLibrariesGathered = true; |
657 Kern::Printf("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount); |
629 LOGSTRING2("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount); |
658 |
630 |
659 return 0; |
631 return 0; |
660 } |
632 } |
661 } |
633 } |
662 #endif |
634 else |
|
635 { |
|
636 LOGSTRING("MemSamplerImpl::ProcessLibs() 0"); |
|
637 iHandledLibs =0; |
|
638 } |
|
639 return -1; |
|
640 } |
|
641 #endif |
|
642 |
663 inline TInt DMemSamplerImpl::EncodeNameCode() |
643 inline TInt DMemSamplerImpl::EncodeNameCode() |
664 { |
644 { |
665 sample[0] = 1; |
645 sample[0] = 1; |
666 sample[1] = 0xaa; |
646 sample[1] = 0xaa; |
667 return 2; |
647 return 2; |
825 |
804 |
826 // append the thread user stack size |
805 // append the thread user stack size |
827 this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); |
806 this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); |
828 *size += sizeof(TInt); |
807 *size += sizeof(TInt); |
829 |
808 |
830 LOGSTRING2("Data - %d",*size); |
809 LOGSTRING2("chunk Data - %d",*size); |
831 return ((TInt)(*size))+1; |
810 return ((TInt)(*size))+1; |
832 |
|
833 } |
811 } |
834 |
812 |
835 inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t) |
813 inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t) |
836 { |
814 { |
837 LOGTEXT("MemSamplerImpl::EncodeChunkData - entry"); |
|
838 //LOGSTRING2("MemSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t); |
|
839 |
|
840 // the size of the following name is in the first byte |
815 // the size of the following name is in the first byte |
841 TUint8* size = &sample[0]; |
816 TUint8* size = &sample[0]; |
842 *size = 0; |
817 *size = 0; |
|
818 TInt zero(0); |
843 this->sampleDescriptor.Zero(); |
819 this->sampleDescriptor.Zero(); |
844 |
820 //LOGTEXT("MemSamplerImpl::EncodeChunkData - cleared"); |
845 LOGTEXT("MemSamplerImpl::EncodeChunkData - cleared"); |
|
846 |
821 |
847 this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); |
822 this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); |
848 *size += sizeof(TUint); |
823 *size += sizeof(TUint); |
849 |
824 |
850 // copy the total amount of memory allocated for user side stack |
825 // copy the total amount of memory allocated for user side stack |
851 this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); |
826 this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); |
852 *size += sizeof(TInt); |
827 *size += sizeof(TInt); |
853 |
828 |
854 TInt zero(0); |
829 |
855 // append the cell amount allocated (zero, not in use here) |
830 // append the cell amount allocated (zero, not in use here) |
856 this->sampleDescriptor.Append((TUint8*)&zero,sizeof(TInt)); |
831 this->sampleDescriptor.Append((TUint8*)&zero,sizeof(TInt)); |
857 *size += sizeof(TInt); |
832 *size += sizeof(TInt); |
858 |
833 |
859 // append the chunk size (this is not a chunk) |
834 // append the chunk size (this is not a chunk) |
899 |
874 |
900 } |
875 } |
901 #endif |
876 #endif |
902 void DMemSamplerImpl::Reset() |
877 void DMemSamplerImpl::Reset() |
903 { |
878 { |
904 Kern::Printf("MemSamplerImpl::Reset"); |
879 LOGSTRING("MemSamplerImpl::Reset - entry"); |
905 iCount = 0; // sample threads 1 cycle after actual MEM sample time... |
880 iCount = 0; // sample threads 1 cycle after actual MEM sample time... |
906 this->iTimeToSample = false; |
881 this->iTimeToSample = true; |
907 this->iChunkCount = 0; |
882 this->iChunkCount = 0; |
908 this->iNewChunkCount = 0; |
883 this->iNewChunkCount = 0; |
909 |
884 |
910 this->iTotalMemoryOk = false; |
885 this->iTotalMemoryOk = false; |
911 this->iTotalMemoryNameOk = false; |
886 this->iTotalMemoryNameOk = false; |
912 |
887 |
913 this->iChunksProcessing = ENothingToProcess; |
888 this->iChunksProcessing = ENothingToProcess; |
914 this->iThreadsProcessing = ENothingToProcess; |
889 this->iThreadsProcessing = ENothingToProcess; |
915 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
890 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS |
916 this->iLibrariesProcessing = ENothingToProcess; |
891 this->iLibrariesProcessing = ENothingToProcess; |
|
892 #else |
917 this->iSampleType = ESampleThreads; |
893 this->iSampleType = ESampleThreads; |
918 #else |
894 //this->iSampleType = ESampleChunks; |
919 this->iSampleThreads = true; |
895 //this->iSampleThreads = true; |
920 #endif |
896 #endif |
921 |
897 this->sampleDescriptor.Zero(); |
922 this->sampleDescriptor.Zero(); |
898 // clear all chunk tags |
923 |
|
924 // clear all chunk tags |
|
925 NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex |
899 NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex |
926 DObjectCon* chunks = Kern::Containers()[EChunk]; |
900 DObjectCon* chunks = Kern::Containers()[EChunk]; |
927 chunks->Wait(); // Obtain the container mutex so the list does get changed under us |
901 chunks->Wait(); // Obtain the container mutex so the list does get changed under us |
928 |
902 |
929 TInt totalChunkCount = chunks->Count(); |
903 TInt totalChunkCount = chunks->Count(); |