151 TUint32* pa = physAddrs; |
152 TUint32* pa = physAddrs; |
152 TUint32 alignMask = (1 << allocData.iAlign) - 1; |
153 TUint32 alignMask = (1 << allocData.iAlign) - 1; |
153 TUint initialFreeRam = FreeRam(); |
154 TUint initialFreeRam = FreeRam(); |
154 TInt r = KErrNone; |
155 TInt r = KErrNone; |
155 TUint allocations = 0; |
156 TUint allocations = 0; |
156 for (; allocations <= maxAllocs + 1; allocations++) |
157 for(; allocations <= maxAllocs; ++allocations) |
157 { |
158 { |
158 TUint freeRam = FreeRam(); |
159 TUint freeRam = FreeRam(); |
159 r = AllocPhysicalRam(*pa, allocData.iSize, allocData.iAlign); |
160 r = AllocPhysicalRam(*pa, allocData.iSize, allocData.iAlign); |
160 if (r != KErrNone) |
161 if (r != KErrNone) |
161 break; |
162 break; |
163 { |
164 { |
164 r = KErrGeneral; |
165 r = KErrGeneral; |
165 RDebug::Printf("Error alignment phys addr 0x%08x", *(pa - 1)); |
166 RDebug::Printf("Error alignment phys addr 0x%08x", *(pa - 1)); |
166 break; |
167 break; |
167 } |
168 } |
168 if (allocData.iCheckFreeRam && freeRam - allocData.iSize != (TUint)FreeRam()) |
169 TUint newFreeRam = FreeRam(); |
|
170 if (allocData.iCheckFreeRam && freeRam - allocData.iSize != newFreeRam) |
169 { |
171 { |
170 r = KErrGeneral; |
172 r = KErrGeneral; |
171 RDebug::Printf("Error in free ram 0x%08x orig 0x%08x", FreeRam(), freeRam); |
173 RDebug::Printf("Error in free ram 0x%08x orig 0x%08x", newFreeRam, freeRam); |
172 } |
|
173 if (allocData.iCheckMaxAllocs && allocations > maxAllocs && r == KErrNone) |
|
174 { |
|
175 r = KErrOverflow; |
|
176 RDebug::Printf("Error able to allocate too many pages"); |
|
177 break; |
174 break; |
178 } |
175 } |
179 } |
176 } |
180 |
177 |
181 TUint32* physEnd = pa; |
178 TUint32* physEnd = pa; |
185 if (FreePhysicalRam(*pa, allocData.iSize) != KErrNone) |
182 if (FreePhysicalRam(*pa, allocData.iSize) != KErrNone) |
186 failFrees = ETrue; |
183 failFrees = ETrue; |
187 } |
184 } |
188 if (failFrees) |
185 if (failFrees) |
189 r = KErrNotFound; |
186 r = KErrNotFound; |
190 if (allocData.iCheckFreeRam && initialFreeRam != (TUint)FreeRam()) |
187 if (allocData.iCheckMaxAllocs && allocations > maxAllocs) |
|
188 { |
|
189 r = KErrOverflow; |
|
190 RDebug::Printf("Error able to allocate too many pages"); |
|
191 } |
|
192 TUint finalFreeRam = FreeRam(); |
|
193 if (allocData.iCheckFreeRam && initialFreeRam != finalFreeRam) |
191 { |
194 { |
192 r = KErrGeneral; |
195 r = KErrGeneral; |
193 RDebug::Printf("Error in free ram 0x%08x initial 0x%08x", FreeRam(), initialFreeRam); |
196 RDebug::Printf("Error in free ram 0x%08x initial 0x%08x", finalFreeRam, initialFreeRam); |
194 } |
197 } |
195 delete[] physAddrs; |
198 delete[] physAddrs; |
196 if (r != KErrNone && r != KErrNoMemory) |
199 if (r != KErrNone && r != KErrNoMemory) |
197 return r; |
200 return r; |
198 TUint possibleAllocs = initialFreeRam / allocData.iSize; |
201 TUint possibleAllocs = initialFreeRam / allocData.iSize; |
216 // Start several threads all contiguous allocating memory. |
219 // Start several threads all contiguous allocating memory. |
217 RThread* threads = new RThread[aNumThreads]; |
220 RThread* threads = new RThread[aNumThreads]; |
218 TRequestStatus* status = new TRequestStatus[aNumThreads]; |
221 TRequestStatus* status = new TRequestStatus[aNumThreads]; |
219 TUint i = 0; |
222 TUint i = 0; |
220 for (; i < aNumThreads; i++) |
223 for (; i < aNumThreads; i++) |
221 { |
224 {// Need enough heap to store addr of every possible allocation + 1. |
222 TInt r = threads[i].Create(KNullDesC, FillPhysicalRam, KDefaultStackSize, PageSize, PageSize, (TAny*)&allocData); |
225 TUint requiredHeapMax = Max(PageSize, ((TotalRam / aSize) * sizeof(TUint32)) + sizeof(TUint32)); |
|
226 TInt r = threads[i].Create(KNullDesC, FillPhysicalRam, KDefaultStackSize, PageSize, requiredHeapMax, (TAny*)&allocData); |
223 test_KErrNone(r); |
227 test_KErrNone(r); |
224 threads[i].Logon(status[i]); |
228 threads[i].Logon(status[i]); |
225 } |
229 } |
226 for (i = 0; i < aNumThreads; i++) |
230 for (i = 0; i < aNumThreads; i++) |
227 { |
231 { |
246 }TouchData; |
250 }TouchData; |
247 |
251 |
248 |
252 |
249 TInt TouchMemory(TAny*) |
253 TInt TouchMemory(TAny*) |
250 { |
254 { |
|
255 RThread::Rendezvous(KErrNone); // Signal that this thread has started running. |
251 while (!TouchDataStop) |
256 while (!TouchDataStop) |
252 { |
257 { |
253 TUint8* p = Chunk.Base(); |
258 TUint8* p = Chunk.Base(); |
254 TUint8* pEnd = p + ChunkCommitEnd; |
259 TUint8* pEnd = p + ChunkCommitEnd; |
255 TUint8* fragPEnd = p + TouchData.iFrequency; |
260 TUint8* fragPEnd = p + TouchData.iFrequency; |
299 (offset + FragData.iSize) < ChunkCommitEnd; |
304 (offset + FragData.iSize) < ChunkCommitEnd; |
300 offset += FragData.iFrequency, freeBlocks++) |
305 offset += FragData.iFrequency, freeBlocks++) |
301 { |
306 { |
302 test_KErrNone(Chunk.Decommit(offset, FragData.iSize)); |
307 test_KErrNone(Chunk.Decommit(offset, FragData.iSize)); |
303 } |
308 } |
304 if (!FragData.iFragThread) |
|
305 test_Equal(FreeRam(), freeBlocks * FragData.iSize); |
|
306 |
309 |
307 if (FragData.iDiscard && CacheSizeAdjustable && !FragThreadStop) |
310 if (FragData.iDiscard && CacheSizeAdjustable && !FragThreadStop) |
308 { |
311 { |
309 TUint minCacheSize = FreeRam(); |
312 TUint minCacheSize = FreeRam(); |
310 TUint maxCacheSize = minCacheSize; |
313 TUint maxCacheSize = minCacheSize; |
343 FragData.iFrequency = aFrequency; |
347 FragData.iFrequency = aFrequency; |
344 FragData.iDiscard = aDiscard; |
348 FragData.iDiscard = aDiscard; |
345 FragData.iFragThread = aFragThread; |
349 FragData.iFragThread = aFragThread; |
346 |
350 |
347 TChunkCreateInfo chunkInfo; |
351 TChunkCreateInfo chunkInfo; |
348 chunkInfo.SetDisconnected(0, 0, FreeRam()); |
352 chunkInfo.SetDisconnected(0, 0, TotalRam); |
349 chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged); |
353 chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged); |
350 test_KErrNone(Chunk.Create(chunkInfo)); |
354 test_KErrNone(Chunk.Create(chunkInfo)); |
351 |
355 |
352 if (aFragThread) |
356 if (aFragThread) |
353 { |
357 { |
354 TInt r = FragThread.Create(KNullDesC, FragmentMemoryThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); |
358 TInt r = FragThread.Create(KNullDesC, FragmentMemoryThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); |
355 test_KErrNone(r); |
359 test_KErrNone(r); |
356 FragThread.Logon(FragStatus); |
360 FragThread.Logon(FragStatus); |
357 FragThreadStop = EFalse; |
361 FragThreadStop = EFalse; |
|
362 TRequestStatus threadInitialised; |
|
363 FragThread.Rendezvous(threadInitialised); |
358 FragThread.Resume(); |
364 FragThread.Resume(); |
|
365 User::WaitForRequest(threadInitialised); |
|
366 test_KErrNone(threadInitialised.Int()); |
359 } |
367 } |
360 else |
368 else |
361 { |
369 { |
362 FragmentMemoryFunc(); |
370 FragmentMemoryFunc(); |
363 } |
371 } |
367 TouchData.iFrequency = aFrequency; |
375 TouchData.iFrequency = aFrequency; |
368 TInt r = TouchThread.Create(KNullDesC, TouchMemory, KDefaultStackSize, PageSize, PageSize, NULL); |
376 TInt r = TouchThread.Create(KNullDesC, TouchMemory, KDefaultStackSize, PageSize, PageSize, NULL); |
369 test_KErrNone(r); |
377 test_KErrNone(r); |
370 TouchThread.Logon(TouchStatus); |
378 TouchThread.Logon(TouchStatus); |
371 TouchDataStop = EFalse; |
379 TouchDataStop = EFalse; |
|
380 TRequestStatus threadInitialised; |
|
381 TouchThread.Rendezvous(threadInitialised); |
372 TouchThread.Resume(); |
382 TouchThread.Resume(); |
|
383 User::WaitForRequest(threadInitialised); |
|
384 test_KErrNone(threadInitialised.Int()); |
373 } |
385 } |
374 } |
386 } |
375 |
387 |
376 |
388 |
377 void UnfragmentMemory(TBool aDiscard, TBool aTouchMemory, TBool aFragThread) |
389 void UnfragmentMemory(TBool aDiscard, TBool aTouchMemory, TBool aFragThread) |
408 // Only check free all ram could be allocated in manual tests as fixed pages may be fragmented. |
420 // Only check free all ram could be allocated in manual tests as fixed pages may be fragmented. |
409 allocData.iCheckMaxAllocs = (ManualTest && !aTouchMemory && !aAllocAlign)? ETrue : EFalse; |
421 allocData.iCheckMaxAllocs = (ManualTest && !aTouchMemory && !aAllocAlign)? ETrue : EFalse; |
410 allocData.iCheckFreeRam = ETrue; |
422 allocData.iCheckFreeRam = ETrue; |
411 allocData.iSize = aAllocSize; |
423 allocData.iSize = aAllocSize; |
412 allocData.iAlign = aAllocAlign; |
424 allocData.iAlign = aAllocAlign; |
413 FillPhysicalRam(&allocData); |
425 TInt r = FillPhysicalRam(&allocData); |
|
426 test_Value(r, r >= 0); |
414 UnfragmentMemory(aDiscard, aTouchMemory, EFalse); |
427 UnfragmentMemory(aDiscard, aTouchMemory, EFalse); |
415 } |
428 } |
416 |
429 |
417 |
430 |
418 void TestFragmentedAllocation() |
431 void TestFragmentedAllocation() |
489 User::CommandLine(cmdLine); |
502 User::CommandLine(cmdLine); |
490 cmdLine.LowerCase(); |
503 cmdLine.LowerCase(); |
491 ManualTest = cmdLine.Find(KManual) != KErrNotFound; |
504 ManualTest = cmdLine.Find(KManual) != KErrNotFound; |
492 } |
505 } |
493 |
506 |
494 InitFreeRam=FreeRam(); |
507 // Turn off lazy dll unloading and ensure any supervisor clean up has completed |
495 test.Printf(_L("Free RAM=%08x, Page size=%x, Page shift=%d\n"),InitFreeRam,PageSize,PageShift); |
508 // so the free ram checking isn't affected. |
|
509 RLoader l; |
|
510 test(l.Connect()==KErrNone); |
|
511 test(l.CancelLazyDllUnload()==KErrNone); |
|
512 l.Close(); |
|
513 UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); |
|
514 |
|
515 test_KErrNone(HAL::Get(HAL::EMemoryRAM, TotalRam)); |
|
516 |
|
517 test.Printf(_L("Free RAM=%08x, Page size=%x, Page shift=%d\n"),FreeRam(),PageSize,PageShift); |
496 |
518 |
497 test.Next(_L("Open test LDD")); |
519 test.Next(_L("Open test LDD")); |
498 r=Shadow.Open(); |
520 r=Shadow.Open(); |
499 test(r==KErrNone); |
521 test(r==KErrNone); |
500 |
522 |