diff -r a151135b0cf9 -r aa2539c91954 tracesrv/tracecore/btrace_handler/src/TraceCore.cpp --- /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 +#include +#include + +#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( "Init(); + } + else + { + ret = KErrNoMemory; + } + TC_TRACE( ETraceLevelFlow, Kern::Printf( "Init(); + } + else + { + ret = KErrNoMemory; + } + TC_TRACE( ETraceLevelFlow, Kern::Printf( "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; + }