tracesrv/tracecore/btrace_handler/src/TraceCoreMediaSWriter.cpp
changeset 56 aa2539c91954
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecore/btrace_handler/src/TraceCoreMediaSWriter.cpp	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,363 @@
+// 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
+//
+
+#include <kernel/kernel.h>
+
+#include "TraceCoreMediaSWriter.h"
+#include "TraceCoreMediaIf.h"
+#include "TraceCoreConstants.h"
+#include "TraceCore.h"
+#include "TraceCoreSendReceive.h"
+#include "TraceCoreDebug.h"
+
+
+//- Internal definitions ----------------------------------------------------
+#ifdef MEDIA_WRITER_STATISTICS
+
+/**
+ * Collects statistics about the media writer
+ */
+class TMediaSWriterStatistics
+    {
+public:
+    TUint32 iTraces;                // Number of traces received
+    TUint32 iSent;                  // Number of traces sent
+    TUint32 iFailed;                // Number of traces failed to send
+    TUint32 iMissed;                // Number of traces missed due to not enough buffers
+    TUint32 iSleepCount;            // Number of times the threads have slept waiting for buffers
+    TUint32 iCannotSleepCount;      // Number of times a thread could not be slept when it should
+    TUint32 iBlockCount;            // Number of times a thread has been blocked waiting for buffers
+    TUint32 iCannotBlockCount;      // Number of times a thread could not be blocked when it should
+    TUint32 iWaitDidNotHelp;        // Number of waits that did not help
+    TUint32 iMinFreeBuffers;        // Minimum number of free buffers since boot
+    TUint32 iInvalidContextTrace;   // Number of IRQ / IDFC traces ignored
+    TUint32 iIdlePings;             // Statistics are written after some idle time
+    TBool iStatisticsChanged;       // Flags indicating change in statistics
+    };
+
+/**
+ * Macro to wrap statistics-related code
+ */
+#define STATS( x ) x
+
+/**
+ * Initializes the statistics structure
+ */
+TBool DTraceCoreMediaSWriter::InitStatistics()
+    {
+    iStatistics = new TMediaSWriterStatistics();
+    return iStatistics != NULL;
+    }
+
+#else
+
+/**
+ * Empty class for statistics if flag is not set
+ */
+class TMediaSWriterStatistics {};
+
+#define STATS( x )
+
+#endif
+
+
+/**
+ * Max length of one trace
+ */
+const TUint32 KMaxBufLength = 256;
+
+/**
+ * Number of traces that can be buffered
+ */
+const TUint32 KBufCount = 1;
+
+/**
+ * Constructor
+ */
+EXPORT_C DTraceCoreMediaSWriter::DTraceCoreMediaSWriter()
+: DTraceCoreWriter( EWriterTypeUSBPhonet )
+, iSendDfc( DTraceCoreMediaSWriter::SendDfc, this, DTraceCore::GetActivationQ(), KDefaultDfcPriority )
+, iSendTimerActive( EFalse )
+, iFirstFreeBuffer( NULL )
+, iFirstReadyBuffer( NULL )
+, iLastReadyBuffer( NULL )
+, iTraceBuffers( NULL )
+, iFreeBuffers( KBufCount )
+, iSenderThread( NULL )
+, iLastTraceSent( 0 )
+, iStatistics( NULL )
+    {
+    // No implementation in constructor
+    }
+
+
+/**
+ * Destructor
+ */
+EXPORT_C DTraceCoreMediaSWriter::~DTraceCoreMediaSWriter()
+    {
+    // Delete all trace buffers
+    for ( TUint i = 0; i < KBufCount; i++ )
+        {
+        delete[] iTraceBuffers[ i ].iBuffer;
+        }
+
+    delete[] iTraceBuffers;
+    delete iStatistics;
+    }
+
+
+/**
+ * Registers this writer to TraceCore
+ *
+ * @return KErrNone if successful
+ */
+EXPORT_C TInt DTraceCoreMediaSWriter::Register()
+    {
+    // Media writer uses the media interface from SendReceive
+    TInt retval( KErrGeneral );
+
+    // Get TraceCore
+    DTraceCore* traceCore = DTraceCore::GetInstance();
+    if ( traceCore != NULL )
+        {
+
+        // Get MediaWriter interface
+        DTraceCoreMediaIf* writerIf = traceCore->GetSendReceive().GetMediaWriterIf();
+        if ( writerIf != NULL )
+            {
+            // Allocates memory for the trace buffers
+            TBool memOK = ETrue;
+            STATS( memOK = InitStatistics() );
+            if(memOK)
+                {
+                iTraceBuffers = new TTraceBuffer[ KBufCount ];
+                }
+            if (iTraceBuffers == NULL)
+                {
+                memOK=EFalse;
+                }
+            if ( memOK )
+                {
+                for ( TUint i = 0; i < KBufCount && memOK; i++ )
+                    {
+                    iTraceBuffers[ i ].iBuffer = new TUint8[ KMaxBufLength ];
+                    if (iTraceBuffers[ i ].iBuffer == NULL )
+                        {
+                        memOK = EFalse;
+                        }
+                    if ( memOK )
+                        {
+                        // Initially all buffers are linked to iFirstFreeBuffer
+                        // Casting needed to work around armv5 "pointless comparison of unsigned integer with zero" warning
+                        if ( (TInt) i < (TInt) ( KBufCount - 1 ) )
+                            {
+                            iTraceBuffers[ i ].iNext = &( iTraceBuffers[ i + 1 ] );
+                            }
+                        }
+                    else
+                        {
+                        memOK = EFalse;
+                        }
+                    }
+                }
+            else
+                {
+                memOK = EFalse;
+                }
+
+            // Memory was allocated succesfully
+            if ( memOK )
+                {
+                iFastCounterBetweenTraces = NKern::FastCounterFrequency() / GetTraceFrequency();
+                iFirstFreeBuffer = iTraceBuffers;
+
+                // Register to the TraceCore
+                retval = DTraceCoreWriter::Register();
+                if ( retval == KErrNone )
+                    {
+                    iMediaIf = writerIf;
+                    }
+                }
+            else
+                {
+                retval = KErrNoMemory;
+                }
+            }
+        }
+    TC_TRACE( ETraceLevelFlow, Kern::Printf("<DTraceCoreMediaSWriter::Register - %d", retval) );
+    return retval;
+    }
+
+
+/**
+ * Starts an entry
+ *
+ * @param aType the type of the trace entry
+ * @return the entry ID that is passed to other Write-functions
+ */
+EXPORT_C TUint32 DTraceCoreMediaSWriter::WriteStart( TWriterEntryType aType )
+    {
+
+    // Detaches the first free buffer from the free buffers list
+    TInt context( NKern::CurrentContext() );
+    TTraceBuffer* freeBuf = NULL;
+
+    if ( context == NKern::EThread || context == NKern::EIDFC )
+        {
+#ifndef __SMP__
+        // In non SMP env the __SPIN_LOCK macro is empty. We need Kern::Lock.
+		NKern::Lock(); // Unlocked in WriteEnd
+#else
+		//already locked by BTrace spin lock
+#endif
+
+		freeBuf = iFirstFreeBuffer;
+
+        if ( freeBuf != NULL )
+            {
+            StartBuffer( aType, *freeBuf );
+            }
+        }
+    else
+        {
+        freeBuf = NULL;
+        }
+
+    return ( TUint32 )freeBuf;
+    }
+
+
+/**
+ * Ends an entry
+ *
+ * @param aEntryId the entry ID returned by WriteStart
+ * @param aWriteEndingZero If ETrue, write ending zero.
+ */
+EXPORT_C void DTraceCoreMediaSWriter::WriteEnd( TUint32 aEntryId  )
+    {
+
+    if ( aEntryId != 0 )
+        {
+        TTraceBuffer* buf = ( TTraceBuffer* )aEntryId;
+        TBool drop = EndBuffer( *buf );
+
+        if( !drop ) //trace isn't dropped
+            {
+            iSendDfc.RawAdd();
+            }
+
+        // Locked in WriteStart
+#ifndef __SMP__
+        // In non SMP the __SPIN_LOCK macro is empty. We need Kern::Unlock.
+		NKern::Unlock(); // Locked in WriteStart
+#else
+		//BTrace lock is used from outside of this method.
+#endif
+        }
+    }
+
+
+/**
+ * Writes 8-bit data to given entry
+ *
+ * @param aEntryId the entry ID returned by WriteStart
+ * @param aData the trace data
+ */
+EXPORT_C void DTraceCoreMediaSWriter::WriteData( TUint32 aEntryId, TUint8 aData )
+    {
+    if ( aEntryId != 0 )
+        {
+        TTraceBuffer* buf = ( TTraceBuffer* )aEntryId;
+        if ( buf->iLength < KMaxBufLength )
+            {
+            *( buf->iBuffer + buf->iLength ) = aData;
+            buf->iLength++;
+            }
+        }
+    }
+
+
+/**
+ * Writes 16-bit data to given entry
+ *
+ * @param aEntryId the entry ID returned by WriteStart
+ * @param aData the trace data
+ */
+EXPORT_C void DTraceCoreMediaSWriter::WriteData( TUint32 aEntryId, TUint16 aData )
+    {
+    if ( aEntryId != 0 )
+        {
+        TTraceBuffer* buf = ( TTraceBuffer* )aEntryId;
+        if ( buf->iLength + sizeof ( TUint16 ) <= KMaxBufLength )
+            {
+            *( ( TUint16* )( buf->iBuffer + buf->iLength ) ) = aData;
+            buf->iLength += sizeof ( TUint16 );
+            }
+        }
+    }
+
+
+/**
+ * Writes 32-bit data to given entry
+ *
+ * @param aEntryId the entry ID returned by WriteStart
+ * @param aData the trace data
+ */
+EXPORT_C void DTraceCoreMediaSWriter::WriteData( TUint32 aEntryId, TUint32 aData )
+    {
+    if ( aEntryId != 0 )
+        {
+        TTraceBuffer* buf = ( TTraceBuffer* )aEntryId;
+        if ( buf->iLength + sizeof ( TUint32 ) <= KMaxBufLength )
+            {
+            *( ( TUint32* )( buf->iBuffer + buf->iLength ) ) = SWAP_DATA( aData );
+            buf->iLength += sizeof ( TUint32 );
+            }
+        }
+    }
+
+
+/**
+ * DFC for sending data
+ *
+ * @param aMediaWriter the media writer
+ */
+void DTraceCoreMediaSWriter::SendDfc( TAny* aMediaWriter )
+    {
+    DTraceCoreMediaSWriter* writer = static_cast< DTraceCoreMediaSWriter* >( aMediaWriter );
+    writer->SendDfc();
+    }
+
+
+/**
+ * Called from static DFC function to send a buffer
+ */
+void DTraceCoreMediaSWriter::SendDfc()
+    {
+    // Create and send note random values
+    TBuf8<64> note; // CodForChk_Dis_Magic
+    note.Append(0xAE); // Dont care, CodForChk_Dis_Magic
+    note.Append(0xAE); // Dont care, CodForChk_Dis_Magic
+    note.Append(0x00); // Lentght MSB, CodForChk_Dis_Magic
+    note.Append(0x02); // Length LSB, CodForChk_Dis_Magic
+    note.Append(0xED); // Dont care, CodForChk_Dis_Magic
+    note.Append(0xED); // Dont care, CodForChk_Dis_Magic
+
+    iMediaIf->SendTrace( note );
+    }
+
+// End of File