Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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 <e32svr.h>
#include <u32hal.h>
#include <f32file.h>
#include <f32dbg.h>
#include <e32msgqueue.h>
#include <e32math.h>
#include <e32btrace.h>
#include <d32btrace.h>
#include <d32locd.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;
}