kernel/eka/include/memmodel/epoc/mmubase/ramalloc.h
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
child 22 2f92ad2dc5db
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32\include\memmodel\epoc\mmubase\ramalloc.h
// 
//

/**
 @file
 @internalComponent
*/

#ifndef __RAMALLOC_H__
#define __RAMALLOC_H__
#include <kernel/klib.h>

// RAM information block passed from bootstrap to kernel.
// Consists of two consecutive lists of SRamBank structures, each terminated by
// a bank with iSize=0.
// The first list specifies all available blocks of RAM in the system.
// The second list specifies any blocks of RAM which are reserved and not
// available for general allocation. This should not include RAM mapped by the
// bootstrap - this will be discovered when the initial page mappings are
// analysed.
struct SRamInfo
	{
	SRamBank iBanks[1];				// extend for multiple banks
//	SRamBank iReservedBlocks[1];
	};

/** The number of types of pages that can't be moved or discarded
*/
const TInt KPageImmovable = EPageMovable;

/** The lowest enum from TZonePageType that DRamAllocater will allocate
*/
const TUint KPageTypeAllocBase = EPageFixed;

/** Element 0 of SZone::iBma is the bit map of all allocated pages 
regardless of type.
*/
const TUint KBmaAllPages = 0;

/** The maximum number of freeable contiguous pages that can be found by
DRamAllocator::FindFreeableContiguousPages and RamCacheBase::AllocFreeContiguousPages.
*/
const TUint KMaxFreeableContiguousPages = 16;


/** Structure to store the information on a zone.
*/
struct SZone
	{
	TBitMapAllocator* iBma[EPageTypes];	/**< Pointers to bit map allocators for each type of page*/
	TPhysAddr iPhysBase;	/**< physical base address of this zone*/
	TPhysAddr iPhysEnd;		/**< physical end address of this zone*/
	TUint32 iPhysPages;		/**< the total no. of pages that are in this zone*/
	TUint32 iAllocPages[EPageTypes]; /**< number of pages allocated of each type*/
	TUint32 iFreePages;		/**< number of pages free*/
	SDblQueLink iPrefLink;	/**< The link of this zone into the preference ordered list*/
	TUint iPrefRank;		/**< The rank of this zone in the preference ordered list.*/
	TUint iId;				/**< the ID of the zone*/
	TUint iFlags;			/**< bit flags for this zone, all flags masked KRamZoneFlagInvalid are 
								 for use by the kernel only*/
	TUint8 iPref;			/**< the preference of the zone, lower preference zones are used first*/
	};

/** The different stages of a general defragmentation*/
enum TGenDefragStage
	{
	EGenDefragStage0,	/**< 	This stage should discard any pages needed to
								allow the required movable pages to fit into the
								RAM zones to be in use after the general defrag.*/
	EGenDefragStage1,	/**< 	This stage should reduce the number of RAM
								zones in use to the minmum required.*/
	EGenDefragStage2,	/**<	This stage clears space in most preferable RAM 
								zones for fixed page allocations by placing movable 
								and discardable pages in the least preferable RAM 
								zones in use.*/
	EGenDefragStageEnd,
	};

// forward declare
struct SPageInfo;

