--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_app.cpp Thu Sep 02 22:05:40 2010 +0300
@@ -0,0 +1,415 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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 <e32base.h>
+#include <e32base_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <e32debug.h>
+#include <e32property.h>
+#include <u32hal.h>
+#include <hal.h>
+#include <f32file.h>
+#include <e32svr.h>
+#include <e32const.h>
+
+
+#include "t_rmdebug_app.h"
+
+IMPORT_C extern void RMDebug_BranchTst2();
+
+LOCAL_C void ParseCommandLineL(TInt32& aFunctionType, TUint& aDelay, TUint& aExtraThreads, TInt32& aCpuNumber, TInt32& aThreadPriority)
+ {
+
+ // get the length of the command line arguments
+ TInt argc = User::CommandLineLength();
+ RDebug::Printf(" t_rmdebug_app: ParseCommandLineL argc=%d", argc);
+
+ // allocate a buffer for the command line arguments and extract the data to it
+ HBufC* commandLine = HBufC::NewLC(argc);
+ TPtr commandLineBuffer = commandLine->Des();
+ User::CommandLine(commandLineBuffer);
+
+ // create a lexer and read through the command line
+ TLex lex(*commandLine);
+ while (!lex.Eos())
+ {
+ // expecting the first character to be a '-'
+ if (lex.Get() == '-')
+ {
+ TChar arg = lex.Get();
+ switch (arg)
+ {
+ case 'f':
+ // the digits following '-f' give the function type
+ User::LeaveIfError(lex.Val(aFunctionType));
+ RDebug::Printf(" t_rmdebug_app: setting aFunctionType=%d", aFunctionType);
+ break;
+ case 'd':
+ // the digits following '-d' give the delay
+ User::LeaveIfError(lex.Val(aDelay));
+ RDebug::Printf(" t_rmdebug_app: setting aDelay=%d", aDelay);
+ break;
+ case 'e':
+ // the digits following '-e' give the number of extra threads to launch
+ User::LeaveIfError(lex.Val(aExtraThreads));
+ RDebug::Printf(" t_rmdebug_app: setting aExtraThreads=%d", aExtraThreads);
+ break;
+
+ case 'p':
+ // the digits following '-p' gives the value to set for the main thread priority
+ User::LeaveIfError(lex.Val(aThreadPriority));
+ RDebug::Printf(" t_rmdebug_app: aThreadPriority =%d", aThreadPriority);
+ break;
+
+ case 'a':
+ // the digits following '-a' gives the cpu on which this thread will execute on
+ User::LeaveIfError(lex.Val(aCpuNumber));
+ RDebug::Printf(" t_rmdebug_app: CPU Number =%d", aCpuNumber );
+ break;
+
+ default:
+ // unknown argument so leave
+ User::Leave(KErrArgument);
+ }
+ lex.SkipSpace();
+ }
+ else
+ {
+ // unknown argument so leave
+ User::Leave(KErrArgument);
+ }
+ }
+
+ // do clean up
+ CleanupStack::PopAndDestroy(commandLine);
+ }
+
+typedef void (*TPfun)();
+
+// test function to call corresponding to EPrefetchAbortFunction
+void PrefetchAbort()
+ {
+ TPfun f = NULL;
+ f();
+ }
+
+// test function to call corresponding to EUserPanicFunction
+void UserPanic()
+ {
+ User::Panic(KUserPanic, KUserPanicCode);
+ }
+
+// calls self repeatedly until stack is used up. Slightly convoluted to prevent UREL optimising this out...
+TUint32 StackOverFlowFunction(TUint32 aInt=0)
+ {
+ TUint32 unusedArray[150];
+ for(TInt i=0; i<150; i++)
+ {
+ unusedArray[i] = StackOverFlowFunction(i);
+ }
+ return unusedArray[0];
+ }
+
+void DataAbort()
+ {
+ TInt* r = (TInt*) 0x1000;
+ *r = 0x42;
+ }
+
+void UndefInstruction()
+ {
+ TUint32 undef = 0xE6000010;
+ TPfun f = (TPfun) &undef;
+ f();
+ }
+
+TInt DataRead()
+ {
+ TInt* r = (TInt*) 0x1000;
+ TInt rr = (TInt)*r;
+ //include the following line to ensure that rr doesn't get optimised out
+ RDebug::Printf("Shouldn't see this being printed out: %d", rr);
+
+ // Stop compilation warning. Should not get here anyway.
+ rr++;
+ return rr;
+ }
+
+void DataWrite()
+ {
+ TInt* r = (TInt*) 0x1000;
+ *r = 0x42;
+ }
+
+void UserException()
+ {
+ User::RaiseException(EExcGeneral);
+ }
+
+void SpinForeverWithBreakPoint()
+ {
+
+ // finding the process t_rmdebug2/t_rmdebug2_oem/t_rmdebug2_oem2
+ // we find the process.SID to attach to the property
+ _LIT(KThreadWildCard, "t_rmdebug2*");
+
+ TInt err = KErrNone;
+ TUid propertySid = KNullUid;
+ TFindThread find(KThreadWildCard);
+ TFullName name;
+ TBool found = EFalse;
+ while(find.Next(name)==KErrNone && !found)
+ {
+ RThread thread;
+ err = thread.Open(find);
+ if (err == KErrNone)
+ {
+ RProcess process;
+ thread.Process(process);
+ TFullName fullname = thread.FullName();
+ //RDebug::Printf("SID Search Match Found Name %lS Process ID%ld Thread Id %ld", &fullname, process.Id().Id(), thread.Id().Id());
+ found = ETrue;
+ //SID saved so that the property can be attached to
+ propertySid = process.SecureId();
+ process.Close();
+ }
+ thread.Close();
+ }
+
+ // publish the address of the RMDebug_BranchTst2 with the correct SID value
+ TInt address = (TInt)&RMDebug_BranchTst2;
+ err = RProperty::Set(propertySid, EMyPropertyInteger, address);
+ if(KErrNone != err)
+ RDebug::Printf("Error Set of the property %d", err);
+
+ //open semaphore to signal the fact we have reached the point where we have to set the property
+ RSemaphore globsem;
+ globsem.OpenGlobal(_L("RMDebugGlobSem"));
+ globsem.Signal();
+ globsem.Close();
+
+ RProcess thisProcess;
+ TFileName thisProcessName = thisProcess.FileName();
+ RDebug::Print(_L("App Process Name %S process id %ld thread id %ld"), &thisProcessName, thisProcess.Id().Id(), RThread().Id().Id());
+
+ TInt i=0;
+ RThread::Rendezvous(KErrNone);
+ while(i<0xffffffff)
+ {
+ RMDebug_BranchTst2();
+ User::After(10000);
+ }
+ }
+
+void SpinForever()
+ {
+ TInt i=0;
+ RThread::Rendezvous(KErrNone);
+ while(i<0xffffffff)
+ {
+ User::After(10000);
+ }
+ }
+
+void NormalExit()
+ {
+ RDebug::Printf("Target app: NormalExit() function. Returning to MainL" );
+ }
+
+void LaunchThreads(TUint aNumber)
+ {
+ _LIT(KDebugThreadName, "DebugThread");
+ const TUint KDebugThreadDefaultHeapSize=0x10000;
+ for(TInt i=0; i<aNumber; i++)
+ {
+ RThread thread;
+ RBuf threadName;
+ threadName.Create(KDebugThreadName().Length()+10); // the 10 is for appending i to the end of the name
+ threadName.Append(KDebugThreadName());
+ threadName.AppendNum(i);
+ TInt err = thread.Create(threadName, (TThreadFunction)SpinForever, KDefaultStackSize, KDebugThreadDefaultHeapSize, KDebugThreadDefaultHeapSize, NULL);
+ if(err != KErrNone)
+ {
+ RDebug::Printf("Couldn't create thread %d", err);
+ threadName.Close();
+ thread.Close();
+ break;
+ }
+ thread.SetPriority(EPriorityNormal);
+ TRequestStatus status;
+ thread.Rendezvous(status);
+ thread.Resume();
+ User::WaitForRequest(status);
+ thread.Close();
+ threadName.Close();
+ }
+ }
+
+void WaitFiveSecondsThenExit(void)
+ {
+ // wait for 5 seconds
+ User::After(5000000);
+ }
+
+TInt NumberOfCpus()
+ {
+ TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
+ return r;
+ }
+
+TInt SetCpuAffinity(TInt aCpuNumber)
+ {
+ TInt TestCpuCount = NumberOfCpus();
+ RDebug::Printf("SetCpuAffinity --> TestCpuCount = %d\n", TestCpuCount);
+ TUint32 cpu = 0;
+
+ if ((aCpuNumber % TestCpuCount) != 0)
+ cpu = (TUint32)(aCpuNumber % TestCpuCount);
+
+ RDebug::Printf("SetCpuAffinity --> Setting cpu %3d\n", cpu);
+ TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
+ return r;
+ }
+
+void SetCurrentThreadPriority(TInt aThreadPriority)
+ {
+ RDebug::Printf("SetCurrentThreadPriority aThreadPriority =%d\n", aThreadPriority);
+ RThread().SetPriority((TThreadPriority) aThreadPriority);
+ RDebug::Printf("SetCurrentThreadPriority Crashapp RThread Priority() = %d", (TInt) RThread().Priority()) ;
+ }
+
+TInt GetTimeInMs()
+{
+ TInt period = 0;
+ User::LeaveIfError(HAL::Get(HALData::ENanoTickPeriod, period));
+ TInt periodInMs = period / 1000;
+ return User::NTickCount() * periodInMs;
+}
+
+void SetNanoTickTime()
+ {
+ TUid t_performance_test_Sid;
+ t_performance_test_Sid.iUid = 0x102831E5;
+ RProperty::Set(t_performance_test_Sid, EPropertyTimeOfCrash, GetTimeInMs());
+ }
+
+// call the function corresponding to aFunctionType
+LOCAL_C void CallFunction(TDebugFunctionType aFunctionType, TUint aDelay, TUint aExtraThreads, TInt32 aCpuNumber, TUint aThreadPriority )
+ {
+
+ // pause for aDelay microseconds
+ User::After(aDelay);
+
+ // set cpu on which this thread should execute on
+ if ( aCpuNumber )
+ SetCpuAffinity(aCpuNumber);
+
+ if ( aThreadPriority )
+ SetCurrentThreadPriority(aThreadPriority);
+
+ // launch the extra threads
+ LaunchThreads(aExtraThreads);
+
+ // Publish Nano tick count time for RMDBG performance testing
+ SetNanoTickTime();
+
+ // call appropriate function
+ switch( aFunctionType )
+ {
+ case EPrefetchAbortFunction:
+ PrefetchAbort();
+ break;
+ case EUserPanicFunction:
+ UserPanic();
+ break;
+ case EStackOverflowFunction:
+ StackOverFlowFunction();
+ break;
+ case EDataAbortFunction:
+ DataAbort();
+ break;
+ case EUndefInstructionFunction:
+ UndefInstruction();
+ break;
+ case EDataReadErrorFunction:
+ DataRead();
+ break;
+ case EDataWriteErrorFunction:
+ DataWrite();
+ break;
+ case EUserExceptionFunction:
+ UserException();
+ break;
+ case EWaitFiveSecondsThenExit:
+ WaitFiveSecondsThenExit();
+ break;
+ case ESpinForever:
+ SpinForever();
+ break;
+ case ESpinForeverWithBreakPoint:
+ SpinForeverWithBreakPoint();
+ break;
+ case ENormalExit:
+ NormalExit();
+ break;
+ case EDefaultDebugFunction:
+ default:
+ break;
+ }
+ }
+
+void PrintHelp()
+ {
+ RDebug::Printf("Invoke with arguments:\n");
+ RDebug::Printf("\t-d<delay>\n\t: delay in microseconds before calling target function\n");
+ RDebug::Printf("\t-f<function-number>\n\t: enumerator from TDebugFunctionType representing function to call\n");
+ RDebug::Printf("\t-e<number>\n\t: number of extra threads to launch, these threads run endlessly\n");
+ }
+
+TInt E32Main()
+ {
+
+ RDebug::Printf("<<<<< E32Main() RThread Priority() = %d, RProcess Priority() = %d", (TInt) RThread().Priority(), (TInt) RProcess().Priority()) ;
+ RDebug::Printf("t_rmdebug_app tid=%d,pid=%d", I64LOW(RThread().Id().Id()), I64LOW(RProcess().Id().Id()) ) ;
+ // setup heap checking and clean up trap
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ RThread().SetPriority(EPriorityNormal);
+ RProcess::Rendezvous(KErrNone);
+
+ // read arguments from command line
+ TUint delay = 0;
+ TInt32 functionTypeAsTInt32 = (TInt32)EDefaultDebugFunction;
+ TUint extraThreads = 0;
+ TInt32 aCpuNumber = 0;
+ TInt32 aThreadPriority = 0;
+
+ TRAPD(err, ParseCommandLineL(functionTypeAsTInt32, delay, extraThreads, aCpuNumber, aThreadPriority));
+
+ RDebug::Printf("E32Main :: aThreadPriority=%d", aThreadPriority ) ;
+
+ if(KErrNone == err)
+ {
+ // if the command line arguments were successfully read then call the appropriate function
+ CallFunction((TDebugFunctionType)functionTypeAsTInt32, delay, extraThreads, aCpuNumber, aThreadPriority);
+ }
+
+ // perform clean up and return any error which was recorded
+ delete cleanup;
+ __UHEAP_MARKEND;
+ return err;
+ }
+