Skip to content

Commit 7662c47

Browse files
fix: freelist ext issues
1 parent 4cd865d commit 7662c47

1 file changed

Lines changed: 56 additions & 77 deletions

File tree

extensions/pl_freelist_ext.c

Lines changed: 56 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ pl_freelist_get_node(plFreeList* ptFreeList, uint64_t uSize)
101101

102102
// find best block
103103
uint64_t szSmallestDiff = ~(uint64_t)0;
104-
plFreeListNode* ptCurrentBlock = &ptFreeList->_tFreeList;
104+
plFreeListNode* ptCurrentBlock = ptFreeList->_tFreeList._ptNext;
105105
while(ptCurrentBlock)
106106
{
107107

@@ -151,96 +151,75 @@ pl_freelist_return_node(plFreeList* ptFreeList, plFreeListNode* ptNode)
151151
{
152152
ptFreeList->uUsedSpace -= ptNode->uSize;
153153

154-
// if the free list is not empty
155-
if(ptFreeList->_tFreeList._ptNext != NULL)
154+
155+
// If free list is empty, add as first node
156+
if (ptFreeList->_tFreeList._ptNext == NULL)
156157
{
157-
// Add node to free list
158-
plFreeListNode* ptFreeBlock = ptFreeList->_tFreeList._ptNext;
159-
while(ptFreeBlock)
160-
{
161-
// Insert new node to middle
162-
if(ptFreeBlock > ptNode)
163-
{
164-
plFreeListNode *_ptNext = ptFreeBlock;
165-
plFreeListNode *_ptPrev = ptFreeBlock->_ptPrev;
166-
167-
_ptNext->_ptPrev = ptNode;
168-
ptNode->_ptNext = _ptNext;
169-
ptNode->_ptPrev = _ptPrev;
170-
_ptPrev->_ptNext = ptNode;
171-
break;
172-
173-
}
158+
ptNode->_ptPrev = &ptFreeList->_tFreeList;
159+
ptNode->_ptNext = NULL;
160+
ptFreeList->_tFreeList._ptNext = ptNode;
161+
return;
162+
}
174163

175-
// There isn't a next block so Insert new node to the end
176-
if(ptFreeBlock->_ptNext == NULL)
177-
{
178-
ptNode->_ptNext = NULL;
179-
ptNode->_ptPrev = ptFreeBlock;
180-
ptFreeBlock->_ptNext = ptNode;
181-
break;
182-
}
164+
// 1) Insert by uOffset order (not by pointer!)
165+
plFreeListNode* it = ptFreeList->_tFreeList._ptNext;
166+
plFreeListNode* insert_after = &ptFreeList->_tFreeList;
183167

184-
ptFreeBlock = ptFreeBlock->_ptNext;
185-
}
168+
while (it && it->uOffset < ptNode->uOffset)
169+
{
170+
insert_after = it;
171+
it = it->_ptNext;
172+
}
186173

187-
// Defrag
188-
plFreeListNode* _ptPrevBlock = ptNode->_ptPrev;
189-
plFreeListNode* _ptNextBlock = ptNode->_ptNext;
174+
ptNode->_ptPrev = insert_after;
175+
ptNode->_ptNext = it;
176+
insert_after->_ptNext = ptNode;
177+
if (it) it->_ptPrev = ptNode;
190178

191-
if(_ptPrevBlock != &ptFreeList->_tFreeList)
179+
// 2) Coalesce with previous if adjacent
180+
if (ptNode->_ptPrev != &ptFreeList->_tFreeList)
181+
{
182+
plFreeListNode* prev = ptNode->_ptPrev;
183+
if (prev->uOffset + prev->uSize == ptNode->uOffset)
192184
{
193-
// if prev block and block are adjacent
194-
if((_ptPrevBlock->uOffset + _ptPrevBlock->uSize) == ptNode->uOffset)
195-
{
196-
_ptPrevBlock->uSize += ptNode->uSize;
197-
pl_sb_push(ptFreeList->_sbuFreeNodeHoleSlot, ptNode->_uIndex);
198-
199-
// delete node
200-
if(_ptNextBlock != NULL) {_ptNextBlock->_ptPrev = _ptPrevBlock; }
201-
_ptPrevBlock->_ptNext = _ptNextBlock;
202-
ptNode->_ptNext = NULL;
203-
ptNode->_ptPrev = NULL;
204-
ptNode->uOffset = 0;
205-
ptNode->uSize = 0;
206-
207-
// Allows us to defrag with the next block without checking if we defragged with this one
208-
ptNode = _ptPrevBlock;
209-
}
210-
}
185+
prev->uSize += ptNode->uSize;
211186

212-
if(_ptNextBlock != NULL)
213-
{
187+
// Recycle this node descriptor
188+
pl_sb_push(ptFreeList->_sbuFreeNodeHoleSlot, ptNode->_uIndex);
214189

215-
plFreeListNode* _ptNextNextBlock = _ptNextBlock->_ptNext;
190+
// Remove ptNode from the list
191+
if (ptNode->_ptNext) ptNode->_ptNext->_ptPrev = prev;
192+
prev->_ptNext = ptNode->_ptNext;
216193

217-
// if block and next block are adjacent
218-
if((ptNode->uOffset + ptNode->uSize) == _ptNextBlock->uOffset)
219-
{
220-
ptNode->uSize += _ptNextBlock->uSize;
221-
pl_sb_push(ptFreeList->_sbuFreeNodeHoleSlot, _ptNextBlock->_uIndex);
222-
223-
// delete next node
224-
if(_ptNextNextBlock != NULL)
225-
{
226-
_ptNextNextBlock->_ptPrev = ptNode;
227-
}
228-
ptNode->_ptNext = _ptNextNextBlock;
229-
_ptNextBlock->_ptNext = NULL;
230-
_ptNextBlock->_ptPrev = NULL;
231-
_ptNextBlock->uOffset = 0;
232-
_ptNextBlock->uSize = 0;
194+
// Clean up metadata
195+
ptNode->_ptPrev = ptNode->_ptNext = NULL;
196+
ptNode->uOffset = 0;
197+
ptNode->uSize = 0;
233198

234-
}
199+
// Continue coalescing using the merged 'prev' block
200+
ptNode = prev;
235201
}
236202
}
237-
else
203+
204+
// 3) Coalesce forward as long as next is adjacent
205+
while (ptNode->_ptNext &&
206+
(ptNode->uOffset + ptNode->uSize) == ptNode->_ptNext->uOffset)
238207
{
239-
// Add node to the front of the free list if list is empty
240-
ptNode->_ptNext = NULL;
241-
ptNode->_ptPrev = &ptFreeList->_tFreeList;
242-
ptFreeList->_tFreeList._ptNext = ptNode;
208+
plFreeListNode* next = ptNode->_ptNext;
209+
plFreeListNode* nn = next->_ptNext;
210+
211+
ptNode->uSize += next->uSize;
212+
pl_sb_push(ptFreeList->_sbuFreeNodeHoleSlot, next->_uIndex);
213+
214+
// unlink next
215+
ptNode->_ptNext = nn;
216+
if (nn) nn->_ptPrev = ptNode;
217+
218+
next->_ptPrev = next->_ptNext = NULL;
219+
next->uOffset = 0;
220+
next->uSize = 0;
243221
}
222+
244223
}
245224

246225
//-----------------------------------------------------------------------------

0 commit comments

Comments
 (0)