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"));