ucc_geth DPRAM alloc error, 2.6.22-rc3
Rune Torgersen
runet at innovsys.com
Fri Jun 15 08:50:03 EST 2007
Here is what I had to do to get best-fit + not allocating too much:
(against 2.6.18)
--- linux-innsys/arch/ppc/lib/rheap.c 2006/10/10 22:54:41 175
+++ linux-innsys/arch/ppc/lib/rheap.c 2006/12/03 18:04:42 205
@@ -428,19 +428,22 @@
{
struct list_head *l;
rh_block_t *blk;
- rh_block_t *newblk;
+ rh_block_t *newblk1, *newblk2;
void *start;
-
+ int align_mask = alignment - 1;
+ int off;
+ unsigned long s, e, m, bs, be;
+
/* Validate size, (must be power of two) */
if (size <= 0 || (alignment & (alignment - 1)) != 0)
return ERR_PTR(-EINVAL);
/* given alignment larger that default rheap alignment */
- if (alignment > info->alignment)
- size += alignment - 1;
+ //if (alignment > info->alignment)
+ // size += alignment - 1;
/* Align to configured alignment */
- size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
+ //size = (size + (info->alignment - 1)) & ~(info->alignment -
1);
if (assure_empty(info, 1) < 0)
return ERR_PTR(-ENOMEM);
@@ -448,8 +451,18 @@
blk = NULL;
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
- if (size <= blk->size)
+
+ if ((blk->size == size) && (((int)blk->start &
align_mask) == 0))
+ break;
+
+ if (((int)blk->start & align_mask) != 0)
+ off = align_mask - ((int)blk->start &
align_mask) + 1;
+ else
+ off = 0;
+
+ if (blk->size - off >= size)
break;
+
blk = NULL;
}
@@ -468,25 +481,35 @@
return start;
}
- newblk = get_slot(info);
- newblk->start = blk->start;
- newblk->size = size;
- newblk->owner = owner;
-
- /* blk still in free list, with updated start, size */
- blk->start = (int8_t *)blk->start + size;
- blk->size -= size;
+ bs = (int)blk->start;
+ be = (int)blk->start + blk->size;
+ s = (int)blk->start + off;
+ e = s + size;
+
+ if (bs == s || be == e) {
+ if (bs == s)
+ blk->start = (int8_t *)blk->start + size;
+ blk->size -= size;
- start = newblk->start;
+ } else {
+ /* The front free fragment */
+ blk->size = s - bs;
- attach_taken_block(info, newblk);
-
- /* for larger alignment return fixed up pointer */
- /* this is no problem with the deallocator since */
- /* we scan for pointers that lie in the blocks */
- if (alignment > info->alignment)
- start = (void *)(((unsigned long)start + alignment - 1)
&
- ~(alignment - 1));
+ /* The back free fragment */
+ newblk2 = get_slot(info);
+ newblk2->start = (void *)e;
+ newblk2->size = be - e;
+
+ list_add(&newblk2->list, &blk->list);
+ }
+
+ newblk1 = get_slot(info);
+ newblk1->start = (void *)s;
+ newblk1->size = e - s;
+ newblk1->owner = owner;
+
+ start = newblk1->start;
+ attach_taken_block(info, newblk1);
return start;
}
More information about the Linuxppc-dev
mailing list