diff -r 000000000000 -r a41df078684a kerneltest/e32test/mmu/t_asid.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/t_asid.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,240 @@ +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\misc\t_asid.cpp +// +// +#define __E32TEST_EXTENSION__ +#include +#include +#include + +#include "t_asid.h" +#include "d_asid.h" + +#define TEST_R(r, e) if (!(e)) {RDebug::Printf("Failure at line %d, r = %d", __LINE__, r); return r; } + +_LIT(KDummyProcessName,"T_ASID_DUMMY"); + +RTest test(_L("T_ASID")); + +const TUint KMaxAsids = 256; // On arm and current version of FMM has maximum of 256 active processes at once. +const TUint KLeakedProcesses = KMaxAsids<<1; + +void TestMaxAsids() + { + test.Printf(_L("Attempt to load > %d zombie processes\n"), KMaxAsids); + RProcess* processes = new RProcess[KLeakedProcesses]; + TUint i = 0; + for (; i < KLeakedProcesses; i++) + { + test_KErrNone(processes[i].Create(KDummyProcessName, KNullDesC)); + TRequestStatus s; + processes[i].Logon(s); + test_Equal(KRequestPending, s.Int()); + processes[i].Resume(); + User::WaitForRequest(s); + if (processes[i].ExitType()!=EExitKill || processes[i].ExitReason()!=KErrNone) + { + TExitCategoryName aExitCategory = processes[i].ExitCategory(); + test.Printf(_L("Exit %d,%d,%S\n"),processes[i].ExitType(),processes[i].ExitReason(),&aExitCategory); + test(0); + } + } + // Clean up the process handles here. + for (i = 0; i < KLeakedProcesses; i++) + processes[i].Close(); + delete[] processes; + } + + +TInt TestIpcThread(TAny*) + { + // Start a server for zombie to connect to. + RServer2 ipcServer; + TInt r = ipcServer.CreateGlobal(KAsidIpcServerName); + TEST_R(r, r == KErrNone); + RMessage2 ipcMessage; + for (TUint i = 0; i < 300; i++) + { + // Start the process. + RProcess zombie; + TInt r = zombie.Create(KDummyProcessName, KAsidIpcServerName); + TEST_R(r, r == KErrNone); + TRequestStatus s; + zombie.Logon(s); + TEST_R(s.Int(), s.Int() == KRequestPending); + zombie.Resume(); + + // Wait for the connect and ipc message from the zombie + ipcServer.Receive(ipcMessage); + TEST_R(ipcMessage.Function(), ipcMessage.Function() == EConnect); + ipcMessage.Complete(KErrNone); + ipcServer.Receive(ipcMessage); + TEST_R(ipcMessage.Function(), ipcMessage.Function() == EIpcData); + + TUint8 array1[KAsidDesLen]; + memset(array1, KAsidValue, KAsidDesLen); + TPtr8 buf1(array1, KAsidDesLen, KAsidDesLen); + + TUint8 array[KAsidDesLen]; + TPtr8 buf(array, KAsidDesLen); + test_Equal(KErrNone, ipcMessage.Read(0, buf)); + r = ipcMessage.Read(0, buf); + TEST_R(r, r == KErrNone); + r = buf.Compare(buf1); + TEST_R(r, r == 0); + ipcMessage.Complete(KErrNone); + + // Try to read from the client while it is exiting. + ipcServer.Receive(ipcMessage); + TEST_R(ipcMessage.Function(), ipcMessage.Function() == EIpcData); + User::After(5*i); + + r = ipcMessage.Read(0, buf); + //RDebug::Printf("%d", r); + + // Wait for client to exit. + User::WaitForRequest(s); + TEST_R(s.Int(), s.Int() == KErrNone); + ipcServer.Receive(ipcMessage); // Clear out the disconnect message. + TEST_R(ipcMessage.Function(), ipcMessage.Function() == EDisConnect); + ipcMessage.Complete(KErrNone); + zombie.Close(); + } + ipcServer.Close(); + return KErrNone; + } + + +TInt TestDesThread(TAny*) + { + RAsidLdd asidLdd; + TInt r = asidLdd.Open(); + TEST_R(r, r == KErrNone); + RMessage2 desMessage; + RServer2 desServer; + // Start a server for zombie to connect to. + r = desServer.CreateGlobal(KAsidDesServerName); + TEST_R(r, r == KErrNone); + + for (TUint i = 0; i < 300; i++) + { + // Start the process. + RProcess zombie; + r = zombie.Create(KDummyProcessName, KAsidDesServerName); + TEST_R(r, r == KErrNone); + TRequestStatus s; + zombie.Logon(s); + TEST_R(s.Int(), s.Int() == KRequestPending); + zombie.Resume(); + + // Wait for the connect and des message from the zombie + desServer.Receive(desMessage); + TEST_R(desMessage.Function(), desMessage.Function() == EConnect); + desMessage.Complete(KErrNone); + desServer.Receive(desMessage); + TEST_R(desMessage.Function(), desMessage.Function() == EDesData); + + TAny* desPtr = (TAny*)desMessage.Ptr0(); + TAny* threadPtr = (TAny*)desMessage.Ptr1(); + // Open a handle on the client's thread to stop it being deleted. + r = asidLdd.OpenThread(threadPtr); + TEST_R(r, r == KErrNone); + SDesHeader desHdr; + desHdr.iDes = desPtr; + r = asidLdd.ReadDesHeader(threadPtr, desHdr); + TEST_R(r, r == KErrNone); + TEST_R(desHdr.iLength, desHdr.iLength == KAsidDesLen); + TEST_R(desHdr.iMaxLength, desHdr.iMaxLength == KAsidDesLen); + desMessage.Complete(KErrNone); + + // Wait for further des message from client. + desServer.Receive(desMessage); + TEST_R(desMessage.Function(), desMessage.Function() == EDesData); + desPtr = (TAny*)desMessage.Ptr0(); + TEST_R((TInt)desMessage.Ptr1(), (TInt)desMessage.Ptr1() == (TInt)threadPtr); + + // Try to read descriptor header from the client while it is exiting. + TInt r = asidLdd.ReadDesHeader(threadPtr, desHdr); + User::After(5*i); + + //RDebug::Printf("%d", r); + if (r == KErrNone) + { + TEST_R(desHdr.iLength, desHdr.iLength == KAsidDesLen); + TEST_R(desHdr.iMaxLength, desHdr.iMaxLength == KAsidDesLen); + } + + // Wait for client to exit. + User::WaitForRequest(s); + TEST_R(s.Int(), s.Int() == KErrNone); + desServer.Receive(desMessage); // Clear out the disconnect message. + TEST_R(desMessage.Function(), desMessage.Function() == EDisConnect); + desMessage.Complete(KErrNone); + // Close handles in client process and thread. + r = asidLdd.CloseThread(); + TEST_R(r, r == KErrNone); + zombie.Close(); + } + desServer.Close(); + asidLdd.Close(); + return KErrNone; + } + +GLDEF_C TInt E32Main() + { + test.Title(); + test.Start(_L("Test zombie processes release their ASIDs")); + + // Get memory model. + if ((UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL)&EMemModelTypeMask) < EMemModelTypeFlexible) + { + test.Printf(_L("SKIPPING TEST - Older memory models don't release ASIDs from zombie processes\n")); + test.End(); + return KErrNone; + } + + TestMaxAsids(); + + test.Next(_L("Test ipc message copy to a zombie process")); + + test_KErrNone(TestIpcThread(NULL)); + TestMaxAsids(); + + test.Next(_L("Test reading descriptor header from a zombie process")); + test_KErrNone(TestDesThread(NULL)); + TestMaxAsids(); + + test.Next(_L("Test ipc and des header to zombie processes concurrently")); + RThread ipcThread; + RThread desThread; + ipcThread.Create(KNullDesC, TestIpcThread, 0x2000, NULL, NULL); + desThread.Create(KNullDesC, TestDesThread, 0x2000, NULL, NULL); + TRequestStatus ipcStatus; + TRequestStatus desStatus; + ipcThread.Logon(ipcStatus); + desThread.Logon(desStatus); + ipcThread.Resume(); + desThread.Resume(); + + // Wait for threads to complete. + User::WaitForRequest(ipcStatus); + test_KErrNone(ipcStatus.Int()); + User::WaitForRequest(desStatus); + test_KErrNone(desStatus.Int()); + TestMaxAsids(); + + test.End(); + return KErrNone; + }