|
1 // Copyright (c) 2008-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 // f32\sfile\sf_memory_man.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalTechnology |
|
21 */ |
|
22 |
|
23 |
|
24 #include <e32std.h> |
|
25 #include <e32std_private.h> |
|
26 #include "sf_std.h" |
|
27 #include <e32uid.h> |
|
28 #include <e32wins.h> |
|
29 #include <f32file.h> |
|
30 #include <hal.h> |
|
31 #include "sf_memory_man.h" |
|
32 #include "sf_memory_client.h" |
|
33 |
|
34 /** |
|
35 Destructor of the CCacheMemoryManager, need to destroy all registered clients. |
|
36 */ |
|
37 CCacheMemoryManager::~CCacheMemoryManager() |
|
38 { |
|
39 for (TInt i = 0; i < iRegisteredClients.Count(); i++) |
|
40 { |
|
41 iRegisteredClients[i]->Reset(); |
|
42 delete iRegisteredClients[i]; |
|
43 } |
|
44 iRegisteredClients.Close(); |
|
45 } |
|
46 |
|
47 /** |
|
48 Static factory function of CCacheMemoryManager |
|
49 @param aCacheSize the total size of the virtual address space |
|
50 */ |
|
51 CCacheMemoryManager* CCacheMemoryManager::NewL(TInt aCacheSize) |
|
52 { |
|
53 CCacheMemoryManager* cacheMemoryManager = new (ELeave) CCacheMemoryManager(aCacheSize); |
|
54 |
|
55 CleanupStack::PushL(cacheMemoryManager); |
|
56 cacheMemoryManager->ConstructL(); |
|
57 CleanupStack::Pop(1, cacheMemoryManager); |
|
58 |
|
59 return cacheMemoryManager; |
|
60 } |
|
61 |
|
62 /** |
|
63 Constructor of CCacheMemoryManager |
|
64 @param aMaxSize the total size of the virtual address space |
|
65 */ |
|
66 CCacheMemoryManager::CCacheMemoryManager(TUint32 aMaxSize) |
|
67 :iBase(NULL), |
|
68 iSizeInBytes(aMaxSize), |
|
69 iCurrentOffsetMark(0) |
|
70 { |
|
71 } |
|
72 |
|
73 /** |
|
74 Second phase constructor of CCacheMemoryManager. |
|
75 Creates RChunk object and sets low memory threshold. |
|
76 */ |
|
77 void CCacheMemoryManager::ConstructL() |
|
78 { |
|
79 // calculate the low-memory threshold below which we fail any attempt to allocate memory |
|
80 TMemoryInfoV1Buf meminfo; |
|
81 TInt r = UserHal::MemoryInfo(meminfo); |
|
82 ASSERT(r==KErrNone); |
|
83 User::LeaveIfError(r); |
|
84 iLowMemoryThreshold = (meminfo().iTotalRamInBytes * TGlobalCacheMemorySettings::LowMemoryThreshold()) / 100; |
|
85 TChunkCreateInfo createInfo; |
|
86 createInfo.SetCache(iSizeInBytes); |
|
87 createInfo.SetOwner(EOwnerProcess); |
|
88 r = iChunk.Create(createInfo); |
|
89 ASSERT(r==KErrNone); |
|
90 User::LeaveIfError(r); |
|
91 UserSvr::RegisterTrustedChunk(iChunk.Handle()); |
|
92 iBase = iChunk.Base(); |
|
93 iRegisteredClients.ReserveL(10); |
|
94 __PRINT3(_L("CCacheMemoryManager::ConstructL(lowMem=%d, iSize=%d, base=0x%lx)"), iLowMemoryThreshold, iSizeInBytes, iBase); |
|
95 } |
|
96 |
|
97 /** |
|
98 Connect or register a client. |
|
99 Note: callers of this function should be constructor of various caches, it is their resposibility |
|
100 to make sure that parameters are sensible when calling this function |
|
101 |
|
102 @internalTechnology |
|
103 @released |
|
104 |
|
105 @param aClientName an identifier of the client to be connected |
|
106 @param aMinSizeInSegs minimum client size in segments |
|
107 @param aMaxSizeInSegs maximum client size in segments |
|
108 @return CCacheMemoryClient* pointer to the client that connected, or NULL if parameters are not valid. |
|
109 @leave if no memory |
|
110 */ |
|
111 EXPORT_C CCacheMemoryClient* CCacheMemoryManager::ConnectClientL(const TDesC& aClientName, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs) |
|
112 { |
|
113 __PRINT3(_L("CCacheMemoryManager::ConnectClientL: [%S], minSeg=%d, maxSeg=%d"), &aClientName, aMinSizeInSegs, aMaxSizeInSegs); |
|
114 for (TInt i = 0; i < iRegisteredClients.Count(); i++) |
|
115 { |
|
116 if (aClientName.Compare(iRegisteredClients[i]->Name()) == 0) |
|
117 { |
|
118 ASSERT(iRegisteredClients[i]->iTouchedRegionFlag == 0); |
|
119 __PRINT1(_L("CCacheMemoryManager::ConnectClientL: [%S] found!"), &aClientName); |
|
120 return iRegisteredClients[i]; |
|
121 } |
|
122 } |
|
123 |
|
124 // parameter validation |
|
125 ASSERT(iSizeInBytes > iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2())); |
|
126 if (iSizeInBytes < iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2())) |
|
127 { |
|
128 ASSERT(0); |
|
129 return NULL; |
|
130 } |
|
131 |
|
132 // if not found in registered clients, creates new |
|
133 // this may leave under OOM condition |
|
134 CCacheMemoryClient* client = CCacheMemoryClient::NewL(*this, aClientName, iCurrentOffsetMark, aMinSizeInSegs, aMaxSizeInSegs); |
|
135 |
|
136 // if error happens during client registration, the client will be deleted |
|
137 // this may leave under OOM condition |
|
138 TInt err = iRegisteredClients.Append(client); |
|
139 if (err != KErrNone) |
|
140 { |
|
141 ASSERT(0); |
|
142 delete client; |
|
143 client = NULL; |
|
144 User::Leave(err); |
|
145 } |
|
146 |
|
147 // record current offset mark for next client |
|
148 iCurrentOffsetMark += (aMaxSizeInSegs << SegmentSizeInBytesLog2()); |
|
149 return client; |
|
150 } |
|
151 |
|
152 /** |
|
153 Commit a contiguous set of segments. |
|
154 @param aStartRamAddr the start ram address of the region to be committed. |
|
155 @param aSegmentCount the segment number of the contiguous region to be committed. |
|
156 @return TInt KErrNone if succeeded, KErrNoMemory if passed low memory threshold, otherwise a system-wide error code. |
|
157 */ |
|
158 TInt CCacheMemoryManager::AllocateAndLockSegments(TUint8* aStartRamAddr, TInt aSegmentCount) |
|
159 { |
|
160 __PRINT2(_L("CCacheMemoryManager::AllocateAndLockSegments: base=0x%x, seg=%d"), aStartRamAddr, aSegmentCount); |
|
161 TMemoryInfoV1Buf meminfo; |
|
162 TInt r = UserHal::MemoryInfo(meminfo); |
|
163 __ASSERT_DEBUG(r==KErrNone,Fault(EMemoryInfoFailed)); |
|
164 if (r != KErrNone) |
|
165 { |
|
166 return r; |
|
167 } |
|
168 |
|
169 if (isMemoryLow || (meminfo().iFreeRamInBytes < iLowMemoryThreshold)) |
|
170 { |
|
171 __PRINT(_L("CCacheMemoryManager: free RAM below threshold !!!")); |
|
172 return KErrNoMemory; |
|
173 } |
|
174 return Commit(aStartRamAddr, aSegmentCount); |
|
175 } |
|
176 |
|
177 /** |
|
178 Notify the change of memory status |
|
179 @param aIsMemoryLow the flag that sets current memory status |
|
180 */ |
|
181 void CCacheMemoryManager::FreeMemoryChanged(TBool aIsMemoryLow) |
|
182 { |
|
183 isMemoryLow = aIsMemoryLow; |
|
184 } |
|
185 |
|
186 /** |
|
187 Decommit a contiguous set of segments. |
|
188 @param aStartRamAddr the start ram address of the region to be decommitted. |
|
189 @param aSegmentCount the segment number of the contiguous region to be decommitted. |
|
190 @return TInt KErrNone if succeeded, otherwise a system-wide error code. |
|
191 */ |
|
192 TInt CCacheMemoryManager::DecommitSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount) |
|
193 { |
|
194 return Decommit(aStartRamAddr, aSegmentCount); |
|
195 } |
|
196 |
|
197 /** |
|
198 Lock a contiguous set of segments. |
|
199 @param aStartRamAddr the start ram address of the region to be locked. |
|
200 @param aSegmentCount the segment number of the contiguous region to be locked. |
|
201 @return TInt KErrNone if succeeded, otherwise a system-wide error code. |
|
202 */ |
|
203 TInt CCacheMemoryManager::LockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount) |
|
204 { |
|
205 return Lock(aStartRamAddr, aSegmentCount); |
|
206 } |
|
207 |
|
208 /** |
|
209 Unlock a contiguous set of segments. |
|
210 @param aStartRamAddr the start ram address of the region to be unlocked. |
|
211 @param aSegmentCount the segment number of the contiguous region to be unlocked. |
|
212 @return TInt KErrNone if succeeded, otherwise a system-wide error code. |
|
213 */ |
|
214 TInt CCacheMemoryManager::UnlockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount) |
|
215 { |
|
216 return Unlock(aStartRamAddr, aSegmentCount); |
|
217 } |
|
218 |
|
219 /** |
|
220 Commit a contiguous set of segments. |
|
221 @param aStartRamAddr the start ram address of the region to be committed. |
|
222 @param aSegmentCount the segment number of the contiguous region to be committed. |
|
223 @return TInt KErrNone if succeeded, otherwise a system-wide error code. |
|
224 */ |
|
225 TInt CCacheMemoryManager::Commit(TUint8* aStartRamAddr, TInt aSegmentCount) |
|
226 { |
|
227 TInt offset = aStartRamAddr - iBase; |
|
228 TInt r = iChunk.Commit(offset, aSegmentCount << KSegmentSizeLog2); |
|
229 return r; |
|
230 } |
|
231 |
|
232 /** |
|
233 Actual implementation of DecommitSegments(). |
|
234 @see CCacheMemoryManager::DecommitSegments(). |
|
235 */ |
|
236 TInt CCacheMemoryManager::Decommit(TUint8* aStartRamAddr, TInt aSegmentCount) |
|
237 { |
|
238 return iChunk.Decommit(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2); |
|
239 } |
|
240 |
|
241 /** |
|
242 Actual implementation of UnlockSegments(). |
|
243 @see CCacheMemoryManager::UnlockSegments(). |
|
244 */ |
|
245 TInt CCacheMemoryManager::Unlock(TUint8* aStartRamAddr, TInt aSegmentCount) |
|
246 { |
|
247 TInt r = iChunk.Unlock(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2); |
|
248 return r; |
|
249 } |
|
250 |
|
251 /** |
|
252 Actual implementation of LockSegments(). |
|
253 @see CCacheMemoryManager::LockSegments(). |
|
254 */ |
|
255 TInt CCacheMemoryManager::Lock(TUint8* aStartRamAddr, TInt aSegmentCount) |
|
256 { |
|
257 return iChunk.Lock(aStartRamAddr - iBase, aSegmentCount << KSegmentSizeLog2); |
|
258 } |
|
259 |
|
260 |
|
261 //===================================================================== |
|
262 TUint8* CCacheMemoryManager::Base() |
|
263 { |
|
264 return iChunk.Base(); |
|
265 } |
|
266 |
|
267 /** |
|
268 Get function, returns log2 value of a segment size in bytes. |
|
269 |
|
270 @internalTechnology |
|
271 @released |
|
272 */ |
|
273 EXPORT_C TUint CCacheMemoryManager::SegmentSizeInBytesLog2() const |
|
274 { |
|
275 return KSegmentSizeLog2; |
|
276 } |
|
277 |
|
278 |
|
279 //============================================================================= |
|
280 /** |
|
281 The singleton of global cache memory manager |
|
282 */ |
|
283 CCacheMemoryManager* CCacheMemoryManagerFactory::iCacheMemoryManager = NULL; |
|
284 |
|
285 /** |
|
286 Global factory function of CCacheMemoryManager. |
|
287 */ |
|
288 void CCacheMemoryManagerFactory::CreateL() |
|
289 { |
|
290 iCacheMemoryManager = CCacheMemoryManager::NewL(TGlobalCacheMemorySettings::CacheSize()); |
|
291 } |
|
292 |
|
293 /** |
|
294 Global get function of CCacheMemoryManager. |
|
295 |
|
296 @internalTechnology |
|
297 @released |
|
298 */ |
|
299 EXPORT_C CCacheMemoryManager* CCacheMemoryManagerFactory::CacheMemoryManager() |
|
300 { |
|
301 return iCacheMemoryManager; |
|
302 } |
|
303 |
|
304 /** |
|
305 Global destroy function of CCacheMemoryManager. |
|
306 */ |
|
307 void CCacheMemoryManagerFactory::Destroy() |
|
308 { |
|
309 delete iCacheMemoryManager; |
|
310 iCacheMemoryManager = NULL; |
|
311 } |
|
312 |
|
313 //============================================================================= |
|
314 const TInt KByteToByteShift = 10; |
|
315 TInt32 TGlobalCacheMemorySettings::iCacheSizeInBytes = KDefaultGlobalCacheMemorySize << KByteToByteShift; |
|
316 TInt32 TGlobalCacheMemorySettings::iLowMemoryThreshold = KDefaultLowMemoryThreshold; |
|
317 _LIT8(KLitSectionNameCacheMemory,"CacheMemory"); |
|
318 |
|
319 /** |
|
320 Read ESTART.TXT file for global cache memory settings |
|
321 */ |
|
322 void TGlobalCacheMemorySettings::ReadPropertiesFile() |
|
323 { |
|
324 // Get size of cache in kilobytes |
|
325 TInt32 cacheSizeInKBytes; |
|
326 if (F32Properties::GetInt(KLitSectionNameCacheMemory, _L8("GlobalCacheMemorySize"), cacheSizeInKBytes)) |
|
327 { |
|
328 iCacheSizeInBytes = cacheSizeInKBytes << KByteToByteShift; |
|
329 } |
|
330 |
|
331 // Get low memory threshold |
|
332 TInt32 lowMemoryThreshold; |
|
333 if (F32Properties::GetInt(KLitSectionNameCacheMemory, _L8("LowMemoryThreshold"), lowMemoryThreshold)) |
|
334 iLowMemoryThreshold = lowMemoryThreshold; |
|
335 } |
|
336 |
|
337 TInt TGlobalCacheMemorySettings::CacheSize() |
|
338 { |
|
339 return iCacheSizeInBytes; |
|
340 } |
|
341 |
|
342 TInt TGlobalCacheMemorySettings::LowMemoryThreshold() |
|
343 { |
|
344 return iLowMemoryThreshold; |
|
345 } |
|
346 |
|
347 |