1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/mmu/t_mmustress.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,669 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\mmu\t_mmustress.cpp
1.18 +// Stress test for memory management services performed by the kernel's memory model.
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 + @file
1.24 +*/
1.25 +
1.26 +#define __E32TEST_EXTENSION__
1.27 +#include <e32test.h>
1.28 +#include "u32std.h"
1.29 +#include <u32hal.h>
1.30 +#include <e32svr.h>
1.31 +#include <dptest.h>
1.32 +#include <e32def.h>
1.33 +#include <e32def_private.h>
1.34 +#include "d_memorytest.h"
1.35 +#include "..\defrag\d_pagemove.h"
1.36 +
1.37 +TBool TRACE = 0;
1.38 +
1.39 +LOCAL_D RTest test(_L("T_MMUSTRESS"));
1.40 +
1.41 +TUint32 MemModelAttributes;
1.42 +TUint32 MemModel;
1.43 +TInt PageSize;
1.44 +TInt PageMask;
1.45 +
1.46 +#if !defined(__WINS__) && !defined(__X86__)
1.47 +const TPtrC KMoveLddFileName=_L("D_PAGEMOVE.LDD");
1.48 +RPageMove MoveLdd;
1.49 +#endif
1.50 +
1.51 +RMemoryTestLdd Ldd;
1.52 +
1.53 +const TUint KNumTestChunks = 6;
1.54 +RChunk Chunks[KNumTestChunks];
1.55 +TInt Committed[KNumTestChunks] = {0}; // for each chunk, is the 'owned' region uncommited(0), commited(1) or mixed(-1)
1.56 +class TNicePtr8 : public TPtr8 { public: TNicePtr8() : TPtr8(0,0) {} } ChunkPtr[KNumTestChunks];
1.57 +
1.58 +const TUint KNumSlaveProcesses = 4;
1.59 +RProcess Slaves[KNumSlaveProcesses];
1.60 +TRequestStatus SlaveLogons[KNumSlaveProcesses];
1.61 +TRequestStatus SlaveRendezvous[KNumSlaveProcesses];
1.62 +
1.63 +TInt SlaveNumber = -1; // master process is slave -1
1.64 +
1.65 +const TInt KLocalIpcBufferSize = 0x10000;
1.66 +TUint8* LocalIpcBuffer = 0;
1.67 +
1.68 +RSemaphore StartSemaphore;
1.69 +
1.70 +//
1.71 +// Random number generation
1.72 +//
1.73 +
1.74 +TUint32 RandomSeed;
1.75 +
1.76 +TUint32 Random()
1.77 + {
1.78 + RandomSeed = RandomSeed*69069+1;
1.79 + return RandomSeed;
1.80 + }
1.81 +
1.82 +TUint32 Random(TUint32 aRange)
1.83 + {
1.84 + return (TUint32)((TUint64(Random())*TUint64(aRange))>>32);
1.85 + }
1.86 +
1.87 +void RandomInit(TUint32 aSeed)
1.88 + {
1.89 + RandomSeed = aSeed+(aSeed<<8)+(aSeed<<16)+(aSeed<<24);
1.90 + Random();
1.91 + Random();
1.92 + }
1.93 +
1.94 +
1.95 +
1.96 +//
1.97 +// Chunk utils
1.98 +//
1.99 +
1.100 +TBuf<KMaxKernelName> ChunkName(TInt aChunkNumber)
1.101 + {
1.102 + TBuf<KMaxKernelName> name;
1.103 + name.Format(_L("T_MMUSTRESS-Chunk%d"),aChunkNumber);
1.104 + return name;
1.105 + }
1.106 +
1.107 +#ifdef __WINS__
1.108 +TInt KChunkShift = 16;
1.109 +#elif defined(__X86__)
1.110 +TInt KChunkShift = 22;
1.111 +#else
1.112 +TInt KChunkShift = 20;
1.113 +#endif
1.114 +
1.115 +TInt ChunkSize(TInt aChunkNumber)
1.116 + {
1.117 + // biggest chunk (number 0) is big enough for each slave to own a region which is
1.118 + // 2 page tables ('chunks') in size...
1.119 + return (2*KNumSlaveProcesses)<<(KChunkShift-aChunkNumber);
1.120 + }
1.121 +
1.122 +// check smallest chunk is less than 'chunk' size...
1.123 +__ASSERT_COMPILE((2*KNumSlaveProcesses>>(KNumTestChunks-1))==0);
1.124 +
1.125 +
1.126 +/* Memory region 'owned' by this slave process */
1.127 +void ChunkOwnedRegion(TInt aChunkNumber,TInt& aOffset,TInt& aSize)
1.128 + {
1.129 + TInt size = ChunkSize(aChunkNumber)/KNumSlaveProcesses;
1.130 + aSize = size;
1.131 + aOffset = SlaveNumber*size;
1.132 + test_Equal(0,size&PageMask);
1.133 + }
1.134 +
1.135 +void ChunkMarkRegion(TInt aChunkNumber,TInt aOffset,TInt aSize)
1.136 + {
1.137 + TInt pageSize = PageSize;
1.138 + TUint32 mark = aOffset|aChunkNumber|(SlaveNumber<<4);
1.139 + TUint8* ptr = Chunks[aChunkNumber].Base()+aOffset;
1.140 + TUint8* ptrEnd = ptr+aSize;
1.141 + while(ptr<ptrEnd)
1.142 + {
1.143 + ((TUint32*)ptr)[0] = mark;
1.144 + ((TUint32*)ptr)[1] = ~mark;
1.145 + mark += pageSize;
1.146 + ptr += pageSize;
1.147 + }
1.148 + }
1.149 +
1.150 +void ChunkCheckRegion(TInt aChunkNumber,TInt aOffset,TInt aSize)
1.151 + {
1.152 + TInt pageSize = PageSize;
1.153 + TUint32 mark = aOffset|aChunkNumber|(SlaveNumber<<4);
1.154 + TUint8* ptr = Chunks[aChunkNumber].Base()+aOffset;
1.155 + TUint8* ptrEnd = ptr+aSize;
1.156 + while(ptr<ptrEnd)
1.157 + {
1.158 + test_Equal(mark,((TUint32*)ptr)[0]);
1.159 + test_Equal(~mark,((TUint32*)ptr)[1]);
1.160 + mark += pageSize;
1.161 + ptr += pageSize;
1.162 + }
1.163 + }
1.164 +
1.165 +TInt ChunkOpen(TInt aChunkNumber)
1.166 + {
1.167 + RChunk& chunk = Chunks[aChunkNumber];
1.168 + if(chunk.Handle()!=0)
1.169 + return KErrNone;
1.170 +
1.171 + if(TRACE) RDebug::Printf("%d %d Open",SlaveNumber,aChunkNumber);
1.172 + TInt r = chunk.OpenGlobal(ChunkName(aChunkNumber),false);
1.173 + if(r!=KErrNoMemory)
1.174 + test_KErrNone(r);
1.175 + return r;
1.176 + }
1.177 +
1.178 +//
1.179 +// Server utils
1.180 +//
1.181 +
1.182 +TBuf<KMaxKernelName> ServerName(TInt aSlaveNumber)
1.183 + {
1.184 + TBuf<KMaxKernelName> name;
1.185 + name.Format(_L("T_MMUSTRESS-Server%d"),aSlaveNumber);
1.186 + return name;
1.187 + }
1.188 +
1.189 +RServer2 Server;
1.190 +RMessage2 ServerMessage;
1.191 +TRequestStatus ServerStatus;
1.192 +
1.193 +class RTestSession : public RSessionBase
1.194 + {
1.195 +public:
1.196 + TInt Connect(TInt aServerNumber)
1.197 + {
1.198 + return CreateSession(ServerName(aServerNumber),TVersion(),1,EIpcSession_Unsharable,0,&iStatus);
1.199 + }
1.200 + TInt Send(TInt aChunkNumber)
1.201 + {
1.202 + return RSessionBase::Send(0,TIpcArgs(SlaveNumber,aChunkNumber,&ChunkPtr[aChunkNumber]));
1.203 + }
1.204 + TRequestStatus iStatus;
1.205 + };
1.206 +RTestSession Sessions[KNumSlaveProcesses];
1.207 +
1.208 +
1.209 +//
1.210 +//
1.211 +//
1.212 +
1.213 +void SlaveInit()
1.214 + {
1.215 + RDebug::Printf("Slave %d initialising",SlaveNumber);
1.216 +
1.217 + TBuf<KMaxKernelName> name;
1.218 + name.Format(_L("T_MMUSTRESS-Slave%d"),SlaveNumber);
1.219 + User::RenameThread(name);
1.220 +
1.221 + test_KErrNone(StartSemaphore.Open(2));
1.222 + TInt r;
1.223 +#if !defined(__WINS__) && !defined(__X86__)
1.224 + // Move ldd may not be in the ROM so needs to be loaded.
1.225 + r=User::LoadLogicalDevice(KMoveLddFileName);
1.226 + test_Value(r, r==KErrNone || r==KErrAlreadyExists);
1.227 + test_KErrNone(MoveLdd.Open());
1.228 +#endif
1.229 +
1.230 + test_KErrNone(Ldd.Open());
1.231 + test_KErrNone(Ldd.CreateVirtualPinObject());
1.232 +
1.233 + LocalIpcBuffer = (TUint8*)User::Alloc(KLocalIpcBufferSize);
1.234 + test(LocalIpcBuffer!=0);
1.235 +
1.236 + test_KErrNone(Server.CreateGlobal(ServerName(SlaveNumber)));
1.237 +
1.238 + TUint i;
1.239 +
1.240 + // create sessions with other slaves...
1.241 + for(i=0; i<KNumSlaveProcesses; i++)
1.242 + {
1.243 + for(;;)
1.244 + {
1.245 + r = Sessions[i].Connect(i);
1.246 +// RDebug::Printf("%d Session %d = %d,%d",SlaveNumber,i,r,Sessions[i].iStatus.Int());
1.247 + if(r==KErrNotFound)
1.248 + {
1.249 + // give other slaves time to create their servers...
1.250 + User::After(10000);
1.251 + continue;
1.252 + }
1.253 + test_KErrNone(r);
1.254 + break;
1.255 + }
1.256 + }
1.257 +
1.258 + // process session connect messages...
1.259 + for(i=0; i<KNumSlaveProcesses; i++)
1.260 + {
1.261 + RMessage2 m;
1.262 +// RDebug::Printf("%d Server waiting for connect message",SlaveNumber);
1.263 + Server.Receive(m);
1.264 + test_Equal(RMessage2::EConnect,m.Function())
1.265 + m.Complete(KErrNone);
1.266 + }
1.267 +
1.268 + // wait for our session connections...
1.269 + for(i=0; i<KNumSlaveProcesses; i++)
1.270 + {
1.271 +// RDebug::Printf("%d Session wait %d",SlaveNumber,i);
1.272 + User::WaitForRequest(Sessions[i].iStatus);
1.273 + }
1.274 +
1.275 + // prime server for receiving mesages...
1.276 + Server.Receive(ServerMessage,ServerStatus);
1.277 +
1.278 + // synchronise with other processes...
1.279 + RDebug::Printf("Slave %d waiting for trigger",SlaveNumber);
1.280 + RProcess::Rendezvous(KErrNone);
1.281 + StartSemaphore.Wait();
1.282 + RDebug::Printf("Slave %d started",SlaveNumber);
1.283 + }
1.284 +
1.285 +
1.286 +
1.287 +//
1.288 +// Test by random operations...
1.289 +//
1.290 +
1.291 +void DoTest()
1.292 + {
1.293 + RandomInit(SlaveNumber);
1.294 + TInt r;
1.295 + for(;;)
1.296 + {
1.297 + // select random chunk...
1.298 + TInt chunkNumber = Random(KNumTestChunks);
1.299 + RChunk& chunk = Chunks[chunkNumber];
1.300 +
1.301 + // get the region of this chunk which this process 'owns'...
1.302 + TInt offset;
1.303 + TInt size;
1.304 + ChunkOwnedRegion(chunkNumber,offset,size);
1.305 +
1.306 + // calculate a random region in the owned part...
1.307 + TInt randomOffset = offset+(Random(size)&~PageMask);
1.308 + TInt randomSize = (Random(size-(randomOffset-offset))+PageMask)&~PageMask;
1.309 + if(!randomSize)
1.310 + continue; // try again
1.311 +
1.312 + // pick a random slave...
1.313 + TInt randomSlave = Random(KNumSlaveProcesses);
1.314 +
1.315 + // open chunk if it isn't already...
1.316 + r = ChunkOpen(chunkNumber);
1.317 + if(r==KErrNoMemory)
1.318 + continue; // can't do anything with chunk if we can't open it
1.319 +
1.320 + // check our contents of chunk...
1.321 + if(Committed[chunkNumber]==1)
1.322 + {
1.323 + if(TRACE) RDebug::Printf("%d %d Check %08x+%08x",SlaveNumber,chunkNumber,offset,size);
1.324 + ChunkCheckRegion(chunkNumber,offset,size);
1.325 + }
1.326 +
1.327 + // perform random operation...
1.328 + switch(Random(12))
1.329 + {
1.330 + case 0:
1.331 + case 1:
1.332 + // close chunk...
1.333 + if(TRACE) RDebug::Printf("%d %d Close",SlaveNumber,chunkNumber);
1.334 + chunk.Close();
1.335 + break;
1.336 +
1.337 + case 2:
1.338 + // commit all...
1.339 + if(TRACE) RDebug::Printf("%d %d Commit all %08x+%08x",SlaveNumber,chunkNumber,offset,size);
1.340 + if(Committed[chunkNumber]!=0)
1.341 + {
1.342 + r = chunk.Decommit(offset,size);
1.343 + test_KErrNone(r);
1.344 + Committed[chunkNumber] = 0;
1.345 + }
1.346 + r = chunk.Commit(offset,size);
1.347 + if(r!=KErrNoMemory)
1.348 + {
1.349 + test_KErrNone(r);
1.350 + Committed[chunkNumber] = 1;
1.351 + ChunkMarkRegion(chunkNumber,offset,size);
1.352 + }
1.353 + break;
1.354 +
1.355 + case 3:
1.356 + // decommit all...
1.357 + if(TRACE) RDebug::Printf("%d %d Decommit all %08x+%08x",SlaveNumber,chunkNumber,offset,size);
1.358 + r = chunk.Decommit(offset,size);
1.359 + test_KErrNone(r);
1.360 + Committed[chunkNumber] = 0;
1.361 + break;
1.362 +
1.363 + case 4:
1.364 + case 5:
1.365 + // commit random...
1.366 + if(TRACE) RDebug::Printf("%d %d Commit %08x+%08x",SlaveNumber,chunkNumber,randomOffset,randomSize);
1.367 + r = chunk.Commit(randomOffset,randomSize);
1.368 + if(r!=KErrNoMemory)
1.369 + {
1.370 + if(Committed[chunkNumber]==0)
1.371 + {
1.372 + test_KErrNone(r);
1.373 + Committed[chunkNumber] = -1;
1.374 + }
1.375 + else if(Committed[chunkNumber]==1)
1.376 + {
1.377 + test_Equal(KErrAlreadyExists,r);
1.378 + }
1.379 + else
1.380 + {
1.381 + if(r!=KErrAlreadyExists)
1.382 + test_KErrNone(r);
1.383 + }
1.384 + }
1.385 + break;
1.386 +
1.387 + case 6:
1.388 + case 7:
1.389 + // decommit random...
1.390 + if(TRACE) RDebug::Printf("%d %d Decommit %08x+%08x",SlaveNumber,chunkNumber,randomOffset,randomSize);
1.391 + r = chunk.Decommit(randomOffset,randomSize);
1.392 + test_KErrNone(r);
1.393 + if(Committed[chunkNumber]==1)
1.394 + Committed[chunkNumber] = -1;
1.395 + break;
1.396 +
1.397 + case 8:
1.398 + if(TRACE) RDebug::Printf("%d %d IPC Send->%d",SlaveNumber,chunkNumber,randomSlave);
1.399 +// ChunkPtr[chunkNumber].Set(chunk.Base(),ChunkSize(chunkNumber),ChunkSize(chunkNumber));
1.400 + ChunkPtr[chunkNumber].Set(chunk.Base()+offset,size,size);
1.401 + Sessions[randomSlave].Send(chunkNumber);
1.402 + break;
1.403 +
1.404 + case 9:
1.405 + // process IPC messages...
1.406 + if(ServerStatus.Int()==KRequestPending)
1.407 + continue;
1.408 + User::WaitForRequest(ServerStatus);
1.409 +
1.410 + {
1.411 + TInt sourceSlave = ServerMessage.Int0();
1.412 + chunkNumber = ServerMessage.Int1();
1.413 + if(TRACE) RDebug::Printf("%d %d IPC Receive<-%d",SlaveNumber,chunkNumber,sourceSlave);
1.414 + test_Equal(0,ServerMessage.Function());
1.415 +
1.416 + // get local descriptor for owned region in chunk...
1.417 + size = ServerMessage.GetDesMaxLength(2);
1.418 + test_NotNegative(size);
1.419 + if(size>KLocalIpcBufferSize)
1.420 + size = KLocalIpcBufferSize;
1.421 + TPtr8 local(LocalIpcBuffer,size,size);
1.422 +
1.423 +// if(Random(2))
1.424 + {
1.425 + // IPC read from other slave...
1.426 + if(TRACE) RDebug::Printf("%d %d IPC Read<-%d",SlaveNumber,chunkNumber,sourceSlave);
1.427 + TInt panicTrace = Ldd.SetPanicTrace(EFalse);
1.428 + r = ServerMessage.Read(2,local);
1.429 + Ldd.SetPanicTrace(panicTrace);
1.430 + if(r!=KErrBadDescriptor)
1.431 + test_KErrNone(r);
1.432 + }
1.433 +// else
1.434 +// {
1.435 +// // IPC write to other slave...
1.436 +// if(TRACE) RDebug::Printf("%d %d IPC Write->%d",SlaveNumber,chunkNumber,sourceSlave);
1.437 +// r = ServerMessage.Write(2,local,offset);
1.438 +// if(r!=KErrBadDescriptor)
1.439 +// test_KErrNone(r);
1.440 +// if(Committed[chunkNumber]==1)
1.441 +// ChunkMarkRegion(chunkNumber,offset,size);
1.442 +// }
1.443 + }
1.444 +
1.445 + ServerMessage.Complete(KErrNone);
1.446 + Server.Receive(ServerMessage,ServerStatus);
1.447 + break;
1.448 +
1.449 + case 10:
1.450 + case 11:
1.451 + // pin memory...
1.452 + {
1.453 + test_KErrNone(Ldd.UnpinVirtualMemory());
1.454 + for(TInt tries=10; tries>0; --tries)
1.455 + {
1.456 + TInt chunkSize = ChunkSize(chunkNumber);
1.457 + offset = Random(chunkSize);
1.458 + TInt maxSize = chunkSize-offset;
1.459 + if(maxSize>0x1000)
1.460 + maxSize = 0x1000;
1.461 + size = Random(maxSize);
1.462 + r = Ldd.PinVirtualMemory((TLinAddr)chunk.Base()+offset, size);
1.463 + if(r!=KErrNotFound && r!=KErrNoMemory)
1.464 + {
1.465 + test_KErrNone(r);
1.466 + break;
1.467 + }
1.468 + }
1.469 + }
1.470 + break;
1.471 + case 12:
1.472 + case 13:
1.473 + // Move any page in the chunk, not just the owned region.
1.474 + {
1.475 +#if !defined(__WINS__) && !defined(__X86__)
1.476 + for(TInt tries=10; tries>0; --tries)
1.477 + {
1.478 + TInt chunkSize = ChunkSize(chunkNumber);
1.479 + offset = Random(chunkSize);
1.480 + MoveLdd.TryMovingUserPage((TAny*)(chunk.Base()+offset), ETrue);
1.481 + // Allow the move to fail for any reason as the page of the chunk
1.482 + // may or may not be currently committed, pinned, or accessed.
1.483 + }
1.484 +#endif
1.485 + }
1.486 + break;
1.487 + default:
1.488 + test(false); // can't happen
1.489 + break;
1.490 + }
1.491 + }
1.492 + }
1.493 +
1.494 +
1.495 +
1.496 +TInt E32Main()
1.497 + {
1.498 + // get system info...
1.499 + MemModelAttributes = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
1.500 + MemModel = MemModelAttributes&EMemModelTypeMask;
1.501 + UserHal::PageSizeInBytes(PageSize);
1.502 + PageMask = PageSize-1;
1.503 +
1.504 + // see if we are a slave process...
1.505 + if(User::GetTIntParameter(1,SlaveNumber)==KErrNone)
1.506 + {
1.507 + // do testing...
1.508 + SlaveInit();
1.509 + DoTest();
1.510 + return KErrGeneral; // shouldn't have returned from testing
1.511 + }
1.512 +
1.513 + // master process...
1.514 + TBool pass = true; // final test result
1.515 + test.Title();
1.516 + if((MemModelAttributes&EMemModelAttrVA)==false)
1.517 + {
1.518 + test.Start(_L("TESTS NOT RUN - Not relevent for the memory model"));
1.519 + test.End();
1.520 + return KErrNone;
1.521 + }
1.522 +
1.523 + // get time to run tests for...
1.524 + TInt timeout = 10; // time in seconds
1.525 + TInt cmdLineLen = User::CommandLineLength();
1.526 + if(cmdLineLen)
1.527 + {
1.528 + // get timeout value from command line
1.529 + RBuf cmdLine;
1.530 + test_KErrNone(cmdLine.Create(cmdLineLen));
1.531 + User::CommandLine(cmdLine);
1.532 + test_KErrNone(TLex(cmdLine).Val(timeout));
1.533 + if(timeout==0)
1.534 + timeout = KMaxTInt;
1.535 + }
1.536 + TTimeIntervalMicroSeconds32 tickTime;
1.537 + test_KErrNone(UserHal::TickPeriod(tickTime));
1.538 + TInt ticksPerSecond = 1000000/tickTime.Int();
1.539 + TInt timeoutTicks;
1.540 + if(timeout<KMaxTInt/ticksPerSecond)
1.541 + timeoutTicks = timeout*ticksPerSecond;
1.542 + else
1.543 + {
1.544 + timeoutTicks = KMaxTInt;
1.545 + timeout = timeoutTicks/ticksPerSecond;
1.546 + }
1.547 +
1.548 + // master process runs at higher priority than slaves so it can timeout and kill them...
1.549 + RThread().SetPriority(EPriorityMore);
1.550 +
1.551 + test.Start(_L("Creating test chunks"));
1.552 + TUint i;
1.553 + for(i=0; i<KNumTestChunks; i++)
1.554 + {
1.555 + test.Printf(_L("Size %dkB\r\n"),ChunkSize(i)>>10);
1.556 + test_KErrNone(Chunks[i].CreateDisconnectedGlobal(ChunkName(i),0,0,ChunkSize(i)));
1.557 + }
1.558 +
1.559 + test.Next(_L("Spawning slave processes"));
1.560 + test_KErrNone(StartSemaphore.CreateGlobal(KNullDesC,0));
1.561 + TFileName processFile(RProcess().FileName());
1.562 + for(i=0; i<KNumSlaveProcesses; i++)
1.563 + {
1.564 + test.Printf(_L("Slave %d\r\n"),i);
1.565 + RProcess& slave = Slaves[i];
1.566 + test_KErrNone(slave.Create(processFile,KNullDesC));
1.567 + test_KErrNone(slave.SetParameter(1,i));
1.568 + test_KErrNone(slave.SetParameter(2,StartSemaphore));
1.569 + slave.Logon(SlaveLogons[i]);
1.570 + test_Equal(KRequestPending,SlaveLogons[i].Int());
1.571 + slave.Rendezvous(SlaveRendezvous[i]);
1.572 + test_Equal(KRequestPending,SlaveRendezvous[i].Int());
1.573 + }
1.574 +
1.575 + test.Next(_L("Create timer"));
1.576 + RTimer timer;
1.577 + test_KErrNone(timer.CreateLocal());
1.578 +
1.579 + test.Next(_L("Resuming slave processes"));
1.580 + for(i=0; i<KNumSlaveProcesses; i++)
1.581 + Slaves[i].Resume();
1.582 +
1.583 + // this test must now take care not to die (e.g. panic due to assert fail)
1.584 + // until it has killed the slave processes
1.585 +
1.586 + test.Next(_L("Change paging cache size"));
1.587 + TUint cacheOriginalMin = 0;
1.588 + TUint cacheOriginalMax = 0;
1.589 + TUint cacheCurrentSize = 0;
1.590 + DPTest::CacheSize(cacheOriginalMin, cacheOriginalMax, cacheCurrentSize);
1.591 + DPTest::SetCacheSize(1, 2*ChunkSize(0)); // big enough for all the test chunks
1.592 +
1.593 + test.Next(_L("Wait for slaves to initialise"));
1.594 + TRequestStatus timeoutStatus;
1.595 + timer.After(timeoutStatus,10*1000000); // allow short time for slaves to initialise
1.596 + for(i=0; i<KNumSlaveProcesses; i++)
1.597 + {
1.598 + User::WaitForAnyRequest(); // wait for a rendexvous
1.599 + if(timeoutStatus.Int()!=KRequestPending)
1.600 + {
1.601 + test.Printf(_L("Timeout waiting for slaves to initialise\r\n"));
1.602 + pass = false;
1.603 + break;
1.604 + }
1.605 + }
1.606 +
1.607 + test.Next(_L("Restore paging cache size"));
1.608 + DPTest::SetCacheSize(cacheOriginalMin, cacheOriginalMax);
1.609 +
1.610 + if(pass)
1.611 + {
1.612 + timer.Cancel();
1.613 + User::WaitForAnyRequest(); // swallow timer signal
1.614 +
1.615 + test.Next(_L("Check slaves are ready"));
1.616 + for(i=0; i<KNumSlaveProcesses; i++)
1.617 + {
1.618 + if(SlaveRendezvous[i].Int()!=KErrNone || Slaves[i].ExitType()!=EExitPending)
1.619 + {
1.620 + test.Printf(_L("Slaves not ready or died!\r\n"));
1.621 + pass = false;
1.622 + break;
1.623 + }
1.624 + }
1.625 + }
1.626 +
1.627 + if(pass)
1.628 + {
1.629 + test.Next(_L("Setup simulated kernel heap failure"));
1.630 + __KHEAP_SETFAIL(RAllocator::EDeterministic,100);
1.631 +
1.632 + TBuf<80> text;
1.633 + text.Format(_L("Stressing for %d seconds..."),timeout);
1.634 + test.Next(text);
1.635 + timer.AfterTicks(timeoutStatus,timeoutTicks);
1.636 + StartSemaphore.Signal(KNumSlaveProcesses); // release slaves to start testing
1.637 + User::WaitForAnyRequest(); // wait for timeout or slave death via logon completion
1.638 +
1.639 + pass = timeoutStatus.Int()==KErrNone; // timeout means slaves are still running OK
1.640 +
1.641 + test.Next(_L("Check slaves still running"));
1.642 + for(i=0; i<KNumSlaveProcesses; i++)
1.643 + if(Slaves[i].ExitType()!=EExitPending)
1.644 + pass = false;
1.645 +
1.646 + test.Next(_L("Clear kernel heap failure"));
1.647 + TUint kheapFails = __KHEAP_CHECKFAILURE;
1.648 + __KHEAP_RESET;
1.649 + test.Printf(_L("Number of simulated memory failures = %d\r\n"),kheapFails);
1.650 + }
1.651 +
1.652 + test.Next(_L("Killing slave processes"));
1.653 + for(i=0; i<KNumSlaveProcesses; i++)
1.654 + Slaves[i].Kill(0);
1.655 +
1.656 + test.Next(_L("Assert test passed"));
1.657 + test(pass);
1.658 +
1.659 + test.End();
1.660 +
1.661 + for(i=0; i<KNumSlaveProcesses; i++)
1.662 + Slaves[i].Close();
1.663 + for(i=0; i<KNumTestChunks; i++)
1.664 + Chunks[i].Close();
1.665 + timer.Close();
1.666 + for(i=0; i<KNumSlaveProcesses; i++)
1.667 + User::WaitForRequest(SlaveLogons[i]);
1.668 +
1.669 + UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, (TAny*)5000, 0);
1.670 +
1.671 + return KErrNone;
1.672 + }