/** * Allocates a region on the kernel's heap */ void *kalloc(uint32_t size) { //kc_printf("Alloc\n"); struct heap_block_hdr_t *p, *prevp; unsigned nunits; nunits = (size + sizeof(struct heap_block_hdr_t) - 1) / sizeof(struct heap_block_hdr_t) + 1; if((prevp = kernel_heap_free) == NULL) { kernel_heap_free_base.block_size = 0; kernel_heap_free = prevp = &kernel_heap_free_base; kernel_heap_free_base.next_block = kernel_heap_free; } for(p = prevp->next_block; ; prevp = p, p = p->next_block) { if(p->block_size >= nunits) { if(p->block_size == nunits) { prevp->next_block = p->next_block; } else { // Not all units required, relocate header p->block_size -= nunits; p += p->block_size; p->block_size = nunits; } kernel_heap_free = prevp; //kc_printf("OK (%x)\n", (uint32_t) (p+1)); return (void *) (p + 1); } if(p == kernel_heap_free) if(kbrk() == NULL) return NULL; } }
/***************************************************************************** kmalloc() and kfree() use g_heap_bot, but not g_kbrk nor g_heap_top *****************************************************************************/ void *kmalloc(size_t size) { unsigned total_size; malloc_t *m, *n; int delta; if(size == 0) return NULL; total_size = size + sizeof(malloc_t); /* search heap for free block (FIRST FIT) */ m = (malloc_t *)g_heap_bot; /* g_heap_bot == 0 == NULL if heap does not yet exist */ if(m != NULL) { if(m->magic != MALLOC_MAGIC) // panic("kernel heap is corrupt in kmalloc()"); { printf("*** kernel heap is corrupt in kmalloc()\n"); return NULL; } for(; m->next != NULL; m = m->next) { if(m->used) continue; /* size == m->size is a perfect fit */ if(size == m->size) m->used = 1; else { /* otherwise, we need an extra sizeof(malloc_t) bytes for the header of a second, free block */ if(total_size > m->size) continue; /* create a new, smaller free block after this one */ n = (malloc_t *)((char *)m + total_size); n->size = m->size - total_size; n->next = m->next; n->magic = MALLOC_MAGIC; n->used = 0; /* reduce the size of this block and mark it used */ m->size = size; m->next = n; m->used = 1; } return (char *)m + sizeof(malloc_t); } } /* use kbrk() to enlarge (or create!) heap */ delta = total_size; n = kbrk(&delta); /* uh-oh */ if(n == NULL) return NULL; if(m != NULL) m->next = n; n->size = size; n->magic = MALLOC_MAGIC; n->used = 1; /* did kbrk() return the exact amount of memory we wanted? cast to make "gcc -Wall -W ..." shut the hell up */ if((int)total_size == delta) n->next = NULL; else { /* it returned more than we wanted (it will never return less): create a new, free block */ m = (malloc_t *)((char *)n + total_size); m->size = delta - total_size - sizeof(malloc_t); m->next = NULL; m->magic = MALLOC_MAGIC; m->used = 0; n->next = m; } return (char *)n + sizeof(malloc_t); }
static void *core_palloc(size_t size) { unsigned total_size; palloc_t *m, *n; int delta; if(size == 0) return NULL; total_size = size + sizeof(palloc_t); /* search heap for free block (FIRST FIT) */ m = (palloc_t *)p_heap_bottom; /* p_heap_bottom == 0 == NULL if heap does not yet exists */ if(m != NULL) { for( ;m -> next != NULL; m = m -> next) { /* Check the heap nodes already allocated */ if(check_magic(m) == FALSE) { if(palloc_error_message(m) == TRUE) return NULL; } if(m -> used) { continue; } /* size == m -> size is a perfect fit */ if(size == m -> size) { m -> used = 1; } else { /* otherwise, we need an extra sizeof(palloc_t) bytes for the header * of a second, free block. */ if(total_size > m -> size) continue; /* create a new, smaller free block after this one. */ n = (palloc_t *)((char *)m + total_size); n -> size = m -> size - total_size; n -> next = m -> next; n -> magic = PALLOC_MAGIC; /* An extra check to make sure all nodes allocated are proper */ if(check_magic(m) == FALSE) { palloc_error_message(m); return NULL; } n -> used = 0; /* reduce the size of this block and mark it used. */ m -> size = size; m -> next = n; m -> used = 1; } /* return location of memory that is after palloc_t node (header) */ return (char *)m + sizeof(palloc_t); } } /* Check the heap nodes already allocated */ if(check_magic(m) == FALSE) { if(palloc_error_message(m) == TRUE) return NULL; } /* use kbrk() to enlarge (or create!) heap */ delta = total_size; n = kbrk(&delta); /* oops! allocation failed */ if(n == NULL) return NULL; if(m != NULL) { m -> next = n; } n -> size = size; n -> magic = PALLOC_MAGIC; n -> used = 1; /* did kbrk() return exact amount of memory we wanted? */ if((int) total_size == delta) n -> next = NULL; else { /* it returned more than we wanted (it will never return less) * create a new, free block. */ m = (palloc_t *)((char *)n + total_size); m -> size = delta - total_size - sizeof(palloc_t); m -> next = NULL; m -> magic = PALLOC_MAGIC; m -> used = 0; n -> next = m; } /* return location of memory that is after palloc_t node (header) */ return (char *) n + sizeof(palloc_t); }