void buddy_free_range(buddy_t *bd, range_t range) { unsigned i; uint64_t old_start, start; uintptr_t sz, min_sz; min_sz = 1 << MIN_BUDDY_SZ_LOG2; if (aligned_for(range.start, MIN_BUDDY_SZ_LOG2) == 0) { if (range.extent < min_sz) { return; } old_start = range.start; range.start &= ~0ULL << MIN_BUDDY_SZ_LOG2; range.start += min_sz; range.extent -= range.start - old_start; } while (range.extent >= min_sz && aligned_for(range.start, MIN_BUDDY_SZ_LOG2)) { for(i = MAX_BUDDY_SZ_LOG2; i >= MIN_BUDDY_SZ_LOG2; i--) { sz = 1 << i; start = range.start - bd->start; if (sz > range.extent || aligned_for(start, i) == 0) { continue; } range.extent -= sz; range.start += sz; buddy_free(bd, start + bd->start, sz); break; } } }
void buddy_free_range(buddy_t *bd, range_t range) { uintptr_t min_sz = 1 << MIN_BUDDY_SZ_LOG2; /** Firstly, we use a helper function to check if the range's start address is aligned to a multiple of the smallest block size. If not, we adjust it so that it is. { */ /* Ensure the range start address is at least aligned to MIN_BUDDY_SZ_LOG2. */ if (aligned_for(range.start, MIN_BUDDY_SZ_LOG2) == 0) { if (range.extent < min_sz) return; uint64_t old_start = range.start; range.start &= ~0ULL << MIN_BUDDY_SZ_LOG2; range.start += min_sz; range.extent -= range.start - old_start; } /** Now, we iteratively work through the range trying to allocate the largest block we can. { */ while (range.extent >= min_sz && aligned_for(range.start, MIN_BUDDY_SZ_LOG2)) { for (unsigned i = MAX_BUDDY_SZ_LOG2; i >= MIN_BUDDY_SZ_LOG2; --i) { uintptr_t sz = 1 << i; uint64_t start = range.start - bd->start; if (sz > range.extent || aligned_for(start, i) == 0) continue; range.extent -= sz; range.start += sz; buddy_free(bd, start + bd->start, sz); break; } } }