piprofiler/plugins/GeneralsPlugin/src/MemSamplerImpl.cpp
changeset 20 a71a3e32a2ae
child 49 7fdc9a71d314
equal deleted inserted replaced
15:ccab7f1f8266 20:a71a3e32a2ae
       
     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 #include <piprofiler/ProfilerVersion.h>
       
    20 #include <piprofiler/ProfilerTraces.h>
       
    21 
       
    22 #include <kern_priv.h>
       
    23 #include <plat_priv.h>
       
    24 
       
    25 #include "MemSamplerImpl.h"
       
    26 
       
    27 // for testing precise stack utilization tracing...
       
    28 // crashes at the moment
       
    29 
       
    30 #include <nk_cpu.h>
       
    31 
       
    32 #if !defined(__NKERN_H__)
       
    33 #include <nkern.h>
       
    34 #endif 
       
    35 
       
    36 #define TAG(obj) (*(TUint32*)&(obj->iAsyncDeleteNext))
       
    37 #define PROFILER_CHUNK_MARK		((TUint32)0x00001000)
       
    38 #define PROFILER_MEM_THREAD_MARK	((TUint32)0x00000001)
       
    39 #define PROFILER_LIBRARY_MARK    ((TUint32)0x10000000)
       
    40 #define PROFILER_MEM_THREAD_UNMARK  ~PROFILER_MEM_THREAD_MARK
       
    41 
       
    42 #ifdef MEM_EVENT_HANDLER
       
    43 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
    44 _LIT8(KMemVersion,"2.03");
       
    45 #else
       
    46 _LIT8(KMemVersion, "2.02");
       
    47 #endif
       
    48 #else
       
    49 _LIT8(KMemVersion, "1.56");
       
    50 #endif
       
    51 
       
    52 DMemSamplerImpl::DMemSamplerImpl() :
       
    53 	sampleDescriptor(&(this->sample[1]),0,256)
       
    54     {
       
    55     LOGSTRING("MemSamplerImpl::MemSamplerImpl() - konstruktori");
       
    56 
       
    57 	iCount = 0;
       
    58 		
       
    59 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
    60 	iSampleType = ESampleThreads;
       
    61 #else
       
    62 	iSampleThreads = true;
       
    63 #endif
       
    64 	iTimeToSample = false;
       
    65 	
       
    66 	iTotalMemoryOk = false;
       
    67 	iTotalMemoryNameOk = false;
       
    68 	
       
    69 	iNewChunkCount = 0;
       
    70 	iChunkCount = 0;
       
    71 	iChunksProcessing = ENothingToProcess;
       
    72     iThreadsProcessing = ENothingToProcess;
       
    73 	
       
    74 	iNewThreadCount = 0;
       
    75 	iThreadCount = 0;
       
    76 	
       
    77 	// reset data structures
       
    78     for(TInt i(0);i<KProfilerMaxChunksAmount;i++)
       
    79         {
       
    80         // heap chunks
       
    81         this->heapChunksToSample[i] = 0;
       
    82         this->heapChunkNamesToReport[i] = 0;
       
    83         }
       
    84     
       
    85     for(TInt i(0);i<KProfilerMaxThreadsAmount;i++)
       
    86         {
       
    87         // threads
       
    88         this->threadsToSample[i] = 0;
       
    89         this->threadNamesToReport[i] = 0;
       
    90         }
       
    91     
       
    92 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
    93     iLibrariesProcessing = ENothingToProcess;
       
    94     iNewLibraryCount = 0;
       
    95     iLibraryCount = 0;
       
    96     
       
    97     for(TInt i(0); i<KProfilerMaxLibrariesAmount; i++)
       
    98         {
       
    99         // libraries
       
   100         this->librariesToSample[i] = 0;
       
   101         this->libraryNamesToReport[i] = 0;
       
   102         }
       
   103 #endif
       
   104 
       
   105     }
       
   106 
       
   107 DMemSamplerImpl::~DMemSamplerImpl()
       
   108     {
       
   109 
       
   110     }
       
   111 
       
   112 TInt DMemSamplerImpl::CreateFirstSample()
       
   113     {
       
   114     LOGSTRING("MemSamplerImpl::CreateFirstSample - entry");
       
   115 	
       
   116 	this->sampleDescriptor.Zero();
       
   117 	this->sampleDescriptor.Append(_L8("Bappea_V"));
       
   118 	this->sampleDescriptor.Append(KMemVersion);
       
   119 	this->sampleDescriptor.Append(_L8("_MEM"));
       
   120 	
       
   121 	sample[0] = this->sampleDescriptor.Size();
       
   122 
       
   123 	LOGSTRING("MemSamplerImpl::CreateFirstSample - exit");
       
   124 
       
   125 	return (TInt)(sample[0]+1);
       
   126     }
       
   127 
       
   128 TBool DMemSamplerImpl::SampleNeeded()
       
   129     {
       
   130 	iCount++;
       
   131 #ifdef MEM_EVENT_HANDLER
       
   132     // make the collection of chunks/threads only once, rest will be collected with mem event handler
       
   133 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   134 	if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv3) == 0))
       
   135 #else
       
   136     if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0))
       
   137 #endif
       
   138 #else
       
   139 	if ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0)
       
   140 #endif
       
   141 	    {
       
   142         LOGSTRING2("MemSamplerImpl::SampleNeeded - time: %d", iCount);
       
   143 		iTimeToSample = true;
       
   144 		return true;
       
   145         }
       
   146 	else 
       
   147 	    {
       
   148 		return false;
       
   149         }
       
   150 
       
   151     }
       
   152 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   153 TInt DMemSamplerImpl::SampleImpl()
       
   154     {    
       
   155     // Sample threads:
       
   156     if( iSampleType == ESampleThreads )
       
   157         {    
       
   158         if(this->iThreadsProcessing == ENothingToProcess )
       
   159             {     
       
   160             if(!iTimeToSample)
       
   161                 {
       
   162                 return 0;
       
   163                 }
       
   164             else
       
   165                 {
       
   166                 iTimeToSample = false;
       
   167                 // gather first all thread stacks
       
   168                 return GatherThreads();
       
   169                 }
       
   170             }
       
   171         else
       
   172             {
       
   173             // process now thread stack list
       
   174             TInt length = this->ProcessThreads();
       
   175 
       
   176             if(length == 0)
       
   177                 {
       
   178                 this->iThreadsProcessing = ENothingToProcess;
       
   179                 // switch to collect chunk data
       
   180                 iSampleType = ESampleChunks;
       
   181                 }
       
   182             return length;
       
   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
       
   199                 return GatherChunks();
       
   200                 }
       
   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
       
   228                 {
       
   229                 iTimeToSample = false;
       
   230                 // gather libraries
       
   231                 return GatherLibraries();
       
   232                 }
       
   233             }
       
   234         else
       
   235             {
       
   236             // process now thread stack list
       
   237             TInt length = this->ProcessLibraries();
       
   238             if(length == 0)
       
   239                 {
       
   240                 this->iLibrariesProcessing = ENothingToProcess;
       
   241                 // switch to collect chunk data
       
   242                 iSampleType = ESampleThreads;
       
   243                 }
       
   244             return length;
       
   245             }
       
   246         }
       
   247 
       
   248     // should not reach this point...
       
   249     return 0;
       
   250     }
       
   251 #else
       
   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 
       
   315 inline TInt DMemSamplerImpl::GatherChunks()
       
   316     {
       
   317     // encode a process binary
       
   318     name.Zero();
       
   319     
       
   320     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   321     DObjectCon& chunks = *Kern::Containers()[EChunk];
       
   322     chunks.Wait();  // Obtain the container mutex so the list does get changed under us
       
   323     
       
   324     this->iChunkCount = 0; 
       
   325     this->iNewChunkCount = 0;
       
   326     this->iTotalMemoryOk = false;
       
   327     TInt totalChunkCount(chunks.Count());
       
   328     DChunk* c; 
       
   329     
       
   330     for(TInt i(0);i<totalChunkCount;i++)
       
   331         {
       
   332         c = (DChunk*)(chunks)[i];
       
   333 
       
   334         LOGSTRING3("Processing chunk %d, tag: 0x%x",i,TAG(c));
       
   335         
       
   336         if( (TAG(c) & 0x0000ffff) != PROFILER_CHUNK_MARK)
       
   337             {
       
   338             LOGSTRING4("Marking chunk %d/%d, old tag 0x%x",i,(totalChunkCount-1), TAG(c));
       
   339             // this chunk has not been tagged yet
       
   340             name.Zero();
       
   341             c->TraceAppendName(name,false);
       
   342             const TUint8* ptr = name.Ptr();
       
   343             
       
   344             TAG(c) = (PROFILER_CHUNK_MARK);
       
   345             this->heapChunkNamesToReport[iNewChunkCount] = c;
       
   346             iNewChunkCount++;
       
   347             }
       
   348 
       
   349         // the chunk has been tagged, add heap chunks to the list
       
   350         this->heapChunksToSample[this->iChunkCount] = c;
       
   351         this->iChunkCount++;
       
   352         LOGSTRING2("Added chunk %d to Chunks",i);
       
   353         }
       
   354 
       
   355     if(this->iChunkCount > 0 || this->iNewChunkCount > 0)
       
   356         {
       
   357         this->iChunksProcessing = EStartingToProcess;
       
   358         
       
   359         // process the first sample
       
   360         TInt length = this->ProcessChunks();
       
   361         
       
   362         if(length == 0)
       
   363             {
       
   364             this->iChunksProcessing = ENothingToProcess;
       
   365             }
       
   366     
       
   367         chunks.Signal();  // Release the container mutex
       
   368         NKern::ThreadLeaveCS();  // End of critical section
       
   369         return length;
       
   370         }
       
   371 
       
   372     LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); 
       
   373     chunks.Signal();  // Release the container mutex
       
   374     NKern::ThreadLeaveCS();  // End of critical section
       
   375     return 0;
       
   376     }
       
   377 
       
   378 inline TInt DMemSamplerImpl::GatherThreads()
       
   379     {
       
   380     // The thread memory consumption
       
   381     
       
   382     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   383     DObjectCon& threads = *Kern::Containers()[EThread];
       
   384     threads.Wait(); // Obtain the container mutex so the list does get changed under us
       
   385     
       
   386     this->iThreadCount = 0; 
       
   387     this->iNewThreadCount = 0;
       
   388     this->iTotalMemoryOk = false;           
       
   389 
       
   390     TInt totalThreadCount = threads.Count();
       
   391 
       
   392     for(TInt i(0);i<totalThreadCount;i++)
       
   393         {
       
   394         DThread* t = (DThread*)(threads)[i];
       
   395 
       
   396         LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t));
       
   397 
       
   398         if( (TAG(t) & PROFILER_MEM_THREAD_MARK) == 0)
       
   399             {
       
   400             LOGSTRING4("Marking thread %d/%d, old tag 0x%x",i,(totalThreadCount-1), TAG(t));
       
   401             // this thread's chunk has not been reported yet
       
   402             this->threadNamesToReport[iNewThreadCount] = t;
       
   403             iNewThreadCount++;
       
   404             // tag the thread
       
   405             TAG(t) |= PROFILER_MEM_THREAD_MARK;
       
   406             }
       
   407 
       
   408         // the chunk has been tagged, add heap chunks to the list
       
   409         this->threadsToSample[this->iThreadCount] = t;
       
   410         this->iThreadCount++;
       
   411         LOGSTRING2("Added thread %d to threads to sample",i);
       
   412         }
       
   413     
       
   414     if(this->iThreadCount > 0 || this->iNewThreadCount > 0)
       
   415         {
       
   416         this->iThreadsProcessing = EStartingToProcess;
       
   417         
       
   418         // process the first sample
       
   419         TInt length = this->ProcessThreads();
       
   420         
       
   421         if(length == 0)
       
   422             {
       
   423             this->iThreadsProcessing = ENothingToProcess;
       
   424             }
       
   425         threads.Signal();  // Release the container mutex
       
   426         NKern::ThreadLeaveCS();  // End of critical section
       
   427         return length;
       
   428         }
       
   429     
       
   430     LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); 
       
   431     threads.Signal();  // Release the container mutex
       
   432     NKern::ThreadLeaveCS();  // End of critical section
       
   433     return 0;
       
   434     }
       
   435 
       
   436 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   437 
       
   438 inline TInt DMemSamplerImpl::GatherLibraries()
       
   439     {
       
   440     LOGTEXT("MemSamplerImpl::GatherLibraries() - entry");
       
   441     // encode a process binary
       
   442     name.Zero();
       
   443     
       
   444     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   445     DObjectCon& libs = *Kern::Containers()[ELibrary];
       
   446     libs.Wait();  // Obtain the container mutex so the list does get changed under us
       
   447     
       
   448     this->iLibraryCount = 0; 
       
   449     this->iNewLibraryCount = 0;
       
   450     this->iTotalMemoryOk = false;
       
   451     TInt totalLibCount(libs.Count());
       
   452     DLibrary* l; 
       
   453     
       
   454     for(TInt i(0);i<totalLibCount;i++)
       
   455         {
       
   456         l = (DLibrary*)(libs)[i];
       
   457 
       
   458         LOGSTRING3("Processing library %d, tag: 0x%x",i,TAG(l));
       
   459         
       
   460         if( (TAG(l) & 0xffffffff) != PROFILER_LIBRARY_MARK)
       
   461             {
       
   462             LOGSTRING4("Marking library %d/%d, old tag 0x%x",i,(totalLibCount-1), TAG(l));
       
   463             // this library has not been tagged yet
       
   464             name.Zero();
       
   465             l->TraceAppendName(name,false);
       
   466             const TUint8* ptr = name.Ptr();
       
   467             
       
   468             TAG(l) = (PROFILER_LIBRARY_MARK);
       
   469             this->libraryNamesToReport[iNewLibraryCount] = l;
       
   470             iNewLibraryCount++;
       
   471             }
       
   472 
       
   473         // the library has been tagged, add library to the list
       
   474         this->librariesToSample[this->iLibraryCount] = l;
       
   475         this->iLibraryCount++;
       
   476         LOGSTRING2("Added library %d to Libraries",i);
       
   477         }
       
   478 
       
   479     if(this->iLibraryCount > 0 || this->iNewLibraryCount > 0)
       
   480         {
       
   481         this->iLibrariesProcessing = EStartingToProcess;
       
   482         
       
   483         // process the first sample
       
   484         TInt length = this->ProcessLibraries();
       
   485         
       
   486         if(length == 0)
       
   487             {
       
   488             this->iLibrariesProcessing = ENothingToProcess;
       
   489             }
       
   490     
       
   491         libs.Signal();  // Release the container mutex
       
   492         NKern::ThreadLeaveCS();  // End of critical section
       
   493         return length;
       
   494         }
       
   495 
       
   496     LOGTEXT("MemSamplerImpl::SampleImpl - Error, no libraries"); 
       
   497     libs.Signal();  // Release the container mutex
       
   498     NKern::ThreadLeaveCS();  // End of critical section
       
   499     return 0;
       
   500     }
       
   501 #endif
       
   502 
       
   503 inline TInt DMemSamplerImpl::ProcessChunks()
       
   504     {
       
   505     if(iNewChunkCount > 0)
       
   506         {
       
   507         if(this->iChunksProcessing == EStartingToProcess)
       
   508             {
       
   509             // this is the first sample, encode a code for names
       
   510             this->iChunksProcessing = EProcessingNames;
       
   511             return EncodeNameCode();
       
   512             }
       
   513 
       
   514         if(iTotalMemoryNameOk == false)
       
   515             {
       
   516             return EncodeTotalMemoryName();
       
   517             }
       
   518         
       
   519         // there are new chunk names to report
       
   520         iNewChunkCount--;
       
   521         DChunk* c = this->heapChunkNamesToReport[iNewChunkCount];
       
   522         return EncodeChunkName(*c);
       
   523         
       
   524         }
       
   525     else if(iChunkCount > 0)
       
   526         {
       
   527         if(this->iChunksProcessing == EProcessingNames || this->iChunksProcessing == EStartingToProcess)
       
   528             {
       
   529             // this is the first data sample, encode a code for data
       
   530             this->iChunksProcessing = EProcessingData;
       
   531             return EncodeDataCode();
       
   532             }
       
   533         
       
   534         if(this->iTotalMemoryOk == false)
       
   535             {
       
   536             return EncodeTotalMemory();	
       
   537             }
       
   538 
       
   539         // there are no new chunks to report
       
   540         // thus generate the real report
       
   541         iChunkCount--;
       
   542         DChunk* c = this->heapChunksToSample[iChunkCount];
       
   543         return EncodeChunkData(*c);
       
   544         }
       
   545     else
       
   546         {
       
   547         // everything is processed
       
   548         LOGSTRING2(" Chunks processed! Chunk count = %d", iChunkCount);
       
   549 #ifdef MEM_EVENT_HANDLER
       
   550         this->iChunksGathered = true;
       
   551         Kern::Printf("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount);
       
   552 #endif
       
   553         return 0;
       
   554         }
       
   555     }
       
   556 
       
   557 inline TInt DMemSamplerImpl::ProcessThreads()
       
   558     {
       
   559 
       
   560     if(iNewThreadCount > 0)
       
   561         {
       
   562         if(this->iThreadsProcessing == EStartingToProcess)
       
   563             {
       
   564             // this is the first sample, encode a code for names
       
   565             this->iThreadsProcessing = EProcessingNames;
       
   566             return EncodeNameCode();
       
   567             }
       
   568         
       
   569         if(iTotalMemoryNameOk == false)
       
   570             {
       
   571             return EncodeTotalMemoryName();
       
   572             }
       
   573 
       
   574         iNewThreadCount--;
       
   575         DThread* t = this->threadNamesToReport[iNewThreadCount];
       
   576         return EncodeChunkName(*t);
       
   577         }
       
   578     else if(iThreadCount > 0)
       
   579         {
       
   580         if(this->iThreadsProcessing == EProcessingNames || this->iThreadsProcessing == EStartingToProcess)
       
   581             {
       
   582             // this is the first data sample, encode a code for data
       
   583             this->iThreadsProcessing = EProcessingData;
       
   584             return EncodeDataCode();
       
   585             }
       
   586 
       
   587         if(this->iTotalMemoryOk == false)
       
   588             {
       
   589             return EncodeTotalMemory(); 
       
   590             }
       
   591 
       
   592         // there are no new threads to report
       
   593         // thus generate the real report
       
   594         iThreadCount--;
       
   595         DThread* t = this->threadsToSample[iThreadCount];
       
   596         return EncodeChunkData(*t);
       
   597         }
       
   598     else
       
   599         {   
       
   600         // everything is processed
       
   601         LOGSTRING2(" Threads processed! Thread count = %d", iThreadCount);
       
   602 #ifdef MEM_EVENT_HANDLER
       
   603         this->iThreadsGathered = true;
       
   604         Kern::Printf("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount);
       
   605 #endif
       
   606         return 0;
       
   607         }
       
   608     }
       
   609 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   610 inline TInt DMemSamplerImpl::ProcessLibraries()
       
   611     {
       
   612     LOGTEXT("ProcessLibraries - entry");
       
   613     if(iNewLibraryCount > 0)
       
   614         {
       
   615         if(this->iLibrariesProcessing == EStartingToProcess)
       
   616             {
       
   617             // this is the first sample, encode a code for names
       
   618             this->iLibrariesProcessing = EProcessingNames;
       
   619             return EncodeNameCode();
       
   620             }
       
   621 
       
   622         if(iTotalMemoryNameOk == false)
       
   623             {
       
   624             return EncodeTotalMemoryName();
       
   625             }
       
   626         
       
   627         // there are new library names to report
       
   628         iNewLibraryCount--;
       
   629         DLibrary* l = this->libraryNamesToReport[iNewLibraryCount];
       
   630         return EncodeChunkName(*l);
       
   631         
       
   632         }
       
   633     else if(iLibraryCount > 0)
       
   634         {
       
   635         if(this->iLibrariesProcessing == EProcessingNames || this->iLibrariesProcessing == EStartingToProcess)
       
   636             {
       
   637             // this is the first data sample, encode a code for data
       
   638             this->iLibrariesProcessing = EProcessingData;
       
   639             return EncodeDataCode();
       
   640             }
       
   641         
       
   642         if(this->iTotalMemoryOk == false)
       
   643             {
       
   644             return EncodeTotalMemory(); 
       
   645             }
       
   646 
       
   647         // there are no new libraries to report
       
   648         // thus generate the real report
       
   649         iLibraryCount--;
       
   650         DLibrary* l = this->librariesToSample[iLibraryCount];
       
   651         return EncodeChunkData(*l);
       
   652         }
       
   653     else
       
   654         {
       
   655         // everything is processed
       
   656         LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount);
       
   657 
       
   658         this->iLibrariesGathered = true;
       
   659         Kern::Printf("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount);
       
   660 
       
   661         return 0;
       
   662         }
       
   663     }
       
   664 #endif
       
   665 inline TInt DMemSamplerImpl::EncodeNameCode()
       
   666     {
       
   667 	sample[0] = 1;
       
   668 	sample[1] = 0xaa;
       
   669 	return 2;
       
   670     }
       
   671 
       
   672 inline TInt DMemSamplerImpl::EncodeDataCode()
       
   673     {
       
   674 	sample[0] = 1;
       
   675 	sample[1] = 0xdd;
       
   676 	return 2;
       
   677     }
       
   678 
       
   679 inline TInt DMemSamplerImpl::EncodeTotalMemoryName()
       
   680     {
       
   681 	this->iTotalMemoryNameOk = true;
       
   682 	
       
   683 	TUint8* size = &sample[0];
       
   684 	*size = 0;
       
   685 		
       
   686 	// encode name
       
   687 	this->sampleDescriptor.Zero();
       
   688 	this->sampleDescriptor.Append(_L("TOTAL_MEMORY"));
       
   689 	*size += this->sampleDescriptor.Size();
       
   690 		
       
   691 	// add id here
       
   692 	TUint32 id(0xbabbeaaa);
       
   693 	this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32));
       
   694 	*size += sizeof(TUint32);
       
   695 	
       
   696 	// the size is the descriptor length + the size field
       
   697 	return ((TInt)(*size))+1;	
       
   698     }
       
   699 
       
   700 inline TInt DMemSamplerImpl::EncodeTotalMemory()
       
   701     {	
       
   702 	
       
   703 	TUint8* size = &sample[0];
       
   704 	*size = 0;
       
   705 
       
   706 	NKern::LockSystem();
       
   707 	TInt freeRam = Kern::FreeRamInBytes();
       
   708 	TInt totalRam = Kern::SuperPage().iTotalRamSize;
       
   709 	NKern::UnlockSystem();
       
   710 
       
   711 	this->sampleDescriptor.Zero();
       
   712 	
       
   713 	TUint32 id(0xbabbeaaa);
       
   714 	TInt zero(0);
       
   715 		
       
   716 	this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32));
       
   717 	*size += sizeof(TUint);
       
   718 	
       
   719 	this->sampleDescriptor.Append((TUint8*)&(totalRam),sizeof(TInt));
       
   720 	*size += sizeof(TInt);
       
   721 		
       
   722 	// append the cell amount allocated
       
   723 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   724 	*size += sizeof(TInt);
       
   725 	
       
   726 	// append the chunk size
       
   727 	this->sampleDescriptor.Append((TUint8*)&(freeRam),sizeof(TInt));
       
   728 	*size += sizeof(TInt);
       
   729 		
       
   730 	// append the thread user stack size
       
   731 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   732 	*size += sizeof(TInt);
       
   733 
       
   734 	this->iTotalMemoryOk = true;
       
   735 
       
   736 	return ((TInt)(*size))+1;
       
   737     }
       
   738 
       
   739 inline TInt DMemSamplerImpl::EncodeChunkName(DChunk& c)
       
   740     {	
       
   741 	// the size of the following name is in the first byte
       
   742 	TUint8* size = &sample[0];
       
   743 	*size = 0;
       
   744 		
       
   745 	// encode chunk name
       
   746 	this->sampleDescriptor.Zero();
       
   747 	this->sampleDescriptor.Append(_L("C_"));
       
   748 	c.TraceAppendFullName(this->sampleDescriptor,false);
       
   749 	*size += this->sampleDescriptor.Size();
       
   750 		
       
   751 	// add chunk object address here
       
   752 	TUint32 chunkAddr((TUint32)&c);
       
   753 	this->sampleDescriptor.Append((TUint8*)&(chunkAddr),sizeof(TUint32));
       
   754 	*size += sizeof(TUint32);
       
   755 
       
   756 	// the size is the descriptor length + the size field
       
   757 	LOGSTRING2("Non-Heap Chunk Name - %d",*size);
       
   758 	return ((TInt)(*size))+1;			
       
   759     }
       
   760 
       
   761 inline TInt DMemSamplerImpl::EncodeChunkName(DThread& t)
       
   762     {		
       
   763 	// the size of the following name is in the first byte
       
   764 	TUint8* size = &sample[0];
       
   765 	*size = 0;
       
   766 	this->sampleDescriptor.Zero();
       
   767 	
       
   768 	this->sampleDescriptor.Append(_L("T_"));
       
   769 	t.TraceAppendFullName(this->sampleDescriptor,false);
       
   770 	*size += this->sampleDescriptor.Size();
       
   771 	
       
   772 	// copy the 4 bytes from the thread id field
       
   773 	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
       
   774 	*size += sizeof(TUint);
       
   775 
       
   776 	// the size is the descriptor length + the size field
       
   777 	LOGSTRING2("Name - %d",*size);
       
   778 	return ((TInt)(*size))+1;
       
   779     }
       
   780 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   781 inline TInt DMemSamplerImpl::EncodeChunkName(DLibrary& l)
       
   782     {   
       
   783     // the size of the following name is in the first byte
       
   784     TUint8* size = &sample[0];
       
   785     *size = 0;
       
   786         
       
   787     // encode library name
       
   788     this->sampleDescriptor.Zero();
       
   789     this->sampleDescriptor.Append(_L("L_"));
       
   790     l.TraceAppendFullName(this->sampleDescriptor,false);
       
   791     *size += this->sampleDescriptor.Size();
       
   792         
       
   793     // add chunk object address here
       
   794     TUint32 libAddr((TUint32)&l);
       
   795     this->sampleDescriptor.Append((TUint8*)&(libAddr),sizeof(TUint32));
       
   796     *size += sizeof(TUint32);
       
   797 
       
   798     // the size is the descriptor length + the size field
       
   799     LOGSTRING2("Name - %d",*size);
       
   800     return ((TInt)(*size))+1;           
       
   801     }
       
   802 #endif
       
   803 inline TInt DMemSamplerImpl::EncodeChunkData(DChunk& c)
       
   804     {
       
   805 	// the size of the following name is in the first byte
       
   806 	TUint8* size = &sample[0];
       
   807 	*size = 0;
       
   808 	this->sampleDescriptor.Zero();
       
   809 	TInt zero(0);
       
   810 
       
   811 	TUint32 address((TUint32)&c);
       
   812 		
       
   813 	this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
       
   814 	*size += sizeof(TUint);
       
   815 	
       
   816 	// copy the total amount of memory allocated
       
   817 	this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TInt));
       
   818 	*size += sizeof(TInt);
       
   819 		
       
   820 	// append the cell amount allocated
       
   821 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   822 	*size += sizeof(TInt);
       
   823 	
       
   824 	// append the chunk size
       
   825 	this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TUint));
       
   826 	*size += sizeof(TUint);
       
   827 		
       
   828 	// append the thread user stack size
       
   829 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   830 	*size += sizeof(TInt);
       
   831 
       
   832 	LOGSTRING2("Data - %d",*size);
       
   833 	return ((TInt)(*size))+1;
       
   834 
       
   835     }
       
   836 
       
   837 inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t)
       
   838     {
       
   839 	LOGTEXT("MemSamplerImpl::EncodeChunkData - entry");
       
   840 	//LOGSTRING2("MemSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t);
       
   841 		
       
   842 	// the size of the following name is in the first byte
       
   843 	TUint8* size = &sample[0];
       
   844 	*size = 0;
       
   845 	this->sampleDescriptor.Zero();
       
   846 
       
   847 	LOGTEXT("MemSamplerImpl::EncodeChunkData - cleared");
       
   848 
       
   849 	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
       
   850 	*size += sizeof(TUint);
       
   851 		
       
   852 	// copy the total amount of memory allocated for user side stack
       
   853 	this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt));
       
   854 	*size += sizeof(TInt);
       
   855 
       
   856 	TInt zero(0);		
       
   857 	// append the cell amount allocated (zero, not in use here)
       
   858 	this->sampleDescriptor.Append((TUint8*)&zero,sizeof(TInt));
       
   859 	*size += sizeof(TInt);
       
   860 	
       
   861 	// append the chunk size (this is not a chunk)
       
   862 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint));
       
   863 	*size += sizeof(TUint);
       
   864 
       
   865 	// append user stack (max) size
       
   866 	this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt));
       
   867 	*size += sizeof(TInt);
       
   868 
       
   869 	LOGSTRING2("Data -> %d",*size);
       
   870 	return ((TInt)(*size))+1;
       
   871     }
       
   872 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   873 inline TInt DMemSamplerImpl::EncodeChunkData(DLibrary& l)
       
   874     {
       
   875     LOGTEXT("MemSamplerImpl::EncodeChunkData (Library) - entry");
       
   876     // the size of the following name is in the first byte
       
   877     TUint8* size = &sample[0];
       
   878     *size = 0;
       
   879     this->sampleDescriptor.Zero();
       
   880     
       
   881     TUint32 address((TUint32)&l);
       
   882         
       
   883     this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
       
   884     *size += sizeof(TUint);
       
   885              
       
   886 	this->sampleDescriptor.Append((TUint8*)&(l.iCodeSeg->iSize),sizeof(TUint32));
       
   887     *size += sizeof(TInt); 
       
   888              
       
   889     this->sampleDescriptor.Append((TUint8*)&(l.iMapCount),sizeof(TInt));
       
   890     *size += sizeof(TInt);  
       
   891         
       
   892     TInt zero(0);   
       
   893     this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   894     *size += sizeof(TInt);   
       
   895         
       
   896     this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   897     *size += sizeof(TInt);   
       
   898 
       
   899     LOGSTRING2("LData - %d",*size);
       
   900     return ((TInt)(*size))+1;
       
   901 
       
   902     }
       
   903 #endif
       
   904 void DMemSamplerImpl::Reset()
       
   905     {
       
   906 	Kern::Printf("MemSamplerImpl::Reset");
       
   907 	iCount = 0; // sample threads 1 cycle after actual MEM sample time...
       
   908     this->iTimeToSample = false;
       
   909     this->iChunkCount = 0;
       
   910 	this->iNewChunkCount = 0;
       
   911 	
       
   912 	this->iTotalMemoryOk = false;
       
   913 	this->iTotalMemoryNameOk = false;
       
   914 
       
   915 	this->iChunksProcessing = ENothingToProcess;
       
   916     this->iThreadsProcessing = ENothingToProcess;
       
   917 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   918     this->iLibrariesProcessing = ENothingToProcess;
       
   919     this->iSampleType = ESampleThreads;
       
   920 #else
       
   921     this->iSampleThreads = true;
       
   922 #endif
       
   923     
       
   924 	this->sampleDescriptor.Zero();
       
   925 	
       
   926 	// clear all chunk tags
       
   927     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   928 	DObjectCon* chunks = Kern::Containers()[EChunk];
       
   929     chunks->Wait(); // Obtain the container mutex so the list does get changed under us
       
   930 
       
   931 	TInt totalChunkCount = chunks->Count();
       
   932 	for(TInt i=0;i<totalChunkCount;i++)
       
   933 	    {
       
   934 		DChunk* c = (DChunk*)(*chunks)[i];
       
   935 		TAG(c) = 0;
       
   936 	    }
       
   937 	chunks->Signal();  // Release the container mutex
       
   938 
       
   939 	Kern::Printf("MemSamplerImpl::Reset");
       
   940 	this->iThreadCount = 0;
       
   941 	this->iNewThreadCount = 0;
       
   942 	this->sampleDescriptor.Zero();
       
   943 
       
   944 	// clear all chunk tags
       
   945 	DObjectCon* threads = Kern::Containers()[EThread];
       
   946     threads->Wait(); // Obtain the container mutex so the list does get changed under us
       
   947 
       
   948 	TInt totalThreadCount = threads->Count();
       
   949 	for(TInt i=0;i<totalThreadCount;i++)
       
   950 	    {
       
   951 		DThread* t = (DThread*)(*threads)[i];
       
   952 		TAG(t) = (TAG(t) & 0xfffffffe);
       
   953 	    }
       
   954 	threads->Signal();  // Release the container mutex
       
   955 	
       
   956 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   957 	this->iLibraryCount = 0;
       
   958 	this->iNewLibraryCount = 0;
       
   959 	this->sampleDescriptor.Zero();
       
   960 
       
   961 	// clear all library tags
       
   962 	DObjectCon* libs = Kern::Containers()[ELibrary];
       
   963 	libs->Wait(); // Obtain the container mutex so the list does get changed under us
       
   964 
       
   965 	TInt totalLibraryCount = libs->Count();
       
   966 	for(TInt i=0; i<totalLibraryCount; i++)
       
   967 	    {
       
   968         DLibrary* l = (DLibrary*)(*libs)[i];
       
   969         TAG(l) = (TAG(l) & 0xefffffff);
       
   970 	    }
       
   971 	libs->Signal();  // Release the container mutex
       
   972 #endif
       
   973 
       
   974     NKern::ThreadLeaveCS();  // End of critical section
       
   975     }
       
   976