--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecore/btrace_handler/src/TraceCore.cpp Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,589 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Trace Core main instance implementation
+//
+//
+
+#include <e32def.h>
+#include <e32btrace.h>
+#include <trace_certification.h>
+
+#include "TraceCore.h"
+#include "TraceCoreSendReceive.h"
+#include "TraceCoreRouter.h"
+#include "TraceCoreDebug.h"
+#include "TraceCoreBTraceHandler.h"
+#include "TraceCorePrintfTraceHandler.h"
+#include "TraceCoreNotifier.h"
+#include "TraceCoreConfiguration.h"
+#include "TraceCoreInternalMessageHandler.h"
+#include "TraceCoreActivation.h"
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "TraceCoreTraces.h"
+#endif
+
+/**
+ * TraceCore global instance
+ */
+DTraceCore* DTraceCore::iInstance = NULL;
+
+
+/**
+ * Gets the TraceCore instance,
+ * @return DTraceCore object or NULL if TraceCore is not created yet.
+ */
+EXPORT_C DTraceCore* DTraceCore::GetInstance()
+ {
+ return iInstance;
+ }
+
+/**
+ * Returns ETrue if tracecore is loaded already EFalse otherwies
+ */
+EXPORT_C TBool DTraceCore::IsLoaded()
+ {
+ return ( iInstance != NULL );
+ }
+
+/**
+ * Gets the BTrace handler
+ */
+DTraceCoreBTraceHandler* DTraceCore::GetBTraceHandler()
+ {
+ DTraceCoreBTraceHandler* retval = NULL;
+ DTraceCore* traceCore = DTraceCore::GetInstance();
+ // BTrace handler is the first one to be registered
+ if ( traceCore != NULL && traceCore->iHandlers.Count() > 0 )
+ {
+ retval = ( DTraceCoreBTraceHandler* )traceCore->iHandlers[ 0 ];
+ }
+ return retval;
+ }
+
+/**
+ * Constructor
+ */
+DTraceCore::DTraceCore()
+: iRouter( NULL )
+, iSendReceive( NULL )
+, iNotifier( NULL )
+, iConfiguration( NULL )
+, iInternalMessageHandler( NULL )
+, iBTrace( NULL )
+, iPrintf( NULL )
+, iTraceCoreSettings( NULL )
+, iActiveWriter( NULL )
+, iActivationQ(NULL)
+, iPreviousTraceDropped(EFalse)
+, iTraceCertified(EFalse)
+ {
+ }
+
+/**
+ * Destructor
+ */
+DTraceCore::~DTraceCore()
+ {
+ // Writers and handlers are deleted first
+ // -> They call unregister functions
+ delete iBTrace;
+ delete iPrintf;
+
+ iHandlers.Reset();
+ iWriters.Reset();
+ iActivations.Reset();
+
+ delete iRouter;
+ delete iSendReceive;
+ delete iNotifier;
+ delete iConfiguration;
+ //destroy iActivationQue
+ if (iActivationQ)
+ iActivationQ->Destroy();
+ }
+
+
+/*
+ * Init TraceCore
+ */
+TInt DTraceCore::Init()
+ {
+ TC_TRACE( ETraceLevelFlow, Kern::Printf( ">DTraceCore::Init()" ) );
+ TInt ret;
+
+ //TODO: measure how much time it takes to boot up
+ //TODO: measure how much memory is consumed by TraceCore
+ //TODO: check granularity of internal RArrays - update this for most used use case
+
+ //TODO: check dfc que (if we have any) that deals with pulling trace data from buffer
+
+ // Store the trace certified flag, used to suppress tracing on production images.
+ // This stored value is used throughout the session, even if the status of the certificate changes.
+ // This is done to avoid performance issues when performing the check with every trace outputted.
+ iTraceCertified = TraceCertification::IsTraceCertified();
+
+ //create activation/deactivation queue
+ const TInt KTCDfcThreadPriority = 24; // Kern::DfcQ0 is 27
+ //TODO: put this const to a header
+ //TODO: check if I can use constants for this (DFCQ0-1) ?
+ _LIT(KTCDfcQueue, "TraceCoreActivationDfcQ");
+ Kern::Printf("Creating TC dfc - %S...", &KTCDfcQueue);
+ ret = Kern::DynamicDfcQCreate(iActivationQ, KTCDfcThreadPriority, KTCDfcQueue);
+ Kern::Printf("returned code: %d, ptr: 0x%x", ret, iActivationQ);
+ if (ret==KErrNone)
+ //disable real-time state of the dfcq
+ iActivationQ->SetRealtimeState(ERealtimeStateOff);
+
+ // Disable Component ID filtering in BTrace
+ BTrace::SetFilter2(1);
+
+ // Create needed components
+ iRouter = new DTraceCoreRouter();
+ iSendReceive = new DTraceCoreSendReceive();
+ iNotifier = new DTraceCoreNotifier();
+ iConfiguration = new DTraceCoreConfiguration();
+ iInternalMessageHandler = new DTraceCoreInternalMessageHandler();
+
+ // Check that creating of the components was succesfull
+ if ( iRouter != NULL && iSendReceive != NULL && iNotifier != NULL && iConfiguration != NULL )
+ {
+ ret = iSendReceive->Init( *iRouter );
+ if ( ret == KErrNone )
+ {
+ ret = iRouter->Init( *iSendReceive );
+ if ( ret == KErrNone )
+ {
+ ret = iConfiguration->Init();
+ if ( ret == KErrNone )
+ {
+ ret = iInternalMessageHandler->Init();
+ }
+ }
+ }
+ }
+ else
+ {
+ ret = KErrNoMemory;
+ }
+
+ // BTrace handler is integrated to TraceCore
+ if ( ret == KErrNone )
+ {
+ ret = StartBTrace();
+ }
+
+ // Printf handler is integrated to TraceCore
+ if ( ret == KErrNone )
+ {
+ ret = StartPrintfTraceHandler();
+ }
+ TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::Init() - %d", ret ) );
+
+ return ret;
+ }
+
+/**
+ * Starts the BTrace handler
+ */
+TInt DTraceCore::StartBTrace()
+ {
+ TInt ret = KErrNone;
+
+ // Create BTrace handler
+ iBTrace = new DTraceCoreBTraceHandler();
+ if ( iBTrace != NULL )
+ {
+ // Init calls RegisterHandler
+ ret = iBTrace->Init();
+ }
+ else
+ {
+ ret = KErrNoMemory;
+ }
+ TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::StartBTrace() - %d", ret ) );
+ return ret;
+ }
+
+
+/**
+ * Starts the Printf trace handler
+ */
+TInt DTraceCore::StartPrintfTraceHandler()
+ {
+ TInt ret;
+
+ // Create PrintF handler
+ iPrintf = new DTraceCorePrintfTraceHandler();
+ if ( iPrintf != NULL )
+ {
+ // Init calls RegisterHandler
+ ret = iPrintf->Init();
+ }
+ else
+ {
+ ret = KErrNoMemory;
+ }
+ TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::StartPrintfTraceHandler() - %d", ret ) );
+ return ret;
+ }
+
+
+/**
+ * Registers an activation interface
+ */
+TInt DTraceCore::RegisterActivation( MTraceCoreActivation& aActivation )
+ {
+ return iActivations.Append( &aActivation );
+ }
+
+
+/**
+ * Gets an activation interface.
+ * Tracing from this method is not allowed.
+ */
+MTraceCoreActivation* DTraceCore::GetActivation( TUint32 aComponentId )
+ {
+ MTraceCoreActivation* retval = NULL;
+
+ // Find the correct activation interface from the list
+ for ( int i = 0; i < iActivations.Count(); i++ )
+ {
+ if ( iActivations[ i ]->IsComponentSupported( aComponentId ) )
+ {
+ retval = iActivations[ i ];
+ }
+ }
+
+ return retval;
+ }
+
+
+/**
+ * Registers a handler
+ *
+ * @param aHandler The handler
+ */
+TInt DTraceCore::RegisterHandler( DTraceCoreHandler& aHandler )
+ {
+ OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERHANDLER_ENTRY, "> DTraceCore::RegisterHandler 0x%x", ( TUint )&( aHandler ) );
+ TInt ret = iHandlers.Append( &aHandler );
+
+ // If there is not yet active writer, set the new one
+ if ( ret == KErrNone && iActiveWriter != NULL )
+ {
+ aHandler.SetWriter( iActiveWriter );
+ }
+
+ // Set settings to the handler
+ if ( ret == KErrNone && iTraceCoreSettings != NULL )
+ {
+ aHandler.SetSettings( iTraceCoreSettings );
+ }
+ OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERHANDLER_EXIT, "< DTraceCore::RegisterHandler. Ret:%d", ret );
+
+ return ret;
+ }
+
+
+/**
+ * Unregisters a handler
+ *
+ * @param aHandler The handler
+ */
+void DTraceCore::UnregisterHandler( DTraceCoreHandler& aHandler )
+ {
+ // Find thiss handler from the list of handlers
+ for ( TInt i = 0; i < iHandlers.Count(); i++ )
+ {
+ if ( iHandlers[ i ] == &aHandler )
+ {
+ OstTrace1( TRACE_NORMAL, DTRACECORE_UNREGISTERHANDLER_HANDLER_REMOVED, "DTraceCore::UnregisterHandler - Handler removed 0x%x", ( TUint )&aHandler );
+ iHandlers.Remove( i );
+ i = iHandlers.Count();
+ }
+ }
+ }
+
+/**
+ * Registers the settings
+ *
+ * @param aSettings The settings saver
+ * @return KErrNone if registration successful
+ */
+TInt DTraceCore::RegisterSettings( DTraceCoreSettings& aSettings )
+ {
+ iTraceCoreSettings = &aSettings;
+ for ( TInt i = 0; i < iHandlers.Count(); i++ )
+ {
+ iHandlers[ i ]->SetSettings( iTraceCoreSettings );
+ }
+ return KErrNone;
+ }
+
+
+/**
+ * Unregisters the settings
+ *
+ * @param aSettings The settings
+ */
+void DTraceCore::UnregisterSettings( DTraceCoreSettings& aSettings )
+ {
+ if ( &aSettings == iTraceCoreSettings )
+ {
+ iTraceCoreSettings = NULL;
+
+ // Remove settings from all the handlers
+ for ( TInt i = 0; i < iHandlers.Count(); i++ )
+ {
+ iHandlers[ i ]->SetSettings( NULL );
+ }
+ }
+ }
+
+
+/**
+ * Registers a writer
+ *
+ * @param aWriter The writer
+ */
+TInt DTraceCore::RegisterWriter( DTraceCoreWriter& aWriter )
+ {
+ OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERWRITER_ENTRY, "> DTraceCore::RegisterWriter 0x%x", ( TUint )&( aWriter ) );
+
+ TInt ret = iWriters.Append( &aWriter );
+ if ( ret == KErrNone )
+ {
+ // First writer that registers is selected as the active one
+ if ( iActiveWriter == NULL )
+ {
+ iActiveWriter = &aWriter;
+ SetWriterToHandlers();
+ }
+ }
+
+ OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERWRITER_EXIT, "< DTraceCore::RegisterWriter %d", ret );
+ return ret;
+ }
+
+
+/**
+ * Unregisters a writer
+ *
+ * @param aWriter The writer
+ */
+void DTraceCore::UnregisterWriter( DTraceCoreWriter& aWriter )
+ {
+ for ( TInt i = 0; i < iWriters.Count(); i++ )
+ {
+ if ( iWriters[ i ] == &aWriter )
+ {
+ OstTraceExt2( TRACE_NORMAL, DTRACECORE_UNREGISTERHANDLER_WRITER_UNREGISTERED, "DTraceCore::UnregisterWriter - Writer unregistered WriterType:%d Addr:0x%x", ( TInt )aWriter.GetWriterType(), ( TUint )&aWriter );
+ iWriters.Remove( i );
+ i = iWriters.Count();
+ // If the active writer was removed, another writer needs to be activated
+ if ( &aWriter == iActiveWriter )
+ {
+ SwitchToFirstWriter();
+ }
+ }
+ }
+ }
+
+
+/**
+ * Starts to use the first writer from the writers list
+ */
+void DTraceCore::SwitchToFirstWriter()
+ {
+ if ( iWriters.Count() > 0 )
+ {
+ iActiveWriter = iWriters[ 0 ];
+ }
+ else
+ {
+ iActiveWriter = NULL;
+ }
+ SetWriterToHandlers();
+ }
+
+
+/**
+ * Starts to use a writer of the specific type. Does nothing if the writer is already active
+ */
+EXPORT_C TInt DTraceCore::SwitchToWriter( TWriterType aWriterType )
+ {
+ OstTrace1( TRACE_FLOW, DTRACECORE_SWITCHTOWRITER_ENTRY,"> DTraceCore::SwitchToWriter WriterType:%d", ( TUint )( aWriterType ) );
+ TInt retval( KErrNone );
+
+ // Remove writer
+ if ( aWriterType == EWriterTypeNone )
+ {
+ if ( iActiveWriter != NULL )
+ {
+ iActiveWriter = NULL;
+ SetWriterToHandlers();
+ }
+ }
+ else
+ {
+ if ( iActiveWriter == NULL || iActiveWriter->GetWriterType() != aWriterType )
+ {
+ retval = KErrNotSupported;
+
+ // Find the correct writer from the list
+ for ( int i = 0; i < iWriters.Count() && retval != KErrNone; i++ )
+ {
+ DTraceCoreWriter* writer = iWriters[ i ];
+
+ // revert this
+ TWriterType wt = writer->GetWriterType();
+
+ if ( wt == aWriterType )
+ {
+ iActiveWriter = writer;
+ retval = KErrNone;
+ }
+ }
+
+ // Set writer to all handlers
+ if ( retval == KErrNone )
+ {
+ SetWriterToHandlers();
+ }
+ }
+ }
+ OstTrace1( TRACE_FLOW, DTRACECORE_SWITCHTOWRITER_EXIT, "< DTraceCore::SwitchToWriter %d", retval );
+ return retval;
+ }
+
+/**
+ * Sets the active writer to all registered handlers
+ */
+void DTraceCore::SetWriterToHandlers()
+ {
+ if ( iActiveWriter != NULL )
+ {
+ OstTraceExt2( TRACE_NORMAL, DTRACECORE_SETWRITERTOHANDLERS_WRITER_SELECTED, "DTraceCore::SetWriterToHandlers - Writer selected 0x%x WriterType:%d", (TUint) iActiveWriter, (TInt) iActiveWriter->GetWriterType() );
+ }
+
+ // PrepareSetWriter method is called with interrupts enabled
+ // SetWriter is called with interrupts disabled to prevent tracing
+ // while switching the writer
+ for ( TInt i = 0; i < iHandlers.Count(); i++ )
+ {
+ iHandlers[ i ]->PrepareSetWriter( iActiveWriter );
+ }
+ //TODO: this is not SMP safe but it's rare case - update it later
+ TInt interrupts = NKern::DisableAllInterrupts();
+ for ( TInt j = 0; j < iHandlers.Count(); j++ )
+ {
+ iHandlers[ j ]->SetWriter( iActiveWriter );
+ }
+ NKern::RestoreInterrupts( interrupts );
+ }
+
+/**
+ * Get current writer type
+ *
+ * @return Current writer type
+ */
+EXPORT_C TInt DTraceCore::GetCurrentWriterType()
+ {
+ TInt ret(0);
+ ret = iActiveWriter->GetWriterType();
+ return ret;
+ }
+
+/*
+ * Destroy the static instance of tracecore
+ */
+EXPORT_C void DTraceCore::DestroyTraceCore()
+ {
+ TC_TRACE( ETraceLevelNormal, Kern::Printf( "StopTraceCore started" ) );
+ delete DTraceCore::GetInstance();
+ DTraceCore::iInstance = NULL;
+ TC_TRACE( ETraceLevelNormal, Kern::Printf( "StopTraceCore Finished" ) );
+ }
+
+
+/**
+ * Sets the "Trace Dropped" flag
+ *
+ * @param aTraceDropped ETrue if Trace Dropped, EFalse Otherwise
+ */
+EXPORT_C void DTraceCore::SetPreviousTraceDropped(TBool aTraceDropped)
+ {
+ iPreviousTraceDropped = aTraceDropped;
+ }
+
+/**
+ * returns the state of the "Trace Dropped" flag
+ *
+ * @param none
+ */
+EXPORT_C TBool DTraceCore::PreviousTraceDropped() const
+ {
+ return iPreviousTraceDropped;
+ }
+
+
+EXPORT_C DTraceCore* DTraceCore::CreateInstance()
+ {
+ if(iInstance == NULL)
+ {
+ DTraceCore* instance = new DTraceCore();
+ if ( instance != NULL )
+ {
+ iInstance = instance;
+ TInt ret = iInstance->Init();
+ if(ret != KErrNone)
+ {
+ delete iInstance;
+ iInstance = NULL;
+ }
+ }
+ }
+
+ return iInstance;
+ }
+
+
+EXPORT_C DTraceCoreWriter* DTraceCore::GetActiveWriter()
+ {
+ return iActiveWriter;
+ }
+
+/**
+ * Reactivate all currently activated traces
+ *
+ * @param none
+ * @return KErrNone if refresh successful
+ */
+TInt DTraceCore::RefreshActivations()
+ {
+ TInt ret = KErrNone;
+ // Go through all activation interfaces from the list
+ TInt activationsCount = iActivations.Count();
+ for ( int i = 0; i < activationsCount; i++ )
+ {
+ TInt err = iActivations[ i ]->RefreshActivations();
+ if (err != KErrNone)
+ {
+ ret = err;
+ }
+ }
+ return ret;
+ }