kmalloc: bugfixes and performance improvements
This commit is contained in:
parent
d4ee4e5953
commit
347bb5cc9c
2 changed files with 62 additions and 11 deletions
|
@ -119,13 +119,23 @@ void clist_del(struct clist *node);
|
||||||
/**
|
/**
|
||||||
* @brief Get the next entry in a clist.
|
* @brief Get the next entry in a clist.
|
||||||
*
|
*
|
||||||
* @param entry The `struct *` embedding a clist to get the sccessor of
|
* @param entry The `struct *` embedding a clist to get the successor of
|
||||||
* @param member Name of the `struct clist` embedded within the entry
|
* @param member Name of the `struct clist` embedded within the entry
|
||||||
* @returns The next `struct *` in the list
|
* @returns The next `struct *` in the list
|
||||||
*/
|
*/
|
||||||
#define clist_next_entry(entry, member) \
|
#define clist_next_entry(entry, member) \
|
||||||
clist_entry((entry)->member.next, typeof(*(entry)), member)
|
clist_entry((entry)->member.next, typeof(*(entry)), member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the previous entry in a clist.
|
||||||
|
*
|
||||||
|
* @param entry the `struct *` embedding a clist to the the predecessor of
|
||||||
|
* @param emember Name of the `struct clist` embedded within the entry
|
||||||
|
* @returns The previous `struct *` in the list
|
||||||
|
*/
|
||||||
|
#define clist_prev_entry(entry, member) \
|
||||||
|
clist_entry((entry)->member.prev, typeof(*(entry)), member)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Iterate over each entry within a list.
|
* @brief Iterate over each entry within a list.
|
||||||
*
|
*
|
||||||
|
@ -134,10 +144,46 @@ void clist_del(struct clist *node);
|
||||||
* @param member Name of the `struct clist` within the embedding structure
|
* @param member Name of the `struct clist` within the embedding structure
|
||||||
*/
|
*/
|
||||||
#define clist_foreach_entry(head, cursor, member) \
|
#define clist_foreach_entry(head, cursor, member) \
|
||||||
for ((cursor) = clist_first_entry(head, typeof((*cursor)), member); \
|
for ((cursor) = clist_first_entry(head, typeof(*(cursor)), member); \
|
||||||
&(cursor)->member != (head); \
|
&(cursor)->member != (head); \
|
||||||
(cursor) = clist_next_entry(cursor, member))
|
(cursor) = clist_next_entry(cursor, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Continue iterating over each entry within a clist.
|
||||||
|
*
|
||||||
|
* @param head The `struct clist *` that is the head node in the list
|
||||||
|
* @param cursor The `struct *` list entry from which to continue
|
||||||
|
* @param member Name of the `struct clist` within the embedding structure
|
||||||
|
*/
|
||||||
|
#define clist_foreach_entry_continue(head, cursor, member) \
|
||||||
|
for ((cursor) = clist_next_entry(cursor, member); \
|
||||||
|
&(cursor)->member != (head); \
|
||||||
|
(cursor) = clist_next_entry(cursor, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Iterate over a clist in reverse order.
|
||||||
|
*
|
||||||
|
* @param head The `struct clist *` that is the head node in the list
|
||||||
|
* @param cursor A `struct *` the list nodes are embedded in to use as a cursor
|
||||||
|
* @param member Name of the `struct clist` within the embedding structure
|
||||||
|
*/
|
||||||
|
#define clist_foreach_entry_rev(head, cursor, member) \
|
||||||
|
for ((cursor) = clist_last_entry(head, typeof(*(cursor)), member); \
|
||||||
|
&(cursor)->member != (head); \
|
||||||
|
(cursor) = clist_prev_entry(cursor, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Continue iterating over a clist in reverse order.
|
||||||
|
*
|
||||||
|
* @param head The `struct clist *` that is the head node in the list
|
||||||
|
* @param cursor The `struct *` list entry from which to continue
|
||||||
|
* @param member Name of the `struct clist` within the embedding structure
|
||||||
|
*/
|
||||||
|
#define clist_foreach_entry_rev_continue(head, cursor, member) \
|
||||||
|
for ((cursor) = clist_prev_entry(cursor, member); \
|
||||||
|
&(cursor)->member != (head); \
|
||||||
|
(cursor) = clist_prev_entry(cursor, member))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Iterate over each entry within a list, this is safe from element removal.
|
* @brief Iterate over each entry within a list, this is safe from element removal.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* doesn't have paging:
|
* doesn't have paging:
|
||||||
* <https://git.bsd.gay/fef/ardix/src/commit/c767d551d3301fc30f9fce30eda8f04e2f9a42ab/kernel/mm.c>
|
* <https://git.bsd.gay/fef/ardix/src/commit/c767d551d3301fc30f9fce30eda8f04e2f9a42ab/kernel/mm.c>
|
||||||
* As a matter of fact, this allocator is merely an extension of the one from
|
* As a matter of fact, this allocator is merely an extension of the one from
|
||||||
* Ardix with the only difference being that the heap can grow upwards.
|
* Ardix with the only difference being that the heap can be extended upwards.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +46,7 @@ struct memblk {
|
||||||
/** @brief Used as the return value for `kmalloc()` */
|
/** @brief Used as the return value for `kmalloc()` */
|
||||||
u8 data[0];
|
u8 data[0];
|
||||||
/**
|
/**
|
||||||
* @brief Used to get the copy of the low_size field at the end of
|
* @brief Used to get the copy of the size at the end of
|
||||||
* the block, right after the last byte of `data`
|
* the block, right after the last byte of `data`
|
||||||
*/
|
*/
|
||||||
usize high_size[0];
|
usize high_size[0];
|
||||||
|
@ -274,7 +274,7 @@ static struct memblk *blk_try_merge(struct memblk *blk)
|
||||||
if (blk_get_size(cursor) >= blk_get_size(blk))
|
if (blk_get_size(cursor) >= blk_get_size(blk))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
clist_add_first(&cursor->clink, &blk->clink);
|
clist_add(&cursor->clink, &blk->clink);
|
||||||
|
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
@ -292,13 +292,14 @@ static struct memblk *blk_merge(struct memblk *bottom, struct memblk *top)
|
||||||
|
|
||||||
static struct memblk *blk_slice(struct memblk *blk, usize slice_size)
|
static struct memblk *blk_slice(struct memblk *blk, usize slice_size)
|
||||||
{
|
{
|
||||||
|
struct memblk *cursor = clist_prev_entry(blk, clink);
|
||||||
clist_del(&blk->clink);
|
clist_del(&blk->clink);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the remaining low_size is less than the minimum allocation unit, we
|
* If the remaining size is less than the minimum allocation unit, we
|
||||||
* hand out the entire block. Additionally, we must add an underflow
|
* hand out the entire block. Additionally, we must add an underflow
|
||||||
* check which happens if the slice low_size is less than OVERHEAD smaller
|
* check which happens if the slice size is less than OVERHEAD smaller
|
||||||
* than the full block low_size.
|
* than the full block size.
|
||||||
*/
|
*/
|
||||||
usize rest_size = blk_get_size(blk) - slice_size - OVERHEAD;
|
usize rest_size = blk_get_size(blk) - slice_size - OVERHEAD;
|
||||||
if (rest_size < MIN_SIZE || rest_size + OVERHEAD < rest_size) {
|
if (rest_size < MIN_SIZE || rest_size + OVERHEAD < rest_size) {
|
||||||
|
@ -316,8 +317,7 @@ static struct memblk *blk_slice(struct memblk *blk, usize slice_size)
|
||||||
blk_set_alloc(blk);
|
blk_set_alloc(blk);
|
||||||
blk_clear_border_end(blk);
|
blk_clear_border_end(blk);
|
||||||
|
|
||||||
struct memblk *cursor;
|
clist_foreach_entry_rev_continue(&blocks, cursor, clink) {
|
||||||
clist_foreach_entry(&blocks, cursor, clink) {
|
|
||||||
if (blk_get_size(cursor) <= rest_size)
|
if (blk_get_size(cursor) <= rest_size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -348,6 +348,11 @@ static inline struct memblk *blk_next(struct memblk *blk)
|
||||||
|
|
||||||
static inline usize blk_get_size(struct memblk *blk)
|
static inline usize blk_get_size(struct memblk *blk)
|
||||||
{
|
{
|
||||||
|
# ifdef DEBUG
|
||||||
|
usize index = blk->low_size[0] / sizeof(blk->low_size[0]);
|
||||||
|
if ((blk->low_size[0] & SIZE_MASK) != (blk->high_size[index] & SIZE_MASK))
|
||||||
|
kprintf("Memory corruption in block %p detected!\n", blk);
|
||||||
|
# endif
|
||||||
return blk->low_size[0] & SIZE_MASK;
|
return blk->low_size[0] & SIZE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +361,7 @@ static void blk_set_size(struct memblk *blk, usize size)
|
||||||
/* don't affect flags */
|
/* don't affect flags */
|
||||||
blk->low_size[0] &= ~SIZE_MASK;
|
blk->low_size[0] &= ~SIZE_MASK;
|
||||||
# ifdef DEBUG
|
# ifdef DEBUG
|
||||||
if (size & SIZE_MASK)
|
if (size & ~SIZE_MASK)
|
||||||
kprintf("Unaligned size in blk_set_size()\n");
|
kprintf("Unaligned size in blk_set_size()\n");
|
||||||
# endif
|
# endif
|
||||||
blk->low_size[0] |= size & SIZE_MASK;
|
blk->low_size[0] |= size & SIZE_MASK;
|
||||||
|
|
Loading…
Reference in a new issue