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)
70 if (SubAllocatorSize == t)
73 uint AllocSize=t/FIXED_UNIT_SIZE*UNIT_SIZE+UNIT_SIZE;
74 if ((HeapStart=(byte *)rarmalloc(AllocSize)) == NULL)
76 ErrHandler.MemoryError();
79 HeapEnd=HeapStart+AllocSize-UNIT_SIZE;
85 void SubAllocator::InitSubAllocator()
88 memset(FreeList,0,sizeof(FreeList));
90 uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7);
91 uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE;
92 uint Size1=SubAllocatorSize-Size2;
93 uint RealSize1=Size1/FIXED_UNIT_SIZE*UNIT_SIZE+Size1%FIXED_UNIT_SIZE;
94 HiUnit=HeapStart+SubAllocatorSize;
95 LoUnit=UnitsStart=HeapStart+RealSize1;
96 FakeUnitsStart=HeapStart+Size1;
97 HiUnit=LoUnit+RealSize2;
98 for (i=0,k=1;i < N1 ;i++,k += 1)
100 for (k++;i < N1+N2 ;i++,k += 2)
102 for (k++;i < N1+N2+N3 ;i++,k += 3)
104 for (k++;i < N1+N2+N3+N4;i++,k += 4)
106 for (GlueCount=k=i=0;k < 128;k++)
108 i += (Indx2Units[i] < k+1);
114 inline void SubAllocator::GlueFreeBlocks()
116 RAR_MEM_BLK s0, * p, * p1;
118 if (LoUnit != HiUnit)
120 for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
121 while ( FreeList[i].next )
123 p=(RAR_MEM_BLK*)RemoveNode(i);
128 for (p=s0.next;p != &s0;p=p->next)
129 while ((p1=p+p->NU)->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000)
134 while ((p=s0.next) != &s0)
136 for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p += 128)
137 InsertNode(p,N_INDEXES-1);
138 if (Indx2Units[i=Units2Indx[sz-1]] != sz)
140 k=sz-Indx2Units[--i];
141 InsertNode(p+(sz-k),k-1);
147 void* SubAllocator::AllocUnitsRare(int indx)
153 if ( FreeList[indx].next )
154 return RemoveNode(indx);
159 if (++i == N_INDEXES)
162 i=U2B(Indx2Units[indx]);
163 int j=12*Indx2Units[indx];
164 if (FakeUnitsStart-pText > j)
172 } while ( !FreeList[i].next );
173 void* RetVal=RemoveNode(i);
174 SplitBlock(RetVal,i,indx);
179 inline void* SubAllocator::AllocUnits(int NU)
181 int indx=Units2Indx[NU-1];
182 if ( FreeList[indx].next )
183 return RemoveNode(indx);
185 LoUnit += U2B(Indx2Units[indx]);
186 if (LoUnit <= HiUnit)
188 LoUnit -= U2B(Indx2Units[indx]);
189 return AllocUnitsRare(indx);
193 void* SubAllocator::AllocContext()
195 if (HiUnit != LoUnit)
196 return (HiUnit -= UNIT_SIZE);
197 if ( FreeList->next )
198 return RemoveNode(0);
199 return AllocUnitsRare(0);
203 void* SubAllocator::ExpandUnits(void* OldPtr,int OldNU)
205 int i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
208 void* ptr=AllocUnits(OldNU+1);
211 memcpy(ptr,OldPtr,U2B(OldNU));
212 InsertNode(OldPtr,i0);
218 void* SubAllocator::ShrinkUnits(void* OldPtr,int OldNU,int NewNU)
220 int i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
223 if ( FreeList[i1].next )
225 void* ptr=RemoveNode(i1);
226 memcpy(ptr,OldPtr,U2B(NewNU));
227 InsertNode(OldPtr,i0);
232 SplitBlock(OldPtr,i0,i1);
238 void SubAllocator::FreeUnits(void* ptr,int OldNU)
240 InsertNode(ptr,Units2Indx[OldNU-1]);