i think in your implementation of MergeIfPossible you're missing to merge with all free chunks of memory. Let's say you have a Chunk A (which is free), B (in use), and C (free). After freeing B you'll merge B with C, but miss the oportunity to merge with A.
Please look at the call site for MergeIfPossible and note that it is called twice, once for B-C (in your example) and once for A-B. If you still think there is a problem, please let me know what it is and I'll take a look!