void DPriSamplerImpl::Reset() { /* * * EKA-2 implementation of PRI trace * */ LOGTEXT("PriSamplerImpl::Reset"); iCountti = 50; // sample threads 16 cycles before actual MEM and PRI sample time... this->iThreadCount = 0; this->iNewThreadCount = 0; this->iProcessing = ENothingToProcess; this->sampleDescriptor.Zero(); // clear all thread tags NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex DObjectCon* threads = Kern::Containers()[EThread]; threads->Wait(); // Obtain the container mutex so the list does get changed under us TInt totalThreadCount = threads->Count(); for(TInt i=0;i<totalThreadCount;i++) { DThread* t = (DThread*)(*threads)[i]; TAG(t) = (TAG(t) & 0xfffffffd); } threads->Signal(); NKern::ThreadLeaveCS(); // End of critical section }
/** * Stop Mode routine to retrieve the process list and place it in the response buffer * @param aItem List item describing the list * @return One of the system wide error codes */ TInt StopModeDebug::GetProcessList(const TListItem* aItem, bool aCheckConsistent) { Kern::Printf("\nDumping the process list"); if(aItem->iListScope != EScopeGlobal) { return KErrArgument; //No other scope makes sense for process list } //Check that the process obj con lock is ok if required DObjectCon* objCon = Kern::Containers()[EProcess]; if(aCheckConsistent && objCon->Lock()->iHoldCount) { return KErrNotReady; } //Look at the buffer TUint8* buffer = (TUint8*)aItem->iBufferAddress; TUint8* bufferPos = Align4(buffer + sizeof(TListReturn)); TUint8* bufferEnd = buffer + aItem->iBufferSize; TListReturn* listResp = (TListReturn*)buffer; listResp->iReqNo = EProcess; listResp->iNumberItems = 0; listResp->iDataSize = 0; DProcess** firstProcess = (DProcess**)objCon->iObjects; TInt numProcesses = objCon->Count(); for(TInt cnt = 0; cnt < numProcesses; cnt++) { //Get process and see if we want to list it DProcess* proc = firstProcess[cnt]; if(proc && (proc->iId >= aItem->iStartElement) ) { TUint32 sizeOfProc = 0; TInt err = AppendProcessToBuffer(proc, bufferPos, bufferEnd, sizeOfProc); if(KErrNone != err) { return err; } ++(listResp->iNumberItems); listResp->iDataSize += sizeOfProc; bufferPos += sizeOfProc; } } return KErrNone; }
// ----------------------------------------------------------------------------- // DIscDevice::InitializeLdd2LddInterface // Function to connect to DataTransmission and Multiplexer ldds // ( other items were commented in a header ). // ----------------------------------------------------------------------------- // TInt DIscDevice::InitializeLdd2LddInterface() { C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface()" ) ) ); // Find pointer to second level LDD. DObjectCon* lDevices = Kern::Containers()[ ELogicalDevice ]; TKName driverName; ASSERT_RESET_ALWAYS( lDevices, "IscDriver", EIscLogicalDevicesNotFound ); TInt err( KErrNone ); //TInt driverHandle( KErrNone ); // API change in SOS9.2 WK08 TFindHandle driverHandle; // Find pointer to ISC Multiplexer. err = lDevices->FindByName( driverHandle, KIscMultiplexerName, driverName ); if( KErrNone != err ) { C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface() ISC Multiplexer Not Found!" ) ) ); ASSERT_RESET_ALWAYS( 0, "IscDriver" ,EIscMultiplexerNotFound ); } iIscMultiplexerInterface = static_cast<DIscMultiplexerBase*>( lDevices->At( driverHandle ) ); ASSERT_RESET_ALWAYS( iIscMultiplexerInterface, "IscDriver", EIscMultiplexerNotFound ); //TInt secondDriverHandle( KErrNone ); // API change in SOS9.2 WK08 TFindHandle secondDriverHandle; // Find pointer to Data Transmission Plugin. err = lDevices->FindByName( secondDriverHandle, KIscDataTransmissionDriverName, driverName ); if( KErrNone != err ) { C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface() Data Transmission Plug-In Not Found!" ) ) ); ASSERT_RESET_ALWAYS( 0, "IscDriver", EIscDataTransmissionDriverNotFound ); } iIscDataTransmissionInterface = static_cast<DIscDataTransmissionBase*>( lDevices->At( secondDriverHandle ) ); ASSERT_RESET_ALWAYS( iIscDataTransmissionInterface, "IscDriver", EIscDataTransmissionDriverNotFound ); iIscDataTransmissionInterface->Connect( this ); iIscMultiplexerInterface->Connect( this ); C_TRACE( ( _T( "DIscDevice::InitializeLdd2LddInterface - return 0x%x" ), err ) ); return err; }
TInt DKdaChannel::OpenTempObject(TUint aId, TObjectType aType) { __ASSERT_DEBUG(aType == EProcess || aType == EThread, Kern::Fault(KFault, __LINE__)); __ASSERT_DEBUG(! iTempObj, Kern::Fault(KFault, __LINE__)); DObjectCon* pC = Kern::Containers()[aType]; NKern::ThreadEnterCS(); pC->Wait(); DObject* tempObj = (aType == EProcess) ? (DObject*)Kern::ProcessFromId(aId) : (DObject*)Kern::ThreadFromId(aId); NKern::LockSystem(); iTempObj = tempObj; TInt r = KErrNotFound; if (iTempObj) r = iTempObj->Open(); NKern::UnlockSystem(); pC->Signal(); NKern::ThreadLeaveCS(); return r; }
TInt DPriSamplerImpl::SampleImpl() { /* * * EKA-2 implementation of PRI trace * */ if(this->iProcessing == ENothingToProcess) { if((iCountti % iPriSamplingPeriod) != 0 ) return 0; LOGTEXT("Processing threads..."); DObjectCon* threads = Kern::Containers()[EThread]; NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex threads->Wait(); // PRI trace variables this->iThreadCount = 0; this->iNewThreadCount = 0; TInt totalThreadCount = threads->Count(); for(TInt i=0;i<totalThreadCount;i++) { //DThread* t = (DThread*)(threads)[i]; DObject* pO=(*threads)[i]; DThread* t = (DThread*)pO; LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t)); if( (TAG(t) & PROFILER_THREAD_MARK) == 0) { LOGSTRING2("Marking thread %d",i); // this thread's chunk has not been reported yet this->threadNamesToReport[iNewThreadCount] = t; iNewThreadCount++; // tag the thread TAG(t) |= PROFILER_THREAD_MARK; LOGSTRING2("New Thread %d",i); } else { LOGSTRING3("Thread %d marked already - 0x%x",i,TAG(t)); } // the thread has been tagged, add heap chunks to the list this->threadsToSample[this->iThreadCount] = t; this->iThreadCount++; LOGSTRING2("Added thread %d to threads to sample",i); } threads->Signal(); NKern::ThreadLeaveCS(); // End of critical section if(this->iThreadCount > 0 || this->iNewThreadCount > 0) { this->iProcessing = EStartingToProcess; // process the first sample TInt length = this->ProcessChunks(); if(length == 0) { this->iProcessing = ENothingToProcess; } return length; } else { // there were no threads, should not take place LOGTEXT("PriSamplerImpl::SampleImpl - Error, no threads"); return 0; } } else { TInt length = this->ProcessChunks(); if(length == 0) { this->iProcessing = ENothingToProcess; } return length; } }
/** * Generic method that looks at all kernel objects of aObjectType * @param aObjectType * @param aDumpScope - if you wish to dump for the the current process, current thread or entire system * @param aDataToDump - data you wish to dump * @param aSizeDumped - records how much was dumped * @return */ TInt SCMonitor::LogObjectContainers(TObjectType aObjectType, SCMDataSave::TDumpScope aDumpScope, const SCMDataSave::TDataToDump& aDataToDump, TUint& aSizeDumped) const { aSizeDumped = 0; if(aObjectType >= ENumObjectTypes) { return KErrArgument; } //Get the object container for the given object type DObjectCon* objectContainer = Kern::Containers()[aObjectType]; if(objectContainer == NULL) { CLTRACE("tFailed to get object container"); return KErrNotFound; } //Must check the mutex on this is ok otherwise the data will be in an inconsistent state if(objectContainer->iMutex->iHoldCount) { CLTRACE("\tObject Container is in an inconsistant state"); return KErrCorrupt; } TInt numObjects = objectContainer->Count(); TInt err = KErrNone; for(TInt cnt = 0; cnt< numObjects; cnt ++) { DObject* object = (*objectContainer)[cnt]; //Are we interested in the object? scope only relevant for thread and process objects, for others, the scope is implicit if(aObjectType == EThread) { switch(aDumpScope) { case SCMDataSave::EThreadSpecific : { //if we are interested in the current thread and this is not it, continue if(((DThread*)object) != &Kern::CurrentThread()) continue; break; } case SCMDataSave::EProcessSpecific : { //if we are interested in the current proc and this is not it, continue if(((DThread*)object)->iOwningProcess != &Kern::CurrentProcess()) continue; break; } case SCMDataSave::ESystemWide : default: break; } } else if(aObjectType == EProcess) { switch(aDumpScope) { case SCMDataSave::EProcessSpecific : { if((DProcess*)object != &Kern::CurrentProcess()) continue; break; } case SCMDataSave::EThreadSpecific : //thread specific process doesnt make sense return KErrArgument; case SCMDataSave::ESystemWide : default: break; } } //Now we look at the data we have been asked to dump if(aDataToDump.iMetaData) { TUint dumped = 0; err = HelpDumpMetaData(object, aObjectType, dumped); if(KErrNone != err) { CLTRACE1("Failed to meta data: [%d]", err); return err; } aSizeDumped += dumped; } if(aDataToDump.iCodeSegs) { if(aObjectType != EProcess) { return KErrArgument; } TUint dumped = 0; err = iDataSave->LogCodeSegments((DProcess*)object, dumped); if(KErrNone != err) { CLTRACE1("Failed to log code segments: [%d]", err); return err; } aSizeDumped += dumped; } if(aDataToDump.iStk != SCMDataSave::EStackTypeNone) { TUint dumped = 0; err = HelpDumpStacks(object, aObjectType, dumped, aDataToDump.iStk); if(KErrNone != err) { CLTRACE1("Failed to log stacks: [%d]", err); return err; } aSizeDumped += dumped; } if(aDataToDump.iReg != SCMDataSave::ERegSetNone) { if(aObjectType != EThread) { return KErrArgument; } TUint dumped = 0; err = iDataSave->LogRegisters((DThread*)object, aDataToDump.iReg, dumped); if(KErrNone != err && KErrNotSupported !=err) //we expect to send down a KErrNotSupported when we ask for Full CPU set for the non crashed thread - thats fine { CLTRACE1("Failed to log registers: [%d]", err); return err; } aSizeDumped += dumped; } } return KErrNone; }
void DMemSamplerImpl::Reset() { Kern::Printf("MemSamplerImpl::Reset"); iCount = 0; // sample threads 1 cycle after actual MEM sample time... this->iTimeToSample = false; this->iChunkCount = 0; this->iNewChunkCount = 0; this->iTotalMemoryOk = false; this->iTotalMemoryNameOk = false; this->iChunksProcessing = ENothingToProcess; this->iThreadsProcessing = ENothingToProcess; #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS this->iLibrariesProcessing = ENothingToProcess; this->iSampleType = ESampleThreads; #else this->iSampleThreads = true; #endif this->sampleDescriptor.Zero(); // clear all chunk tags NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex DObjectCon* chunks = Kern::Containers()[EChunk]; chunks->Wait(); // Obtain the container mutex so the list does get changed under us TInt totalChunkCount = chunks->Count(); for(TInt i=0;i<totalChunkCount;i++) { DChunk* c = (DChunk*)(*chunks)[i]; TAG(c) = 0; } chunks->Signal(); // Release the container mutex Kern::Printf("MemSamplerImpl::Reset"); this->iThreadCount = 0; this->iNewThreadCount = 0; this->sampleDescriptor.Zero(); // clear all chunk tags DObjectCon* threads = Kern::Containers()[EThread]; threads->Wait(); // Obtain the container mutex so the list does get changed under us TInt totalThreadCount = threads->Count(); for(TInt i=0;i<totalThreadCount;i++) { DThread* t = (DThread*)(*threads)[i]; TAG(t) = (TAG(t) & 0xfffffffe); } threads->Signal(); // Release the container mutex #ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS this->iLibraryCount = 0; this->iNewLibraryCount = 0; this->sampleDescriptor.Zero(); // clear all library tags DObjectCon* libs = Kern::Containers()[ELibrary]; libs->Wait(); // Obtain the container mutex so the list does get changed under us TInt totalLibraryCount = libs->Count(); for(TInt i=0; i<totalLibraryCount; i++) { DLibrary* l = (DLibrary*)(*libs)[i]; TAG(l) = (TAG(l) & 0xefffffff); } libs->Signal(); // Release the container mutex #endif NKern::ThreadLeaveCS(); // End of critical section }
TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams ) { TMemSpyDriverInternalChunkInfoParams params; TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); if ( r != KErrNone ) { TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r)); return r; } TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle)); DObjectCon* container = Kern::Containers()[EChunk]; NKern::ThreadEnterCS(); container->Wait(); const TInt count = container->Count(); DChunk* foundChunk = NULL; for(TInt i=0; i<count; i++) { DChunk* chunk = (DChunk*) (*container)[i]; if ( chunk == params.iHandle ) { foundChunk = chunk; TRACE( PrintChunkInfo( *chunk ) ); r = foundChunk->Open(); break; } } container->Signal(); if ( foundChunk == NULL ) { Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk"); NKern::ThreadLeaveCS(); return KErrNotFound; } if (r) { Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - %d - Failed to open chunk", r); NKern::ThreadLeaveCS(); return r; } // Prepare return data DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); // params.iBaseAddress = chunkAdaption.GetBase( *foundChunk ); params.iSize = chunkAdaption.GetSize( *foundChunk ); params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk ); foundChunk->FullName( params.iName ); // Mirror the process memory tracker DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk ); if ( owner ) { params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); } else { owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) ); if ( owner ) { params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); } else { params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk ); } } // Get type & attribs params.iType = IdentifyChunkType( *foundChunk ); params.iAttributes = chunkAdaption.GetAttributes( *foundChunk ); // Finished with foundChunk foundChunk->Close(NULL); NKern::ThreadLeaveCS(); // Write back to client r = Kern::ThreadRawWrite( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); if ( r == KErrBadDescriptor ) { MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); } TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r )); return r; }
TInt DMemSpyDriverLogChanChunks::GetChunkHandles( TMemSpyDriverInternalChunkHandleParams* aParams ) { TMemSpyDriverInternalChunkHandleParams params; TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkHandleParams) ); if ( r != KErrNone ) { TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - params read error: %d", r)); return r; } const TInt maxCount = params.iMaxCount; TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - START - id: %d, maxCount: %d, type: %d", params.iId, maxCount, params.iType)); DMemSpyDriverOSAdaptionDThread& threadAdaption = OSAdaption().DThread(); DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); // This variable holds the number of handles that we have already // written to the client-side. TInt currentWriteIndex = 0; if ( params.iType == EMemSpyDriverPrivateObjectTypeProcess || params.iType == EMemSpyDriverPrivateObjectTypeThread ) { if ( params.iType == EMemSpyDriverPrivateObjectTypeThread ) { r = OpenTempObject( params.iId, EThread ); if ( r == KErrNone ) { // Open the owning process instead, so that we can see which chunks are mapped // into the thread. DThread* thread = (DThread*) TempObject(); DProcess* process = threadAdaption.GetOwningProcess( *thread ); if ( process ) { const TUint parentProcessId = processAdaption.GetId( *process ); CloseTempObject(); r = OpenTempObject( parentProcessId, EProcess ); } else { CloseTempObject(); r = KErrNotFound; } } } else { r = OpenTempObject( params.iId, EProcess ); } // Handle error opening correct process if (r != KErrNone) { Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - parent process not found"); return r; } DProcess* process = (DProcess*) TempObject(); NKern::ThreadEnterCS(); // Iterate through each handle in the process MemSpyObjectIx* processHandles = processAdaption.GetHandles( *process ); MemSpyObjectIx_HandleLookupLock(); const TInt processHandleCount = processHandles->Count(); MemSpyObjectIx_HandleLookupUnlock(); for( TInt processHandleIndex = 0; processHandleIndex<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ ) { // Get a handle from the process container... MemSpyObjectIx_HandleLookupLock(); if (processHandleIndex >= processHandles->Count()) break; // Count may have changed in the meantime DObject* object = (*processHandles)[ processHandleIndex ]; if (object && object->Open() != KErrNone) object = NULL; MemSpyObjectIx_HandleLookupUnlock(); if ( object ) { const TObjectType objectType = processAdaption.GetObjectType( *object ); if ( objectType == EChunk ) { DChunk* chunk = (DChunk*) object; TAny* handle = (TAny*) chunk; r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) ); if ( r == KErrNone ) { ++currentWriteIndex; } } object->Close(NULL); } } // If we were asked for process-related chunks, also check the chunk container // for entries which we don't have handles to, but do refer to our process // Need a listing of all chunks in the system. Let client filter duplicates. DObjectCon* container = Kern::Containers()[ EChunk ]; container->Wait(); // const TInt count = container->Count(); for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ ) { DChunk* chunk= (DChunk*) (*container)[ i ]; // const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() ); if ( isRelated ) { r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) ); if ( r == KErrNone ) { ++currentWriteIndex; } } } // container->Signal(); NKern::ThreadLeaveCS(); CloseTempObject(); } else { // Need a listing of all chunks in the system. Let client filter duplicates. DObjectCon* container = Kern::Containers()[ EChunk ]; NKern::ThreadEnterCS(); container->Wait(); // const TInt count = container->Count(); for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ ) { DChunk* chunk= (DChunk*) (*container)[ i ]; // r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) ); if (r == KErrNone) { ++currentWriteIndex; } } // container->Signal(); NKern::ThreadLeaveCS(); } if ( r == KErrBadDescriptor ) { MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); } else { const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, ¤tWriteIndex, sizeof(TInt) ); if ( r == KErrNone ) { r = finalWrite; } } TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r)); return r; }