sysanadatacapture/piprofiler/piprofiler_api/inc/ProfilerGenericClassesKrn.inl
changeset 1 3ff3fecb12fe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysanadatacapture/piprofiler/piprofiler_api/inc/ProfilerGenericClassesKrn.inl	Thu Feb 11 15:52:57 2010 +0200
@@ -0,0 +1,531 @@
+/*
+* Copyright (c) 2009 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:  
+*
+*/
+
+
+#include <kern_priv.h>
+
+#include <piprofiler/ProfilerGenericClassesKrn.h>
+
+
+/*
+ *	
+ *	Class CProfilerSamplerBase implementation
+ *
+ */
+
+inline DProfilerSamplerBase::DProfilerSamplerBase()
+    {
+	
+    }
+
+inline DProfilerSamplerBase::~DProfilerSamplerBase()
+    {
+	
+    }
+
+/*
+ *	
+ *	Class CProfilerSampleBuffer implementation
+ *
+ */
+
+inline DProfilerSampleBuffer::DProfilerSampleBuffer(TUint8* aBuffer, 
+											TUint8* aDblBuffer, 
+											TUint32 aBufferSize )
+    {
+	LOGSTRING3("CProfilerSampleBuffer::CProfilerSampleBuffer AtFirst: b:0x%x db:0x%x",aBuffer,aDblBuffer);
+
+	// make sure the alignment is right
+	if((((TUint32)aBuffer) %4) != 0)
+	    aBuffer += (4-(((TUint32)aBuffer)%4));
+	if((((TUint32)aDblBuffer) %4) != 0)
+	    aDblBuffer += (4-(((TUint32)aDblBuffer)%4));
+
+	LOGSTRING3("CProfilerSampleBuffer::CProfilerSampleBuffer b:0x%x db:0x%x",aBuffer,aDblBuffer);
+
+	iBufStruct = (TProfilerSampleBufStruct*)aBuffer;
+	iDblBufStruct = (TProfilerSampleBufStruct*)aDblBuffer;
+
+	LOGSTRING3("CProfilerSampleBuffer::CProfilerSampleBuffer bufStruct rem:0x%x dbuStruct rem:0x%x",
+						&iBufStruct->iSampleRemainder,&iDblBufStruct->iSampleRemainder);
+
+	iBufferDataSize = aBufferSize-4;
+	iBufferRealSize = aBufferSize;
+
+	ClearBuffer();
+    }
+
+inline DProfilerSampleBuffer::~DProfilerSampleBuffer()
+    {
+	
+    }
+
+inline TInt DProfilerSampleBuffer::AddSample(TUint8* aSample, TUint32 aLength)
+    {
+	TUint32 bytesTotal;
+
+	// check whether the buffer status is
+	switch (iBufferStatus)
+	    {
+		case DProfilerSampleBuffer::BufferOk:
+			// add the data normally to the buffer
+			bytesTotal = iBytesWritten+aLength;
+
+			if(bytesTotal < iBufferDataSize)
+			    {
+				memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,aLength);
+				iBytesWritten+=aLength;
+				return 0;
+			    }
+			else
+			    {
+
+				// the sample does not fit to the buffer
+				// first copy as much data as we can fit to the first buffer
+				TUint32 fitsToBuffer = iBufferDataSize-iBytesWritten;
+				TUint32 remaining = aLength-fitsToBuffer;
+
+				memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,fitsToBuffer);
+				iBytesWritten = iBufferDataSize;
+
+				// ->switch to the double buffer
+				iBufferStatus = DProfilerSampleBuffer::BufferCopyAsap;
+				
+				TProfilerSampleBufStruct* tmpPtr = iBufStruct;
+				iBufStruct = iDblBufStruct;
+				iDblBufStruct = tmpPtr;
+				
+				iDblBytesWritten = iBytesWritten;
+
+				// and this is the remainder of a sample
+				// that will be copied to the new buffer
+				// just in a while
+				iBufStruct->iSampleRemainder = remaining;
+				
+				// now that the buffers have been switched
+				// add the rest of the sample to the buffer
+				aSample+=fitsToBuffer;
+
+				// there should be room - in case the single sample
+				// is smaller than the whole buffer! so we don't
+				// bother to check
+
+				memcpy((&(iBufStruct->iDataStart)),aSample,remaining);
+				iBytesWritten = remaining;
+				return 0;
+			    }
+
+		case DProfilerSampleBuffer::BufferCopyAsap:
+
+			// no difference to the BufferOk case
+			// unless the double buffer gets filled
+			// before the data has been copied
+			// add the data normally to the buffer
+			bytesTotal = iBytesWritten+aLength;
+
+			if(bytesTotal < iBufferDataSize)
+			    {
+				memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,aLength);
+				iBytesWritten+=aLength;
+				return 0;
+			    }
+			else
+			    {
+				// the double buffer is now also full - there is no
+				// place to put the data -> we have to waste it!
+				// this is an indication of a too small buffer size
+				iBufferStatus = DProfilerSampleBuffer::BufferFull;
+				LOGSTRING("CProfilerSampleBuffer::AddSample - double buffer full!!");
+				return -1;
+			    }
+
+		case DProfilerSampleBuffer::BufferBeingCopied:
+
+			// no difference to the BufferCopyAsap case
+			bytesTotal = iBytesWritten+aLength;
+
+			if(bytesTotal < iBufferDataSize)
+			    {
+				memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,aLength);
+				iBytesWritten+=aLength;
+				return 0;
+			    }
+			else
+			    {
+				// the double buffer is now also full - there is no
+				// place to put the data -> we have to waste it!
+				// this is an indication of a too small buffer size
+				LOGSTRING("CProfilerSampleBuffer::AddSample - double buffer full!!");
+				
+				// don't change the state to CProfilerSampleBuffer::BufferFull, since it is
+				// already being copied
+				return -1;
+			    }
+
+		case DProfilerSampleBuffer::BufferFull:
+			// the buffer is still full, there is noting we can do
+			// about it -> return
+			LOGSTRING("CProfilerSampleBuffer::AddSample - double buffer full!!");
+			return -1;
+
+		default:
+			LOGSTRING("CProfilerSampleBuffer::AddSample - wrong switch!!");
+			return -1;
+	    }
+    }
+
+inline void DProfilerSampleBuffer::EndSampling()
+    {
+	LOGSTRING("CProfilerSampleBuffer::EndSampling");
+	// this will switch to the dbl buffer even though
+	// the buffer is not full, so that data can be copied
+
+	// during this operation, no other buffer
+	// operations are allowed
+
+	// ensure that the normal buffer is in use and that the
+	// buffer is in normal state ( this procedure is performed only once )
+	if(iBufferStatus == DProfilerSampleBuffer::BufferOk)
+	    {
+		// ->switch to the double buffer
+		LOGSTRING("CProfilerSampleBuffer::EndSampling - switching to double buffer");
+		iBufferStatus = DProfilerSampleBuffer::BufferCopyAsap;
+		
+		TProfilerSampleBufStruct* tmpPtr = iBufStruct;
+		iBufStruct = iDblBufStruct;
+		iDblBufStruct = tmpPtr;
+				
+		iDblBytesWritten = iBytesWritten;
+		
+		// there is no new sample so the remainder is
+		// zero, (this shouldn't be used anyway)
+		iBufStruct->iSampleRemainder = 0;
+	    }
+    }
+
+inline TUint32 DProfilerSampleBuffer::GetBufferStatus()
+    {
+	return iBufferStatus;
+    }
+
+inline void DProfilerSampleBuffer::ClearBuffer()
+    {
+	LOGSTRING2("CProfilerSampleBuffer::ClearBuffer - %d",bufferDataSize);
+
+	// the buffers are of same size
+	TUint8* ptr1 = (TUint8*)&(iBufStruct->iDataStart);
+	TUint8* ptr2 = (TUint8*)&(iDblBufStruct->iDataStart);
+
+	for(TUint32 i=0;i<iBufferDataSize;i++)
+	    {
+		ptr1[i] = 0;
+		ptr2[i] = 0;
+	    }
+
+
+	iBufStruct->iSampleRemainder = 0;
+	iDblBufStruct->iSampleRemainder = 0;
+
+	// written the dblBufStruct
+	iBytesWritten = 0;
+	iDblBytesWritten = 0;
+	iDblBytesRead = 0;
+
+	iBufferStatus = DProfilerSampleBuffer::BufferOk;
+    }
+
+inline void DProfilerSampleBuffer::DataCopied()
+    {
+	iDblBytesRead = 0;
+	iDblBytesWritten = 0;
+	iBufferStatus = DProfilerSampleBuffer::BufferOk;
+    }
+
+/*
+ *
+ *	Class DProfilerSampleStream implementation
+ *
+ */
+
+inline DProfilerSampleStream::DProfilerSampleStream()
+    {
+	LOGSTRING("DProfilerSampleStream::DProfilerSampleStream");
+
+	iCurrentBuffer = 0;
+	iPendingRequest = 0;
+	iAddingSamples = 0;
+	iClient = 0;
+    }
+
+inline DProfilerSampleStream::~DProfilerSampleStream()
+    {
+	LOGSTRING("DProfilerSampleStream::~DProfilerSampleStream");	
+    }
+
+inline void DProfilerSampleStream::InsertCurrentClient(DThread* aClient)
+    {
+	iClient = aClient;
+	LOGSTRING2("DProfilerSampleStream::InsertCurrentClient - iClient is 0x%x",iClient);
+    }
+
+
+inline void DProfilerSampleStream::AddSampleBuffer(TBapBuf* aBuffer,TRequestStatus* aStatus)
+    {
+	if(iCurrentBuffer != 0 || iPendingRequest != 0)
+	    {
+		LOGSTRING("DProfilerSampleStream::AddSampleBuffer - ERROR 1");
+		return;
+	    }
+
+	LOGSTRING3("DProfilerSampleStream::AddSampleBuffer - OK 0x%x,0x%x",aBuffer,aStatus);
+	iCurrentBuffer = aBuffer;
+	iPendingRequest = aStatus;
+	
+	LOGSTRING2("DProfilerSampleStream::AddSampleBuffer - Current Client is 0x%x",iClient);	
+    }
+
+
+inline void DProfilerSampleStream::ReleaseIfPending()
+    {
+	LOGSTRING("DProfilerSampleStream::ReleaseIfPending - entry");
+
+	if(iCurrentBuffer != 0 && iPendingRequest != 0 && iClient != 0)
+	    {
+		LOGSTRING("DProfilerSampleStream::ReleaseIfPending - release buffer");
+
+		LOGSTRING2("DProfilerSampleStream::AddSamples - completing request 0x%x",iPendingRequest);
+		Kern::RequestComplete(iClient,iPendingRequest,KErrNone);
+		
+		iPendingRequest = 0;
+		iCurrentBuffer = 0;
+	    }
+
+	LOGSTRING("DProfilerSampleStream::ReleaseIfPending - exit");
+    }
+
+inline void DProfilerSampleStream::AddSamples(DProfilerSampleBuffer& aBuffer, TInt aSamplerId)
+    {
+	LOGSTRING3("DProfilerSampleStream::AddSamples - entry ID: %d, currentbuffer: 0x%x", aSamplerId,iCurrentBuffer);
+	if(iCurrentBuffer != 0)
+	    {
+		// the following will perform simple mutual exclusion
+		iAddingSamples++;
+		if(iAddingSamples > 1) 
+		    {
+			// there is someone else adding samples to the buffer
+			LOGSTRING("DProfilerSampleStream::AddSamples - mutex in use");
+			iAddingSamples--;
+			return;
+		    }
+
+		LOGSTRING("DProfilerSampleStream::AddSamples - reading TBapBuf");
+		
+		// use a copy of the client TBapBuf structure during processing
+		TBapBuf realBuf;
+		TPtr8 ptr((TUint8*)&realBuf,(TInt)sizeof(TBapBuf));
+	
+		Kern::ThreadRawRead(iClient,(TAny*)(iCurrentBuffer),(TAny*)&realBuf,sizeof(TBapBuf));
+
+		ptr.SetLength(sizeof(TBapBuf));
+
+		LOGSTRING4("DProfilerSampleStream::AddSamples - read %d bytes from 0x%x of thread 0x%x",ptr.Size(),iCurrentBuffer,iClient);
+
+		LOGSTRING5("DProfilerSampleStream::AddSamples - current buffer 0x%x -> b:0x%x s:%d d:%d",
+			&realBuf,
+			realBuf.iBuffer,
+			realBuf.iBufferSize,
+			realBuf.iDataSize);
+
+		// get the address of the source buffer data
+		TUint8* src = (TUint8*)&(aBuffer.iDblBufStruct->iDataStart);
+		src += aBuffer.iDblBytesRead;
+
+		// the amount of data to copy is the 4 header bytes +
+		// the remaining data in the buffer
+		TInt amount = aBuffer.iDblBytesWritten-aBuffer.iDblBytesRead;
+
+		TUint8* dst = realBuf.iBuffer;
+
+		LOGSTRING4("DProfilerSampleStream::AddSamples - s:0x%x d:0x%x a:%d",src,dst,amount);
+
+		if(realBuf.iDataSize == 0)
+		    {
+			LOGSTRING("DProfilerSampleStream::AddSamples - case 1");
+
+			// the buffer is empty
+			if(realBuf.iBufferSize >= (amount+4))
+			    {
+				LOGSTRING("DProfilerSampleStream::AddSamples - case 1.1");
+
+				// the source buffer is smaller or of equal size than the amount of output data
+				PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,0,amount);
+				realBuf.iDataSize += amount+4;
+				// the rest of the source buffer was copied at once, so signal the buffer
+				aBuffer.DataCopied();
+			    }
+			else
+			    {
+				LOGSTRING("DProfilerSampleStream::AddSamples - case 1.2");
+
+				// only a part of the source buffer will fit to the client side buffer
+				amount = realBuf.iBufferSize-4;
+				PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,0,amount);
+				realBuf.iDataSize += amount+4;
+				// add the amount of bytes read to the source buffer
+				aBuffer.iDblBytesRead+=amount;
+			    }
+		    }
+		else
+		    {
+			LOGSTRING("DProfilerSampleStream::AddSamples - case 2");
+
+			// there is data in the client buffer
+			dst += realBuf.iDataSize;
+			TInt remainingSpace = realBuf.iBufferSize-realBuf.iDataSize;
+
+			if( remainingSpace >= (amount+4) )
+			    {
+				LOGSTRING("DProfilerSampleStream::AddSamples - case 2.1");
+
+				// the source buffer is smaller or of equal size than the amount of output data
+				PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,realBuf.iDataSize,amount);
+				realBuf.iDataSize += (amount+4);
+				// the rest of the source buffer was copied at once, so signal the buffer
+				aBuffer.DataCopied();
+			    }
+			else
+			    {
+				LOGSTRING("DProfilerSampleStream::AddSamples - case 2.2");
+
+				// only a part of the source buffer will fit to the client side buffer
+				if(remainingSpace >= 12)
+				    {
+					LOGSTRING("DProfilerSampleStream::AddSamples - case 2.3");
+
+					amount = remainingSpace-4;
+					// there are at least 8 bytes left for data, write it
+					PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,realBuf.iDataSize,amount);
+					realBuf.iDataSize += (amount+4);
+					// add the amount of bytes read to the source buffer
+					aBuffer.iDblBytesRead+=amount;				
+				    }
+			    }
+		    }
+	
+		// copy the data in the modified TBapBuf structure back to the client
+		LOGSTRING("DProfilerSampleStream::AddSamples - writing TBapBuf");
+		//iClient->Write(currentBuffer,ptr);
+
+		Kern::ThreadDesWrite(iClient,(TAny*)(realBuf.iDes),ptr,0,KChunkShiftBy0,iClient);
+
+		// if the client side buffer is full or nearly full, signal the client
+		LOGSTRING("DProfilerSampleStream::AddSamples - data copied");
+
+		if(realBuf.iBufferSize-realBuf.iDataSize < 12)
+		    {
+			LOGSTRING("DProfilerSampleStream::AddSamples - release buffer");
+			
+			LOGSTRING2("DProfilerSampleStream::AddSamples - completing request 0x%x",iPendingRequest);
+
+			Kern::RequestComplete(iClient,iPendingRequest,KErrNone);
+
+			iPendingRequest = 0;
+			iCurrentBuffer = 0;
+			//iClient = 0;
+		    }
+
+		// free the lock
+		iAddingSamples--;
+	    }
+	LOGSTRING("DProfilerSampleStream::AddSamples - exit");
+    }
+
+
+
+inline TInt DProfilerSampleStream::EndSampling(DProfilerSampleBuffer& aBuffer,TInt aSamplerId)
+    {
+	LOGSTRING2("DProfilerSampleStream::EndSampling, sampler ID: %d",aSamplerId);
+
+	// switch the buffer to double buffer
+	// even though it would not be full yet
+	// the switch is done only once / end sampling procedure
+	// (Only with BufferOk status)
+	aBuffer.EndSampling();
+	
+	LOGSTRING2("DProfilerSampleStream::EndSampling, iClient: 0x%x",iClient);
+	
+	if(aBuffer.iBufferStatus != DProfilerSampleBuffer::BufferDataEnd)
+	    {
+		// add these final samples to the client buffer
+		AddSamples(aBuffer,aSamplerId);
+		
+		// if all data was copied to the buffer, the buffer status is now BufferOk
+
+		if(aBuffer.iBufferStatus != DProfilerSampleBuffer::BufferOk)
+		    {
+			LOGSTRING("DProfilerSampleStream::EndSampling - more data to copy");
+			// there is still more data to copy, the pending request should have been
+			// completed in AddSamples(), because the client buffer got filled 
+			return 1;
+		    }
+		else
+		    {
+			// buffer status was changed to BufferOk in AddSamples() - 
+			// this means all data from it could be copied
+			// now we have to change the status of the buffer to BufferDataEnd, so
+			// we know that the particular buffer has no more data to copy
+			LOGSTRING("DProfilerSampleStream::EndSampling - switch to BufferDataEnd");
+			aBuffer.iBufferStatus = DProfilerSampleBuffer::BufferDataEnd;
+		    }
+	    }
+
+	// the buffer was completely emptied to the client buffer, or there was no
+	// data to copy to the client side
+	LOGSTRING("DProfilerSampleStream::EndSampling - no more data to copy");
+
+	return 0;
+    }
+
+inline void DProfilerSampleStream::PerformCopy(TUint8 aSamplerId,TUint8* aSrc,TPtr8* aDst,TInt aOffset,TInt aAmount)
+    {
+	LOGSTRING2("DProfilerSampleStream::PerformCopy for sampler ID: %d",aSamplerId);	
+	LOGSTRING5("DProfilerSampleStream::PerformCopy - 0x%x -> 0x%x - %d - offset: %d",aSrc, aDst, aAmount, aOffset);	
+	TUint32 header;
+	header = aAmount & 0x00ffffff;
+	header += (aSamplerId << 24);
+	TPtr8 ptr((TUint8*)&header,4);
+	ptr.SetLength(4);
+
+	LOGSTRING2("DProfilerSampleStream::PerformCopy - start header copy HDR = 0x%x",header);	
+
+	// write the header
+	Kern::ThreadDesWrite(iClient,(TAny*)aDst,ptr,aOffset,KChunkShiftBy0);
+
+	LOGSTRING2("DProfilerSampleStream::PerformCopy - copied header %d bytes",ptr.Size());	
+	aOffset+=4;
+
+	LOGSTRING("DProfilerSampleStream::PerformCopy - start copy");	
+	// write the data
+	ptr.Set(aSrc,aAmount,aAmount);
+	ptr.SetLength(aAmount);
+	
+	Kern::ThreadDesWrite(iClient,(TAny*)aDst,ptr,aOffset,KChunkShiftBy0);
+
+
+	LOGSTRING2("DProfilerSampleStream::PerformCopy - copied data %d bytes",ptr.Size());	
+
+    }