tracesrv/tracecore/btrace_handler/src/BTraceOstCategoryHandler.cpp
changeset 56 aa2539c91954
--- /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