Change the search for free space from one based on segments to one based on free list sets, so that the same free list sets are not examined more than once, and so that confusion that might arise when a search for a range in one segment produces a range in another segment might be eliminated.
If a single free block cannot satisfy the request, keep trying by looking for a sequence of almost-big-enough free blocks.
When a sequence of almost-big-enough blocks is examined, allow smaller free blocks to complete the allocation, if possible. Allow smaller free blocks to begin the allocation too. If a range of free blocks is examined, and the range is not big enough to satisfy the request, move those almost-big-enough free blocks in the free list so that they won't be encountered again.