116 test(r==KErrNone); |
129 test(r==KErrNone); |
117 test(FreeRam()==free); |
130 test(FreeRam()==free); |
118 |
131 |
119 } |
132 } |
120 |
133 |
|
134 |
|
135 struct SPhysAllocData |
|
136 { |
|
137 TUint iSize; |
|
138 TUint iAlign; |
|
139 TBool iCheckMaxAllocs; |
|
140 TBool iCheckFreeRam; |
|
141 }; |
|
142 |
|
143 |
|
144 TInt FillPhysicalRam(TAny* aArgs) |
|
145 { |
|
146 SPhysAllocData& allocData = *((SPhysAllocData*)aArgs); |
|
147 TUint maxAllocs = FreeRam() / allocData.iSize; |
|
148 TUint32* physAddrs = new TUint32[maxAllocs + 1]; |
|
149 if (!physAddrs) |
|
150 return KErrNoMemory; |
|
151 TUint32* pa = physAddrs; |
|
152 TUint32 alignMask = (1 << allocData.iAlign) - 1; |
|
153 TUint initialFreeRam = FreeRam(); |
|
154 TInt r = KErrNone; |
|
155 TUint allocations = 0; |
|
156 for (; allocations <= maxAllocs + 1; allocations++) |
|
157 { |
|
158 TUint freeRam = FreeRam(); |
|
159 r = AllocPhysicalRam(*pa, allocData.iSize, allocData.iAlign); |
|
160 if (r != KErrNone) |
|
161 break; |
|
162 if (*pa++ & alignMask) |
|
163 { |
|
164 r = KErrGeneral; |
|
165 RDebug::Printf("Error alignment phys addr 0x%08x", *(pa - 1)); |
|
166 break; |
|
167 } |
|
168 if (allocData.iCheckFreeRam && freeRam - allocData.iSize != (TUint)FreeRam()) |
|
169 { |
|
170 r = KErrGeneral; |
|
171 RDebug::Printf("Error in free ram 0x%08x orig 0x%08x", FreeRam(), 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; |
|
178 } |
|
179 } |
|
180 |
|
181 TUint32* physEnd = pa; |
|
182 TBool failFrees = EFalse; |
|
183 for (pa = physAddrs; pa < physEnd; pa++) |
|
184 { |
|
185 if (FreePhysicalRam(*pa, allocData.iSize) != KErrNone) |
|
186 failFrees = ETrue; |
|
187 } |
|
188 if (failFrees) |
|
189 r = KErrNotFound; |
|
190 if (allocData.iCheckFreeRam && initialFreeRam != (TUint)FreeRam()) |
|
191 { |
|
192 r = KErrGeneral; |
|
193 RDebug::Printf("Error in free ram 0x%08x initial 0x%08x", FreeRam(), initialFreeRam); |
|
194 } |
|
195 delete[] physAddrs; |
|
196 if (r != KErrNone && r != KErrNoMemory) |
|
197 return r; |
|
198 TUint possibleAllocs = initialFreeRam / allocData.iSize; |
|
199 if (allocData.iCheckMaxAllocs && possibleAllocs != allocations) |
|
200 { |
|
201 RDebug::Printf("Error in number of allocations possibleAllocs %d allocations %d", possibleAllocs, allocations); |
|
202 return KErrGeneral; |
|
203 } |
|
204 return allocations; |
|
205 } |
|
206 |
|
207 |
|
208 void TestMultipleContiguousAllocations(TUint aNumThreads, TUint aSize, TUint aAlign) |
|
209 { |
|
210 test.Printf(_L("TestMultiContig threads %d size 0x%x, align %d\n"), aNumThreads, aSize, aAlign); |
|
211 SPhysAllocData allocData; |
|
212 allocData.iSize = aSize; |
|
213 allocData.iAlign = aAlign; |
|
214 allocData.iCheckMaxAllocs = EFalse; |
|
215 allocData.iCheckFreeRam = EFalse; |
|
216 // Start several threads all contiguous allocating memory. |
|
217 RThread* threads = new RThread[aNumThreads]; |
|
218 TRequestStatus* status = new TRequestStatus[aNumThreads]; |
|
219 TUint i = 0; |
|
220 for (; i < aNumThreads; i++) |
|
221 { |
|
222 TInt r = threads[i].Create(KNullDesC, FillPhysicalRam, KDefaultStackSize, PageSize, PageSize, (TAny*)&allocData); |
|
223 test_KErrNone(r); |
|
224 threads[i].Logon(status[i]); |
|
225 } |
|
226 for (i = 0; i < aNumThreads; i++) |
|
227 { |
|
228 threads[i].Resume(); |
|
229 } |
|
230 for (i = 0; i < aNumThreads; i++) |
|
231 { |
|
232 User::WaitForRequest(status[i]); |
|
233 test_Equal(EExitKill, threads[i].ExitType()); |
|
234 TInt exitReason = threads[i].ExitReason(); |
|
235 test_Value(exitReason, exitReason >= 0 || exitReason == KErrNoMemory); |
|
236 threads[i].Close(); |
|
237 } |
|
238 delete[] status; |
|
239 delete[] threads; |
|
240 } |
|
241 |
|
242 struct STouchData |
|
243 { |
|
244 TUint iSize; |
|
245 TUint iFrequency; |
|
246 }TouchData; |
|
247 |
|
248 |
|
249 TInt TouchMemory(TAny*) |
|
250 { |
|
251 while (!TouchDataStop) |
|
252 { |
|
253 TUint8* p = Chunk.Base(); |
|
254 TUint8* pEnd = p + ChunkCommitEnd; |
|
255 TUint8* fragPEnd = p + TouchData.iFrequency; |
|
256 for (TUint8* fragP = p + TouchData.iSize; fragPEnd < pEnd;) |
|
257 { |
|
258 TUint8* data = fragP; |
|
259 for (; data < fragPEnd; data += PageSize) |
|
260 { |
|
261 *data = (TUint8)(data - fragP); |
|
262 } |
|
263 for (data = fragP; data < fragPEnd; data += PageSize) |
|
264 { |
|
265 if (*data != (TUint8)(data - fragP)) |
|
266 { |
|
267 RDebug::Printf("Error unexpected data 0x%x read from 0x%08x", *data, data); |
|
268 return KErrGeneral; |
|
269 } |
|
270 } |
|
271 fragP = fragPEnd + TouchData.iSize; |
|
272 fragPEnd += TouchData.iFrequency; |
|
273 } |
|
274 } |
|
275 return KErrNone; |
|
276 } |
|
277 |
|
278 struct SFragData |
|
279 { |
|
280 TUint iSize; |
|
281 TUint iFrequency; |
|
282 TUint iDiscard; |
|
283 TBool iFragThread; |
|
284 }FragData; |
|
285 |
|
286 void FragmentMemoryFunc() |
|
287 { |
|
288 ChunkCommitEnd = 0; |
|
289 TInt r; |
|
290 while(KErrNone == (r = Chunk.Commit(ChunkCommitEnd,PageSize)) && !FragThreadStop) |
|
291 { |
|
292 ChunkCommitEnd += PageSize; |
|
293 } |
|
294 if (FragThreadStop) |
|
295 return; |
|
296 test_Equal(KErrNoMemory, r); |
|
297 TUint freeBlocks = 0; |
|
298 for ( TUint offset = 0; |
|
299 (offset + FragData.iSize) < ChunkCommitEnd; |
|
300 offset += FragData.iFrequency, freeBlocks++) |
|
301 { |
|
302 test_KErrNone(Chunk.Decommit(offset, FragData.iSize)); |
|
303 } |
|
304 if (!FragData.iFragThread) |
|
305 test_Equal(FreeRam(), freeBlocks * FragData.iSize); |
|
306 |
|
307 if (FragData.iDiscard && CacheSizeAdjustable && !FragThreadStop) |
|
308 { |
|
309 TUint minCacheSize = FreeRam(); |
|
310 TUint maxCacheSize = minCacheSize; |
|
311 TUint currentCacheSize; |
|
312 test_KErrNone(DPTest::CacheSize(OrigMinCacheSize, OrigMaxCacheSize, currentCacheSize)); |
|
313 test_KErrNone(DPTest::SetCacheSize(minCacheSize, maxCacheSize)); |
|
314 test_KErrNone(DPTest::SetCacheSize(OrigMinCacheSize, maxCacheSize)); |
|
315 } |
|
316 } |
|
317 |
|
318 |
|
319 void UnfragmentMemoryFunc() |
|
320 { |
|
321 if (FragData.iDiscard && CacheSizeAdjustable) |
|
322 test_KErrNone(DPTest::SetCacheSize(OrigMinCacheSize, OrigMaxCacheSize)); |
|
323 Chunk.Decommit(0, Chunk.MaxSize()); |
|
324 } |
|
325 |
|
326 |
|
327 TInt FragmentMemoryThreadFunc(TAny*) |
|
328 { |
|
329 while (!FragThreadStop) |
|
330 { |
|
331 FragmentMemoryFunc(); |
|
332 UnfragmentMemoryFunc(); |
|
333 } |
|
334 return KErrNone; |
|
335 } |
|
336 |
|
337 |
|
338 void FragmentMemory(TUint aSize, TUint aFrequency, TBool aDiscard, TBool aTouchMemory, TBool aFragThread) |
|
339 { |
|
340 test_Value(aTouchMemory, !aTouchMemory || !aFragThread); |
|
341 test_Value(aSize, aSize < aFrequency); |
|
342 FragData.iSize = aSize; |
|
343 FragData.iFrequency = aFrequency; |
|
344 FragData.iDiscard = aDiscard; |
|
345 FragData.iFragThread = aFragThread; |
|
346 |
|
347 TChunkCreateInfo chunkInfo; |
|
348 chunkInfo.SetDisconnected(0, 0, FreeRam()); |
|
349 chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged); |
|
350 test_KErrNone(Chunk.Create(chunkInfo)); |
|
351 |
|
352 if (aFragThread) |
|
353 { |
|
354 TInt r = FragThread.Create(KNullDesC, FragmentMemoryThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); |
|
355 test_KErrNone(r); |
|
356 FragThread.Logon(FragStatus); |
|
357 FragThreadStop = EFalse; |
|
358 FragThread.Resume(); |
|
359 } |
|
360 else |
|
361 { |
|
362 FragmentMemoryFunc(); |
|
363 } |
|
364 if (aTouchMemory && !ManualTest) |
|
365 { |
|
366 TouchData.iSize = aSize; |
|
367 TouchData.iFrequency = aFrequency; |
|
368 TInt r = TouchThread.Create(KNullDesC, TouchMemory, KDefaultStackSize, PageSize, PageSize, NULL); |
|
369 test_KErrNone(r); |
|
370 TouchThread.Logon(TouchStatus); |
|
371 TouchDataStop = EFalse; |
|
372 TouchThread.Resume(); |
|
373 } |
|
374 } |
|
375 |
|
376 |
|
377 void UnfragmentMemory(TBool aDiscard, TBool aTouchMemory, TBool aFragThread) |
|
378 { |
|
379 test_Value(aTouchMemory, !aTouchMemory || !aFragThread); |
|
380 if (aTouchMemory && !ManualTest) |
|
381 { |
|
382 TouchDataStop = ETrue; |
|
383 User::WaitForRequest(TouchStatus); |
|
384 test_Equal(EExitKill, TouchThread.ExitType()); |
|
385 test_KErrNone(TouchThread.ExitReason()); |
|
386 CLOSE_AND_WAIT(TouchThread); |
|
387 } |
|
388 if (aFragThread) |
|
389 { |
|
390 FragThreadStop = ETrue; |
|
391 User::WaitForRequest(FragStatus); |
|
392 test_Equal(EExitKill, FragThread.ExitType()); |
|
393 test_KErrNone(FragThread.ExitReason()); |
|
394 CLOSE_AND_WAIT(FragThread); |
|
395 } |
|
396 else |
|
397 UnfragmentMemoryFunc(); |
|
398 CLOSE_AND_WAIT(Chunk); |
|
399 } |
|
400 |
|
401 |
|
402 void TestFillPhysicalRam(TUint aFragSize, TUint aFragFreq, TUint aAllocSize, TUint aAllocAlign, TBool aDiscard, TBool aTouchMemory) |
|
403 { |
|
404 test.Printf(_L("TestFillPhysicalRam aFragSize 0x%x aFragFreq 0x%x aAllocSize 0x%x aAllocAlign %d dis %d touch %d\n"), |
|
405 aFragSize, aFragFreq, aAllocSize, aAllocAlign, aDiscard, aTouchMemory); |
|
406 FragmentMemory(aFragSize, aFragFreq, aDiscard, aTouchMemory, EFalse); |
|
407 SPhysAllocData allocData; |
|
408 // 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; |
|
410 allocData.iCheckFreeRam = ETrue; |
|
411 allocData.iSize = aAllocSize; |
|
412 allocData.iAlign = aAllocAlign; |
|
413 FillPhysicalRam(&allocData); |
|
414 UnfragmentMemory(aDiscard, aTouchMemory, EFalse); |
|
415 } |
|
416 |
|
417 |
|
418 void TestFragmentedAllocation() |
|
419 { |
|
420 // Test every other page free. |
|
421 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize, 0, EFalse, EFalse); |
|
422 if (ManualTest) |
|
423 { |
|
424 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize * 2, 0, EFalse, EFalse); |
|
425 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize, 0, EFalse, ETrue); |
|
426 } |
|
427 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize * 2, 0, EFalse, ETrue); |
|
428 // Test every 2 pages free. |
|
429 TestFillPhysicalRam(PageSize * 2, PageSize * 4, PageSize * 8, 0, EFalse, EFalse); |
|
430 if (ManualTest) |
|
431 TestFillPhysicalRam(PageSize * 2, PageSize * 4, PageSize * 8, 0, EFalse, ETrue); |
|
432 // Test 10 pages free then 20 pages allocated, allocate 256 pages (1MB in most cases). |
|
433 if (ManualTest) |
|
434 TestFillPhysicalRam(PageSize * 10, PageSize * 30, PageSize * 256, 0, EFalse, EFalse); |
|
435 TestFillPhysicalRam(PageSize * 10, PageSize * 30, PageSize * 256, 0, EFalse, ETrue); |
|
436 |
|
437 if (CacheSizeAdjustable) |
|
438 {// It is possible to adjust the cache size so test phyiscally contiguous |
|
439 // allocations discard and move pages when required. |
|
440 test.Next(_L("TestFragmentedAllocations with discardable data no true free memory")); |
|
441 // Test every other page free. |
|
442 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize, 0, ETrue, EFalse); |
|
443 if (ManualTest) |
|
444 { |
|
445 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize, 0, ETrue, ETrue); |
|
446 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize * 2, 0, ETrue, EFalse); |
|
447 } |
|
448 TestFillPhysicalRam(PageSize, PageSize * 2, PageSize * 2, 0, ETrue, ETrue); |
|
449 // Test every 2 pages free. |
|
450 TestFillPhysicalRam(PageSize * 2, PageSize * 4, PageSize * 8, 0, ETrue, EFalse); |
|
451 if (ManualTest) |
|
452 TestFillPhysicalRam(PageSize * 2, PageSize * 4, PageSize * 8, 0, ETrue, ETrue); |
|
453 // Test 10 pages free then 20 pages allocated, allocate 256 pages (1MB in most cases). |
|
454 if (ManualTest) |
|
455 TestFillPhysicalRam(PageSize * 10, PageSize * 30, PageSize * 256, 0, ETrue, EFalse); |
|
456 TestFillPhysicalRam(PageSize * 10, PageSize * 30, PageSize * 256, 0, ETrue, ETrue); |
|
457 } |
|
458 } |
|
459 |
|
460 |
121 GLDEF_C TInt E32Main() |
461 GLDEF_C TInt E32Main() |
122 // |
462 // |
123 // Test RAM allocation |
463 // Test RAM allocation |
124 // |
464 // |
125 { |
465 { |
146 TestAlignedAllocs(); |
502 TestAlignedAllocs(); |
147 |
503 |
148 test.Next(_L("TestClaimPhys")); |
504 test.Next(_L("TestClaimPhys")); |
149 TestClaimPhys(); |
505 TestClaimPhys(); |
150 |
506 |
|
507 if (memodel >= EMemModelTypeFlexible) |
|
508 { |
|
509 test.Next(_L("TestFragmentedAllocation")); |
|
510 TestFragmentedAllocation(); |
|
511 |
|
512 test.Next(_L("TestMultipleContiguousAllocations")); |
|
513 TestMultipleContiguousAllocations(20, PageSize * 16, 0); |
|
514 TestMultipleContiguousAllocations(20, PageSize * 16, PageShift + 1); |
|
515 TestMultipleContiguousAllocations(20, PageSize * 128, PageShift + 2); |
|
516 |
|
517 FragmentMemory(PageSize, PageSize * 2, EFalse, EFalse, EFalse); |
|
518 TestMultipleContiguousAllocations(20, PageSize * 128, PageShift + 2); |
|
519 UnfragmentMemory(EFalse, EFalse, EFalse); |
|
520 |
|
521 test.Next(_L("TestMultipleContiguousAllocations while accessing memory")); |
|
522 FragmentMemory(PageSize, PageSize * 2, EFalse, ETrue, EFalse); |
|
523 TestMultipleContiguousAllocations(20, PageSize * 128, PageShift + 2); |
|
524 UnfragmentMemory(EFalse, ETrue, EFalse); |
|
525 FragmentMemory(PageSize, PageSize * 2, ETrue, ETrue, EFalse); |
|
526 TestMultipleContiguousAllocations(50, PageSize * 256, PageShift + 5); |
|
527 UnfragmentMemory(ETrue, ETrue, EFalse); |
|
528 FragmentMemory(PageSize * 16, PageSize * 32, ETrue, ETrue, EFalse); |
|
529 TestMultipleContiguousAllocations(10, PageSize * 512, PageShift + 8); |
|
530 UnfragmentMemory(ETrue, ETrue, EFalse); |
|
531 FragmentMemory(PageSize * 32, PageSize * 64, ETrue, ETrue, EFalse); |
|
532 TestMultipleContiguousAllocations(10, PageSize * 1024, PageShift + 10); |
|
533 UnfragmentMemory(ETrue, ETrue, EFalse); |
|
534 |
|
535 test.Next(_L("TestMultipleContiguousAllocations with repeated movable and discardable allocations")); |
|
536 FragmentMemory(PageSize, PageSize * 2, EFalse, EFalse, ETrue); |
|
537 TestMultipleContiguousAllocations(20, PageSize * 2, PageShift); |
|
538 UnfragmentMemory(EFalse, EFalse, ETrue); |
|
539 FragmentMemory(PageSize, PageSize * 2, EFalse, EFalse, ETrue); |
|
540 TestMultipleContiguousAllocations(20, PageSize * 128, PageShift + 2); |
|
541 UnfragmentMemory(EFalse, EFalse, ETrue); |
|
542 FragmentMemory(PageSize, PageSize * 2, ETrue, EFalse, ETrue); |
|
543 TestMultipleContiguousAllocations(50, PageSize * 256, PageShift + 5); |
|
544 UnfragmentMemory(ETrue, EFalse, ETrue); |
|
545 FragmentMemory(PageSize * 16, PageSize * 32, ETrue, EFalse, ETrue); |
|
546 TestMultipleContiguousAllocations(20, PageSize * 512, PageShift + 8); |
|
547 UnfragmentMemory(ETrue, EFalse, ETrue); |
|
548 FragmentMemory(PageSize * 32, PageSize * 64, ETrue, EFalse, ETrue); |
|
549 TestMultipleContiguousAllocations(20, PageSize * 1024, PageShift + 10); |
|
550 UnfragmentMemory(ETrue, EFalse, ETrue); |
|
551 } |
|
552 |
151 Shadow.Close(); |
553 Shadow.Close(); |
|
554 test.Printf(_L("Free RAM=%08x at end of test\n"),FreeRam()); |
152 test.End(); |
555 test.End(); |
153 return(KErrNone); |
556 return(KErrNone); |
154 } |
557 } |
155 |
|