tracesrv/tracecore/btrace_handler/src/TraceCore.cpp
changeset 56 aa2539c91954
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     1 // Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //  Trace Core main instance implementation
       
    15 //
       
    16 //
       
    17 
       
    18 #include <e32def.h>
       
    19 #include <e32btrace.h>
       
    20 #include <trace_certification.h>
       
    21 
       
    22 #include "TraceCore.h"
       
    23 #include "TraceCoreSendReceive.h"
       
    24 #include "TraceCoreRouter.h"
       
    25 #include "TraceCoreDebug.h"
       
    26 #include "TraceCoreBTraceHandler.h"
       
    27 #include "TraceCorePrintfTraceHandler.h"
       
    28 #include "TraceCoreNotifier.h"
       
    29 #include "TraceCoreConfiguration.h"
       
    30 #include "TraceCoreInternalMessageHandler.h"
       
    31 #include "TraceCoreActivation.h"
       
    32 
       
    33 #include "OstTraceDefinitions.h"
       
    34 #ifdef OST_TRACE_COMPILER_IN_USE
       
    35 #include "TraceCoreTraces.h"
       
    36 #endif
       
    37 
       
    38 /**
       
    39  * TraceCore global instance
       
    40  */
       
    41 DTraceCore* DTraceCore::iInstance = NULL;
       
    42 
       
    43 
       
    44 /**
       
    45  * Gets the TraceCore instance,
       
    46  * @return DTraceCore object or NULL if TraceCore is not created yet.
       
    47  */
       
    48 EXPORT_C DTraceCore* DTraceCore::GetInstance()
       
    49     {
       
    50     return iInstance;
       
    51     }
       
    52 
       
    53 /**
       
    54  * Returns ETrue if tracecore is loaded already EFalse otherwies
       
    55  */
       
    56 EXPORT_C TBool DTraceCore::IsLoaded()
       
    57     {
       
    58     return ( iInstance != NULL );
       
    59     }
       
    60 
       
    61 /**
       
    62  * Gets the BTrace handler
       
    63  */
       
    64 DTraceCoreBTraceHandler* DTraceCore::GetBTraceHandler()
       
    65     {
       
    66     DTraceCoreBTraceHandler* retval = NULL;
       
    67     DTraceCore* traceCore = DTraceCore::GetInstance();
       
    68     // BTrace handler is the first one to be registered
       
    69     if ( traceCore != NULL && traceCore->iHandlers.Count() > 0 )
       
    70         {
       
    71         retval = ( DTraceCoreBTraceHandler* )traceCore->iHandlers[ 0 ];
       
    72         }
       
    73     return retval;
       
    74     }
       
    75 
       
    76 /**
       
    77  * Constructor
       
    78  */
       
    79 DTraceCore::DTraceCore()
       
    80 : iRouter( NULL )
       
    81 , iSendReceive( NULL )
       
    82 , iNotifier( NULL )
       
    83 , iConfiguration( NULL )
       
    84 , iInternalMessageHandler( NULL )
       
    85 , iBTrace( NULL )
       
    86 , iPrintf( NULL )
       
    87 , iTraceCoreSettings( NULL )
       
    88 , iActiveWriter( NULL )
       
    89 , iActivationQ(NULL)
       
    90 , iPreviousTraceDropped(EFalse)
       
    91 , iTraceCertified(EFalse)
       
    92     {
       
    93     }
       
    94 
       
    95 /**
       
    96  * Destructor
       
    97  */
       
    98 DTraceCore::~DTraceCore()
       
    99     {
       
   100     // Writers and handlers are deleted first
       
   101     //  -> They call unregister functions
       
   102     delete iBTrace;
       
   103     delete iPrintf;
       
   104 
       
   105     iHandlers.Reset();
       
   106     iWriters.Reset();
       
   107     iActivations.Reset();
       
   108 
       
   109     delete iRouter;
       
   110     delete iSendReceive;
       
   111     delete iNotifier;
       
   112     delete iConfiguration;
       
   113 	//destroy iActivationQue
       
   114     if (iActivationQ)
       
   115         iActivationQ->Destroy();
       
   116     }
       
   117 
       
   118 
       
   119 /*
       
   120  * Init TraceCore
       
   121  */
       
   122 TInt DTraceCore::Init()
       
   123     {
       
   124     TC_TRACE( ETraceLevelFlow, Kern::Printf( ">DTraceCore::Init()" ) );
       
   125     TInt ret;
       
   126 
       
   127     //TODO: measure how much time it takes to boot up
       
   128     //TODO: measure how much memory is consumed by TraceCore
       
   129    //TODO: check granularity of internal RArrays - update this for most used use case
       
   130 
       
   131     //TODO: check dfc que (if we have any) that deals with pulling trace data from buffer
       
   132 
       
   133    // Store the trace certified flag, used to suppress tracing on production images.
       
   134    // This stored value is used throughout the session, even if the status of the certificate changes.
       
   135    // This is done to avoid performance issues when performing the check with every trace outputted.
       
   136    iTraceCertified = TraceCertification::IsTraceCertified();
       
   137 
       
   138     //create activation/deactivation queue
       
   139    const TInt KTCDfcThreadPriority = 24; // Kern::DfcQ0 is 27
       
   140    //TODO: put this const to a header
       
   141    //TODO: check if I can use constants for this (DFCQ0-1) ?
       
   142    _LIT(KTCDfcQueue, "TraceCoreActivationDfcQ");
       
   143    Kern::Printf("Creating TC dfc - %S...", &KTCDfcQueue);
       
   144    ret = Kern::DynamicDfcQCreate(iActivationQ, KTCDfcThreadPriority, KTCDfcQueue);
       
   145    Kern::Printf("returned code: %d, ptr: 0x%x", ret, iActivationQ);
       
   146    if (ret==KErrNone)
       
   147        //disable real-time state of the dfcq
       
   148        iActivationQ->SetRealtimeState(ERealtimeStateOff);
       
   149 
       
   150     // Disable Component ID filtering in BTrace
       
   151     BTrace::SetFilter2(1);
       
   152 
       
   153     // Create needed components
       
   154     iRouter = new DTraceCoreRouter();
       
   155     iSendReceive = new DTraceCoreSendReceive();
       
   156     iNotifier = new DTraceCoreNotifier();
       
   157     iConfiguration = new DTraceCoreConfiguration();
       
   158     iInternalMessageHandler = new DTraceCoreInternalMessageHandler();
       
   159 
       
   160     // Check that creating of the components was succesfull
       
   161     if ( iRouter != NULL && iSendReceive != NULL && iNotifier != NULL && iConfiguration != NULL )
       
   162         {
       
   163         ret = iSendReceive->Init( *iRouter );
       
   164         if ( ret == KErrNone )
       
   165             {
       
   166             ret = iRouter->Init( *iSendReceive );
       
   167             if ( ret == KErrNone )
       
   168                 {
       
   169                 ret = iConfiguration->Init();
       
   170                 if ( ret == KErrNone )
       
   171                     {
       
   172                     ret = iInternalMessageHandler->Init();
       
   173                     }
       
   174                 }
       
   175             }
       
   176         }
       
   177     else
       
   178         {
       
   179         ret = KErrNoMemory;
       
   180         }
       
   181 
       
   182     // BTrace handler is integrated to TraceCore
       
   183     if ( ret == KErrNone )
       
   184         {
       
   185         ret = StartBTrace();
       
   186         }
       
   187 
       
   188     // Printf handler is integrated to TraceCore
       
   189     if ( ret == KErrNone )
       
   190         {
       
   191         ret = StartPrintfTraceHandler();
       
   192         }
       
   193     TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::Init() - %d", ret ) );
       
   194 
       
   195     return ret;
       
   196     }
       
   197 
       
   198 /**
       
   199  * Starts the BTrace handler
       
   200  */
       
   201 TInt DTraceCore::StartBTrace()
       
   202     {
       
   203     TInt ret = KErrNone;
       
   204 
       
   205     // Create BTrace handler
       
   206     iBTrace = new DTraceCoreBTraceHandler();
       
   207     if ( iBTrace != NULL )
       
   208         {
       
   209         // Init calls RegisterHandler
       
   210         ret = iBTrace->Init();
       
   211         }
       
   212     else
       
   213         {
       
   214         ret = KErrNoMemory;
       
   215         }
       
   216     TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::StartBTrace() - %d", ret ) );
       
   217     return ret;
       
   218     }
       
   219 
       
   220 
       
   221 /**
       
   222  * Starts the Printf trace handler
       
   223  */
       
   224 TInt DTraceCore::StartPrintfTraceHandler()
       
   225     {
       
   226     TInt ret;
       
   227 
       
   228     // Create PrintF handler
       
   229     iPrintf = new DTraceCorePrintfTraceHandler();
       
   230     if ( iPrintf != NULL )
       
   231         {
       
   232         // Init calls RegisterHandler
       
   233         ret = iPrintf->Init();
       
   234         }
       
   235     else
       
   236         {
       
   237         ret = KErrNoMemory;
       
   238         }
       
   239     TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::StartPrintfTraceHandler() - %d", ret ) );
       
   240     return ret;
       
   241     }
       
   242 
       
   243 
       
   244 /**
       
   245  * Registers an activation interface
       
   246  */
       
   247 TInt DTraceCore::RegisterActivation( MTraceCoreActivation& aActivation )
       
   248     {
       
   249     return iActivations.Append( &aActivation );
       
   250     }
       
   251 
       
   252 
       
   253 /**
       
   254  * Gets an activation interface.
       
   255  * Tracing from this method is not allowed.
       
   256  */
       
   257 MTraceCoreActivation* DTraceCore::GetActivation( TUint32 aComponentId )
       
   258     {
       
   259     MTraceCoreActivation* retval = NULL;
       
   260 
       
   261     // Find the correct activation interface from the list
       
   262     for ( int i = 0; i < iActivations.Count(); i++ )
       
   263         {
       
   264         if ( iActivations[ i ]->IsComponentSupported( aComponentId ) )
       
   265             {
       
   266             retval = iActivations[ i ];
       
   267             }
       
   268         }
       
   269 
       
   270     return retval;
       
   271     }
       
   272 
       
   273 
       
   274 /**
       
   275  * Registers a handler
       
   276  *
       
   277  * @param aHandler The handler
       
   278  */
       
   279 TInt DTraceCore::RegisterHandler( DTraceCoreHandler& aHandler )
       
   280     {
       
   281     OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERHANDLER_ENTRY, "> DTraceCore::RegisterHandler 0x%x", ( TUint )&( aHandler ) );
       
   282     TInt ret = iHandlers.Append( &aHandler );
       
   283 
       
   284     // If there is not yet active writer, set the new one
       
   285     if ( ret == KErrNone && iActiveWriter != NULL )
       
   286         {
       
   287         aHandler.SetWriter( iActiveWriter );
       
   288         }
       
   289 
       
   290     // Set settings to the handler
       
   291     if ( ret == KErrNone && iTraceCoreSettings != NULL )
       
   292      	{
       
   293      	aHandler.SetSettings( iTraceCoreSettings );
       
   294     	}
       
   295     OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERHANDLER_EXIT, "< DTraceCore::RegisterHandler. Ret:%d", ret );
       
   296 
       
   297     return ret;
       
   298     }
       
   299 
       
   300 
       
   301 /**
       
   302  * Unregisters a handler
       
   303  *
       
   304  * @param aHandler The handler
       
   305  */
       
   306 void DTraceCore::UnregisterHandler( DTraceCoreHandler& aHandler )
       
   307     {
       
   308     // Find thiss handler from the list of handlers
       
   309     for ( TInt i = 0; i < iHandlers.Count(); i++ )
       
   310         {
       
   311         if ( iHandlers[ i ] == &aHandler )
       
   312             {
       
   313             OstTrace1( TRACE_NORMAL, DTRACECORE_UNREGISTERHANDLER_HANDLER_REMOVED, "DTraceCore::UnregisterHandler - Handler removed 0x%x", ( TUint )&aHandler );
       
   314             iHandlers.Remove( i );
       
   315             i = iHandlers.Count();
       
   316             }
       
   317         }
       
   318     }
       
   319 
       
   320 /**
       
   321  * Registers the settings
       
   322  *
       
   323  * @param aSettings The settings saver
       
   324  * @return KErrNone if registration successful
       
   325  */
       
   326 TInt DTraceCore::RegisterSettings( DTraceCoreSettings& aSettings )
       
   327     {
       
   328     iTraceCoreSettings = &aSettings;
       
   329     for ( TInt i = 0; i < iHandlers.Count(); i++ )
       
   330         {
       
   331         iHandlers[ i ]->SetSettings( iTraceCoreSettings );
       
   332         }
       
   333     return KErrNone;
       
   334     }
       
   335 
       
   336 
       
   337 /**
       
   338  * Unregisters the settings
       
   339  *
       
   340  * @param aSettings The settings
       
   341  */
       
   342 void DTraceCore::UnregisterSettings( DTraceCoreSettings& aSettings )
       
   343     {
       
   344     if ( &aSettings == iTraceCoreSettings )
       
   345         {
       
   346         iTraceCoreSettings = NULL;
       
   347 
       
   348         // Remove settings from all the handlers
       
   349         for ( TInt i = 0; i < iHandlers.Count(); i++ )
       
   350             {
       
   351             iHandlers[ i ]->SetSettings( NULL );
       
   352             }
       
   353         }
       
   354     }
       
   355 
       
   356 
       
   357 /**
       
   358  * Registers a writer
       
   359  *
       
   360  * @param aWriter The writer
       
   361  */
       
   362 TInt DTraceCore::RegisterWriter( DTraceCoreWriter& aWriter )
       
   363     {
       
   364     OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERWRITER_ENTRY, "> DTraceCore::RegisterWriter 0x%x", ( TUint )&( aWriter ) );
       
   365 
       
   366     TInt ret = iWriters.Append( &aWriter );
       
   367     if ( ret == KErrNone )
       
   368         {
       
   369         // First writer that registers is selected as the active one
       
   370         if ( iActiveWriter == NULL )
       
   371             {
       
   372             iActiveWriter = &aWriter;
       
   373             SetWriterToHandlers();
       
   374             }
       
   375         }
       
   376 
       
   377     OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERWRITER_EXIT, "< DTraceCore::RegisterWriter %d", ret );
       
   378     return ret;
       
   379     }
       
   380 
       
   381 
       
   382 /**
       
   383  * Unregisters a writer
       
   384  *
       
   385  * @param aWriter The writer
       
   386  */
       
   387 void DTraceCore::UnregisterWriter( DTraceCoreWriter& aWriter )
       
   388     {
       
   389     for ( TInt i = 0; i < iWriters.Count(); i++ )
       
   390         {
       
   391         if ( iWriters[ i ] == &aWriter )
       
   392             {
       
   393             OstTraceExt2( TRACE_NORMAL, DTRACECORE_UNREGISTERHANDLER_WRITER_UNREGISTERED, "DTraceCore::UnregisterWriter - Writer unregistered WriterType:%d Addr:0x%x", ( TInt )aWriter.GetWriterType(), ( TUint )&aWriter );
       
   394             iWriters.Remove( i );
       
   395             i = iWriters.Count();
       
   396             // If the active writer was removed, another writer needs to be activated
       
   397             if ( &aWriter == iActiveWriter )
       
   398                 {
       
   399                 SwitchToFirstWriter();
       
   400                 }
       
   401             }
       
   402         }
       
   403     }
       
   404 
       
   405 
       
   406 /**
       
   407  * Starts to use the first writer from the writers list
       
   408  */
       
   409 void DTraceCore::SwitchToFirstWriter()
       
   410     {
       
   411     if ( iWriters.Count() > 0 )
       
   412         {
       
   413         iActiveWriter = iWriters[ 0 ];
       
   414         }
       
   415     else
       
   416         {
       
   417         iActiveWriter = NULL;
       
   418         }
       
   419     SetWriterToHandlers();
       
   420     }
       
   421 
       
   422 
       
   423 /**
       
   424  * Starts to use a writer of the specific type. Does nothing if the writer is already active
       
   425  */
       
   426 EXPORT_C TInt DTraceCore::SwitchToWriter( TWriterType aWriterType )
       
   427     {
       
   428     OstTrace1( TRACE_FLOW, DTRACECORE_SWITCHTOWRITER_ENTRY,"> DTraceCore::SwitchToWriter WriterType:%d", ( TUint )( aWriterType ) );
       
   429     TInt retval( KErrNone );
       
   430 
       
   431     // Remove writer
       
   432     if ( aWriterType == EWriterTypeNone )
       
   433         {
       
   434         if ( iActiveWriter != NULL )
       
   435             {
       
   436             iActiveWriter = NULL;
       
   437             SetWriterToHandlers();
       
   438             }
       
   439         }
       
   440     else
       
   441         {
       
   442         if ( iActiveWriter == NULL || iActiveWriter->GetWriterType() != aWriterType )
       
   443             {
       
   444             retval = KErrNotSupported;
       
   445 
       
   446             // Find the correct writer from the list
       
   447             for ( int i = 0; i < iWriters.Count() && retval != KErrNone; i++ )
       
   448                 {
       
   449                 DTraceCoreWriter* writer = iWriters[ i ];
       
   450 
       
   451                 // revert this
       
   452                 TWriterType wt = writer->GetWriterType();
       
   453 
       
   454                 if ( wt == aWriterType )
       
   455                     {
       
   456                     iActiveWriter = writer;
       
   457                     retval = KErrNone;
       
   458                     }
       
   459                 }
       
   460 
       
   461             // Set writer to all handlers
       
   462             if ( retval == KErrNone )
       
   463                 {
       
   464                 SetWriterToHandlers();
       
   465                 }
       
   466             }
       
   467         }
       
   468     OstTrace1( TRACE_FLOW, DTRACECORE_SWITCHTOWRITER_EXIT, "< DTraceCore::SwitchToWriter %d", retval );
       
   469     return retval;
       
   470     }
       
   471 
       
   472 /**
       
   473  * Sets the active writer to all registered handlers
       
   474  */
       
   475 void DTraceCore::SetWriterToHandlers()
       
   476     {
       
   477     if ( iActiveWriter != NULL )
       
   478         {
       
   479         OstTraceExt2( TRACE_NORMAL, DTRACECORE_SETWRITERTOHANDLERS_WRITER_SELECTED, "DTraceCore::SetWriterToHandlers - Writer selected 0x%x WriterType:%d", (TUint) iActiveWriter, (TInt) iActiveWriter->GetWriterType() );
       
   480         }
       
   481 
       
   482     // PrepareSetWriter method is called with interrupts enabled
       
   483     // SetWriter is called with interrupts disabled to prevent tracing
       
   484     // while switching the writer
       
   485     for ( TInt i = 0; i < iHandlers.Count(); i++ )
       
   486         {
       
   487         iHandlers[ i ]->PrepareSetWriter( iActiveWriter );
       
   488         }
       
   489     //TODO: this is not SMP safe but it's rare case - update it later
       
   490     TInt interrupts = NKern::DisableAllInterrupts();
       
   491     for ( TInt j = 0; j < iHandlers.Count(); j++ )
       
   492         {
       
   493         iHandlers[ j ]->SetWriter( iActiveWriter );
       
   494         }
       
   495     NKern::RestoreInterrupts( interrupts );
       
   496     }
       
   497 
       
   498 /**
       
   499  * Get current writer type
       
   500  *
       
   501  * @return Current writer type
       
   502  */
       
   503 EXPORT_C TInt DTraceCore::GetCurrentWriterType()
       
   504     {
       
   505     TInt ret(0);
       
   506     ret = iActiveWriter->GetWriterType();
       
   507     return ret;
       
   508     }
       
   509 
       
   510 /*
       
   511  * Destroy the static instance of tracecore
       
   512  */
       
   513 EXPORT_C void DTraceCore::DestroyTraceCore()
       
   514     {
       
   515     TC_TRACE( ETraceLevelNormal, Kern::Printf( "StopTraceCore started" ) );
       
   516     delete DTraceCore::GetInstance();
       
   517     DTraceCore::iInstance = NULL;
       
   518     TC_TRACE( ETraceLevelNormal, Kern::Printf( "StopTraceCore Finished" ) );
       
   519     }
       
   520 
       
   521 
       
   522 /**
       
   523  * Sets the "Trace Dropped" flag
       
   524  *
       
   525  * @param aTraceDropped ETrue if Trace Dropped, EFalse Otherwise
       
   526  */
       
   527 EXPORT_C void DTraceCore::SetPreviousTraceDropped(TBool aTraceDropped)
       
   528     {
       
   529     iPreviousTraceDropped = aTraceDropped;
       
   530     }
       
   531 
       
   532 /**
       
   533  * returns the state of the  "Trace Dropped" flag
       
   534  *
       
   535  * @param none
       
   536  */
       
   537 EXPORT_C TBool DTraceCore::PreviousTraceDropped() const
       
   538     {
       
   539     return iPreviousTraceDropped;
       
   540     }
       
   541 
       
   542 
       
   543 EXPORT_C DTraceCore* DTraceCore::CreateInstance()
       
   544     {
       
   545     if(iInstance == NULL)
       
   546       {
       
   547         DTraceCore* instance = new DTraceCore();
       
   548         if ( instance != NULL )
       
   549             {
       
   550             iInstance = instance;
       
   551             TInt ret = iInstance->Init();
       
   552             if(ret != KErrNone)
       
   553                 {
       
   554                 delete iInstance;
       
   555                 iInstance = NULL;
       
   556                 }
       
   557             }
       
   558         }
       
   559 
       
   560     return iInstance;
       
   561     }
       
   562 
       
   563 
       
   564 EXPORT_C DTraceCoreWriter* DTraceCore::GetActiveWriter()
       
   565     {
       
   566     return iActiveWriter;
       
   567     }
       
   568 
       
   569 /**
       
   570  * Reactivate all currently activated traces
       
   571  *
       
   572  * @param none
       
   573  * @return KErrNone if refresh successful
       
   574  */
       
   575 TInt DTraceCore::RefreshActivations()
       
   576     {
       
   577     TInt ret = KErrNone;
       
   578     // Go through all activation interfaces from the list
       
   579     TInt activationsCount = iActivations.Count();
       
   580     for ( int i = 0; i < activationsCount; i++ )
       
   581         {
       
   582         TInt err = iActivations[ i ]->RefreshActivations();
       
   583         if (err != KErrNone)
       
   584             {
       
   585             ret = err;
       
   586             }
       
   587         }
       
   588     return ret;
       
   589     }