1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/mmu/t_sharedchunk.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1435 @@
1.4 +// Copyright (c) 2004-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_sharedchunk.cpp
1.18 +// Overview:
1.19 +// Test sharing an RChunk with a logical device
1.20 +// API Information:
1.21 +// RChunk
1.22 +// Details:
1.23 +// - Load and open the logical device driver ("D_SHAREDCHUNK"). Verify
1.24 +// results.
1.25 +// - Test and verify results of creating shared chunks under OOM conditions. Also verify
1.26 +// creating a chunk with a bad type, bad size and too large all fail as
1.27 +// expected.
1.28 +// - Test and verify opening and closing chunk user handles work as expected.
1.29 +// - Test and verify thread local and process local handles work as expected
1.30 +// - Test and verify setting restrictions on RChunk if created as shared chunk are as expected.
1.31 +// - Test and verify memory access for multiply and singly shared chunks,
1.32 +// is as expected. Including IPC, kernel, DFC and ISR reads & writes.
1.33 +// - Test and verify discontinuous memory commits for multiply and singly
1.34 +// shared chunks are as expected.
1.35 +// - Test and verify continuous memory commits for multiply and singly shared
1.36 +// chunks are as expected.
1.37 +// - Test and verify discontinuous and continuous physical memory commits for
1.38 +// multiply and singly shared chunks is as expected.
1.39 +// - Test Kern::OpenSharedChunk for multiply and singly shared chunks. Verify
1.40 +// results are as expected.
1.41 +// - Test that physical memory can be freed immediately after the chunk that mapped
1.42 +// it has been closed.
1.43 +// Platforms/Drives/Compatibility:
1.44 +// All.
1.45 +// Assumptions/Requirement/Pre-requisites:
1.46 +// Failures and causes:
1.47 +// Base Port information:
1.48 +//
1.49 +//
1.50 +
1.51 +//! @file
1.52 +//! @SYMTestCaseID KBASE-T_SHAREDCHUNK
1.53 +//! @SYMREQ 3699
1.54 +//! @SYMTestPriority High
1.55 +//! @SYMTestActions Check creation, memory allocation and access to Shared Chunks
1.56 +//! @SYMTestExpectedResults Test runs until this message is emitted: RTEST: SUCCESS : T_SHAREDCHUNK test completed O.K.
1.57 +//! @SYMTestType UT
1.58 +#define __E32TEST_EXTENSION__
1.59 +
1.60 +#include "d_sharedchunk.h"
1.61 +#include "d_gobble.h"
1.62 +#include <e32test.h>
1.63 +#include <e32hal.h>
1.64 +#include "u32std.h"
1.65 +#include <u32hal.h>
1.66 +#include <e32svr.h>
1.67 +#include <f32dbg.h>
1.68 +#include <e32def.h>
1.69 +#include <e32def_private.h>
1.70 +#include "freeram.h"
1.71 +
1.72 +enum TSlaveCommand
1.73 + {
1.74 + ESlaveCheckChunk,
1.75 + ESlaveCreateChunk,
1.76 + };
1.77 +
1.78 +//
1.79 +// Global data
1.80 +//
1.81 +
1.82 +
1.83 +RSharedChunkLdd Ldd;
1.84 +RChunk TheChunk;
1.85 +TInt PageSize;
1.86 +TUint32 MemModelAttributes;
1.87 +TBool PhysicalCommitSupported;
1.88 +TBool CachingAttributesSupported;
1.89 +TUint8 BssMem[100];
1.90 +
1.91 +const TUint ChunkSize = 0x400000; // 4 meg reserved space for test chunk
1.92 +
1.93 +_LIT(KSecondProcessName,"t_sharedchunk");
1.94 +#ifdef __T_SHAREDCHUNKF__
1.95 +_LIT(KOtherProcessName,"t_sharedchunk");
1.96 +LOCAL_D RTest test(_L("T_SHAREDCHUNKF"));
1.97 +#else
1.98 +_LIT(KOtherProcessName,"t_sharedchunkf");
1.99 +LOCAL_D RTest test(_L("T_SHAREDCHUNK"));
1.100 +#endif
1.101 +
1.102 +_LIT8(KTestString, "lks4b7qeyfcea5fyaifyaefyi4flwdysuxanabxa");
1.103 +_LIT8(KTestString2,"jhfcalurnhfirlxszhrvcvduhrvndrucxnshxcsx");
1.104 +const TUint32 KTestValue = 0x12345678;
1.105 +const TUint32 KTestValue2 = KTestValue^0x0f0f0f0f;
1.106 +
1.107 +//
1.108 +// Utilitiies for use by tests
1.109 +//
1.110 +
1.111 +
1.112 +_LIT(KLitKernExec, "KERN-EXEC");
1.113 +
1.114 +void CheckFailMessage(const char* n,const char* c,const char* f,TInt r)
1.115 + {
1.116 + TPtrC8 nn((const TUint8*)n);
1.117 + TPtrC8 cc((const TUint8*)c);
1.118 + TPtrC8 ff((const TUint8*)f);
1.119 + RBuf8 buf;
1.120 + buf.Create((nn.Size()+cc.Size()+ff.Size()+64)*2);
1.121 + buf.AppendFormat(_L8("\nCHECK failed: %S == 0x%x but was tested for %S%S\n"),&ff,r,&cc,&nn);
1.122 + test.Printf(buf.Expand());
1.123 + buf.Close();
1.124 + }
1.125 +
1.126 +#define CHECK(n,c,f) \
1.127 + { \
1.128 + TInt _r=(TInt)(f); \
1.129 + if(!((TInt)(n)c(_r))) \
1.130 + { \
1.131 + CheckFailMessage(#n,#c,#f,_r); \
1.132 + test(0); \
1.133 + } \
1.134 + }
1.135 +
1.136 +#define KCHECK_MEMORY(result,offset) \
1.137 + { \
1.138 + /* test.Printf(_L("check offset 0x%08x\r"),offset); */ \
1.139 + CHECK(result,==,Ldd.CheckMemory(offset)); \
1.140 + }
1.141 +
1.142 +#define KWRITE_MEMORY(offset,value) \
1.143 + { \
1.144 + CHECK(KErrNone,==,Ldd.WriteMemory(offset,value)); \
1.145 + }
1.146 +
1.147 +#define UREAD_MEMORY(offset,value) \
1.148 + { \
1.149 + CHECK(value,==,*(TUint*)(Base+offset)); \
1.150 + }
1.151 +
1.152 +inline TUint32 Tag(TUint32 offset)
1.153 + { return (69069u*(offset*4+1)); }
1.154 +
1.155 +TInt MemoryAccessThread(TAny* aAddress)
1.156 + {
1.157 + TInt r = *(volatile TUint8*)aAddress; // read from aAddress
1.158 + (void)r;
1.159 + return 0;
1.160 + }
1.161 +
1.162 +TInt CheckUMemory(TAny* aAddress)
1.163 + {
1.164 + RThread thread;
1.165 + thread.Create(KNullDesC,MemoryAccessThread,PageSize,&User::Heap(),aAddress);
1.166 + TRequestStatus status;
1.167 + thread.Logon(status);
1.168 + TBool jit = User::JustInTime();
1.169 + User::SetJustInTime(EFalse);
1.170 + thread.Resume();
1.171 + User::WaitForRequest(status);
1.172 + User::SetJustInTime(jit);
1.173 + TInt r;
1.174 + if(thread.ExitType()==EExitKill && thread.ExitReason()==0)
1.175 + r = 1; // Memory access pass
1.176 + else if(thread.ExitType()==EExitPanic && thread.ExitCategory()==KLitKernExec && thread.ExitReason()==3 )
1.177 + r = 0; // Memory access failed
1.178 + else
1.179 + r = -1; // Unexpected result
1.180 + CLOSE_AND_WAIT(thread);
1.181 + return r;
1.182 + }
1.183 +
1.184 +#define UCHECK_MEMORY(result,offset) \
1.185 + { \
1.186 + /* test.Printf(_L("ucheck offset 0x%08x\r"),offset); */ \
1.187 + CHECK(result,==,CheckUMemory(Base+offset)); \
1.188 + }
1.189 +
1.190 +TInt CheckPlatSecPanic(TThreadFunction aThreadFunction,TInt aThreadArgument)
1.191 + {
1.192 + RThread thread;
1.193 + thread.Create(KNullDesC,aThreadFunction,PageSize,&User::Heap(),(TAny*)aThreadArgument);
1.194 + TRequestStatus status;
1.195 + thread.Logon(status);
1.196 + TBool jit = User::JustInTime();
1.197 + User::SetJustInTime(EFalse);
1.198 + thread.Resume();
1.199 + User::WaitForRequest(status);
1.200 + User::SetJustInTime(jit);
1.201 + TInt r;
1.202 + if(thread.ExitType()==EExitPanic && thread.ExitCategory()==KLitKernExec && thread.ExitReason()==46 )
1.203 + r = 1; // PlatSec panic
1.204 + else if(thread.ExitType()==EExitKill && thread.ExitReason()==0)
1.205 + r = 0; // Exit without error
1.206 + else
1.207 + r = -1; // Unexpected result
1.208 + CLOSE_AND_WAIT(thread);
1.209 + return r;
1.210 + }
1.211 +
1.212 +//
1.213 +// The tests
1.214 +//
1.215 +
1.216 +void CreateWithOomCheck(TInt aCreateFlags)
1.217 + {
1.218 + TInt failResult=KErrGeneral;
1.219 + for(TInt failCount=1; failCount<1000; failCount++)
1.220 + {
1.221 + test.Printf(_L("alloc fail count = %d\n"),failCount);
1.222 + User::__DbgSetBurstAllocFail(ETrue,RAllocator::EFailNext,failCount,1000);
1.223 + __KHEAP_MARK;
1.224 + failResult = Ldd.CreateChunk(aCreateFlags);
1.225 + if(failResult==KErrNone)
1.226 + break;
1.227 + CHECK(KErrNoMemory,==,failResult);
1.228 + Ldd.IsDestroyed(); // This includes delay to let idle thread do cleanup
1.229 + __KHEAP_MARKEND;
1.230 + }
1.231 + User::__DbgSetAllocFail(ETrue,RAllocator::ENone,0);
1.232 + __KHEAP_RESET;
1.233 + CHECK(KErrNone,==,failResult);
1.234 + }
1.235 +
1.236 +void TestCreate()
1.237 + {
1.238 + test.Start(_L("Creating chunk type Single,OwnsMemory"));
1.239 + CreateWithOomCheck(ChunkSize|ESingle|EOwnsMemory);
1.240 + CHECK(0,==,Ldd.IsDestroyed());
1.241 +
1.242 + test.Next(_L("Close kernel handle"));
1.243 + CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
1.244 + CHECK(1,==,Ldd.IsDestroyed());
1.245 +
1.246 + test.Next(_L("Creating chunk type Multiple,OwnsMemory"));
1.247 + CreateWithOomCheck(ChunkSize|EMultiple|EOwnsMemory);
1.248 + CHECK(0,==,Ldd.IsDestroyed());
1.249 +
1.250 + test.Next(_L("Close kernel handle"));
1.251 + CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
1.252 + CHECK(1,==,Ldd.IsDestroyed());
1.253 +
1.254 + if(PhysicalCommitSupported)
1.255 + {
1.256 + test.Next(_L("Creating chunk type Single,!OwnsMemory"));
1.257 + CreateWithOomCheck(ChunkSize|ESingle);
1.258 + CHECK(0,==,Ldd.IsDestroyed());
1.259 +
1.260 + test.Next(_L("Close kernel handle"));
1.261 + CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
1.262 + CHECK(1,==,Ldd.IsDestroyed());
1.263 +
1.264 + test.Next(_L("Creating chunk type Multiple,!OwnsMemory"));
1.265 + CreateWithOomCheck(ChunkSize|EMultiple);
1.266 + CHECK(0,==,Ldd.IsDestroyed());
1.267 +
1.268 + test.Next(_L("Close kernel handle"));
1.269 + CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
1.270 + CHECK(1,==,Ldd.IsDestroyed());
1.271 + }
1.272 + else
1.273 + {
1.274 + test.Next(_L("Try creating unsupported chunk type Single,!OwnsMemory"));
1.275 + CHECK(KErrNotSupported,==,Ldd.CreateChunk(ChunkSize|ESingle));
1.276 +
1.277 + test.Next(_L("Try creating unsupported chunk type Multiple,!OwnsMemory"));
1.278 + CHECK(KErrNotSupported,==,Ldd.CreateChunk(ChunkSize|EMultiple));
1.279 + }
1.280 +
1.281 + test.Next(_L("__KHEAP_MARK"));
1.282 + __KHEAP_MARK;
1.283 +
1.284 + test.Next(_L("Creating chunk (bad type)"));
1.285 + CHECK(KErrArgument,==,Ldd.CreateChunk(EBadType|EOwnsMemory|ChunkSize));
1.286 +
1.287 + test.Next(_L("Creating chunk (bad size)"));
1.288 + CHECK(KErrArgument,==,Ldd.CreateChunk(ESingle|EOwnsMemory|0xffffff00));
1.289 +
1.290 + test.Next(_L("Creating chunk (size too big)"));
1.291 + CHECK(KErrNoMemory,==,Ldd.CreateChunk(ESingle|EOwnsMemory|0x7fffff00));
1.292 +
1.293 + test.Next(_L("__KHEAP_MARKEND"));
1.294 + __KHEAP_MARKEND;
1.295 +
1.296 + test.End();
1.297 + }
1.298 +
1.299 +
1.300 +void OpenWithOomCheck(RChunk& aChunk)
1.301 + {
1.302 + TInt failResult=KErrGeneral;
1.303 + for(TInt failCount=1; failCount<1000; failCount++)
1.304 + {
1.305 + test.Printf(_L("alloc fail count = %d\n"),failCount);
1.306 + User::__DbgSetBurstAllocFail(ETrue,RAllocator::EFailNext,failCount,1000);
1.307 + __KHEAP_MARK;
1.308 + failResult = Ldd.GetChunkHandle(aChunk);
1.309 + if(failResult==KErrNone)
1.310 + break;
1.311 + CHECK(KErrNoMemory,==,failResult);
1.312 + Ldd.IsDestroyed(); // This includes delay to let idle thread do cleanup
1.313 + __KHEAP_MARKEND;
1.314 + }
1.315 + User::__DbgSetAllocFail(ETrue,RAllocator::ENone,0);
1.316 + __KHEAP_RESET;
1.317 + CHECK(KErrNone,==,failResult);
1.318 + }
1.319 +
1.320 +void TestHandles()
1.321 + {
1.322 + TUint ChunkAttribs = ChunkSize|ESingle|EOwnsMemory;
1.323 +
1.324 + test.Start(_L("Create chunk"));
1.325 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.326 +
1.327 + test.Next(_L("Open user handle"));
1.328 + OpenWithOomCheck(TheChunk);
1.329 +
1.330 + test.Next(_L("Close user handle"));
1.331 + TheChunk.Close();
1.332 +
1.333 + test.Next(_L("Check chunk not destroyed"));
1.334 + CHECK(0,==,Ldd.IsDestroyed());
1.335 +
1.336 + test.Next(_L("Close kernel handle"));
1.337 + CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
1.338 +
1.339 + test.Next(_L("Check chunk destroyed"));
1.340 + CHECK(1,==,Ldd.IsDestroyed());
1.341 +
1.342 + // Another chunk - closing handles in reverse order
1.343 +
1.344 + test.Next(_L("Create chunk"));
1.345 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.346 +
1.347 + test.Next(_L("Open user handle"));
1.348 + OpenWithOomCheck(TheChunk);
1.349 +
1.350 + test.Next(_L("Close kernel handle"));
1.351 + CHECK(KErrNone,==,Ldd.CloseChunk());
1.352 +
1.353 + test.Next(_L("Check chunk not destroyed"));
1.354 + CHECK(0,==,Ldd.IsDestroyed());
1.355 +
1.356 + test.Next(_L("Using user handle to check chunk info"));
1.357 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.358 + {
1.359 + CHECK(0,==,TheChunk.Size());
1.360 + }
1.361 + CHECK(ChunkSize,==,TheChunk.MaxSize());
1.362 +
1.363 + test.Next(_L("Close user handle"));
1.364 + TheChunk.Close();
1.365 +
1.366 + test.Next(_L("Check chunk destroyed"));
1.367 + CHECK(1,==,Ldd.IsDestroyed());
1.368 +
1.369 + test.End();
1.370 + }
1.371 +
1.372 +TInt HandleOwnershipThread(TAny* aArg)
1.373 + {
1.374 + // Use existing handle and attempt to read from chunk
1.375 + TInt handle = (TInt) aArg;
1.376 + RChunk chunk;
1.377 + chunk.SetHandle(handle);
1.378 + TInt r = *(volatile TUint8*)chunk.Base();
1.379 + (void)r;
1.380 + CLOSE_AND_WAIT(chunk);
1.381 + return KErrNone;
1.382 + }
1.383 +
1.384 +void TestHandleOwnership()
1.385 + {
1.386 + TUint ChunkAttribs = ChunkSize|ESingle|EOwnsMemory;
1.387 + RThread thread;
1.388 + TRequestStatus rs;
1.389 +
1.390 + test.Start(_L("Create chunk"));
1.391 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.392 +
1.393 + test.Next(_L("Commit page to chunk"));
1.394 + CHECK(KErrNone,==,Ldd.CommitMemory(EDiscontiguous,PageSize));
1.395 +
1.396 + test.Next(_L("Check can access memory kernel side"));
1.397 + KCHECK_MEMORY(ETrue, 0);
1.398 +
1.399 + // Handle is thread-owned
1.400 + test.Next(_L("Open user handle (thread-owned)"));
1.401 + CHECK(0,<=,Ldd.GetChunkHandle(TheChunk, ETrue));
1.402 +
1.403 + test.Next(_L("Get memory size info"));
1.404 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.405 + {
1.406 + CHECK(PageSize,==,TheChunk.Size());
1.407 + }
1.408 + CHECK(ChunkSize,==,TheChunk.MaxSize());
1.409 + TUint8* Base = TheChunk.Base();
1.410 + CHECK(Base,!=,0);
1.411 +
1.412 + test.Next(_L("Check can access memory user side"));
1.413 + UCHECK_MEMORY(ETrue, 0);
1.414 +
1.415 + test.Next(_L("Use handle in a new thread"));
1.416 + CHECK(KErrNone,==,thread.Create(_L("thread1"), HandleOwnershipThread, KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*)TheChunk.Handle()));
1.417 + thread.Logon(rs);
1.418 + thread.Resume();
1.419 + User::WaitForRequest(rs);
1.420 + CHECK(EExitPanic,==,thread.ExitType());
1.421 + CHECK(0,==,thread.ExitReason()); // KERN-EXEC 0
1.422 + CLOSE_AND_WAIT(thread);
1.423 +
1.424 + test.Next(_L("Close user handle"));
1.425 + TheChunk.Close();
1.426 +
1.427 + // Handle is process-owned
1.428 + test.Next(_L("Open user handle (process-owned"));
1.429 + CHECK(0,<=,Ldd.GetChunkHandle(TheChunk, EFalse));
1.430 +
1.431 + test.Next(_L("Check can access memory user side"));
1.432 + UCHECK_MEMORY(ETrue, 0);
1.433 +
1.434 + test.Next(_L("Close kernel handle"));
1.435 + CHECK(KErrNone,==,Ldd.CloseChunk());
1.436 +
1.437 + test.Next(_L("Check chunk destroyed"));
1.438 + CHECK(0,==,Ldd.IsDestroyed());
1.439 +
1.440 + test.Next(_L("Use handle in a new thread"));
1.441 + CHECK(KErrNone,==,thread.Create(_L("thread2"), HandleOwnershipThread, KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*)TheChunk.Handle()));
1.442 + thread.Logon(rs);
1.443 + thread.Resume();
1.444 + User::WaitForRequest(rs);
1.445 + CHECK(EExitKill,==,thread.ExitType());
1.446 + CHECK(KErrNone,==,thread.ExitReason());
1.447 + CLOSE_AND_WAIT(thread);
1.448 +
1.449 + test.Next(_L("Check chunk destroyed"));
1.450 + CHECK(1,==,Ldd.IsDestroyed()); // Object was deleted
1.451 +
1.452 + test.End();
1.453 + }
1.454 +
1.455 +void SetCreateFlags(TUint& aCreateFlags,TCommitType aCommitType)
1.456 + {
1.457 + if(!((TInt)aCommitType&EPhysicalMask))
1.458 + aCreateFlags |= EOwnsMemory;
1.459 + else
1.460 + aCreateFlags &= ~EOwnsMemory;
1.461 + }
1.462 +
1.463 +
1.464 +void TestAccess(TUint aCreateFlags,TCommitType aCommitType)
1.465 + {
1.466 + const TUint32 offset = 0;
1.467 + const TUint32 size = PageSize;
1.468 +
1.469 + SetCreateFlags(aCreateFlags,aCommitType);
1.470 +
1.471 + test.Start(_L("Create chunk"));
1.472 + TUint8* kernelAddress;
1.473 + CHECK(KErrNone,==,Ldd.CreateChunk(aCreateFlags|ChunkSize,(TAny**)&kernelAddress));
1.474 +
1.475 + if((MemModelAttributes&TUint32(EMemModelAttrNonExProt)) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.476 + {
1.477 + test.Next(_L("Check can't access memory"));
1.478 + KCHECK_MEMORY(EFalse,offset);
1.479 + }
1.480 +
1.481 + test.Next(_L("Commit page to chunk"));
1.482 + CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|offset,size));
1.483 +
1.484 + test.Next(_L("Check can access memory kernel side"));
1.485 + KCHECK_MEMORY(ETrue, offset);
1.486 +
1.487 + if((MemModelAttributes&EMemModelAttrKernProt) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.488 + {
1.489 + test.Next(_L("Check user side can't access kernel memory"));
1.490 + TUint8* Base = kernelAddress;
1.491 + UCHECK_MEMORY(EFalse, offset);
1.492 + }
1.493 +
1.494 + test.Next(_L("Open user handle"));
1.495 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.496 +
1.497 + test.Next(_L("Get memory size info"));
1.498 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.499 + {
1.500 + CHECK(PageSize,==,TheChunk.Size());
1.501 + }
1.502 + CHECK(ChunkSize,==,TheChunk.MaxSize());
1.503 + TUint8* Base = TheChunk.Base();
1.504 + CHECK(Base,!=,0);
1.505 +
1.506 + test.Next(_L("Check can access memory user side"));
1.507 + UCHECK_MEMORY(ETrue, offset);
1.508 +
1.509 + test.Next(_L("Check user and kernel access same memory"));
1.510 + KWRITE_MEMORY(offset,~Tag(offset));
1.511 + UREAD_MEMORY(offset,~Tag(offset));
1.512 + KWRITE_MEMORY(offset,Tag(offset));
1.513 + UREAD_MEMORY(offset,Tag(offset));
1.514 +
1.515 + test.Next(_L("Close user handle"));
1.516 + CHECK(0,==,Ldd.CloseChunkHandle(TheChunk));
1.517 + CHECK(0,==,Ldd.IsDestroyed());
1.518 +
1.519 + if((MemModelAttributes&EMemModelAttrKernProt) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.520 + {
1.521 + test.Next(_L("Check can no-longer access memory user side"));
1.522 + UCHECK_MEMORY(EFalse,offset);
1.523 + }
1.524 +
1.525 + test.Next(_L("Check can still access memory kernel side"));
1.526 + KCHECK_MEMORY(ETrue, offset);
1.527 +
1.528 + test.Next(_L("Open user handle again"));
1.529 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.530 +
1.531 + test.Next(_L("Check can access chunk user side again"));
1.532 + CHECK(Base,==,TheChunk.Base());
1.533 + CHECK(ChunkSize,==,TheChunk.MaxSize());
1.534 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.535 + {
1.536 + CHECK(size,==,TheChunk.Size());
1.537 + }
1.538 + UREAD_MEMORY(offset,Tag(offset));
1.539 +
1.540 + test.Next(_L("Close kernel handle"));
1.541 + CHECK(0,==,Ldd.CloseChunk());
1.542 + CHECK(0,==,Ldd.IsDestroyed());
1.543 +
1.544 + test.Next(_L("Check can still access chunk user side"));
1.545 + CHECK(Base,==,TheChunk.Base());
1.546 + CHECK(ChunkSize,==,TheChunk.MaxSize());
1.547 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.548 + {
1.549 + CHECK(size,==,TheChunk.Size());
1.550 + }
1.551 + UREAD_MEMORY(offset,Tag(offset));
1.552 +
1.553 + test.Next(_L("Close user handle"));
1.554 + TheChunk.Close();
1.555 + CHECK(1,==,Ldd.IsDestroyed());
1.556 +
1.557 + test.Next(_L("Create chunk in another process"));
1.558 +
1.559 + // Create test server
1.560 + RServer2 server;
1.561 + RMessage2 message;
1.562 + TRequestStatus status;
1.563 + CHECK(KErrNone,==,server.CreateGlobal(KSecondProcessName));
1.564 + server.Receive(message,status);
1.565 +
1.566 + // Launch slave process
1.567 + RProcess process;
1.568 + CHECK(KErrNone,==,process.Create(KSecondProcessName,KNullDesC));
1.569 + CHECK(KErrNone,==,process.SetParameter(1,ESlaveCreateChunk));
1.570 + CHECK(KErrNone,==,process.SetParameter(2,(RBusLogicalChannel&)Ldd));
1.571 + CHECK(KErrNone,==,process.SetParameter(3,ChunkSize|aCreateFlags));
1.572 + CHECK(KErrNone,==,process.SetParameter(4,aCommitType));
1.573 + CHECK(KErrNone,==,process.SetParameter(5,PageSize));
1.574 + TRequestStatus logon;
1.575 + process.Logon(logon);
1.576 + process.Resume();
1.577 +
1.578 + // Wait for slave to connect to test server
1.579 + User::WaitForRequest(logon,status);
1.580 + CHECK(KRequestPending,==,logon.Int())
1.581 + CHECK(KErrNone,==,status.Int());
1.582 + CHECK(RMessage2::EConnect,==,message.Function());
1.583 + message.Complete(KErrNone);
1.584 + server.Receive(message,status);
1.585 +
1.586 + // Wait for message
1.587 + User::WaitForRequest(logon,status);
1.588 + CHECK(KRequestPending,==,logon.Int())
1.589 + CHECK(KErrNone,==,status.Int());
1.590 + CHECK(0,==,message.Function());
1.591 +
1.592 + test.Next(_L("Check IPC read/write"));
1.593 + RBuf8 buf;
1.594 + buf.Create(KTestString().Size());
1.595 + CHECK(KErrNone,==,message.Read(0,buf));
1.596 + CHECK(ETrue,==,buf==KTestString());
1.597 + CHECK(KErrNone,==,message.Write(0,KTestString2));
1.598 + CHECK(KErrNone,==,message.Read(0,buf));
1.599 + CHECK(ETrue,==,buf==KTestString2());
1.600 +
1.601 + test.Next(_L("Check Kernel read/write"));
1.602 + TInt n;
1.603 + TUint32 value;
1.604 + for(n=0; n<KTestString2().Size()-(TInt)sizeof(TInt)+1; n+=sizeof(TInt))
1.605 + {
1.606 + Ldd.ReadMemory(n,value);
1.607 + CHECK(*(TInt*)&KTestString2()[n],==,value);
1.608 + CHECK(KErrNone,==,Ldd.WriteMemory(n,*(TInt*)&KTestString()[n]));
1.609 + Ldd.ReadMemory(n,value);
1.610 + CHECK(*(TInt*)&KTestString()[n],==,value);
1.611 + }
1.612 + CHECK(KErrNone,==,message.Read(0,buf));
1.613 + CHECK(ETrue,==,buf==KTestString());
1.614 + buf.Close();
1.615 +
1.616 + test.Next(_L("Check read/write from DFC"));
1.617 + CHECK(KErrNone,==,Ldd.WriteMemory(0,KTestValue));
1.618 + value = KTestValue2;
1.619 + CHECK(KErrNone,==,Ldd.DfcReadWrite(0,value));
1.620 + CHECK(KTestValue,==,value);
1.621 + CHECK(KErrNone,==,Ldd.ReadMemory(0,value));
1.622 + CHECK(KTestValue2,==,value);
1.623 +
1.624 + test.Next(_L("Check read/write from ISR"));
1.625 + CHECK(KErrNone,==,Ldd.WriteMemory(0,KTestValue));
1.626 + value = KTestValue2;
1.627 + CHECK(KErrNone,==,Ldd.IsrReadWrite(0,value));
1.628 + CHECK(KTestValue,==,value);
1.629 + CHECK(KErrNone,==,Ldd.ReadMemory(0,value));
1.630 + CHECK(KTestValue2,==,value);
1.631 +
1.632 + test.Next(_L("Cleanup resources"));
1.633 + server.Close();
1.634 + User::WaitForRequest(logon);
1.635 + CLOSE_AND_WAIT(process);
1.636 +
1.637 + test.End();
1.638 + }
1.639 +
1.640 +
1.641 +RProcess OtherProcess;
1.642 +
1.643 +TInt HandleShare(TAny* aHandle)
1.644 + {
1.645 + TInt r=OtherProcess.Create(KOtherProcessName,KNullDesC,EOwnerProcess);
1.646 + if(r==KErrNone)
1.647 + {
1.648 + r = OtherProcess.SetParameter(1,(RChunk&)aHandle);
1.649 + }
1.650 + return r;
1.651 + }
1.652 +
1.653 +void TestRestrictions(TInt aAttrib)
1.654 + {
1.655 + TUint ChunkAttribs = ChunkSize|aAttrib|EOwnsMemory;
1.656 +
1.657 + test.Start(_L("Create chunk"));
1.658 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.659 +
1.660 + test.Next(_L("Open user handle"));
1.661 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.662 +
1.663 + test.Next(_L("Try changing restrictions"));
1.664 + CHECK(KErrAccessDenied,==,TheChunk.SetRestrictions(0));
1.665 +
1.666 + test.Next(_L("Check allocation restrictions"));
1.667 + CHECK(KErrAccessDenied,==,TheChunk.Adjust(ChunkSize/2));
1.668 + CHECK(KErrAccessDenied,==,TheChunk.AdjustDoubleEnded(PageSize,ChunkSize));
1.669 + CHECK(KErrAccessDenied,==,TheChunk.Commit(PageSize,PageSize));
1.670 + CHECK(KErrAccessDenied,==,TheChunk.Allocate(PageSize));
1.671 + CHECK(KErrAccessDenied,==,TheChunk.Decommit(PageSize,PageSize));
1.672 +
1.673 + test.Next(_L("Duplicate handle in same process"));
1.674 + RChunk chunk2;
1.675 + chunk2.SetHandle(TheChunk.Handle());
1.676 + CHECK(KErrNone,==,chunk2.Duplicate(RThread(),EOwnerProcess));
1.677 +
1.678 + test.Next(_L("Try passing handle to other process"));
1.679 + if(aAttrib==EMultiple)
1.680 + {
1.681 + CHECK(0,==,CheckPlatSecPanic(HandleShare,*(TInt*)&chunk2));
1.682 + }
1.683 + else
1.684 + {
1.685 + CHECK(1,==,CheckPlatSecPanic(HandleShare,*(TInt*)&chunk2));
1.686 + }
1.687 + // Cleanup leftover process
1.688 + OtherProcess.Kill(0);
1.689 + OtherProcess.Close();
1.690 +
1.691 + test.Next(_L("Close handles"));
1.692 + chunk2.Close();
1.693 + CHECK(0,==,Ldd.CloseChunk());
1.694 + TheChunk.Close();
1.695 +
1.696 + test.End();
1.697 + }
1.698 +
1.699 +
1.700 +class TCommitRegion
1.701 + {
1.702 +public:
1.703 + TInt iOffset;
1.704 + TInt iSize;
1.705 + TInt iExpectedResult;
1.706 + };
1.707 +
1.708 +void CheckRegion(TCommitRegion aRegion, TBool aCheckClear)
1.709 + {
1.710 + TUint8* Base = TheChunk.Base();
1.711 + TInt offset = aRegion.iOffset*PageSize;
1.712 + TInt limit = offset+aRegion.iSize*PageSize;
1.713 + while(offset<limit)
1.714 + {
1.715 + KCHECK_MEMORY(1,offset);
1.716 + UCHECK_MEMORY(1,offset);
1.717 + offset += PageSize;
1.718 + }
1.719 + if(!aCheckClear)
1.720 + return;
1.721 +
1.722 + TUint32* ptr = (TUint32*)(Base+aRegion.iOffset*PageSize);
1.723 + TUint32* end = (TUint32*)((TInt)ptr+aRegion.iSize*PageSize);
1.724 + while(ptr<end)
1.725 + if(*ptr++!=0x03030303u)
1.726 + {
1.727 + CHECK(0x03030303u,==,*ptr);
1.728 + }
1.729 + };
1.730 +
1.731 +void SetTags(TCommitRegion aRegion)
1.732 + {
1.733 + TUint8* Base = TheChunk.Base();
1.734 + TInt offset = aRegion.iOffset*PageSize;
1.735 + TInt limit = offset+aRegion.iSize*PageSize;
1.736 + while(offset<limit)
1.737 + {
1.738 + *(TUint*)(Base+offset) = Tag(offset);
1.739 + offset += sizeof(TUint);
1.740 + }
1.741 + };
1.742 +
1.743 +void CheckTags(const TCommitRegion& aRegion)
1.744 + {
1.745 + TUint8* Base = TheChunk.Base();
1.746 + TInt offset = aRegion.iOffset*PageSize;
1.747 + TInt limit = offset+aRegion.iSize*PageSize;
1.748 + while(offset<limit)
1.749 + {
1.750 + KCHECK_MEMORY(1,offset); // Check page exists
1.751 + TInt limit2 = offset+PageSize;
1.752 + while(offset<limit2)
1.753 + {
1.754 + UREAD_MEMORY(offset,Tag(offset)); // Check contents match tags we set previousely
1.755 + offset += sizeof(TUint);
1.756 + }
1.757 + }
1.758 + };
1.759 +
1.760 +void CheckOldTags(const TCommitRegion& aRegion, TInt aNewOffset)
1.761 + {
1.762 + TUint8* Base = TheChunk.Base();
1.763 + TInt oldOffset = aRegion.iOffset*PageSize;
1.764 + TInt offset = aNewOffset;
1.765 + TInt limit = offset+aRegion.iSize*PageSize;
1.766 + while(offset<limit)
1.767 + {
1.768 + KCHECK_MEMORY(1,offset); // Check page exists
1.769 + TInt limit2 = offset+PageSize;
1.770 + while(offset<limit2)
1.771 + {
1.772 + UREAD_MEMORY(offset,Tag(oldOffset)); // Check contents matched old tags
1.773 + offset += sizeof(TUint);
1.774 + oldOffset += sizeof(TUint);
1.775 + }
1.776 + }
1.777 + };
1.778 +
1.779 +// Following assumes 4k pages...
1.780 +static const TCommitRegion CommitList[] =
1.781 + {
1.782 + {0,0}, // zero size commit
1.783 + {1,1}, // page 1
1.784 +
1.785 + // Regions which overlap previous commit
1.786 + {1,1,KErrAlreadyExists},
1.787 + {0,2,KErrAlreadyExists},
1.788 + {1,2,KErrAlreadyExists},
1.789 + {0,3,KErrAlreadyExists},
1.790 +
1.791 + {0,1}, // page 0
1.792 + {2,1}, // page 2
1.793 +
1.794 + {250,6}, // pages at end of chunk boundary
1.795 +
1.796 + {768,256}, // whole 1meg chunk
1.797 +
1.798 + {400,512,KErrAlreadyExists}, // Monster commit which overlaps previous regions
1.799 +
1.800 + {256,257}, // big commit which straddles more than one 1meg chunk
1.801 +
1.802 + {-1,-1} // End marker
1.803 + };
1.804 +
1.805 +void CheckCommitedContents(TInt aIndex)
1.806 + {
1.807 + while(--aIndex>=0)
1.808 + if(CommitList[aIndex].iExpectedResult==KErrNone)
1.809 + CheckTags(CommitList[aIndex]);
1.810 + };
1.811 +
1.812 +void CheckCommitState(TInt aIndex)
1.813 + {
1.814 + TInt page=0;
1.815 + TInt lastPage=TheChunk.MaxSize()/PageSize;
1.816 + while(page<lastPage)
1.817 + {
1.818 + TInt i=aIndex;
1.819 + while(--i>=0)
1.820 + if(CommitList[i].iExpectedResult==KErrNone)
1.821 + if((TUint)(page-CommitList[i].iOffset) < (TUint)CommitList[i].iSize)
1.822 + break;
1.823 + TInt offset = page*PageSize;
1.824 + if(i>=0)
1.825 + {
1.826 + KCHECK_MEMORY(1,offset); // Check page exists
1.827 + }
1.828 + else
1.829 + {
1.830 + KCHECK_MEMORY(0,offset); // Check page doesn't exists
1.831 + }
1.832 + ++page;
1.833 + }
1.834 + };
1.835 +
1.836 +
1.837 +void TestCommit(TUint aCreateFlags,TCommitType aCommitType)
1.838 + {
1.839 + SetCreateFlags(aCreateFlags,aCommitType);
1.840 + TUint ChunkAttribs = ChunkSize|aCreateFlags;
1.841 +
1.842 + test.Start(_L("Create chunk"));
1.843 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.844 +
1.845 + test.Next(_L("Check wrong commit type"));
1.846 + CHECK(KErrNotSupported,==,Ldd.CommitMemory((aCommitType^EPhysicalMask)|0,PageSize));
1.847 + CHECK(KErrNotSupported,==,Ldd.CommitMemory((aCommitType^EPhysicalMask^EContiguous)|0,PageSize));
1.848 +
1.849 + if((TInt)aCommitType&EPhysicalMask)
1.850 + {
1.851 + test.Next(_L("Check commit with bad pysical address"));
1.852 + CHECK(KErrArgument,==,Ldd.CommitMemory((aCommitType|EBadPhysicalAddress)|0,PageSize));
1.853 + }
1.854 +
1.855 + test.Next(_L("Open user handle"));
1.856 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.857 +
1.858 + const TCommitRegion* list = CommitList;
1.859 + for(;list->iOffset>=0; ++list)
1.860 + {
1.861 + TInt offset = list->iOffset*PageSize;
1.862 + TInt size = list->iSize*PageSize;
1.863 + TInt expectedResult = list->iExpectedResult;
1.864 + if((MemModelAttributes&EMemModelTypeMask)==EMemModelTypeDirect && expectedResult==KErrAlreadyExists)
1.865 + continue;
1.866 + TBuf<100> text;
1.867 + text.AppendFormat(_L("Commit pages: offset=%08x size=%08x expectedResult=%d"),offset,size,expectedResult);
1.868 + test.Next(text);
1.869 +
1.870 + test.Start(_L("Do the Commit"));
1.871 + CHECK(expectedResult,==,Ldd.CommitMemory(aCommitType|offset,size));
1.872 +
1.873 + if(expectedResult==KErrNone)
1.874 + {
1.875 + test.Next(_L("Check new memory has been comitted"));
1.876 + CheckRegion(*list,!(aCommitType&EPhysicalMask));
1.877 + }
1.878 +
1.879 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.880 + {
1.881 + test.Next(_L("Check commit state of all pages in chunk"));
1.882 + CheckCommitState(list-CommitList+1);
1.883 + }
1.884 +
1.885 + test.Next(_L("Check contents of previous commited regions are unchanged"));
1.886 + CheckCommitedContents(list-CommitList);
1.887 +
1.888 + if(expectedResult==KErrNone)
1.889 + {
1.890 + test.Next(_L("Mark new memory"));
1.891 + SetTags(*list);
1.892 + }
1.893 + test.End();
1.894 + }
1.895 +
1.896 + if((aCreateFlags&EMultiple) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.897 + {
1.898 + test.Next(_L("Check another process sees same chunk state"));
1.899 + TInt regionCount = list-CommitList;
1.900 +
1.901 + // create another process
1.902 + RProcess process;
1.903 + CHECK(KErrNone,==,process.Create(KOtherProcessName,KNullDesC));
1.904 + CHECK(KErrNone,==,process.SetParameter(1,ESlaveCheckChunk));
1.905 + CHECK(KErrNone,==,process.SetParameter(2,(RBusLogicalChannel&)Ldd));
1.906 + CHECK(KErrNone,==,process.SetParameter(3,(RChunk&)TheChunk));
1.907 + CHECK(KErrNone,==,process.SetParameter(4,regionCount));
1.908 + TRequestStatus status;
1.909 + process.Logon(status);
1.910 + process.Resume();
1.911 +
1.912 + // Check chunk again in this process, concurrently with other process
1.913 + CheckCommitedContents(regionCount);
1.914 + CheckCommitState(regionCount);
1.915 +
1.916 + // wait for other process to finish
1.917 + User::WaitForRequest(status);
1.918 + CHECK(EExitKill,==,process.ExitType());
1.919 + CHECK(0,==,process.ExitReason());
1.920 + CLOSE_AND_WAIT(process);
1.921 + }
1.922 +
1.923 + test.Next(_L("Close handles"));
1.924 + TheChunk.Close();
1.925 + CHECK(1,==,Ldd.CloseChunk());
1.926 +
1.927 + if(aCommitType&EPhysicalMask)
1.928 + {
1.929 + // For Physical commit tests, check correct allocation by creating a new chunk
1.930 + // and checking that pages comitted contain the old TAGs placed there by the
1.931 + // tests above.
1.932 +
1.933 + test.Next(_L("Check commit uses correct physical pages"));
1.934 +
1.935 + test.Start(_L("Create chunk"));
1.936 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.937 +
1.938 + test.Next(_L("Open user handle"));
1.939 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.940 +
1.941 + TInt offset = 0;
1.942 + for(list=CommitList; list->iOffset>=0; ++list)
1.943 + {
1.944 + if(list->iExpectedResult!=KErrNone)
1.945 + continue;
1.946 +
1.947 + TInt size = list->iSize*PageSize;
1.948 + TBuf<100> text;
1.949 + text.AppendFormat(_L("Commit pages: offset=%08x size=%08x"),offset,size);
1.950 + test.Next(text);
1.951 + CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|offset,size));
1.952 +
1.953 + test.Next(_L("Check RAM contents preserved from previous usage"));
1.954 + CheckOldTags(*list,offset);
1.955 + offset += size;
1.956 + }
1.957 +
1.958 + test.Next(_L("Close handles"));
1.959 + TheChunk.Close();
1.960 + CHECK(1,==,Ldd.CloseChunk());
1.961 +
1.962 + test.End();
1.963 + }
1.964 + else
1.965 + {
1.966 + // We don't do these OOM tests for Physical commit because we can't do it reliably
1.967 + // (as only a couple of page tables come from the free pool not the whole memory
1.968 + // to be comitted)
1.969 + test.Next(_L("Check Out Of Memory conditions"));
1.970 +
1.971 + // Make sure any clean up has happened otherwise the amount of free RAM may change.
1.972 + UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
1.973 +
1.974 + test.Start(_L("Gobble up most of RAM"));
1.975 + test.Next(_L("Load gobbler LDD"));
1.976 + TInt r = User::LoadLogicalDevice(KGobblerLddFileName);
1.977 + test(r==KErrNone || r==KErrAlreadyExists);
1.978 + RGobbler gobbler;
1.979 + r = gobbler.Open();
1.980 + test(r==KErrNone);
1.981 + TUint32 taken = gobbler.GobbleRAM(2*1024*1024);
1.982 + test.Printf(_L("Gobbled: %dK\n"), taken/1024);
1.983 + test.Printf(_L("Free RAM 0x%08X bytes\n"),FreeRam());
1.984 +
1.985 + test.Next(_L("Get baseline free memory"));
1.986 + __KHEAP_MARK;
1.987 + TInt freeRam1 = FreeRam();
1.988 +
1.989 + test.Next(_L("Create shared chunk"));
1.990 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.991 + TInt freeRam2 = FreeRam();
1.992 +
1.993 + test.Next(_L("Commit memory which will causes OOM"));
1.994 + CHECK(KErrNoMemory,==,Ldd.CommitMemory(aCommitType,4096*1024));
1.995 +
1.996 + test.Next(_L("Check free RAM unchanged"));
1.997 + CHECK(freeRam2,==,FreeRam());
1.998 +
1.999 + test.Next(_L("Check OOM during ChunkCommit"));
1.1000 + TInt failResult=KErrGeneral;
1.1001 + for(TInt failCount=1; failCount<1000; failCount++)
1.1002 + {
1.1003 + User::__DbgSetAllocFail(ETrue,RAllocator::EFailNext,failCount);
1.1004 + failResult = Ldd.CommitMemory(aCommitType,1);
1.1005 + if(failResult==KErrNone)
1.1006 + break;
1.1007 + CHECK(KErrNoMemory,==,failResult);
1.1008 + }
1.1009 + User::__DbgSetAllocFail(ETrue,RAllocator::ENone,0);
1.1010 + CHECK(KErrNone,==,failResult);
1.1011 +
1.1012 + test.Next(_L("Destroy shared chunk"));
1.1013 + CHECK(1,==,Ldd.CloseChunk());
1.1014 + CHECK(1,==,Ldd.IsDestroyed());
1.1015 +
1.1016 + test.Next(_L("Check free memory returns to baseline"));
1.1017 + CHECK(freeRam1,==,FreeRam());
1.1018 + __KHEAP_MARKEND;
1.1019 +
1.1020 + test.Next(_L("Free gobbled RAM"));
1.1021 + gobbler.Close();
1.1022 +
1.1023 + test.End();
1.1024 + }
1.1025 +
1.1026 + test.End();
1.1027 + }
1.1028 +
1.1029 +
1.1030 +void TestOpenSharedChunk(TUint aCreateFlags,TCommitType aCommitType)
1.1031 + {
1.1032 + SetCreateFlags(aCreateFlags,aCommitType);
1.1033 + TUint ChunkAttribs = ChunkSize|aCreateFlags;
1.1034 +
1.1035 + test.Start(_L("Create chunk"));
1.1036 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.1037 +
1.1038 + test.Next(_L("Open user handle"));
1.1039 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.1040 +
1.1041 + test.Next(_L("Commit some memory"));
1.1042 + CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|1*PageSize,PageSize));
1.1043 + CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|2*PageSize,PageSize));
1.1044 + CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|4*PageSize,PageSize));
1.1045 +
1.1046 + test.Next(_L("Check OpenSharedChunk with handle"));
1.1047 + CHECK(KErrNone,==,Ldd.TestOpenHandle(TheChunk.Handle()));
1.1048 +
1.1049 + test.Next(_L("Check OpenSharedChunk with wrong chunk handle"));
1.1050 + RChunk testChunk;
1.1051 + CHECK(KErrNone,==,testChunk.CreateLocal(PageSize,PageSize));
1.1052 + CHECK(KErrNotFound,==,Ldd.TestOpenHandle(testChunk.Handle()));
1.1053 + testChunk.Close();
1.1054 +
1.1055 + test.Next(_L("Check OpenSharedChunk with wrong handle type"));
1.1056 + CHECK(KErrNotFound,==,Ldd.TestOpenHandle(RThread().Handle()));
1.1057 +
1.1058 + test.Next(_L("Check OpenSharedChunk with bad handle"));
1.1059 + CHECK(KErrNotFound,==,Ldd.TestOpenHandle(0));
1.1060 +
1.1061 + test.Next(_L("Check OpenSharedChunk with address"));
1.1062 + TUint8* Base = TheChunk.Base();
1.1063 + CHECK(KErrNone,==,Ldd.TestOpenAddress(Base));
1.1064 + CHECK(KErrNone,==,Ldd.TestOpenAddress(Base+ChunkSize-1));
1.1065 +
1.1066 + test.Next(_L("Check OpenSharedChunk with bad address"));
1.1067 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(Base-1));
1.1068 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(Base+ChunkSize));
1.1069 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(0));
1.1070 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress((TAny*)~0));
1.1071 +
1.1072 + test.Next(_L("Check OpenSharedChunk with stack memory address"));
1.1073 + TUint8 stackMem[100];
1.1074 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(stackMem));
1.1075 +
1.1076 + test.Next(_L("Check OpenSharedChunk with heap memory address"));
1.1077 + TUint8* heapMem = new TUint8[100];
1.1078 + CHECK(0,!=,heapMem);
1.1079 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(heapMem));
1.1080 + delete [] heapMem;
1.1081 +
1.1082 + test.Next(_L("Check OpenSharedChunk with BSS memory address"));
1.1083 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(BssMem));
1.1084 +
1.1085 + test.Next(_L("Check OpenSharedChunk with code memory address"));
1.1086 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress((TAny*)&TestOpenSharedChunk));
1.1087 +
1.1088 + test.Next(_L("Check OpenSharedChunk with NULL address"));
1.1089 + CHECK(KErrNotFound,==,Ldd.TestOpenAddress(0));
1.1090 +
1.1091 + test.Next(_L("Check ChunkAddress for given memory region"));
1.1092 + static const TCommitRegion regions[] =
1.1093 + {
1.1094 + {0,1,KErrNotFound},
1.1095 + {0,2,KErrNotFound},
1.1096 + {0,3,KErrNotFound},
1.1097 + {1,1},
1.1098 + {1,2},
1.1099 + {1,3,KErrNotFound},
1.1100 + {2,1},
1.1101 + {2,2,KErrNotFound},
1.1102 + {2,3,KErrNotFound},
1.1103 + {3,1,KErrNotFound},
1.1104 + {3,2,KErrNotFound},
1.1105 + {3,3,KErrNotFound},
1.1106 + {4,1},
1.1107 + {4,2,KErrNotFound},
1.1108 + {4,3,KErrNotFound},
1.1109 + {0,10240,KErrArgument}, // too big
1.1110 + {1,0,KErrArgument}, // bad size
1.1111 + {1,-1,KErrArgument}, // bad size
1.1112 + {10240,1,KErrArgument}, // bad offset
1.1113 + {-2,2,KErrArgument}, // bad offset
1.1114 + {-1}
1.1115 + };
1.1116 + const TCommitRegion* region = regions;
1.1117 + for(;region->iOffset!=-1; ++region)
1.1118 + {
1.1119 + TUint32 offset = region->iOffset*PageSize;
1.1120 + TUint32 size = region->iSize*PageSize;
1.1121 + TInt expectedResult = region->iExpectedResult;
1.1122 + if((MemModelAttributes&EMemModelTypeMask)==EMemModelTypeDirect && expectedResult==KErrNotFound)
1.1123 + continue;
1.1124 + TBuf<100> text;
1.1125 + text.AppendFormat(_L("Memory region: offset=%08x size=%08x expectedResult=%d"),offset,size,expectedResult);
1.1126 + test.Next(text);
1.1127 + CHECK(expectedResult,==,Ldd.TestAddress(offset,size));
1.1128 + }
1.1129 +
1.1130 + test.Next(_L("Close handles"));
1.1131 + TheChunk.Close();
1.1132 + CHECK(1,==,Ldd.CloseChunk());
1.1133 +
1.1134 + test.End();
1.1135 + }
1.1136 +
1.1137 +
1.1138 +void AccessSpeed(TCreateFlags aCreateFlags, TInt& aRead,TInt& aWrite)
1.1139 + {
1.1140 +// test.Start(_L("Create chunk"));
1.1141 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkSize|ESingle|EOwnsMemory|aCreateFlags));
1.1142 +
1.1143 +// test.Next(_L("Commit some memory"));
1.1144 + if((MemModelAttributes&EMemModelTypeMask)==EMemModelTypeDirect)
1.1145 + {
1.1146 + CHECK(KErrNone,==,Ldd.CommitMemory(EDiscontiguous|0*PageSize,PageSize));
1.1147 + }
1.1148 + else
1.1149 + {
1.1150 + // Allocate contiguous memory when possible so that the
1.1151 + // Cache::SyncMemoryBeforeXxxx calls in the test driver get exercised
1.1152 + CHECK(KErrNone,==,Ldd.CommitMemory(EContiguous|0*PageSize,PageSize));
1.1153 + }
1.1154 +
1.1155 +// test.Next(_L("Open user handle"));
1.1156 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.1157 + volatile TUint32* p = (TUint32*)TheChunk.Base();
1.1158 +
1.1159 + TUint32 time;
1.1160 + TInt itterCount=128;
1.1161 + do
1.1162 + {
1.1163 + itterCount *= 2;
1.1164 + TUint32 lastCount=User::NTickCount();
1.1165 + for(TInt i=itterCount; i>0; --i)
1.1166 + {
1.1167 + TUint32 x=p[0]; x=p[1]; x=p[2]; x=p[3]; x=p[4]; x=p[5]; x=p[6]; x=p[7];
1.1168 + }
1.1169 + time = User::NTickCount()-lastCount;
1.1170 + }
1.1171 + while(time<200);
1.1172 + aRead = itterCount*8/time;
1.1173 +
1.1174 + itterCount=128;
1.1175 + do
1.1176 + {
1.1177 + itterCount *= 2;
1.1178 + TUint32 lastCount=User::NTickCount();
1.1179 + for(TInt i=itterCount; i>0; --i)
1.1180 + {
1.1181 + p[0]=i; p[1]=i; p[2]=i; p[3]=i; p[4]=i; p[5]=i; p[6]=i; p[7]=i;
1.1182 + }
1.1183 + time = User::NTickCount()-lastCount;
1.1184 + }
1.1185 + while(time<200);
1.1186 + aWrite = itterCount*8/time;
1.1187 +
1.1188 + TBuf<100> text;
1.1189 + text.AppendFormat(_L("Read speed=%7d Write speed=%7d\n"),aRead,aWrite);
1.1190 + test.Printf(text);
1.1191 +
1.1192 +// test.Next(_L("Close handles"));
1.1193 + TheChunk.Close();
1.1194 + CHECK(1,==,Ldd.CloseChunk());
1.1195 +
1.1196 +// test.End();
1.1197 + }
1.1198 +
1.1199 +void TestMappingAttributes()
1.1200 + {
1.1201 + test.Start(_L("Fully Blocking"));
1.1202 + TInt blockedRead;
1.1203 + TInt blockedWrite;
1.1204 + AccessSpeed(EBlocking,blockedRead,blockedWrite);
1.1205 +
1.1206 + TInt read;
1.1207 + TInt write;
1.1208 +
1.1209 + test.Next(_L("Write Buffered"));
1.1210 + AccessSpeed(EBuffered,read,write);
1.1211 + CHECK(2*blockedRead,>,read);
1.1212 +// CHECK(2*blockedWrite,<,write); // Write buffering doesn't seem to work when cache disabled (?)
1.1213 +
1.1214 + test.Next(_L("Fully Cached"));
1.1215 + AccessSpeed(ECached,read,write);
1.1216 + CHECK(2*blockedRead,<,read);
1.1217 +#ifndef __X86__ // X86 seems to do always do write buffering
1.1218 + // Following check disabled because most dev boards only seem to be a bit faster
1.1219 + // and asserting a particular speed improvement is unreliable
1.1220 +// CHECK(2*blockedWrite,<,write);
1.1221 +#endif
1.1222 +
1.1223 + test.End();
1.1224 + }
1.1225 +
1.1226 +class RSession : public RSessionBase
1.1227 + {
1.1228 +public:
1.1229 + inline TInt CreateSession(const TDesC& aServer,const TVersion& aVersion)
1.1230 + { return RSessionBase::CreateSession(aServer,aVersion); }
1.1231 + inline TInt SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
1.1232 + { return RSessionBase::SendReceive(aFunction,aArgs); }
1.1233 + };
1.1234 +
1.1235 +TInt SlaveCommand(TSlaveCommand aCommand)
1.1236 + {
1.1237 + RDebug::Print(_L("Slave Process - Command %d\n"),aCommand);
1.1238 + CHECK(KErrNone,==,UserHal::PageSizeInBytes(PageSize));
1.1239 + CHECK(KErrNone,==,((RBusLogicalChannel&)Ldd).Open(2,EOwnerProcess));
1.1240 + switch(aCommand)
1.1241 + {
1.1242 + case ESlaveCheckChunk:
1.1243 + {
1.1244 + RDebug::Print(_L("Slave Process - TheChunk.Open()\n"));
1.1245 + CHECK(KErrNone,==,TheChunk.Open(3));
1.1246 + RDebug::Print(_L("Slave Process - Get Region Count\n"));
1.1247 + TInt regionCount;
1.1248 + CHECK(KErrNone,==,User::GetTIntParameter(4,regionCount));
1.1249 + RDebug::Print(_L("Slave Process - CheckCommitedContents(%d)\n"),regionCount);
1.1250 + CheckCommitedContents(regionCount);
1.1251 + RDebug::Print(_L("Slave Process - CheckCommitState(%d)\n"),regionCount);
1.1252 + CheckCommitState(regionCount);
1.1253 + RDebug::Print(_L("Slave Process - Done\n"));
1.1254 + return 0;
1.1255 + }
1.1256 +
1.1257 + case ESlaveCreateChunk:
1.1258 + {
1.1259 + RDebug::Print(_L("Slave Process - Get parameters\n"));
1.1260 + TInt createFlags;
1.1261 + TInt commitType;
1.1262 + TInt commitSize;
1.1263 + CHECK(KErrNone,==,User::GetTIntParameter(3,createFlags));
1.1264 + CHECK(KErrNone,==,User::GetTIntParameter(4,commitType));
1.1265 + CHECK(KErrNone,==,User::GetTIntParameter(5,commitSize));
1.1266 +
1.1267 + RDebug::Print(_L("Slave Process - Create Chunk\n"));
1.1268 + CHECK(KErrNone,==,Ldd.CreateChunk(createFlags));
1.1269 + CHECK(KErrNone,==,Ldd.CommitMemory(commitType,commitSize));
1.1270 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.1271 + TUint8* chunkBase=TheChunk.Base();
1.1272 + memcpy(chunkBase,KTestString().Ptr(),KTestString().Size());
1.1273 +
1.1274 + RDebug::Print(_L("Slave Process - Connecting to test server\n"));
1.1275 + RSession session;
1.1276 + CHECK(KErrNone,==,session.CreateSession(KSecondProcessName,TVersion()));
1.1277 +
1.1278 + RDebug::Print(_L("Slave Process - Sending message\n"));
1.1279 + TPtr8 ptr(chunkBase,commitSize,commitSize);
1.1280 + session.SendReceive(0,TIpcArgs(&ptr));
1.1281 +
1.1282 + RDebug::Print(_L("Slave Process - Destroy Chunk\n"));
1.1283 + TheChunk.Close();
1.1284 + CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
1.1285 + CHECK(1,==,Ldd.IsDestroyed());
1.1286 + return 0;
1.1287 + }
1.1288 +
1.1289 + default:
1.1290 + RDebug::Print(_L("Slave Process - Bad Command\n"));
1.1291 + return KErrArgument;
1.1292 + }
1.1293 + }
1.1294 +
1.1295 +void TestChunkUserBase()
1.1296 + {
1.1297 + TUint ChunkAttribs = ChunkSize|ESingle|EOwnsMemory;
1.1298 +
1.1299 + test.Start(_L("Create chunk"));
1.1300 + CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
1.1301 +
1.1302 + test.Next(_L("Open user handle"));
1.1303 + CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
1.1304 +
1.1305 + test.Next(_L("Commit some memory"));
1.1306 + CHECK(KErrNone,==,Ldd.CommitMemory(EDiscontiguous|1*PageSize,PageSize));
1.1307 +
1.1308 + test.Next(_L("Check OpenSharedChunk with handle"));
1.1309 + CHECK(KErrNone,==,Ldd.TestOpenHandle(TheChunk.Handle()));
1.1310 +
1.1311 + test.Next(_L("Get Kernel's user base"));
1.1312 + TAny *kernelUserAddress;
1.1313 + CHECK(KErrNone,==,Ldd.GetChunkUserBase(&kernelUserAddress));
1.1314 + TAny *userAddress = TheChunk.Base();
1.1315 + test(kernelUserAddress == userAddress);
1.1316 +
1.1317 + TheChunk.Close();
1.1318 + CHECK(1,==,Ldd.CloseChunk());
1.1319 +
1.1320 + test.End();
1.1321 + }
1.1322 +
1.1323 +
1.1324 +TInt E32Main()
1.1325 + {
1.1326 + // Running as slave?
1.1327 + TInt slaveCommand;
1.1328 + if(User::GetTIntParameter(1,slaveCommand)==KErrNone)
1.1329 + return SlaveCommand((TSlaveCommand)slaveCommand);
1.1330 +
1.1331 +// Turn off lazy dll unloading
1.1332 + RLoader l;
1.1333 + test(l.Connect()==KErrNone);
1.1334 + test(l.CancelLazyDllUnload()==KErrNone);
1.1335 + l.Close();
1.1336 +
1.1337 + test.Title();
1.1338 +
1.1339 + MemModelAttributes=UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
1.1340 + TUint mm=MemModelAttributes&EMemModelTypeMask;
1.1341 +#ifdef __T_SHAREDCHUNKF__
1.1342 + if(mm!=EMemModelTypeMoving)
1.1343 + {
1.1344 + test.Start(_L("TESTS NOT RUN - Only valid on Moving Memory Model"));
1.1345 + test.End();
1.1346 + return 0;
1.1347 + }
1.1348 +#endif
1.1349 +
1.1350 + test.Start(_L("Initialise"));
1.1351 + CHECK(KErrNone,==,UserHal::PageSizeInBytes(PageSize));
1.1352 + PhysicalCommitSupported = mm!=EMemModelTypeDirect && mm!=EMemModelTypeEmul;
1.1353 + CachingAttributesSupported = mm!=EMemModelTypeDirect && mm!=EMemModelTypeEmul;
1.1354 +
1.1355 +
1.1356 + test.Next(_L("Loading test driver"));
1.1357 + TInt r = User::LoadLogicalDevice(KSharedChunkLddName);
1.1358 + test(r==KErrNone || r==KErrAlreadyExists);
1.1359 +
1.1360 + test.Next(_L("Opening channel"));
1.1361 + CHECK(KErrNone,==,Ldd.Open());
1.1362 +
1.1363 + // now 'unload' test driver, however, it will remain loaded whilst
1.1364 + // we still have a channel open with it...
1.1365 + User::FreeLogicalDevice(KSharedChunkLddName);
1.1366 +
1.1367 + test.Next(_L("Test chunk create"));
1.1368 + TestCreate();
1.1369 +
1.1370 + test.Next(_L("Test handles"));
1.1371 + TestHandles();
1.1372 +
1.1373 + test.Next(_L("Test handle ownership"));
1.1374 + TestHandleOwnership();
1.1375 +
1.1376 + test.Next(_L("Test restrictions for multiply shared chunks"));
1.1377 + TestRestrictions(EMultiple);
1.1378 + test.Next(_L("Test restrictions for singly shared chunks"));
1.1379 + TestRestrictions(ESingle);
1.1380 +
1.1381 + test.Next(_L("Test memory access for multiply shared chunks"));
1.1382 + TestAccess(EMultiple|EOwnsMemory,EDiscontiguous);
1.1383 + test.Next(_L("Test memory access for singly shared chunks"));
1.1384 + TestAccess(ESingle|EOwnsMemory,EDiscontiguous);
1.1385 +
1.1386 + test.Next(_L("Test Discontiguous memory commit for multiply shared chunks"));
1.1387 + TestCommit(EMultiple,EDiscontiguous);
1.1388 + test.Next(_L("Test Discontiguous memory commit for singly shared chunks"));
1.1389 + TestCommit(ESingle,EDiscontiguous);
1.1390 +
1.1391 + if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
1.1392 + {
1.1393 + test.Next(_L("Test Contiguous memory commit for multiply shared chunks"));
1.1394 + TestCommit(EMultiple,EContiguous);
1.1395 + test.Next(_L("Test Contiguous memory commit for singly shared chunks"));
1.1396 + TestCommit(ESingle,EContiguous);
1.1397 + }
1.1398 +
1.1399 + if(PhysicalCommitSupported)
1.1400 + {
1.1401 + test.Next(_L("Test Discontiguous Physical commit for multiply shared chunks"));
1.1402 + TestCommit(EMultiple,EDiscontiguousPhysical);
1.1403 + test.Next(_L("Test Discontiguous Physical commit for singly shared chunks"));
1.1404 + TestCommit(ESingle,EDiscontiguousPhysical);
1.1405 +
1.1406 + test.Next(_L("Test Contiguous Physical commit for multiply shared chunks"));
1.1407 + TestCommit(EMultiple,EContiguousPhysical);
1.1408 + test.Next(_L("Test Contiguous Physical commit for singly shared chunks"));
1.1409 + TestCommit(ESingle,EContiguousPhysical);
1.1410 + }
1.1411 +
1.1412 + test.Next(_L("Test Kern::OpenSharedChunk for multiply shared chunks"));
1.1413 + TestOpenSharedChunk(EMultiple,EDiscontiguous);
1.1414 + test.Next(_L("Test Kern::OpenSharedChunk for singly shared chunks"));
1.1415 + TestOpenSharedChunk(ESingle,EDiscontiguous);
1.1416 +
1.1417 + if(CachingAttributesSupported)
1.1418 + {
1.1419 + test.Next(_L("Test Mapping Attributes"));
1.1420 + TestMappingAttributes();
1.1421 + }
1.1422 +
1.1423 + test.Next(_L("Testing Kern::ChunkUserBase for shared chunks"));
1.1424 + TestChunkUserBase();
1.1425 +
1.1426 + if (PhysicalCommitSupported)
1.1427 + {
1.1428 + test.Next(_L("Testing Kern::ChunkClose allows immediate freeing of physical ram"));
1.1429 + test_KErrNone(Ldd.TestChunkCloseAndFree());
1.1430 + }
1.1431 +
1.1432 + test.Next(_L("Close test driver"));
1.1433 + Ldd.Close();
1.1434 +
1.1435 + test.End();
1.1436 +
1.1437 + return 0;
1.1438 + }