65 /// Note that this does not always correspond to the state of the page in RAM - for example a |
65 /// Note that this does not always correspond to the state of the page in RAM - for example a |
66 /// page can be dirty in RAM but blank in swap if it has never been written out. |
66 /// page can be dirty in RAM but blank in swap if it has never been written out. |
67 enum TSwapState |
67 enum TSwapState |
68 { |
68 { |
69 EStateUnreserved = 0, ///< swap space not yet reserved, or page is being decommitted |
69 EStateUnreserved = 0, ///< swap space not yet reserved, or page is being decommitted |
70 EStateBlank = 1, ///< swap page has never been written |
70 EStateBlank = 1, ///< swap page has never been written or the last write failed |
71 EStateWritten = 2, ///< swap page has been written out at least once |
71 EStateWritten = 2, ///< swap page has been written out at least once |
72 EStateWriting = 3 ///< swap page is in the process of being written out |
72 EStateWriting = 3 ///< swap page is in the process of being written out |
73 }; |
73 }; |
74 |
74 |
75 enum |
75 enum |
462 */ |
463 */ |
463 TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs) |
464 TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs) |
464 { |
465 { |
465 __ASSERT_CRITICAL; |
466 __ASSERT_CRITICAL; |
466 |
467 |
467 TInt r = KErrNone; |
|
468 const TUint readUnitShift = iDevice->iReadUnitShift; |
468 const TUint readUnitShift = iDevice->iReadUnitShift; |
469 TUint readSize = KPageSize >> readUnitShift; |
469 TUint readSize = KPageSize >> readUnitShift; |
470 TThreadMessage message; |
470 TThreadMessage message; |
471 |
471 |
472 const TUint indexEnd = aIndex + aCount; |
472 const TUint indexEnd = aIndex + aCount; |
475 START_PAGING_BENCHMARK; |
475 START_PAGING_BENCHMARK; |
476 |
476 |
477 MmuLock::Lock(); // MmuLock required for atomic access to manager data. |
477 MmuLock::Lock(); // MmuLock required for atomic access to manager data. |
478 TUint swapData = aMemory->PagingManagerData(index); |
478 TUint swapData = aMemory->PagingManagerData(index); |
479 TSwapState state = SwapState(swapData); |
479 TSwapState state = SwapState(swapData); |
|
480 TUint swapPage = SwapIndex(swapData); |
480 |
481 |
481 if (state == EStateUnreserved) |
482 if (state == EStateUnreserved) |
482 {// This page is not committed to the memory object |
483 { |
|
484 // This page is not committed to the memory object |
483 MmuLock::Unlock(); |
485 MmuLock::Unlock(); |
484 return KErrNotFound; |
486 return KErrNotFound; |
485 } |
487 } |
486 else if (state == EStateBlank) |
488 else if (state == EStateBlank) |
487 {// This page has not been written to yet so don't read from swap |
489 { |
488 // just wipe it if required. |
490 if (swapPage != 0) |
489 TUint allocFlags = aMemory->RamAllocFlags(); |
|
490 MmuLock::Unlock(); |
|
491 TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe); |
|
492 if (wipePages) |
|
493 { |
491 { |
494 TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ? |
492 // An error occured while writing the page out, so report it now |
495 (allocFlags >> Mmu::EAllocWipeByteShift) & 0xff : |
493 MmuLock::Unlock(); |
496 0x03; |
494 return -swapPage; |
497 memset((TAny*)aLinAddr, wipeByte, KPageSize); |
495 } |
|
496 else |
|
497 { |
|
498 // This page has not been written to yet so don't read from swap |
|
499 // just wipe it if required. |
|
500 TUint allocFlags = aMemory->RamAllocFlags(); |
|
501 MmuLock::Unlock(); |
|
502 TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe); |
|
503 if (wipePages) |
|
504 { |
|
505 TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ? |
|
506 (allocFlags >> Mmu::EAllocWipeByteShift) & 0xff : |
|
507 0x03; |
|
508 memset((TAny*)aLinAddr, wipeByte, KPageSize); |
|
509 } |
498 } |
510 } |
499 } |
511 } |
500 else |
512 else |
501 { |
513 { |
502 // It is not possible to get here if the page is in state EStateWriting as if so it must |
514 // It is not possible to get here if the page is in state EStateWriting as if so it must |
504 __NK_ASSERT_DEBUG(state == EStateWritten); |
516 __NK_ASSERT_DEBUG(state == EStateWritten); |
505 |
517 |
506 // OK to release as if the object's data is decommitted the pager |
518 // OK to release as if the object's data is decommitted the pager |
507 // will check that data is still valid before mapping it. |
519 // will check that data is still valid before mapping it. |
508 MmuLock::Unlock(); |
520 MmuLock::Unlock(); |
509 TUint readStart = (SwapIndex(swapData) << KPageShift) >> readUnitShift; |
521 TUint readStart = (swapPage << KPageShift) >> readUnitShift; |
510 START_PAGING_BENCHMARK; |
522 START_PAGING_BENCHMARK; |
511 r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging); |
523 TInt r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging); |
|
524 END_PAGING_BENCHMARK(EPagingBmReadDataMedia); |
|
525 __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore shouldn't fail with KErrNoMemory |
512 if (r != KErrNone) |
526 if (r != KErrNone) |
513 __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r)); |
527 __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r)); |
514 __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory |
528 r = ThePager.EmbedErrorContext(EPagingErrorContextDataRead, r); |
515 END_PAGING_BENCHMARK(EPagingBmReadDataMedia); |
529 if (r != KErrNone) |
516 __NK_ASSERT_ALWAYS(r == KErrNone); |
530 return r; |
517 } |
531 } |
518 END_PAGING_BENCHMARK(EPagingBmReadDataPage); |
532 END_PAGING_BENCHMARK(EPagingBmReadDataPage); |
519 } |
533 } |
520 |
534 |
521 return r; |
535 return KErrNone; |
522 } |
536 } |
523 |
537 |
524 |
538 |
525 /** |
539 /** |
526 Write the specified memory object's pages from the RAM into the swap. |
540 Write the specified memory object's pages from the RAM into the swap. |
624 TInt r; |
638 TInt r; |
625 if (aLinAddr == 0) |
639 if (aLinAddr == 0) |
626 r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground); |
640 r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground); |
627 else |
641 else |
628 r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground); |
642 r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground); |
|
643 END_PAGING_BENCHMARK(EPagingBmWriteDataMedia); |
629 |
644 |
630 if (r != KErrNone) |
645 if (r != KErrNone) |
631 { |
646 { |
632 __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r)); |
647 __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r)); |
|
648 if (r > 0) |
|
649 r = KErrGeneral; |
633 } |
650 } |
634 __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory |
651 __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory |
635 __NK_ASSERT_ALWAYS(r == KErrNone); |
652 r = ThePager.EmbedErrorContext(EPagingErrorContextDataWrite, r); |
636 END_PAGING_BENCHMARK(EPagingBmWriteDataMedia); |
|
637 |
653 |
638 TUint i; |
654 TUint i; |
639 TUint swapData[KMaxPagesToClean]; |
655 TUint swapData[KMaxPagesToClean]; |
640 |
656 |
641 MmuLock::Lock(); |
657 MmuLock::Lock(); |
645 swapData[i] = aMemory[i]->PagingManagerData(aIndex[i]); |
661 swapData[i] = aMemory[i]->PagingManagerData(aIndex[i]); |
646 TSwapState s = SwapState(swapData[i]); |
662 TSwapState s = SwapState(swapData[i]); |
647 __NK_ASSERT_DEBUG(s == EStateUnreserved || s == EStateWriting); |
663 __NK_ASSERT_DEBUG(s == EStateUnreserved || s == EStateWriting); |
648 if (s == EStateWriting) |
664 if (s == EStateWriting) |
649 { |
665 { |
650 // Store the new swap location and mark the page as saved. |
666 // Store the new swap location and mark the page as saved, or if an error occured then |
651 aMemory[i]->SetPagingManagerData(aIndex[i], SwapData(EStateWritten, aSwapIndex + i)); |
667 // record the error code instead |
|
668 TUint swapData = (r == KErrNone) |
|
669 ? SwapData(EStateWritten, aSwapIndex + i) |
|
670 : SwapData(EStateBlank, -r); |
|
671 aMemory[i]->SetPagingManagerData(aIndex[i], swapData); |
652 } |
672 } |
653 } |
673 } |
654 MmuLock::Unlock(); |
674 MmuLock::Unlock(); |
655 |
675 |
656 for (i = 0 ; i < aCount ; ++i) |
676 for (i = 0 ; i < aCount ; ++i) |
657 { |
677 { |
658 TSwapState s = SwapState(swapData[i]); |
678 TSwapState s = SwapState(swapData[i]); |
659 if (s == EStateUnreserved) |
679 if (s == EStateUnreserved || s == EStateBlank) |
660 { |
680 { |
661 // The page was decommitted while we were cleaning it, so free the swap page we |
681 // The page was either decommitted while we were cleaning it, or an error occured while |
662 // allocated and continue, leaving this page in the unreserved state. |
682 // writing. Free the swap page and don't modify the state. |
663 FreeSwapIndex(aSwapIndex + i); |
683 FreeSwapIndex(aSwapIndex + i); |
664 } |
684 } |
665 } |
685 } |
666 |
686 |
667 return KErrNone; |
687 // write errors are not reported at this point as this will just kill a thread unrelated to the |
|
688 // one whose data has been lost |
|
689 return KErrNone; |
668 } |
690 } |
669 |
691 |
670 |
692 |
671 /** |
693 /** |
672 Notify the media driver that the page written to swap is no longer required. |
694 Notify the media driver that the page written to swap is no longer required. |