os/kernelhwsrv/kerneltest/e32test/demandpaging/t_threadcreate.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}