--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/demandpaging/loader/t_pageldrtst.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,5143 @@
+// Copyright (c) 2006-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:
+// f32test\demandpaging\loader\t_pageldrtst.cpp
+// Demand Paging Loader Stress Tests
+// Demand Paging Loader stress tests attempt to cause as much paging as possible
+// whilst putting the system various types of load.
+// t_pageldrtst.exe is the root of the tests, it in turn will start copies of
+// itself stored in various types of media (t_pageldrtst_rom.exe for example).
+// It also loads DLLs from various media, each DLL containing simple functions
+// that are aligned on page boundaries, so each function call is likely to
+// cause a page fault.
+// Usage:
+// t_pageldrtst and t_pageldrtst_rom
+// Common command lines:
+// t_pageldrtst - run the auto test suite
+// t_pageldrtst lowmem - run the low memory tests
+// t_pageldrtst chunks - run the chunk tests
+// t_pageldrtst chunks+ - run the chunk tests (same as used in autotest)
+// t_pageldrtst echunks - run the really stressful chunk tests
+// t_pageldrtst auto debug - run the autotest but with debug output to the serial port
+// t_pageldrtst d_exc - run the d_exc tests
+// Arguments:
+// single - run the tests in a single thread
+// multiple <numThreads> - run the tests in multiple threads where <numThreads>
+// auto - dummy param to trick the tests into running the auto test suite with extra params
+// fullauto - param to make the tests perform the full automatic stress test
+// interleave - force thread interleaving
+// prio - each thread reschedules in between each function call, causes lots of context changes
+// media - perform media access during the tests, very stressful
+// mmc - only use the mmc media for media access to test file caching
+// min - min cache size in pages
+// max - max cache size in pages
+// chunks - simple chunk stress tests
+// chunks+ - the chunk auto tests
+// echunks - extremem chunks tests
+// nochunkdata - don't check the integrity of the data in the chunks
+// lowmem - low memory tests
+// dll - only load dll's
+// exe - only start exe's (t_pagestress)
+// self - only start copies of self (t_pageldrtst from various media)
+// complete - dll, exe and self.
+// rom - only load from ROM
+// base - only load the base DLL and exe's (from code)
+// mixed - rom and base.
+// all_media - load dlls and exes from all media
+// debug - switch on debugging information
+// silent - no output to the screen or serial port
+// noclean - don't delete copied files on exit
+// d_exc - run the d_exc tests
+// global - load dlls once globally
+// thread - load dlls once per thread
+// func - load dlls in the test function (default and most stressful)
+// forward - patern in which to execute function calls
+// backward - patern in which to execute function calls
+// random - patern in which to execute function calls
+// all - patern in which to execute function calls (forward, backward and random)
+// inst - for debugging a parameter passed to a spawned exe to give it an id.
+// iters <count> - the number of times to loop (a '-' means run forever)
+// reaper - test the reaper.
+// btrace - test the btrace code.
+// defrag - test the ram defrag code.
+// stressfree - set the page cache to stress free size and run tests.
+// t_pageldrtst causes a large ammount of paging by repeatedly calling
+// functions from multiple DLLs which include 64 functions which have
+// been aligned on page boundaries from multiple threads, whilst causing
+// background paging by spawning copies of itself and t_pagestress.
+// The test also endeavours to stress the loader by loading and unloading
+// DLLs from multiple threads from various types of media at the same
+// time as stressing the media, testing chunks, the reaper and changing
+// thread priorities.
+// 002 Load thrashing, test rapid loading and unloading of DLLs from
+// multiple threads (DEF100158)
+// 003 Multiple threads loading DLLs in random pattern
+// 004 Multiple threads loading EXE, SELF and DLLs in random pattern with
+// all media, loaded in thread with prio change
+// 005 Multiple threads loading EXE, SELF and DLLs in random pattern with
+// all media, loaded globally with prio change
+// 006 Multiple threads loading EXE, SELF and DLLs in random pattern with
+// all media, loaded in func with process interleaving
+// 007 Multiple threads loading EXE, SELF and DLLs in random pattern with
+// all media, loaded in func with process interleaving, prio change
+// and media access
+// 008 Low Memory setup test
+// 009 Low Memory, Multiple threads loading EXE, SELF and DLLs in random
+// pattern, loaded in func.
+// 010 Low Memory setup test
+// 011 Low Memory, Multiple threads loading EXE, SELF and DLLs in random
+// pattern, loaded in func with process interleaving,
+// prio change and media access
+// 012 Close test driver
+// 013 Chunk tests, Multiple threads loading EXE, SELF and DLLs in random
+// pattern with ROM / ROFS media, loaded in func with prio change
+// 014 Reaper tests with Multiple threads loading EXE, SELF and DLLs in random
+// pattern with all media
+// 015 Reaper tests with Multiple threads loading EXE, SELF and DLLs in random
+// pattern with all media, prio change and process interleaving
+// 016 d_exc check test
+//
+//
+
+//! @SYMTestCaseID KBASE-T_PAGELDRTST-0326
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1110
+//! @SYMTestCaseDesc Demand Paging Loader Stress Tests
+//! @SYMTestActions 001 Demand Paging loader stress tests...
+//! @SYMTestExpectedResults All tests should pass.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+
+#include <e32test.h>
+#include <e32rom.h>
+#include <u32hal.h>
+#include <f32file.h>
+#include <f32dbg.h>
+#include <e32msgqueue.h>
+#include <e32math.h>
+#include <e32btrace.h>
+#include <d32btrace.h>
+#include <hal.h>
+
+#include "t_hash.h"
+#include "paging_info.h"
+
+#ifndef TEST_AUTOTEST
+#define TEST_RUN_REAPERTEST
+#define TEST_RUN_LOWMEMTEST
+#define TEST_RUN_DEFRAGTEST
+#define TEST_RUN_D_EXCTEST
+#define TEST_RUN_CHUNKTEST
+#define TEST_RUN_AUTOTEST
+RTest test(_L("T_PAGELDRTST"));
+#else
+#ifdef TEST_RUN_REAPERTEST
+RTest test(_L("T_PAGELDRTST_REAPER"));
+#endif
+#ifdef TEST_RUN_LOWMEMTEST
+RTest test(_L("T_PAGELDRTST_LOWMEM"));
+#endif
+#ifdef TEST_RUN_DEFRAGTEST
+RTest test(_L("T_PAGELDRTST_DEFRAG"));
+#endif
+#ifdef TEST_RUN_D_EXCTEST
+RTest test(_L("T_PAGELDRTST_D_EXC"));
+#endif
+#ifdef TEST_RUN_CHUNKTEST
+RTest test(_L("T_PAGELDRTST_CHUNK"));
+#endif
+#ifdef TEST_RUN_AUTOTEST
+RTest test(_L("T_PAGELDRTST_AUTO"));
+#endif
+#endif //TEST_AUTOTEST
+
+const TInt KMessageBufSize = 80;
+typedef TBuf<KMessageBufSize> TMessageBuf;
+
+//#define TEST_SHORT_TEST
+//#define TEST_THRASHING_TEST
+//#define TEST_ADD_FAT_MEDIA
+#define TEST_DONT_RESET_STATS
+#define TEST_MINIMAL_STATS
+//#define TEST_KERN_HEAP
+#define TEST_ADD_FRAGD_MEDIA
+#ifdef TEST_ADD_FRAGD_MEDIA
+#endif
+
+#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
+//#define WANT_FS_CACHE_STATS
+#endif
+
+#ifdef __X86__
+#define TEST_ON_UNPAGED
+#define TEST_NO_DEXC_IN_AUTO
+#endif
+
+
+#include "t_pagestress.h"
+#include "t_pageldrtstdll.h"
+
+#include "t_ramstress.h"
+
+TBool TestDebug = EFalse;
+TBool TestSilent = EFalse;
+TBool TestExit = EFalse;
+#define TEST_EXE 0x01
+#define TEST_DLL 0x02
+#define TEST_SELF 0x04
+#define TEST_EXE_SELF (TEST_EXE | TEST_SELF)
+#define TEST_EXE_SELF_DLL (TEST_EXE | TEST_SELF | TEST_DLL)
+TInt TestLoading = TEST_EXE_SELF_DLL;
+
+#define TEST_MEDIA_BASE (1 << KTestMediaBase)
+#define TEST_MEDIA_ROM (1 << KTestMediaRom)
+#define TEST_MEDIA_ROFS (1 << KTestMediaRofs)
+#define TEST_MEDIA_EXT (1 << KTestMediaExt)
+#define TEST_MEDIA_FAT (1 << KTestMediaFat)
+#define TEST_MEDIA_MMC (1 << KTestMediaMmc)
+#define TEST_MEDIA_ROM_BASE (TEST_MEDIA_ROM | TEST_MEDIA_BASE)
+#define TEST_MEDIA_ALL (TEST_MEDIA_ROM | TEST_MEDIA_BASE | TEST_MEDIA_ROFS | TEST_MEDIA_EXT | TEST_MEDIA_MMC)
+
+typedef enum
+{
+ KTestMediaBase = 0,
+ KTestMediaRom,
+ KTestMediaExt,
+ KTestMediaRofs,
+#ifdef TEST_ADD_FAT_MEDIA
+ KTestMediaFat, // this is the last one that is always present.
+#endif
+ KTestMediaMmc,
+#ifdef TEST_ADD_FRAGD_MEDIA
+ KTestMediaNandFrag,
+ KTestMediaMmcFrag,
+#endif
+ KTestMediaCOUNT,
+}ETestMediaType;
+#ifdef TEST_ADD_FAT_MEDIA
+#define TEST_MEDIA_COUNT_HACK (KTestMediaFat + 1)
+#else
+#define TEST_MEDIA_COUNT_HACK (KTestMediaRofs + 1)
+#endif
+
+typedef enum
+{
+ KTestMediaAccessNone = 0,
+ KTestMediaAccessBasic,
+ KTestMediaAccessMultipleThreads,
+ KTestMediaAccessMultiplePattern,
+ KTestMediaAccessMixed,
+ KTestMediaAccessCOUNT,
+}ETestMediaAccess;
+
+TInt TestWhichMedia = TEST_MEDIA_ROM_BASE;
+TInt DriveNumber=-1; // Parameter - Which drive? -1 = autodetect.
+TBool TestSingle = EFalse;
+TBool TestMultiple = EFalse;
+TInt TestMaxLoops = 20;
+#define TEST_2MEDIA_THREADS 20
+#define TEST_ALLMEDIA_THREADS 20
+TInt TestMultipleThreadCount = TEST_2MEDIA_THREADS;
+TInt TestInstanceId = 0;
+TBool TestWeAreTheTestBase = EFalse;
+TBool TestBootedFromMmc = EFalse;
+TBool TestOnlyFromMmc = EFalse;
+TBool TestD_Exc = EFalse;
+TBool TestNoClean = EFalse;
+TBool TestFullAutoTest = EFalse;
+#define TEST_DLL_GLOBAL 0x01
+#define TEST_DLL_THREAD 0x02
+#define TEST_DLL_FUNC 0x04
+TInt TestLoadDllHow = TEST_DLL_FUNC;
+TBool TestIsAutomated = EFalse;
+
+#define TEST_INTERLEAVE_PRIO EPriorityMore//EPriorityRealTime //23 // KNandThreadPriority - 1
+TBool TestInterleave = EFalse;
+TFileName TestNameBuffer;
+TBool TestPrioChange = EFalse;
+
+volatile TBool TestStopMedia = EFalse;
+ETestMediaAccess TestMediaAccess = KTestMediaAccessNone;
+#define TEST_NUM_FILES 5
+
+RSemaphore TestMultiSem;
+RMsgQueue<TMessageBuf> TestMsgQueue;
+
+#define TEST_LM_NUM_FREE 0
+#define TEST_LM_BLOCKSIZE 1
+#define TEST_LM_BLOCKS_FREE 4
+TBool TestLowMem = EFalse;
+TBool TestingLowMem = EFalse;
+RPageStressTestLdd PagestressLdd;
+RRamStressTestLdd RamstressLdd;
+
+TBool TestBtrace = EFalse;
+TBool TestDefrag = EFalse;
+TBool TestChunks = EFalse;
+TBool TestChunksPlus = EFalse;
+TBool TestExtremeChunks = EFalse;
+TBool TestChunkData = ETrue;
+TBool TestingChunks = EFalse;
+volatile TBool TestDefragTestEnd = EFalse;
+TBool TestingDefrag = EFalse;
+volatile TBool TestThreadsExit = EFalse;
+TInt TestPageSize = 4096;
+RChunk TestChunk;
+TInt TestCommitEnd = 0;
+TUint8* TestChunkBase = NULL;
+#define TEST_NUM_PAGES 64
+#define TEST_NUM_CHUNK_PAGES (TEST_NUM_PAGES * 2)
+TBool TestChunkPageState[TEST_NUM_CHUNK_PAGES];
+
+TBool TestReaper = EFalse;
+TBool TestingReaper = EFalse;
+TBool TestingReaperCleaningFiles = EFalse;
+#define TEST_REAPER_ITERS 20
+#define TEST_DOT_PERIOD 30
+TBool TestStressFree = EFalse;
+TInt TestMinCacheSize = 64 * 4096;
+TInt TestMaxCacheSize = 128 * 4096;
+TBool TestIsDemandPaged = ETrue;
+#define TEST_MAX_ZONE_THREADS 8
+TUint TestZoneCount = 0;
+TInt TickPeriod = 15625;
+
+#define TEST_NONE 0x0
+#define TEST_THRASH 0x1
+#define TEST_FORWARD 0x2
+#define TEST_BACKWARD 0x4
+#define TEST_RANDOM 0x8
+#define TEST_ALL (TEST_RANDOM | TEST_BACKWARD | TEST_FORWARD)
+TUint32 TestWhichTests = TEST_ALL;
+_LIT(KRomPath, "z:\\sys\\bin\\");
+_LIT(KMmcDefaultPath, "d:\\sys\\bin\\");
+
+#define EXISTS(__val) ((__val == KErrNone) ? &KFileExists : &KFileMissing)
+_LIT(KSysHash,"?:\\Sys\\Hash\\");
+_LIT(KTestBlank, "");
+_LIT(KFileExists, "Exists");
+_LIT(KFileMissing, "Missing");
+_LIT(KMultipleTest, "Multiple");
+_LIT(KSingleTest, "Single ");
+_LIT(KTestExe, "Exe ");
+_LIT(KTestDll, "Dll ");
+_LIT(KTestSelf, "Self ");
+_LIT(KTestBase, "Base ");
+_LIT(KTestRom, "ROM ");
+_LIT(KTestAll, "All ");
+_LIT(KTestGlobal, "Global");
+_LIT(KTestThread, "Thread");
+_LIT(KTestFunc, "Func");
+_LIT(KTestInter, "Interleave ");
+_LIT(KTestPrio, "Prio ");
+_LIT(KTestMedia, "Media ");
+_LIT(KTestLowMem, "LowMem ");
+_LIT(KTestChunking, "Chunks ");
+_LIT(KTestEChunking, "EChunks ");
+_LIT(KTestChunkingPlus, "Chunks+ ");
+_LIT(KTestReaper, "Reaper ");
+_LIT(KTestThrash, "Thrash ");
+_LIT(KTestForward, "Forward ");
+_LIT(KTestBackward, "Backward ");
+_LIT(KTestRandom, "Random ");
+
+typedef struct
+ {
+ TBool testFullAutoOnly;
+ TInt testLoading;
+ TInt testWhichMedia;
+ TBool testMultiple;
+ TInt testMaxLoops;
+ TInt testMultipleThreadCount;
+ TBool testLoadDllHow;
+ TBool testInterleave;
+ TBool testPrioChange;
+ ETestMediaAccess testMediaAccess;
+ TUint32 testWhichTests;
+ TBool testLowMem;
+ TInt testFreeRam;
+ }TTheTests;
+
+typedef struct
+ {
+ TInt ok;
+ TInt fail;
+ }TChunkTestPair;
+
+typedef struct
+ {
+ TChunkTestPair lock;
+ TChunkTestPair unlock;
+ TChunkTestPair decommit;
+ TChunkTestPair commit;
+ TChunkTestPair check;
+ }
+TChunkTestStats;
+
+TChunkTestStats TestChunkStats[TEST_NUM_CHUNK_PAGES];
+
+
+TPtrC TestPsExeNames[KTestMediaCOUNT] = { _L("t_pagestress.exe"),
+ _L("t_pagestress_rom.exe"),
+ _L("t_pagestress_ext.exe"),
+ _L("t_pagestress_rofs.exe"),
+#ifdef TEST_ADD_FAT_MEDIA
+ _L("t_pagestress_fat.exe"),
+#endif
+ _L("t_pagestress_mmc.exe"),
+#ifdef TEST_ADD_FRAGD_MEDIA
+ _L("t_pagestress_nfr.exe"),
+ _L("t_pagestress_mfr.exe"),
+#endif
+ };
+
+TPtrC TestPlExeNames[KTestMediaCOUNT] = { _L("t_pageldrtst.exe"),
+ _L("t_pageldrtst_rom.exe"),
+ _L("t_pageldrtst_ext.exe"),
+ _L("t_pageldrtst_rofs.exe"),
+#ifdef TEST_ADD_FAT_MEDIA
+ _L("t_pageldrtst_fat.exe"),
+#endif
+ _L("t_pageldrtst_mmc.exe"),
+#ifdef TEST_ADD_FRAGD_MEDIA
+ _L("t_pageldrtst_nfr.exe"),
+ _L("t_pageldrtst_mfr.exe"),
+#endif
+ };
+
+_LIT(KDllBaseName, "t_pageldrtst");
+
+TPtrC TestPlExtNames[KTestMediaCOUNT] = { _L(".dll"),
+ _L("_rom.dll"),
+ _L("_ext.dll"),
+ _L("_rofs.dll"),
+#ifdef TEST_ADD_FAT_MEDIA
+ _L("_fat.dll"),
+#endif
+ _L("_mmc.dll"),
+#ifdef TEST_ADD_FRAGD_MEDIA
+ _L("_nfr.dll"),
+ _L("_mfr.dll"),
+#endif
+ };
+
+
+TBool TestDllExesExist[KTestMediaCOUNT] = { EFalse,
+ EFalse,
+ EFalse,
+ EFalse,
+#ifdef TEST_ADD_FAT_MEDIA
+ EFalse,
+#endif
+ EFalse,
+#ifdef TEST_ADD_FRAGD_MEDIA
+ EFalse,
+ EFalse,
+#endif
+ };
+#define DBGS_PRINT(__args)\
+ if (!TestSilent) test.Printf __args;
+
+#define DBGD_PRINT(__args)\
+ if (TestDebug) test.Printf __args;
+
+void SendDebugMessage(RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ for (;;)
+ {
+ aTheSem->Wait();
+ TInt r = aMsgQueue->Send(*aBuffer);
+ aTheSem->Signal();
+ if (r != KErrOverflow)
+ return;
+ User::After(0);
+ }
+ }
+
+#define DEBUG_PRINT(__args)\
+if (!TestSilent) \
+ {\
+ if (aMsgQueue && aBuffer && aTheSem)\
+ {\
+ aBuffer->Zero();\
+ aBuffer->Format __args ;\
+ SendDebugMessage(aMsgQueue, aBuffer, aTheSem);\
+ }\
+ else\
+ {\
+ test.Printf __args ;\
+ }\
+ }
+
+#define RUNTEST(__test, __error)\
+ if (!TestSilent)\
+ test(__test == __error);\
+ else\
+ __test;
+
+#define RUNTEST1(__test)\
+ if (!TestSilent)\
+ test(__test);
+
+
+#define DEBUG_PRINT1(__args)\
+if (TestDebug)\
+ {\
+ DEBUG_PRINT(__args)\
+ }
+
+#define DOTEST(__operation, __condition)\
+ if (aLowMem) \
+ {\
+ __operation;\
+ while (!__condition)\
+ {\
+ DBGD_PRINT((_L("Releasing some memory on line %d\n"), __LINE__));\
+ if (pTheSem)\
+ pTheSem->Wait();\
+ PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
+ if (pTheSem)\
+ pTheSem->Signal();\
+ __operation;\
+ }\
+ RUNTEST1(__condition);\
+ }\
+ else\
+ {\
+ __operation;\
+ RUNTEST1(__condition);\
+ }
+
+#define DOTEST1(__var, __func, __ok, __fail)\
+ if (aLowMem) \
+ {\
+ __var = __func;\
+ while (__var == __fail)\
+ {\
+ DBGD_PRINT((_L("Releasing some memory on line %d\n"), __LINE__));\
+ if (pTheSem)\
+ pTheSem->Wait();\
+ PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
+ if (pTheSem)\
+ pTheSem->Signal();\
+ __var = __func;\
+ }\
+ if (__var != __ok)\
+ DBGS_PRINT((_L("Failing on line %d with error %d\n"), __LINE__, __var));\
+ RUNTEST1(__var == __ok);\
+ }\
+ else\
+ {\
+ __var = __func;\
+ RUNTEST1(__var == __ok);\
+ }
+
+#define DOLOADALLOC(__numDlls, __pTheLibs, __theSem)\
+ if (TestingLowMem)\
+ {\
+ __pTheLibs = (PageLdrRLibrary *)User::AllocZ(sizeof(PageLdrRLibrary) * __numDlls);\
+ while (__pTheLibs == NULL)\
+ {\
+ DEBUG_PRINT1((_L("Releasing some memory for alloc on line %d\n"), __LINE__));\
+ if (__theSem)\
+ __theSem->Wait();\
+ PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
+ if (__theSem)\
+ __theSem->Signal();\
+ __pTheLibs = (PageLdrRLibrary *)User::AllocZ(sizeof(PageLdrRLibrary) * __numDlls);\
+ }\
+ }\
+ else\
+ {\
+ __pTheLibs = (PageLdrRLibrary *)User::AllocZ(sizeof(PageLdrRLibrary) * __numDlls);\
+ if (__pTheLibs == NULL)\
+ return KErrGeneral;\
+ }
+
+#define TEST_NEXT(__args) \
+ if (!TestSilent)\
+ test.Next __args;
+
+void DoStats();
+void CheckFilePresence(TBool aDoFileCopy);
+void CleanupFiles(TBool silent);
+typedef TInt (*TCallFunction)(TUint32 funcIndex, TInt param1, TInt param2);
+
+class PageLdrRLibrary : public RLibrary
+ {
+public:
+ TInt TestLoadLibrary(const TDesC& aFileName, TInt aThreadIndex, RMsgQueue<TMessageBuf> *aMsgQueue, TMessageBuf *aBuffer, RSemaphore *aTheSem);
+ TInt CloseLibrary();
+
+public:
+ TBool iInUse;
+ TUint32 iFuncCount;
+ TLibraryFunction iInitFunc;
+ TLibraryFunction iFunctionCountFunc;
+ TCallFunction iCallFunctionFunc;
+ TLibraryFunction iSetCloseFunc;
+ };
+
+TInt PageLdrRLibrary::CloseLibrary()
+ {
+ if (iInUse)
+ {
+ if (iSetCloseFunc)
+ (iSetCloseFunc)();
+ Close();
+ iFuncCount = 0;
+ iInitFunc = NULL;
+ iFunctionCountFunc = NULL;
+ iCallFunctionFunc = NULL;
+ iSetCloseFunc = NULL;
+ iInUse = EFalse;
+ }
+ return KErrNone;
+ }
+
+PageLdrRLibrary theGlobalLibs[PAGELDRTST_MAX_DLLS * KTestMediaCOUNT];
+
+////////////////////////////////////////////////////////////
+// Template functions encapsulating ControlIo magic
+//
+GLDEF_D template <class C>
+GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c)
+{
+ TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C));
+
+ TInt r = fs.ControlIo(drv, fkn, ptrC);
+
+ return r;
+}
+
+//
+// FreeRam
+//
+// Get available free ram.
+//
+
+TInt FreeRam()
+ {
+ // wait for any async cleanup in the supervisor to finish first...
+ UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
+
+ TMemoryInfoV1Buf meminfo;
+ TInt r=UserHal::MemoryInfo(meminfo);
+ test (r==KErrNone);
+ return meminfo().iFreeRamInBytes;
+ }
+
+//
+// FindFsNANDDrive
+//
+// Find the NAND drive
+//
+
+static TInt FindFsNANDDrive(RFs& aFs)
+ {
+ TDriveList driveList;
+ TDriveInfo driveInfo;
+ TInt r=aFs.DriveList(driveList);
+ if (r == KErrNone)
+ {
+ for (TInt drvNum= (DriveNumber<0)?0:DriveNumber; drvNum<KMaxDrives; ++drvNum)
+ {
+ if(!driveList[drvNum])
+ continue; //-- skip unexisting drive
+
+ if (aFs.Drive(driveInfo, drvNum) == KErrNone)
+ {
+ if(driveInfo.iMediaAtt&KMediaAttPageable)
+ {
+ TBool readOnly = driveInfo.iMediaAtt & KMediaAttWriteProtected; // skip ROFS partitions
+ if(!readOnly && (driveInfo.iType != EMediaHardDisk))
+ {
+ if ((drvNum==DriveNumber) || (DriveNumber<0)) // only test if running on this drive
+ {
+ return (drvNum);
+ }
+ }
+ }
+ }
+ }
+ }
+ return (-1);
+ }
+
+//
+// FindMMCDriveNumber
+//
+// Find the first read write drive.
+//
+
+TInt FindMMCDriveNumber(RFs& aFs)
+ {
+ TDriveInfo driveInfo;
+ for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
+ {
+ TInt r = aFs.Drive(driveInfo, drvNum);
+ if (r >= 0)
+ {
+ if (driveInfo.iType == EMediaHardDisk)
+ return (drvNum);
+ }
+ }
+ return -1;
+ }
+
+
+//
+// PageLdrRLibrary::TestLoadLibrary
+//
+// Load a library and initialise information about that library
+//
+
+TInt PageLdrRLibrary::TestLoadLibrary(const TDesC& aFileName,
+ TInt aThreadIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ TInt retVal = KErrNone;
+ if (TestingLowMem)
+ {
+ TBool whinged = EFalse;
+ TInt initialFreeRam = 0;
+ TInt freeRam = 0;
+
+ while (1)
+ {
+ initialFreeRam = FreeRam();
+ retVal = Load(aFileName);
+ freeRam = FreeRam();
+ if (retVal == KErrNoMemory)
+ {
+ if (!whinged && (freeRam > (4 * TestPageSize)))
+ {
+ whinged = ETrue;
+ DEBUG_PRINT1((_L("Load() %d pages %S\n"), (freeRam / TestPageSize), &aFileName));
+ if (TestIsDemandPaged)
+ {
+ SVMCacheInfo tempPages;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+
+ DEBUG_PRINT1((_L("DPC : min %d max %d curr %d\n"),
+ tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize));
+ DEBUG_PRINT1((_L(" : maxFree %d freeRam %d\n"),
+ tempPages.iMaxFreeSize, FreeRam()));
+ }
+ }
+ DEBUG_PRINT1((_L("Load() releasing some memory for %S (%d)\n"), &aFileName, retVal));
+ if (aTheSem)
+ aTheSem->Wait();
+ PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);
+ if (aTheSem)
+ aTheSem->Signal();
+ }
+ else
+ {
+ if (whinged)
+ {
+ DEBUG_PRINT((_L("Load() Ok %d pages (%d) %S\n"), ((initialFreeRam - freeRam) / TestPageSize), (freeRam / TestPageSize), &aFileName));
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT1((_L("Loading %S (%d)\n"), &aFileName, aThreadIndex));
+ retVal = Load(aFileName);
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT1((_L("Load failed %S (%d)\n"), &aFileName, aThreadIndex));
+ if (TestingReaper )
+ {
+ TInt tempIndex = 0;
+ TBool whinged = EFalse;
+ while ( ( (retVal == KErrNotFound)
+ || (retVal == KErrPermissionDenied)
+ || (retVal == KErrCorrupt)
+ || (retVal == KErrInUse))
+ && ( TestingReaperCleaningFiles
+ || (tempIndex < TEST_REAPER_ITERS)))
+ {
+ User::After(2000000);
+ if (!whinged)
+ {
+ DEBUG_PRINT((_L("Load() retrying load for %S (%d)\n"), &aFileName, retVal));
+ whinged = ETrue;
+ }
+ retVal = Load(aFileName);
+ if (!TestingReaperCleaningFiles)
+ {
+ tempIndex ++;
+ }
+ }
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Load() failing for %S (%d) idx %d\n"), &aFileName, retVal, tempIndex));
+ }
+ }
+ else if (TestingDefrag)
+ {
+ TInt tempIndex = 0;
+ TBool whinged = EFalse;
+ while ((retVal == KErrGeneral) && (tempIndex < 10))
+ {
+ User::After(20000);
+ if (!whinged)
+ {
+ DEBUG_PRINT((_L("Load() retrying load for %S (%d)\n"), &aFileName, retVal));
+ whinged = ETrue;
+ }
+ retVal = Load(aFileName);
+ tempIndex ++;
+ }
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Load() failing for %S (%d) idx %d\n"), &aFileName, retVal, tempIndex));
+ }
+ }
+ }
+ }
+ DEBUG_PRINT1((_L("Loaded %S (%d)\n"), &aFileName, aThreadIndex));
+ if (retVal == KErrNone)
+ {
+ iInUse = ETrue;
+ iInitFunc = Lookup(PAGELDRTST_FUNC_Init);
+ iFunctionCountFunc = Lookup(PAGELDRTST_FUNC_FunctionCount);
+ iCallFunctionFunc = (TCallFunction)Lookup(PAGELDRTST_FUNC_CallFunction);
+ iSetCloseFunc = Lookup(PAGELDRTST_FUNC_SetClose);
+ if ( (iInitFunc != NULL)
+ && (iFunctionCountFunc != NULL)
+ && (iCallFunctionFunc != NULL)
+ && (iSetCloseFunc != NULL))
+ {
+ retVal = (iInitFunc)();
+ if (retVal == KErrNone)
+ {
+ iFuncCount = (iFunctionCountFunc)();
+ if (iFuncCount != 0)
+ {
+ DEBUG_PRINT1((_L("Loaded ok %S (%d)\n"), &aFileName, aThreadIndex));
+ return KErrNone;
+ }
+ retVal = KErrGeneral;
+ DEBUG_PRINT((_L("!!! bad count %S (%d)\n"), &aFileName, aThreadIndex));
+ }
+ else
+ {
+ DEBUG_PRINT((_L("!!! init failed %S (%d)\n"), &aFileName, aThreadIndex));
+ retVal = KErrGeneral;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("!!! missing %S (%d)\n"), &aFileName, aThreadIndex));
+ retVal = KErrGeneral;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Load() failed %S %d\n"), &aFileName, retVal));
+#ifdef WANT_FS_CACHE_STATS
+ RFs fs;
+ if (KErrNone != fs.Connect())
+ {
+ DEBUG_PRINT(_L("TestLoadLibrary : Can't connect to the FS\n"));
+ }
+ else
+ {
+ TFileCacheStats stats1;
+ TInt drvNum = FindMMCDriveNumber(fs);
+ controlIo(fs,drvNum, KControlIoFileCacheStats, stats1);
+
+ DEBUG_PRINT((_L("FSC: drv %d %c free %d used %d locked %d\n"),
+ drvNum, 'a' + drvNum,
+ stats1.iFreeCount,
+ stats1.iUsedCount,
+ stats1.iLockedSegmentCount));
+ DEBUG_PRINT((_L(" : alloc %d lock %d closed %d\n"),
+ stats1.iAllocatedSegmentCount,
+ stats1.iFileCount,
+ stats1.iFilesOnClosedQueue));
+ fs.Close();
+ }
+#endif //WANT_FS_CACHE_STATS
+
+ if (TestIsDemandPaged)
+ {
+ SVMCacheInfo tempPages;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+
+ DEBUG_PRINT((_L("DPC : min %d max %d curr %d\n"),
+ tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize));
+ DEBUG_PRINT((_L(" : maxFree %d freeRam %d\n"),
+ tempPages.iMaxFreeSize, FreeRam()));
+ }
+ }
+ return retVal;
+ }
+
+//
+// GetNumDlls
+//
+// Work out how many Dlls we will play with
+//
+TInt GetNumDlls()
+ {
+ TInt maxDllIndex;
+
+ switch (TestWhichMedia)
+ {
+ default:
+ case TEST_MEDIA_BASE:
+ case TEST_MEDIA_ROM:
+ maxDllIndex = PAGELDRTST_MAX_DLLS;
+ break;
+
+ case TEST_MEDIA_ROM_BASE:
+ maxDllIndex = PAGELDRTST_MAX_DLLS * 2;
+ break;
+
+ case TEST_MEDIA_ALL:
+ maxDllIndex = PAGELDRTST_MAX_DLLS * KTestMediaCOUNT;
+ break;
+ }
+ return maxDllIndex;
+ }
+
+//
+// LoadTheLibs
+//
+// Open DLLs for use in the tests.
+//
+
+TInt LoadTheLibs(PageLdrRLibrary *aTheLibs,
+ TInt aLibCount,
+ TInt aThreadIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ TBuf<128> nameBuffer;
+ TInt dllIndex = 0;
+ TInt realDllIndex = 0;
+ TInt dllOffset = -1;
+ TInt testWhich;
+ RThread thisThread;
+
+ memset(aTheLibs, 0, sizeof(*aTheLibs) * aLibCount);
+ for (dllIndex = 0; dllIndex < aLibCount; dllIndex ++)
+ {
+ realDllIndex = (dllIndex + aThreadIndex) % PAGELDRTST_MAX_DLLS;
+// realDllIndex = (dllIndex) % PAGELDRTST_MAX_DLLS;
+ if (realDllIndex == 0)
+ dllOffset ++;
+
+ if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ALL)
+ testWhich = (dllIndex + dllOffset) % KTestMediaCOUNT;
+ else if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ROM_BASE)
+ testWhich = ((dllIndex + dllOffset) & 1) ? KTestMediaBase : KTestMediaRom;
+ else if (TestWhichMedia & TEST_MEDIA_BASE )
+ testWhich = KTestMediaBase;
+ else
+ testWhich = KTestMediaRom;
+
+ if (!TestDllExesExist[testWhich])
+ testWhich = KTestMediaBase;
+
+ nameBuffer.Format(_L("%S%d%S"), &KDllBaseName, realDllIndex, &TestPlExtNames[testWhich]);
+
+ DEBUG_PRINT1((_L("LoadTheLibs[%02d] - loading %S\n"), aThreadIndex, &nameBuffer));
+ TInt theErr = aTheLibs[dllIndex].TestLoadLibrary(nameBuffer, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
+ if (theErr != KErrNone)
+ {
+ DEBUG_PRINT((_L("LoadTheLibs[%02d] - fail %S %d\n"), aThreadIndex, &nameBuffer, theErr));
+ return KErrGeneral;
+ }
+ else
+ {
+ DEBUG_PRINT1((_L("LoadTheLibs[%02d] - loaded %S OK\n"), aThreadIndex, &nameBuffer));
+ }
+ if (TestThreadsExit)
+ {
+ DEBUG_PRINT((_L("LoadTheLibs[%02d] - cancelled\n"), aThreadIndex));
+ return KErrCancel;
+ }
+ if (TestPrioChange)
+ {
+ TThreadPriority originalThreadPriority = thisThread.Priority();
+ DEBUG_PRINT1((_L("LoadTheLibs[%02d] before priority change\n"), aThreadIndex));
+ thisThread.SetPriority(EPriorityLess);
+ User::AfterHighRes(0);
+ thisThread.SetPriority(originalThreadPriority);
+ DEBUG_PRINT1((_L("LoadTheLibs[%02d] after priority change\n"), aThreadIndex));
+ }
+ }
+ DEBUG_PRINT((_L("LoadTheLibs[%02d] done\n"), aThreadIndex));
+ return KErrNone;
+ }
+
+//
+// CloseTheLibs
+//
+// Close the DLLs that we have previously opened
+//
+
+void CloseTheLibs (PageLdrRLibrary *aTheLibs,
+ TInt aLibCount)
+ {
+ TInt dllIndex = 0;
+
+ for (dllIndex = 0; dllIndex < aLibCount; dllIndex ++)
+ {
+ aTheLibs[dllIndex].CloseLibrary();
+ }
+ memset(aTheLibs, 0, sizeof(*aTheLibs) * aLibCount);
+ }
+
+//
+// RunThreadForward
+//
+// Walk through the function pointer array (forwards) calling each function
+//
+
+TInt RunThreadForward(TInt aThreadIndex,
+ PageLdrRLibrary *aTheLibs,
+ TInt aMaxDllIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ TInt seed = 1;
+ TUint32 index = 0;
+ RThread thisThread;
+ PageLdrRLibrary *pTheLibs = NULL;
+ TInt dllIndex = 0;
+
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
+ if (pTheLibs)
+ {
+ TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Forward[%d] - load fail\n"), aThreadIndex));
+ CloseTheLibs (pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ return retVal;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Forward[%d] - alloc fail\n"), aThreadIndex));
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ pTheLibs = aTheLibs;
+ }
+
+ for (dllIndex = 0; dllIndex < aMaxDllIndex; dllIndex ++)
+ {
+ index = 0;
+ while (index < pTheLibs[dllIndex].iFuncCount)
+ {
+ if (TestPrioChange)
+ {
+ TThreadPriority originalThreadPriority = thisThread.Priority();
+ thisThread.SetPriority(EPriorityLess);
+ User::AfterHighRes(0);
+ thisThread.SetPriority(originalThreadPriority);
+ }
+ if (pTheLibs[dllIndex].iCallFunctionFunc)
+ seed = pTheLibs[dllIndex].iCallFunctionFunc(index, seed, index);
+ else
+ DEBUG_PRINT((_L("Forward[%d] : dll %d was NULL\n"), aThreadIndex, dllIndex));
+ index ++;
+ if (TestThreadsExit)
+ break;
+ }
+ if (TestThreadsExit)
+ break;
+ }
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ CloseTheLibs(pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ }
+ return KErrNone;
+ }
+
+//
+// RunThreadBackward
+//
+// Walk through the function pointer array (backwards) calling each function
+//
+
+TInt RunThreadBackward(TInt aThreadIndex,
+ PageLdrRLibrary *aTheLibs,
+ TInt aMaxDllIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ TInt seed = 1;
+ TUint32 index = 0;
+ RThread thisThread;
+ PageLdrRLibrary *pTheLibs = NULL;
+ TInt dllIndex = 0;
+
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
+ if (pTheLibs)
+ {
+ TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Backward[%d] - load fail\n"), aThreadIndex));
+ CloseTheLibs (pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ return retVal;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Backward[%d] - alloc fail\n"), aThreadIndex));
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ pTheLibs = aTheLibs;
+ }
+
+ for (dllIndex = aMaxDllIndex - 1; dllIndex >= 0; dllIndex --)
+ {
+ index = pTheLibs[dllIndex].iFuncCount;
+ while (index > 0)
+ {
+ if (TestPrioChange)
+ {
+ TThreadPriority originalThreadPriority = thisThread.Priority();
+ thisThread.SetPriority(EPriorityLess);
+ User::AfterHighRes(0);
+ thisThread.SetPriority(originalThreadPriority);
+ }
+ if (pTheLibs[dllIndex].iCallFunctionFunc)
+ seed = pTheLibs[dllIndex].iCallFunctionFunc(index, seed, index);
+ else
+ DEBUG_PRINT((_L("Backward[%d] : dll %d was NULL\n"), aThreadIndex, dllIndex));
+ index --;
+ if (TestThreadsExit)
+ break;
+ }
+ if (TestThreadsExit)
+ break;
+ }
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ CloseTheLibs(pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ }
+ return KErrNone;
+ }
+
+//
+// RunThreadRandom
+//
+// Walk through the function pointer array in a random order a number of times calling each function
+//
+
+TInt RunThreadRandom(TInt aThreadIndex,
+ PageLdrRLibrary *aTheLibs,
+ TInt aMaxDllIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ TInt seed = 1;
+ TUint randNum;
+ RThread thisThread;
+ PageLdrRLibrary *pTheLibs = NULL;
+ TUint dllIndex = 0;
+
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
+ if (pTheLibs)
+ {
+ TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Random[%d] - load fail\n"), aThreadIndex));
+ CloseTheLibs (pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ return retVal;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Random[%d] - alloc fail\n"), aThreadIndex));
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ pTheLibs = aTheLibs;
+ }
+
+
+ TUint funcCount = (TUint)pTheLibs[0].iFuncCount;
+ TInt iterCount = aMaxDllIndex * funcCount;
+
+ // reduce the time for auto tests by reducing the number of cycles.
+ if (TestIsAutomated)
+ iterCount /= 4;
+
+ while (iterCount > 0)
+ {
+ if (TestPrioChange)
+ {
+ TThreadPriority originalThreadPriority = thisThread.Priority();
+ thisThread.SetPriority(EPriorityLess);
+ User::AfterHighRes(0);
+ thisThread.SetPriority(originalThreadPriority);
+ }
+
+ randNum = (TUint)Math::Random();
+ dllIndex = randNum % (TUint)aMaxDllIndex;
+
+ randNum %= funcCount;
+
+ if ( (randNum < funcCount)
+ && ((TInt)dllIndex < aMaxDllIndex))
+ {
+ if (pTheLibs[dllIndex].iCallFunctionFunc)
+ {
+ seed = pTheLibs[dllIndex].iCallFunctionFunc(randNum, seed, randNum);
+ }
+ else
+ DEBUG_PRINT((_L("Random[%d] : dll %d was NULL\n"), aThreadIndex, dllIndex));
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Random[%d] : %d ERROR dllIndex %u rand %u\n"), aThreadIndex, iterCount, dllIndex, randNum));
+ }
+
+ --iterCount;
+ if (TestThreadsExit)
+ break;
+ }
+
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ CloseTheLibs(pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ }
+ return KErrNone;
+ }
+
+
+//
+// ThrashThreadLoad
+//
+// Load and unload the DLLs rapidly to show up a timing window in the kernel.
+//
+
+TInt ThrashThreadLoad (TInt aThreadIndex,
+ PageLdrRLibrary *aTheLibs,
+ TInt aMaxDllIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ if (TestLoadDllHow == TEST_DLL_FUNC)
+ {
+ PageLdrRLibrary *pTheLibs = NULL;
+ DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
+ if (pTheLibs)
+ {
+ TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Thrash[%d] - load fail\n"), aThreadIndex));
+ CloseTheLibs (pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ return retVal;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Thrash[%d] - alloc fail\n"), aThreadIndex));
+ return KErrGeneral;
+ }
+
+ CloseTheLibs(pTheLibs, aMaxDllIndex);
+ User::Free(pTheLibs);
+ }
+ return KErrNone;
+ }
+
+
+//
+// PerformTestThread
+//
+// This is the function that actually does the work.
+// It is complicated a little because test.Printf can only be called from the first thread that calls it
+// so if we are using multiple threads we need to use a message queue to pass the debug info from the
+// child threads back to the parent for the parent to then call printf.
+//
+//
+
+LOCAL_C TInt PerformTestThread(TInt aThreadIndex,
+ RMsgQueue<TMessageBuf> *aMsgQueue = NULL,
+ TMessageBuf *aBuffer = NULL,
+ RSemaphore *aTheSem = NULL)
+ {
+ TUint start = User::TickCount();
+
+ TFullName n(RThread().Name());
+
+ DEBUG_PRINT((_L("%S : thread %d Executing %S\n"), &TestNameBuffer, aThreadIndex, &n));
+
+ // now select how we do the test...
+ TInt iterIndex;
+
+ PageLdrRLibrary *pTheLibs = theGlobalLibs;
+ TInt maxDllIndex = GetNumDlls();
+
+ switch (TestLoadDllHow)
+ {
+ case TEST_DLL_THREAD:
+ pTheLibs = NULL;
+ DOLOADALLOC(maxDllIndex, pTheLibs, aTheSem);
+ if (pTheLibs)
+ {
+ TInt retVal = LoadTheLibs(pTheLibs, maxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
+ if (retVal != KErrNone)
+ {
+ DEBUG_PRINT((_L("Perform[%d] - load fail\n"), aThreadIndex));
+ CloseTheLibs (pTheLibs, maxDllIndex);
+ User::Free(pTheLibs);
+ return retVal;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("Perform[%d] - alloc fail\n"), aThreadIndex));
+ return KErrGeneral;
+ }
+ break;
+
+ case TEST_DLL_GLOBAL:
+ pTheLibs = theGlobalLibs;
+ break;
+
+ case TEST_DLL_FUNC:
+ default:
+ // do nowt
+ break;
+ }
+
+ TInt retVal = KErrNone;
+ if (TEST_ALL == (TestWhichTests & TEST_ALL))
+ {
+ #define LOCAL_ORDER_INDEX1 6
+ #define LOCAL_ORDER_INDEX2 3
+ TInt order[LOCAL_ORDER_INDEX1][LOCAL_ORDER_INDEX2] = { {TEST_FORWARD, TEST_BACKWARD,TEST_RANDOM},
+ {TEST_FORWARD, TEST_RANDOM, TEST_BACKWARD},
+ {TEST_BACKWARD,TEST_FORWARD, TEST_RANDOM},
+ {TEST_BACKWARD,TEST_RANDOM, TEST_FORWARD},
+ {TEST_RANDOM, TEST_FORWARD, TEST_BACKWARD},
+ {TEST_RANDOM, TEST_BACKWARD,TEST_FORWARD}};
+ TInt whichOrder = 0;
+
+ for (iterIndex = 0; ; )
+ {
+ TInt selOrder = ((aThreadIndex + 1) * (iterIndex + 1)) % LOCAL_ORDER_INDEX1;
+ for (whichOrder = 0; whichOrder < LOCAL_ORDER_INDEX2; whichOrder ++)
+ {
+ switch (order[selOrder][whichOrder])
+ {
+ case TEST_FORWARD:
+ DEBUG_PRINT((_L("%S : %d Iter %d.%d Forward\n"),
+ &TestNameBuffer, aThreadIndex, iterIndex, whichOrder));
+ retVal = RunThreadForward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ break;
+
+ case TEST_BACKWARD:
+ DEBUG_PRINT((_L("%S : %d Iter %d.%d Backward\n"),
+ &TestNameBuffer, aThreadIndex, iterIndex, whichOrder));
+ retVal = RunThreadBackward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ break;
+
+ case TEST_RANDOM:
+ DEBUG_PRINT((_L("%S : %d Iter %d.%d Random\n"),
+ &TestNameBuffer, aThreadIndex, iterIndex, whichOrder));
+ retVal = RunThreadRandom(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ break;
+
+ default: // this is really an error.
+ break;
+ }
+ DEBUG_PRINT((_L("%S : %d Iter %d.%d finished %d\n"),
+ &TestNameBuffer, aThreadIndex, iterIndex, whichOrder, retVal));
+ if ((retVal == KErrCancel) && iterIndex > 0)
+ retVal = KErrNone;
+ if ((retVal != KErrNone) || TestThreadsExit)
+ break;
+ }
+ if ((retVal != KErrNone) || TestThreadsExit)
+ break;
+ if (++iterIndex >= TestMaxLoops)
+ break;
+ User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
+ }
+ }
+ else
+ {
+ if (TestWhichTests & TEST_FORWARD)
+ {
+ for (iterIndex = 0; ; )
+ {
+ DEBUG_PRINT((_L("%S : %d Iter %d Forward\n"), &TestNameBuffer, aThreadIndex, iterIndex));
+ retVal = RunThreadForward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
+ if ((retVal == KErrCancel) && iterIndex > 0)
+ retVal = KErrNone;
+ if ((retVal != KErrNone) || TestThreadsExit)
+ break;
+ if (++iterIndex >= TestMaxLoops)
+ break;
+ User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
+ }
+ }
+
+ if (TestWhichTests & TEST_BACKWARD)
+ {
+ for (iterIndex = 0; ; )
+ {
+ DEBUG_PRINT((_L("%S : %d Iter %d Backward\n"), &TestNameBuffer, aThreadIndex, iterIndex));
+ retVal = RunThreadBackward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
+ if ((retVal == KErrCancel) && iterIndex > 0)
+ retVal = KErrNone;
+ if ((retVal != KErrNone) || TestThreadsExit)
+ break;
+ if (++iterIndex >= TestMaxLoops)
+ break;
+ User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
+ }
+ }
+
+ if (TestWhichTests & TEST_RANDOM)
+ {
+ for (iterIndex = 0; ; )
+ {
+ DEBUG_PRINT((_L("%S : %d Iter %d Random\n"), &TestNameBuffer, aThreadIndex, iterIndex));
+ retVal = RunThreadRandom(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
+ if ((retVal == KErrCancel) && iterIndex > 0)
+ retVal = KErrNone;
+ if ((retVal != KErrNone) || TestThreadsExit)
+ break;
+ if (++iterIndex >= TestMaxLoops)
+ break;
+ User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
+ }
+ }
+
+ if (TestWhichTests & TEST_THRASH)
+ {
+ for (iterIndex = 0; ; )
+ {
+ DEBUG_PRINT((_L("%S : %d Iter %d Thrash Load\n"), &TestNameBuffer, aThreadIndex, iterIndex));
+ retVal = ThrashThreadLoad(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
+ DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
+ if ((retVal == KErrCancel) && iterIndex > 0)
+ retVal = KErrNone;
+ if ((retVal != KErrNone) || TestThreadsExit)
+ break;
+ if (++iterIndex >= TestMaxLoops)
+ break;
+ User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
+ }
+ }
+ }
+
+ if (TestLoadDllHow == TEST_DLL_THREAD)
+ {
+ CloseTheLibs(pTheLibs, maxDllIndex);
+ User::Free(pTheLibs);
+ }
+
+ DEBUG_PRINT((_L("%S : thread %d Exit (tick %u)\n"), &TestNameBuffer, aThreadIndex, User::TickCount() - start));
+ return retVal;
+ }
+
+
+//
+// MultipleTestThread
+//
+// Thread function, one created for each thread in a multiple thread test.
+//
+
+LOCAL_C TInt MultipleTestThread(TAny* aUseTb)
+ {
+ TInt ret;
+ TMessageBuf localBuffer;
+
+ if (TestInterleave)
+ {
+ RThread thisThread;
+ thisThread.SetPriority((TThreadPriority) TEST_INTERLEAVE_PRIO);
+ }
+
+ ret = PerformTestThread((TInt) aUseTb, &TestMsgQueue, &localBuffer, &TestMultiSem);
+ if (!TestingChunks)
+ {
+ if (ret != KErrNone)
+ User::Panic(_L("LOAD"), KErrGeneral);
+ }
+ return KErrNone;
+ }
+
+//
+// StartExe
+//
+// Start an executable.
+//
+
+TInt StartExe(RProcess& aTheProcesses, TRequestStatus* aPrStatus, TInt aIndex, TBool aLoadSelf, TBool aLowMem, RSemaphore *pTheSem = NULL)
+ {
+ TBuf<256> buffer;
+ TInt testWhich = KTestMediaRom;
+ //y_LIT(KTestDebug, "debug");
+ _LIT(KTestSilent, "silent");
+
+ if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ALL)
+ testWhich = aIndex % KTestMediaCOUNT;
+ else if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ROM_BASE)
+ testWhich = (aIndex & 1) ? KTestMediaBase : KTestMediaRom;
+ else if (TestWhichMedia & TEST_MEDIA_BASE )
+ testWhich = KTestMediaBase;
+ else
+ testWhich = KTestMediaRom;
+
+ if (!TestDllExesExist[testWhich])
+ testWhich = KTestMediaBase;
+
+ buffer.Zero();
+ TInt ret;
+ if (aLoadSelf)
+ {
+ buffer.Format(_L("single random dll %S iters %d inst %d"),
+ /* TestDebug ? &KTestDebug : */ &KTestSilent, TestMaxLoops, aIndex);
+ if (TestExtremeChunks)
+ buffer.Append(_L(" echunks"));
+ else if (TestChunksPlus)
+ buffer.Append(_L(" chunks prio"));
+ if (TestChunkData == EFalse)
+ buffer.Append(_L(" nochunkdata"));
+ DBGS_PRINT((_L("%S : Starting Process %d %S %S\n"),
+ &TestNameBuffer, aIndex, &TestPlExeNames[testWhich], &buffer));
+ DOTEST1(ret,aTheProcesses.Create(TestPlExeNames[testWhich],buffer),KErrNone, KErrNoMemory);
+ }
+ else
+ {
+ buffer.Format(_L("single random %S iters %d inst %d"),
+ /* TestDebug ? &KTestDebug : */ &KTestSilent, TestMaxLoops, aIndex);
+ DBGS_PRINT((_L("%S : Starting Process %d %S %S\n"),
+ &TestNameBuffer, aIndex, &TestPsExeNames[testWhich], &buffer));
+ DOTEST1(ret,aTheProcesses.Create(TestPsExeNames[testWhich],buffer),KErrNone, KErrNoMemory);
+ }
+ if (ret == KErrNone)
+ {
+ if(aPrStatus)
+ {
+ aTheProcesses.Logon(*aPrStatus);
+ RUNTEST1(*aPrStatus == KRequestPending);
+ }
+ aTheProcesses.Resume();
+ }
+ return ret;
+ }
+
+//
+// PerformRomAndFileSystemAccessThread
+//
+// Access the rom and dump it out to one of the writeable partitions...
+// really just to make the media server a little busy during the test.
+//
+TInt PerformRomAndFileSystemAccessThread(TInt aThreadId,
+ RMsgQueue<TMessageBuf> *aMsgQueue,
+ TMessageBuf *aBuffer,
+ RSemaphore *aTheSem,
+ TBool aLowMem)
+ {
+ RThread thisThread;
+ TUint maxBytes = KMaxTUint;
+ TInt startTime = User::TickCount();
+ RSemaphore *pTheSem = aTheSem;
+ RFs fs;
+ RFile file;
+
+ if (KErrNone != fs.Connect())
+ {
+ DEBUG_PRINT(_L("PerformRomAndFileSystemAccessThread : Can't connect to the FS\n"));
+ return KErrGeneral;
+ }
+
+ // get info about the ROM...
+ TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
+ TUint8* start;
+ TUint8* end;
+ if(romHeader->iPageableRomStart)
+ {
+ start = (TUint8*)romHeader + romHeader->iPageableRomStart;
+ end = start + romHeader->iPageableRomSize;
+ }
+ else
+ {
+ start = (TUint8*)romHeader;
+ end = start + romHeader->iUncompressedSize;
+ }
+ if (end <= start)
+ return KErrGeneral;
+
+ // read all ROM pages in a random order...and write out to file in ROFs
+ TInt pageSize = 0;
+ UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0);
+
+ TUint size = end - start - pageSize;
+ if(size > maxBytes)
+ size = maxBytes;
+
+ TUint32 random = 1 + aThreadId;
+ TPtrC8 sourceData;
+ TUint8* theAddr;
+ HBufC8* checkData;
+
+ DOTEST((checkData = HBufC8::New(pageSize + 10)),
+ (checkData != NULL));
+
+ if (!checkData)
+ {
+ DEBUG_PRINT((_L("RomAndFSThread %S : failed to alloc read buffer\n"), &TestNameBuffer));
+ }
+
+ TInt drvNum = (TestBootedFromMmc || TestOnlyFromMmc) ? FindMMCDriveNumber(fs) : FindFsNANDDrive(fs);
+ TBuf<32> filename;
+
+ filename.Format(_L("?:\\Pageldrtst%d.tmp"), aThreadId);
+ if (drvNum >= 0)
+ {
+ DEBUG_PRINT((_L("%S : Filename %S\n"), &TestNameBuffer, &filename));
+ }
+ else
+ {
+ DEBUG_PRINT((_L("RomAndFSThread : error getting drive num\n")));
+ drvNum = 3; //make it 'd' by default.
+ }
+ filename[0] = 'a' + drvNum;
+
+#ifdef WANT_FS_CACHE_STATS
+ TInt allocatedSegmentCount = 0;
+ TInt filesOnClosedQueue = 0;
+#endif
+ TInt ret;
+ while(1)
+ {
+ for(TInt i = size / (pageSize); i>0; --i)
+ {
+ DEBUG_PRINT1((_L("%S : Opening the file\n"), &TestNameBuffer));
+ DOTEST((ret = file.Replace(fs, filename, EFileWrite)),
+ (KErrNone == ret));
+
+ random = random * 69069 + 1;
+ theAddr = (TUint8 *)(start + ((TInt64(random) * TInt64(size - pageSize)) >> 32));
+ sourceData.Set(theAddr,pageSize);
+ DEBUG_PRINT1((_L("%S : Writing the file\n"), &TestNameBuffer));
+ ret = file.Write(sourceData);
+ if (ret != KErrNone)
+ {
+ DEBUG_PRINT((_L("%S : Write returned error %d\n"), &TestNameBuffer, ret));
+ }
+ DEBUG_PRINT1((_L("%S : Closing the file\n"), &TestNameBuffer));
+ file.Close();
+
+ if (checkData)
+ {
+ TPtr8 theBuf = checkData->Des();
+
+#ifdef WANT_FS_CACHE_STATS
+ // Page cache
+ TFileCacheStats stats1;
+ TFileCacheStats stats2;
+ ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats1);
+ if ((ret != KErrNone) && (ret != KErrNotSupported))
+ {
+ DEBUG_PRINT((_L("%S : KControlIoFileCacheStats 1 failed %d\n"), &TestNameBuffer, ret));
+ }
+
+ if (aThreadId & 1)
+ {
+ // flush closed files queue
+ ret = fs.ControlIo(drvNum, KControlIoFlushClosedFiles);
+ if (ret != KErrNone)
+ {
+ DEBUG_PRINT((_L("%S : KControlIoFlushClosedFiles failed %d\n"), &TestNameBuffer, ret));
+ }
+ }
+ else
+#endif //WANT_FS_CACHE_STATS
+ {
+ // rename file to make sure it has cleared the cache.
+ TBuf<32> newname;
+ newname.Format(_L("d:\\Pageldrtst%d.temp"), aThreadId);
+ if (drvNum >= 0)
+ {
+ newname[0] = 'a' + drvNum;
+ }
+ fs.Rename(filename, newname);
+ filename = newname;
+ }
+#ifdef WANT_FS_CACHE_STATS
+ ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats2);
+ if (ret != KErrNone && ret != KErrNotSupported)
+ {
+ DEBUG_PRINT((_L("%S : KControlIoFileCacheStats2 failed %d\n"), &TestNameBuffer, ret));
+ }
+
+ allocatedSegmentCount = (allocatedSegmentCount > stats1.iAllocatedSegmentCount) ? allocatedSegmentCount : stats1.iAllocatedSegmentCount;
+ filesOnClosedQueue = (filesOnClosedQueue > stats1.iFilesOnClosedQueue) ? filesOnClosedQueue : stats1.iFilesOnClosedQueue;
+#endif //WANT_FS_CACHE_STATS
+
+ DOTEST((ret = file.Open(fs, filename, EFileRead)),
+ (KErrNone == ret));
+ // now read back the page that we wrote and compare with the source.
+ ret = file.Read(0, theBuf, pageSize);
+ if (ret == KErrNone)
+ {
+ ret = sourceData.Compare(theBuf);
+ if (ret != 0)
+ {
+ DEBUG_PRINT((_L("%S : read compare error %d\n"), &TestNameBuffer, ret));
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("%S : failed read compare, error %d\n"), &TestNameBuffer, ret));
+ }
+ file.Close();
+ }
+ DEBUG_PRINT1((_L("%S : Deleting the file\n"), &TestNameBuffer));
+ ret = fs.Delete(filename);
+ if (KErrNone != ret)
+ {
+ DEBUG_PRINT((_L("%S [%d] Delete %S Failed %d!\n"), &TestNameBuffer, aThreadId, &filename, ret));
+ }
+
+ if (TestPrioChange)
+ {
+ TThreadPriority originalThreadPriority = thisThread.Priority();
+ DEBUG_PRINT1((_L("%S [%d] media thread before priority change, stop = %d\n"), &TestNameBuffer, aThreadId, TestStopMedia));
+ thisThread.SetPriority(EPriorityLess);
+ User::AfterHighRes(0);
+ thisThread.SetPriority(originalThreadPriority);
+ DEBUG_PRINT1((_L("%S [%d] media thread after priority change, stop = %d\n"), &TestNameBuffer, aThreadId, TestStopMedia));
+ }
+ if (TestStopMedia)
+ break;
+ }
+ if (TestStopMedia)
+ break;
+ }
+
+#ifdef WANT_FS_CACHE_STATS
+ DEBUG_PRINT((_L("%S : [%d] allocPageCount %d filesClosedQueue %d \n"),&TestNameBuffer, aThreadId,allocatedSegmentCount,filesOnClosedQueue));
+#endif //WANT_FS_CACHE_STATS
+
+ if (checkData)
+ {
+ delete checkData;
+ }
+ fs.Close();
+ DEBUG_PRINT1((_L("Done in %d ticks\n"), User::TickCount() - startTime));
+ return KErrNone;
+ }
+
+//
+// PerformFileSystemAccessThread
+//
+// Access the rom and dump it out to one of the writeable partitions...
+// really just to make the media server a little busy during the test.
+//
+TInt PerformFileSystemAccessThread(TInt aThreadId,
+ RMsgQueue<TMessageBuf> *aMsgQueue,
+ TMessageBuf *aBuffer,
+ RSemaphore *aTheSem,
+ TBool aLowMem)
+ {
+ RThread thisThread;
+ TInt startTime = User::TickCount();
+ RSemaphore *pTheSem = aTheSem;
+ RFs fs;
+ RFile file;
+ if (KErrNone != fs.Connect())
+ {
+ DEBUG_PRINT(_L("PerformFileSystemAccessThread : Can't connect to the FS\n"));
+ return KErrGeneral;
+ }
+
+ // read all ROM pages in a random order...and write out to file in ROFs
+ TInt pageSize = 0;
+ UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0);
+
+ HBufC8* checkData;
+ HBufC8* sourceData;
+ TUint32 random = 1 + aThreadId;
+ TInt dataSize = pageSize + (pageSize / 2);
+
+ DOTEST((sourceData = HBufC8::New(dataSize)),
+ (sourceData != NULL));
+ if (!sourceData)
+ {
+ DEBUG_PRINT((_L("RomAndFSThread %S : failed to alloc read buffer\n"), &TestNameBuffer));
+ fs.Close();
+ return KErrGeneral;
+ }
+
+ DOTEST((checkData = HBufC8::New(dataSize)),
+ (checkData != NULL));
+ if (!checkData)
+ {
+ DEBUG_PRINT((_L("RomAndFSThread %S : failed to alloc read buffer\n"), &TestNameBuffer));
+ }
+
+ TInt drvNum = (TestBootedFromMmc || TestOnlyFromMmc) ? FindMMCDriveNumber(fs) : FindFsNANDDrive(fs);
+ TBuf<32> filename;
+
+ if (drvNum < 0)
+ {
+ drvNum = 3; //make it 'd' by default.
+ DEBUG_PRINT((_L("FSAccessThread : error getting drive num\n")));
+ }
+
+#ifdef WANT_FS_CACHE_STATS
+ TInt allocatedSegmentCount = 0;
+ TInt filesOnClosedQueue = 0;
+#endif
+ TInt fileIndex;
+ TInt ret;
+
+ TPtr8 pBuf = sourceData->Des();
+
+ while (1)
+ {
+ TUint32 randomStart = random;
+ // write the file
+ for (fileIndex = 0; fileIndex < TEST_NUM_FILES; fileIndex ++)
+ {
+ filename.Format(_L("%c:\\pldrtst%d_%d.tmp"), 'a' + drvNum, aThreadId, fileIndex);
+
+ DEBUG_PRINT1((_L("%S : Opening the file\n"), &TestNameBuffer));
+
+ DOTEST ((ret = file.Replace(fs, filename, EFileWrite)),
+ (KErrNone == ret));
+
+ pBuf.Zero();
+ if (fileIndex & 1)
+ {
+ TInt fillSize = dataSize / sizeof(TUint32);
+ while (fillSize > 0)
+ {
+ random = random * 69069 + 1;
+ pBuf.Append((const TUint8 *) &random, sizeof(random));
+ fillSize --;
+ }
+ }
+ else
+ {
+ pBuf.Fill('x',dataSize);
+ }
+
+
+ DEBUG_PRINT1((_L("%S : Writing the file\n"), &TestNameBuffer));
+ ret = file.Write(sourceData->Des());
+ if (ret != KErrNone)
+ {
+ DEBUG_PRINT((_L("%S : Write returned error %d\n"), &TestNameBuffer, ret));
+ }
+ DEBUG_PRINT1((_L("%S : Closing the file\n"), &TestNameBuffer));
+ file.Close();
+ }
+
+ random = randomStart;
+ // check the file
+ for (fileIndex = 0; fileIndex < TEST_NUM_FILES; fileIndex ++)
+ {
+ filename.Format(_L("%c:\\pldrtst%d_%d.tmp"), 'a' + drvNum, aThreadId, fileIndex);
+
+ if (checkData)
+ {
+ TPtr8 theBuf = checkData->Des();
+
+#ifdef WANT_FS_CACHE_STATS
+ // Page cache
+ TFileCacheStats stats1;
+ TFileCacheStats stats2;
+ ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats1);
+ if ((ret != KErrNone) && (ret != KErrNotSupported))
+ {
+ DEBUG_PRINT((_L("%S : KControlIoFileCacheStats 1 failed %d\n"), &TestNameBuffer, ret));
+ }
+
+ if (aThreadId & 1)
+ {
+ // flush closed files queue
+ ret = fs.ControlIo(drvNum, KControlIoFlushClosedFiles);
+ if (ret != KErrNone)
+ {
+ DEBUG_PRINT((_L("%S : KControlIoFlushClosedFiles failed %d\n"), &TestNameBuffer, ret));
+ }
+ }
+ else
+#endif //WANT_FS_CACHE_STATS
+ {
+ // rename file to make sure it has cleared the cache.
+ TBuf<32> newname;
+ newname.Format(_L("%c:\\pldrtst%d_%d.temp"), 'a' + drvNum, aThreadId, fileIndex);
+ fs.Rename(filename, newname);
+ filename = newname;
+ }
+#ifdef WANT_FS_CACHE_STATS
+ ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats2);
+ if (ret != KErrNone && ret != KErrNotSupported)
+ {
+ DEBUG_PRINT((_L("%S : KControlIoFileCacheStats2 failed %d\n"), &TestNameBuffer, ret));
+ }
+ allocatedSegmentCount = (allocatedSegmentCount > stats1.iAllocatedSegmentCount) ? allocatedSegmentCount : stats1.iAllocatedSegmentCount;
+ filesOnClosedQueue = (filesOnClosedQueue > stats1.iFilesOnClosedQueue) ? filesOnClosedQueue : stats1.iFilesOnClosedQueue;
+#endif //WANT_FS_CACHE_STATS
+
+ DOTEST((ret = file.Open(fs, filename, EFileRead)),
+ (KErrNone == ret));
+ // now read back the page that we wrote and compare with the source.
+ ret = file.Read(0, theBuf, dataSize);
+ if (ret == KErrNone)
+ {
+ pBuf.Zero();
+ if (fileIndex & 1)
+ {
+ TInt fillSize = dataSize / sizeof(TUint32);
+ while (fillSize > 0)
+ {
+ random = random * 69069 + 1;
+ pBuf.Append((const TUint8 *) &random, sizeof(random));
+ fillSize --;
+ }
+ }
+ else
+ {
+ pBuf.Fill('x',dataSize);
+ }
+
+ ret = sourceData->Des().Compare(theBuf);
+ if (ret != 0)
+ {
+ DEBUG_PRINT((_L("%S :compare error %S %d\n"), &TestNameBuffer, &filename, ret));
+ }
+ }
+ else
+ {
+ DEBUG_PRINT((_L("%S : failed read compare, error %d\n"), &TestNameBuffer, ret));
+ }
+ file.Close();
+ }
+ DEBUG_PRINT1((_L("%S : Deleting the file\n"), &TestNameBuffer));
+ ret = fs.Delete(filename);
+ if (KErrNone != ret)
+ {
+ DEBUG_PRINT((_L("%S [%d] Delete %S Failed %d!\n"), &TestNameBuffer, aThreadId, &filename, ret));
+ }
+ if (TestPrioChange)
+ {
+ TThreadPriority originalThreadPriority = thisThread.Priority();
+ thisThread.SetPriority(EPriorityLess);
+ User::AfterHighRes(0);
+ thisThread.SetPriority(originalThreadPriority);
+ }
+ if (TestStopMedia)
+ break;
+ }
+ if (TestStopMedia)
+ break;
+ }
+#ifdef WANT_FS_CACHE_STATS
+ DEBUG_PRINT((_L("%S : [%d] allocPageCount %d filesClosedQueue %d \n"),&TestNameBuffer, aThreadId,allocatedSegmentCount,filesOnClosedQueue));
+#endif //WANT_FS_CACHE_STATS
+
+ if (checkData)
+ {
+ delete checkData;
+ }
+ delete sourceData;
+ fs.Close();
+ DEBUG_PRINT1((_L("Done in %d ticks\n"), User::TickCount() - startTime));
+ return KErrNone;
+ }
+
+//
+// PerformRomAndFileSystemAccess
+//
+// Thread function, kicks off the file system access.
+//
+
+LOCAL_C TInt PerformRomAndFileSystemAccess(TAny* aParam)
+ {
+ TMessageBuf localBuffer;
+ TInt threadId = (TInt) aParam;
+ TInt retVal = KErrGeneral;
+
+ if (TestInterleave)
+ {
+ RThread thisThread;
+ thisThread.SetPriority((TThreadPriority) TEST_INTERLEAVE_PRIO);
+ }
+
+ switch (TestMediaAccess)
+ {
+ default:
+ break;
+
+ case KTestMediaAccessBasic:
+ case KTestMediaAccessMultipleThreads:
+ retVal = PerformRomAndFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);
+ break;
+
+ case KTestMediaAccessMultiplePattern:
+ retVal = PerformFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);
+ break;
+
+ case KTestMediaAccessMixed:
+ if (threadId < ((TestMultipleThreadCount + 1) / 2))
+ retVal = PerformRomAndFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);
+ else
+ retVal = PerformFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);
+ break;
+ }
+ return retVal;
+ }
+
+
+//
+// DisplayTestBanner
+//
+// Output a header showing the test parameters.
+//
+
+void DisplayTestBanner(TBool aMultiple)
+ {
+ DBGS_PRINT((_L("%S : what = %S%S%S(0x%x), media = %S%S%S(0x%x)\n"),
+ aMultiple ? &KMultipleTest : &KSingleTest,
+ TestLoading & TEST_EXE ? &KTestExe : &KTestBlank,
+ TestLoading & TEST_DLL ? &KTestDll : &KTestBlank,
+ TestLoading & TEST_SELF ? &KTestSelf : &KTestBlank,
+ TestLoading,
+ TestWhichMedia & TEST_MEDIA_BASE ? &KTestBase : &KTestBlank,
+ TestWhichMedia & TEST_MEDIA_ROM ? &KTestRom : &KTestBlank,
+ (TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ALL ? &KTestAll : &KTestBlank,
+ TestWhichMedia));
+ DBGS_PRINT((_L(" : maxLoops = %d, threads = %d, loadHow = %S (0x%x)\n"),
+ TestMaxLoops,
+ TestMultipleThreadCount,
+ TestLoadDllHow == TEST_DLL_GLOBAL ? &KTestGlobal : TestLoadDllHow == TEST_DLL_THREAD ? &KTestThread : &KTestFunc, TestLoadDllHow));
+ DBGS_PRINT((_L(" : options = %S%S%S%S%S%S, which = %S%S%S%S (0x%x)\n"),
+ TestInterleave ? &KTestInter : &KTestBlank,
+ TestPrioChange ? &KTestPrio: &KTestBlank,
+ (TestMediaAccess == KTestMediaAccessNone) ? &KTestBlank : &KTestMedia,
+ TestingLowMem ? &KTestLowMem : &KTestBlank,
+ TestExtremeChunks ? &KTestEChunking : TestChunksPlus ? &KTestChunkingPlus : TestingChunks ? &KTestChunking : &KTestBlank,
+ TestingReaper ? &KTestReaper : &KTestBlank,
+ TestWhichTests & TEST_THRASH ? &KTestThrash : &KTestBlank,
+ TestWhichTests & TEST_FORWARD ? &KTestForward : &KTestBlank,
+ TestWhichTests & TEST_BACKWARD ? &KTestBackward : &KTestBlank,
+ TestWhichTests & TEST_RANDOM ? &KTestRandom : &KTestBlank,
+ TestWhichTests));
+ }
+
+//
+// DoSingleTest
+//
+// Perform the single thread test, spawning a number of threads.
+//
+
+LOCAL_C TInt DoSingleTest(TBool aLowMem = EFalse)
+ {
+ TUint start = User::TickCount();
+ RSemaphore *pTheSem = NULL;
+ TInt ret = KErrNone;
+ DisplayTestBanner(EFalse);
+
+ if (aLowMem)
+ {
+ DOTEST1(ret,TestMultiSem.CreateLocal(1),KErrNone, KErrNoMemory);
+ pTheSem = &TestMultiSem;
+ }
+ if (TestLoading & TEST_EXE)
+ {
+ RProcess theProcess;
+ TRequestStatus status;
+
+ if (StartExe(theProcess, &status, 0, EFalse, aLowMem, pTheSem) == KErrNone)
+ {
+ User::WaitForRequest(status);
+ if (theProcess.ExitType() == EExitPanic)
+ {
+ DBGS_PRINT((_L("%S : Process Panic'd...\n"), &TestNameBuffer));
+ }
+ theProcess.Close();
+ }
+ }
+
+ if (TestLoading & TEST_SELF)
+ {
+ RProcess theProcess;
+ TRequestStatus status;
+
+ if (StartExe(theProcess, &status, 0, ETrue, aLowMem,pTheSem) == KErrNone)
+ {
+ User::WaitForRequest(status);
+ if (theProcess.ExitType() == EExitPanic)
+ {
+ DBGS_PRINT((_L("%S : Process Panic'd...\n"), &TestNameBuffer));
+ }
+ theProcess.Close();
+ }
+ }
+
+ if (TestLoading & TEST_DLL)
+ {
+ TInt maxDlls = GetNumDlls();
+ if (TestLoadDllHow == TEST_DLL_GLOBAL)
+ {
+ TInt retVal = LoadTheLibs(theGlobalLibs, maxDlls, TestInstanceId, NULL, NULL, pTheSem);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("DoSingleTest - unable to load libs\n") ));
+ CloseTheLibs (theGlobalLibs, PAGELDRTST_MAX_DLLS);
+ if (aLowMem)
+ {
+ TestMultiSem.Close();
+ }
+ return KErrGeneral;
+ }
+ }
+
+ ret = PerformTestThread((TInt) TestInstanceId, NULL, NULL, pTheSem);
+
+ if (TestLoadDllHow == TEST_DLL_GLOBAL)
+ {
+ CloseTheLibs(theGlobalLibs, maxDlls);
+ }
+ }
+ if (aLowMem)
+ {
+ TestMultiSem.Close();
+ }
+
+ if (!TestSilent)
+ {
+ TInt end = User::TickCount();
+ TInt time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
+ DBGS_PRINT((_L("\n%S : Single Test : (%u seconds)\n"), &TestNameBuffer, time));
+ }
+
+ return ret;
+ }
+
+//
+// FillPage
+//
+// Fill a page with test data
+//
+
+void FillPage(TUint aOffset)
+ {
+ if (TestChunkData)
+ {
+ TUint32* ptr = (TUint32 *)((TUint8 *)TestChunkBase+aOffset);
+ TUint32* ptrEnd = (TUint32 *)((TUint8 *)ptr + TestPageSize);
+ do
+ {
+ *ptr = 0x55000000 + aOffset;
+ ptr ++;
+ aOffset += 4;
+ }
+ while(ptr<ptrEnd);
+ }
+ }
+
+//
+// CheckPage
+//
+// Check a page matches test data....
+//
+
+TBool CheckPage(TUint index, TUint aOffset)
+ {
+ TBool ret = ETrue;
+ if (TestChunkData)
+ {
+ TUint32* ptr = (TUint32 *)((TUint8 *)TestChunkBase+aOffset);
+ TUint32* ptrEnd = (TUint32 *)((TUint8 *)ptr + TestPageSize);
+ do
+ {
+ if (*ptr != (0x55000000 + aOffset))
+ break;
+ ptr ++;
+ aOffset += 4;
+ }
+ while(ptr<ptrEnd);
+ if (ptr==ptrEnd)
+ {
+ TestChunkStats[index].check.ok ++;
+ }
+ else
+ {
+ TestChunkStats[index].check.fail ++;
+ ret = EFalse;
+ }
+ }
+ return ret;
+ }
+
+//
+// DoSomeChunking
+//
+// Lock and unlock various pages in a chunk...
+//
+TUint TestChunkingIndex = 0;
+TUint TestChunkingIndexFails = 0;
+
+void DoSomeChunking()
+ {
+ TUint iters = TEST_NUM_CHUNK_PAGES / 4;
+ TBool lockit = EFalse;
+ TBool decomit = EFalse;
+ TUint index;
+ TInt ret;
+ TInt theOffset;
+
+ while (iters)
+ {
+ TestChunkingIndex = TestChunkingIndex * 69069 + 1;
+ index = TUint64((TUint64)TestChunkingIndex*(TUint64)TEST_NUM_CHUNK_PAGES)>>32;
+ if (index >= TEST_NUM_CHUNK_PAGES)
+ TestChunkingIndexFails ++;
+
+ theOffset = index * TestPageSize;
+ if (theOffset < TestCommitEnd)
+ {
+ if (lockit)
+ {
+ if (decomit)
+ {
+ ret = TestChunk.Decommit(theOffset,TestPageSize);
+ if (KErrNone == ret)
+ TestChunkStats[index].decommit.ok ++;
+ else
+ TestChunkStats[index].decommit.fail ++;
+ ret = TestChunk.Commit(theOffset,TestPageSize);
+ if (KErrNone == ret)
+ {
+ TestChunkStats[index].commit.ok ++;
+ FillPage(theOffset);
+ TestChunkPageState[index] = ETrue;
+ }
+ else
+ {
+ TestChunkStats[index].commit.fail ++;
+ TestChunkPageState[index] = EFalse;
+ }
+ ret = KErrNone;
+ }
+ else
+ {
+ ret = TestChunk.Lock(theOffset,TestPageSize);
+ if (KErrNone == ret)
+ {
+ TestChunkStats[index].lock.ok ++;
+ if (!CheckPage(index, theOffset))
+ FillPage(theOffset);
+ TestChunkPageState[index] = ETrue;
+ }
+ else
+ {
+ TestChunkStats[index].lock.fail ++;
+ TestChunkPageState[index] = EFalse;
+ }
+ }
+ decomit = !decomit;
+ }
+ else
+ {
+ if (TestChunkPageState[index])
+ {
+ // this one should still be locked so the data should be ok.
+ if (KErrNone == TestChunk.Lock(theOffset,TestPageSize))
+ {
+ TestChunkStats[index].lock.ok ++;
+ CheckPage(index, theOffset);
+ }
+ else
+ TestChunkStats[index].lock.fail ++;
+ }
+ ret = TestChunk.Unlock(theOffset,TestPageSize);
+ if (KErrNone == ret)
+ TestChunkStats[index].unlock.ok ++;
+ else
+ TestChunkStats[index].unlock.fail ++;
+ TestChunkPageState[index] = EFalse;
+ }
+ if (KErrNone != ret)
+ {
+ // so now we need to commit another page in this pages place.
+ ret = TestChunk.Commit(theOffset,TestPageSize);
+ if (KErrNone != ret)
+ {
+ TestChunkStats[index].commit.fail ++;
+ //DBGS_PRINT((_L("%S : DoSomeChunking[%03d] index %03d failed to commit a page %d\n"), &TestNameBuffer, iters, index, ret));
+ TestChunkPageState[index] = EFalse;
+ }
+ else
+ {
+ TestChunkStats[index].commit.ok ++;
+ FillPage(theOffset);
+ TestChunkPageState[index] = ETrue;
+ }
+ }
+ lockit = !lockit;
+ }
+ else
+ {
+ RDebug::Printf("DoSomeChunking - offset was bad %d / %d", theOffset, TestCommitEnd);
+ }
+ iters --;
+ }
+ }
+
+//
+// DoMultipleTest
+//
+// Perform the multiple thread test, spawning a number of threads.
+// It is complicated a little because test.Printf can only be called from the first thread that calls it
+// so if we are using multiple threads we need to use a message queue to pass the debug info from the
+// child threads back to the parent for the parent to then call printf.
+//
+
+TInt DoMultipleTest(TBool aLowMem = EFalse)
+ {
+ TInt index;
+ TUint start = User::TickCount();
+ RThread *pTheThreads = NULL;
+ TInt *pThreadInUse = NULL;
+
+ RProcess *pTheProcesses = NULL;
+ TInt *pProcessInUse = NULL;
+
+ RThread *pMedThreads = NULL;
+ TInt *pMedInUse = NULL;
+
+ TRequestStatus mediaStatus;
+ RThread mediaThread;
+ TInt ret;
+
+ RSemaphore *pTheSem = NULL;
+
+ DisplayTestBanner(ETrue);
+
+ TestThreadsExit = EFalse;
+
+ DOTEST1(ret,TestMultiSem.CreateLocal(1),KErrNone, KErrNoMemory);
+
+ pTheSem = &TestMultiSem;
+ if (TestLoading & TEST_DLL)
+ {
+ DOTEST((pTheThreads = (RThread *)User::AllocZ(sizeof(RThread) * TestMultipleThreadCount)),
+ (pTheThreads != NULL))
+ DOTEST((pThreadInUse = (TInt *)User::AllocZ(sizeof(TInt) * TestMultipleThreadCount)),
+ (pThreadInUse != NULL));
+ RUNTEST1(pTheThreads && pThreadInUse);
+ if (!(pTheThreads && pThreadInUse))
+ return KErrGeneral;
+ }
+
+ if (TestLoading & TEST_EXE_SELF)
+ {
+ DOTEST((pTheProcesses = (RProcess *)User::AllocZ(sizeof(RProcess) * TestMultipleThreadCount)),
+ (pTheProcesses != NULL));
+ DOTEST((pProcessInUse = (TInt *)User::AllocZ(sizeof(TInt) * TestMultipleThreadCount)),
+ (pProcessInUse != NULL));
+ RUNTEST1(pTheProcesses && pProcessInUse);
+ if (!(pTheProcesses && pProcessInUse))
+ return KErrGeneral;
+ }
+
+ if (!TestSilent)
+ {
+ DOTEST1(ret,TestMsgQueue.CreateLocal(TestMultipleThreadCount * 10, EOwnerProcess),KErrNone, KErrNoMemory);
+ if (ret != KErrNone)
+ return KErrGeneral;
+ }
+
+ if (TestMediaAccess != KTestMediaAccessNone)
+ {
+ if (TestMediaAccess != KTestMediaAccessBasic)
+ {
+ TestStopMedia = EFalse;
+ DOTEST((pMedThreads = (RThread *)User::AllocZ(sizeof(RThread) * TestMultipleThreadCount)),
+ (pMedThreads != NULL))
+ DOTEST((pMedInUse = (TInt *)User::AllocZ(sizeof(TInt) * TestMultipleThreadCount)),
+ (pMedInUse != NULL));
+ RUNTEST1(pMedThreads && pMedInUse);
+ if (!(pMedThreads && pMedInUse))
+ return KErrGeneral;
+
+ for (index = 0; index < TestMultipleThreadCount; index++)
+ {
+ DBGS_PRINT((_L("%S : Starting Media Thread %d\n"), &TestNameBuffer, index));
+ DOTEST1(ret,pMedThreads[index].Create(KTestBlank,PerformRomAndFileSystemAccess,KDefaultStackSize,NULL,(TAny*) index),KErrNone, KErrNoMemory);
+ if (ret == KErrNone)
+ {
+ pMedThreads[index].Resume();
+ pMedInUse[index] = 1;
+ }
+ User::AfterHighRes(0);
+ }
+ }
+ else
+ {
+ TestStopMedia = EFalse;
+ DOTEST1(ret,mediaThread.Create(KTestBlank,PerformRomAndFileSystemAccess,KDefaultStackSize,NULL,(TAny *) 0),KErrNone, KErrNoMemory);
+ if (ret == KErrNone)
+ {
+ mediaThread.Logon(mediaStatus);
+ RUNTEST1(mediaStatus == KRequestPending);
+ mediaThread.Resume();
+ }
+ }
+ }
+
+ TInt maxDlls = GetNumDlls();
+ if (TestLoadDllHow == TEST_DLL_GLOBAL)
+ {
+ TInt retVal = LoadTheLibs(theGlobalLibs, maxDlls, 0, NULL, NULL, NULL);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("DoMultipleTest - unable to load libs\n")));
+ CloseTheLibs (theGlobalLibs, maxDlls);
+ if (!TestSilent)
+ {
+ TestMsgQueue.Close();
+ }
+ TestMultiSem.Close();
+ return KErrGeneral;
+ }
+ }
+
+ // make sure we have a priority higher than that of the threads we spawn...
+ RThread thisThread;
+ TThreadPriority savedThreadPriority = thisThread.Priority();
+ const TThreadPriority KMainThreadPriority = EPriorityMuchMore;
+ __ASSERT_COMPILE(KMainThreadPriority>TEST_INTERLEAVE_PRIO);
+ thisThread.SetPriority(KMainThreadPriority);
+
+
+ for (index = 0; index < TestMultipleThreadCount; index++)
+ {
+ if (TestLoading & TEST_EXE_SELF)
+ {
+ if (KErrNone == StartExe(pTheProcesses[index], 0, index + ((TestLoading & TEST_DLL) ? TestMultipleThreadCount : 0), ((TestLoading & TEST_EXE_SELF) == TEST_EXE_SELF) ? (index & 2) : (TestLoading & TEST_SELF), aLowMem, pTheSem))
+ {
+ User::AfterHighRes(0);
+ pProcessInUse[index] = 1;
+ }
+ }
+
+
+ if (TestLoading & TEST_DLL)
+ {
+ DBGS_PRINT((_L("%S : Starting Thread %d\n"), &TestNameBuffer, index));
+ DOTEST1(ret,pTheThreads[index].Create(KTestBlank,MultipleTestThread,KDefaultStackSize,NULL,(TAny*) index),KErrNone, KErrNoMemory);
+ if (ret == KErrNone)
+ {
+ pTheThreads[index].Resume();
+ User::AfterHighRes(0);
+ pThreadInUse[index] = 1;
+ }
+ }
+ }
+
+ // wait for any child threads to exit and process any debug messages they pass back to the parent.
+ TBool anyUsed = ETrue;
+ TMessageBuf localBuffer;
+
+ TInt processOk = 0;
+ TInt threadOk = 0;
+ TInt processPanic = 0;
+ TInt threadPanic = 0;
+ TUint end = start;
+ TUint now;
+ TUint time;
+ TUint killNext = 0;
+ TUint numDots = 0;
+ TUint maxDots = (10*60)/TEST_DOT_PERIOD; // No individual test should take longer than 10 minutes!
+ // Most have been tuned to take between 2 and 8 minutes.
+ // The autotests should not take more than 120 minutes total.
+
+ while(anyUsed)
+ {
+ TInt threadCount = 0;
+ TInt processCount = 0;
+ anyUsed = EFalse;
+
+ // check the message queue and call printf if we get a message.
+ if (!TestSilent)
+ {
+ while (KErrNone == TestMsgQueue.Receive(localBuffer))
+ {
+ DBGS_PRINT((localBuffer));
+ }
+ }
+
+ // walk through the thread list to check which are still alive.
+ for (index = 0; index < TestMultipleThreadCount; index++)
+ {
+ if (TestLoading & TEST_DLL)
+ {
+ if (pThreadInUse[index])
+ {
+ if (pTheThreads[index].ExitType() != EExitPending)
+ {
+ if (pTheThreads[index].ExitType() == EExitPanic)
+ {
+ DBGS_PRINT((_L("%S : Thread %d Panic'd after %u ticks \n"),
+ &TestNameBuffer, index, User::TickCount() - start));
+ threadPanic ++;
+ }
+ else
+ {
+ DBGS_PRINT((_L("%S : Thread %d Exited after %u ticks \n"),
+ &TestNameBuffer, index, User::TickCount() - start));
+ threadOk ++;
+ }
+ pTheThreads[index].Close();
+ pThreadInUse[index] = EFalse;
+ }
+ else
+ {
+ threadCount += 1;
+ anyUsed = ETrue;
+ if (TestThreadsExit)
+ {
+ now = User::TickCount();
+ time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
+ if (time > TEST_DOT_PERIOD)
+ {
+ DBGS_PRINT((_L("%S : Thread %d still running\n"), &TestNameBuffer, index));
+ }
+ time = TUint((TUint64)(now-killNext)*(TUint64)TickPeriod/(TUint64)1000000);
+ const TUint killTimeStep = (TEST_DOT_PERIOD+9)/10; // 1/10th of a dot
+ if(time>TEST_DOT_PERIOD+killTimeStep)
+ {
+ killNext += killTimeStep*1000000/TickPeriod;
+ DBGS_PRINT((_L("%S : killing Thread %d\n"), &TestNameBuffer, index));
+ pTheThreads[index].Kill(KErrNone);
+ pTheThreads[index].Close();
+ pThreadInUse[index] = EFalse;
+ }
+ }
+ }
+ }
+ }
+ if (TestLoading & TEST_EXE_SELF)
+ {
+ if (pProcessInUse[index])
+ {
+ if (pTheProcesses[index].ExitType() != EExitPending)
+ {
+ if (pTheProcesses[index].ExitType() == EExitPanic)
+ {
+ DBGS_PRINT((_L("%S : Process %d Panic'd after %u ticks \n"),
+ &TestNameBuffer,
+ index + ((TestLoading & TEST_DLL) ? TestMultipleThreadCount : 0),
+ User::TickCount() - start));
+ processPanic ++;
+ }
+ else
+ {
+ DBGS_PRINT((_L("%S : Process %d Exited after %u ticks \n"),
+ &TestNameBuffer,
+ index + ((TestLoading & TEST_DLL) ? TestMultipleThreadCount : 0),
+ User::TickCount() - start));
+ processOk ++;
+ }
+
+ pTheProcesses[index].Close();
+ pProcessInUse[index] = EFalse;
+ }
+ else
+ {
+ processCount += 1;
+ anyUsed = ETrue;
+ if (TestThreadsExit)
+ {
+ now = User::TickCount();
+ time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
+ if (time > TEST_DOT_PERIOD)
+ {
+ DBGS_PRINT((_L("%S : Process %d still running; killing it.\n"),
+ &TestNameBuffer, index));
+ pTheProcesses[index].Kill(EExitKill);
+ pTheProcesses[index].Close();
+ pProcessInUse[index] = EFalse;
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ now = User::TickCount();
+ time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
+
+ DBGD_PRINT((_L("%S : %d seconds (%d ticks) %d threads, %d processes still alive\n"),
+ &TestNameBuffer, time, now, threadCount, processCount));
+
+ if (time > TEST_DOT_PERIOD)
+ {
+ DBGS_PRINT((_L(".")));
+ numDots ++;
+ end += TEST_DOT_PERIOD*1000000/TickPeriod;
+ if (TestingReaper)
+ {
+ TestingReaperCleaningFiles = ETrue;
+ CleanupFiles(EFalse);
+ CheckFilePresence(ETrue);
+ TestingReaperCleaningFiles = EFalse;
+ }
+ if ((numDots >= maxDots) && (!TestThreadsExit))
+ {
+ DBGS_PRINT((_L("Taking longer than %d dots...exiting test case."), maxDots));
+ TestThreadsExit = ETrue;
+ killNext = end;
+ }
+ }
+
+ if (TestingChunks)
+ {
+ DoSomeChunking();
+ }
+
+#ifdef TEST_THRASHING_TEST
+ User::AfterHighRes(1000);
+#else
+ User::AfterHighRes(TickPeriod);
+#endif
+ }
+
+ DBGD_PRINT((_L("%S : all test threads presumably gone now\n"), &TestNameBuffer));
+
+ if (TestMediaAccess != KTestMediaAccessNone)
+ {
+ if (TestMediaAccess != KTestMediaAccessBasic)
+ {
+ TBool killMedia = EFalse;
+ TestStopMedia = ETrue;
+ anyUsed = ETrue;
+ DBGS_PRINT((_L("%S : Waiting for media threads to exit...\n"), &TestNameBuffer));
+ end = User::TickCount();
+ while (anyUsed)
+ {
+ anyUsed = EFalse;
+
+ // check the message queue and call printf if we get a message.
+ if (!TestSilent)
+ {
+ while (KErrNone == TestMsgQueue.Receive(localBuffer))
+ {
+ DBGS_PRINT((localBuffer));
+ }
+ }
+
+ for (index = 0; index < TestMultipleThreadCount; index++)
+ {
+ if (pMedInUse[index])
+ {
+ if (pMedThreads[index].ExitType() != EExitPending)
+ {
+ if (pMedThreads[index].ExitType() == EExitPanic)
+ {
+ DBGS_PRINT((_L("%S : Media Thread %d Panic'd after %u ticks \n"),
+ &TestNameBuffer, index, User::TickCount() - start));
+ threadPanic ++;
+ }
+ else
+ {
+ DBGS_PRINT((_L("%S : Media Thread %d Exited after %u ticks \n"),
+ &TestNameBuffer, index, User::TickCount() - start));
+ threadOk ++;
+ }
+ pMedInUse[index] = EFalse;
+ }
+ else
+ {
+ anyUsed = ETrue;
+ if (killMedia)
+ {
+ DBGS_PRINT((_L("%S : Media Thread %d still going after %u ticks; killing it!\n"),
+ &TestNameBuffer, index, User::TickCount() - start));
+ pMedThreads[index].Kill(EExitKill);
+ }
+ }
+ }
+ }
+ now = User::TickCount();
+ time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
+ if (time > TEST_DOT_PERIOD)
+ {
+ DBGS_PRINT((_L(".")));
+ end += TEST_DOT_PERIOD*1000000/TickPeriod;
+ killMedia = ETrue;
+ }
+
+ User::AfterHighRes(50000);
+
+ }
+ DBGS_PRINT((_L("%S : Media threads exited...\n"), &TestNameBuffer));
+ User::Free(pMedThreads);
+ User::Free(pMedInUse);
+ }
+ else
+ {
+ TestStopMedia = ETrue;
+ DBGS_PRINT((_L("%S : Waiting for media thread to exit...\n"), &TestNameBuffer));
+ end = User::TickCount();
+ while (mediaThread.ExitType() == EExitPending)
+ {
+ now = User::TickCount();
+ time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
+ if (time > TEST_DOT_PERIOD)
+ {
+ DBGS_PRINT((_L("%S : Media thread still going after %u seconds; killing it!\n"),
+ &TestNameBuffer, time));
+ mediaThread.Kill(EExitKill);
+ }
+ User::AfterHighRes(50000);
+ }
+ User::WaitForRequest(mediaStatus);
+ mediaThread.Close();
+ DBGS_PRINT((_L("%S : Media thread exited...\n"), &TestNameBuffer));
+ }
+ }
+
+ DBGD_PRINT((_L("%S : all media threads presumably gone now\n"), &TestNameBuffer));
+
+ if (!TestSilent)
+ {
+ TestMsgQueue.Close();
+ }
+ TestMultiSem.Close();
+
+ DBGD_PRINT((_L("%S : about to close the libraries\n"), &TestNameBuffer));
+
+ if (TestLoadDllHow == TEST_DLL_GLOBAL)
+ {
+ CloseTheLibs(theGlobalLibs, maxDlls);
+ }
+
+ TestThreadsExit = EFalse;
+
+ DBGD_PRINT((_L("%S : cleaning up\n"), &TestNameBuffer));
+
+ // cleanup the resources and exit.
+ if (TestLoading & TEST_EXE_SELF)
+ {
+ User::Free(pTheProcesses);
+ User::Free(pProcessInUse);
+ }
+
+ // cleanup the resources and exit.
+ if (TestLoading & TEST_DLL)
+ {
+ User::Free(pTheThreads);
+ User::Free(pThreadInUse);
+ }
+
+ if (!TestSilent)
+ {
+ end = User::TickCount();
+ time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
+ DBGS_PRINT((_L("\n%S : Multiple Test : (%u seconds)\n\tThreads panic'd = %d Ok = %d\n\tProcess panic'd = %d Ok = %d\n"), &TestNameBuffer, time, threadPanic, threadOk, processPanic, processOk));
+ }
+
+ thisThread.SetPriority(savedThreadPriority);
+
+ return (threadPanic | processPanic) ? KErrGeneral : KErrNone;
+ }
+
+//
+// DoChunkTests
+//
+// Allocate a chunk and assign some pages to it...
+// Then do a multiple test.
+//
+
+void DoChunkTests()
+ {
+ SVMCacheInfo tempPages;
+ memset(&tempPages, 0, sizeof(tempPages));
+ if (TestIsDemandPaged)
+ {
+ // Shrink the page cache down to the minimum.
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+
+ DBGS_PRINT((_L("Start : min %d max %d current %d maxFree %d freeRam %d\n"),
+ tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam()));
+
+ // set the cache small
+ TInt minSize = 16 * TestPageSize;
+ TInt maxSize = TEST_NUM_PAGES * TestPageSize;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+
+ if (KErrNone != TestChunk.CreateDisconnectedLocal(0,0,TEST_NUM_CHUNK_PAGES *TestPageSize))
+ {
+ DBGS_PRINT((_L("DoChunkTests - create failed.\n")));
+ return;
+ }
+ TestChunkBase = TestChunk.Base();
+ if (TestChunkBase == NULL)
+ {
+ RDebug::Printf("DoChunkTests - TestChunkBase was NULL");
+ TestChunk.Close();
+ return;
+ }
+ TInt retVal = KErrNone;
+ TUint index = 0;
+ TestCommitEnd = 0;
+ memset(TestChunkPageState, 0, sizeof(TestChunkPageState));
+ memset(TestChunkStats,0,sizeof(TestChunkStats));
+ while(index < TEST_NUM_CHUNK_PAGES)
+ {
+ retVal = TestChunk.Commit(TestCommitEnd,TestPageSize);
+ if (KErrNone != retVal)
+ {
+ DBGS_PRINT((_L("%S : TestChunk.Commit returned %d for 0x%08x...\n"), &TestNameBuffer, retVal, TestCommitEnd));
+ break;
+ }
+ TestChunkPageState[index] = ETrue;
+ FillPage(TestCommitEnd);
+ TestCommitEnd += TestPageSize;
+ index ++;
+ }
+ RUNTEST1(retVal == KErrNone);
+
+ // now do some testing....
+ TestingChunks = ETrue;
+ TestInterleave = EFalse;
+ TestPrioChange = ETrue;
+ TestMediaAccess = KTestMediaAccessNone;
+ // temp
+ TestWhichMedia = TEST_MEDIA_ROM_BASE;
+
+ if (TestChunksPlus)
+ {
+ TestMaxLoops = 1;
+ TestMultipleThreadCount = 40;
+ }
+ else if (TestExtremeChunks)
+ {
+ TestMaxLoops = 10;
+ TestMultipleThreadCount = 12;
+ }
+ else
+ {
+ TestMaxLoops = 3;
+ TestMultipleThreadCount = 20;
+ }
+ TestWhichTests = TEST_RANDOM;
+
+ TestLoading = TEST_EXE_SELF_DLL;
+ TestLoadDllHow = TEST_DLL_FUNC;
+ TestChunkingIndexFails = 0;
+
+ TEST_NEXT((_L("Multiple threads random with chunks.")));
+ RUNTEST(DoMultipleTest(), KErrNone);
+
+ TestingChunks = EFalse;
+
+ // clean up.
+ UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0);
+ TestChunk.Close();
+
+ if (TestIsDemandPaged)
+ {
+ // put the cache back to the the original values.
+ TInt minSize = tempPages.iMinSize;
+ TInt maxSize = tempPages.iMaxSize;
+
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+
+ DBGS_PRINT((_L("Finish : min %d max %d current %d maxFree %d freeRam %d\n"),
+ tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam()));
+ }
+ TChunkTestStats stats;
+
+ memset(&stats, 0, sizeof(stats));
+ DBGS_PRINT((_L("Stats : (pass/fail) \nindex\t\tlock\t\tunlock\t\tcommit\t\tdecommit\t\tcheck\n")));
+ for (index = 0; index < TEST_NUM_CHUNK_PAGES; index ++)
+ {
+ DBGS_PRINT((_L("%u\t\t%d/%d\t\t%d/%d\t\t%d/%d\t\t%d/%d\t\t%d/%d\n"),
+ index,
+ TestChunkStats[index].lock.ok, TestChunkStats[index].lock.fail,
+ TestChunkStats[index].unlock.ok, TestChunkStats[index].unlock.fail,
+ TestChunkStats[index].commit.ok, TestChunkStats[index].commit.fail,
+ TestChunkStats[index].decommit.ok, TestChunkStats[index].decommit.fail,
+ TestChunkStats[index].check.ok, TestChunkStats[index].check.fail));
+
+ stats.lock.ok += TestChunkStats[index].lock.ok;
+ stats.lock.fail += TestChunkStats[index].lock.fail;
+ stats.unlock.ok += TestChunkStats[index].unlock.ok;
+ stats.unlock.fail += TestChunkStats[index].unlock.fail;
+ stats.decommit.ok += TestChunkStats[index].decommit.ok;
+ stats.decommit.fail += TestChunkStats[index].decommit.fail;
+ stats.commit.ok += TestChunkStats[index].commit.ok;
+ stats.commit.fail += TestChunkStats[index].commit.fail;
+ stats.check.ok += TestChunkStats[index].check.ok;
+ stats.check.fail += TestChunkStats[index].check.fail;
+ }
+
+ DBGS_PRINT((_L("Total Stats (p/f): \n\t lock %d / %d\n\t unlock %d / %d\n\t commit %d / %d\n\t decommit %d / %d\n\t check %d / %d\n"),
+ stats.lock.ok, stats.lock.fail,
+ stats.unlock.ok, stats.unlock.fail,
+ stats.commit.ok, stats.commit.fail,
+ stats.decommit.ok, stats.decommit.fail,
+ stats.check.ok, stats.check.fail));
+ DBGS_PRINT((_L("TestChunkingIndexFails %d\n"), TestChunkingIndexFails));
+
+ }
+
+//
+// DoReaperTests
+//
+// Test the reaper by deleting the transient files and re-creating them.
+//
+
+void DoReaperTests(void)
+ {
+ // make sure we have the full complement of files.
+ CheckFilePresence(ETrue);
+
+ // now do some testing....
+ TestInterleave = EFalse;
+ TestPrioChange = EFalse;
+ TestMediaAccess = KTestMediaAccessNone;
+ // temp
+ TestWhichMedia = TEST_MEDIA_ALL;
+ TestMaxLoops = 3;
+ TestMultipleThreadCount = 12;
+ TestWhichTests = TEST_RANDOM;
+
+ TestLoading = TEST_EXE_SELF_DLL;
+ TestLoadDllHow = TEST_DLL_FUNC;
+
+ TestingReaper = ETrue;
+
+ TEST_NEXT((_L("Reaper tests.")));
+ RUNTEST(DoMultipleTest(), KErrNone);
+ TestInterleave = ETrue;
+ TestPrioChange = ETrue;
+ TEST_NEXT((_L("Reaper tests 2.")));
+ RUNTEST(DoMultipleTest(), KErrNone);
+
+ TestingReaper = EFalse;
+ }
+
+//
+// DoBtraceTest
+//
+// Test the paging BTrace function.
+//
+
+void DoBtraceTest(void)
+ {
+#define LE4(a) ((*((a) + 3) << 24) + (*((a) + 2) << 16) + (*((a) + 1) << 8) + *(a))
+
+ RBTrace bTraceHandle;
+
+ TInt r = bTraceHandle.Open();
+ test(r == KErrNone);
+
+ r = bTraceHandle.ResizeBuffer(0x200000);
+ test(r == KErrNone);
+ bTraceHandle.SetFilter(BTrace::EPaging, ETrue);
+
+ // Enable trace
+ bTraceHandle.Empty();
+ bTraceHandle.SetMode(RBTrace::EEnable);
+
+ TestLoading = TEST_EXE_SELF_DLL;
+ TestWhichMedia = TEST_MEDIA_ROM_BASE;
+ TestMaxLoops = 2;
+ TestMultipleThreadCount = 10;
+ TestLoadDllHow = TEST_DLL_FUNC;
+ TestInterleave = ETrue;
+ TestPrioChange = ETrue;
+ TestMediaAccess = KTestMediaAccessNone;
+ TestWhichTests = TEST_RANDOM;
+ TestingLowMem = EFalse;
+
+ RUNTEST(DoMultipleTest(TestingLowMem), KErrNone);
+
+ bTraceHandle.SetMode(0);
+
+ // analyse the btrace logs and display on the serial port.
+ TUint8* pDataStart;
+ TInt dataSize;
+ TUint8* pTemp;
+ TUint8* pThis;
+ TUint8* pEnd;
+ TBuf<128> data;
+ while (1)
+ {
+ dataSize = bTraceHandle.GetData(pDataStart);
+ if (dataSize <= 0)
+ {
+ break;
+ }
+ pEnd = pDataStart + dataSize;
+ pTemp = pDataStart;
+ while (pTemp < pEnd)
+ {
+ TUint8 recSize = pTemp[BTrace::ESizeIndex];
+ TUint8 recFlags = pTemp[BTrace::EFlagsIndex];
+ TUint8 recCat = pTemp[BTrace::ECategoryIndex];
+ TUint8 recSub = pTemp[BTrace::ESubCategoryIndex];
+ TUint32 addr[4];
+ pThis = pTemp;
+
+ data.Zero();
+ // step over the header.
+ data.Format(_L("size %d cat %d sub %d flg 0x%02x "), recSize, recCat, recSub, recFlags);
+ pTemp += 4;
+
+ if (recFlags & BTrace::EHeader2Present)
+ {
+ data.AppendFormat(_L("h2 0x%08x "), LE4(pTemp));
+ pTemp += 4;
+ }
+ if (recFlags & BTrace::ETimestampPresent)
+ {
+ data.AppendFormat(_L("ts 0x%08x "), LE4(pTemp));
+ pTemp += 4;
+ }
+ if (recFlags & BTrace::ETimestamp2Present)
+ {
+ data.AppendFormat(_L("ts2 0x%08x "), LE4(pTemp));
+ pTemp += 4;
+ }
+ if (recFlags & BTrace::EContextIdPresent)
+ {
+ data.AppendFormat(_L("cId 0x%08x "), LE4(pTemp));
+ pTemp += 4;
+ }
+ TInt index;
+ for (index = 0; index < 4; index ++)
+ {
+ if (recSize > pTemp - pThis)
+ {
+ addr[index] = LE4(pTemp);
+ pTemp += 4;
+ }
+ else
+ addr[index] = 0;
+ }
+
+ switch(recCat)
+ {
+ case BTrace::EPaging:
+ {
+ switch (recSub)
+ {
+ case BTrace::EPagingPageInBegin:
+ /**
+ - 4 bytes containing the virtual address which was accessed, causing this paging event.
+ - 4 bytes containing the virtual address of the instuction which caused this paging event.
+ (The PC value.)
+ **/
+ test.Printf(_L("PageInBegin : %S addr 0x%08x inst 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 0 bytes. (No extra data.)
+ */
+ case BTrace::EPagingPageInUnneeded:
+ test.Printf(_L("PageInUnneeded : %S\n"), &data);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page 'paged in'.
+ - 4 bytes containing the virtual address of the page 'paged in'.
+ */
+ case BTrace::EPagingPageInROM:
+ test.Printf(_L("PageInROM : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being 'paged out'.
+ - 4 bytes containing the virtual address of the page being 'paged out'.
+ */
+ case BTrace::EPagingPageOutROM:
+ test.Printf(_L("PageOutROM : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being 'paged in'.
+ */
+ case BTrace::EPagingPageInFree:
+ test.Printf(_L("PageInFree : %S phys 0x%08x\n"), &data, addr[0]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being 'paged out'.
+ */
+ case BTrace::EPagingPageOutFree:
+ test.Printf(_L("PageOutFree : %S phys 0x%08x\n"), &data, addr[0]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being rejuvenated, (made young).
+ - 4 bytes containing the virtual address which was accessed, causing this paging event.
+ - 4 bytes containing the virtual address of the instuction which caused this paging event.
+ (The PC value.)
+ */
+ case BTrace::EPagingRejuvenate:
+ test.Printf(_L("Rejuvenate : %S phys 0x%08x virt 0x%08x inst 0x%08x\n"), &data, addr[0], addr[1], addr[2]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page accessed.
+ - 4 bytes containing the virtual address which was accessed, causing this paging event.
+ - 4 bytes containing the virtual address of the instuction which caused this paging event.
+ (The PC value.)
+ */
+ case BTrace::EPagingPageNop:
+ test.Printf(_L("PageNop : %S phys 0x%08x virt 0x%08x inst 0x%08x\n"), &data, addr[0], addr[1], addr[2]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being locked.
+ - 4 bytes containing the value of the lock count after the paged was locked.
+ */
+ case BTrace::EPagingPageLock:
+ test.Printf(_L("PageLock : %S phys 0x%08x lock 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being unlocked.
+ - 4 bytes containing the value of the lock count before the paged was unlocked.
+ */
+ case BTrace::EPagingPageUnlock:
+ test.Printf(_L("PageUnlock : %S phys 0x%08x lock 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being 'paged out'.
+ - 4 bytes containing the virtual address of the page being 'paged out'.
+ */
+ case BTrace::EPagingPageOutCache:
+ test.Printf(_L("PageOutCache : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page 'paged in'.
+ - 4 bytes containing the virtual address of the page 'paged in'.
+ */
+ case BTrace::EPagingPageInCode:
+ test.Printf(_L("PageInCode : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being 'paged out'.
+ - 4 bytes containing the virtual address of the page being 'paged out'.
+ */
+ case BTrace::EPagingPageOutCode:
+ test.Printf(_L("PageOutCode : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page 'paged in'.
+ - 4 bytes containing the virtual address of the page 'paged in'.
+ */
+ case BTrace::EPagingMapCode:
+ test.Printf(_L("MapCode : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
+ break;
+
+ /**
+ - 4 bytes containing the physical address of the page being aged, (made old).
+ */
+ case BTrace::EPagingAged:
+ test.Printf(_L("Aged : %S phys 0x%08x\n"), &data, addr[0]);
+ break;
+ }
+ }
+ break;
+
+ default:
+
+ break;
+ }
+ pTemp = BTrace::NextRecord(pThis);
+ }
+ bTraceHandle.DataUsed();
+ }
+ bTraceHandle.Close();
+ }
+
+//
+// ParseCommandLine
+//
+// read the arguments passed from the command line and set global variables to
+// control the tests.
+//
+
+TBool ParseCommandLine()
+ {
+ TBuf<256> args;
+ User::CommandLine(args);
+ TLex lex(args);
+ TBool retVal = ETrue;
+
+ // initially test for arguments, the parse them, if not apply some sensible defaults.
+ TBool foundArgs = EFalse;
+
+ FOREVER
+ {
+ TPtrC token=lex.NextToken();
+ if(token.Length()!=0)
+ {
+ if ((token == _L("help")) || (token == _L("-h")) || (token == _L("-?")))
+ {
+ DBGS_PRINT((_L("\nUsage: [ single | multiple <numThreads>] [ dll | exe | self | complete ] [func | thread | global ] [ rom | base | mixed | mall ] [reaper] [chunks|echunks|chunks+ {nochunkdata}] [prio] [media] [lowmem] [forward | backward | random | all] [loadGlobal | loadThread | loadFunc] [interleave] [d_exc] [btrace] [defrag] [noclean] [min <pages>] [max <pages>] [stressfree] [iters <iters>]\n'-' indicated infinity.\n\n")));
+ test.Getch();
+ }
+ else if (token == _L("mmc"))
+ {
+ TestOnlyFromMmc = ETrue;
+ }
+ else if (token == _L("min"))
+ {
+ TPtrC val=lex.NextToken();
+ TLex lexv(val);
+ TInt value;
+ lexv.Val(value);
+ TestMinCacheSize = value * 4096;
+ }
+ else if (token == _L("max"))
+ {
+ TPtrC val=lex.NextToken();
+ TLex lexv(val);
+ TInt value;
+ lexv.Val(value);
+ TestMaxCacheSize = value * 4096;
+ }
+ else if (token == _L("interleave"))
+ {
+ TestInterleave = ETrue;
+ }
+ else if (token == _L("auto"))
+ {
+ TestFullAutoTest = EFalse;
+ retVal = EFalse;
+ }
+ else if (token == _L("stressfree"))
+ {
+ TestStressFree = !TestStressFree;
+ retVal = EFalse;
+ }
+ else if (token == _L("fullauto"))
+ {
+ TestFullAutoTest = ETrue;
+ retVal = EFalse;
+ }
+ else if (token == _L("prio"))
+ {
+ TestPrioChange = !TestPrioChange;
+ }
+ else if (token == _L("media"))
+ {
+ TestMediaAccess = KTestMediaAccessBasic;
+ }
+ else if (token == _L("reaper"))
+ {
+ TestReaper = ETrue;
+ }
+ else if (token == _L("btrace"))
+ {
+ TestBtrace = ETrue;
+ }
+ else if (token == _L("defrag"))
+ {
+ TestDefrag = ETrue;
+ }
+ else if (token == _L("echunks"))
+ {
+ TestChunks = ETrue;
+ TestExtremeChunks = ETrue;
+ }
+ else if (token == _L("chunks+"))
+ {
+ TestChunks = ETrue;
+ TestChunksPlus = ETrue;
+ }
+ else if (token == _L("chunks"))
+ {
+ TestChunks = ETrue;
+ }
+ else if (token == _L("nochunkdata"))
+ {
+ TestChunkData = EFalse;
+ }
+ else if (token == _L("lowmem"))
+ {
+ TestLowMem = ETrue;
+ }
+ else if (token == _L("dll"))
+ {
+ TestLoading = TEST_DLL;
+ }
+ else if (token == _L("exe"))
+ {
+ TestLoading = TEST_EXE;
+ }
+ else if (token == _L("self"))
+ {
+ TestLoading = TEST_SELF;
+ }
+ else if (token == _L("complete"))
+ {
+ TestLoading |= TEST_EXE_SELF_DLL;
+ }
+ else if (token == _L("rom"))
+ {
+ TestWhichMedia = TEST_MEDIA_ROM;
+ }
+ else if (token == _L("base"))
+ {
+ TestWhichMedia = TEST_MEDIA_BASE;
+ }
+ else if (token == _L("mixed"))
+ {
+ TestWhichMedia |= TEST_MEDIA_ROM_BASE;
+ }
+ else if (token == _L("all_media"))
+ {
+ TestWhichMedia |= TEST_MEDIA_ALL;
+ }
+ else if (token == _L("debug"))
+ {
+ if (!TestSilent)
+ {
+ TestDebug = ETrue;
+ TestPrioChange = ETrue;
+ }
+ }
+ else if (token == _L("silent"))
+ {
+ TestSilent = ETrue;
+ TestDebug = EFalse;
+ }
+ else if (token == _L("noclean"))
+ {
+ TestNoClean = ETrue;
+ }
+ else if (token == _L("d_exc"))
+ {
+ TestD_Exc = ETrue;
+ }
+ else if (token == _L("global"))
+ {
+ TestLoadDllHow = TEST_DLL_GLOBAL;
+ }
+ else if (token == _L("thread"))
+ {
+ TestLoadDllHow = TEST_DLL_THREAD;
+ }
+ else if (token == _L("func"))
+ {
+ TestLoadDllHow = TEST_DLL_FUNC;
+ }
+ else if (token == _L("single"))
+ {
+ TestSingle = ETrue;
+ }
+ else if (token == _L("multiple"))
+ {
+ TPtrC val=lex.NextToken();
+ TLex lexv(val);
+ TInt value;
+
+ if (lexv.Val(value)==KErrNone)
+ {
+ if ((value <= 0) || (value > 100))
+ {
+ TestMultipleThreadCount = 10;
+ }
+ else
+ {
+ TestMultipleThreadCount = value;
+ }
+ }
+ else
+ {
+ DBGS_PRINT((_L("Bad value for thread count '%S' was ignored.\n"), &val));
+ retVal = EFalse;
+ break;
+ }
+ TestMultiple = ETrue;
+ }
+ else if (token == _L("forward"))
+ {
+ TestWhichTests = TEST_FORWARD;
+ }
+ else if (token == _L("backward"))
+ {
+ TestWhichTests = TEST_BACKWARD;
+ }
+ else if (token == _L("random"))
+ {
+ TestWhichTests = TEST_RANDOM;
+ }
+ else if (token == _L("all"))
+ {
+ TestWhichTests = TEST_ALL;
+ }
+ else if (token == _L("inst"))
+ {
+ TPtrC val=lex.NextToken();
+ TLex lexv(val);
+ TInt value;
+
+ if (lexv.Val(value)==KErrNone)
+ {
+ TestInstanceId = value;
+ }
+ }
+ else if (token == _L("iters"))
+ {
+ TPtrC val=lex.NextToken();
+ TLex lexv(val);
+ TInt value;
+
+ if (val==_L("-"))
+ {
+ TestMaxLoops = KMaxTInt;
+ }
+ else
+ {
+ if (lexv.Val(value)==KErrNone)
+ {
+ TestMaxLoops = value;
+ }
+ else
+ {
+ DBGS_PRINT((_L("Bad value for thread count '%S' was ignored.\n"), &val));
+ retVal = EFalse;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if ((foundArgs == EFalse) && (token.Length() == 1))
+ {
+ // Single letter argument...only run on 'd'
+ if (token.CompareF(_L("d")) == 0)
+ {
+
+ TestFullAutoTest = EFalse;
+ TestIsAutomated = ETrue;
+ break;
+ }
+ else
+ {
+ if (!TestSilent)
+ {
+ test.Title();
+ test.Start(_L("Skipping non drive 'd' - Test Exiting."));
+ test.End();
+ }
+ foundArgs = ETrue;
+ TestExit = ETrue;
+ break;
+ }
+ }
+ DBGS_PRINT((_L("Unknown argument '%S' was ignored.\n"), &token));
+ break;
+ }
+ foundArgs = ETrue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (!foundArgs)
+ {
+ retVal = EFalse;
+ }
+ return retVal;
+ }
+
+//
+// AreWeTheTestBase
+//
+// Test whether we are the root of the tests.
+//
+void AreWeTheTestBase()
+ {
+ if (!TestSilent)
+ {
+ TFileName filename(RProcess().FileName());
+
+ TParse myParse;
+ myParse.Set(filename, NULL, NULL);
+ TestNameBuffer.Zero();
+ TestNameBuffer.Append(myParse.Name());
+ TestNameBuffer.Append(_L(".exe"));
+
+ TestWeAreTheTestBase = !TestNameBuffer.Compare(TestPlExeNames[KTestMediaBase]);
+
+ RFs fs;
+ if (KErrNone == fs.Connect())
+ {
+ TEntry anEntry;
+ TInt retVal = fs.Entry(_L("z:\\test\\mmcdemandpaginge32tests.bat"), anEntry);
+ if (retVal == KErrNone)
+ {
+ TestBootedFromMmc = ETrue;
+ }
+ else
+ {
+ TestBootedFromMmc = EFalse;
+ }
+ fs.Close();
+ }
+ }
+ else
+ {
+ TestNameBuffer.Zero();
+ TestNameBuffer.Append(_L("t_pageldrtst.exe"));
+ }
+ }
+#define MEDNONE KTestMediaAccessNone
+#define MEDBASIC KTestMediaAccessBasic
+#define MEDMTHRE KTestMediaAccessMultipleThreads
+#define MEDMPATT KTestMediaAccessMultiplePattern
+#define MEDMIX KTestMediaAccessMixed
+
+TTheTests TheAutoTests[] =
+ {// fullOnly, loading, media, multi, loops, threads, loadHow, inter, prio, media, whichTests, lowmem, free, testName
+#ifdef TEST_SHORT_TEST
+ { EFalse, TEST_DLL, TEST_MEDIA_ALL, ETrue, 2, 24, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL Load (ALL Media) Multiple thread all."), },
+#else
+ { EFalse, TEST_DLL, TEST_MEDIA_BASE, ETrue, 5, 24, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_THRASH, EFalse, 0, }, //_L("DLL Load (ROM) Multiple thread Thrash."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 5, 20, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_ALL, EFalse, 0, }, //_L("DLL Load (ROM/ROFS) Single thread all."), },
+ { ETrue, TEST_EXE, TEST_MEDIA_ROM_BASE, EFalse, 5, 20, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_ALL, EFalse, 0, }, //_L("Exe Load (ROM/ROFS) Single thread."), },
+ { ETrue, TEST_SELF, TEST_MEDIA_ROM_BASE, EFalse, 5, 20, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_ALL, EFalse, 0, }, //_L("Self Load (ROM/ROFS) Single thread."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, ETrue, 5, 20, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL Load (ROM/ROFS) Multiple thread all."), },
+ { EFalse, TEST_DLL, TEST_MEDIA_ALL, ETrue, 3, 20, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL Load (ALL Media) Multiple thread all."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, EFalse, ETrue, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with prio."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 10, TEST_DLL_FUNC, EFalse, EFalse, MEDBASIC, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with media access."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_FUNC, EFalse, ETrue, MEDBASIC, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with media access and prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_THREAD, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load thread (All Media) Multiple threads."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_THREAD, EFalse, ETrue, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load thread (All Media) Multiple threads with prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_THREAD, EFalse, ETrue, MEDBASIC, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load thread (All Media) Multiple threads with media access and prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_GLOBAL, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load global (All Media) Multiple threads."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_GLOBAL, EFalse, ETrue, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load global (All Media) Multiple threads with prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_GLOBAL, EFalse, ETrue, MEDBASIC, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load global (All Media) Multiple threads with media access and prio."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, ETrue, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, prio."), },
+
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, ETrue, MEDBASIC, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, media and prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_FUNC, ETrue, ETrue, MEDMTHRE, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, multi media and prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_FUNC, ETrue, ETrue, MEDMPATT, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, media and prio."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_FUNC, ETrue, ETrue, MEDMIX, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, media and prio."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 10, TEST_DLL_FUNC, ETrue, ETrue, MEDMIX, TEST_RANDOM, EFalse, 0, }, //_L("DLL/EXE/SELF Load Multiple threads with interleave, media and prio."), },
+#endif // TEST_SHORT_TEST
+ };
+#define NUM_AUTO_TESTS (TInt)(sizeof(TheAutoTests) / sizeof(TTheTests))
+
+//
+// PerformAutoTest
+//
+// The autotest.
+//
+
+void PerformAutoTest(TBool aReduceTime = EFalse)
+ {
+ TInt testIndex;
+ TTheTests *pTest = &TheAutoTests[0];
+
+ DoStats();
+
+ for (testIndex = 0; testIndex < NUM_AUTO_TESTS; testIndex ++, pTest++)
+ {
+ if ( ( !TestWeAreTheTestBase
+ && ( (pTest->testLoadDllHow != TEST_DLL_FUNC)
+ || !pTest->testMultiple))
+ || ((TestFullAutoTest == EFalse) && (pTest->testFullAutoOnly)))
+ {
+ continue;
+ }
+
+ TestLoading = pTest->testLoading;
+ TestWhichMedia = pTest->testWhichMedia;
+ TestMaxLoops = aReduceTime ? 1 : pTest->testMaxLoops;
+ TestMultipleThreadCount = aReduceTime ? 10 : pTest->testMultipleThreadCount;
+ TestLoadDllHow = pTest->testLoadDllHow;
+ TestInterleave = pTest->testInterleave;
+ TestPrioChange = pTest->testPrioChange;
+ TestMediaAccess = pTest->testMediaAccess;
+ if (aReduceTime && (TestMediaAccess != MEDBASIC) && (TestMediaAccess != MEDNONE))
+ {
+ continue;
+ }
+ TestWhichTests = pTest->testWhichTests;
+ TestingLowMem = pTest->testLowMem;
+ if (!TestSilent)
+ {
+ test.Next(_L("Auto Test"));
+ }
+ if (pTest->testMultiple)
+ {
+ RUNTEST(DoMultipleTest(ETrue), KErrNone);
+ }
+ else
+ {
+ RUNTEST(DoSingleTest(ETrue), KErrNone);
+ }
+
+ DoStats();
+
+#ifdef TEST_KERN_HEAP
+ __KHEAP_MARK;
+ __KHEAP_CHECK(0);
+ __KHEAP_MARKEND;
+#endif
+ }
+#ifdef TEST_KERN_HEAP
+ __KHEAP_MARK;
+ __KHEAP_CHECK(0);
+ __KHEAP_MARKEND;
+#endif
+ }
+
+TTheTests TheLowMemTests[] =
+ {// fullOnly, loading, media, multi, loops, threads, loadHow, inter, prio, media, whichTests, lowmem, free, testName
+#ifndef TEST_SHORT_TEST
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Single thread with Low memory (init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, EFalse, 5, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, ETrue, 0, }, //_L("Single thread with Low memory."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory (init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 16, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory ."), },
+ { EFalse, TEST_DLL, TEST_MEDIA_ALL, EFalse, 5, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory and All media(init)."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 12, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory and All media."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory, with starting free ram (init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 16, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, ETrue, 32, }, //_L("Multiple thread with Low memory, with starting free ram."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 16, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory and prio and media access(init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 16, TEST_DLL_FUNC, EFalse, ETrue, MEDBASIC, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory and prio and media access."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory interleave, prio and media access(init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, ETrue, MEDBASIC, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory interleave, prio and media access."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory interleave, media access and All media (init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, EFalse, MEDBASIC, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory interleave, media access and All media + loading."), },
+ { EFalse, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 10, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Single thread with Low memory (init)."), },
+ { EFalse, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 5, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, ETrue, 0, }, //_L("Single thread with Low memory."), },
+#endif //TEST_SHORT_TEST
+ { EFalse, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 10, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, ETrue, MEDBASIC, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media + loading."), },
+ { EFalse, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 5, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
+ { EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, ETrue, 2, 10, TEST_DLL_FUNC, ETrue, ETrue, MEDMTHRE, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory interleave, prio, multi media access and All media + loading."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, ETrue, MEDBASIC, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media + loading."), },
+ { ETrue, TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse, 1, 1, TEST_DLL_FUNC, EFalse, EFalse, MEDNONE, TEST_RANDOM, EFalse, 0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
+ { ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL, ETrue, 2, 16, TEST_DLL_FUNC, ETrue, ETrue, MEDMTHRE, TEST_RANDOM, ETrue, 0, }, //_L("Multiple thread with Low memory interleave, prio, multi media access and All media + loading."), },
+
+ };
+#define NUM_LOWMEM_TESTS (TInt)(sizeof(TheLowMemTests) / sizeof(TTheTests))
+
+//
+// DoLowMemTest
+//
+// Low Memory Test
+//
+void DoLowMemTest(TBool aEnableAllMedia = EFalse)
+ {
+ TInt r = User::LoadLogicalDevice(KPageStressTestLddName);
+ RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
+ RUNTEST(PagestressLdd.Open(),KErrNone);
+ RUNTEST(PagestressLdd.DoSetDebugFlag((TInt)TestDebug),KErrNone);
+
+ SVMCacheInfo tempPages;
+ memset(&tempPages, 0, sizeof(tempPages));
+ if (TestIsDemandPaged)
+ {
+ // get the old cache info
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+ TInt minSize = 8 * 4096;
+ TInt maxSize = 256 * 4096;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+
+ TInt testIndex;
+ TTheTests *pTest = &TheLowMemTests[0];
+ for (testIndex = 0; testIndex < NUM_LOWMEM_TESTS; testIndex ++, pTest++)
+ {
+ if ( (!aEnableAllMedia && (pTest->testWhichMedia == TEST_MEDIA_ALL))
+ || ((TestFullAutoTest == EFalse) && (pTest->testFullAutoOnly)))
+ {
+ continue;
+ }
+
+ TestLoading = pTest->testLoading;
+ TestWhichMedia = pTest->testWhichMedia;
+ TestMaxLoops = pTest->testMaxLoops;
+ TestMultipleThreadCount = pTest->testMultipleThreadCount;
+ TestLoadDllHow = pTest->testLoadDllHow;
+ TestInterleave = pTest->testInterleave;
+ TestPrioChange = pTest->testPrioChange;
+ TestMediaAccess = pTest->testMediaAccess;
+ TestWhichTests = pTest->testWhichTests;
+ TestingLowMem = pTest->testLowMem;
+ if (!TestSilent)
+ {
+ test.Next(_L("Low Memory"));
+ }
+ if (pTest->testLowMem)
+ {
+ PagestressLdd.DoConsumeRamSetup(pTest->testFreeRam, TEST_LM_BLOCKSIZE);
+ }
+
+ if (pTest->testMultiple)
+ {
+ RUNTEST(DoMultipleTest(pTest->testLowMem), KErrNone);
+ }
+ else
+ {
+ RUNTEST(DoSingleTest(pTest->testLowMem), KErrNone);
+ }
+
+ if (pTest->testLowMem)
+ {
+ PagestressLdd.DoConsumeRamFinish();
+ }
+
+ DoStats();
+#ifdef TEST_KERN_HEAP
+ __KHEAP_MARK;
+ __KHEAP_CHECK(0);
+ __KHEAP_MARKEND;
+#endif
+ }
+
+ if (!TestSilent)
+ {
+ test.Next(_L("Close test driver"));
+ }
+ PagestressLdd.Close();
+ RUNTEST(User::FreeLogicalDevice(KPageStressTestLddName), KErrNone);
+
+ if (TestIsDemandPaged)
+ {
+ TInt minSize = tempPages.iMinSize;
+ TInt maxSize = tempPages.iMaxSize;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+
+#ifdef TEST_KERN_HEAP
+ __KHEAP_MARK;
+ __KHEAP_CHECK(0);
+ __KHEAP_MARKEND;
+#endif
+ TestingLowMem = EFalse;
+
+ }
+
+//
+// MultipleDefragThread
+//
+// Thread function, one created for each zone in a multiple thread test.
+//
+
+LOCAL_C TInt MultipleDefragThread(TAny* aUseTb)
+ {
+ TInt numZones = 1;
+ TInt zoneId = (TInt)aUseTb;
+
+ if (TestZoneCount > TEST_MAX_ZONE_THREADS)
+ {
+ numZones = TestZoneCount / TEST_MAX_ZONE_THREADS;
+ }
+
+ while (1)
+ {
+ TInt index = 0;
+ TInt tempy = 0;
+ for (; index < numZones; index ++)
+ {
+ User::AfterHighRes(TEST_MAX_ZONE_THREADS*TickPeriod/4);
+ tempy = zoneId + (TEST_MAX_ZONE_THREADS * index);
+ if (tempy < (TInt)TestZoneCount)
+ {
+ RamstressLdd.DoMovePagesInZone(tempy);
+ }
+ if (TestDefragTestEnd)
+ break;
+ }
+ if (TestDefragTestEnd)
+ break;
+ }
+ return KErrNone;
+ }
+
+//
+// DoDefragAutoTest
+//
+// Call the auto tests whilst defraging in the background.
+//
+
+void DoDefragAutoTest()
+ {
+ TUint localZoneCount = TestZoneCount;
+ if (TestZoneCount > TEST_MAX_ZONE_THREADS)
+ {
+ localZoneCount = TEST_MAX_ZONE_THREADS;
+ }
+ TInt size = (sizeof(RThread) * localZoneCount)
+ + (sizeof(TInt) * localZoneCount);
+ TUint8* pBuf = (TUint8*)User::AllocZ(size);
+
+ test(pBuf != NULL);
+ RThread *pTheThreads = (RThread*)pBuf;
+ TInt *pThreadInUse = (TInt*)(pTheThreads + localZoneCount);
+ TInt ret;
+ TUint index;
+ for (index = 0; index < localZoneCount; index ++)
+ {
+ DBGS_PRINT((_L("%S : Starting Defrag Thread %d\n"), &TestNameBuffer, index));
+ ret = pTheThreads[index].Create(KTestBlank,MultipleDefragThread,KDefaultStackSize,NULL,(TAny*) index);
+ if (ret == KErrNone)
+ {
+ pTheThreads[index].Resume();
+ pThreadInUse[index] = 1;
+ }
+ else
+ {
+ DBGS_PRINT((_L("%S : Starting Defrag Thread Failed %d\n"), &TestNameBuffer, index));
+ }
+ }
+
+ // Do the full auto tests...
+ PerformAutoTest(TestIsDemandPaged);
+
+ TestDefragTestEnd = ETrue;
+ RamstressLdd.DoSetEndFlag(1);
+ TBool anyUsed = ETrue;
+
+ DBGS_PRINT((_L("%S : Waiting for Defrag Threads to exit...\n"), &TestNameBuffer));
+ TUint killNext = User::TickCount();
+ while(anyUsed)
+ {
+ anyUsed = EFalse;
+
+ // walk through the thread list to check which are still alive.
+ for (index = 0; index < localZoneCount; index++)
+ {
+ if (pThreadInUse[index])
+ {
+ if (pTheThreads[index].ExitType() != EExitPending)
+ {
+ if (pTheThreads[index].ExitType() == EExitPanic)
+ {
+ DBGS_PRINT((_L("%S : Defrag Thread %d Panic'd\n"), &TestNameBuffer, index));
+ }
+ else
+ {
+ DBGS_PRINT((_L("%S : Defrag Thread %d Exited\n"), &TestNameBuffer, index));
+ }
+ pTheThreads[index].Close();
+ pThreadInUse[index] = EFalse;
+ }
+ else
+ {
+ anyUsed = ETrue;
+ TUint now = User::TickCount();
+ TUint time = TUint((TUint64)(now-killNext)*(TUint64)TickPeriod/(TUint64)1000000);
+ const TUint killTimeStep = (TEST_DOT_PERIOD+9)/10; // 1/10th of a dot
+ if(time>TEST_DOT_PERIOD+killTimeStep)
+ {
+ killNext += killTimeStep*1000000/TickPeriod;
+ DBGS_PRINT((_L("%S : killing Defrag Thread %d\n"), &TestNameBuffer, index));
+ pTheThreads[index].Kill(KErrNone);
+ pTheThreads[index].Close();
+ pThreadInUse[index] = EFalse;
+ }
+ }
+ }
+ }
+ User::After(500000);
+ }
+ DBGS_PRINT((_L("%S : Defrag Threads exited...\n"), &TestNameBuffer));
+ RamstressLdd.DoSetEndFlag(0);
+ User::Free(pBuf);
+ }
+
+//
+// DoDefragTest
+//
+// Test the ram defrag code.
+//
+
+void DoDefragTest(void)
+ {
+ SVMCacheInfo tempPages;
+ memset(&tempPages, 0, sizeof(tempPages));
+
+ test.Next(_L("Ram Defrag : Get the number of zones"));
+ // first get the number of zones
+ TInt ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneCount,&TestZoneCount,0);
+ if(ret==KErrNotSupported)
+ {
+ test.Next(_L("TESTS NOT RUN - Ram Defrag appears to not be supported.\n"));
+ return;
+ }
+ test(ret == KErrNone);
+ test(TestZoneCount != 0);
+ test.Printf(_L("RAM Zones (count=%u)\n"),TestZoneCount);
+
+ // now get the config of each of the zones.
+ TUint index;
+ struct SRamZoneConfig config;
+ struct SRamZoneUtilisation util;
+ test.Next(_L("Ram Defrag : Get info about the zones"));
+ for (index = 0; index < TestZoneCount; index ++)
+ {
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)index, (TAny*)&config);
+ test(ret == KErrNone);
+ test.Printf(_L("config : id=%d index=%d base=0x%08x end=0x%08x pages=%d pref=%d flags=0x%x\n"),
+ config.iZoneId,config.iZoneIndex,config.iPhysBase,config.iPhysEnd,config.iPhysPages,
+ config.iPref,config.iFlags);
+
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)index, (TAny*)&util);
+ test(ret == KErrNone);
+ test.Printf(_L("usage : id=%d index=%d pages=%d free=%d unknown=%d fixed=%d move=%d discard=%d other=%d\n"),
+ util.iZoneId,util.iZoneIndex,util.iPhysPages,util.iFreePages,
+ util.iAllocUnknown,util.iAllocFixed,util.iAllocMovable,util.iAllocDiscardable,util.iAllocOther);
+ }
+ // Now test for zones out of range.
+ test.Next(_L("Ram Defrag : test out of range indexes"));
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)(TestZoneCount + 1), (TAny*)&config);
+ test(ret != KErrNone);
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)(TestZoneCount + 1), (TAny*)&util);
+ test(ret != KErrNone);
+
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)-1, (TAny*)&config);
+ test(ret != KErrNone);
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)-1, (TAny*)&util);
+ test(ret != KErrNone);
+ test.Next(_L("Ram Defrag : test out of range enums"));
+ ret = UserSvr::HalFunction(EHalGroupRam,-1, 0, 0);
+ test(ret != KErrNone);
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation + 1,0, 0);
+ test(ret != KErrNone);
+
+ TInt r = User::LoadLogicalDevice(KRamStressTestLddName);
+ RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
+ RUNTEST(RamstressLdd.Open(),KErrNone);
+ //TestDebug = ETrue;
+ RUNTEST(RamstressLdd.DoSetDebugFlag((TInt)TestDebug),KErrNone);
+
+ test.Next(_L("Ram Defrag : set VM cache to stress free..."));
+
+ if (TestIsDemandPaged)
+ {
+ // get the old cache info
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+
+ TInt minSize = 512 * 4096;
+ TInt maxSize = 32767 * 4096;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+
+ test.Next(_L("Ram Defrag : move all pages in all zone in 1 thread..."));
+
+ for (index = 0; index < TestZoneCount; index ++)
+ {
+ test.Printf(_L("Ram Defrag : moving pages in zone %u\n"),index);
+ ret = RamstressLdd.DoMovePagesInZone(index);
+ if (ret != KErrNone)
+ {
+ test.Printf(_L("Ram Defrag : moving pages in zone failed %u err=%d\n"), index, ret);
+ }
+ }
+
+
+ test.Next(_L("Ram Defrag : Get info after test"));
+ for (index = 0; index < TestZoneCount; index ++)
+ {
+ ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)index, (TAny*)&util);
+ test(ret == KErrNone);
+ test.Printf(_L("usage : id=%d index=%d pages=%d free=%d unknown=%d fixed=%d move=%d discard=%d other=%d\n"),
+ util.iZoneId,util.iZoneIndex,util.iPhysPages,util.iFreePages,
+ util.iAllocUnknown,util.iAllocFixed,util.iAllocMovable,util.iAllocDiscardable,util.iAllocOther);
+ }
+
+ test.Next(_L("Ram Defrag : Page moving on multiple threads with auto test running."));
+
+ TestingDefrag = ETrue;
+ TestDefragTestEnd = EFalse;
+
+ DoDefragAutoTest();
+ TestingDefrag = EFalse;
+ /*
+ * End of test cleanup.
+ */
+
+ test.Next(_L("Ram Defrag : reset VM cache back to stressed."));
+ if (TestIsDemandPaged)
+ {
+ TInt minSize = tempPages.iMinSize;
+ TInt maxSize = tempPages.iMaxSize;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+ RamstressLdd.Close();
+ test.Next(_L("Ram Defrag : Done"));
+ }
+
+//
+// PerformExceptionThread
+//
+// Generate a Panic
+//
+
+LOCAL_C TInt PerformExceptionThread(TAny* )
+ {
+ User::AfterHighRes(1000000);
+ // this line will cause a Kern::Exec 0 !!!
+ test.Printf(_L("Hello World\n"));
+
+ return KErrNone;
+ }
+
+//
+// DoExceptionInAnotherThread
+//
+// Test the d_exc and minkda functionality with faulting processes.
+//
+
+void DoExceptionInAnotherThread(void)
+ {
+ TRequestStatus theStatus;
+ RThread theThread;
+
+ TInt ret = theThread.Create(KTestBlank,PerformExceptionThread,KDefaultStackSize,NULL,NULL);
+ test(ret == KErrNone);
+ theThread.Logon(theStatus);
+ RUNTEST1(theStatus == KRequestPending);
+ theThread.Resume();
+ theThread.Close();
+ User::WaitForRequest(theStatus);
+ }
+
+//
+// DoTestD_Exc
+//
+// Test the d_exc and minkda functionality with faulting processes.
+//
+
+TInt DoTestD_Exc()
+ {
+ if (!TestSilent)
+ {
+ test.Next(_L("DoTestD_Exc : d_exc check test."));
+ }
+ DBGS_PRINT((_L("%S : DoTestD_Exc start...\n"), &TestNameBuffer));
+ // first we need to spawn d_exc.exe
+ RProcess dexcProcess;
+ TInt ret = dexcProcess.Create(_L("d_exc.exe"),_L("-b"));
+ RUNTEST1(KErrNone == ret);
+ TRequestStatus dexcStatus;
+ dexcProcess.Logon(dexcStatus);
+ RUNTEST1(dexcStatus == KRequestPending);
+ dexcProcess.Resume();
+
+ DBGS_PRINT((_L("%S : DoTestD_Exc started d_exc.exe\n"), &TestNameBuffer));
+
+ DoExceptionInAnotherThread();
+
+ DBGS_PRINT((_L("%S : DoTestD_Exc test completed\n"), &TestNameBuffer));
+ // check that d_exc and minkda don't die!
+ RUNTEST1(dexcProcess.ExitType() == EExitPending);
+
+ DBGS_PRINT((_L("%S : DoTestD_Exc d_exc still running\n"), &TestNameBuffer));
+
+ // kill off d_exc!
+ dexcProcess.Kill(KErrNone);
+ dexcProcess.Close();
+ User::WaitForRequest(dexcStatus);
+ DBGS_PRINT((_L("%S : DoTestD_Exc d_exc killed and exiting\n"), &TestNameBuffer));
+ return KErrNone;
+ }
+
+/**
+ Get name of the hash file used for an EXE or DLL which has been
+ copied to writable media.
+
+ @param aOrigName Name of EXE or DLL which has been copied to
+ writable media. This does not have to be
+ qualified because only the name and extension
+ are used.
+ @param aHashName On return this is set to the absolute filename
+ which should contain the file's hash. This
+ function does not create the file, or its containing
+ directory.
+ */
+
+static void GetHashFileName(const TDesC& aOrigName, TDes& aHashName)
+ {
+ aHashName.Copy(KSysHash);
+ aHashName[0] = (TUint8) RFs::GetSystemDriveChar();
+ const TParsePtrC ppc(aOrigName);
+ aHashName.Append(ppc.NameAndExt());
+ }
+
+//
+// HashFile
+// take hash of files require full drive:/path/name.ext
+//
+
+void HashFile(const TDesC& aFileName, RFs& aFs)
+ {
+ CSHA1* sha1 = CSHA1::NewL();
+ CleanupStack::PushL(sha1);
+
+ TBuf<50> hashfile;
+ hashfile = KSysHash;
+ hashfile[0] = (TUint8) RFs::GetSystemDriveChar();
+
+ TInt r = aFs.MkDirAll(hashfile);
+ RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
+
+ RFile fDest;
+ r = fDest.Open(aFs, aFileName, EFileRead | EFileStream);
+ if (r != KErrNone)
+ {
+ if (TestingReaper && (r == KErrInUse))
+ {
+ TBool whinged = EFalse;
+ while (r == KErrInUse)
+ {
+ User::After(2000000);
+ if (!whinged)
+ {
+ DBGS_PRINT((_L("HashFile() retrying Open for %S (%d)\n"), &aFileName, r));
+ whinged = ETrue;
+ }
+ r = fDest.Open(aFs, aFileName, EFileRead | EFileStream);
+ }
+
+ }
+ else
+ {
+ DBGS_PRINT((_L("fDest.Open returned %d\n"), r));
+ }
+ }
+ User::LeaveIfError(r);
+ CleanupClosePushL(fDest);
+
+ TBool done;
+ TBuf8<512> content;
+ do
+ {
+ r = fDest.Read(content);
+ if (r!=KErrNone)
+ DBGS_PRINT((_L("fDest.Read returned %d\n"), r));
+ User::LeaveIfError(r);
+ done = (content.Length() == 0);
+ if (! done)
+ sha1->Update(content);
+ } while (! done);
+ CleanupStack::PopAndDestroy(&fDest);
+
+ // write hash to \sys\hash
+ TBuf8<SHA1_HASH> hashVal = sha1->Final();
+
+ TFileName fnSrc(aFileName);
+ GetHashFileName(aFileName, fnSrc);
+ RFile fHash;
+ r = fHash.Replace(aFs, fnSrc, EFileWrite | EFileStream);
+ if (r != KErrNone)
+ DBGS_PRINT((_L("fHash.Replace returned %d\n"), r));
+ User::LeaveIfError(r);
+ CleanupClosePushL(fHash);
+ r = fHash.Write(hashVal);
+ if (r != KErrNone)
+ DBGS_PRINT((_L("fHash.Write returned %d\n"), r));
+ User::LeaveIfError(r);
+
+ CleanupStack::PopAndDestroy(2, sha1);
+ }
+
+//
+// CopyFileToMMc
+//
+// Copy a file to the MMC card and create a hash of it.
+//
+
+TInt CopyFileToMMc(RFs& aFs,CFileMan* aFileMan, TPtrC aPath, TPtrC aOldFilename, TPtrC aNewFilename)
+ {
+ TInt retVal = aFs.MkDirAll(aPath);
+ RUNTEST1(retVal==KErrNone || retVal==KErrAlreadyExists);
+
+ TFileName newPath;
+ TFileName oldPath;
+
+ oldPath.Format(_L("%S%S"),&KRomPath, &aOldFilename);
+ newPath.Format(_L("%S%S"),&aPath, &aNewFilename);
+ DBGD_PRINT((_L("Copying %S to %S\n"), &oldPath, &newPath));
+ retVal = aFileMan->Copy(oldPath, newPath, CFileMan::EOverWrite);
+ if (retVal == KErrNone)
+ {
+ retVal = aFileMan->Attribs(newPath, KEntryAttNormal, KEntryAttReadOnly, 0);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("%S : Attribs failed (%d)\n"), &newPath, retVal));
+ }
+ TEntry anEntry;
+ retVal = aFs.Entry(newPath, anEntry);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("%S : aFs.Entry failed (%d)\n"), &newPath, retVal));
+ }
+ TRAPD(r, HashFile(newPath, aFs));
+ RUNTEST1(r == KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("Failed to copy file %d\n"), retVal));
+ DBGD_PRINT((_L("%S : now %S (%d)\n"), &newPath, EXISTS(retVal), retVal));
+ return retVal;
+ }
+
+//
+// CopyAndFragmentFiles
+//
+// Copy the test files to a specified location edeavouring to fragment as much as possible.
+//
+
+TBool CopyAndFragmentFiles(RFs& aFs,CFileMan* aFileMan, TPtrC aPath, ETestMediaType aMediaType)
+ {
+ TInt retVal = aFs.MkDirAll(aPath);
+ RUNTEST1(retVal==KErrNone || retVal==KErrAlreadyExists);
+#define FILECOUNTMAX (PAGELDRTST_MAX_DLLS + 2)
+ RFile theInFiles[FILECOUNTMAX];
+ RFile theOutFiles[FILECOUNTMAX];
+ TInt inFileSize[FILECOUNTMAX];
+ TInt inFilePos[FILECOUNTMAX];
+ TBool fileOk[FILECOUNTMAX];
+
+ TInt index;
+ TFileName newPath;
+ TFileName oldPath;
+
+ for (index = 0; index < FILECOUNTMAX; index ++)
+ {
+ inFileSize[index] = 0;
+ inFilePos[index] = 0;
+ fileOk[index] = EFalse;
+
+ if (index < PAGELDRTST_MAX_DLLS)
+ {
+ oldPath.Format(_L("%S%S%d%S"), &KRomPath, &KDllBaseName, index, &TestPlExtNames[KTestMediaBase]);
+ newPath.Format(_L("%S%S%d%S"), &aPath, &KDllBaseName, index, &TestPlExtNames[aMediaType]);
+ }
+ else if (index < (PAGELDRTST_MAX_DLLS + 1))
+ {
+ oldPath.Format(_L("%S%S"), &KRomPath, &TestPsExeNames[KTestMediaBase]);
+ newPath.Format(_L("%S%S"), &aPath, &TestPsExeNames[aMediaType]);
+ }
+ else
+ {
+ oldPath.Format(_L("%S%S"), &KRomPath, &TestPlExeNames[KTestMediaBase]);
+ newPath.Format(_L("%S%S"), &aPath, &TestPlExeNames[aMediaType]);
+ }
+
+ retVal = theInFiles[index].Open(aFs, oldPath, EFileRead);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("%S : Failed to open for read (%d)\n"), &oldPath, retVal));
+ break;
+ }
+ retVal = theInFiles[index].Size(inFileSize[index]);
+ if (retVal != KErrNone)
+ {
+ theInFiles[index].Close();
+ DBGS_PRINT((_L("%S : Failed to get file size (%d)\n"), &newPath, retVal));
+ break;
+ }
+ retVal = theOutFiles[index].Replace(aFs, newPath, EFileWrite);
+ if (retVal != KErrNone)
+ {
+ theInFiles[index].Close();
+ DBGS_PRINT((_L("%S : Failed to open for write (%d)\n"), &newPath, retVal));
+ break;
+ }
+
+ fileOk[index] = ETrue;
+ }
+
+ const TInt KBufferSize = 3333;
+ TBuf8<KBufferSize> buffer;
+ TBool stillGoing;
+
+ do
+ {
+ stillGoing = EFalse;
+ for (index = 0; index < FILECOUNTMAX; index ++)
+ {
+ if (!fileOk[index])
+ break;
+ if (inFilePos[index] < inFileSize[index])
+ {
+ retVal = theInFiles[index].Read(buffer);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("theInFiles[%d] read failed (%d)\n"), index, retVal));
+ break;
+ }
+ retVal = theOutFiles[index].Write(buffer);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("theOutFiles[%d] Write failed (%d)\n"), index, retVal));
+ break;
+ }
+ retVal = theOutFiles[index].Flush();
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("theOutFiles[%d] flush failed (%d)\n"), index, retVal));
+ break;
+ }
+ inFilePos[index] += buffer.Length();
+ if (inFilePos[index] < inFileSize[index])
+ stillGoing = ETrue;
+ }
+ }
+ }
+ while (stillGoing);
+
+ TBool allOk = retVal == KErrNone;
+ for (index = 0; index < FILECOUNTMAX; index ++)
+ {
+ if (!fileOk[index])
+ {
+ allOk = EFalse;
+ break;
+ }
+ theInFiles[index].Close();
+ theOutFiles[index].Close();
+ if (index < PAGELDRTST_MAX_DLLS)
+ {
+ newPath.Format(_L("%S%S%d%S"), &aPath, &KDllBaseName, index, &TestPlExtNames[aMediaType]);
+ }
+ else if (index < (PAGELDRTST_MAX_DLLS + 1))
+ {
+ newPath.Format(_L("%S%S"), &aPath, &TestPsExeNames[aMediaType]);
+ }
+ else
+ {
+ newPath.Format(_L("%S%S"), &aPath, &TestPlExeNames[aMediaType]);
+ }
+
+ retVal = aFileMan->Attribs(newPath, KEntryAttNormal, KEntryAttReadOnly, 0);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("%S : Attribs failed (%d)\n"), &newPath, retVal));
+ allOk = EFalse;
+ }
+ TEntry anEntry;
+ retVal = aFs.Entry(newPath, anEntry);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("%S : aFs.Entry failed (%d)\n"), &newPath, retVal));
+ allOk = EFalse;
+ }
+ TRAPD(r, HashFile(newPath, aFs));
+ if (r != KErrNone)
+ {
+ allOk = EFalse;
+ }
+ DBGD_PRINT((_L("%S : %S!\n"), &newPath, EXISTS(!allOk)));
+ }
+ return allOk;
+ }
+
+//
+// CheckFilePresence
+//
+// Checks all the files required for the test are present and copies some tests to the MMC card
+//
+
+void CheckFilePresence(TBool aDoFileCopy)
+ {
+ TUint start = User::TickCount();
+
+ RFs fs;
+ if (KErrNone != fs.Connect())
+ {
+ DBGS_PRINT(_L("CheckFilePresence : Can't connect to the FS\n"));
+ return ;
+ }
+
+ TFileName filename;
+ TFileName newFilename;
+ TEntry anEntry;
+ TInt index;
+ TInt retVal;
+ TInt dllIndex;
+
+ // now we need to add the MMC files
+ TInt drvNum = FindMMCDriveNumber(fs);
+ TBuf<32> mmcPath;
+ mmcPath.Format(_L("%S"),&KMmcDefaultPath);
+ if (drvNum >= 0)
+ mmcPath[0] = 'a' + drvNum;
+
+ TBool allOk;
+ //TInt indexMax = aDoFileCopy ? KTestMediaMmc : KTestMediaCOUNT;
+ for (index = 0; index < TEST_MEDIA_COUNT_HACK; index ++)
+ {
+ allOk = ETrue;
+ filename.Format(_L("%S%S"),(index == KTestMediaMmc) ? & mmcPath : &KRomPath, &TestPsExeNames[index]);
+ if (KErrNone != fs.Entry(filename, anEntry))
+ allOk = EFalse;
+
+ filename.Format(_L("%S%S"),(index == KTestMediaMmc) ? & mmcPath : &KRomPath, &TestPlExeNames[index]);
+ if (KErrNone != fs.Entry(filename, anEntry))
+ allOk = EFalse;
+
+ for (dllIndex = 0; dllIndex < PAGELDRTST_MAX_DLLS; dllIndex ++)
+ {
+ filename.Format(_L("%S%S%d%S"), (index == KTestMediaMmc) ? & mmcPath : &KRomPath, &KDllBaseName, dllIndex, &TestPlExtNames[index]);
+ if (KErrNone != fs.Entry(filename, anEntry))
+ allOk = EFalse;
+ }
+ TestDllExesExist[index] = allOk;
+ DBGS_PRINT((_L("%S : %S!\n"), &TestPsExeNames[index], EXISTS(!TestDllExesExist[index])));
+ }
+ TInt nandDrvNum = FindFsNANDDrive(fs);
+ if (aDoFileCopy && (drvNum >= 0) && (nandDrvNum >= 0))
+ {
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+ if(!cleanupStack)
+ DBGS_PRINT((_L("Cleanup stack failed\n")));
+ CFileMan* pFileMan = NULL;
+ TRAP(retVal, pFileMan = CFileMan::NewL(fs));
+
+ // First make a clean copy of the DLLs to the MMC card.
+ allOk = ETrue;
+ if (KErrNone != CopyFileToMMc(fs, pFileMan, mmcPath, TestPsExeNames[KTestMediaBase], TestPsExeNames[KTestMediaMmc]))
+ allOk = EFalse;
+ if (KErrNone != CopyFileToMMc(fs, pFileMan, mmcPath, TestPlExeNames[KTestMediaBase], TestPlExeNames[KTestMediaMmc]))
+ allOk = EFalse;
+ for (dllIndex = 0; dllIndex < PAGELDRTST_MAX_DLLS; dllIndex ++)
+ {
+ filename.Format(_L("%S%d%S"), &KDllBaseName, dllIndex, &TestPlExtNames[KTestMediaBase]);
+ newFilename.Format(_L("%S%d%S"), &KDllBaseName, dllIndex, &TestPlExtNames[KTestMediaMmc]);
+ if (KErrNone != CopyFileToMMc(fs, pFileMan, mmcPath, filename, newFilename))
+ allOk = EFalse;
+ }
+ TestDllExesExist[KTestMediaMmc] = allOk;
+ DBGS_PRINT((_L("%S : %S! (Drive %c)\n"), &TestPsExeNames[index], EXISTS(!TestDllExesExist[index]), mmcPath[0]));
+#ifdef TEST_ADD_FRAGD_MEDIA
+ //now make some fragmented files on the MMC card.
+ TestDllExesExist[KTestMediaMmcFrag] = CopyAndFragmentFiles(fs, pFileMan, mmcPath, KTestMediaMmcFrag);
+ DBGS_PRINT((_L("%S : %S! (Drive %c)\n"), &TestPsExeNames[KTestMediaMmcFrag], EXISTS(!TestDllExesExist[KTestMediaMmcFrag]), mmcPath[0]));
+
+ //now make some fragmented files on the NAND card.
+ if (nandDrvNum >= 0)
+ {
+ mmcPath[0] = 'a' + nandDrvNum;
+ TestDllExesExist[KTestMediaNandFrag] = CopyAndFragmentFiles(fs, pFileMan, mmcPath, KTestMediaNandFrag);
+ DBGS_PRINT((_L("%S : %S! (Drive %c)\n"), &TestPsExeNames[KTestMediaNandFrag], EXISTS(!TestDllExesExist[KTestMediaNandFrag]), mmcPath[0]));
+ }
+ else
+ DBGS_PRINT((_L("CheckFilePresence : Failed to get NAND drive number\n")));
+#endif // TEST_ADD_FRAGD_MEDIA
+ delete pFileMan; pFileMan = NULL;
+ delete cleanupStack; cleanupStack = NULL;
+ }
+
+ fs.Close();
+
+ TUint end = User::TickCount();
+ TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
+ DBGS_PRINT((_L("CheckFilePresence : %d secs elapsed\n"), time));
+ }
+
+//
+// DoDeleteFile
+//
+// Delete a file and remove the hash
+//
+
+void DoDeleteFile(CFileMan* aFileMan, TBool aSilent,TFileName& aFileName )
+ {
+ TFileName hashName;
+ RLoader l;
+ test(l.Connect() == KErrNone);
+
+ DBGD_PRINT((_L("Deleting %S ...\n"), &aFileName));
+ if (!aSilent)
+ DBGD_PRINT((_L("Deleting %S\n"), &aFileName));
+ TInt retVal = aFileMan->Delete(aFileName);
+ if (retVal != KErrNone)
+ {
+ if (TestingReaper)
+ {
+ aFileMan->Attribs(aFileName, KEntryAttNormal, KEntryAttReadOnly, 0);
+ retVal = l.Delete(aFileName);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("RLoader::Delete %S Failed %d\n"), &aFileName, retVal));
+ }
+ }
+ else
+ {
+ if (!aSilent)
+ DBGS_PRINT((_L("Deleting %S Failed %d\n"), &aFileName, retVal));
+ }
+ }
+ GetHashFileName(aFileName, hashName);
+ retVal = aFileMan->Delete(hashName);
+ if (retVal != KErrNone)
+ {
+ if (TestingReaper && (retVal == KErrInUse))
+ {
+ retVal = l.Delete(hashName);
+ if (retVal != KErrNone)
+ {
+ DBGS_PRINT((_L("RLoader::Delete %S Failed %d\n"), &hashName, retVal));
+ }
+ }
+ else
+ {
+ if (!aSilent)
+ DBGS_PRINT((_L("Deleting %S Failed %d\n"), &hashName, retVal));
+ }
+ }
+ l.Close();
+ }
+
+//
+// CleanupFiles
+//
+// Remove any copied files and created directories.
+//
+
+void CleanupFiles(TBool silent)
+ {
+ TUint start = User::TickCount();
+
+ RFs fs;
+ if (KErrNone != fs.Connect())
+ {
+ DBGS_PRINT(_L("CleanupFiles : Can't connect to the FS\n"));
+ return ;
+ }
+
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+ if(!cleanupStack)
+ if (!silent)
+ DBGS_PRINT((_L("Cleanup stack failed\n")));
+
+ CFileMan* pFileMan = NULL;
+ TInt retVal;
+ TRAP(retVal, pFileMan = CFileMan::NewL(fs));
+
+ TFileName newPath;
+ TInt index;
+ TInt dllIndex;
+
+ TBuf<32> path;
+ path.Format(_L("%S"),&KMmcDefaultPath);
+ TInt mmcDrvNum = FindMMCDriveNumber(fs);
+ TInt nandDrvNum = FindFsNANDDrive(fs);
+ for (index = KTestMediaMmc; index < KTestMediaCOUNT; index ++)
+ {
+#ifdef TEST_ADD_FRAGD_MEDIA
+ if (index == KTestMediaNandFrag)
+ {
+ if (nandDrvNum < 0)
+ continue;
+ path[0] = 'a' + nandDrvNum;
+ }
+ else
+ {
+ if (mmcDrvNum < 0)
+ continue;
+ path[0] = 'a' + mmcDrvNum;
+ }
+#else
+ path[0] = 'a' + mmcDrvNum;
+#endif
+ newPath.Format(_L("%S%S"),&path, &TestPsExeNames[index]);
+ DoDeleteFile(pFileMan, silent, newPath);
+
+ newPath.Format(_L("%S%S"),&path, &TestPlExeNames[index]);
+ DoDeleteFile(pFileMan, silent, newPath);
+
+ for (dllIndex = 0; dllIndex < PAGELDRTST_MAX_DLLS; dllIndex ++)
+ {
+ newPath.Format(_L("%S%S%d%S"), &path, &KDllBaseName, dllIndex, &TestPlExtNames[index]);
+ DoDeleteFile(pFileMan, silent, newPath);
+ }
+ }
+ if (nandDrvNum >= 0)
+ {
+ path[0] = 'a' + nandDrvNum;
+ fs.RmDir(path);
+ }
+ if (mmcDrvNum >= 0)
+ {
+ path[0] = 'a' + mmcDrvNum;
+ fs.RmDir(path);
+ }
+
+ delete pFileMan; pFileMan = NULL;
+ delete cleanupStack; cleanupStack = NULL;
+ fs.Close();
+ TUint end = User::TickCount();
+ TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
+ DBGS_PRINT((_L("CleanupFiles : %d secs elapsed\n"), time));
+ }
+
+#ifdef _DEBUG
+
+//
+// FindLocalDriveNumber
+//
+// Find the local drive
+//
+
+TInt FindLocalDriveNumber(RFs &aFs, TInt aFsDrvNum)
+ {
+ RFile file;
+ TBuf<256> fileName;
+ fileName.Append((TChar)('A' + aFsDrvNum));
+ fileName+=_L(":\\f32-tst\\");
+ TInt r=aFs.MkDirAll(fileName);
+ TInt locDriveNumber = -1;
+ if (r==KErrNone || r== KErrAlreadyExists)
+ {
+ fileName += _L("tempy.txt");
+ r=file.Replace(aFs,fileName,EFileWrite);
+ if (r!=KErrNone)
+ DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: file '%S' could not be created\n"),r,&fileName));
+ RUNTEST1(r==KErrNone);
+ r=file.Write(_L8("Flies as big as sparrows indoletly buzzing in the warm air, heavy with the stench of rotting carcasses"));
+ if (r!=KErrNone)
+ {
+ DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: could not write to file %d (%S)\n"),r,aFsDrvNum, &fileName));
+ }
+ else
+ {
+ // write caching may be enabled to flush the cache...
+ TRequestStatus flushStatus;
+ file.Flush(flushStatus);
+ User::WaitForRequest(flushStatus);
+ // get the block map
+ SBlockMapInfo info;
+ TInt64 start=0;
+ r=file.BlockMap(info, start, -1,ETestDebug);
+ if (r==KErrNone || r==KErrCompletion)
+ {
+ locDriveNumber=info.iLocalDriveNumber;
+ DBGD_PRINT((_L("FindLocalDriveNumber : locDriveNumber %d\n"), locDriveNumber));
+ }
+ else
+ DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: error getting blockmap for drive %d (%S)\n"),r,aFsDrvNum, &fileName));
+ }
+ aFs.Delete(fileName);
+ file.Close();
+ }
+ else
+ DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: error creating dir \n"),r));
+ return locDriveNumber;
+ }
+
+//
+// ResetConcurrencyStats
+//
+// Reset the stats
+//
+
+void ResetConcurrencyStats(RFs& aFs)
+ {
+ if(TestBootedFromMmc)
+ {
+ TInt fsDriveNum = FindMMCDriveNumber(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if (locDriveNumber >= 0)
+ {
+ RUNTEST(PagingInfo::ResetConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("ResetConcurrencyStats MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("ResetConcurrencyStats MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ else
+ {
+ TInt fsDriveNum = FindFsNANDDrive(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if (locDriveNumber >= 0)
+ {
+ RUNTEST(PagingInfo::ResetConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("ResetConcurrencyStats NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("ResetConcurrencyStats NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ }
+
+//
+// ResetBenchmarks
+//
+// Reset the stats
+//
+
+void ResetBenchmarks(RFs& aFs)
+ {
+ if(TestBootedFromMmc)
+ {
+ TInt fsDriveNum = FindMMCDriveNumber(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if (locDriveNumber >= 0)
+ {
+ RUNTEST(PagingInfo::ResetBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("ResetBenchmarks MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("ResetBenchmarks MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ else
+ {
+ TInt fsDriveNum = FindFsNANDDrive(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if (locDriveNumber >= 0)
+ {
+ RUNTEST(PagingInfo::ResetBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("ResetBenchmarks NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("ResetBenchmarks NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ }
+
+//
+// DisplayConcurrencyStats
+//
+// Display the stats
+//
+
+void DisplayConcurrencyStats(RFs& aFs)
+ {
+ if(TestBootedFromMmc)
+ {
+ TInt fsDriveNum = FindMMCDriveNumber(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if (locDriveNumber >= 0)
+ {
+ DBGS_PRINT((_L("MMC stats\n")));
+ RUNTEST1(PagingInfo::PrintConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("DisplayConcurrencyStats MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("DisplayConcurrencyStats MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ else
+ {
+ TInt fsDriveNum = FindFsNANDDrive(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+
+ if (locDriveNumber >= 0)
+ {
+ DBGS_PRINT((_L("NAND stats\n")));
+ RUNTEST1(PagingInfo::PrintConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("DisplayConcurrencyStats NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("DisplayConcurrencyStats NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ }
+
+void DisplayBenchmarks(RFs& aFs)
+ {
+ if(TestBootedFromMmc)
+ {
+ TInt fsDriveNum = FindMMCDriveNumber(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if(locDriveNumber>=0)
+ {
+ DBGS_PRINT((_L("MMC benchmarks\n")));
+ RUNTEST1(PagingInfo::PrintBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("DisplayBenchmarks MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("DisplayBenchmarks MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ else
+ {
+ TInt fsDriveNum = FindFsNANDDrive(aFs);
+ if (fsDriveNum >= 0)
+ {
+ TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
+ if(locDriveNumber>=0)
+ {
+ DBGS_PRINT((_L("NAND benchmarks\n")));
+ RUNTEST1(PagingInfo::PrintBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
+ }
+ else
+ DBGS_PRINT((_L("DisplayBenchmarks NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
+ }
+ else
+ DBGS_PRINT((_L("DisplayBenchmarks NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
+ }
+ }
+
+#endif
+
+void DoStats()
+ {
+ if (TestIsDemandPaged)
+ {
+ SVMCacheInfo tempPages;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+ DBGS_PRINT((_L("DPC : min %d max %d curr %d\n"),
+ tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize));
+ DBGS_PRINT((_L(" : maxFree %d freeRam %d\n"),
+ tempPages.iMaxFreeSize, FreeRam()));
+ }
+
+#ifdef _DEBUG
+ if (TestWeAreTheTestBase && !TestSilent)
+ {
+ RFs fs;
+ if (KErrNone != fs.Connect())
+ {
+ DBGS_PRINT(_L("ResetConcurrencyStats : Can't connect to the FS\n"));
+ return;
+ }
+
+#ifndef TEST_MINIMAL_STATS
+ DisplayConcurrencyStats(fs);
+ DisplayBenchmarks(fs);
+#endif
+#ifndef TEST_DONT_RESET_STATS
+ ResetConcurrencyStats(fs);
+ ResetBenchmarks(fs);
+#endif
+ fs.Close();
+ }
+#endif
+ }
+
+
+//
+// E32Main
+//
+// Main entry point.
+//
+
+TInt E32Main()
+ {
+#ifndef TEST_ON_UNPAGED
+ TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
+ if(!romHeader->iPageableRomStart)
+ {
+ TestIsDemandPaged = EFalse;
+ }
+#endif
+ // Turn off lazy dll unloading
+ RLoader l;
+ if (l.Connect() == KErrNone)
+ {
+ l.CancelLazyDllUnload();
+ l.Close();
+ }
+
+ HAL::Get(HAL::ESystemTickPeriod, TickPeriod);
+
+ SVMCacheInfo tempPages;
+ memset(&tempPages, 0, sizeof(tempPages));
+
+ TBool parseResult = ParseCommandLine();
+
+ if (TestExit)
+ {
+ return KErrNone;
+ }
+
+ TUint start = User::TickCount();
+
+ AreWeTheTestBase();
+
+ if (TestIsDemandPaged)
+ {
+ TInt minSize = TestMinCacheSize;
+ TInt maxSize = TestMaxCacheSize;
+
+ SVMCacheInfo tempPages;
+
+ // get the old cache info
+ UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
+ // set the cache to our test value
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+ if (!TestSilent)
+ {
+ test.Title();
+ test.Start(_L("Demand Paging loader stress tests..."));
+ test.Printf(_L("%S (%d)\n"), &TestNameBuffer, TestWeAreTheTestBase);
+ test.Printf(_L("TestBootedFromMmc %d\n"), TestBootedFromMmc);
+
+ if (TestWeAreTheTestBase)
+ CleanupFiles(ETrue);
+
+ CheckFilePresence(TestWeAreTheTestBase);
+ }
+
+ if (parseResult)
+ {
+ if (TestLowMem)
+ {
+ DoLowMemTest(ETrue);
+ }
+ if (TestSingle)
+ {
+ RUNTEST(DoSingleTest(),KErrNone);
+ }
+ if (TestMultiple)
+ {
+ RUNTEST(DoMultipleTest(),KErrNone);
+ }
+ if (TestD_Exc)
+ {
+ RUNTEST(DoTestD_Exc(),KErrNone);
+ }
+ if (TestChunks)
+ {
+ DoChunkTests();
+ }
+ if (TestReaper)
+ {
+ DoReaperTests();
+ }
+ if (TestBtrace)
+ {
+ DoBtraceTest();
+ }
+ if (TestDefrag)
+ {
+ DoDefragTest();
+ }
+ }
+ else
+ {
+#ifdef _DEBUG
+ if (TestWeAreTheTestBase)
+ {
+ RFs fs;
+ if (KErrNone == fs.Connect())
+ {
+ //fs.SetDebugRegister(KCACHE);
+ ResetConcurrencyStats(fs);
+ ResetBenchmarks(fs);
+ fs.Close();
+ }
+ }
+#endif
+
+ while (1)
+ {
+ if (TestIsDemandPaged)
+ {
+#ifdef TEST_RUN_AUTOTEST
+ PerformAutoTest();
+#endif //TEST_RUN_AUTOTEST
+
+#ifndef TEST_SHORT_TEST
+#ifdef TEST_RUN_LOWMEMTEST
+ DoLowMemTest(ETrue);
+#endif //TEST_RUN_LOWMEMTEST
+#ifdef TEST_RUN_CHUNKTEST
+ DoChunkTests();
+#endif //TEST_RUN_CHUNKTEST
+#ifdef TEST_RUN_REAPERTEST
+ DoReaperTests();
+#endif //TEST_RUN_REAPERTEST
+#endif //TEST_SHORT_TEST
+ }
+
+#ifdef TEST_RUN_DEFRAGTEST
+ DoDefragTest();
+#endif //TEST_RUN_DEFRAGTEST
+
+ if (TestStressFree)
+ {
+ TInt minSize = 512 * 4096;
+ TInt maxSize = 32767 * 4096;
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+
+ test.Printf(_L("%S Stress Free!!\n"), &TestNameBuffer, TestWeAreTheTestBase);
+ TestStressFree = EFalse;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+#ifndef TEST_SHORT_TEST
+#ifndef TEST_NO_DEXC_IN_AUTO
+#ifdef TEST_RUN_D_EXCTEST
+ RUNTEST(DoTestD_Exc(),KErrNone);
+#endif //TEST_RUN_D_EXCTEST
+#endif //TEST_NO_DEXC_IN_AUTO
+ if (TestWeAreTheTestBase && TestFullAutoTest && TestIsDemandPaged)
+ {
+ RProcess theProcess;
+ TRequestStatus status;
+
+ TInt retVal = theProcess.Create(_L("t_pageldrtst_rom.exe"),_L("fullauto"));
+ if (retVal != KErrNotFound)
+ {
+ RUNTEST1(KErrNone == retVal);
+ theProcess.Logon(status);
+ RUNTEST1(status == KRequestPending);
+ theProcess.Resume();
+#ifdef TEST_THRASHING_TEST
+ while (1)
+ {
+ if (theProcess.ExitType() != EExitPending)
+ {
+ RUNTEST1(theProcess.ExitType() != EExitPanic);
+ break;
+ }
+ User::AfterHighRes(1);
+ }
+ User::WaitForRequest(status);
+#else
+ User::WaitForRequest(status);
+ if (theProcess.ExitType() != EExitPending)
+ {
+ RUNTEST1(theProcess.ExitType() != EExitPanic);
+ }
+#endif //TEST_THRASHING_TEST
+ theProcess.Close();
+ }
+ }
+#endif //TEST_SHORT_TEST
+#ifdef _DEBUG
+ if (TestWeAreTheTestBase && !TestSilent)
+ {
+ RFs fs;
+ if (KErrNone == fs.Connect())
+ {
+ DisplayConcurrencyStats(fs);
+ DisplayBenchmarks(fs);
+ fs.Close();
+ }
+ }
+#endif
+ }
+
+ if (TestWeAreTheTestBase && !TestNoClean)
+ CleanupFiles(EFalse);
+
+ if (TestIsDemandPaged)
+ {
+ TInt minSize = tempPages.iMinSize;
+ TInt maxSize = tempPages.iMaxSize;
+ // put the cache back to the the original values.
+ UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
+ }
+ if (!TestSilent)
+ {
+ TUint end = User::TickCount();
+ TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
+ test.Printf(_L("%S : Complete (%u seconds)\n"), &TestNameBuffer, time);
+ test.End();
+ }
+ return KErrNone;
+ }