111 { |
106 { |
112 TUint iMinLength; |
107 TUint iMinLength; |
113 RChunk iChunk; |
108 RChunk iChunk; |
114 TUint8 *iBase; |
109 TUint8 *iBase; |
115 TUint8 *iTop; |
110 TUint8 *iTop; |
116 //RHeap::SCell iFree; |
111 RHeap::SCell iFree; |
117 }; |
112 }; |
118 |
113 |
119 #pragma warning ( disable :4705 ) // statement has no effect |
114 #pragma warning ( disable :4705 ) // statement has no effect |
120 RHeapDump OrigDump; |
115 RHeapDump OrigDump; |
121 #pragma warning ( default :4705 ) |
116 #pragma warning ( default :4705 ) |
122 |
117 |
123 #if defined(_DEBUG) |
118 #if defined(_DEBUG) |
124 void RTestHeap::__DbgTest(void* aPtr) const |
119 void RTestHeap::__DbgTest(void* aPtr) const |
125 { |
120 { |
126 (void) aPtr; |
|
127 /* |
|
128 RHeapDump& d = *(RHeapDump*)aPtr; |
121 RHeapDump& d = *(RHeapDump*)aPtr; |
129 d.iMinLength=iMinLength; |
122 d.iMinLength=iMinLength; |
130 d.iChunk.SetHandle(iChunkHandle); |
123 d.iChunk.SetHandle(iChunkHandle); |
131 d.iBase=iBase; |
124 d.iBase=iBase; |
132 d.iTop=iTop; |
125 d.iTop=iTop; |
133 d.iFree=iFree; |
126 d.iFree=iFree; |
134 */ |
|
135 } |
127 } |
136 #endif |
128 #endif |
137 |
129 |
138 |
130 |
139 #if defined(_DEBUG) |
131 #if defined(_DEBUG) |
140 TBool Invariant(RHeap* aHeap) |
132 TBool Invariant(RHeap* aHeap) |
141 { |
133 { |
142 (void) aHeap; |
|
143 /* |
|
144 RHeapDump dump; |
134 RHeapDump dump; |
145 ((RTestHeap*)aHeap)->__DbgTest(&dump); |
135 ((RTestHeap*)aHeap)->__DbgTest(&dump); |
146 if(dump.iMinLength!=OrigDump.iMinLength) return(EFalse); |
136 if(dump.iMinLength!=OrigDump.iMinLength) return(EFalse); |
147 // Note: iChunk is a class |
137 // Note: iChunk is a class |
148 if(dump.iBase!=OrigDump.iBase) return(EFalse); |
138 if(dump.iBase!=OrigDump.iBase) return(EFalse); |
149 if(*dump.iBase!=*OrigDump.iBase) return(EFalse); |
139 if(*dump.iBase!=*OrigDump.iBase) return(EFalse); |
150 if(dump.iTop!=OrigDump.iTop) return(EFalse); |
140 if(dump.iTop!=OrigDump.iTop) return(EFalse); |
151 if(dump.iTop[-1]!=OrigDump.iTop[-1]) return(EFalse); |
141 if(dump.iTop[-1]!=OrigDump.iTop[-1]) return(EFalse); |
152 if(dump.iFree.len!=OrigDump.iFree.len) return(EFalse); |
142 if(dump.iFree.len!=OrigDump.iFree.len) return(EFalse); |
153 // iFree.Next changes during allocation/freeing etc. |
143 // iFree.Next changes during allocation/freeing etc. |
154 */ |
|
155 return(ETrue); |
144 return(ETrue); |
156 } |
145 } |
157 #define INV(x) x; |
146 #define INV(x) x; |
158 #else |
147 #else |
159 #define INV(x) |
148 #define INV(x) |
537 CellSize=pHeap->AllocLen(aCell); // test? |
508 CellSize=pHeap->AllocLen(aCell); // test? |
538 |
509 |
539 // Resize positively |
510 // Resize positively |
540 for(TInt aSize=0; aSize<=BiggestBlock; aSize++, pHeap->Available(BiggestBlock)) |
511 for(TInt aSize=0; aSize<=BiggestBlock; aSize++, pHeap->Available(BiggestBlock)) |
541 { |
512 { |
542 aCell = pHeap->ReAlloc(aCell, aSize); |
513 test(pHeap->ReAlloc(aCell, aSize)!=NULL); |
543 test(aCell!=NULL); |
|
544 CellSize=pHeap->AllocLen(aCell); |
514 CellSize=pHeap->AllocLen(aCell); |
545 test(CellSize>=aSize); |
515 test(CellSize>=aSize); |
|
516 if (aSize<KMinCellLength) |
|
517 test(CellSize==KMinCellLength); |
|
518 else |
|
519 test(CellSize<aSize+KAlign); |
546 } |
520 } |
547 |
521 |
|
522 // Note: when increasing a cell size the size is rounded up to the nearest 4 but when |
|
523 // decreasing a cell the size is rounded down to the nearest 8 - this is due to the fact |
|
524 // that when memory is released its size must be big enough to hold a free cell header which |
|
525 // is greater(8) than an allocated header(4) |
|
526 // i.e. size = 16, resize to 17 => result is 20. But resize to 15 stays as 16, resize to 9 |
|
527 // stays as 16 but resize as 8 will resize to 8 |
|
528 |
|
529 for(TInt aSize2=(TInt)pHeap->AllocLen(aCell); aSize2>=0; aSize2--) |
|
530 { |
|
531 test(pHeap->ReAlloc(aCell, aSize2)!=NULL); |
|
532 |
|
533 test((TInt)pHeap->AllocLen(aCell)>=aSize2); |
|
534 |
|
535 TInt aTmpSize2 = Max(_ALIGN_UP(aSize2 + RHeap::EAllocCellSize, KAlign), KMinFreeSize); |
|
536 |
|
537 test((TInt)pHeap->AllocLen(aCell)<=aTmpSize2+KMinFreeSize); |
|
538 } |
|
539 |
548 pHeap->Check(); |
540 pHeap->Check(); |
549 pHeap->Reset(); |
541 pHeap->Reset(); |
550 // Allocate a block, fill with data, allocate another block or two then resize the original |
542 // Allocate a block, fill with data, allocate another block or two then resize the original |
551 // block such that it has to be moved in memory, then check the blocks' contents |
543 // block such that it has to be moved in memory, then check the blocks' contents |
552 TAny* Cell1=pHeap->Alloc(16); |
544 TAny* Cell1=pHeap->Alloc(16); |
744 TPtrC myHeapName=_L("MyHeap"); |
736 TPtrC myHeapName=_L("MyHeap"); |
745 // myHeap will have default GrowBy of KMinHeapGrowBy |
737 // myHeap will have default GrowBy of KMinHeapGrowBy |
746 RMyHeap* myHeap=(RMyHeap*)User::ChunkHeap(&myHeapName,0x100,0x2000); |
738 RMyHeap* myHeap=(RMyHeap*)User::ChunkHeap(&myHeapName,0x100,0x2000); |
747 const TInt KnormHeapGrowBy = 0x2000; |
739 const TInt KnormHeapGrowBy = 0x2000; |
748 RHeap* normHeap=User::ChunkHeap(NULL,0x100,0x20000,KnormHeapGrowBy); |
740 RHeap* normHeap=User::ChunkHeap(NULL,0x100,0x20000,KnormHeapGrowBy); |
749 // |
|
750 // Configure paged heap threshold 128 Kb (pagepower 17) |
|
751 // |
|
752 RHybridHeap::STestCommand conf; |
|
753 conf.iCommand = RHybridHeap::EGetConfig; |
|
754 if ( normHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&conf ) == KErrNone ) |
|
755 { |
|
756 test.Printf(_L("New allocator detected, configuring paged threshold to 128 kb\r\n")); |
|
757 conf.iCommand = RHybridHeap::ESetConfig; |
|
758 conf.iConfig.iPagePower = 17; |
|
759 test( normHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&conf ) == KErrNone); |
|
760 } |
|
761 |
741 |
762 TAny* ptrMy1=myHeap->Alloc(0x102); |
742 TAny* ptrMy1=myHeap->Alloc(0x102); |
763 test(ptrMy1!=NULL); |
743 test(ptrMy1!=NULL); |
764 TAny* ptrMy2=myHeap->Alloc(0x1001); |
744 TAny* ptrMy2=myHeap->Alloc(0x1001); |
765 test(ptrMy2!=NULL); |
745 test(ptrMy2!=NULL); |
802 r=normHeap->Size(); |
782 r=normHeap->Size(); |
803 |
783 |
804 // Calc the amount, if any, the overall size of normHeap will have been shrunk by |
784 // Calc the amount, if any, the overall size of normHeap will have been shrunk by |
805 // will depend on value of KHeapShrinkHysRatio. |
785 // will depend on value of KHeapShrinkHysRatio. |
806 // 1st calc current total size of the allocated cells |
786 // 1st calc current total size of the allocated cells |
807 TInt normAllocdSize = normHeap->AllocLen(ptrNorm1)+KHeadSize + |
787 TInt normAllocdSize = normHeap->AllocLen(ptrNorm1)+RHeap::EAllocCellSize + |
808 normHeap->AllocLen(ptrNorm2)+KHeadSize; |
788 normHeap->AllocLen(ptrNorm2)+RHeap::EAllocCellSize; |
809 TInt normReduce = RHeapCalcReduce(oldNormHeapSize-normAllocdSize,KnormHeapGrowBy); |
789 TInt normReduce = RHeapCalcReduce(oldNormHeapSize-normAllocdSize,KnormHeapGrowBy); |
810 oldNormHeapSize -= normReduce; |
790 oldNormHeapSize -= normReduce; |
811 test(r==oldNormHeapSize); |
791 test(r==oldNormHeapSize); |
812 |
792 |
813 normHeap->Free(ptrNorm2); |
793 normHeap->Free(ptrNorm2); |
1178 gHeapPtr->Free(p1); |
1158 gHeapPtr->Free(p1); |
1179 comp=gHeapPtr->Compress(); |
1159 comp=gHeapPtr->Compress(); |
1180 test(comp==0); |
1160 test(comp==0); |
1181 TInt biggest1; |
1161 TInt biggest1; |
1182 TInt avail1=gHeapPtr->Available(biggest1); |
1162 TInt avail1=gHeapPtr->Available(biggest1); |
1183 test(avail==avail1); |
1163 test(avail1==avail1); |
1184 test(biggest==biggest1); |
1164 test(biggest==biggest1); |
1185 test(gHeapPtr->Count()==0); |
1165 test(gHeapPtr->Count()==0); |
1186 gHeapPtr->Close(); |
1166 gHeapPtr->Close(); |
1187 test.End(); |
1167 test.End(); |
1188 } |
1168 } |
1189 |
1169 |
1190 LOCAL_C TInt NormalChunk(RChunk& aChunk, TInt aInitialSize, TInt aMaxSize) |
|
1191 { |
|
1192 TChunkCreateInfo createInfo; |
|
1193 createInfo.SetNormal(aInitialSize, aMaxSize); |
|
1194 TInt r=aChunk.Create(createInfo); |
|
1195 return r; |
|
1196 } |
|
1197 |
|
1198 LOCAL_C TInt DisconnectedChunk(RChunk& aChunk, TInt aInitialBottom, TInt aInitialTop, TInt aMaxSize) |
|
1199 { |
|
1200 TChunkCreateInfo createInfo; |
|
1201 createInfo.SetDisconnected(aInitialBottom, aInitialTop, aMaxSize); |
|
1202 TInt r=aChunk.Create(createInfo); |
|
1203 return r; |
|
1204 } |
|
1205 |
|
1206 LOCAL_C TBool TestIsHybridHeap(RHeap* aHeap) |
|
1207 { |
|
1208 RHybridHeap::STestCommand cmd; |
|
1209 cmd.iCommand = RHybridHeap::EHeapMetaData; |
|
1210 aHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&cmd, 0); |
|
1211 |
|
1212 RHybridHeap* hybridHeap = (RHybridHeap*) cmd.iData; |
|
1213 return (TestHybridHeap::IsHybrid(hybridHeap)); |
|
1214 } |
|
1215 |
|
1216 LOCAL_C void TestHeapType() |
|
1217 { |
|
1218 TBool onlyDL = EFalse; |
|
1219 _LIT(KHeap, "NamedHeap"); |
|
1220 // 1: Create a heap in a local chunk |
|
1221 RHeap* heap; |
|
1222 heap = UserHeap::ChunkHeap(NULL,0x100,0x2000); |
|
1223 TBool hybrid = TestIsHybridHeap(heap); |
|
1224 if (hybrid==0) |
|
1225 { |
|
1226 test.Printf(_L("Only DL allocator is in use \n")); |
|
1227 onlyDL = ETrue;; |
|
1228 } |
|
1229 else |
|
1230 test(hybrid==1); |
|
1231 heap->Close(); |
|
1232 |
|
1233 // 2: Create a heap in a global chunk |
|
1234 heap = UserHeap::ChunkHeap(&KHeap,0,0x1800,0x6000); |
|
1235 hybrid = TestIsHybridHeap(heap); |
|
1236 if(!onlyDL) |
|
1237 test(hybrid==1); |
|
1238 heap->Close(); |
|
1239 |
|
1240 // 3: Create a heap in an existing normal chunk |
|
1241 RChunk chunk; |
|
1242 TInt r = NormalChunk(chunk,0,0x1000); |
|
1243 heap = UserHeap::ChunkHeap(chunk,0); |
|
1244 hybrid = TestIsHybridHeap(heap); |
|
1245 test(hybrid==0); |
|
1246 heap->Close(); |
|
1247 |
|
1248 // 4: Create a heap in an existing disconnected chunk |
|
1249 // when offset = 0. Minimum heap size for a hybrid heap is 12KB |
|
1250 r = DisconnectedChunk(chunk,0,0,0x3000); |
|
1251 heap = UserHeap::ChunkHeap(chunk,0); |
|
1252 hybrid = TestIsHybridHeap(heap); |
|
1253 if(!onlyDL) |
|
1254 test(hybrid==1); |
|
1255 heap->Close(); |
|
1256 |
|
1257 // 5: Create a heap in an existing disconnected chunk |
|
1258 // when offset > 0 |
|
1259 r = DisconnectedChunk(chunk,0,0x1800,0x6000); |
|
1260 heap = UserHeap::OffsetChunkHeap(chunk,0,0x2800); |
|
1261 hybrid = TestIsHybridHeap(heap); |
|
1262 test(hybrid==0); |
|
1263 heap->Close(); |
|
1264 |
|
1265 // 6: Create a fixed length heap at a normal chunk's base address |
|
1266 r = NormalChunk(chunk,0x1000,0x1000); |
|
1267 heap = UserHeap::FixedHeap(chunk.Base(), 0x1000); |
|
1268 hybrid = TestIsHybridHeap(heap); |
|
1269 test(hybrid==0); |
|
1270 heap->Close(); |
|
1271 chunk.Close(); |
|
1272 |
|
1273 // 7: Create a fixed length heap at a disconnected chunk's base address |
|
1274 // when bottom = 0 |
|
1275 r = DisconnectedChunk(chunk,0,0x2000,0x2000); |
|
1276 heap = UserHeap::FixedHeap(chunk.Base(), 0x2000); |
|
1277 hybrid = TestIsHybridHeap(heap); |
|
1278 test(hybrid==0); |
|
1279 heap->Close(); |
|
1280 chunk.Close(); |
|
1281 |
|
1282 // 8: Create a fixed length heap at a disconnected chunk's base address |
|
1283 // when bottom > 0 |
|
1284 r = DisconnectedChunk(chunk,0x6000,0x7000,0x13000); |
|
1285 heap = UserHeap::FixedHeap(chunk.Base()+ 0x6000, 0x1000); |
|
1286 hybrid = TestIsHybridHeap(heap); |
|
1287 test(hybrid==0); |
|
1288 heap->Close(); |
|
1289 chunk.Close(); |
|
1290 |
|
1291 // 9: Create a fixed length heap for allocated buffer |
|
1292 heap = UserHeap::ChunkHeap(&KNullDesC(), 4096, (4096 * 1024)); |
|
1293 test(heap != NULL); |
|
1294 TAny* buffer = heap->Alloc(1024 * 1024); |
|
1295 test(buffer != NULL); |
|
1296 TInt lth = heap->AllocLen(buffer); |
|
1297 test.Printf(_L("Fixed heap buffer: %x, length: %x \n"), buffer, lth); |
|
1298 |
|
1299 RHeap* heapf = UserHeap::FixedHeap(buffer, (1024 * 1024)); |
|
1300 test(heapf != NULL); |
|
1301 test.Printf(_L("Fixed heap: %x \n"), heapf); |
|
1302 hybrid = TestIsHybridHeap(heapf); |
|
1303 test(hybrid==0); |
|
1304 |
|
1305 heapf->Close(); |
|
1306 heap->Free(buffer); |
|
1307 |
|
1308 heap->Close(); |
|
1309 } |
|
1310 |
1170 |
1311 GLDEF_C TInt E32Main(void) |
1171 GLDEF_C TInt E32Main(void) |
1312 { |
1172 { |
1313 |
1173 |
1314 test.Title(); |
1174 test.Title(); |