Update contrib.
     1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
     2 // All rights reserved.
 
     3 // This component and the accompanying materials are made available
 
     4 // under the terms of the License "Eclipse Public License v1.0"
 
     5 // which accompanies this distribution, and is available
 
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
 
     8 // Initial Contributors:
 
     9 // Nokia Corporation - initial contribution.
 
    14 // e32test\mmu\t_alias_remove.cpp
 
    16 // Test interactions when free memory being aliases.
 
    18 // Create 3 mappings to one chunk one that owns the chunk, one to map it again another process 
 
    19 // and another alias mapping.
 
    20 // Then while the alias mapping is accessing the chunk close the second mapping.
 
    21 // Platforms/Drives/Compatibility:
 
    23 // Assumptions/Requirement/Pre-requisites:
 
    24 // Failures and causes:
 
    25 // Base Port information:
 
    29 #define __E32TEST_EXTENSION__
 
    33 #include "..\defrag\d_pagemove.h"
 
    35 const TPtrC KAliasProcessName = _L("T_ALIAS_REMOVE");
 
    36 const TPtrC KAliasChunkName = _L("AliasChunk");
 
    37 const TPtrC KAliasServerName = _L("AliasServer");
 
    38 const TPtrC KMasterServerName = _L("MasterServer");
 
    41 RBuf MasterServerName;
 
    44 RTest test(KAliasProcessName);
 
    46 //#define ENABLE_PRINTFS
 
    47 #ifndef __MSVC6__	// VC6 can't cope with variable arguments in macros.
 
    49 #define T_PRINTF(x...) test.Printf(x)
 
    50 #define D_PRINTF(x...) RDebug::Printf(x)
 
    55 #endif // ENABLE_PRINTFS
 
    64 	ESlaveDisconnect = -2,
 
    66 	ESlaveClosedChunk = 1,
 
    74 	RThread* iMasterThread;
 
    79 class RAliasSession : public RSessionBase
 
    82 	TInt CreateSession(const TDesC& aServerName, TInt aMsgSlots) 
 
    84 		return RSessionBase::CreateSession(aServerName,User::Version(),aMsgSlots);
 
    86 	TInt PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr)
 
    88 		return (SendReceive(aFunction, aPtr));
 
    90 	TInt PublicSend(TInt aFunction, const TIpcArgs &aPtr)
 
    92 		return (Send(aFunction, aPtr));
 
    97 TInt SlaveProcess(TUint aProcessId, TUint aFillValue)
 
    99 	// Connect to the master server to indicate that we're ready to receive ipc messages.
 
   100 	RAliasSession masterSession;
 
   101 	test_KErrNone(masterSession.CreateSession(MasterServerName, 1));
 
   103 	PRINTF(T_PRINTF(_L("Process ID %d Slave open chunk\n"), aProcessId));
 
   104 	// Open the global chunk.
 
   106 	TInt r = chunk.OpenGlobal(ChunkName, ETrue);
 
   109 	// Connect to alias server.
 
   110 	PRINTF(T_PRINTF(_L("Process ID %d Slave connect to alias server\n"), aProcessId));
 
   111 	RAliasSession aliasSession;
 
   112 	test_KErrNone(aliasSession.CreateSession(AliasServerName, 1));
 
   114 	PRINTF(T_PRINTF(_L("Process ID %d Slave send data to alias server\n"), aProcessId));
 
   115 	TPtr8 arg0(chunk.Base(), chunk.Size(), chunk.Size());
 
   116 	r = aliasSession.PublicSend(ESlaveReadChunk, TIpcArgs(&arg0));
 
   119 	// Close the chunk removing its mapping before the server has read it.
 
   121 	PRINTF(T_PRINTF(_L("Process ID %d Slave closed chunk\n"), aProcessId));
 
   123 	r = masterSession.PublicSendReceive(ESlaveClosedChunk, TIpcArgs());
 
   125 	aliasSession.Close();
 
   126 	masterSession.Close();
 
   131 TInt ChunkReadThread(TAny* aThreadData)
 
   133 	SThreadData* threadData =  (SThreadData*)aThreadData;
 
   134 	RServer2 aliasServer;
 
   135 	TInt r = aliasServer.CreateGlobal(AliasServerName);
 
   138 		RDebug::Printf("Process ID %d Error creating alias server r=%d", threadData->iProcessId, r);
 
   141 	// Connect to the master server to indicate that we're ready to receive ipc messages.
 
   142 	RAliasSession masterSession;
 
   143 	test_KErrNone(masterSession.CreateSession(MasterServerName, 1));
 
   145 	PRINTF(D_PRINTF("Process ID %d Alias wait for slave connection", threadData->iProcessId));
 
   146 	RMessage2 aliasMessage;
 
   147 	// Read and complete the connect message from the slave.
 
   148 	aliasServer.Receive(aliasMessage);
 
   149 	test_Equal(ESlaveConnect, aliasMessage.Function());
 
   150 	aliasMessage.Complete(KErrNone);
 
   152 	// Read the data of the remote chunk.
 
   153 	PRINTF(D_PRINTF("Process ID %d Alias read chunk data", threadData->iProcessId));
 
   154 	HBufC8* argTmp = HBufC8::New(threadData->iChunkSize);
 
   155 	test_NotNull(argTmp);
 
   156 	RBuf8 argBuf(argTmp);
 
   157 	aliasServer.Receive(aliasMessage);
 
   158 	test_Equal(ESlaveReadChunk, aliasMessage.Function());
 
   159 	r = aliasMessage.Read(0, argBuf);
 
   161 		{// Successfully read the chunk so verify it.
 
   162 		aliasMessage.Complete(KErrNone);
 
   164 		PRINTF(D_PRINTF("Process ID %d Alias verify chunk data", threadData->iProcessId));
 
   165 		const TUint8* bufPtr = argBuf.Ptr();
 
   166 		const TUint8* bufEnd = bufPtr + threadData->iChunkSize;
 
   167 		for (; bufPtr < bufEnd; bufPtr++)
 
   169 			if (*bufPtr != threadData->iFillValue)
 
   171 				RDebug::Printf("Process ID %d Read incorrect data exp 0x%x got 0x%x", 
 
   172 								threadData->iProcessId, threadData->iFillValue, *bufPtr);
 
   180 		PRINTF(D_PRINTF("Process ID %d Error reading chunk remotely %d", threadData->iProcessId, r));
 
   183 	masterSession.Close();
 
   188 TInt MasterProcess(TInt aProcessId)
 
   191 	UserHal::PageSizeInBytes(pageSize);
 
   192 	// Need a large chunk so that alias that reads it is held for a long
 
   193 	// enough period for there to be conflicts with the chunk closure in 
 
   194 	// the slave process.
 
   195 	const TUint KChunkSize = pageSize * 1024;
 
   197 	PRINTF(T_PRINTF(_L("Process ID %d Create chunk\n"), aProcessId));
 
   199 	TInt r = chunk.CreateGlobal(ChunkName, KChunkSize, KChunkSize);
 
   203 	for (TUint8 fillValue = 1; fillValue < 255; fillValue++)
 
   205 		// Output a character every 16 iterations so test machines 
 
   207 		if ((fillValue & 0xf) == 1)
 
   208 			test.Printf(_L("."));
 
   210 		PRINTF(T_PRINTF(_L("Process ID %d start slave fill value %d\n"), aProcessId, fillValue));
 
   211 		RServer2 masterServer;
 
   212 		r = masterServer.CreateGlobal(MasterServerName);
 
   214 		RMessage2 masterMessage;
 
   216 		// Update the chunk to new fill value.
 
   217 		memset(chunk.Base(), fillValue, KChunkSize);
 
   219 		PRINTF(T_PRINTF(_L("Process ID %d Start the slave process\n"), aProcessId));
 
   220 		RProcess slaveProcess;
 
   221 		test_KErrNone(slaveProcess.Create(KAliasProcessName, KNullDesC));
 
   222 		test_KErrNone(slaveProcess.SetParameter(1, aProcessId));
 
   223 		test_KErrNone(slaveProcess.SetParameter(2, fillValue));
 
   224 		TRequestStatus slaveStatus;
 
   225 		slaveProcess.Logon(slaveStatus);
 
   226 		test_Equal(KRequestPending, slaveStatus.Int());
 
   227 		slaveProcess.Resume();
 
   229 		// Wait for the connect message from the slave process.
 
   230 		masterServer.Receive(masterMessage);
 
   231 		test_Equal(ESlaveConnect, masterMessage.Function());
 
   233 		SThreadData threadData;
 
   234 		threadData.iFillValue = fillValue;
 
   235 		threadData.iChunkSize = KChunkSize;
 
   236 		threadData.iProcessId = aProcessId;
 
   238 		r = readThread.Create(KNullDesC, ChunkReadThread, 10 * pageSize, KChunkSize, KChunkSize * 2, &threadData);
 
   240 		TRequestStatus threadStatus;
 
   241 		readThread.Logon(threadStatus);
 
   242 		test_Equal(KRequestPending, threadStatus.Int());
 
   245 		PRINTF(T_PRINTF(_L("Process ID %d Wait for alias thread to start server\n"), aProcessId));
 
   246 		RMessage2 aliasMessage;
 
   247 		masterServer.Receive(aliasMessage);
 
   248 		test_Equal(ESlaveConnect, aliasMessage.Function());
 
   249 		aliasMessage.Complete(KErrNone);
 
   251 		// Signal to the slave process to send chunk to alias thread.
 
   252 		PRINTF(T_PRINTF(_L("Process ID %d Signal to slave to send chunk to alias\n"), aProcessId));
 
   253 		masterMessage.Complete(KErrNone);
 
   255 		// Wait for slave to close the chunk and fill it with new value.
 
   258 			masterServer.Receive(masterMessage);
 
   259 			TInt func = masterMessage.Function();
 
   260 			PRINTF(T_PRINTF(_L("Process ID %d rxd %d\n"), aProcessId, func));
 
   261 			if (func == ESlaveClosedChunk)
 
   262 				{// Slave closed the chunk.
 
   263 				memset(chunk.Base(), ++fillValue, KChunkSize);
 
   267 				{// Alias has read the chunk and completed.
 
   268 				test_Equal(ESlaveDisconnect, func);
 
   272 		PRINTF(T_PRINTF(_L("Process ID %d Wait for alias to complete\n"), aProcessId));
 
   273 		masterMessage.Complete(KErrNone);
 
   274 		User::WaitForRequest(threadStatus);
 
   275 		TInt statusInt = threadStatus.Int();
 
   276 		test_Value(	statusInt, 
 
   277 					statusInt == KErrNone || 
 
   278 					statusInt == KErrBadDescriptor ||
 
   279 					statusInt == KErrDied);
 
   280 		test_Equal(EExitKill, readThread.ExitType());
 
   283 		PRINTF(T_PRINTF(_L("Process ID %d Wait for slave to complete\n"), aProcessId));
 
   284 		User::WaitForRequest(slaveStatus);
 
   285 		test_Equal(EExitKill, slaveProcess.ExitType());
 
   286 		test_Equal(KErrNone, slaveProcess.ExitReason());
 
   287 		slaveProcess.Close();
 
   288 		masterServer.Close();
 
   297 GLDEF_C TInt E32Main()
 
   300 	if(User::GetTIntParameter(1, processId)==KErrNone)
 
   302 		test_KErrNone(ChunkName.Create(KAliasChunkName.Length() + 3));
 
   303 		ChunkName.Copy(KAliasChunkName);
 
   304 		ChunkName.AppendNum(processId);
 
   306 		test_KErrNone(MasterServerName.Create(KMasterServerName.Length() + 3));
 
   307 		MasterServerName.Copy(KMasterServerName);
 
   308 		MasterServerName.AppendNum(processId);
 
   310 		test_KErrNone(AliasServerName.Create(KAliasServerName.Length() + 3));
 
   311 		AliasServerName.Copy(KAliasServerName);
 
   312 		AliasServerName.AppendNum(processId);
 
   315 		if(User::GetTIntParameter(2, fillValue)==KErrNone)
 
   317 			return SlaveProcess(processId, fillValue);
 
   319 		return MasterProcess(processId);
 
   322 	// Get the number of cpus and use it to determine how many processes to execute.
 
   324 	test_KErrNone(pagemove.Open());
 
   325 	TUint masterProcesses = pagemove.NumberOfCpus() + 1;
 
   328 	TInt cmdLineLen = User::CommandLineLength();
 
   332 		test_KErrNone(cmdLine.Create(cmdLineLen));
 
   333 		User::CommandLine(cmdLine);
 
   334 		test_KErrNone(TLex(cmdLine).Val(masterProcesses));
 
   339 	test.Printf(_L("Create %d processes for accessing aliases being removed\n"), masterProcesses); 
 
   341 	TUint32 debugMask = UserSvr::DebugMask();
 
   342 	User::SetDebugMask(0);
 
   344 	// Start master processes to alias memory between each other.
 
   345 	RProcess* masters = new RProcess[masterProcesses];
 
   346 	TRequestStatus* masterStatus = new TRequestStatus[masterProcesses];
 
   348 	for (; i < masterProcesses; i++)
 
   350 		test_KErrNone(masters[i].Create(KAliasProcessName, KNullDesC));
 
   351 		test_KErrNone(masters[i].SetParameter(1, i));
 
   352 		masters[i].Logon(masterStatus[i]);
 
   353 		test_Equal(KRequestPending, masterStatus[i].Int());
 
   355 	test.Next(_L("Resume the processes")); 
 
   356 	for (i = 0; i < masterProcesses; i++)
 
   361 	test.Next(_L("Wait for processes to exit")); 
 
   362 	for (i = 0; i < masterProcesses; i++)
 
   364 		User::WaitForRequest(masterStatus[i]);
 
   365 		test_Equal(EExitKill, masters[i].ExitType());
 
   366 		test_Equal(KErrNone, masters[i].ExitReason());
 
   368 	User::SetDebugMask(debugMask);
 
   371 	test.Printf(_L("\n"));