diff -r 000000000000 -r a41df078684a kerneltest/f32test/demandpaging/integtest/src/t_dpattr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/demandpaging/integtest/src/t_dpattr.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,823 @@ +// 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: +// @SYMTestCaseID KBASE-DP_FUNC_ATTRIBUTES-0303 +// @SYMTestCaseDesc Symbian OS Toolchain's Paging Override and the +// Paging Policy settings +// @SYMREQ REQ6808 +// @SYMPREQ PREQ1110 +// @SYMTestPriority High +// @SYMTestActions +// 1. Load executables with the RProcess API and run them. Each executable has a +// different set of attributes: +// " Paging attribute: paged, unpaged or no paging attribute in MMP and/or +// OBY files +// " Compression mode: specified or not +// " Executable built in ROM as 'data' or 'file' +// " Solid binaries or aliases +// Retrieve and analyse the demand paging activity trace caused by the preceding +// action, in order to determine whether this binary is paged on demand or not. +// 2. Repeat the preceding action by loading DLLs with the RLibrary API and +// making calls to them. +// @SYMTestExpectedResults +// 1. Process complete without error. If, according to the trace data gathered, +// the main thread newly created process causes the executable to be paged in, +// then it is a proof that the executable is paged. Depending on the Paging +// Override setting and the Loader Paging Policy specified at the time the ROM was +// built, the Loader makes a decision as to whether page the binary or not, +// according to the rules listed in the Design Sketch. This is how we determine +// this, in this order: +// a. If ROM paging is disabled: not paged +// b. If executable was built in ROM as 'data': not paged +// c. If the a file compression scheme was specified at ROM build time: not paged +// d. If the Loader Paging policy is 'NOT PAGED': not paged +// e. If the Loader Paging policy is 'ALWAYS PAGE': paged +// f. If the Paging Override is 'NOT PAGED': not paged +// g. If the Paging Override is 'ALWAYS PAGE': paged +// h. If the OBY paging keyword for this executable is 'PAGED': paged +// i. If the OBY paging keyword for this executable is 'NOT PAGED': unpaged +// j. If the MMP paging keyword for this executable is 'PAGED': paged +// k. If the MMP paging keyword for this executable is 'NOT PAGED': not paged +// l. If the Paging Override is 'DEFAULT UNPAGED': not paged +// m. If the Paging Override is 'DEFAULT PAGED': paged +// n. If the Paging Policy is 'DEFAULT UNPAGED': not paged +// o. The executable must be paged +// 2. DLL is loaded. Functions are called and complete without errors. The rules +// to determine whether the binary should be paged or not are the same as in the +// preceding action. +// +// + +#include +#include +#include +#include "u32std.h" +#include +#include + +#define TEST_EQ(a,b) { if (a != b) { test.Printf(_L("%d != %d\n"), a, b); test(EFalse); } } +#define TEST_CONDITION(a) { if (!a) { test.Printf(_L("TEST FAILED at line %d\n"), __LINE__); pass = EFalse; } } +#define LE4(a) ((TUint) (*((a) + 3) << 24) + (*((a) + 2) << 16) + (*((a) + 1) << 8) + *(a)) + +RTest test(_L("T_DPATTR")); +RBTrace btrace; +RFs fs; + +// ROM paging settings +TBool gIsRomDemangPagingEnabled; +TInt gPagingOverride; +TInt gPagingPolicy; + +// This process +TUint32 gNThreadId = 0; + +// Test executables attributes flags +enum + { + ENone = 0, + EMMPPaged = 1 << 0, // "PAGED" keyword in MMP file + EMMPUnpaged = 1 << 1, // "UNPAGED" keyword in MMP file + EMMPCompressTarget = 1 << 2, // "COMPRESSTARGET" keyword in MMP file + EMMPNoCompressTarget = 1 << 3, // "UNCOMPRESSTARGET" keyword in MMP file + EIBYData = 1 << 4, // File included as "data" in IBY file + EIBYFile = 1 << 5, // File included as "file" in IBY file + EIBYFileCompress = 1 << 6, // File included as "file_x_" in IBY file (_x_=compression scheme) + EIBYPaged = 1 << 7, // File declared "paged" in IBY file + EIBYUnpaged = 1 << 8, // File declared "unpaged in IBY file + EIBYAlias = 1 << 9, // File name is an alias + EDLLWritableStaticData = 1 << 10 // DLL contains writable static data + }; + +// Test executables attributes +const TUint testExeAttr[] = + { + /* 000 - does not exist */ ENone, + /* 001 */ EIBYFile, + /* 002 */ EMMPPaged | EIBYFile, + /* 003 */ EMMPUnpaged | EIBYFile, + /* 004 */ EIBYFileCompress, + /* 005 */ EMMPPaged | EIBYFileCompress, + /* 006 */ EMMPUnpaged | EIBYFileCompress, + /* 007 */ EIBYFileCompress, + /* 008 */ EMMPPaged | EIBYFileCompress, + /* 009 */ EMMPUnpaged | EIBYFileCompress, + /* 010 */ EIBYFileCompress, + /* 011 */ EMMPPaged | EIBYFileCompress, + /* 012 */ EMMPUnpaged | EIBYFileCompress, + /* 013 */ EIBYFile | EMMPCompressTarget, + /* 014 */ EMMPPaged | EIBYFile | EMMPNoCompressTarget, + /* 015 */ EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged, + /* 016 */ EIBYData, + /* 017 */ EMMPPaged | EIBYData, + /* 018 */ EMMPUnpaged | EIBYData, + /* 019 */ EIBYFile | EIBYPaged, + /* 020 */ EMMPPaged | EIBYFile | EIBYPaged, + /* 021 */ EMMPUnpaged | EIBYFile | EIBYPaged, + /* 022 */ EIBYFile | EIBYUnpaged, + /* 023 */ EMMPPaged | EIBYFile | EIBYUnpaged, + /* 024 */ EMMPUnpaged | EIBYFile | EIBYUnpaged, + /* 025 */ EIBYData | EIBYPaged, + /* 026 */ EMMPPaged | EIBYData | EIBYPaged, + /* 027 */ EMMPUnpaged | EIBYData | EIBYPaged, + /* 028 */ EIBYData | EIBYUnpaged, + /* 029 */ EMMPPaged | EIBYData | EIBYUnpaged, + /* 030 */ EMMPUnpaged | EIBYData | EIBYUnpaged, + /* 031 */ EIBYAlias | EIBYFile, + /* 032 */ EIBYAlias | EMMPPaged | EIBYFile, + /* 033 */ EIBYAlias | EMMPUnpaged | EIBYFile, + /* 034 */ EIBYAlias | EIBYFileCompress, + /* 035 */ EIBYAlias | EMMPPaged | EIBYFileCompress, + /* 036 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress, + /* 037 */ EIBYAlias | EIBYFileCompress, + /* 038 */ EIBYAlias | EMMPPaged | EIBYFileCompress, + /* 039 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress, + /* 040 */ EIBYAlias | EIBYFileCompress, + /* 041 */ EIBYAlias | EMMPPaged | EIBYFileCompress, + /* 042 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress, + /* 043 */ EIBYAlias | EIBYFile | EMMPCompressTarget, + /* 044 */ EIBYAlias | EMMPPaged | EIBYFile | EMMPNoCompressTarget, + /* 045 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged, + /* 046 */ EIBYAlias | EIBYData, + /* 047 */ EIBYAlias | EMMPPaged | EIBYData, + /* 048 */ EIBYAlias | EMMPUnpaged | EIBYData, + /* 049 */ EIBYAlias | EIBYFile | EIBYPaged, + /* 050 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYPaged, + /* 051 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYPaged, + /* 052 */ EIBYAlias | EIBYFile | EIBYUnpaged, + /* 053 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYUnpaged, + /* 054 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYUnpaged, + /* 055 */ EIBYAlias | EIBYData | EIBYPaged, + /* 056 */ EIBYAlias | EMMPPaged | EIBYData | EIBYPaged, + /* 057 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYPaged, + /* 058 */ EIBYAlias | EIBYData | EIBYUnpaged, + /* 059 */ EIBYAlias | EMMPPaged | EIBYData | EIBYUnpaged, + /* 060 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYUnpaged + }; +const TUint testDllAttr[] = + { + /* 000 - does not exist */ ENone, + /* 001 */ EIBYFile, + /* 002 */ EMMPPaged | EIBYFile, + /* 003 */ EMMPUnpaged | EIBYFile, + /* 004 */ EIBYFileCompress, + /* 005 */ EMMPPaged | EIBYFileCompress, + /* 006 */ EMMPUnpaged | EIBYFileCompress, + /* 007 */ EDLLWritableStaticData, + /* 008 */ EMMPPaged | EDLLWritableStaticData, + /* 009 */ EMMPUnpaged | EDLLWritableStaticData, + /* 010 */ EIBYFileCompress, + /* 011 */ EMMPPaged | EIBYFileCompress, + /* 012 */ EMMPUnpaged | EIBYFileCompress, + /* 013 */ EIBYFile | EMMPCompressTarget, + /* 014 */ EMMPPaged | EIBYFile | EMMPNoCompressTarget, + /* 015 */ EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged, + /* 016 */ EIBYData, + /* 017 */ EMMPPaged | EIBYData, + /* 018 */ EMMPUnpaged | EIBYData, + /* 019 */ EIBYFile | EIBYPaged, + /* 020 */ EMMPPaged | EIBYFile | EIBYPaged, + /* 021 */ EMMPUnpaged | EIBYFile | EIBYPaged, + /* 022 */ EIBYFile | EIBYUnpaged, + /* 023 */ EMMPPaged | EIBYFile | EIBYUnpaged, + /* 024 */ EMMPUnpaged | EIBYFile | EIBYUnpaged, + /* 025 */ EIBYData | EIBYPaged, + /* 026 */ EMMPPaged | EIBYData | EIBYPaged, + /* 027 */ EMMPUnpaged | EIBYData | EIBYPaged, + /* 028 */ EIBYData | EIBYUnpaged, + /* 029 */ EMMPPaged | EIBYData | EIBYUnpaged, + /* 030 */ EMMPUnpaged | EIBYData | EIBYUnpaged, + /* 031 */ EIBYAlias | EIBYFile, + /* 032 */ EIBYAlias | EMMPPaged | EIBYFile, + /* 033 */ EIBYAlias | EMMPUnpaged | EIBYFile, + /* 034 */ EIBYAlias | EIBYFileCompress, + /* 035 */ EIBYAlias | EMMPPaged | EIBYFileCompress, + /* 036 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress, + /* 037 */ EIBYAlias | EDLLWritableStaticData, + /* 038 */ EIBYAlias | EMMPPaged | EDLLWritableStaticData, + /* 039 */ EIBYAlias | EMMPUnpaged | EDLLWritableStaticData, + /* 040 */ EIBYAlias | EIBYFileCompress, + /* 041 */ EIBYAlias | EMMPPaged | EIBYFileCompress, + /* 042 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress, + /* 043 */ EIBYAlias | EIBYFile | EMMPCompressTarget, + /* 044 */ EIBYAlias | EMMPPaged | EIBYFile | EMMPNoCompressTarget, + /* 045 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged, + /* 046 */ EIBYAlias | EIBYData, + /* 047 */ EIBYAlias | EMMPPaged | EIBYData, + /* 048 */ EIBYAlias | EMMPUnpaged | EIBYData, + /* 049 */ EIBYAlias | EIBYFile | EIBYPaged, + /* 050 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYPaged, + /* 051 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYPaged, + /* 052 */ EIBYAlias | EIBYFile | EIBYUnpaged, + /* 053 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYUnpaged, + /* 054 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYUnpaged, + /* 055 */ EIBYAlias | EIBYData | EIBYPaged, + /* 056 */ EIBYAlias | EMMPPaged | EIBYData | EIBYPaged, + /* 057 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYPaged, + /* 058 */ EIBYAlias | EIBYData | EIBYUnpaged, + /* 059 */ EIBYAlias | EMMPPaged | EIBYData | EIBYUnpaged, + /* 060 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYUnpaged + }; + +void InitNThreadID() + { + _LIT(KThreadName, "ARandomThreadName"); + btrace.SetFilter(BTrace::EThreadIdentification, ETrue); + btrace.Empty(); + btrace.SetMode(RBTrace::EEnable); + // rename the current thread to force a ThreadID trace + User::RenameThread(KThreadName); + btrace.SetMode(0); + TInt size; + TUint8* pDataStart; + TUint8* pCurrentRecord; + // extract the nano-kernel thread ID from the trace + while ((size = btrace.GetData(pDataStart)) != 0) + { + pCurrentRecord = pDataStart; + while (pCurrentRecord - pDataStart < size) + { + TInt extensionCount = 4 * ( + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EHeader2Present ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestampPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EContextIdPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EPcPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EExtraPresent ? 1 : 0)); + // + if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EThreadIdentification) && (pCurrentRecord[BTrace::ESubCategoryIndex] == BTrace::EThreadName)) + { + TBuf<255> threadName; + threadName.Format(_L("")); + for (TUint8* j = pCurrentRecord + 12 + extensionCount; j < pCurrentRecord + *pCurrentRecord; j++) + { + threadName.AppendFormat(_L("%c"), *j); + } + if (threadName == KThreadName) + { + test.Printf(_L("This thread's NThread ID: %08x\n"), LE4(pCurrentRecord + 4 + extensionCount)); + gNThreadId = LE4(pCurrentRecord + 4 + extensionCount); + } + } + pCurrentRecord = BTrace::NextRecord(pCurrentRecord); + } + btrace.DataUsed(); + } + } + +void LoadExesRom() + { + TInt r; + TBool pass = ETrue; + r = btrace.ResizeBuffer(32768); // 32k should be large enough + TEST_EQ(r, KErrNone); + btrace.SetFilter(BTrace::EPaging, ETrue); + btrace.SetFilter(BTrace::EThreadIdentification, ETrue); + btrace.SetMode(0); + + for (TInt i = 1; i <= 60; i++) + { + TBuf<255> filename; + filename.Format(_L("Z:\\SYS\\BIN\\DPEXE%03d.EXE"), i); + + test.Printf(_L("Loading %S... "), &filename); + + TBool paged = EFalse; + TBool inRom = EFalse; + + TUint32 nthreadAddr = 0; + TBuf<255> processName; + + if (fs.IsFileInRom(filename) != NULL) + { + inRom = ETrue; + } + else + { + inRom = EFalse; + } + + // Ensure that the paging live list is empty + r = DPTest::FlushCache(); + if (gIsRomDemangPagingEnabled) + { + TEST_EQ(r, KErrNone); + } + else + { + TEST_EQ(r, KErrNotSupported); + } + + btrace.Empty(); // empty the BTrace buffer + btrace.SetMode(RBTrace::EEnable); + RProcess proc; + r = proc.Create(filename, _L("")); + + if ((testExeAttr[i] & EIBYAlias) && (testExeAttr[i] & EIBYData) && (gIsRomDemangPagingEnabled)) + // There cannot be aliases mapping to "data" files since they are moved to ROFS if the ROM is paged + { + TEST_EQ(r, KErrNotFound); + continue; + } + else + { + TEST_EQ(r, KErrNone); + } + + // Resume the process and wait until it completes + TRequestStatus ps; + proc.Logon(ps); + proc.Resume(); + proc.Close(); + User::WaitForRequest(ps); + + // Disable trace + btrace.SetMode(0); + + TInt size; + TUint8* pDataStart; + TUint8* pCurrentRecord; + + // We have a while loop here, in the unlikely case that our trace is fragmented + while ((size = btrace.GetData(pDataStart)) != 0) + { + pCurrentRecord = pDataStart; + while (pCurrentRecord - pDataStart < size) + { + // Number of bytes used by the BTrace extensions + TInt extensionCount = 4 * ( + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EHeader2Present ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestampPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EContextIdPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EPcPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EExtraPresent ? 1 : 0)); + + if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EThreadIdentification) && (pCurrentRecord[BTrace::ESubCategoryIndex] == BTrace::EProcessName)) + // Process renamed + { + processName.Format(_L("")); + for (TUint8* j = pCurrentRecord + 12 + extensionCount; j < pCurrentRecord + *pCurrentRecord; j++) + { + processName.AppendFormat(_L("%c"), *j); + } + TBuf<255> expected; + expected.Format(_L("dpexe%03d.exe[%08x]%04x"), i, 0, 1); + + if (processName == expected) + { + nthreadAddr = LE4(pCurrentRecord + 4 + extensionCount); + } + } + if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EPaging) && (LE4(pCurrentRecord + 8) == nthreadAddr)) + /* The main thread of the test process tries to page in the test executable */ + { + paged = ETrue; + } + pCurrentRecord = BTrace::NextRecord(pCurrentRecord); // move on to the next record + } + btrace.DataUsed(); + } + + if (paged) + test.Printf(_L("paged!\n")); + else + test.Printf(_L("not paged!\n")); + + if (!gIsRomDemangPagingEnabled) + // ROM paging disabled. All files are in ROM and unpaged + { + test.Printf(_L("ROM Paging disabled: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (testExeAttr[i] & EIBYData) + // data - if ROM paged, then these executables will be moved to ROFS + // these are always expected to be RAM loaded + { + test.Printf(_L("EXE is DATA in ROFS\n")); + TEST_CONDITION(!inRom); + } + else if (testExeAttr[i] & EIBYFileCompress) + // Compression format specified in the IBY file + // These are expected to be stay in ROM, but will be RAM-loaded + { + test.Printf(_L("EXE has own compression method: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + // from this point onwards, all executables can potentially be paged - paging policy takes precedence + else if (gPagingPolicy == EKernelConfigCodePagingPolicyNoPaging) + { + test.Printf(_L("Paging policy is No Paging: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingPolicy == EKernelConfigCodePagingPolicyAlwaysPage) + { + test.Printf(_L("Paging policy is No Paging: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // from this point onwards, paging policy is either Default Paged or Default Unpaged - paging override takes precedence + else if (gPagingOverride == EKernelConfigCodePagingPolicyNoPaging) + { + test.Printf(_L("Paging override is No Paging: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingOverride == EKernelConfigCodePagingPolicyAlwaysPage) + { + test.Printf(_L("Paging override is Always Page: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // from this point onwards, paging policy and override are either Default Paged or Default Unpaged - IBY setting takes precedence + else if (testExeAttr[i] & EIBYPaged) + { + test.Printf(_L("Paged keyword in OBY: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + else if (testExeAttr[i] & EIBYUnpaged) + { + test.Printf(_L("Unpaged keyword in OBY: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + // Next, MMP setting takes precedence + else if (testExeAttr[i] & EMMPPaged) + { + test.Printf(_L("Paged keyword in MMP: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + else if (testExeAttr[i] & EMMPUnpaged) + { + test.Printf(_L("Unpaged keyword in MMP: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + // The test exe has no attribute. Paging overright default paging mode takes precedence + else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultUnpaged) + { + test.Printf(_L("Paging override is Default Unpaged: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultPaged) + { + test.Printf(_L("Paging override is Default Paged: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // Paging policy default paging mode takes precedence + else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultUnpaged) + { + test.Printf(_L("Paging policy is Default Unpaged: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultPaged) + { + test.Printf(_L("Paging policy is Default paged: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // ROM Paging enabled without a default paging policy - this should not happen (default policy is No Paging) + else + { + test.Printf(_L("No paging policy!\n")); + test(EFalse); + } + } + test(pass); + } + + +void LoadDllsRom() + { + TInt r; + TBool pass = ETrue; + r = btrace.ResizeBuffer(32768); // 32k should be large enough + TEST_EQ(r, KErrNone); + btrace.SetFilter(BTrace::EPaging, ETrue); + btrace.SetFilter(BTrace::EThreadIdentification, ETrue); + btrace.SetMode(0); + + for (TInt i = 1; i <= 60; i++) + { + TBuf<255> filename; + filename.Format(_L("Z:\\SYS\\BIN\\DPDLL%03d.DLL"), i); + + test.Printf(_L("Loading %S... "), &filename); + + TBool paged = EFalse; + TBool inRom = EFalse; + + TUint libLoadEnd; + TInt filesize; + + TUint8* addr; + if ((addr = fs.IsFileInRom(filename)) != NULL) + { + inRom = ETrue; + } + else + { + inRom = EFalse; + } + + RFile file; + r = file.Open(fs, filename, EFileRead); + if ((testDllAttr[i] & EIBYAlias) && (testDllAttr[i] & EIBYData) && (gIsRomDemangPagingEnabled)) + // There cannot be aliases mapping to "data" files since they are moved to ROFS if the ROM is paged + { + TEST_EQ(r, KErrNotFound); + continue; + } + else + { + TEST_EQ(r, KErrNone); + } + r = file.Size(filesize); + TEST_EQ(r, KErrNone); + file.Close(); + + // Ensure that the paging live list is empty + r = DPTest::FlushCache(); + if (gIsRomDemangPagingEnabled) + { + TEST_EQ(r, KErrNone); + } + else + { + TEST_EQ(r, KErrNotSupported); + } + + btrace.Empty(); // empty the BTrace buffer + btrace.SetMode(RBTrace::EEnable); + RLibrary lib; + r = lib.Load(filename); + libLoadEnd = User::FastCounter(); + + TEST_EQ(r, KErrNone); + + TLibraryFunction function1; + TLibraryFunction function2; + TLibraryFunction function3; + TLibraryFunction function4; + + function1 = lib.Lookup(1); + function2 = lib.Lookup(2); + function3 = lib.Lookup(3); + function4 = lib.Lookup(4); + + test(function1 != NULL); + test(function2 != NULL); + test(function3 != NULL); + test(function4 == NULL); + + // Resume the process and wait until it completes + + function1(); + function2(); + function3(); + + lib.Close(); + + //processResumeStart = User::FastCounter(); + //processResumeEnd = User::FastCounter(); + + // Disable trace + btrace.SetMode(0); + + TInt size; + TUint8* pDataStart; + TUint8* pCurrentRecord; + + // We have a while loop here, in the unlikely case that our trace is fragmented + while ((size = btrace.GetData(pDataStart)) != 0) + { + pCurrentRecord = pDataStart; + while (pCurrentRecord - pDataStart < size) + { + // Number of bytes used by the BTrace extensions + TInt extensionCount = 4 * ( + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EHeader2Present ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestampPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EContextIdPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EPcPresent ? 1 : 0) + + (pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EExtraPresent ? 1 : 0)); + + if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EPaging) + && (pCurrentRecord[BTrace::ESubCategoryIndex] == BTrace::EPagingPageInBegin) + && (LE4(pCurrentRecord + 4) > libLoadEnd) + && (LE4(pCurrentRecord + extensionCount) == gNThreadId) + && (LE4(pCurrentRecord + 4 + extensionCount) >= (TUint32) addr) + && (LE4(pCurrentRecord + 4 + extensionCount) < ((TUint32) addr) + filesize)) + // If the DLL is paged in under this thread after it's been RLibrary::Load'ed, then we assume the DLL is paged + { + paged = ETrue; + } + pCurrentRecord = BTrace::NextRecord(pCurrentRecord); // move on to the next record + } + btrace.DataUsed(); + } + + if (paged) + test.Printf(_L("paged!\n")); + else + test.Printf(_L("not paged!\n")); + + if (!gIsRomDemangPagingEnabled) + // ROM paging disabled. All files are in ROM and unpaged + { + test.Printf(_L("ROM Paging disabled: shouldn't be paged\n")); + test(inRom); + TEST_CONDITION(!paged); + } + else if (testDllAttr[i] & EIBYData) + // data - if ROM paged, then these executables will be moved to ROFS + // these are always expected to be RAM loaded + { + test.Printf(_L("DLL is DATA in ROFS: shouldn't be paged\n")); + TEST_CONDITION(!inRom); + TEST_CONDITION(!paged); + } + else if (testDllAttr[i] & EIBYFileCompress) + // Compression format specified in the IBY file + // These are expected to be stay in ROM, but will be RAM-loaded + { + test.Printf(_L("DLL has own compression method: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + // from this point onwards, all executables can potentially be paged - paging policy takes precedence + else if (gPagingPolicy == EKernelConfigCodePagingPolicyNoPaging) + { + test.Printf(_L("Paging policy is No Paging: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingPolicy == EKernelConfigCodePagingPolicyAlwaysPage) + { + test.Printf(_L("Paging policy is Always Page: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // from this point onwards, paging policy is either Default Paged or Default Unpaged - paging override takes precedence + else if (gPagingOverride == EKernelConfigCodePagingPolicyNoPaging) + { + test.Printf(_L("Paging override is No Paging: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingOverride == EKernelConfigCodePagingPolicyAlwaysPage) + { + test.Printf(_L("Paging override is Always Page: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // from this point onwards, paging policy and override are either Default Paged or Default Unpaged - IBY setting takes precedence + else if (testDllAttr[i] & EIBYPaged) + { + test.Printf(_L("Paged keyword in OBY: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + else if (testDllAttr[i] & EIBYUnpaged) + { + test.Printf(_L("Unpaged keyword in OBY: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + // Next, MMP setting takes precedence + else if (testDllAttr[i] & EMMPPaged) + { + test.Printf(_L("Paged keyword in MMP: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + else if (testDllAttr[i] & EMMPUnpaged) + { + test.Printf(_L("Unpaged keyword in MMP: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + // The test exe has no attribute. Paging overright default paging mode takes precedence + else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultUnpaged) + { + test.Printf(_L("Paging override is Default Unpaged: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultPaged) + { + test.Printf(_L("Paging override is Default Paged: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // Paging policy default paging mode takes precedence + else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultUnpaged) + { + test.Printf(_L("Paging policy is Default Unpaged: shouldn't be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(!paged); + } + else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultPaged) + { + test.Printf(_L("Paging policy is Default paged: should be paged\n")); + TEST_CONDITION(inRom); + TEST_CONDITION(paged); + } + // ROM Paging enabled without a default paging policy - this should not happen (default policy is No Paging) + else + { + test.Printf(_L("No paging policy!\n")); + test(EFalse); + } + } + test(pass); + } + +GLDEF_C TInt E32Main() + { + TInt r; + test.Title(); + test.Start(_L("Check environment")); + + // Open the BTrace handler + r = btrace.Open(); + TEST_EQ(r, KErrNone); + + // capture the NThread ID of the main thread of the current process + InitNThreadID(); + test(gNThreadId != 0); + + gPagingPolicy = E32Loader::PagingPolicy(); + gPagingOverride = -1; + + r = fs.Connect(); + TEST_EQ(r, KErrNone); + + if (fs.IsFileInRom(_L("\\ovr_nopaging")) != NULL) + { + gPagingOverride = EKernelConfigCodePagingPolicyNoPaging; + } + if (fs.IsFileInRom(_L("\\ovr_alwayspage")) != NULL) + { + gPagingOverride = EKernelConfigCodePagingPolicyAlwaysPage; + } + if (fs.IsFileInRom(_L("\\ovr_defaultunpaged")) != NULL) + { + gPagingOverride = EKernelConfigCodePagingPolicyDefaultUnpaged; + } + if (fs.IsFileInRom(_L("\\ovr_defaultpaged")) != NULL) + { + gPagingOverride = EKernelConfigCodePagingPolicyDefaultPaged; + } + if (fs.IsFileInRom(_L("\\pcy_nopaging")) != NULL) + { + gPagingPolicy = EKernelConfigCodePagingPolicyNoPaging; + } + if (fs.IsFileInRom(_L("\\pcy_alwayspage")) != NULL) + { + gPagingPolicy = EKernelConfigCodePagingPolicyAlwaysPage; + } + if (fs.IsFileInRom(_L("\\pcy_defaultunpaged")) != NULL) + { + gPagingPolicy = EKernelConfigCodePagingPolicyDefaultUnpaged; + } + if (fs.IsFileInRom(_L("\\pcy_defaultpaged")) != NULL) + { + gPagingPolicy = EKernelConfigCodePagingPolicyDefaultPaged; + } + + gIsRomDemangPagingEnabled = (fs.IsFileInRom(_L("Z:\\SYS\\BIN\\DPEXE046.EXE")) == NULL); + + test.Printf(_L("Demand Paging Enabled? %d\n"), gIsRomDemangPagingEnabled); + test.Printf(_L("PagingOverride %d\n"), gPagingOverride); + test.Printf(_L("PagingPolicy %d\n"), gPagingPolicy); + + test.Next(_L("Load ROM EXEs")); + LoadExesRom(); + test.Next(_L("Load ROM DLLs")); + LoadDllsRom(); + + btrace.Close(); + fs.Close(); + test.End(); + test.Close(); + return KErrNone; + }