diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/demandpaging/t_threadcreate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/demandpaging/t_threadcreate.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -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 +#include +#include +#include +#include +#include +#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; + }