--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecore/btrace_handler/src/BTraceOstCategoryHandler.cpp Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,671 @@
+// 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 "TraceCore.h"
+#include "BTraceOstCategoryHandler.h"
+#include "BTraceOstCategoryBitmap.h"
+#include "TraceCoreWriter.h"
+#include "TraceCoreDebug.h"
+#include "TraceCoreConstants.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "BTraceOstCategoryHandlerTraces.h"
+#endif
+
+#ifndef __SMP__
+/**
+ * Length of Trace group ID + Trace ID in the MultiPart traces data part
+ */
+const TUint KTraceGroupIdLen = 4;
+
+/**
+ * Length of BTrace header
+ */
+const TUint KBTraceHeaderLen = 4;
+
+/**
+ * Length of single BTrace variable
+ */
+const TUint KBTraceVariableLen = 4;
+
+/**
+ * Four bytes
+ */
+const TUint KFourBytes = 4;
+
+#endif // !__SMP__
+/**
+ * Group value in GroupId
+ */
+const TUint32 KGroupMask = 0xffff0000;
+
+
+/**
+ * Constructor
+ */
+DBTraceOstCategoryHandler::DBTraceOstCategoryHandler()
+: iAllTracesDeactivated( ETrue )
+, iCacheItem1( iComponentGroupCache ) // One "cache" item contains ComponentId, groupId, and activation info (3*32bit)
+, iCacheItem2( iComponentGroupCache+3 ) //CodForChk_Dis_Magic
+, iCacheItem3( iComponentGroupCache+6 ) //CodForChk_Dis_Magic
+, iCacheItem4( iComponentGroupCache+9 ) //CodForChk_Dis_Magic
+, iOstTraceBitmap( NULL )
+ {
+ }
+
+
+/**
+ * Destructor
+ */
+DBTraceOstCategoryHandler::~DBTraceOstCategoryHandler()
+ {
+ // Delete trace bitmap
+ delete iOstTraceBitmap;
+ }
+
+
+/**
+ * Initializes this handler
+ *
+ * @param aHandler The BTrace handler
+ */
+TInt DBTraceOstCategoryHandler::Init()
+ {
+ TInt ret = KErrNone;
+
+#ifdef __SMP__
+ for( TInt i = 0; i<MAX_MULTIPART_TRACES; i++ )
+ {
+ iMultipartArray[i].iMultiPartId = 0xffffffff;
+ iFreeList[i] = 1; // Set Free
+ }
+#endif // __SMP__
+
+ for (TUint category = KMaxKernelCategory + 1; category <= KMaxCategory; category++)
+ {
+ if (category != KCategoryNokiaBranchCoverage) // Is this exception needed?
+ {
+ ret = AddCategory( category );
+ if (ret != KErrNone)
+ {
+ break;
+ }
+ }
+ }
+
+ if (ret == KErrNone)
+ {
+ iOstTraceBitmap = new DBTraceOstCategoryBitmap( this );
+ if ( iOstTraceBitmap != NULL )
+ {
+ // Initialize TraceBitmap
+ ret = iOstTraceBitmap->Init();
+ if ( ret == KErrNone )
+ {
+ ret = iOstTraceBitmap->RegisterActivationNotification( *this );
+ if ( ret == KErrNone )
+ {
+ ret = Register();
+ if ( ret == KErrNone )
+ {
+ TC_TRACE( ETraceLevelNormal, Kern::Printf(
+ "DBTraceAutogenCategoryHandler::Init - Register OK" ) );
+ }
+ // Register failed
+ else
+ {
+ ret = KErrGeneral;
+ }
+ }
+ // RegisterActivationNotification failed
+ else
+ {
+ ret = KErrGeneral;
+ }
+ }
+ }
+ // Memory allocation failed
+ else
+ {
+ TC_TRACE( ETraceLevelError, Kern::Printf( "DBTraceOstCategoryHandler::Init - Memory allocation failed" ) );
+ ret = KErrNoMemory;
+ }
+ }
+ TC_TRACE( ETraceLevelError, Kern::Printf( "<DBTraceOstCategoryHandler::Init() - %d", ret ) );
+ return ret;
+ }
+
+/**
+ * Set settings
+ *
+ * @param aSettings Settings
+ */
+void DBTraceOstCategoryHandler::SetSettings( DTraceCoreSettings* aSettings )
+ {
+ OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYHANDLER_SETSETTINGS_ENTRY, "> DBTraceOstCategoryHandler::SetSettings 0x%x", ( TUint )( aSettings ) );
+ DBTraceCategoryHandler::SetSettings( aSettings );
+ if ( iOstTraceBitmap != NULL && aSettings != NULL )
+ {
+ // Reads the bitmap configuration from settings
+ iOstTraceBitmap->ReadFromSettings( *aSettings );
+ }
+ }
+
+/**
+ * Notification that the activation state has changed.
+ *
+ * @param aActivation the activation interface that was updated
+ * @param aFromSettings ETrue if activation was due to settings read, EFalse if from some other source
+ * @param aComponentId Component ID of the activation
+ */
+void DBTraceOstCategoryHandler::ActivationChanged( MTraceCoreActivation& aActivation, TBool aFromSettings,
+ TUint32 /*aComponentId*/)
+ {
+ OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYHANDLER_ACTIVATIONCHANGED_ENTRY, "> DBTraceOstCategoryHandler::ActivationChanged 0x%x", ( TUint )&( aActivation ) );
+
+ // Call the bitmap to write changes to settings saver
+ if ( !aFromSettings )
+ {
+ if ( iSettings != NULL )
+ {
+ aActivation.WriteToSettings( *iSettings );
+ }
+ }
+ }
+
+/**
+ * Handler for KCategoryNokiaOst
+ *
+ * @param aHeader BTrace header
+ * @param aHeader2 Extra header data
+ * @param aContext The thread context in which this function was called
+ * @param a1 The first trace parameter
+ * @param a2 The second trace parameter
+ * @param a3 The third trace parameter
+ * @param aExtra Extra trace data
+ * @param aPc The program counter value
+ * @return ETrue if trace was processed, EFalse if not
+ */
+TBool DBTraceOstCategoryHandler::HandleFrame( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
+ const TUint32 a1, const TUint32 a2, const TUint32 a3,
+ const TUint32 aExtra, const TUint32 aPc )
+ {
+ TBool retval(EFalse);
+ if ( iWriter != NULL && !iAllTracesDeactivated )
+ {
+ __ASSERT_DEBUG( iOstTraceBitmap != NULL,
+ Kern::Fault( "DBTraceOstCategoryHandler::HandleFrame - NULL", KErrGeneral ) );
+
+ // Check if tracing is certified
+ DTraceCore* tracecore = DTraceCore::GetInstance();
+ if (!tracecore || !tracecore->IsTraceCertified())
+ {
+ return EFalse;
+ }
+
+ // Check if the trace is a multipart trace
+ TBool isMultiPart = CheckMultiPart(aHeader, aHeader2);
+
+ if (isMultiPart)
+ {
+
+#ifdef __SMP__
+ // Handle the multipart trace
+ retval = HandleMultiPart(aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc);
+#else
+ // Handle the multipart trace. Returns EFalse if trace is not activated.
+ TBool isActivatedMultiPart = HandleMultiPart(aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc);
+ if (isActivatedMultiPart)
+ {
+ retval = ETrue;
+ }
+ else
+ {
+ retval = EFalse;
+ }
+#endif // __SMP__
+
+ }
+ // Not a multipart trace
+ else
+ {
+
+ // Take group and leave trace id away
+ TUint32 group = a2 & KGroupMask;
+
+ if ((*iCacheItem1) == a1 && (*(iCacheItem1 + 1)) == group)
+ {
+ retval = *(iCacheItem1 + 2); //CodForChk_Dis_Magic
+ }
+ else if ((*iCacheItem2) == a1 && (*(iCacheItem2 + 1)) == group)
+ {
+ retval = *(iCacheItem2 + 2); //CodForChk_Dis_Magic
+ }
+ else if ((*iCacheItem3) == a1 && (*(iCacheItem3 + 1)) == group)
+ {
+ retval = *(iCacheItem3 + 2); //CodForChk_Dis_Magic
+ }
+ else if ((*iCacheItem4) == a1 && (*(iCacheItem4 + 1)) == group)
+ {
+ retval = *(iCacheItem4 + 2); //CodForChk_Dis_Magic
+ }
+ else
+ {
+ retval = iOstTraceBitmap->IsTraceActivated(a1, a2);
+
+ iTemp = iCacheItem1;
+ iCacheItem1 = iCacheItem4;
+ iCacheItem4 = iCacheItem3;
+ iCacheItem3 = iCacheItem2;
+ iCacheItem2 = iTemp;
+ *iCacheItem1 = a1;
+ *(iCacheItem1 + 1) = group;
+ *(iCacheItem1 + 2) = retval;
+
+ }
+
+ if ( ( ( aHeader >> ( BTrace::ESubCategoryIndex * KByteSize ) ) & KByteMask ) == EOstTraceActivationQuery )
+ {
+ //Trace from here is not allowed
+ }
+ else if ( retval )
+ {
+ CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
+ TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
+ iWriter->WriteTraceCoreFrame( a1, a2, aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc, recordSize );
+ }
+ }
+ }
+ else
+ {
+ if( iWriter == NULL )
+ {
+ //Trace from here is not allowed
+ retval = EFalse;
+ }
+
+ }
+
+ //Trace from here is not allowed
+ return retval;
+ }
+
+/**
+ * Checks if the given trace is a Multipart trace
+ *
+ * @param aHeader Header data
+ * @param aHeader2 Extra header data
+ * @return ETrue if trace is a Multipart trace, EFalse if not
+ */
+inline TBool DBTraceOstCategoryHandler::CheckMultiPart( TUint32 aHeader, TUint32 aHeader2 )
+ {
+ TBool retval = EFalse;
+ TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
+ if (flags & BTrace::EHeader2Present)
+ {
+ // First, middle or last part of Multipart trace
+ if (aHeader2 & BTrace::EMultipartFlagMask)
+ {
+ retval = ETrue;
+ }
+ }
+
+ //Trace from here is not allowed
+ return retval;
+ }
+
+/**
+ * Checks if there is a dropped trace and updates header if so
+ *
+ * @param aHeader Header data
+ */
+inline TBool DBTraceOstCategoryHandler::CheckDroppedTrace( TUint32& aHeader )
+ {
+ TBool ret(EFalse);
+
+ DTraceCore* tracecore = DTraceCore::GetInstance();
+ if (tracecore && (tracecore->PreviousTraceDropped())) //if previous trace was dropped
+ {
+ //set flags back to EFalse first
+ tracecore->SetPreviousTraceDropped(EFalse);
+
+ //set missing flag in BTrace
+ aHeader |= BTrace::EMissingRecord<<(BTrace::EFlagsIndex * KByteSize);
+
+ ret = ETrue;
+ }
+
+ return ret;
+ }
+
+#ifdef __SMP__
+
+
+TInt DBTraceOstCategoryHandler::Find( TUint32 aMultiPartId )
+ {
+ TInt ret(KErrNotFound);
+ for( TInt i = 0; i<MAX_MULTIPART_TRACES; i++ )
+ {
+ if( iMultipartArray[i].iMultiPartId == aMultiPartId )
+ {
+ ret = i;
+ break;
+ }
+ }
+ return ret;
+ }
+
+void DBTraceOstCategoryHandler::Remove( TUint32 aIndex )
+ {
+ iMultipartArray[aIndex].iMultiPartId = 0xffffffff;
+ iFreeList[aIndex] = 1; // Set free
+ }
+
+ /**
+ *
+ * @return KErrNone if added, otherwise KErrNotFound.
+ */
+TInt DBTraceOstCategoryHandler::InsertIfNotExist( TMultiPartActivationInfo &aMultiPartTrace )
+ {
+ TInt ret = Find( aMultiPartTrace.iMultiPartId );
+ if( ret == KErrNotFound )
+ {
+ // Find free slot
+ for( TInt freeIndex = 0; freeIndex<MAX_MULTIPART_TRACES; freeIndex++ )
+ {
+ if( iFreeList[freeIndex] )
+ {
+ iFreeList[freeIndex] = 0; // Set reserved
+ iMultipartArray[freeIndex].iComponentId = aMultiPartTrace.iComponentId;
+ iMultipartArray[freeIndex].iTraceWord = aMultiPartTrace.iTraceWord;
+ iMultipartArray[freeIndex].iMultiPartId = aMultiPartTrace.iMultiPartId;
+ ret = KErrNone;
+ break;
+ }
+ }
+
+ }
+ return ret;
+ }
+
+
+/**
+ * Handles this Multipart trace
+ *
+ * @param aHeader BTrace header
+ * @param aHeader2 Extra header data
+ * @param aContext The thread context in which this function was called
+ * @param a1 First parameter
+ * @param a2 Second parameter
+ * @param aData The data
+ * @param aExtra Extra trace data
+ * @param aPc The program counter value
+ * @return ETrue if trace is activated
+ */
+TBool DBTraceOstCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
+ const TUint32 a1, const TUint32 a2, const TUint32 aData, const TUint32 aExtra,
+ const TUint32 aPc)
+ {
+ TBool retval = ETrue;
+ TInt multiPartOffset = aHeader2 & BTrace::EMultipartFlagMask;
+ TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
+
+ // First part of multipart trace
+ if (multiPartOffset == BTrace::EMultipartFirst)
+ {
+ // Create new MultiPart activation info and save it to the array
+ TMultiPartActivationInfo activationInfo;
+ activationInfo.iComponentId = a2;
+
+ // This should be safe operation as if there is not enough data, the trace should not
+ // be first part of multipart trace
+ TUint32* ptr = reinterpret_cast< TUint32* >(aData);
+ activationInfo.iTraceWord = *ptr++;
+ activationInfo.iMultiPartId = aExtra;
+ retval = iOstTraceBitmap->IsTraceActivated( activationInfo.iComponentId, activationInfo.iTraceWord );
+
+ if (retval)
+ {
+ // Insert the item to the array
+ TInt ret = InsertIfNotExist( activationInfo );
+
+ if (KErrNone == ret)
+ {
+ CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
+
+ // Write the trace. Skip first 4 bytes as it's the traceWord which is given in different parameter
+ iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord,
+ aHeader, aHeader2, aContext, activationInfo.iComponentId,
+ activationInfo.iTraceWord, aData + 4, aExtra, aPc, recordSize - 4 );
+ }
+ else
+ {
+ retval = EFalse;
+ }
+ }
+ }
+ // Middle or last part of multipart trace
+ else if (multiPartOffset == BTrace::EMultipartMiddle || multiPartOffset == BTrace::EMultipartLast)
+ {
+ // Check index of component id in array
+ TMultiPartActivationInfo tempInfo;
+ tempInfo.iMultiPartId = aExtra;
+
+ TInt index = Find( aExtra );
+
+ if (index != KErrNotFound)
+ {
+ CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
+
+ TMultiPartActivationInfo activationInfo;
+ activationInfo.iComponentId = iMultipartArray[index].iComponentId;
+ activationInfo.iTraceWord = iMultipartArray[index].iTraceWord;
+ activationInfo.iMultiPartId = iMultipartArray[index].iMultiPartId;
+
+ // Write the trace
+ iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord, aHeader, aHeader2,
+ aContext, activationInfo.iComponentId, activationInfo.iTraceWord, aData, aExtra, aPc, recordSize );
+
+ // Last part, remove the item from the array
+ if (multiPartOffset == BTrace::EMultipartLast)
+ {
+ Remove(index);
+ }
+ }
+ }
+
+ //Trace from here is not allowed
+
+ return retval;
+ }
+
+#else // __SMP__
+
+/**
+ * Handles this Multipart trace
+ *
+ * @param aHeader BTrace header
+ * @param aHeader2 Extra header data
+ * @param aContext The thread context in which this function was called
+ * @param a1 First parameter
+ * @param a2 Second parameter
+ * @param aData The data
+ * @param aExtra Extra trace data
+ * @param aPc The program counter value
+ * @return ETrue if trace was processed, EFalse if not
+ */
+TBool DBTraceOstCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
+ const TUint32 a1, const TUint32 a2, const TUint32 aData, const TUint32 aExtra,
+ const TUint32 aPc)
+ {
+ TBool retval = EFalse;
+
+ if (iMultiPartTrace.iMultiPartId == 0 || iMultiPartTrace.iMultiPartId == aExtra)
+ {
+ // First part of multipart trace
+ if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartFirst)
+ {
+ TUint32 componentId = a2;
+ TUint32* ptr = ( TUint32* )aData;
+ TUint32 traceWord = *ptr++;
+ retval = iOstTraceBitmap->IsTraceActivated( componentId, traceWord );
+ if (retval)
+ {
+ CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
+
+ // Set values
+ iMultiPartTrace.iMultiPartId = aExtra;
+ iMultiPartTrace.iComponentId = componentId;
+ iMultiPartTrace.iTraceWord = traceWord;
+ iMultiPartTrace.iContext = aContext;
+ iMultiPartTrace.iPc = aPc;
+ iMultiPartTrace.iHeader = aHeader;
+
+ // Remove the multipart information from the header2
+ aHeader2 &= ~BTrace::EMultipartFlagMask;
+ iMultiPartTrace.iHeader2 = aHeader2;
+
+ // Copy the data
+ TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
+ TUint32 dataSize = recordSize - CalculateDataStartOffset(aHeader);
+ memcpy(iMultiPartTrace.iData, (TUint8*)aData + KTraceGroupIdLen, dataSize - KTraceGroupIdLen);
+ iMultiPartTrace.iDataInserted = dataSize - KTraceGroupIdLen;
+ }
+ }
+ // Middle part of multipart trace
+ else if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartMiddle)
+ {
+ retval = ETrue;
+ // Add to the data buffer
+ TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
+ TUint32 dataSize = recordSize - CalculateDataStartOffset(aHeader);
+
+ // Check that trace is not too big
+ if (iMultiPartTrace.iDataInserted + dataSize < MAX_TRACE_DATA_SIZE)
+ {
+ CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
+ memcpy(iMultiPartTrace.iData + iMultiPartTrace.iDataInserted, (TUint8*)aData, dataSize);
+ iMultiPartTrace.iDataInserted += dataSize;
+ }
+ }
+ // Last part of multipart trace
+ else if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartLast)
+ {
+ retval = ETrue;
+ TUint32 totalDataLen = a1;
+ TUint32 offset = a2;
+
+ // Add to the data buffer
+ TUint32 partLen = totalDataLen - offset;
+ TUint32 dataStartOffset = CalculateDataStartOffset(iMultiPartTrace.iHeader);
+
+ // Check that trace is not too big
+ if (iMultiPartTrace.iDataInserted + partLen <= MAX_TRACE_DATA_SIZE)
+ {
+ CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
+
+ // If the last part contains only last four bytes, it's a value instead of pointer
+ if (partLen == KFourBytes)
+ {
+ iMultiPartTrace.iData[iMultiPartTrace.iDataInserted] = aData & KByteMask;
+ iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 1] = (aData >> 8) & KByteMask; //CodForChk_Dis_Magic
+ iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 2] = (aData >> 16) & KByteMask; //CodForChk_Dis_Magic
+ iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 3] = (aData >> 24) & KByteMask; //CodForChk_Dis_Magic
+ }
+ else
+ {
+ memcpy(iMultiPartTrace.iData + iMultiPartTrace.iDataInserted, (TUint8*)aData, partLen);
+ }
+
+ // Total data length. Four bytes is taken out because it was parsed out from the data
+ // array when parsing first part of the trace
+ totalDataLen = totalDataLen + dataStartOffset - KFourBytes;
+
+ }
+ else
+ {
+ // Total data length. Four bytes is taken out because it was parsed out from the data
+ // array when parsing first part of the trace
+ totalDataLen = iMultiPartTrace.iDataInserted + dataStartOffset - KFourBytes;
+ }
+
+ // Write the trace
+ iWriter->WriteTraceCoreFrame( iMultiPartTrace.iComponentId, iMultiPartTrace.iTraceWord,
+ iMultiPartTrace.iHeader, iMultiPartTrace.iHeader2, iMultiPartTrace.iContext,
+ iMultiPartTrace.iComponentId, iMultiPartTrace.iTraceWord, (TUint32)iMultiPartTrace.iData,
+ iMultiPartTrace.iMultiPartId, iMultiPartTrace.iPc, totalDataLen);
+
+ iMultiPartTrace.iMultiPartId = 0;
+ }
+ }
+
+ return retval;
+ }
+
+/**
+ * Calculates data start offset
+ *
+ * @param aHeader BTrace header
+ */
+TUint32 DBTraceOstCategoryHandler::CalculateDataStartOffset( TUint32 aHeader )
+ {
+ TUint32 offset = 0;
+ TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
+
+ // First add header length
+ offset += KBTraceHeaderLen;
+
+ // Header2 is present
+ if ( flags & BTrace::EHeader2Present )
+ {
+ offset += KBTraceVariableLen;
+ }
+ // Timestamp is present
+ if ( flags & BTrace::ETimestampPresent )
+ {
+ offset += KBTraceVariableLen;
+ }
+ // Timestamp2 is present
+ if ( flags & BTrace::ETimestamp2Present )
+ {
+ offset += KBTraceVariableLen;
+ }
+ // Context ID is present
+ if ( flags & BTrace::EContextIdPresent )
+ {
+ offset += KBTraceVariableLen;
+ }
+ // Program counter is present
+ if ( flags & BTrace::EPcPresent )
+ {
+ offset += KBTraceVariableLen;
+ }
+ // Extra value is present
+ if ( flags & BTrace::EExtraPresent )
+ {
+ offset += KBTraceVariableLen;
+ }
+
+ // Next 8 bytes came with first and second parameter of the multipart trace
+ offset += KFourBytes;
+ offset += KFourBytes;
+
+ return offset;
+ }
+
+#endif // !__SMP__
+
+// End of File