sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\debug\t_schedhook.cpp sl@0: // Overview: sl@0: // Test the device hook functionality. sl@0: // API Information: sl@0: // RBusLogicalChannel, DLogicalDevice sl@0: // Details: sl@0: // - Load the specified logical driver dll and check the return value sl@0: // is as expected. Create the logical channel for the current thread sl@0: // and check the return value as KErrNone. sl@0: // - Install the scheduler hook and check it is installed successfully. sl@0: // - Enable scheduler callback, setup test threads, test the scheduler hook sl@0: // before thread resume and after resume is as expected. sl@0: // - Perform some context switching and check rescheduler count is as expected. sl@0: // - Disable scheduler callback, perform some context switching and check sl@0: // thread rescheduler count is as expected. sl@0: // - Re-enable scheduler callback, perform some context switching and check sl@0: // thread rescheduler count is as expected. sl@0: // - Remove schedule hook and check it is successfully removed. perform some sl@0: // context switching and check thread rescheduler count is as expected. sl@0: // - Check exception during context switching, user mode interrupt, WFAR, sl@0: // exec call are as expected. sl@0: // - Uninstall scheduler hook and check it is as expected. sl@0: // Platforms/Drives/Compatibility: sl@0: // Hardware (Automatic). sl@0: // Assumptions/Requirement/Pre-requisites: sl@0: // Failures and causes: sl@0: // Base Port information: sl@0: // sl@0: // sl@0: sl@0: #include "context.h" sl@0: #define __KERNEL_MODE__ sl@0: #include "nk_priv.h" sl@0: #include sl@0: #undef __KERNEL_MODE__ sl@0: sl@0: RTest test(_L("T_SCHEDHOOK")); sl@0: sl@0: RSchedhookTest ldd; sl@0: sl@0: RThread Thread1; sl@0: TRequestStatus Request1; sl@0: sl@0: sl@0: sl@0: RThread Thread2; sl@0: TRequestStatus Request2; sl@0: sl@0: TInt Thread2Main(TAny*) sl@0: { sl@0: for(;;) sl@0: { sl@0: Request2 = KRequestPending; sl@0: TRequestStatus* request = &Request1; sl@0: Thread1.RequestComplete(request,KErrNone); sl@0: User::WaitForRequest(Request2); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: RThread ThreadException; sl@0: TArmRegSet ThreadExceptionData; sl@0: RThread ThreadWFAR; sl@0: TArmRegSet ThreadWFARData; sl@0: RThread ThreadUserInt; sl@0: TArmRegSet ThreadUserIntData; sl@0: RThread ThreadExecCall; sl@0: TArmRegSet ThreadExecCallData; sl@0: sl@0: sl@0: sl@0: TInt GetThreadContext(RThread aThread,TArmRegSet& aContext) sl@0: { sl@0: TPtr8 context((TUint8*)&aContext,sizeof(TArmRegSet),sizeof(TArmRegSet)); sl@0: return ldd.GetThreadContext(aThread.Id(),context); sl@0: } sl@0: sl@0: sl@0: sl@0: void DumpContext(TArmRegSet& aContext,TInt aType) sl@0: { sl@0: test.Printf(_L(" Context type %d\n"),aType); sl@0: test.Printf(_L(" r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n"),aContext.iR0,aContext.iR1,aContext.iR2,aContext.iR3); sl@0: test.Printf(_L(" r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n"),aContext.iR4,aContext.iR5,aContext.iR6,aContext.iR7); sl@0: test.Printf(_L(" r8 =%08x r9 =%08x r10=%08x r11=%08x\n"),aContext.iR8,aContext.iR9,aContext.iR10,aContext.iR11); sl@0: test.Printf(_L(" r12=%08x r13=%08x r14=%08x r15=%08x\n"),aContext.iR12,aContext.iR13,aContext.iR14,aContext.iR15); sl@0: test.Printf(_L(" cpsr=%08x"),aContext.iFlags); sl@0: } sl@0: sl@0: sl@0: sl@0: void TestContext() sl@0: { sl@0: TInt r; sl@0: TArmRegSet context; sl@0: sl@0: test.Start(_L("Insert scheduler hook")); sl@0: r = ldd.InsertHooks(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Enable scheduler callback")); sl@0: r = ldd.EnableCallback(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Test exception context")); sl@0: r = ThreadException.Create(KNullDesC,ThreadContextHwExc,KDefaultStackSize,&User::Allocator(),&ThreadExceptionData); sl@0: test(r==KErrNone); sl@0: ThreadException.SetPriority(EPriorityMore); sl@0: r = ldd.SetTestThread(ThreadException.Id()); // So ldd handles the exception for this thread sl@0: test(r==KErrNone); sl@0: ThreadException.Resume(); sl@0: User::After(250000); // Let thread run sl@0: r = GetThreadContext(ThreadException,context); sl@0: DumpContext(context,r); sl@0: test(r==NThread::EContextException); sl@0: test(CheckContextHwExc(&context,&ThreadExceptionData)); sl@0: sl@0: test.Next(_L("Test user mode interupt context")); sl@0: r = ThreadUserInt.Create(KNullDesC,ThreadContextUserInt,KDefaultStackSize,&User::Allocator(),&ThreadUserIntData); sl@0: test(r==KErrNone); sl@0: ThreadUserInt.SetPriority(EPriorityLess); sl@0: ThreadUserInt.Resume(); sl@0: User::After(250000); // Let thread run sl@0: r = GetThreadContext(ThreadUserInt,context); sl@0: DumpContext(context,r); sl@0: test(r==NThread::EContextUserInterrupt); sl@0: test(CheckContextUserInt(&context,&ThreadUserIntData)); sl@0: sl@0: test.Next(_L("Test WFAR context")); sl@0: r = ThreadWFAR.Create(KNullDesC,ThreadContextWFAR,KDefaultStackSize,&User::Allocator(),&ThreadWFARData); sl@0: test(r==KErrNone); sl@0: ThreadWFAR.SetPriority(EPriorityMore); sl@0: ThreadWFAR.Resume(); sl@0: User::After(250000); // Let thread run sl@0: r = GetThreadContext(ThreadWFAR,context); sl@0: DumpContext(context,r); sl@0: test(r==NThread::EContextWFAR); sl@0: test(CheckContextWFAR(&context,&ThreadWFARData)); sl@0: sl@0: test.Next(_L("Test exec call context")); sl@0: r = ThreadExecCall.Create(KNullDesC,ThreadContextExecCall,KDefaultStackSize,&User::Allocator(),&ThreadExecCallData); sl@0: test(r==KErrNone); sl@0: ThreadExecCall.SetPriority(EPriorityMore); sl@0: ThreadExecCall.Resume(); sl@0: User::After(250000); // Let thread run sl@0: r = GetThreadContext(ThreadExecCall,context); sl@0: DumpContext(context,r); sl@0: test(r==NThread::EContextExec); sl@0: test(CheckContextExecCall(&context,&ThreadExecCallData)); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: sl@0: TInt DoContextSwitches(TInt aCount) sl@0: { sl@0: TInt r = ldd.SetTestThread(Thread2.Id()); // Zero test count sl@0: test(r==KErrNone); sl@0: while(aCount) sl@0: { sl@0: Request1 = KRequestPending; sl@0: TRequestStatus* request = &Request2; sl@0: Thread2.RequestComplete(request,KErrNone); sl@0: User::WaitForRequest(Request1); sl@0: --aCount; sl@0: } sl@0: r = ldd.GetTestCount(); sl@0: test(r>=0); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: test.Title(); sl@0: TInt r; sl@0: sl@0: test.Start(_L("Loading LDD")); sl@0: r = User::LoadLogicalDevice(_L("D_SCHEDHOOK")); sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: sl@0: test.Next(_L("Open channel to LDD")); sl@0: r = ldd.Open(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Installing scheduler hooks")); sl@0: r = ldd.Install(); sl@0: if (r==KErrNotSupported) sl@0: { sl@0: test.Next(_L("Scheduler hooks not supported on this platform, skipping test")); sl@0: ldd.Close(); sl@0: test.End(); sl@0: return KErrNone; sl@0: } sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Enable scheduler callback")); sl@0: r = ldd.EnableCallback(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Setting up test thread")); sl@0: r= Thread1.Open(RThread().Id()); sl@0: test(r==KErrNone); sl@0: r = Thread2.Create(KNullDesC,Thread2Main,KDefaultStackSize,&User::Allocator(),NULL); sl@0: test(r==KErrNone); sl@0: r = ldd.SetTestThread(Thread2.Id()); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Test scheduler hook (wait)")); sl@0: User::After(1000000); // 1 second sl@0: TInt count = ldd.GetTestCount(); sl@0: test.Printf(_L("count=%d\n"),count); sl@0: test(count==0); sl@0: sl@0: test.Next(_L("Test scheduler hook (resume)")); sl@0: Request1 = KRequestPending; sl@0: Thread2.Resume(); sl@0: User::WaitForRequest(Request1); sl@0: count = ldd.GetTestCount(); sl@0: test.Printf(_L("count=%d\n"),count); sl@0: test(count>0); sl@0: sl@0: test.Next(_L("Test scheduler hook (context switching)")); sl@0: count = DoContextSwitches(1000); sl@0: test.Printf(_L("count=%d\n"),count); sl@0: test(count>=1000); sl@0: sl@0: test.Next(_L("Disable scheduler callback")); sl@0: r = ldd.DisableCallback(); sl@0: test(r==KErrNone); sl@0: count = DoContextSwitches(1000); sl@0: test.Printf(_L("count=%d\n"),count); sl@0: test(count==0); sl@0: sl@0: test.Next(_L("Re-enable scheduler callback")); sl@0: r = ldd.EnableCallback(); sl@0: test(r==KErrNone); sl@0: count = DoContextSwitches(1000); sl@0: test.Printf(_L("count=%d\n"),count); sl@0: test(count>=1000); sl@0: sl@0: test.Next(_L("Removing scheduler hook")); sl@0: r = ldd.RemoveHooks(); sl@0: test(r==KErrNone); sl@0: count=DoContextSwitches(1000); sl@0: r = ldd.GetTestCount(); sl@0: test.Printf(_L("count=%d\n"),r); sl@0: test(r==0); sl@0: sl@0: test.Next(_L("Test thread context")); sl@0: TestContext(); sl@0: sl@0: test.Next(_L("Uninstalling scheduler hook")); sl@0: r = ldd.Uninstall(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("Closing ldd")); sl@0: ldd.Close(); sl@0: sl@0: test.End(); sl@0: sl@0: return(0); sl@0: } sl@0: