diff -r d27dfa8884ad -r da2cedce4920 piprofiler/plugins/GeneralsPlugin/src/MemoryEventHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/MemoryEventHandler.cpp Tue May 25 14:22:58 2010 +0300 @@ -0,0 +1,724 @@ +/* +* 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 +#include +#include +#include +#include +#include + +#include "MemoryEventHandler.h" + + +DMemoryEventHandler::DMemoryEventHandler(DProfilerSampleBuffer* aSampleBuffer) + : DKernelEventHandler(EventHandler, this), + iSampleBuffer(aSampleBuffer), + iSampleDescriptor(&(this->iSample[1]),0,256) + { +// Kern::Printf("DMemoryEventHandler::DMemoryEventHandler()"); + iCount = 0; + iPreviousCount = 0; + } + + +TInt DMemoryEventHandler::Create() + { +// Kern::Printf("DMemoryEventHandler::Create()"); + + TInt err(Kern::MutexCreate(iLock, _L("MemoryEventHandlerLock"), KMutexOrdGeneral0)); + if (err != KErrNone) + return err; + + return Add(); + } + + +DMemoryEventHandler::~DMemoryEventHandler() + { +// Kern::Printf("DMemoryEventHandler::~DMemoryEventHandler()"); + + if (iLock) + iLock->Close(NULL); + + } + + +TInt DMemoryEventHandler::Start() + { +// Kern::Printf("DMemoryEventHandler::Start()"); + + iTracking = ETrue; + return KErrNone; + } + + +TInt DMemoryEventHandler::Stop() + { +// Kern::Printf("DMemoryEventHandler::Stop()"); + + iTracking = EFalse; + return KErrNone; + } + +TBool DMemoryEventHandler::SampleNeeded() + { + LOGTEXT("DMemoryEventHandler::SampleNeeded()"); + + // increase the coutner by one on each round + iCount++; + + // check if event handler was not running +// if(!iTracking) +// return false; // return false + + return true; + } + + +TUint DMemoryEventHandler::EventHandler(TKernelEvent aType, TAny* a1, TAny* a2, TAny* aThis) + { + return ((DMemoryEventHandler*)aThis)->HandleEvent(aType, a1, a2); + } + + + +TUint DMemoryEventHandler::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2) + { + // debug +// Kern::Printf("New kernel event received, %d", aType); + + if (iTracking/* && iCount != iPreviousCount*/) + { +// iPreviousCount = iCount; + iCounters[aType]++; + switch (aType) + { + // capture only chunk creation, updates and destroyal + case EEventNewChunk: + { + DChunk* chunk = (DChunk*)a1; + HandleAddChunk(chunk); + break; + } + case EEventUpdateChunk: + HandleUpdateChunk((DChunk*)a1); + break; + case EEventDeleteChunk: + HandleDeleteChunk((DChunk*)a1); + break; +// case EEventAddProcess: +// Kern::Printf("Process added: 0x%08x", (DProcess*)a1); +// break; +// case EEventUpdateProcess: +// Kern::Printf("DProcess updated: 0x%08x", (DProcess*)a1); +// break; +// case EEventRemoveProcess: +// Kern::Printf("DProcess removed: 0x%08x", (DProcess*)a1); +// break; +// case EEventAddCodeSeg: +// Kern::Printf("DCodeSeg added: 0x%08x", (DCodeSeg*)a1); +// break; +// case EEventRemoveCodeSeg: +// Kern::Printf("DCodeSeg deleted: 0x%08x", (DCodeSeg*)a1); +// break; + case EEventAddThread: + HandleAddThread((DThread*)a1); + break; + case EEventUpdateThread: // thread renaming + HandleUpdateThread((DThread*)a1); + break; +// case EEventKillThread: + case EEventRemoveThread: + HandleDeleteThread((DThread*)a1); + break; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + case EEventAddLibrary: + HandleAddLibrary((DLibrary*)a1, (DThread*)a2); + break; + case EEventRemoveLibrary: + HandleDeleteLibrary((DLibrary*)a1); + break; +#endif + + // ignore exception events + case EEventSwExc: + case EEventHwExc: + + default: + break; + } + } +// else if(iTracking && iCount == iPreviousCount) +// { +// // if time stamp is not updated profiling has stopped +// Stop(); +// } + return DKernelEventHandler::ERunNext; + } + +TInt DMemoryEventHandler::EncodeNameCode() + { + iSample[0] = 1; + iSample[1] = 0xaa; + return 2; + } + +// encode mark for new chunk or thread +TInt DMemoryEventHandler::EncodeNewCode() + { + iSample[0] = 1; + iSample[1] = 0xda; + return 2; + } + +// encode mark for update of chunk or thread +TInt DMemoryEventHandler::EncodeUpdateCode() + { + iSample[0] = 1; + iSample[1] = 0xdb; + return 2; + } + +// encode mark for removal of chunk or thread +TInt DMemoryEventHandler::EncodeRemoveCode() + { + iSample[0] = 1; + iSample[1] = 0xdc; + return 2; + } + +// encode the memory sample header in all memory changes +TInt DMemoryEventHandler::AddHeader() + { + TInt err(KErrNone); + + TUint8 number(4); // mem sampler id + + // check if iCount bigger than previous, i.e. at least 1 ms has passed from the previous sample + if(iCount > iPreviousCount) + { + err = this->iSampleBuffer->AddSample(&number,1); + err = this->iSampleBuffer->AddSample((TUint8*)&(iCount),4); + + // add data chunk header + TInt length(EncodeUpdateCode()); + err = iSampleBuffer->AddSample(iSample, length); + + // add total memory sample in the beginning of each sample + length = EncodeTotalMemory(); + err = iSampleBuffer->AddSample(iSample, length); + AddFooter(); // end mark for total memory sample + } + iPreviousCount = iCount; + + // add actual sample + err = this->iSampleBuffer->AddSample(&number,1); + err = this->iSampleBuffer->AddSample((TUint8*)&(iCount),4); + + return err; + } + +// encode the memory sample header in all memory changes +TInt DMemoryEventHandler::AddFooter() + { + TInt err(KErrNone); + + TUint8 number(0); // end mark + err = this->iSampleBuffer->AddSample(&number,1); + + return err; + } + +TInt DMemoryEventHandler::EncodeTotalMemory() + { + + TUint8* size(&iSample[0]); + *size = 0; + + NKern::LockSystem(); + TInt freeRam(Kern::FreeRamInBytes()); + TInt totalRam(Kern::SuperPage().iTotalRamSize); + NKern::UnlockSystem(); + + iSampleDescriptor.Zero(); + + TUint32 id(0xbabbeaaa); + TInt zero(0); + + iSampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32)); + *size += sizeof(TUint); + + iSampleDescriptor.Append((TUint8*)&(totalRam),sizeof(TInt)); + *size += sizeof(TInt); + + // append the cell amount allocated + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size + iSampleDescriptor.Append((TUint8*)&(freeRam),sizeof(TInt)); + *size += sizeof(TInt); + + // append the thread user stack size + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + return ((TInt)(*size))+1; + } + +// handle chunk activity +TBool DMemoryEventHandler::HandleAddChunk(DChunk* aChunk) + { +// Kern::Printf("New DChunk created: 0x%08x, time: %d", aChunk, iCount); + + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // new chunk, add name of it + TInt length(EncodeNameCode()); + iSampleBuffer->AddSample(iSample, length); + + // new chunk, add name of it + length = EncodeChunkName(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add new chunk tag + length = EncodeNewCode(); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleUpdateChunk(DChunk* aChunk) + { +// Kern::Printf("DChunk updated: 0x%08x, time: %d", aChunk, iCount); + + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeUpdateCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteChunk(DChunk* aChunk) + { +// Kern::Printf("DChunk deleted: 0x%08x, time: %d", aChunk, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeRemoveCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +// handle process activity +TBool DMemoryEventHandler::HandleAddProcess(DProcess *aProcess) + { + return ETrue; + } + +TBool DMemoryEventHandler::HandleUpdateProcess(DProcess *aProcess) + { + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteProcess(DProcess *aProcess) + { + return ETrue; + } + +// handle thread activity +TBool DMemoryEventHandler::HandleAddThread(DThread* aThread) + { +// Kern::Printf("DThread added: 0x%08x, time: %d", aThread->iId, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // new thread, add name of it + TInt length(EncodeNameCode()); + iSampleBuffer->AddSample(iSample, length); + + // new chunk, add name of it + length = EncodeChunkName(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add new chunk tag + length = EncodeNewCode(); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleUpdateThread(DThread* aThread) + { +// Kern::Printf("DThread updated: 0x%08x, time: %d", aThread->iId, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeUpdateCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteThread(DThread* aThread) + { +// Kern::Printf("DThread deleted: 0x%08x, time: %d", aThread->iId, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeRemoveCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleAddLibrary(DLibrary* aLibrary, DThread* aThread) + { + LOGTEXT("DMemoryEventHandler::HandleAddLibrary"); + Kern::Printf("DLibrary added: 0x%08x, time: %d", aLibrary, iCount); + // add header first + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // new library, add name of it + TInt length(EncodeNameCode()); + iSampleBuffer->AddSample(iSample, length); + + // new chunk, add name of it + length = EncodeChunkName(*aLibrary); + iSampleBuffer->AddSample(iSample, length); + + // add new chunk tag + length = EncodeNewCode(); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aLibrary, *aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteLibrary(DLibrary* aLibrary) + { + Kern::Printf("DLibrary deleted: 0x%08x, time: %d", aLibrary, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeRemoveCode()); + iSampleBuffer->AddSample(iSample, length); + + DThread* nullPointer = NULL; + length = EncodeChunkData(*aLibrary, *nullPointer); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +// encode chunk name +TInt DMemoryEventHandler::EncodeChunkName(DChunk& c) + { + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + + // encode chunk name + iSampleDescriptor.Zero(); + iSampleDescriptor.Append(_L("C_")); + c.TraceAppendFullName(iSampleDescriptor,false); + *size += iSampleDescriptor.Size(); + + // add chunk object address here + TUint32 chunkAddr((TUint32)&c); + iSampleDescriptor.Append((TUint8*)&(chunkAddr),sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + LOGSTRING2("Non-Heap Chunk Name - %d",*size); + return ((TInt)(*size))+1; + } + +// encode chunk name +TInt DMemoryEventHandler::EncodeChunkName(DThread& t) + { + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + + iSampleDescriptor.Append(_L("T_")); + t.TraceAppendFullName(iSampleDescriptor,false); + *size += iSampleDescriptor.Size(); + + // copy the 4 bytes from the thread id field + iSampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // the size is the descriptor length + the size field + LOGSTRING2("Name - %d",*size); + return ((TInt)(*size))+1; + } + +// encode chunk name +TInt DMemoryEventHandler::EncodeChunkName(DLibrary& l) + { + LOGTEXT("DMemoryEventHandler::EncodeChunkName (LIBRARY)"); + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + + iSampleDescriptor.Append(_L("L_")); + l.TraceAppendFullName(iSampleDescriptor,false); + *size += iSampleDescriptor.Size(); + + // copy the library address here + TUint32 libAddr((TUint32)&l); + iSampleDescriptor.Append((TUint8*) &libAddr,sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + LOGSTRING2("Name - %d",*size); + return ((TInt)(*size))+1; + } + +// record thread stack changes +TInt DMemoryEventHandler::EncodeChunkData(DThread& t) + { + LOGSTRING("DMemoryEventHandler::EncodeChunkDataT - entry"); + + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + + iSampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // copy the total amount of memory allocated for user side stack + iSampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); + *size += sizeof(TInt); + + TInt zero(0); + // append the cell amount allocated (zero, not in use here) + iSampleDescriptor.Append((TUint8*)&zero,sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size (this is not a chunk) + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint)); + *size += sizeof(TUint); + + // append user stack (max) size + iSampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); + *size += sizeof(TInt); + +// Kern::Printf("TData -> %d",*size); + return ((TInt)(*size))+1; + } + +// record chunk changes +TInt DMemoryEventHandler::EncodeChunkData(DChunk& c) + { + LOGSTRING("DMemoryEventHandler::EncodeChunkDataC - entry"); + + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + TInt zero(0); + + TUint32 address((TUint32)&c); + + iSampleDescriptor.Append((TUint8*)&address,sizeof(TUint32)); + *size += sizeof(TUint); + + // copy the total amount of memory allocated + iSampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TInt)); + *size += sizeof(TInt); + + // append the cell amount allocated + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size + iSampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TUint)); + *size += sizeof(TUint); + + // append the thread user stack size + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + +// Kern::Printf("CData - %d",*size); + return ((TInt)(*size))+1; + } + +// record loaded libraries changes +TInt DMemoryEventHandler::EncodeChunkData(DLibrary& l, DThread& t) + { + LOGSTRING("DMemoryEventHandler::EncodeChunkDataL - entry"); + + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + TInt zero(0); + + TUint32 address((TUint32)&l); + + iSampleDescriptor.Append((TUint8*)&address,sizeof(TUint32)); + *size += sizeof(TUint); + + // append amount of memory that library is allocated + iSampleDescriptor.Append((TUint8*)&(l.iCodeSeg->iSize),sizeof(TUint32)); + *size += sizeof(TInt); + + // append count of how many times librarys is allocated + iSampleDescriptor.Append((TUint8*)&(l.iMapCount),sizeof(TInt)); + *size += sizeof(TInt); + + if(&t != NULL) + { + // created by thread + iSampleDescriptor.Append((TUint8*)&(t),sizeof(TUint32)); + } + else + { + // removed + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint32)); + } + *size += sizeof(TUint); + + // append the thread user stack size + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + return ((TInt)(*size))+1; + } +