Esempio n. 1
0
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;
        }
    }
}
Esempio n. 2
0
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;
    }

  }
}