502 r = TestChunk.Commit(0,min*2); |
503 r = TestChunk.Commit(0,min*2); |
503 test_KErrNone(r); |
504 test_KErrNone(r); |
504 } |
505 } |
505 |
506 |
506 |
507 |
|
508 TBool StopCacheThreads; |
|
509 |
|
510 TInt CacheThreadFunc(TAny* aMax) |
|
511 { |
|
512 RThread::Rendezvous(KErrNone); |
|
513 while (!StopCacheThreads) |
|
514 { |
|
515 TInt maxSize = (TInt)aMax; |
|
516 TInt minSize; |
|
517 TInt r = KErrNone; |
|
518 for (minSize = PageSize << 4; r == KErrNone && !StopCacheThreads; minSize += PageSize) |
|
519 { |
|
520 r = UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize); |
|
521 User::After(minSize/PageSize); |
|
522 } |
|
523 for (minSize -= PageSize; |
|
524 minSize > PageSize << 4 && r == KErrNone && !StopCacheThreads; |
|
525 minSize -= PageSize) |
|
526 { |
|
527 r = UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize); |
|
528 User::After(minSize/PageSize); |
|
529 } |
|
530 } |
|
531 return KErrNone; |
|
532 } |
|
533 |
|
534 |
|
535 TInt DonateThreadFunc(TAny*) |
|
536 { |
|
537 TChunkCreateInfo createInfo; |
|
538 createInfo.SetCache(100 * PageSize); |
|
539 RChunk chunk; |
|
540 TInt r = chunk.Create(createInfo); |
|
541 if (r != KErrNone) |
|
542 { |
|
543 RDebug::Printf("DonateThreadFunc: Failed to create cache chunk %d", r); |
|
544 return r; |
|
545 } |
|
546 TUint chunkEnd = 0; |
|
547 while (chunk.Commit(chunkEnd, PageSize) == KErrNone) |
|
548 chunkEnd += PageSize; |
|
549 |
|
550 RThread::Rendezvous(KErrNone); |
|
551 while (!StopCacheThreads) |
|
552 { |
|
553 for (TUint i = PageSize; i <= chunkEnd && !StopCacheThreads; i += PageSize) |
|
554 { |
|
555 chunk.Unlock(0, i); |
|
556 if (chunk.Lock(0, i) != KErrNone) |
|
557 {// Recommit as many pages as possible. |
|
558 while (chunk.Commit(0, chunkEnd) != KErrNone && !StopCacheThreads) |
|
559 chunkEnd -= PageSize; |
|
560 i = 0; |
|
561 } |
|
562 User::After(i/PageSize); |
|
563 } |
|
564 } |
|
565 CLOSE_AND_WAIT(chunk); |
|
566 return KErrNone; |
|
567 } |
|
568 |
|
569 |
|
570 TInt DirtyThreadFunc(TAny*) |
|
571 { |
|
572 RThread::Rendezvous(KErrNone); |
|
573 |
|
574 RChunk chunk; |
|
575 TChunkCreateInfo createInfo; |
|
576 createInfo.SetNormal(PageSize * 100, PageSize *100); |
|
577 createInfo.SetPaging(TChunkCreateInfo::EPaged); |
|
578 TInt r = chunk.Create(createInfo); |
|
579 if (r != KErrNone) |
|
580 { |
|
581 RDebug::Printf("Failed to create a cache chunk %d", r); |
|
582 return r; |
|
583 } |
|
584 TUint8* base = chunk.Base(); |
|
585 // Dirty each page in the chunk so that there are dirty pages in the live |
|
586 // list while it is being resized and pages are being unlocked. |
|
587 while (!StopCacheThreads) |
|
588 { |
|
589 TUint8* p = base; |
|
590 TUint8* pEnd = base + chunk.Size(); |
|
591 for (; p < pEnd && !StopCacheThreads; p += PageSize) |
|
592 { |
|
593 *p = (TUint8)(pEnd - p); |
|
594 User::After((TUint8)(pEnd - p)); |
|
595 } |
|
596 } |
|
597 CLOSE_AND_WAIT(chunk); |
|
598 return KErrNone; |
|
599 } |
|
600 |
|
601 |
|
602 void TestResizeExcess() |
|
603 { |
|
604 test.Printf(_L("Commit all of memory again leaving 100 free pages\n")); |
|
605 CommitEnd = 0; |
|
606 TInt r; |
|
607 while(KErrNone==(r=TestChunk.Commit(CommitEnd,PageSize))) |
|
608 { |
|
609 CommitEnd += PageSize; |
|
610 } |
|
611 test(r==KErrNoMemory); |
|
612 test_KErrNone(TestChunk.Unlock(0, 100 * PageSize)); |
|
613 |
|
614 SVMCacheInfo info; |
|
615 test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalGetCacheSize, &info, 0)); |
|
616 |
|
617 StopCacheThreads = EFalse; |
|
618 RThread cacheThread; |
|
619 r = cacheThread.Create( KNullDesC, CacheThreadFunc, KDefaultStackSize, PageSize, |
|
620 PageSize, (TAny*)info.iMaxSize); |
|
621 test_KErrNone(r); |
|
622 TRequestStatus threadStarted; |
|
623 cacheThread.Rendezvous(threadStarted); |
|
624 TRequestStatus cacheStatus; |
|
625 cacheThread.Logon(cacheStatus); |
|
626 cacheThread.Resume(); |
|
627 User::WaitForRequest(threadStarted); |
|
628 test_KErrNone(threadStarted.Int()); |
|
629 |
|
630 // Create the dirty thread before the donate thread as the donate thread may |
|
631 // consume all the free ram periodically. |
|
632 RThread dirtyThread; |
|
633 r = dirtyThread.Create(KNullDesC, DirtyThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); |
|
634 test_KErrNone(r); |
|
635 dirtyThread.Rendezvous(threadStarted); |
|
636 TRequestStatus dirtyStatus; |
|
637 dirtyThread.Logon(dirtyStatus); |
|
638 dirtyThread.Resume(); |
|
639 User::WaitForRequest(threadStarted); |
|
640 test_KErrNone(threadStarted.Int()); |
|
641 |
|
642 RThread donateThread; |
|
643 r = donateThread.Create(KNullDesC, DonateThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); |
|
644 test_KErrNone(r); |
|
645 donateThread.Rendezvous(threadStarted); |
|
646 TRequestStatus donateStatus; |
|
647 donateThread.Logon(donateStatus); |
|
648 donateThread.Resume(); |
|
649 User::WaitForRequest(threadStarted); |
|
650 test_KErrNone(threadStarted.Int()); |
|
651 |
|
652 // Run test for 10 secs. |
|
653 User::After(10000000); |
|
654 |
|
655 // End the test. |
|
656 StopCacheThreads = ETrue; |
|
657 User::WaitForRequest(donateStatus); |
|
658 test_Equal(EExitKill, donateThread.ExitType()); |
|
659 test_KErrNone(donateThread.ExitReason()); |
|
660 User::WaitForRequest(dirtyStatus); |
|
661 test_Equal(EExitKill, dirtyThread.ExitType()); |
|
662 test_KErrNone(dirtyThread.ExitReason()); |
|
663 User::WaitForRequest(cacheStatus); |
|
664 test_Equal(EExitKill, cacheThread.ExitType()); |
|
665 test_KErrNone(cacheThread.ExitReason()); |
|
666 |
|
667 CLOSE_AND_WAIT(donateThread); |
|
668 CLOSE_AND_WAIT(cacheThread); |
|
669 CLOSE_AND_WAIT(dirtyThread); |
|
670 |
|
671 test_KErrNone(UserSvr::HalFunction( EHalGroupVM, |
|
672 EVMHalSetCacheSize, |
|
673 (TAny*)info.iMinSize, |
|
674 (TAny*)info.iMaxSize)); |
|
675 } |
|
676 |
507 |
677 |
508 TInt E32Main() |
678 TInt E32Main() |
509 { |
679 { |
510 test.Title(); |
680 test.Title(); |
511 |
681 |