sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalComponent sl@0: */ sl@0: sl@0: #ifndef MSLABALLOC_H sl@0: #define MSLABALLOC_H sl@0: sl@0: #include "mcleanup.h" sl@0: sl@0: /** sl@0: Slab allocator. sl@0: */ sl@0: class RSlabAllocatorBase sl@0: { sl@0: public: sl@0: RSlabAllocatorBase(TBool aDelayedCleanup); sl@0: ~RSlabAllocatorBase(); sl@0: sl@0: /** sl@0: Construct a slab allocator. sl@0: sl@0: @param aMaxSlabs Maximum number of slabs to use. (Number of bits in \a slabBits.) sl@0: @param aObjectSize Size of objects to allocate. sl@0: */ sl@0: TInt Construct(TUint aMaxSlabs, TUint aObjectSize); sl@0: sl@0: /** sl@0: Construct a slab allocator using fixed virtual memory. sl@0: sl@0: @param aMaxSlabs Maximum number of slabs to use. (Number of bits in \a slabBits.) sl@0: @param aObjectSize Size of objects to allocate. sl@0: @param aBase Virtual address for start of memory where slabs will be allocated. sl@0: Zero indicates 'anywhere'. sl@0: */ sl@0: TInt Construct(TUint aMaxSlabs, TUint aObjectSize, TLinAddr aBase); sl@0: sl@0: /** sl@0: Set the memory object to be used for the slab allocator. sl@0: */ sl@0: FORCE_INLINE void SetMemory(DMemoryObject* aMemory, TUint aReserveCount) sl@0: { sl@0: __NK_ASSERT_DEBUG(!iMemory); sl@0: iMemory = aMemory; sl@0: iReserveCount = aReserveCount; sl@0: } sl@0: sl@0: /** sl@0: Allocate an object. sl@0: sl@0: @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. sl@0: sl@0: @pre MmuLock held sl@0: @post MmuLock held, but has always beet flashed sl@0: */ sl@0: TAny* Alloc(); sl@0: sl@0: /** sl@0: Free an object previously allocated with #Alloc. sl@0: sl@0: @param aObject The object. sl@0: sl@0: @pre MmuLock held sl@0: @post MmuLock held, but has always beet flashed sl@0: */ sl@0: void Free(TAny* aObject); sl@0: sl@0: protected: sl@0: class TSlabHeader : public SDblQueLink sl@0: { sl@0: public: sl@0: SDblQue iFreeList; ///< List of unallocated objects in list. sl@0: TUint iAllocCount; ///< Number of objects allocated in this slab. sl@0: TAny* iHighWaterMark; ///< End of initialise region in slab. sl@0: }; sl@0: sl@0: private: sl@0: TBool NewSlab(); sl@0: void InitSlab(TLinAddr aPage); sl@0: void FreeSlab(TSlabHeader* aSlab); sl@0: static void CleanupTrampoline(TAny* aSelf); sl@0: void Cleanup(); sl@0: #ifdef _DEBUG sl@0: void CheckSlab(TSlabHeader* aSlab); sl@0: #endif sl@0: sl@0: private: sl@0: SDblQue iFreeList; ///< List of slabs which have unallocated objects in them. sl@0: TUint iFreeCount; ///< Number of unallocated objects. sl@0: TUint iReserveCount; ///< Number of unallocated objects to keep in reserve (to allow for recursion during allocation). sl@0: TUint iObjectsPerSlab; ///< Number of objects in each slab. sl@0: TUint iObjectSize; ///< Size, in bytes, of objects to be allocated. sl@0: TSpinLock iSpinLock; ///< Spinlock which protects iFreeList, iFreeCount and TSlabHeader contents. sl@0: sl@0: TMemoryCleanup iCleanup; ///< Used to queue Cleanup() if iDelayedCleanup is true. sl@0: TBool iDelayedCleanup; ///< True, if Free() should not free empty slabs. sl@0: sl@0: TBool iAllocatingSlab; ///< True if a new slab page is being allocated. sl@0: TBitMapAllocator* iSlabMap; ///< Bitmap of allocated slabs. sl@0: DMemoryObject* iMemory; ///< The memory object used to store slabs. sl@0: DMemoryMapping* iMapping; ///< The memory mapping used for slabs. sl@0: TLinAddr iBase; ///< Address of first slab. sl@0: }; sl@0: sl@0: sl@0: /** sl@0: Template for a slab allocator which can allocate up to N objects of type T. sl@0: */ sl@0: template sl@0: class RSlabAllocator : public RSlabAllocatorBase sl@0: { sl@0: public: sl@0: enum sl@0: { sl@0: EObjectSize = sizeof(T)>sizeof(SDblQueLink) ? sizeof(T) : sizeof(SDblQueLink), sl@0: EObjectsPerSlab = (KPageSize-sizeof(TSlabHeader))/EObjectSize, sl@0: EMaxSlabs = (N+EObjectsPerSlab-1)/EObjectsPerSlab sl@0: }; sl@0: sl@0: FORCE_INLINE RSlabAllocator() sl@0: : RSlabAllocatorBase(EFalse) sl@0: { sl@0: __ASSERT_COMPILE(EObjectsPerSlab>0); sl@0: } sl@0: sl@0: FORCE_INLINE TInt Construct() sl@0: { sl@0: return RSlabAllocatorBase::Construct(EMaxSlabs,EObjectSize); sl@0: } sl@0: sl@0: /** sl@0: Allocate an object. sl@0: sl@0: @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. sl@0: */ sl@0: FORCE_INLINE T* Alloc() sl@0: { sl@0: return (T*)RSlabAllocatorBase::Alloc(); sl@0: } sl@0: sl@0: /** sl@0: Free an object previously allocated with #Alloc. sl@0: sl@0: @param aObject Object. sl@0: */ sl@0: FORCE_INLINE void Free(T* aObject) sl@0: { sl@0: RSlabAllocatorBase::Free(aObject); sl@0: } sl@0: }; sl@0: sl@0: sl@0: /** sl@0: Template for a slab allocator for allocating objects of type T, using the sl@0: virtual address region [B..E) sl@0: */ sl@0: template sl@0: class RStaticSlabAllocator : public RSlabAllocatorBase sl@0: { sl@0: public: sl@0: enum sl@0: { sl@0: EObjectSize = sizeof(T)>sizeof(SDblQueLink) ? sizeof(T) : sizeof(SDblQueLink), sl@0: EObjectsPerSlab = (KPageSize-sizeof(TSlabHeader))/EObjectSize, sl@0: EMaxSlabs = (E-B)/KPageSize sl@0: }; sl@0: sl@0: FORCE_INLINE RStaticSlabAllocator() sl@0: : RSlabAllocatorBase(ETrue) sl@0: { sl@0: __ASSERT_COMPILE(EObjectsPerSlab>0); sl@0: } sl@0: sl@0: FORCE_INLINE TInt Construct() sl@0: { sl@0: return RSlabAllocatorBase::Construct(EMaxSlabs,EObjectSize,B); sl@0: } sl@0: sl@0: /** sl@0: Allocate an object. sl@0: sl@0: @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. sl@0: */ sl@0: FORCE_INLINE T* Alloc() sl@0: { sl@0: return (T*)RSlabAllocatorBase::Alloc(); sl@0: } sl@0: sl@0: /** sl@0: Free an object previously allocated with #Alloc. sl@0: sl@0: @param aObject Object. sl@0: */ sl@0: FORCE_INLINE void Free(T* aObject) sl@0: { sl@0: RSlabAllocatorBase::Free(aObject); sl@0: } sl@0: }; sl@0: sl@0: #endif sl@0: