os/kernelhwsrv/kerneltest/e32test/debug/t_schedhook.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\debug\t_schedhook.cpp
    15 // Overview:
    16 // Test the device hook functionality.
    17 // API Information:
    18 // RBusLogicalChannel, DLogicalDevice
    19 // Details:	
    20 // - Load the specified logical driver dll and check the return value 
    21 // is as expected. Create the logical channel for the current thread 
    22 // and check the return value as KErrNone.
    23 // - Install the scheduler hook and check it is installed successfully.
    24 // - Enable scheduler callback, setup test threads, test the scheduler hook 
    25 // before thread resume and after resume is as expected.
    26 // - Perform some context switching and check rescheduler count is as expected.
    27 // - Disable scheduler callback, perform some context switching and check 
    28 // thread rescheduler count is as expected.
    29 // - Re-enable scheduler callback, perform some context switching and check 
    30 // thread rescheduler count is as expected.
    31 // - Remove schedule hook and check it is successfully removed. perform some 
    32 // context switching and check thread rescheduler count is as expected.
    33 // - Check exception during context switching, user mode interrupt, WFAR, 
    34 // exec call are as expected.
    35 // - Uninstall scheduler hook and check it is as expected.
    36 // Platforms/Drives/Compatibility:
    37 // Hardware (Automatic).
    38 // Assumptions/Requirement/Pre-requisites:
    39 // Failures and causes:
    40 // Base Port information:
    41 // 
    42 //
    43 
    44 #include "context.h"
    45 #define __KERNEL_MODE__
    46 #include "nk_priv.h"
    47 #include <nk_plat.h>
    48 #undef __KERNEL_MODE__
    49 
    50 RTest test(_L("T_SCHEDHOOK"));
    51 
    52 RSchedhookTest ldd;
    53 
    54 RThread Thread1;
    55 TRequestStatus Request1;
    56 
    57 
    58 
    59 RThread Thread2;
    60 TRequestStatus Request2;
    61 
    62 TInt Thread2Main(TAny*)
    63 	{
    64 	for(;;)
    65 		{
    66 		Request2 = KRequestPending;
    67 		TRequestStatus* request = &Request1;
    68 		Thread1.RequestComplete(request,KErrNone);
    69 		User::WaitForRequest(Request2);
    70 		}
    71 	}
    72 
    73 
    74 
    75 RThread		ThreadException;
    76 TArmRegSet	ThreadExceptionData;
    77 RThread		ThreadWFAR;
    78 TArmRegSet	ThreadWFARData;
    79 RThread		ThreadUserInt;
    80 TArmRegSet	ThreadUserIntData;
    81 RThread		ThreadExecCall;
    82 TArmRegSet	ThreadExecCallData;
    83 
    84 
    85 
    86 TInt GetThreadContext(RThread aThread,TArmRegSet& aContext)
    87 	{
    88 	TPtr8 context((TUint8*)&aContext,sizeof(TArmRegSet),sizeof(TArmRegSet));
    89 	return ldd.GetThreadContext(aThread.Id(),context);
    90 	}
    91 
    92 
    93 
    94 void DumpContext(TArmRegSet& aContext,TInt aType)
    95 	{
    96 	test.Printf(_L("  Context type %d\n"),aType);
    97 	test.Printf(_L("  r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n"),aContext.iR0,aContext.iR1,aContext.iR2,aContext.iR3);
    98 	test.Printf(_L("  r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n"),aContext.iR4,aContext.iR5,aContext.iR6,aContext.iR7);
    99 	test.Printf(_L("  r8 =%08x r9 =%08x r10=%08x r11=%08x\n"),aContext.iR8,aContext.iR9,aContext.iR10,aContext.iR11);
   100 	test.Printf(_L("  r12=%08x r13=%08x r14=%08x r15=%08x\n"),aContext.iR12,aContext.iR13,aContext.iR14,aContext.iR15);
   101 	test.Printf(_L("  cpsr=%08x"),aContext.iFlags);
   102 	}
   103 
   104 
   105 
   106 void TestContext()
   107 	{
   108 	TInt r;
   109 	TArmRegSet context;
   110 
   111 	test.Start(_L("Insert scheduler hook"));
   112 	r = ldd.InsertHooks();
   113 	test(r==KErrNone);
   114 
   115 	test.Next(_L("Enable scheduler callback"));
   116 	r = ldd.EnableCallback();
   117 	test(r==KErrNone);
   118 
   119 	test.Next(_L("Test exception context"));
   120 	r = ThreadException.Create(KNullDesC,ThreadContextHwExc,KDefaultStackSize,&User::Allocator(),&ThreadExceptionData);
   121 	test(r==KErrNone);
   122 	ThreadException.SetPriority(EPriorityMore);
   123 	r = ldd.SetTestThread(ThreadException.Id());   // So ldd handles the exception for this thread
   124 	test(r==KErrNone);
   125 	ThreadException.Resume();
   126 	User::After(250000);   // Let thread run
   127 	r = GetThreadContext(ThreadException,context);
   128 	DumpContext(context,r);
   129 	test(r==NThread::EContextException);
   130 	test(CheckContextHwExc(&context,&ThreadExceptionData));
   131 
   132 	test.Next(_L("Test user mode interupt context"));
   133 	r = ThreadUserInt.Create(KNullDesC,ThreadContextUserInt,KDefaultStackSize,&User::Allocator(),&ThreadUserIntData);
   134 	test(r==KErrNone);
   135 	ThreadUserInt.SetPriority(EPriorityLess);
   136 	ThreadUserInt.Resume();
   137 	User::After(250000);   // Let thread run
   138 	r = GetThreadContext(ThreadUserInt,context);
   139 	DumpContext(context,r);
   140 	test(r==NThread::EContextUserInterrupt);
   141 	test(CheckContextUserInt(&context,&ThreadUserIntData));
   142 
   143 	test.Next(_L("Test WFAR context"));
   144 	r = ThreadWFAR.Create(KNullDesC,ThreadContextWFAR,KDefaultStackSize,&User::Allocator(),&ThreadWFARData);
   145 	test(r==KErrNone);
   146 	ThreadWFAR.SetPriority(EPriorityMore);
   147 	ThreadWFAR.Resume();
   148 	User::After(250000);   // Let thread run
   149 	r = GetThreadContext(ThreadWFAR,context);
   150 	DumpContext(context,r);
   151 	test(r==NThread::EContextWFAR);
   152 	test(CheckContextWFAR(&context,&ThreadWFARData));
   153 
   154 	test.Next(_L("Test exec call context"));
   155 	r = ThreadExecCall.Create(KNullDesC,ThreadContextExecCall,KDefaultStackSize,&User::Allocator(),&ThreadExecCallData);
   156 	test(r==KErrNone);
   157 	ThreadExecCall.SetPriority(EPriorityMore);
   158 	ThreadExecCall.Resume();
   159 	User::After(250000);   // Let thread run
   160 	r = GetThreadContext(ThreadExecCall,context);
   161 	DumpContext(context,r);
   162 	test(r==NThread::EContextExec);
   163 	test(CheckContextExecCall(&context,&ThreadExecCallData));
   164 
   165 	test.End();
   166 	}
   167 
   168 
   169 TInt DoContextSwitches(TInt aCount)
   170 	{
   171 	TInt r = ldd.SetTestThread(Thread2.Id());   // Zero test count
   172 	test(r==KErrNone);
   173 	while(aCount)
   174 		{
   175 		Request1 = KRequestPending;
   176 		TRequestStatus* request = &Request2;
   177 		Thread2.RequestComplete(request,KErrNone);
   178 		User::WaitForRequest(Request1);
   179 		--aCount;
   180 		}
   181 	r = ldd.GetTestCount();
   182 	test(r>=0);
   183 	return r;
   184 	}
   185 
   186 
   187 
   188 GLDEF_C TInt E32Main()
   189     {
   190 	test.Title();
   191 	TInt r;
   192 	
   193 	test.Start(_L("Loading LDD"));
   194 	r = User::LoadLogicalDevice(_L("D_SCHEDHOOK"));
   195 	test(r==KErrNone || r==KErrAlreadyExists);
   196 
   197 	test.Next(_L("Open channel to LDD"));
   198 	r = ldd.Open();
   199 	test(r==KErrNone);
   200 
   201 	test.Next(_L("Installing scheduler hooks"));
   202 	r = ldd.Install();
   203 	if (r==KErrNotSupported)
   204 		{
   205 		test.Next(_L("Scheduler hooks not supported on this platform, skipping test"));
   206 		ldd.Close();
   207 		test.End();
   208 		return KErrNone;
   209 		}
   210 	test(r==KErrNone);
   211 
   212 	test.Next(_L("Enable scheduler callback"));
   213 	r = ldd.EnableCallback();
   214 	test(r==KErrNone);
   215 
   216 	test.Next(_L("Setting up test thread"));
   217 	r= Thread1.Open(RThread().Id());
   218 	test(r==KErrNone);
   219 	r = Thread2.Create(KNullDesC,Thread2Main,KDefaultStackSize,&User::Allocator(),NULL);
   220 	test(r==KErrNone);
   221 	r = ldd.SetTestThread(Thread2.Id());
   222 	test(r==KErrNone);
   223 
   224 	test.Next(_L("Test scheduler hook (wait)"));
   225 	User::After(1000000); // 1 second
   226 	TInt count = ldd.GetTestCount();
   227 	test.Printf(_L("count=%d\n"),count);
   228 	test(count==0);
   229 
   230 	test.Next(_L("Test scheduler hook (resume)"));
   231 	Request1 = KRequestPending;
   232 	Thread2.Resume();
   233 	User::WaitForRequest(Request1);
   234 	count = ldd.GetTestCount();
   235 	test.Printf(_L("count=%d\n"),count);
   236 	test(count>0);
   237 
   238 	test.Next(_L("Test scheduler hook (context switching)"));
   239 	count = DoContextSwitches(1000);
   240 	test.Printf(_L("count=%d\n"),count);
   241 	test(count>=1000);
   242 
   243 	test.Next(_L("Disable scheduler callback"));
   244 	r = ldd.DisableCallback();
   245 	test(r==KErrNone);
   246 	count = DoContextSwitches(1000);
   247 	test.Printf(_L("count=%d\n"),count);
   248 	test(count==0);
   249 
   250 	test.Next(_L("Re-enable scheduler callback"));
   251 	r = ldd.EnableCallback();
   252 	test(r==KErrNone);
   253 	count = DoContextSwitches(1000);
   254 	test.Printf(_L("count=%d\n"),count);
   255 	test(count>=1000);
   256 
   257 	test.Next(_L("Removing scheduler hook"));
   258 	r = ldd.RemoveHooks();
   259 	test(r==KErrNone);
   260 	count=DoContextSwitches(1000);
   261 	r = ldd.GetTestCount();
   262 	test.Printf(_L("count=%d\n"),r);
   263 	test(r==0);
   264 
   265 	test.Next(_L("Test thread context"));
   266 	TestContext();
   267 
   268 	test.Next(_L("Uninstalling scheduler hook"));
   269 	r = ldd.Uninstall();
   270 	test(r==KErrNone);
   271 
   272 	test.Next(_L("Closing ldd"));
   273 	ldd.Close();
   274 	
   275 	test.End();
   276 
   277 	return(0);
   278     }
   279