Example #1
0
/** Freeing is actually easier, as we never have to worry about
    splitting blocks.

    Note that this function can only free addresses and sizes that are
    correctly aligned, so it's only really safe to call this with addresses
    returned from buddy_alloc(). 

    We simply mark the incoming block as free, then while we are not
    at the top level of the tree, see if the buddy is also free. If so,
    we mark them both as unavailable and move up the tree one level. { */
void buddy_free(buddy_t *bd, uint64_t addr, unsigned sz) {
  uint64_t offs = addr - bd->start;
  unsigned log_sz = log2_roundup(sz);
  unsigned idx = offs >> log_sz;

  while (log_sz >= MIN_BUDDY_SZ_LOG2) {
    int order_idx = log_sz - MIN_BUDDY_SZ_LOG2;

    /* Mark this node free. */
    bitmap_set(&bd->orders[order_idx], idx);

    /* Can we coalesce up another level? */
    if (log_sz == MAX_BUDDY_SZ_LOG2)
      break;

    /* Is this node's buddy also free? */
    if (bitmap_isset(&bd->orders[order_idx], BUDDY(idx)) == 0)
      /* no :( */
      break;

    /* FIXME: Ensure max(this, buddy) wouldn't go over the max extent
       of the region. */

    /* Mark them both non free. */
    bitmap_clear(&bd->orders[order_idx], idx);
    bitmap_clear(&bd->orders[order_idx], BUDDY(idx));

    /* Move up an order. */
    idx = DEC_ORDER(idx);
    ++log_sz;
  }

}
Example #2
0
void buddy_free(buddy_t *bd, uint64_t addr, unsigned sz)
{
    uint64_t offs   = addr - bd->start;
    unsigned log_sz = log2_roundup(sz);
    unsigned idx    = offs >> log_sz;

    while (log_sz >= MIN_BUDDY_SZ_LOG2) {
        int order_idx = log_sz - MIN_BUDDY_SZ_LOG2;
        // Mark node free
        bitmap_set(&bd->orders[order_idx], idx);
        // Can we coalese up another level?
        if (log_sz == MAX_BUDDY_SZ_LOG2) {
            break;
        }
        if (bitmap_isset(&bd->orders[order_idx], BUDDY(idx)) == 0) {
            // guess not...
            break;
        }
        // Mark both non-free
        bitmap_clear(&bd->orders[order_idx], idx);
        bitmap_clear(&bd->orders[order_idx], BUDDY(idx));

        // Move up an order
        idx = DEC_ORDER(idx);
        log_sz++;
    }
}