| author | Slion |
| Thu, 07 Jan 2010 01:56:11 +0100 | |
| branch | anywhere |
| changeset 26 | 01da090338f9 |
| parent 0 | a41df078684a |
| permissions | -rw-r--r-- |
// Copyright (c) 2007-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: // /** @file @internalComponent */ #ifndef MSLABALLOC_H #define MSLABALLOC_H #include "mcleanup.h" /** Slab allocator. */ class RSlabAllocatorBase { public: RSlabAllocatorBase(TBool aDelayedCleanup); ~RSlabAllocatorBase(); /** Construct a slab allocator. @param aMaxSlabs Maximum number of slabs to use. (Number of bits in \a slabBits.) @param aObjectSize Size of objects to allocate. */ TInt Construct(TUint aMaxSlabs, TUint aObjectSize); /** Construct a slab allocator using fixed virtual memory. @param aMaxSlabs Maximum number of slabs to use. (Number of bits in \a slabBits.) @param aObjectSize Size of objects to allocate. @param aBase Virtual address for start of memory where slabs will be allocated. Zero indicates 'anywhere'. */ TInt Construct(TUint aMaxSlabs, TUint aObjectSize, TLinAddr aBase); /** Set the memory object to be used for the slab allocator. */ FORCE_INLINE void SetMemory(DMemoryObject* aMemory, TUint aReserveCount) { __NK_ASSERT_DEBUG(!iMemory); iMemory = aMemory; iReserveCount = aReserveCount; } /** Allocate an object. @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. @pre MmuLock held @post MmuLock held, but has always beet flashed */ TAny* Alloc(); /** Free an object previously allocated with #Alloc. @param aObject The object. @pre MmuLock held @post MmuLock held, but has always beet flashed */ void Free(TAny* aObject); protected: class TSlabHeader : public SDblQueLink { public: SDblQue iFreeList; ///< List of unallocated objects in list. TUint iAllocCount; ///< Number of objects allocated in this slab. TAny* iHighWaterMark; ///< End of initialise region in slab. }; private: TBool NewSlab(); void InitSlab(TLinAddr aPage); void FreeSlab(TSlabHeader* aSlab); static void CleanupTrampoline(TAny* aSelf); void Cleanup(); #ifdef _DEBUG void CheckSlab(TSlabHeader* aSlab); #endif private: SDblQue iFreeList; ///< List of slabs which have unallocated objects in them. TUint iFreeCount; ///< Number of unallocated objects. TUint iReserveCount; ///< Number of unallocated objects to keep in reserve (to allow for recursion during allocation). TUint iObjectsPerSlab; ///< Number of objects in each slab. TUint iObjectSize; ///< Size, in bytes, of objects to be allocated. TSpinLock iSpinLock; ///< Spinlock which protects iFreeList, iFreeCount and TSlabHeader contents. TMemoryCleanup iCleanup; ///< Used to queue Cleanup() if iDelayedCleanup is true. TBool iDelayedCleanup; ///< True, if Free() should not free empty slabs. TBool iAllocatingSlab; ///< True if a new slab page is being allocated. TBitMapAllocator* iSlabMap; ///< Bitmap of allocated slabs. DMemoryObject* iMemory; ///< The memory object used to store slabs. DMemoryMapping* iMapping; ///< The memory mapping used for slabs. TLinAddr iBase; ///< Address of first slab. }; /** Template for a slab allocator which can allocate up to N objects of type T. */ template <class T, TUint N> class RSlabAllocator : public RSlabAllocatorBase { public: enum { EObjectSize = sizeof(T)>sizeof(SDblQueLink) ? sizeof(T) : sizeof(SDblQueLink), EObjectsPerSlab = (KPageSize-sizeof(TSlabHeader))/EObjectSize, EMaxSlabs = (N+EObjectsPerSlab-1)/EObjectsPerSlab }; FORCE_INLINE RSlabAllocator() : RSlabAllocatorBase(EFalse) { __ASSERT_COMPILE(EObjectsPerSlab>0); } FORCE_INLINE TInt Construct() { return RSlabAllocatorBase::Construct(EMaxSlabs,EObjectSize); } /** Allocate an object. @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. */ FORCE_INLINE T* Alloc() { return (T*)RSlabAllocatorBase::Alloc(); } /** Free an object previously allocated with #Alloc. @param aObject Object. */ FORCE_INLINE void Free(T* aObject) { RSlabAllocatorBase::Free(aObject); } }; /** Template for a slab allocator for allocating objects of type T, using the virtual address region [B..E) */ template <class T, TLinAddr B, TLinAddr E> class RStaticSlabAllocator : public RSlabAllocatorBase { public: enum { EObjectSize = sizeof(T)>sizeof(SDblQueLink) ? sizeof(T) : sizeof(SDblQueLink), EObjectsPerSlab = (KPageSize-sizeof(TSlabHeader))/EObjectSize, EMaxSlabs = (E-B)/KPageSize }; FORCE_INLINE RStaticSlabAllocator() : RSlabAllocatorBase(ETrue) { __ASSERT_COMPILE(EObjectsPerSlab>0); } FORCE_INLINE TInt Construct() { return RSlabAllocatorBase::Construct(EMaxSlabs,EObjectSize,B); } /** Allocate an object. @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. */ FORCE_INLINE T* Alloc() { return (T*)RSlabAllocatorBase::Alloc(); } /** Free an object previously allocated with #Alloc. @param aObject Object. */ FORCE_INLINE void Free(T* aObject) { RSlabAllocatorBase::Free(aObject); } }; #endif