|
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 |