|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #ifndef MSLABALLOC_H |
|
22 #define MSLABALLOC_H |
|
23 |
|
24 #include "mcleanup.h" |
|
25 |
|
26 /** |
|
27 Slab allocator. |
|
28 */ |
|
29 class RSlabAllocatorBase |
|
30 { |
|
31 public: |
|
32 RSlabAllocatorBase(TBool aDelayedCleanup); |
|
33 ~RSlabAllocatorBase(); |
|
34 |
|
35 /** |
|
36 Construct a slab allocator. |
|
37 |
|
38 @param aMaxSlabs Maximum number of slabs to use. (Number of bits in \a slabBits.) |
|
39 @param aObjectSize Size of objects to allocate. |
|
40 */ |
|
41 TInt Construct(TUint aMaxSlabs, TUint aObjectSize); |
|
42 |
|
43 /** |
|
44 Construct a slab allocator using fixed virtual memory. |
|
45 |
|
46 @param aMaxSlabs Maximum number of slabs to use. (Number of bits in \a slabBits.) |
|
47 @param aObjectSize Size of objects to allocate. |
|
48 @param aBase Virtual address for start of memory where slabs will be allocated. |
|
49 Zero indicates 'anywhere'. |
|
50 */ |
|
51 TInt Construct(TUint aMaxSlabs, TUint aObjectSize, TLinAddr aBase); |
|
52 |
|
53 /** |
|
54 Set the memory object to be used for the slab allocator. |
|
55 */ |
|
56 FORCE_INLINE void SetMemory(DMemoryObject* aMemory, TUint aReserveCount) |
|
57 { |
|
58 __NK_ASSERT_DEBUG(!iMemory); |
|
59 iMemory = aMemory; |
|
60 iReserveCount = aReserveCount; |
|
61 } |
|
62 |
|
63 /** |
|
64 Allocate an object. |
|
65 |
|
66 @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. |
|
67 |
|
68 @pre MmuLock held |
|
69 @post MmuLock held, but has always beet flashed |
|
70 */ |
|
71 TAny* Alloc(); |
|
72 |
|
73 /** |
|
74 Free an object previously allocated with #Alloc. |
|
75 |
|
76 @param aObject The object. |
|
77 |
|
78 @pre MmuLock held |
|
79 @post MmuLock held, but has always beet flashed |
|
80 */ |
|
81 void Free(TAny* aObject); |
|
82 |
|
83 protected: |
|
84 class TSlabHeader : public SDblQueLink |
|
85 { |
|
86 public: |
|
87 SDblQue iFreeList; ///< List of unallocated objects in list. |
|
88 TUint iAllocCount; ///< Number of objects allocated in this slab. |
|
89 TAny* iHighWaterMark; ///< End of initialise region in slab. |
|
90 }; |
|
91 |
|
92 private: |
|
93 TBool NewSlab(); |
|
94 void InitSlab(TLinAddr aPage); |
|
95 void FreeSlab(TSlabHeader* aSlab); |
|
96 static void CleanupTrampoline(TAny* aSelf); |
|
97 void Cleanup(); |
|
98 #ifdef _DEBUG |
|
99 void CheckSlab(TSlabHeader* aSlab); |
|
100 #endif |
|
101 |
|
102 private: |
|
103 SDblQue iFreeList; ///< List of slabs which have unallocated objects in them. |
|
104 TUint iFreeCount; ///< Number of unallocated objects. |
|
105 TUint iReserveCount; ///< Number of unallocated objects to keep in reserve (to allow for recursion during allocation). |
|
106 TUint iObjectsPerSlab; ///< Number of objects in each slab. |
|
107 TUint iObjectSize; ///< Size, in bytes, of objects to be allocated. |
|
108 TSpinLock iSpinLock; ///< Spinlock which protects iFreeList, iFreeCount and TSlabHeader contents. |
|
109 |
|
110 TMemoryCleanup iCleanup; ///< Used to queue Cleanup() if iDelayedCleanup is true. |
|
111 TBool iDelayedCleanup; ///< True, if Free() should not free empty slabs. |
|
112 |
|
113 TBool iAllocatingSlab; ///< True if a new slab page is being allocated. |
|
114 TBitMapAllocator* iSlabMap; ///< Bitmap of allocated slabs. |
|
115 DMemoryObject* iMemory; ///< The memory object used to store slabs. |
|
116 DMemoryMapping* iMapping; ///< The memory mapping used for slabs. |
|
117 TLinAddr iBase; ///< Address of first slab. |
|
118 }; |
|
119 |
|
120 |
|
121 /** |
|
122 Template for a slab allocator which can allocate up to N objects of type T. |
|
123 */ |
|
124 template <class T, TUint N> |
|
125 class RSlabAllocator : public RSlabAllocatorBase |
|
126 { |
|
127 public: |
|
128 enum |
|
129 { |
|
130 EObjectSize = sizeof(T)>sizeof(SDblQueLink) ? sizeof(T) : sizeof(SDblQueLink), |
|
131 EObjectsPerSlab = (KPageSize-sizeof(TSlabHeader))/EObjectSize, |
|
132 EMaxSlabs = (N+EObjectsPerSlab-1)/EObjectsPerSlab |
|
133 }; |
|
134 |
|
135 FORCE_INLINE RSlabAllocator() |
|
136 : RSlabAllocatorBase(EFalse) |
|
137 { |
|
138 __ASSERT_COMPILE(EObjectsPerSlab>0); |
|
139 } |
|
140 |
|
141 FORCE_INLINE TInt Construct() |
|
142 { |
|
143 return RSlabAllocatorBase::Construct(EMaxSlabs,EObjectSize); |
|
144 } |
|
145 |
|
146 /** |
|
147 Allocate an object. |
|
148 |
|
149 @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. |
|
150 */ |
|
151 FORCE_INLINE T* Alloc() |
|
152 { |
|
153 return (T*)RSlabAllocatorBase::Alloc(); |
|
154 } |
|
155 |
|
156 /** |
|
157 Free an object previously allocated with #Alloc. |
|
158 |
|
159 @param aObject Object. |
|
160 */ |
|
161 FORCE_INLINE void Free(T* aObject) |
|
162 { |
|
163 RSlabAllocatorBase::Free(aObject); |
|
164 } |
|
165 }; |
|
166 |
|
167 |
|
168 /** |
|
169 Template for a slab allocator for allocating objects of type T, using the |
|
170 virtual address region [B..E) |
|
171 */ |
|
172 template <class T, TLinAddr B, TLinAddr E> |
|
173 class RStaticSlabAllocator : public RSlabAllocatorBase |
|
174 { |
|
175 public: |
|
176 enum |
|
177 { |
|
178 EObjectSize = sizeof(T)>sizeof(SDblQueLink) ? sizeof(T) : sizeof(SDblQueLink), |
|
179 EObjectsPerSlab = (KPageSize-sizeof(TSlabHeader))/EObjectSize, |
|
180 EMaxSlabs = (E-B)/KPageSize |
|
181 }; |
|
182 |
|
183 FORCE_INLINE RStaticSlabAllocator() |
|
184 : RSlabAllocatorBase(ETrue) |
|
185 { |
|
186 __ASSERT_COMPILE(EObjectsPerSlab>0); |
|
187 } |
|
188 |
|
189 FORCE_INLINE TInt Construct() |
|
190 { |
|
191 return RSlabAllocatorBase::Construct(EMaxSlabs,EObjectSize,B); |
|
192 } |
|
193 |
|
194 /** |
|
195 Allocate an object. |
|
196 |
|
197 @return Allocated object, or the null pointer if there is insufficient memory to perform the allocation. |
|
198 */ |
|
199 FORCE_INLINE T* Alloc() |
|
200 { |
|
201 return (T*)RSlabAllocatorBase::Alloc(); |
|
202 } |
|
203 |
|
204 /** |
|
205 Free an object previously allocated with #Alloc. |
|
206 |
|
207 @param aObject Object. |
|
208 */ |
|
209 FORCE_INLINE void Free(T* aObject) |
|
210 { |
|
211 RSlabAllocatorBase::Free(aObject); |
|
212 } |
|
213 }; |
|
214 |
|
215 #endif |
|
216 |