--- /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;
+ }