kerneltest/e32test/demandpaging/t_threadcreate.cpp
changeset 0 a41df078684a
child 109 b3a1d9898418
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/demandpaging/t_threadcreate.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,404 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\demandpaging\t_threadcreate.cpp
+// 
+//
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <dptest.h>
+#include <e32hal.h>
+#include <u32exec.h>
+#include <e32svr.h>
+#include <e32panic.h>
+#include "u32std.h"
+
+#include "t_dpcmn.h"
+
+enum
+	{
+	EUnspecified, 
+	EPaged, 
+	EUnpaged,
+	};
+
+_LIT(KGlobalThreadName, "gThreadGlobal");
+
+RSemaphore gSem1;
+RSemaphore gSem2;
+TBool gStackPaged;
+TUint8* gStackPtr = NULL;
+
+struct SThreadPagedInfo
+	{
+	TBool iHeapPaged;
+	TBool iStackPaged;
+	};
+
+TUint8 ReadByte(volatile TUint8* aPtr)
+	{
+	return *aPtr;
+	}
+
+TInt TestThreadFunction(TAny* aPtr)
+	{
+	for (TInt i = 0; i<2; i++)
+		{
+		if (i == 1)
+			{
+			User::SetRealtimeState(User::ERealtimeStateOn);
+			RDebug::Printf("aPtr %x",aPtr);
+			ReadByte((TUint8*)aPtr);
+			}
+		}
+	return KErrNone;
+	}
+
+//
+// IsStackPaged
+//
+// Determine whether the stack is paged by flushing the cache and attempting
+// to read a byte that has been paged out
+//
+//
+TInt IsStackPaged(const TUint8* aPtr)
+	{
+	RThread thread;
+	TInt r;
+	r = thread.Create(KNullDesC, TestThreadFunction, 0x1000, NULL, (TAny*)aPtr);
+	if (r != KErrNone)
+		{
+		return r;
+		}
+
+	TRequestStatus status;
+	thread.Logon(status);
+	if(status.Int() != KRequestPending)
+		{
+		return KErrGeneral;
+		}
+	thread.Resume();
+	User::WaitForRequest(status);
+	if (thread.ExitType() == EExitPanic &&
+		thread.ExitCategory() == _L("KERN-EXEC") &&
+		thread.ExitReason() == EIllegalFunctionForRealtimeThread)
+		{
+		gStackPaged = ETrue;
+		}
+	else
+		{ 
+		r = thread.ExitReason();
+		if(r != KErrNone)
+			return r;
+
+		if (EExitKill != thread.ExitType())
+			return KErrGeneral;
+		gStackPaged = EFalse;
+		}	
+	thread.Close();
+	if (!gStackPaged)
+		{
+		RDebug::Printf("    %08x present", aPtr);
+		}
+	else
+		{
+		RDebug::Printf("    %08x not present", aPtr);
+		}
+	return r;
+	}
+
+/**
+Thread that just returns the data paging attributes of the thread.
+*/
+TInt ThreadFunc(TAny* aThreadInfo)
+	{
+	SThreadPagedInfo& info = *(SThreadPagedInfo*)aThreadInfo;
+	RHeap& heap = User::Heap();
+	RChunk chunk;
+	chunk.SetHandle(heap.ChunkHandle());
+	info.iHeapPaged = chunk.IsPaged();
+	gStackPtr = (TUint8*)&chunk;
+	RDebug::Printf("&chunk %x",&chunk);
+	gSem1.Signal();
+	gSem2.Wait();
+	info.iStackPaged = gStackPaged;
+	return KErrNone;
+	}
+
+TInt DummyFunction(TAny*)
+	{
+	return KErrNone;
+	}
+
+TInt PanicThreadCreate(TAny* aCreateInfo)
+	{
+	RThread thread;
+	TThreadCreateInfo createInfo((*(TThreadCreateInfo*) aCreateInfo));
+	thread.Create(createInfo);
+	return KErrGeneral; // Should never reach here
+	}
+
+//
+// CheckHeapStackPaged
+//
+// Using the TThreadCreateInfo used to create the cheap, determine 
+// whether the stack and the heap are paged or not
+//
+//
+TInt CheckHeapStackPaged(TThreadCreateInfo& aCreateInfo, TInt aPaged, SThreadPagedInfo& aPagedInfo, TBool aUseProcessHeap = EFalse)
+	{
+	RThread thread;
+	TBool paged;
+	switch (aPaged)
+		{
+		case EUnspecified:
+			test.Printf(_L("Testing gProcessPaged\n"));
+			paged = gProcessPaged;
+			break;
+
+		case EPaged:
+			test.Printf(_L("Testing Paged\n"));
+			aCreateInfo.SetPaging(TThreadCreateInfo::EPaged);
+			paged = ETrue;
+			break;
+
+		case EUnpaged:
+			test.Printf(_L("Testing Unpaged\n"));
+			aCreateInfo.SetPaging(TThreadCreateInfo::EUnpaged);
+			paged = EFalse;
+			break;
+		}
+
+
+	test_KErrNone(thread.Create(aCreateInfo));
+	
+	// Disable JIT debugging.
+	TBool justInTime=User::JustInTime();
+	User::SetJustInTime(EFalse);
+
+	TRequestStatus status;
+	thread.Logon(status); 
+	
+	thread.Resume();
+	
+	gSem1.Wait();		
+	DPTest::FlushCache();
+	TInt r = IsStackPaged(gStackPtr);
+	test_KErrNone(r);
+	gSem2.Signal();
+
+	User::WaitForRequest(status);
+	test (EExitKill == thread.ExitType());
+	test(KErrNone == status.Int());
+	
+	test(KErrNone == thread.ExitReason());
+
+	if (thread.ExitType() == EExitPanic)
+		{
+		test(thread.ExitCategory()==_L("USER"));
+		}
+			
+	CLOSE_AND_WAIT(thread);
+
+	// Put JIT debugging back to previous status.
+	User::SetJustInTime(justInTime);
+
+	UpdatePaged(paged);
+	if (aUseProcessHeap)
+		{// If using existing thread heap, heap will take the process paging status
+		test_Equal(gProcessPaged, aPagedInfo.iHeapPaged);
+		}
+	else
+		{
+		test_Equal(paged, aPagedInfo.iHeapPaged);
+		}
+	test_Equal(paged, aPagedInfo.iStackPaged);
+	return KErrNone;
+	}
+
+//
+// TestThreadCreate
+//
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID			KBASE-T_THREADHEAPCREATE-xxxx
+//! @SYMTestType			UT
+//! @SYMPREQ				PREQ1954
+//! @SYMTestCaseDesc		TThreadCreateInfo tests
+//!							Verify the thread heap creation implementation
+//! @SYMTestActions	
+//! 1.	Call TThreadCreateInfo::TThreadCreateInfo() with valid parameters. 
+//! 	Following this call RThread::Create()
+//! 2.	Call TThreadCreateInfo::TThreadCreateInfo() with an invalid stack size. 
+//!		Following this call RThread::Create()
+//! 3.	Call TThreadCreateInfo::SetCreateHeap() with an invalid min heap size. 
+//!		Following this call RThread::Create()
+//! 4.	Call TThreadCreateInfo::SetCreateHeap() with an invalid max heap size. 
+//!		Following this call RThread::Create()
+//! 5.	Call TThreadCreateInfo::SetCreateHeap() with minHeapSize. > maxHeapSize 
+//!		Following this call RThread::Create()
+//! 6.	Call TThreadCreateInfo::SetUseHeap() specifying NULL. Following this call RThread::Create()
+//! 7.	Call TThreadCreateInfo::SetOwner() with aOwner set to EOwnerProcess. 
+//!		Following this call RThread::Create()
+//! 8.	Call TThreadCreateInfo::SetOwner() with aOwner set to EOwnerThread. 
+//!		Following this call RThread::Create()
+//! 9.	Call TThreadCreateInfo::SetPaging() with aPaging set to unspecified. 
+//!		Following this call RThread::Create() and check the paging status of the thread
+//! 10.	Call TThreadCreateInfo::SetPaging() with aPaging set to EPaged. 
+//!		Following this call RThread::Create() and check the paging status of the thread
+//! 11.	Call TThreadCreateInfo::SetPaging() with aPaging set to EUnpaged. 
+//!		Following this call RThread::Create() and check the paging status of the thread
+//!
+//! @SYMTestExpectedResults All tests should pass.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void TestThreadCreate()
+	{
+	TInt r;
+	test.Start(_L("Test RThread::Create() (New Heap)"));
+		{
+		RThread thread;
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL);
+		createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
+		r = thread.Create(createInfo);
+		test_KErrNone(r);
+		test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone));
+		thread.Close();
+		}
+
+	test.Next(_L("Test RThread::Create() - invalid stack size"));
+		{
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, -1 , NULL);
+		createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
+		
+		RThread threadPanic;
+		test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, 
+															KMinHeapSize,  (TAny*) &createInfo));
+		test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdStackSizeNegative));
+		}
+
+	test.Next(_L("Test RThread::Create() - invalid min heap size"));
+		{
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize , NULL);
+		createInfo.SetCreateHeap(-1, KMinHeapSize);
+		
+		RThread threadPanic;
+		test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, 
+															KMinHeapSize,  (TAny*) &createInfo));
+
+		test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdHeapMinTooSmall));
+		}
+
+	test.Next(_L("Test RThread::Create() - invalid max heap size"));
+		{
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize , NULL);
+		createInfo.SetCreateHeap(KMinHeapSize, -1);
+		
+		RThread threadPanic;
+		test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, 
+															KMinHeapSize,  (TAny*) &createInfo));
+
+		test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdHeapMaxLessThanMin));
+		}
+
+	test.Next(_L("Test RThread::Create() - min heap size > max heap size"));
+		{
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize , NULL);
+		createInfo.SetCreateHeap(KMinHeapSize << 1, KMinHeapSize);
+		
+		RThread threadPanic;
+		test_KErrNone(threadPanic.Create(_L("Panic UserHeap"), PanicThreadCreate, KDefaultStackSize, KMinHeapSize, 
+															KMinHeapSize,  (TAny*) &createInfo));
+
+		test_KErrNone(TestThreadExit(threadPanic, EExitPanic, EThrdHeapMaxLessThanMin));
+		}
+
+	test.Next(_L("Test TThreadCreateInfo::SetUseHeap() "));
+		{
+		RThread thread;
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL);
+		createInfo.SetUseHeap(NULL);
+		r = thread.Create(createInfo);
+		test_KErrNone(r);
+		test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone));
+		thread.Close();
+		}
+
+	test.Next(_L("Test TThreadCreateInfo::SetOwner(EOwnerProcess) "));
+		{
+		RThread thread;
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL);
+		createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
+		createInfo.SetOwner(EOwnerProcess);
+		r = thread.Create(createInfo);
+		test_KErrNone(r);
+		test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone));
+		thread.Close();
+		}
+
+
+	test.Next(_L("Test TThreadCreateInfo::SetOwner(EOwnerThread) "));
+		{
+		RThread thread;
+		TThreadCreateInfo createInfo(KGlobalThreadName, DummyFunction, KDefaultStackSize, NULL);
+		createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
+		createInfo.SetOwner(EOwnerThread);
+		r = thread.Create(createInfo);
+		test_KErrNone(r);
+		test_KErrNone(TestThreadExit(thread, EExitKill, KErrNone));
+		thread.Close();
+		}
+
+
+
+	gSem1.CreateLocal(0);
+	gSem2.CreateLocal(0);
+	test.Next(_L("Test Thread paging (New Heap)"));
+		{		
+		TBool aPaged = gProcessPaged;
+		SThreadPagedInfo pagedInfo;
+		test.Printf(_L("Testing gProcessPaged: aPaged = %x\n"), aPaged);
+		TThreadCreateInfo createInfo(	KGlobalThreadName, ThreadFunc, KDefaultStackSize,
+										(TAny*)&pagedInfo);
+		createInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
+		
+		test_KErrNone(CheckHeapStackPaged(createInfo, EUnspecified, pagedInfo));
+		test_KErrNone(CheckHeapStackPaged(createInfo, EPaged, pagedInfo));
+		test_KErrNone(CheckHeapStackPaged(createInfo, EUnpaged, pagedInfo));
+		}
+
+
+	test.Next(_L("Test RThread::Create() (Existing Heap)"));
+		{
+		SThreadPagedInfo pagedInfo;
+		TThreadCreateInfo createInfo(	KGlobalThreadName, ThreadFunc, KDefaultStackSize, 
+										(TAny*)&pagedInfo);
+		createInfo.SetUseHeap(NULL);
+		
+		test_KErrNone(CheckHeapStackPaged(createInfo, EUnspecified, pagedInfo, ETrue));
+		test_KErrNone(CheckHeapStackPaged(createInfo, EPaged, pagedInfo, ETrue));
+		test_KErrNone(CheckHeapStackPaged(createInfo, EUnpaged, pagedInfo, ETrue));
+		}
+	test.End();
+	}
+
+
+
+TInt TestingTThreadCreate()
+	{
+	test.Printf(_L("Test TThreadCreateInfo\n"));
+	TestThreadCreate();
+
+	return 0;
+	}