debugsrv/runmodedebug/tsrc/rm_debug/debug_targets/d_rmdebugthread2.cpp
changeset 56 aa2539c91954
--- /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 <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32debug.h>
+#include "d_rmdebugthread2.h"
+
+#include "d_rmdebug_step_test.h"
+#include "d_rmdebug_bkpt_test.h"
+#include "d_demand_paging.h"
+
+TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> 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;
+	}