perfsrv/piprofiler/plugins/GeneralsPlugin/src/MemSamplerImpl.cpp
changeset 51 98307c651589
child 62 1c2bb2fc7c87
equal deleted inserted replaced
42:0ff24a8f6ca2 51:98307c651589
       
     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             
       
   343             TAG(c) = (PROFILER_CHUNK_MARK);
       
   344             this->heapChunkNamesToReport[iNewChunkCount] = c;
       
   345             iNewChunkCount++;
       
   346             }
       
   347 
       
   348         // the chunk has been tagged, add heap chunks to the list
       
   349         this->heapChunksToSample[this->iChunkCount] = c;
       
   350         this->iChunkCount++;
       
   351         LOGSTRING2("Added chunk %d to Chunks",i);
       
   352         }
       
   353 
       
   354     if(this->iChunkCount > 0 || this->iNewChunkCount > 0)
       
   355         {
       
   356         this->iChunksProcessing = EStartingToProcess;
       
   357         
       
   358         // process the first sample
       
   359         TInt length = this->ProcessChunks();
       
   360         
       
   361         if(length == 0)
       
   362             {
       
   363             this->iChunksProcessing = ENothingToProcess;
       
   364             }
       
   365     
       
   366         chunks.Signal();  // Release the container mutex
       
   367         NKern::ThreadLeaveCS();  // End of critical section
       
   368         return length;
       
   369         }
       
   370 
       
   371     LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); 
       
   372     chunks.Signal();  // Release the container mutex
       
   373     NKern::ThreadLeaveCS();  // End of critical section
       
   374     return 0;
       
   375     }
       
   376 
       
   377 inline TInt DMemSamplerImpl::GatherThreads()
       
   378     {
       
   379     // The thread memory consumption
       
   380     
       
   381     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   382     DObjectCon& threads = *Kern::Containers()[EThread];
       
   383     threads.Wait(); // Obtain the container mutex so the list does get changed under us
       
   384     
       
   385     this->iThreadCount = 0; 
       
   386     this->iNewThreadCount = 0;
       
   387     this->iTotalMemoryOk = false;           
       
   388 
       
   389     TInt totalThreadCount = threads.Count();
       
   390 
       
   391     for(TInt i(0);i<totalThreadCount;i++)
       
   392         {
       
   393         DThread* t = (DThread*)(threads)[i];
       
   394 
       
   395         LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t));
       
   396 
       
   397         if( (TAG(t) & PROFILER_MEM_THREAD_MARK) == 0)
       
   398             {
       
   399             LOGSTRING4("Marking thread %d/%d, old tag 0x%x",i,(totalThreadCount-1), TAG(t));
       
   400             // this thread's chunk has not been reported yet
       
   401             this->threadNamesToReport[iNewThreadCount] = t;
       
   402             iNewThreadCount++;
       
   403             // tag the thread
       
   404             TAG(t) |= PROFILER_MEM_THREAD_MARK;
       
   405             }
       
   406 
       
   407         // the chunk has been tagged, add heap chunks to the list
       
   408         this->threadsToSample[this->iThreadCount] = t;
       
   409         this->iThreadCount++;
       
   410         LOGSTRING2("Added thread %d to threads to sample",i);
       
   411         }
       
   412     
       
   413     if(this->iThreadCount > 0 || this->iNewThreadCount > 0)
       
   414         {
       
   415         this->iThreadsProcessing = EStartingToProcess;
       
   416         
       
   417         // process the first sample
       
   418         TInt length = this->ProcessThreads();
       
   419         
       
   420         if(length == 0)
       
   421             {
       
   422             this->iThreadsProcessing = ENothingToProcess;
       
   423             }
       
   424         threads.Signal();  // Release the container mutex
       
   425         NKern::ThreadLeaveCS();  // End of critical section
       
   426         return length;
       
   427         }
       
   428     
       
   429     LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); 
       
   430     threads.Signal();  // Release the container mutex
       
   431     NKern::ThreadLeaveCS();  // End of critical section
       
   432     return 0;
       
   433     }
       
   434 
       
   435 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   436 
       
   437 inline TInt DMemSamplerImpl::GatherLibraries()
       
   438     {
       
   439     LOGTEXT("MemSamplerImpl::GatherLibraries() - entry");
       
   440     // encode a process binary
       
   441     name.Zero();
       
   442     
       
   443     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   444     DObjectCon& libs = *Kern::Containers()[ELibrary];
       
   445     libs.Wait();  // Obtain the container mutex so the list does get changed under us
       
   446     
       
   447     this->iLibraryCount = 0; 
       
   448     this->iNewLibraryCount = 0;
       
   449     this->iTotalMemoryOk = false;
       
   450     TInt totalLibCount(libs.Count());
       
   451     DLibrary* l; 
       
   452     
       
   453     for(TInt i(0);i<totalLibCount;i++)
       
   454         {
       
   455         l = (DLibrary*)(libs)[i];
       
   456 
       
   457         LOGSTRING3("Processing library %d, tag: 0x%x",i,TAG(l));
       
   458         
       
   459         if( (TAG(l) & 0xffffffff) != PROFILER_LIBRARY_MARK)
       
   460             {
       
   461             LOGSTRING4("Marking library %d/%d, old tag 0x%x",i,(totalLibCount-1), TAG(l));
       
   462             // this library has not been tagged yet
       
   463             name.Zero();
       
   464             l->TraceAppendName(name,false);
       
   465             
       
   466             TAG(l) = (PROFILER_LIBRARY_MARK);
       
   467             this->libraryNamesToReport[iNewLibraryCount] = l;
       
   468             iNewLibraryCount++;
       
   469             }
       
   470 
       
   471         // the library has been tagged, add library to the list
       
   472         this->librariesToSample[this->iLibraryCount] = l;
       
   473         this->iLibraryCount++;
       
   474         LOGSTRING2("Added library %d to Libraries",i);
       
   475         }
       
   476 
       
   477     if(this->iLibraryCount > 0 || this->iNewLibraryCount > 0)
       
   478         {
       
   479         this->iLibrariesProcessing = EStartingToProcess;
       
   480         
       
   481         // process the first sample
       
   482         TInt length = this->ProcessLibraries();
       
   483         
       
   484         if(length == 0)
       
   485             {
       
   486             this->iLibrariesProcessing = ENothingToProcess;
       
   487             }
       
   488     
       
   489         libs.Signal();  // Release the container mutex
       
   490         NKern::ThreadLeaveCS();  // End of critical section
       
   491         return length;
       
   492         }
       
   493 
       
   494     LOGTEXT("MemSamplerImpl::SampleImpl - Error, no libraries"); 
       
   495     libs.Signal();  // Release the container mutex
       
   496     NKern::ThreadLeaveCS();  // End of critical section
       
   497     return 0;
       
   498     }
       
   499 #endif
       
   500 
       
   501 inline TInt DMemSamplerImpl::ProcessChunks()
       
   502     {
       
   503     if(iNewChunkCount > 0)
       
   504         {
       
   505         if(this->iChunksProcessing == EStartingToProcess)
       
   506             {
       
   507             // this is the first sample, encode a code for names
       
   508             this->iChunksProcessing = EProcessingNames;
       
   509             return EncodeNameCode();
       
   510             }
       
   511 
       
   512         if(iTotalMemoryNameOk == false)
       
   513             {
       
   514             return EncodeTotalMemoryName();
       
   515             }
       
   516         
       
   517         // there are new chunk names to report
       
   518         iNewChunkCount--;
       
   519         DChunk* c = this->heapChunkNamesToReport[iNewChunkCount];
       
   520         return EncodeChunkName(*c);
       
   521         
       
   522         }
       
   523     else if(iChunkCount > 0)
       
   524         {
       
   525         if(this->iChunksProcessing == EProcessingNames || this->iChunksProcessing == EStartingToProcess)
       
   526             {
       
   527             // this is the first data sample, encode a code for data
       
   528             this->iChunksProcessing = EProcessingData;
       
   529             return EncodeDataCode();
       
   530             }
       
   531         
       
   532         if(this->iTotalMemoryOk == false)
       
   533             {
       
   534             return EncodeTotalMemory();	
       
   535             }
       
   536 
       
   537         // there are no new chunks to report
       
   538         // thus generate the real report
       
   539         iChunkCount--;
       
   540         DChunk* c = this->heapChunksToSample[iChunkCount];
       
   541         return EncodeChunkData(*c);
       
   542         }
       
   543     else
       
   544         {
       
   545         // everything is processed
       
   546         LOGSTRING2(" Chunks processed! Chunk count = %d", iChunkCount);
       
   547 #ifdef MEM_EVENT_HANDLER
       
   548         this->iChunksGathered = true;
       
   549         Kern::Printf("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount);
       
   550 #endif
       
   551         return 0;
       
   552         }
       
   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         }
       
   596     else
       
   597         {   
       
   598         // everything is processed
       
   599         LOGSTRING2(" Threads processed! Thread count = %d", iThreadCount);
       
   600 #ifdef MEM_EVENT_HANDLER
       
   601         this->iThreadsGathered = true;
       
   602         Kern::Printf("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount);
       
   603 #endif
       
   604         return 0;
       
   605         }
       
   606     }
       
   607 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   608 inline TInt DMemSamplerImpl::ProcessLibraries()
       
   609     {
       
   610     LOGTEXT("ProcessLibraries - entry");
       
   611     if(iNewLibraryCount > 0)
       
   612         {
       
   613         if(this->iLibrariesProcessing == EStartingToProcess)
       
   614             {
       
   615             // this is the first sample, encode a code for names
       
   616             this->iLibrariesProcessing = EProcessingNames;
       
   617             return EncodeNameCode();
       
   618             }
       
   619 
       
   620         if(iTotalMemoryNameOk == false)
       
   621             {
       
   622             return EncodeTotalMemoryName();
       
   623             }
       
   624         
       
   625         // there are new library names to report
       
   626         iNewLibraryCount--;
       
   627         DLibrary* l = this->libraryNamesToReport[iNewLibraryCount];
       
   628         return EncodeChunkName(*l);
       
   629         
       
   630         }
       
   631     else if(iLibraryCount > 0)
       
   632         {
       
   633         if(this->iLibrariesProcessing == EProcessingNames || this->iLibrariesProcessing == EStartingToProcess)
       
   634             {
       
   635             // this is the first data sample, encode a code for data
       
   636             this->iLibrariesProcessing = EProcessingData;
       
   637             return EncodeDataCode();
       
   638             }
       
   639         
       
   640         if(this->iTotalMemoryOk == false)
       
   641             {
       
   642             return EncodeTotalMemory(); 
       
   643             }
       
   644 
       
   645         // there are no new libraries to report
       
   646         // thus generate the real report
       
   647         iLibraryCount--;
       
   648         DLibrary* l = this->librariesToSample[iLibraryCount];
       
   649         return EncodeChunkData(*l);
       
   650         }
       
   651     else
       
   652         {
       
   653         // everything is processed
       
   654         LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount);
       
   655 
       
   656         this->iLibrariesGathered = true;
       
   657         Kern::Printf("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount);
       
   658 
       
   659         return 0;
       
   660         }
       
   661     }
       
   662 #endif
       
   663 inline TInt DMemSamplerImpl::EncodeNameCode()
       
   664     {
       
   665 	sample[0] = 1;
       
   666 	sample[1] = 0xaa;
       
   667 	return 2;
       
   668     }
       
   669 
       
   670 inline TInt DMemSamplerImpl::EncodeDataCode()
       
   671     {
       
   672 	sample[0] = 1;
       
   673 	sample[1] = 0xdd;
       
   674 	return 2;
       
   675     }
       
   676 
       
   677 inline TInt DMemSamplerImpl::EncodeTotalMemoryName()
       
   678     {
       
   679 	this->iTotalMemoryNameOk = true;
       
   680 	
       
   681 	TUint8* size = &sample[0];
       
   682 	*size = 0;
       
   683 		
       
   684 	// encode name
       
   685 	this->sampleDescriptor.Zero();
       
   686 	this->sampleDescriptor.Append(_L("TOTAL_MEMORY"));
       
   687 	*size += this->sampleDescriptor.Size();
       
   688 		
       
   689 	// add id here
       
   690 	TUint32 id(0xbabbeaaa);
       
   691 	this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32));
       
   692 	*size += sizeof(TUint32);
       
   693 	
       
   694 	// the size is the descriptor length + the size field
       
   695 	return ((TInt)(*size))+1;	
       
   696     }
       
   697 
       
   698 inline TInt DMemSamplerImpl::EncodeTotalMemory()
       
   699     {	
       
   700 	
       
   701 	TUint8* size = &sample[0];
       
   702 	*size = 0;
       
   703 
       
   704 	NKern::LockSystem();
       
   705 	TInt freeRam = Kern::FreeRamInBytes();
       
   706 	TInt totalRam = Kern::SuperPage().iTotalRamSize;
       
   707 	NKern::UnlockSystem();
       
   708 
       
   709 	this->sampleDescriptor.Zero();
       
   710 	
       
   711 	TUint32 id(0xbabbeaaa);
       
   712 	TInt zero(0);
       
   713 		
       
   714 	this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32));
       
   715 	*size += sizeof(TUint);
       
   716 	
       
   717 	this->sampleDescriptor.Append((TUint8*)&(totalRam),sizeof(TInt));
       
   718 	*size += sizeof(TInt);
       
   719 		
       
   720 	// append the cell amount allocated
       
   721 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   722 	*size += sizeof(TInt);
       
   723 	
       
   724 	// append the chunk size
       
   725 	this->sampleDescriptor.Append((TUint8*)&(freeRam),sizeof(TInt));
       
   726 	*size += sizeof(TInt);
       
   727 		
       
   728 	// append the thread user stack size
       
   729 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   730 	*size += sizeof(TInt);
       
   731 
       
   732 	this->iTotalMemoryOk = true;
       
   733 
       
   734 	return ((TInt)(*size))+1;
       
   735     }
       
   736 
       
   737 inline TInt DMemSamplerImpl::EncodeChunkName(DChunk& c)
       
   738     {	
       
   739 	// the size of the following name is in the first byte
       
   740 	TUint8* size = &sample[0];
       
   741 	*size = 0;
       
   742 		
       
   743 	// encode chunk name
       
   744 	this->sampleDescriptor.Zero();
       
   745 	this->sampleDescriptor.Append(_L("C_"));
       
   746 	c.TraceAppendFullName(this->sampleDescriptor,false);
       
   747 	*size += this->sampleDescriptor.Size();
       
   748 		
       
   749 	// add chunk object address here
       
   750 	TUint32 chunkAddr((TUint32)&c);
       
   751 	this->sampleDescriptor.Append((TUint8*)&(chunkAddr),sizeof(TUint32));
       
   752 	*size += sizeof(TUint32);
       
   753 
       
   754 	// the size is the descriptor length + the size field
       
   755 	LOGSTRING2("Non-Heap Chunk Name - %d",*size);
       
   756 	return ((TInt)(*size))+1;			
       
   757     }
       
   758 
       
   759 inline TInt DMemSamplerImpl::EncodeChunkName(DThread& t)
       
   760     {		
       
   761 	// the size of the following name is in the first byte
       
   762 	TUint8* size = &sample[0];
       
   763 	*size = 0;
       
   764 	this->sampleDescriptor.Zero();
       
   765 	
       
   766 	this->sampleDescriptor.Append(_L("T_"));
       
   767 	t.TraceAppendFullName(this->sampleDescriptor,false);
       
   768 	*size += this->sampleDescriptor.Size();
       
   769 	
       
   770 	// copy the 4 bytes from the thread id field
       
   771 	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
       
   772 	*size += sizeof(TUint);
       
   773 
       
   774 	// the size is the descriptor length + the size field
       
   775 	LOGSTRING2("Name - %d",*size);
       
   776 	return ((TInt)(*size))+1;
       
   777     }
       
   778 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   779 inline TInt DMemSamplerImpl::EncodeChunkName(DLibrary& l)
       
   780     {   
       
   781     // the size of the following name is in the first byte
       
   782     TUint8* size = &sample[0];
       
   783     *size = 0;
       
   784         
       
   785     // encode library name
       
   786     this->sampleDescriptor.Zero();
       
   787     this->sampleDescriptor.Append(_L("L_"));
       
   788     l.TraceAppendFullName(this->sampleDescriptor,false);
       
   789     *size += this->sampleDescriptor.Size();
       
   790         
       
   791     // add chunk object address here
       
   792     TUint32 libAddr((TUint32)&l);
       
   793     this->sampleDescriptor.Append((TUint8*)&(libAddr),sizeof(TUint32));
       
   794     *size += sizeof(TUint32);
       
   795 
       
   796     // the size is the descriptor length + the size field
       
   797     LOGSTRING2("Name - %d",*size);
       
   798     return ((TInt)(*size))+1;           
       
   799     }
       
   800 #endif
       
   801 inline TInt DMemSamplerImpl::EncodeChunkData(DChunk& c)
       
   802     {
       
   803 	// the size of the following name is in the first byte
       
   804 	TUint8* size = &sample[0];
       
   805 	*size = 0;
       
   806 	this->sampleDescriptor.Zero();
       
   807 	TInt zero(0);
       
   808 
       
   809 	TUint32 address((TUint32)&c);
       
   810 		
       
   811 	this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
       
   812 	*size += sizeof(TUint);
       
   813 	
       
   814 	// copy the total amount of memory allocated
       
   815 	this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TInt));
       
   816 	*size += sizeof(TInt);
       
   817 		
       
   818 	// append the cell amount allocated
       
   819 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   820 	*size += sizeof(TInt);
       
   821 	
       
   822 	// append the chunk size
       
   823 	this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TUint));
       
   824 	*size += sizeof(TUint);
       
   825 		
       
   826 	// append the thread user stack size
       
   827 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   828 	*size += sizeof(TInt);
       
   829 
       
   830 	LOGSTRING2("Data - %d",*size);
       
   831 	return ((TInt)(*size))+1;
       
   832 
       
   833     }
       
   834 
       
   835 inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t)
       
   836     {
       
   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
       
   841 	TUint8* size = &sample[0];
       
   842 	*size = 0;
       
   843 	this->sampleDescriptor.Zero();
       
   844 
       
   845 	LOGTEXT("MemSamplerImpl::EncodeChunkData - cleared");
       
   846 
       
   847 	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
       
   848 	*size += sizeof(TUint);
       
   849 		
       
   850 	// copy the total amount of memory allocated for user side stack
       
   851 	this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt));
       
   852 	*size += sizeof(TInt);
       
   853 
       
   854 	TInt zero(0);		
       
   855 	// append the cell amount allocated (zero, not in use here)
       
   856 	this->sampleDescriptor.Append((TUint8*)&zero,sizeof(TInt));
       
   857 	*size += sizeof(TInt);
       
   858 	
       
   859 	// append the chunk size (this is not a chunk)
       
   860 	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint));
       
   861 	*size += sizeof(TUint);
       
   862 
       
   863 	// append user stack (max) size
       
   864 	this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt));
       
   865 	*size += sizeof(TInt);
       
   866 
       
   867 	LOGSTRING2("Data -> %d",*size);
       
   868 	return ((TInt)(*size))+1;
       
   869     }
       
   870 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   871 inline TInt DMemSamplerImpl::EncodeChunkData(DLibrary& l)
       
   872     {
       
   873     LOGTEXT("MemSamplerImpl::EncodeChunkData (Library) - entry");
       
   874     // the size of the following name is in the first byte
       
   875     TUint8* size = &sample[0];
       
   876     *size = 0;
       
   877     this->sampleDescriptor.Zero();
       
   878     
       
   879     TUint32 address((TUint32)&l);
       
   880         
       
   881     this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
       
   882     *size += sizeof(TUint);
       
   883              
       
   884 	this->sampleDescriptor.Append((TUint8*)&(l.iCodeSeg->iSize),sizeof(TUint32));
       
   885     *size += sizeof(TInt); 
       
   886              
       
   887     this->sampleDescriptor.Append((TUint8*)&(l.iMapCount),sizeof(TInt));
       
   888     *size += sizeof(TInt);  
       
   889         
       
   890     TInt zero(0);   
       
   891     this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   892     *size += sizeof(TInt);   
       
   893         
       
   894     this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
       
   895     *size += sizeof(TInt);   
       
   896 
       
   897     LOGSTRING2("LData - %d",*size);
       
   898     return ((TInt)(*size))+1;
       
   899 
       
   900     }
       
   901 #endif
       
   902 void DMemSamplerImpl::Reset()
       
   903     {
       
   904 	Kern::Printf("MemSamplerImpl::Reset");
       
   905 	iCount = 0; // sample threads 1 cycle after actual MEM sample time...
       
   906     this->iTimeToSample = false;
       
   907     this->iChunkCount = 0;
       
   908 	this->iNewChunkCount = 0;
       
   909 	
       
   910 	this->iTotalMemoryOk = false;
       
   911 	this->iTotalMemoryNameOk = false;
       
   912 
       
   913 	this->iChunksProcessing = ENothingToProcess;
       
   914     this->iThreadsProcessing = ENothingToProcess;
       
   915 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   916     this->iLibrariesProcessing = ENothingToProcess;
       
   917     this->iSampleType = ESampleThreads;
       
   918 #else
       
   919     this->iSampleThreads = true;
       
   920 #endif
       
   921     
       
   922 	this->sampleDescriptor.Zero();
       
   923 	
       
   924 	// clear all chunk tags
       
   925     NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
   926 	DObjectCon* chunks = Kern::Containers()[EChunk];
       
   927     chunks->Wait(); // Obtain the container mutex so the list does get changed under us
       
   928 
       
   929 	TInt totalChunkCount = chunks->Count();
       
   930 	for(TInt i=0;i<totalChunkCount;i++)
       
   931 	    {
       
   932 		DChunk* c = (DChunk*)(*chunks)[i];
       
   933 		TAG(c) = 0;
       
   934 	    }
       
   935 	chunks->Signal();  // Release the container mutex
       
   936 
       
   937 	Kern::Printf("MemSamplerImpl::Reset");
       
   938 	this->iThreadCount = 0;
       
   939 	this->iNewThreadCount = 0;
       
   940 	this->sampleDescriptor.Zero();
       
   941 
       
   942 	// clear all chunk tags
       
   943 	DObjectCon* threads = Kern::Containers()[EThread];
       
   944     threads->Wait(); // Obtain the container mutex so the list does get changed under us
       
   945 
       
   946 	TInt totalThreadCount = threads->Count();
       
   947 	for(TInt i=0;i<totalThreadCount;i++)
       
   948 	    {
       
   949 		DThread* t = (DThread*)(*threads)[i];
       
   950 		TAG(t) = (TAG(t) & 0xfffffffe);
       
   951 	    }
       
   952 	threads->Signal();  // Release the container mutex
       
   953 	
       
   954 #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
       
   955 	this->iLibraryCount = 0;
       
   956 	this->iNewLibraryCount = 0;
       
   957 	this->sampleDescriptor.Zero();
       
   958 
       
   959 	// clear all library tags
       
   960 	DObjectCon* libs = Kern::Containers()[ELibrary];
       
   961 	libs->Wait(); // Obtain the container mutex so the list does get changed under us
       
   962 
       
   963 	TInt totalLibraryCount = libs->Count();
       
   964 	for(TInt i=0; i<totalLibraryCount; i++)
       
   965 	    {
       
   966         DLibrary* l = (DLibrary*)(*libs)[i];
       
   967         TAG(l) = (TAG(l) & 0xefffffff);
       
   968 	    }
       
   969 	libs->Signal();  // Release the container mutex
       
   970 #endif
       
   971 
       
   972     NKern::ThreadLeaveCS();  // End of critical section
       
   973     }
       
   974