diff -r a151135b0cf9 -r aa2539c91954 debugsrv/runmodedebug/tsrc/rm_debug/debug_targets/d_rmdebugthread2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debugsrv/runmodedebug/tsrc/rm_debug/debug_targets/d_rmdebugthread2.cpp Fri Oct 08 14:56:39 2010 +0300 @@ -0,0 +1,318 @@ +// Copyright (c) 2006-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: +// Implements a debug thread for testing. +// +// + +#include +#include +#include +#include +#include "d_rmdebugthread2.h" + +#include "d_rmdebug_step_test.h" +#include "d_rmdebug_bkpt_test.h" +#include "d_demand_paging.h" + +TBuf8 gMemoryAccessBytes; +IMPORT_C extern void RMDebug_BranchTst1(); +IMPORT_C extern TInt RMDebugDemandPagingTest(); + +TInt TestData; +TTestFunction FunctionChooser; + +const TInt KNumberOfTraceCalls = 50; + +EXPORT_C TInt TestFunction() + { + // Set TestData to an arbitrary value that can be checked by a tester + TestData = 0xffeeddcc; + RMDebug_BranchTst1(); + + // Code here may not be executed because tests can change the PC value + // at any time, typically once the test passes + return 0; + } + +/** + Wrapper around RMDebugDemandPagingTest, need to pause for a short time to + allow time in t_rmdebug.cpp to issue a User::WaitForRequest to catch the break point + */ +EXPORT_C void TestPagedCode() + { + User::After(100000); + + // call the function in paged code + RMDebugDemandPagingTest(); + } + +EXPORT_C void TestMultipleTraceCalls() + { + //arbitrary function to set a BP on + RMDebug_BranchTst1(); + + // The tester will change FunctionChooser once it gets what it needs out of the test + for(TInt cnt = KNumberOfTraceCalls; cnt>0 && (FunctionChooser==EMultipleTraceCalls); cnt--) + { + RDebug::Printf("T"); + RDebug::Printf("R"); + RDebug::Printf("A"); + RDebug::Printf("C"); + RDebug::Printf("E"); + } + + //another arbitrary function to set a BP on + RMDebug_StepTest_Non_PC_Modifying(); + } + +CDebugServThread::~CDebugServThread() + { + } + +CDebugServThread::CDebugServThread() +// +// Empty constructor +// + { + } + + +/** + * Check that the RProperty argument does not change within the given amount of time. + * If the property does change, the error KErrInUse is returned. + * + */ +EXPORT_C TInt TestRunCountSame( RProperty & aProperty, RTimer & aTimer, TTimeIntervalMicroSeconds32 aTimeOut ) + { + TRequestStatus propertyStatus; + TRequestStatus timerStatus; + TInt propertyValueBefore = 0; + TInt propertyValueAfter = 0; + + aProperty.Subscribe( propertyStatus ); + aProperty.Get( propertyValueBefore ); + aTimer.After( timerStatus, aTimeOut ); + + User::WaitForRequest( propertyStatus, timerStatus ); + if (propertyStatus != KRequestPending) + { + RDebug::Printf(" CDebugServThread::TestRunCountSame: Property has been set. Returning KErrInUse"); + aTimer.Cancel(); + // Wait for the KErrCancel + User::WaitForRequest( timerStatus ); + return KErrInUse; + } + + aProperty.Cancel(); + //This will wait for the KErrCancel to be issued by the property. + User::WaitForRequest( propertyStatus ); + + aProperty.Get( propertyValueAfter ); + if( propertyValueAfter != propertyValueBefore ) + { + RDebug::Printf(" CDebugServThread::TestRunCountSame: Change in property value. Returning KErrInUse"); + return KErrInUse; + } + + return KErrNone; + } + + +/** + * Check that the RProperty argument changes within the given amount of time. + * If the property does not change, the error KErrTimedOut is returned. + * If the values before and after are the same, the error KErrNotReady is returned + */ +EXPORT_C TInt WaitForRunCountChange( RProperty & aProperty, RTimer & aTimer, TTimeIntervalMicroSeconds32 aTimeOut ) + { + TRequestStatus propertyStatus; + TRequestStatus timerStatus; + TInt propertyValueBefore = 0; + TInt propertyValueAfter = 0; + + aProperty.Get( propertyValueBefore ); + aProperty.Subscribe( propertyStatus ); + + aTimer.After( timerStatus, aTimeOut ); + + User::WaitForRequest( propertyStatus, timerStatus ); + if (timerStatus != KRequestPending) + { + RDebug::Printf(" CDebugServThread::WaitForRunCountChange: timeout. Returning KErrTimedOut"); + aProperty.Cancel(); + // Wait for the KErrCancel + User::WaitForRequest( propertyStatus ); + return KErrTimedOut; + } + + aTimer.Cancel(); + //This will wait for the KErrCancel to be issued by the timer. + User::WaitForRequest( timerStatus ); + + aProperty.Get( propertyValueAfter ); + if( propertyValueAfter == propertyValueBefore ) + { + RDebug::Printf(" CDebugServThread::WaitForRunCountChange: No change in property value. Returning KErrNotReady"); + return KErrNotReady; + } + + return KErrNone; + } + +GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*) +// +// Generic thread function for testing +// + { + // set FunctionChooser to run the default function + FunctionChooser = EDefaultFunction; + + CTrapCleanup* cleanup=CTrapCleanup::New(); + if (cleanup == NULL) + { + User::Leave(KErrNoMemory); + } + + TInt err = RProperty::Define( RProcess().SecureId(), ERMDBGRunCountProperty, RProperty::EInt ); + if( (err != KErrAlreadyExists) && (err != KErrNone) ) + { + RDebug::Printf("CDebugServThread::ThreadFunction - unable to create 'ERunCount' property. err:%d", err); + } + + RThread::Rendezvous(KErrNone); + + TestData = 1; + + /* Beware of adding printf or other debug-generating events in this loop because + * they interfere with the tests + */ + while(TestData != 0xFFFFFFFF) + { + //iRunCountPublish.Set( TestData ); + RProperty::Set( RProcess().SecureId(), ERMDBGRunCountProperty, TestData ); + + switch(FunctionChooser) + { + case EDemandPagingFunction: + TestPagedCode(); + break; + case EDefaultFunction: + // the default function is the stepping test functions + case EStepFunction: + { + RMDebug_BranchTst1(); + + // Single stepping test support code + + // ARM tests + RMDebug_StepTest_Non_PC_Modifying(); + + RMDebug_StepTest_Branch(); + + RMDebug_StepTest_Branch_And_Link(); + + RMDebug_StepTest_MOV_PC(); + + RMDebug_StepTest_LDR_PC(); + +// thumb/interworking tests not supported on armv4 +#ifdef __MARM_ARMV5__ + + // Thumb tests + RMDebug_StepTest_Thumb_Non_PC_Modifying(); + + RMDebug_StepTest_Thumb_Branch(); + + RMDebug_StepTest_Thumb_Branch_And_Link(); + + RMDebug_StepTest_Thumb_Back_Branch_And_Link(); + + // ARM <-> Thumb interworking tests + RMDebug_StepTest_Interwork(); + + RMDebug_StepTest_Thumb_AddPC(); + +#endif // __MARM_ARMV5__ + + // Single-stepping performance + RMDebug_StepTest_Count(); + + // multiple step test + RMDebug_StepTest_ARM_Step_Multiple(); + + // Breakpoints in loop test + RMDebug_Bkpt_Test_Entry(); + + TestData++; + + RDebug::Printf("** TestData=%d", TestData) ; + + // Wait 50mSecs. // (suspends this thread) + User::After(50000); + + break; + } + case EMultipleTraceCalls: + TestMultipleTraceCalls(); + break; + default: + //do nothing + break; + } + } + + RProperty::Delete( RProcess().SecureId(), ERMDBGRunCountProperty ); + + delete cleanup; + + return (KErrNone); + } + +EXPORT_C TInt StartDebugThread(RThread& aDebugThread, const TDesC& aDebugThreadName) +// +// Starts a test thread +// +{ + TInt res=KErrNone; + + // Create the thread + res = aDebugThread.Create( aDebugThreadName, + CDebugServThread::ThreadFunction, + KDefaultStackSize, + KDebugThreadDefaultHeapSize, + KDebugThreadDefaultHeapSize, + NULL + ); + + // Check that the creation worked + if (res == KErrNone) + { + TRequestStatus rendezvousStatus; + + aDebugThread.SetPriority(EPriorityNormal); + // Make a request for a rendezvous + aDebugThread.Rendezvous(rendezvousStatus); + // Set the thread as ready for execution + aDebugThread.Resume(); + // Wait for the resumption + User::WaitForRequest(rendezvousStatus); + } + else + { + // Close the handle. + aDebugThread.Close(); + } + + return res; + }