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