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