|
@@ -133,7 +133,7 @@ static rh_block_t *get_slot(rh_info_t * info)
|
|
|
info->empty_slots--;
|
|
|
|
|
|
/* Initialize */
|
|
|
- blk->start = NULL;
|
|
|
+ blk->start = 0;
|
|
|
blk->size = 0;
|
|
|
blk->owner = NULL;
|
|
|
|
|
@@ -158,7 +158,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
|
|
|
|
|
|
/* We assume that they are aligned properly */
|
|
|
size = blkn->size;
|
|
|
- s = (unsigned long)blkn->start;
|
|
|
+ s = blkn->start;
|
|
|
e = s + size;
|
|
|
|
|
|
/* Find the blocks immediately before and after the given one
|
|
@@ -170,7 +170,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
|
|
|
list_for_each(l, &info->free_list) {
|
|
|
blk = list_entry(l, rh_block_t, list);
|
|
|
|
|
|
- bs = (unsigned long)blk->start;
|
|
|
+ bs = blk->start;
|
|
|
be = bs + blk->size;
|
|
|
|
|
|
if (next == NULL && s >= bs)
|
|
@@ -188,10 +188,10 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
|
|
|
}
|
|
|
|
|
|
/* Now check if they are really adjacent */
|
|
|
- if (before != NULL && s != (unsigned long)before->start + before->size)
|
|
|
+ if (before && s != (before->start + before->size))
|
|
|
before = NULL;
|
|
|
|
|
|
- if (after != NULL && e != (unsigned long)after->start)
|
|
|
+ if (after && e != after->start)
|
|
|
after = NULL;
|
|
|
|
|
|
/* No coalescing; list insert and return */
|
|
@@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
|
|
|
|
|
|
/* Grow the after block backwards */
|
|
|
if (before == NULL && after != NULL) {
|
|
|
- after->start = (int8_t *)after->start - size;
|
|
|
+ after->start -= size;
|
|
|
after->size += size;
|
|
|
return;
|
|
|
}
|
|
@@ -321,14 +321,14 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
|
|
|
}
|
|
|
|
|
|
/* Attach a free memory region, coalesces regions if adjuscent */
|
|
|
-int rh_attach_region(rh_info_t * info, void *start, int size)
|
|
|
+int rh_attach_region(rh_info_t * info, unsigned long start, int size)
|
|
|
{
|
|
|
rh_block_t *blk;
|
|
|
unsigned long s, e, m;
|
|
|
int r;
|
|
|
|
|
|
/* The region must be aligned */
|
|
|
- s = (unsigned long)start;
|
|
|
+ s = start;
|
|
|
e = s + size;
|
|
|
m = info->alignment - 1;
|
|
|
|
|
@@ -338,9 +338,12 @@ int rh_attach_region(rh_info_t * info, void *start, int size)
|
|
|
/* Round end down */
|
|
|
e = e & ~m;
|
|
|
|
|
|
+ if (IS_ERR_VALUE(e) || (e < s))
|
|
|
+ return -ERANGE;
|
|
|
+
|
|
|
/* Take final values */
|
|
|
- start = (void *)s;
|
|
|
- size = (int)(e - s);
|
|
|
+ start = s;
|
|
|
+ size = e - s;
|
|
|
|
|
|
/* Grow the blocks, if needed */
|
|
|
r = assure_empty(info, 1);
|
|
@@ -358,7 +361,7 @@ int rh_attach_region(rh_info_t * info, void *start, int size)
|
|
|
}
|
|
|
|
|
|
/* Detatch given address range, splits free block if needed. */
|
|
|
-void *rh_detach_region(rh_info_t * info, void *start, int size)
|
|
|
+unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
|
|
|
{
|
|
|
struct list_head *l;
|
|
|
rh_block_t *blk, *newblk;
|
|
@@ -366,10 +369,10 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
|
|
|
|
|
|
/* Validate size */
|
|
|
if (size <= 0)
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ return (unsigned long) -EINVAL;
|
|
|
|
|
|
/* The region must be aligned */
|
|
|
- s = (unsigned long)start;
|
|
|
+ s = start;
|
|
|
e = s + size;
|
|
|
m = info->alignment - 1;
|
|
|
|
|
@@ -380,34 +383,34 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
|
|
|
e = e & ~m;
|
|
|
|
|
|
if (assure_empty(info, 1) < 0)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return (unsigned long) -ENOMEM;
|
|
|
|
|
|
blk = NULL;
|
|
|
list_for_each(l, &info->free_list) {
|
|
|
blk = list_entry(l, rh_block_t, list);
|
|
|
/* The range must lie entirely inside one free block */
|
|
|
- bs = (unsigned long)blk->start;
|
|
|
- be = (unsigned long)blk->start + blk->size;
|
|
|
+ bs = blk->start;
|
|
|
+ be = blk->start + blk->size;
|
|
|
if (s >= bs && e <= be)
|
|
|
break;
|
|
|
blk = NULL;
|
|
|
}
|
|
|
|
|
|
if (blk == NULL)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return (unsigned long) -ENOMEM;
|
|
|
|
|
|
/* Perfect fit */
|
|
|
if (bs == s && be == e) {
|
|
|
/* Delete from free list, release slot */
|
|
|
list_del(&blk->list);
|
|
|
release_slot(info, blk);
|
|
|
- return (void *)s;
|
|
|
+ return s;
|
|
|
}
|
|
|
|
|
|
/* blk still in free list, with updated start and/or size */
|
|
|
if (bs == s || be == e) {
|
|
|
if (bs == s)
|
|
|
- blk->start = (int8_t *)blk->start + size;
|
|
|
+ blk->start += size;
|
|
|
blk->size -= size;
|
|
|
|
|
|
} else {
|
|
@@ -416,25 +419,29 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
|
|
|
|
|
|
/* the back free fragment */
|
|
|
newblk = get_slot(info);
|
|
|
- newblk->start = (void *)e;
|
|
|
+ newblk->start = e;
|
|
|
newblk->size = be - e;
|
|
|
|
|
|
list_add(&newblk->list, &blk->list);
|
|
|
}
|
|
|
|
|
|
- return (void *)s;
|
|
|
+ return s;
|
|
|
}
|
|
|
|
|
|
-void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
|
|
|
+/* Allocate a block of memory at the specified alignment. The value returned
|
|
|
+ * is an offset into the buffer initialized by rh_init(), or a negative number
|
|
|
+ * if there is an error.
|
|
|
+ */
|
|
|
+unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
|
|
|
{
|
|
|
struct list_head *l;
|
|
|
rh_block_t *blk;
|
|
|
rh_block_t *newblk;
|
|
|
- void *start;
|
|
|
+ unsigned long start;
|
|
|
|
|
|
- /* Validate size, (must be power of two) */
|
|
|
+ /* Validate size, and alignment must be power of two */
|
|
|
if (size <= 0 || (alignment & (alignment - 1)) != 0)
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ return (unsigned long) -EINVAL;
|
|
|
|
|
|
/* given alignment larger that default rheap alignment */
|
|
|
if (alignment > info->alignment)
|
|
@@ -444,7 +451,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne
|
|
|
size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
|
|
|
|
|
|
if (assure_empty(info, 1) < 0)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return (unsigned long) -ENOMEM;
|
|
|
|
|
|
blk = NULL;
|
|
|
list_for_each(l, &info->free_list) {
|
|
@@ -455,7 +462,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne
|
|
|
}
|
|
|
|
|
|
if (blk == NULL)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return (unsigned long) -ENOMEM;
|
|
|
|
|
|
/* Just fits */
|
|
|
if (blk->size == size) {
|
|
@@ -475,7 +482,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne
|
|
|
newblk->owner = owner;
|
|
|
|
|
|
/* blk still in free list, with updated start, size */
|
|
|
- blk->start = (int8_t *)blk->start + size;
|
|
|
+ blk->start += size;
|
|
|
blk->size -= size;
|
|
|
|
|
|
start = newblk->start;
|
|
@@ -486,19 +493,25 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne
|
|
|
/* 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));
|
|
|
+ start = (start + alignment - 1) & ~(alignment - 1);
|
|
|
|
|
|
return start;
|
|
|
}
|
|
|
|
|
|
-void *rh_alloc(rh_info_t * info, int size, const char *owner)
|
|
|
+/* Allocate a block of memory at the default alignment. The value returned is
|
|
|
+ * an offset into the buffer initialized by rh_init(), or a negative number if
|
|
|
+ * there is an error.
|
|
|
+ */
|
|
|
+unsigned long rh_alloc(rh_info_t * info, int size, const char *owner)
|
|
|
{
|
|
|
return rh_alloc_align(info, size, info->alignment, owner);
|
|
|
}
|
|
|
|
|
|
-/* allocate at precisely the given address */
|
|
|
-void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
|
|
|
+/* Allocate a block of memory at the given offset, rounded up to the default
|
|
|
+ * alignment. The value returned is an offset into the buffer initialized by
|
|
|
+ * rh_init(), or a negative number if there is an error.
|
|
|
+ */
|
|
|
+unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, const char *owner)
|
|
|
{
|
|
|
struct list_head *l;
|
|
|
rh_block_t *blk, *newblk1, *newblk2;
|
|
@@ -506,10 +519,10 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
|
|
|
|
|
|
/* Validate size */
|
|
|
if (size <= 0)
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ return (unsigned long) -EINVAL;
|
|
|
|
|
|
/* The region must be aligned */
|
|
|
- s = (unsigned long)start;
|
|
|
+ s = start;
|
|
|
e = s + size;
|
|
|
m = info->alignment - 1;
|
|
|
|
|
@@ -520,20 +533,20 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
|
|
|
e = e & ~m;
|
|
|
|
|
|
if (assure_empty(info, 2) < 0)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return (unsigned long) -ENOMEM;
|
|
|
|
|
|
blk = NULL;
|
|
|
list_for_each(l, &info->free_list) {
|
|
|
blk = list_entry(l, rh_block_t, list);
|
|
|
/* The range must lie entirely inside one free block */
|
|
|
- bs = (unsigned long)blk->start;
|
|
|
- be = (unsigned long)blk->start + blk->size;
|
|
|
+ bs = blk->start;
|
|
|
+ be = blk->start + blk->size;
|
|
|
if (s >= bs && e <= be)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (blk == NULL)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return (unsigned long) -ENOMEM;
|
|
|
|
|
|
/* Perfect fit */
|
|
|
if (bs == s && be == e) {
|
|
@@ -551,7 +564,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
|
|
|
/* blk still in free list, with updated start and/or size */
|
|
|
if (bs == s || be == e) {
|
|
|
if (bs == s)
|
|
|
- blk->start = (int8_t *)blk->start + size;
|
|
|
+ blk->start += size;
|
|
|
blk->size -= size;
|
|
|
|
|
|
} else {
|
|
@@ -560,14 +573,14 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
|
|
|
|
|
|
/* The back free fragment */
|
|
|
newblk2 = get_slot(info);
|
|
|
- newblk2->start = (void *)e;
|
|
|
+ newblk2->start = e;
|
|
|
newblk2->size = be - e;
|
|
|
|
|
|
list_add(&newblk2->list, &blk->list);
|
|
|
}
|
|
|
|
|
|
newblk1 = get_slot(info);
|
|
|
- newblk1->start = (void *)s;
|
|
|
+ newblk1->start = s;
|
|
|
newblk1->size = e - s;
|
|
|
newblk1->owner = owner;
|
|
|
|
|
@@ -577,7 +590,11 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
|
|
|
return start;
|
|
|
}
|
|
|
|
|
|
-int rh_free(rh_info_t * info, void *start)
|
|
|
+/* Deallocate the memory previously allocated by one of the rh_alloc functions.
|
|
|
+ * The return value is the size of the deallocated block, or a negative number
|
|
|
+ * if there is an error.
|
|
|
+ */
|
|
|
+int rh_free(rh_info_t * info, unsigned long start)
|
|
|
{
|
|
|
rh_block_t *blk, *blk2;
|
|
|
struct list_head *l;
|
|
@@ -642,7 +659,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
|
|
|
return nr;
|
|
|
}
|
|
|
|
|
|
-int rh_set_owner(rh_info_t * info, void *start, const char *owner)
|
|
|
+int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
|
|
|
{
|
|
|
rh_block_t *blk, *blk2;
|
|
|
struct list_head *l;
|
|
@@ -684,8 +701,8 @@ void rh_dump(rh_info_t * info)
|
|
|
nr = maxnr;
|
|
|
for (i = 0; i < nr; i++)
|
|
|
printk(KERN_INFO
|
|
|
- " 0x%p-0x%p (%u)\n",
|
|
|
- st[i].start, (int8_t *) st[i].start + st[i].size,
|
|
|
+ " 0x%lx-0x%lx (%u)\n",
|
|
|
+ st[i].start, st[i].start + st[i].size,
|
|
|
st[i].size);
|
|
|
printk(KERN_INFO "\n");
|
|
|
|
|
@@ -695,8 +712,8 @@ void rh_dump(rh_info_t * info)
|
|
|
nr = maxnr;
|
|
|
for (i = 0; i < nr; i++)
|
|
|
printk(KERN_INFO
|
|
|
- " 0x%p-0x%p (%u) %s\n",
|
|
|
- st[i].start, (int8_t *) st[i].start + st[i].size,
|
|
|
+ " 0x%lx-0x%lx (%u) %s\n",
|
|
|
+ st[i].start, st[i].start + st[i].size,
|
|
|
st[i].size, st[i].owner != NULL ? st[i].owner : "");
|
|
|
printk(KERN_INFO "\n");
|
|
|
}
|
|
@@ -704,6 +721,6 @@ void rh_dump(rh_info_t * info)
|
|
|
void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
|
|
|
{
|
|
|
printk(KERN_INFO
|
|
|
- "blk @0x%p: 0x%p-0x%p (%u)\n",
|
|
|
- blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
|
|
|
+ "blk @0x%p: 0x%lx-0x%lx (%u)\n",
|
|
|
+ blk, blk->start, blk->start + blk->size, blk->size);
|
|
|
}
|