class DRamAllocator : public DBase
	{
private:
	/** Used with NextAllocZone to specify which order to run through the zones
	*/
	enum TZoneSearchState
		{
		EZoneSearchPref,
		EZoneSearchAddr,
		EZoneSearchEnd,
		};

	enum TPanic
		{
		EDoNotUse=0,
		EDoMarkPagesAllocated1=1,
		EAllocRamPagesInconsistent=2,
		EZonesTooNumerousOrFew=3,	/**<There are too many or too few RAM zones*/
		EZonesNotDistinct=4,		/**<Some of the RAM zones overlap*/
		EZonesIncomplete=5,			/**<The RAM zones don't cover all the RAM, either because the zones 
										are too small or at least one zone is mapped to an incorrect address*/
		EZonesIDInvalid=6,			/**<KRamZoneInvalidId can't be used for any zone's ID*/
		EZonesIDNotUnique=7,		/**<At least two zones share the same ID*/
		EZonesAlignment=8,			/**<Zones are not aligned to page boundaries*/
		EZonesCountErr=9,			/**<The count of free and alloc'd zone pages is corrupted*/
		EZonesCallbackErr=10,		/**<Unexpected error when zone call back invoked*/
		EZonesFlagsInvalid=11,		/**<Attempt to create a zone with flags set to invalid values*/
		ECreateNoMemory=12,			/**<Not enough free RAM to create a DRamAllocator object*/
		ECreateInvalidReserveBank=13,/**<A specified reserve bank could not be reserved*/
		ECreateInvalidRamBanks=14,	/**<The specified RAM banks are invalid*/
		EFreeingLockedPage=15, 		/**< A locked page was requested for freeing*/
		};

public:

	static DRamAllocator* New(const SRamInfo& aInfo, const SRamZone* aZoneInfo, TRamZoneCallback aZoneCallback);
	static void Panic(TPanic aPanic);
	TUint TotalPhysicalRamPages();
	TInt FreeRamInBytes();
	TUint FreeRamInPages();
	TInt ClaimPhysicalRam(TPhysAddr aBase, TInt aSize);
	TInt FreePhysicalRam(TPhysAddr aBase, TInt aSize);
	void Create(const SRamInfo& aInfo, const SRamZone* aZones, TRamZoneCallback aZoneCallback);
	TInt MarkPageAllocated(TPhysAddr aAddr, TZonePageType aType);
	void MarkPagesAllocated(TPhysAddr aAddr, TInt aCount, TZonePageType aType);
	TInt FreeRamPage(TPhysAddr aAddr, TZonePageType aType);
	void FreeRamPages(TPhysAddr* aPageList, TInt aNumPages, TZonePageType aType);
	TInt AllocRamPages(TPhysAddr* aPageList, TInt aNumPages, TZonePageType aType, TUint aBlockedZoneId=KRamZoneInvalidId, TBool aBlockRest=EFalse);
	TInt ZoneAllocRamPages(TUint* aZoneIdList, TUint aZoneIdCount, TPhysAddr* aPageList, TInt aNumPages, TZonePageType aType);
	TInt AllocContiguousRam(TUint aNumPages, TPhysAddr& aPhysAddr, TZonePageType aType, TInt aAlign=0, TUint aBlockZoneId=KRamZoneInvalidId, TBool aBlockRest=EFalse);
	TInt ZoneAllocContiguousRam(TUint* aZoneIdList, TUint aZoneIdCount, TInt aSize, TPhysAddr& aPhysAddr, TZonePageType aType, TInt aAlign);
#ifdef _DEBUG
	void DebugDump();
#endif
#ifdef __VERIFY_LEASTMOVDIS
	void VerifyLeastPrefMovDis();
#endif
	TInt GetZonePageCount(TUint aId, SRamZonePageCount& aPageData);
	void ChangePageType(SPageInfo* aPageInfo, TZonePageType aOldType, TZonePageType aNewType);
#ifdef BTRACE_RAM_ALLOCATOR
	void SendInitialBtraceLogs(void);
#endif
	TInt GetZoneAddress(TUint aZoneId, TPhysAddr& aPhysBase, TUint& aNumPages);
	TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
	TInt NextAllocatedPage(SZone* aZone, TUint& aOffset, TZonePageType aType) const;
	TUint GenDefragFreePages(TZonePageType aType) const;
	SZone* GeneralDefragStart0(TGenDefragStage& aStage, TUint& aRequiredToBeDiscarded);
	SZone* GeneralDefragNextZone0();
	SZone* GeneralDefragStart1();
	SZone* GeneralDefragNextZone1();
	SZone* GeneralDefragStart2();
	SZone* GeneralDefragNextZone2();
	void GeneralDefragEnd();
	SZone* ZoneFromId(TUint aId) const;
	void ZoneClaimStart(SZone& aZone);
	void ZoneClaimEnd(SZone& aZone);
	TInt ModifyZoneFlags(TUint aId, TUint aClearFlags, TUint aSetFlags);
	void ZoneMark(SZone& aZone);
	TBool ZoneUnmark(SZone& aZone);
	void InitialCallback();
private:
	static DRamAllocator* New();
	SZone* GetZoneAndOffset(TPhysAddr aAddr, TInt& aOffset);
	inline void CountZones(const SRamZone* aZones);
	inline void SortRamZones(const SRamZone* aZones, TUint8* aZoneAddrOrder);
	void ZoneAllocPages(SZone* aZone, TUint32 aCount, TZonePageType aType);
	void ZoneFreePages(SZone* aZone, TUint32 aCount, TZonePageType aType);
	void ZoneClearPages(SZone& aZone, TUint aRequiredPages);
	TUint32 ZoneFindPages(TPhysAddr*& aPageList, SZone& aZone, TUint32 aNumPages, TZonePageType aType);
	TInt SetPhysicalRamState(TPhysAddr aBase, TInt aSize, TBool aState, TZonePageType aType);
	inline TUint InitSPageInfos(const SZone* aZone);
	TBool NextAllocZone(SZone*& aZone, TZoneSearchState& aState, TZonePageType aType, TUint aBlockedZoneId, TBool aBlockRest);
	TBool NoAllocOfPageType(SZone& aZone, TZonePageType aType) const;
private:
	TPhysAddr iPhysAddrBase;	// lowest valid physical address
	TPhysAddr iPhysAddrTop;		// highest valid physical address
	TUint iTotalFreeRamPages;
	TUint iTotalRamPages;

	SZone* iZones;				/**< per-zone info stored in ascending address order*/
	TUint32 iNumZones;			/**< The number of zones*/
	SDblQue iZonePrefList;		/**< Doubly linked list of zones in preference order*/
	SDblQueLink* iZoneLeastMovDis; 		/**< Link to the least preferable RAM zone that has discardable or movable pages*/
	TUint iZoneLeastMovDisRank; 		/**< Rank of the least preferable RAM zone that has discardable or movable pages*/
	TUint64 iZonePwrState;				/**< mask of currently used power blocks*/
	TBool iZoneCallbackInitSent;		/**< Set to ETrue once an ERamZoneOp_Init has been issued*/
	TRamZoneCallback iZonePowerFunc;	/**< Callback function to invoke when RAM zone power state changes*/
	TInt iZoneTmpAddrIndex;				/**< Used by NextAllocZone*/
	SDblQueLink* iZoneTmpPrefLink;		/**< Used by NextAllocZone*/
	SDblQueLink* iZoneGeneralPrefLink;	/**< Link to the current RAM zone being defragged*/
	SDblQueLink* iZoneGeneralTmpLink;	/**< Link to the current RAM zone being defragged*/
	TUint iZoneGeneralStage;			/**< The current stage of any general defrag operation*/
#ifdef _DEBUG
	TBool iAllowBmaVerify;
#endif
	};

#endif