Whenever an allocation request arrives, it is first bucketed based on its size (if it is larger than the largest bucket, it is passed through to a caching OS allocator). Then, the linked list of that bucket is walked, and the allocation is fulfilled by the first pool that has empty "blocks". If there are no such pool, a new pool is created (with number of blocks being possibly larger than in the existing list, if any), this pool becomes the new head of the list and the allocation happens there.