1 /****************************************************************************
2 * This file is part of PPMd project *
3 * Written and distributed to public domain by Dmitry Shkarin 1997, *
5 * Contents: memory allocation routines *
6 ****************************************************************************/
8 SubAllocator::SubAllocator()
14 void SubAllocator::Clean()
20 inline void SubAllocator::InsertNode(void* p,int indx)
22 ((RAR_NODE*) p)->next=FreeList[indx].next;
23 FreeList[indx].next=(RAR_NODE*) p;
27 inline void* SubAllocator::RemoveNode(int indx)
29 RAR_NODE* RetVal=FreeList[indx].next;
30 FreeList[indx].next=RetVal->next;
35 inline uint SubAllocator::U2B(int NU)
37 return /*8*NU+4*NU*/UNIT_SIZE*NU;
41 inline void SubAllocator::SplitBlock(void* pv,int OldIndx,int NewIndx)
43 int i, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx];
44 byte* p=((byte*) pv)+U2B(Indx2Units[NewIndx]);
45 if (Indx2Units[i=Units2Indx[UDiff-1]] != UDiff)
48 p += U2B(i=Indx2Units[i]);
51 InsertNode(p,Units2Indx[UDiff-1]);
57 void SubAllocator::StopSubAllocator()
59 if ( SubAllocatorSize )
67 bool SubAllocator::StartSubAllocator(int SASize)
69 uint t=(uint)(SASize) << 20;
70 if ((uint)SubAllocatorSize == t)
73 uint AllocSize=t/FIXED_UNIT_SIZE*UNIT_SIZE+UNIT_SIZE;
75 if ((HeapStart=(byte *)rarmalloc(AllocSize)) == NULL)
77 ErrHandler.MemoryError();
81 // this is uggly, we keep halfing the size till
82 // we manage to alloc, it's likely that we
84 uint AllocSize2 = AllocSize;
85 while(AllocSize2 && (HeapStart=(byte *)rarmalloc(AllocSize2)) == NULL)
90 ErrHandler.MemoryError();
94 if(AllocSize != AllocSize2)
95 OutputDebugString("ERROR - had to allocate smaller data than required, extract can very well fail");
98 HeapEnd=HeapStart+AllocSize-UNIT_SIZE;
104 void SubAllocator::InitSubAllocator()
107 memset(FreeList,0,sizeof(FreeList));
109 uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7);
110 uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE;
111 uint Size1=SubAllocatorSize-Size2;
112 uint RealSize1=Size1/FIXED_UNIT_SIZE*UNIT_SIZE+Size1%FIXED_UNIT_SIZE;
113 HiUnit=HeapStart+SubAllocatorSize;
114 LoUnit=UnitsStart=HeapStart+RealSize1;
115 FakeUnitsStart=HeapStart+Size1;
116 HiUnit=LoUnit+RealSize2;
117 for (i=0,k=1;i < N1 ;i++,k += 1)
119 for (k++;i < N1+N2 ;i++,k += 2)
121 for (k++;i < N1+N2+N3 ;i++,k += 3)
123 for (k++;i < N1+N2+N3+N4;i++,k += 4)
125 for (GlueCount=k=i=0;k < 128;k++)
127 i += (Indx2Units[i] < k+1);
133 inline void SubAllocator::GlueFreeBlocks()
135 RAR_MEM_BLK s0, * p, * p1;
137 if (LoUnit != HiUnit)
139 for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
140 while ( FreeList[i].next )
142 p=(RAR_MEM_BLK*)RemoveNode(i);
147 for (p=s0.next;p != &s0;p=p->next)
148 while ((p1=p+p->NU)->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000)
153 while ((p=s0.next) != &s0)
155 for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p += 128)
156 InsertNode(p,N_INDEXES-1);
157 if (Indx2Units[i=Units2Indx[sz-1]] != sz)
159 k=sz-Indx2Units[--i];
160 InsertNode(p+(sz-k),k-1);
166 void* SubAllocator::AllocUnitsRare(int indx)
172 if ( FreeList[indx].next )
173 return RemoveNode(indx);
178 if (++i == N_INDEXES)
181 i=U2B(Indx2Units[indx]);
182 int j=12*Indx2Units[indx];
183 if (FakeUnitsStart-pText > j)
191 } while ( !FreeList[i].next );
192 void* RetVal=RemoveNode(i);
193 SplitBlock(RetVal,i,indx);
198 inline void* SubAllocator::AllocUnits(int NU)
200 int indx=Units2Indx[NU-1];
201 if ( FreeList[indx].next )
202 return RemoveNode(indx);
204 LoUnit += U2B(Indx2Units[indx]);
205 if (LoUnit <= HiUnit)
207 LoUnit -= U2B(Indx2Units[indx]);
208 return AllocUnitsRare(indx);
212 void* SubAllocator::AllocContext()
214 if (HiUnit != LoUnit)
215 return (HiUnit -= UNIT_SIZE);
216 if ( FreeList->next )
217 return RemoveNode(0);
218 return AllocUnitsRare(0);
222 void* SubAllocator::ExpandUnits(void* OldPtr,int OldNU)
224 int i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
227 void* ptr=AllocUnits(OldNU+1);
230 memcpy(ptr,OldPtr,U2B(OldNU));
231 InsertNode(OldPtr,i0);
237 void* SubAllocator::ShrinkUnits(void* OldPtr,int OldNU,int NewNU)
239 int i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
242 if ( FreeList[i1].next )
244 void* ptr=RemoveNode(i1);
245 memcpy(ptr,OldPtr,U2B(NewNU));
246 InsertNode(OldPtr,i0);
251 SplitBlock(OldPtr,i0,i1);
257 void SubAllocator::FreeUnits(void* ptr,int OldNU)
259 InsertNode(ptr,Units2Indx[OldNU-1]);