--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mslaballoc.h Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,216 @@
+// 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
+