15 * |
15 * |
16 * |
16 * |
17 */ |
17 */ |
18 |
18 |
19 #include "common.h" |
19 #include "common.h" |
20 #include "StopScheduler.h" |
|
21 #include <hal.h> |
|
22 |
20 |
23 #ifdef TRACE_CHUNK_USAGE |
21 #ifdef TRACE_CHUNK_USAGE |
24 void TraceChunkUsage(TInt aChunkHandle, TUint8* aBase, TInt aChunkSize) |
22 void TraceChunkUsage(TInt aChunkHandle, TUint8* aBase, TInt aChunkSize) |
25 { |
23 { |
26 RDebug::Print(_L("MEM: c,%d,%d,%d"), aChunkHandle, aBase, aChunkSize); |
24 RDebug::Print(_L("MEM: c,%d,%d,%d"), aChunkHandle, aBase, aChunkSize); |
30 #endif |
28 #endif |
31 |
29 |
32 #ifdef __NEW_ALLOCATOR__ |
30 #ifdef __NEW_ALLOCATOR__ |
33 |
31 |
34 #include "MemoryLogger.h" |
32 #include "MemoryLogger.h" |
35 #include "SymbianDLHeap.h" |
33 #include "SymbianDlHeap.h" |
36 |
34 |
37 _LIT(KDLHeapPanicCategory, "DL Heap"); |
35 _LIT(KDLHeapPanicCategory, "DL Heap"); |
38 #define GET_PAGE_SIZE(x) UserHal::PageSizeInBytes(x) |
36 #define GET_PAGE_SIZE(x) UserHal::PageSizeInBytes(x) |
39 #define __CHECK_CELL(p) |
37 #define __CHECK_CELL(p) |
40 #define __POWER_OF_2(x) ((TUint32)((x)^((x)-1))>=(TUint32)(x)) |
38 #define __POWER_OF_2(x) ((TUint32)((x)^((x)-1))>=(TUint32)(x)) |
263 { |
261 { |
264 iAlign = 4; |
262 iAlign = 4; |
265 } |
263 } |
266 iPageSize = 0; |
264 iPageSize = 0; |
267 iFlags = aSingleThread ? (ESingleThreaded|EFixedSize) : EFixedSize; |
265 iFlags = aSingleThread ? (ESingleThreaded|EFixedSize) : EFixedSize; |
268 isLowSystemMemory = 0; |
|
269 |
266 |
270 Init(0, 0, 0); |
267 Init(0, 0, 0); |
271 } |
268 } |
272 |
269 |
273 UEXPORT_C RSymbianDLHeap::RSymbianDLHeap(TInt aChunkHandle, TInt aOffset, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, |
270 UEXPORT_C RSymbianDLHeap::RSymbianDLHeap(TInt aChunkHandle, TInt aOffset, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, |
274 TInt aAlign, TBool aSingleThread) |
271 TInt aAlign, TBool aSingleThread) |
275 : iMinLength(aMinLength), iMaxLength(aMaxLength), iOffset(aOffset), iChunkHandle(aChunkHandle), |
272 : iMinLength(aMinLength), iMaxLength(aMaxLength), iOffset(aOffset), iChunkHandle(aChunkHandle), iNestingLevel(0), iAllocCount(0), |
276 iAlign(aAlign), iNestingLevel(0), iAllocCount(0), iFailType(ENone), iTestData(NULL), iChunkSize(aMinLength) |
273 iAlign(aAlign),iFailType(ENone), iTestData(NULL), iChunkSize(aMinLength) |
277 { |
274 { |
278 // TODO: Locked the page size to 4 KB - change this to pick up from the OS |
275 // TODO: Locked the page size to 4 KB - change this to pick up from the OS |
279 GET_PAGE_SIZE(iPageSize); |
276 GET_PAGE_SIZE(iPageSize); |
280 __ASSERT_ALWAYS(aOffset >=0, User::Panic(KDLHeapPanicCategory, ETHeapNewBadOffset)); |
277 __ASSERT_ALWAYS(aOffset >=0, User::Panic(KDLHeapPanicCategory, ETHeapNewBadOffset)); |
281 iGrowBy = _ALIGN_UP(aGrowBy, iPageSize); |
278 iGrowBy = _ALIGN_UP(aGrowBy, iPageSize); |
282 iFlags = aSingleThread ? ESingleThreaded : 0; |
279 iFlags = aSingleThread ? ESingleThreaded : 0; |
283 isLowSystemMemory = 0; |
|
284 |
280 |
285 // Initialise |
281 // Initialise |
286 // if the heap is created with aMinLength==aMaxLength then it cannot allocate slab or page memory |
282 // if the heap is created with aMinLength==aMaxLength then it cannot allocate slab or page memory |
287 // so these sub-allocators should be disabled. Otherwise initialise with default values |
283 // so these sub-allocators should be disabled. Otherwise initialise with default values |
288 if (aMinLength == aMaxLength) |
284 if (aMinLength == aMaxLength) |
705 insert_chunk(m, r, rsize, 0); |
701 insert_chunk(m, r, rsize, 0); |
706 } |
702 } |
707 return chunk2mem(v); |
703 return chunk2mem(v); |
708 } |
704 } |
709 } |
705 } |
710 //CORRUPTION_ERROR_ACTION(m); |
706 CORRUPTION_ERROR_ACTION(m); |
711 //return 0; |
707 return 0; |
712 } |
708 } |
713 |
709 |
714 inline void RSymbianDLHeap::init_top(mstate m, mchunkptr p, size_t psize) |
710 inline void RSymbianDLHeap::init_top(mstate m, mchunkptr p, size_t psize) |
715 { |
711 { |
716 /* Ensure alignment */ |
712 /* Ensure alignment */ |
797 internal_free(m, oldmem); |
793 internal_free(m, oldmem); |
798 } |
794 } |
799 return newmem; |
795 return newmem; |
800 } |
796 } |
801 } |
797 } |
802 //return 0; |
798 return 0; |
803 } |
799 } |
804 /* ----------------------------- statistics ------------------------------ */ |
800 /* ----------------------------- statistics ------------------------------ */ |
805 mallinfo RSymbianDLHeap::internal_mallinfo(mstate m) { |
801 mallinfo RSymbianDLHeap::internal_mallinfo(mstate m) { |
806 struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
802 struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
807 TInt chunkCnt = 0; |
803 TInt chunkCnt = 0; |
810 if (is_initialized(m)) { |
806 if (is_initialized(m)) { |
811 size_t nfree = SIZE_T_ONE; /* top always free */ |
807 size_t nfree = SIZE_T_ONE; /* top always free */ |
812 size_t mfree = m->topsize + TOP_FOOT_SIZE; |
808 size_t mfree = m->topsize + TOP_FOOT_SIZE; |
813 size_t sum = mfree; |
809 size_t sum = mfree; |
814 msegmentptr s = &m->seg; |
810 msegmentptr s = &m->seg; |
815 // TInt tmp = (TUint8*)m->top - (TUint8*)s->base; |
811 TInt tmp = (TUint8*)m->top - (TUint8*)s->base; |
816 while (s != 0) { |
812 while (s != 0) { |
817 mchunkptr q = align_as_chunk(s->base); |
813 mchunkptr q = align_as_chunk(s->base); |
818 chunkCnt++; |
814 chunkCnt++; |
819 while (segment_holds(s, q) && |
815 while (segment_holds(s, q) && |
820 q != m->top && q->head != FENCEPOST_HEAD) { |
816 q != m->top && q->head != FENCEPOST_HEAD) { |
842 return nm; |
838 return nm; |
843 } |
839 } |
844 |
840 |
845 void RSymbianDLHeap::internal_malloc_stats(mstate m) { |
841 void RSymbianDLHeap::internal_malloc_stats(mstate m) { |
846 if (!PREACTION(m)) { |
842 if (!PREACTION(m)) { |
|
843 size_t maxfp = 0; |
847 size_t fp = 0; |
844 size_t fp = 0; |
848 size_t used = 0; |
845 size_t used = 0; |
849 check_malloc_state(m); |
846 check_malloc_state(m); |
850 if (is_initialized(m)) { |
847 if (is_initialized(m)) { |
851 msegmentptr s = &m->seg; |
848 msegmentptr s = &m->seg; |
|
849 maxfp = m->max_footprint; |
852 fp = m->footprint; |
850 fp = m->footprint; |
853 used = fp - (m->topsize + TOP_FOOT_SIZE); |
851 used = fp - (m->topsize + TOP_FOOT_SIZE); |
854 |
852 |
855 while (s != 0) { |
853 while (s != 0) { |
856 mchunkptr q = align_as_chunk(s->base); |
854 mchunkptr q = align_as_chunk(s->base); |
1827 } |
1825 } |
1828 } |
1826 } |
1829 else |
1827 else |
1830 { |
1828 { |
1831 size_t nsize = chunksize(next); |
1829 size_t nsize = chunksize(next); |
1832 //int next_chunk_unmapped = 0; |
1830 int next_chunk_unmapped = 0; |
1833 if( page_not_in_memory(next, nsize) ) { |
1831 if( page_not_in_memory(next, nsize) ) { |
1834 // next_chunk_unmapped = 1; |
1832 next_chunk_unmapped = 1; |
1835 unmapped_pages += ((tchunkptr)next)->npages; |
1833 unmapped_pages += ((tchunkptr)next)->npages; |
1836 } |
1834 } |
1837 |
1835 |
1838 psize += nsize; |
1836 psize += nsize; |
1839 unlink_chunk(fm, next, nsize); |
1837 unlink_chunk(fm, next, nsize); |
2298 // allocate pages in the chunk |
2296 // allocate pages in the chunk |
2299 // if p is NULL, find an allocate the required number of pages (which must lie in the lower half) |
2297 // if p is NULL, find an allocate the required number of pages (which must lie in the lower half) |
2300 // otherwise commit the pages specified |
2298 // otherwise commit the pages specified |
2301 // |
2299 // |
2302 { |
2300 { |
2303 // Check for min threshold in system RAM to be left free |
2301 ASSERT(p == floor(p, pagesize)); |
2304 TInt sysFreeRAM = 0; |
2302 ASSERT(sz == ceiling(sz, pagesize)); |
2305 if(HAL::Get(HALData::EMemoryRAMFree, sysFreeRAM) == KErrNone) |
2303 ASSERT(sz > 0); |
2306 { |
|
2307 if(sysFreeRAM < KStopThreshold) // 1MB |
|
2308 return 0; |
|
2309 |
|
2310 // check system memory level |
|
2311 if(sysFreeRAM < KGoodMemoryThreshold) |
|
2312 isLowSystemMemory = 1; |
|
2313 else |
|
2314 isLowSystemMemory = 0; |
|
2315 } |
|
2316 |
|
2317 |
|
2318 ASSERT(p == floor(p, pagesize)); |
|
2319 ASSERT(sz == ceiling(sz, pagesize)); |
|
2320 ASSERT(sz > 0); |
|
2321 |
2304 |
2322 if (iChunkSize + sz > iMaxLength) |
2305 if (iChunkSize + sz > iMaxLength) |
2323 return 0; |
2306 return 0; |
2324 |
2307 |
2325 RChunk chunk; |
2308 RChunk chunk; |
2359 { // grow, try and do this in place first |
2342 { // grow, try and do this in place first |
2360 if (!map(offset(p, oldsz), sz-oldsz)) |
2343 if (!map(offset(p, oldsz), sz-oldsz)) |
2361 { |
2344 { |
2362 // need to allocate-copy-free |
2345 // need to allocate-copy-free |
2363 void* newp = map(0, sz); |
2346 void* newp = map(0, sz); |
2364 if(newp) |
2347 memcpy(newp, p, oldsz); |
2365 { |
2348 unmap(p,oldsz); |
2366 memcpy(newp, p, oldsz); |
2349 return newp; |
2367 unmap(p,oldsz); |
|
2368 return newp; |
|
2369 } |
|
2370 else |
|
2371 { |
|
2372 return 0; |
|
2373 } |
|
2374 } |
2350 } |
2375 } |
2351 } |
2376 return p; |
2352 return p; |
2377 } |
2353 } |
2378 |
2354 |