* along with Corax. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <corax/errno.h>
#include <debug.h>
#include "paging.h"
#include "heap.h"
static int heap_grow(const u32_t size)
{
- struct heap_node *cur;
+ struct heap_node *last;
struct heap_node *new;
u32_t sreq;
+ u32_t allocated;
int ret_val;
new = NULL;
- ret_val = 1;
+ ret_val = -ENOMEM;
+ allocated = 0;
- /* add more pages to the pagedir */
+ last = (struct heap_node*)_kheap.h_base;
+
+ while(last->hn_next) {
+ last = last->hn_next;
+ }
+ /* add more pages to the pagedir */
for(sreq = ALIGN(size << 2, PAGE_SIZE); sreq > 0; sreq -= PAGE_SIZE) {
void *addr;
break;
}
- if(!new) {
- new = (struct heap_node*)addr;
- cur = (struct heap_node*)_kheap.h_base;
+ if(!(last->hn_flags & FLAG_USED)) {
+ /* add memory to the last, unused node */
+ last->hn_size += PAGE_SIZE;
+ allocated += PAGE_SIZE;
+ } else {
+ /* add memory to a new node at the end */
- new->hn_size = PAGE_SIZE - sizeof(*new);
- new->hn_flags = 0;
- new->hn_next = NULL;
+ if(!new) {
+ /* create the new node */
+ new = (struct heap_node*)addr;
- /* add new node to the end of the heap */
- while(cur->hn_next) {
- cur = cur->hn_next;
- }
+ new->hn_next = NULL;
+ last->hn_next = new;
- cur->hn_next = new;
- } else {
- new->hn_size += PAGE_SIZE;
+ new->hn_size = PAGE_SIZE - sizeof(*new);
+ new->hn_flags = 0;
+ } else {
+ /* node has already been created - expand it */
+ new->hn_size += PAGE_SIZE;
+ allocated += PAGE_SIZE;
+ }
}
}
- if(new) {
- _kheap.h_size += new->hn_size;
+ _kheap.h_size += allocated;
+ _kheap.h_free += allocated;
+
+ /* return success if we allocated enough to satisfy the request */
+ if(size <= allocated) {
ret_val = 0;
}
heap_grow(size);
}
+ heap_debug();
+
for(cur = (struct heap_node*)_kheap.h_base;
cur;
cur = cur->hn_next) {
new = (struct heap_node*)(ret_val + size);
- new->hn_size = cur->hn_size - size - (2 * sizeof(*new));
+ /*
+ * |<--- cur->hn_size --->|
+ * +-----+----------+-----+----------------+--------------+
+ * | cur | < size > | new | <new->hn_size> | cur->hn_next |
+ * +-----+----------+-----+----------------+--------------+
+ */
+ new->hn_size = cur->hn_size - size - sizeof(*new);
new->hn_next = cur->hn_next;
new->hn_flags = 0;