|
1 // Copyright (c) 2008-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\demandpaging\t_threadcreate.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #define __E32TEST_EXTENSION__ |
|
19 #include <e32test.h> |
|
20 #include <dptest.h> |
|
21 #include <e32hal.h> |
|
22 #include <u32exec.h> |
|
23 #include <e32svr.h> |
|
24 #include <e32panic.h> |
|
25 #include "u32std.h" |
|
26 |
|
27 #include "t_dpcmn.h" |
|
28 |
|
29 enum |
|
30 { |
|
31 EUnspecified, |
|
32 EPaged, |
|
33 EUnpaged, |
|
34 }; |
|
35 |
|
36 _LIT(KGlobalThreadName, "gThreadGlobal"); |
|
37 |
|
38 RSemaphore gSem1; |
|
39 RSemaphore gSem2; |
|
40 TBool gStackPaged; |
|
41 TUint8* gStackPtr = NULL; |
|
42 |
|
43 struct SThreadPagedInfo |
|
44 { |
|
45 TBool iHeapPaged; |
|
46 TBool iStackPaged; |
|
47 }; |
|
48 |
|
49 TUint8 ReadByte(volatile TUint8* aPtr) |
|
50 { |
|
51 return *aPtr; |
|
52 } |
|
53 |
|
54 TInt TestThreadFunction(TAny* aPtr) |
|
55 { |
|
56 for (TInt i = 0; i<2; i++) |
|
57 { |
|
58 if (i == 1) |
|
59 { |
|
60 User::SetRealtimeState(User::ERealtimeStateOn); |
|
61 RDebug::Printf("aPtr %x",aPtr); |
|
62 ReadByte((TUint8*)aPtr); |
|
63 } |
|
64 } |
|
65 return KErrNone; |
|
66 } |
|
67 |
|
68 // |
|
69 // IsStackPaged |
|
70 // |
|
71 // Determine whether the stack is paged by flushing the cache and attempting |
|
72 // to read a byte that has been paged out |
|
73 // |
|
74 // |
|
75 TInt IsStackPaged(const TUint8* aPtr) |
|
76 { |
|
77 RThread thread; |
|
78 TInt r; |
|
79 r = thread.Create(KNullDesC, TestThreadFunction, 0x1000, NULL, (TAny*)aPtr); |
|
80 if (r != KErrNone) |
|
81 { |
|
82 return r; |
|
83 } |
|
84 |
|
85 TRequestStatus status; |
|
86 thread.Logon(status); |
|
87 if(status.Int() != KRequestPending) |
|
88 { |
|
89 return KErrGeneral; |
|
90 } |
|
91 thread.Resume(); |
|
92 User::WaitForRequest(status); |
|
93 if (thread.ExitType() == EExitPanic && |
|
94 thread.ExitCategory() == _L("KERN-EXEC") && |
|
95 thread.ExitReason() == EIllegalFunctionForRealtimeThread) |
|
96 { |
|
97 gStackPaged = ETrue; |
|
98 } |
|
99 else |
|
100 { |
|
101 r = thread.ExitReason(); |
|
102 if(r != KErrNone) |
|
103 return r; |
|
104 |
|
105 if (EExitKill != thread.ExitType()) |
|
106 return KErrGeneral; |
|
107 gStackPaged = EFalse; |
|
108 } |
|
109 thread.Close(); |
|
110 if (!gStackPaged) |
|
111 { |
|
112 RDebug::Printf(" %08x present", aPtr); |
|
113 } |
|
114 else |
|
115 { |
|
116 RDebug::Printf(" %08x not present", aPtr); |
|
117 } |
|
118 return r; |
|
119 } |
|
120 |
|
121 /** |
|
122 Thread that just returns the data paging attributes of the thread. |
|
123 */ |
|
124 TInt ThreadFunc(TAny* aThreadInfo) |
|
125 { |
|
126 SThreadPagedInfo& info = *(SThreadPagedInfo*)aThreadInfo; |
|
127 RHeap& heap = User::Heap(); |
|
128 RChunk chunk; |
|
129 chunk.SetHandle(heap.ChunkHandle()); |
|
130 info.iHeapPaged = chunk.IsPaged(); |
|
131 gStackPtr = (TUint8*)&chunk; |
|
132 RDebug::Printf("&chunk %x",&chunk); |
|
133 gSem1.Signal(); |
|
134 gSem2.Wait(); |
|
135 info.iStackPaged = gStackPaged; |
|
136 return KErrNone; |
|
137 } |
|
138 |
|
139 TInt DummyFunction(TAny*) |
|
140 { |
|
141 return KErrNone; |
|
142 } |
|
143 |
|
144 TInt PanicThreadCreate(TAny* aCreateInfo) |
|
145 { |
|
146 RThread thread; |
|
147 TThreadCreateInfo createInfo((*(TThreadCreateInfo*) aCreateInfo)); |
|
148 thread.Create(createInfo); |
|
149 return KErrGeneral; // Should never reach here |
|
150 } |
|
151 |
|
152 // |
|
153 // CheckHeapStackPaged |
|
154 // |
|
155 // Using the TThreadCreateInfo used to create the cheap, determine |
|
156 // whether the stack and the heap are paged or not |
|
157 // |
|
158 // |
|
159 TInt CheckHeapStackPaged(TThreadCreateInfo& aCreateInfo, TInt aPaged, SThreadPagedInfo& aPagedInfo, TBool aUseProcessHeap = EFalse) |
|
160 { |
|
161 RThread thread; |
|
162 TBool paged; |
|
163 switch (aPaged) |
|
164 { |
|
165 case EUnspecified: |
|
166 test.Printf(_L("Testing gProcessPaged\n")); |
|
167 paged = gProcessPaged; |
|
168 break; |
|
169 |
|
170 case EPaged: |
|
171 test.Printf(_L("Testing Paged\n")); |
|
172 aCreateInfo.SetPaging(TThreadCreateInfo::EPaged); |
|
173 paged = ETrue; |
|
174 break; |
|
175 |
|
176 case EUnpaged: |
|
177 test.Printf(_L("Testing Unpaged\n")); |
|
178 aCreateInfo.SetPaging(TThreadCreateInfo::EUnpaged); |
|
179 paged = EFalse; |
|
180 break; |
|
181 } |
|
182 |
|
183 |
|
184 test_KErrNone(thread.Create(aCreateInfo)); |
|
185 |
|
186 // Disable JIT debugging. |
|
187 TBool justInTime=User::JustInTime(); |
|
188 User::SetJustInTime(EFalse); |
|
189 |
|
190 TRequestStatus status; |
|
191 thread.Logon(status); |
|
192 |
|
193 thread.Resume(); |
|
194 |
|
195 gSem1.Wait(); |
|
196 DPTest::FlushCache(); |
|
197 TInt r = IsStackPaged(gStackPtr); |
|
198 test_KErrNone(r); |
|
199 gSem2.Signal(); |
|
200 |
|
201 User::WaitForRequest(status); |
|
202 test (EExitKill == thread.ExitType()); |
|
203 test(KErrNone == status.Int()); |
|
204 |
|
205 test(KErrNone == thread.ExitReason()); |
|
206 |
|
207 if (thread.ExitType() == EExitPanic) |
|
208 { |
|
209 test(thread.ExitCategory()==_L("USER")); |
|
210 } |
|
211 |
|
212 CLOSE_AND_WAIT(thread); |
|
213 |
|
214 // Put JIT debugging back to previous status. |
|
215 User::SetJustInTime(justInTime); |
|
216 |
|
217 UpdatePaged(paged); |
|
218 if (aUseProcessHeap) |
|
219 {// If using existing thread heap, heap will take the process paging status |
|
220 test_Equal(gProcessPaged, aPagedInfo.iHeapPaged); |
|
221 } |
|
222 else |
|
223 { |
|
224 test_Equal(paged, aPagedInfo.iHeapPaged); |
|
225 } |
|
226 test_Equal(paged, aPagedInfo.iStackPaged); |
|
227 return KErrNone; |
|
228 } |
|
229 |
|
230 // |
|
231 // TestThreadCreate |
|
232 // |
|
233 //---------------------------------------------------------------------------------------------- |
|
234 //! @SYMTestCaseID KBASE-T_THREADHEAPCREATE-xxxx |
|
235 //! @SYMTestType UT |
|
236 //! @SYMPREQ PREQ1954 |
|
237 //! @SYMTestCaseDesc TThreadCreateInfo tests |
|
238 //! Verify the thread heap creation implementation |
|
239 //! @SYMTestActions |
|
240 //! 1. Call TThreadCreateInfo::TThreadCreateInfo() with valid parameters. |
|
241 //! Following this call RThread::Create() |
|
242 //! 2. Call TThreadCreateInfo::TThreadCreateInfo() with an invalid stack size. |
|
243 //! Following this call RThread::Create() |
|
244 //! 3. Call TThreadCreateInfo::SetCreateHeap() with an invalid min heap size. |
|
245 //! Following this call RThread::Create() |
|
246 //! 4. Call TThreadCreateInfo::SetCreateHeap() with an invalid max heap size. |
|
247 //! Following this call RThread::Create() |
|
248 //! 5. Call TThreadCreateInfo::SetCreateHeap() with minHeapSize. > maxHeapSize |
|
249 //! Following this call RThread::Create() |
|
250 //! 6. Call TThreadCreateInfo::SetUseHeap() specifying NULL. Following this call RThread::Create() |
|
251 //! 7. Call TThreadCreateInfo::SetOwner() with aOwner set to EOwnerProcess. |
|
252 //! Following this call RThread::Create() |
|
253 //! 8. Call TThreadCreateInfo::SetOwner() with aOwner set to EOwnerThread. |
|
254 //! Following this call RThread::Create() |
|
255 //! 9. Call TThreadCreateInfo::SetPaging() with aPaging set to unspecified. |
|
256 //! Following this call RThread::Create() and check the paging status of the thread |
|
257 //! 10. Call TThreadCreateInfo::SetPaging() with aPaging set to EPaged. |
|
258 //! Following this call RThread::Create() and check the paging status of the thread |
|
259 //! 11. Call TThreadCreateInfo::SetPaging() with aPaging set to EUnpaged. |
|
260 //! Following this call RThread::Create() and check the paging status of the thread |
|
261 //! |
|
262 //! @SYMTestExpectedResults All tests should pass. |
|
263 //! @SYMTestPriority High |
|
264 //! @SYMTestStatus Implemented |
|
265 //---------------------------------------------------------------------------------------------- |
|
266 void TestThreadCreate() |
|
267 { |
|
268 TInt r; |
|
269 test.Start(_L("Test RThread::Create() (New Heap)")); |
|
270 { |
|
271 RThread thread; |
|
272 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL); |
|
273 createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize); |
|
274 r = thread.Create(createInfo); |
|
275 test_KErrNone(r); |
|
276 test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone)); |
|
277 thread.Close(); |
|
278 } |
|
279 |
|
280 test.Next(_L("Test RThread::Create() - invalid stack size")); |
|
281 { |
|
282 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, -1 , NULL); |
|
283 createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize); |
|
284 |
|
285 RThread threadPanic; |
|
286 test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, |
|
287 KMinHeapSize, (TAny*) &createInfo)); |
|
288 test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdStackSizeNegative)); |
|
289 } |
|
290 |
|
291 test.Next(_L("Test RThread::Create() - invalid min heap size")); |
|
292 { |
|
293 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize , NULL); |
|
294 createInfo.SetCreateHeap(-1, KMinHeapSize); |
|
295 |
|
296 RThread threadPanic; |
|
297 test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, |
|
298 KMinHeapSize, (TAny*) &createInfo)); |
|
299 |
|
300 test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdHeapMinTooSmall)); |
|
301 } |
|
302 |
|
303 test.Next(_L("Test RThread::Create() - invalid max heap size")); |
|
304 { |
|
305 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize , NULL); |
|
306 createInfo.SetCreateHeap(KMinHeapSize, -1); |
|
307 |
|
308 RThread threadPanic; |
|
309 test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, |
|
310 KMinHeapSize, (TAny*) &createInfo)); |
|
311 |
|
312 test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdHeapMaxLessThanMin)); |
|
313 } |
|
314 |
|
315 test.Next(_L("Test RThread::Create() - min heap size > max heap size")); |
|
316 { |
|
317 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize , NULL); |
|
318 createInfo.SetCreateHeap(KMinHeapSize << 1, KMinHeapSize); |
|
319 |
|
320 RThread threadPanic; |
|
321 test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, |
|
322 KMinHeapSize, (TAny*) &createInfo)); |
|
323 |
|
324 test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdHeapMaxLessThanMin)); |
|
325 } |
|
326 |
|
327 test.Next(_L("Test TThreadCreateInfo::SetUseHeap() ")); |
|
328 { |
|
329 RThread thread; |
|
330 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL); |
|
331 createInfo.SetUseHeap(NULL); |
|
332 r = thread.Create(createInfo); |
|
333 test_KErrNone(r); |
|
334 test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone)); |
|
335 thread.Close(); |
|
336 } |
|
337 |
|
338 test.Next(_L("Test TThreadCreateInfo::SetOwner(EOwnerProcess) ")); |
|
339 { |
|
340 RThread thread; |
|
341 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL); |
|
342 createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize); |
|
343 createInfo.SetOwner(EOwnerProcess); |
|
344 r = thread.Create(createInfo); |
|
345 test_KErrNone(r); |
|
346 test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone)); |
|
347 thread.Close(); |
|
348 } |
|
349 |
|
350 |
|
351 test.Next(_L("Test TThreadCreateInfo::SetOwner(EOwnerThread) ")); |
|
352 { |
|
353 RThread thread; |
|
354 TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL); |
|
355 createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize); |
|
356 createInfo.SetOwner(EOwnerThread); |
|
357 r = thread.Create(createInfo); |
|
358 test_KErrNone(r); |
|
359 test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone)); |
|
360 thread.Close(); |
|
361 } |
|
362 |
|
363 |
|
364 |
|
365 gSem1.CreateLocal(0); |
|
366 gSem2.CreateLocal(0); |
|
367 test.Next(_L("Test Thread paging (New Heap)")); |
|
368 { |
|
369 TBool aPaged = gProcessPaged; |
|
370 SThreadPagedInfo pagedInfo; |
|
371 test.Printf(_L("Testing gProcessPaged: aPaged = %x\n"), aPaged); |
|
372 TThreadCreateInfo createInfo( KGlobalThreadName, ThreadFunc, KDefaultStackSize, |
|
373 (TAny*)&pagedInfo); |
|
374 createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize); |
|
375 |
|
376 test_KErrNone(CheckHeapStackPaged(createInfo, EUnspecified, pagedInfo)); |
|
377 test_KErrNone(CheckHeapStackPaged(createInfo, EPaged, pagedInfo)); |
|
378 test_KErrNone(CheckHeapStackPaged(createInfo, EUnpaged, pagedInfo)); |
|
379 } |
|
380 |
|
381 |
|
382 test.Next(_L("Test RThread::Create() (Existing Heap)")); |
|
383 { |
|
384 SThreadPagedInfo pagedInfo; |
|
385 TThreadCreateInfo createInfo( KGlobalThreadName, ThreadFunc, KDefaultStackSize, |
|
386 (TAny*)&pagedInfo); |
|
387 createInfo.SetUseHeap(NULL); |
|
388 |
|
389 test_KErrNone(CheckHeapStackPaged(createInfo, EUnspecified, pagedInfo, ETrue)); |
|
390 test_KErrNone(CheckHeapStackPaged(createInfo, EPaged, pagedInfo, ETrue)); |
|
391 test_KErrNone(CheckHeapStackPaged(createInfo, EUnpaged, pagedInfo, ETrue)); |
|
392 } |
|
393 test.End(); |
|
394 } |
|
395 |
|
396 |
|
397 |
|
398 TInt TestingTThreadCreate() |
|
399 { |
|
400 test.Printf(_L("Test TThreadCreateInfo\n")); |
|
401 TestThreadCreate(); |
|
402 |
|
403 return 0; |
|
404 } |