Code: Select all
/* heap.cpp: Allocation code for my operating system. Uses a linked list to maintain heap data. */
// standard includes
#include <stdint.h>
#include <_null.h>
// kernel includes
#include <kernel/heap.h>
#include <kernel/mmngr_virt.h>
#include <kernel/mmngr_phys.h>
/* internal definitions/constants/macros */
#define BLOCK_SIZE 4096
typedef long Align; // this helps us align memory headers on long boundaries
/* internal (private) structures/enums */
union heap_header {
struct {
heap_header *next; // point to the next allocation/free block
unsigned int alloc_sz; // allocation size
} s;
Align x;
};
/* internal (private) globals */
static heap_header _heap_base;
static heap_header *_heap_free=0;
static uint32_t _virt_addr = 0xb0000000;
/* internal (private) routines */
heap_header *morecore () {
char *cp;
heap_header *up;
cp = (char *) pmmngr_alloc_block (); // allocate more memory for the heap
// if cp is null we have no memory left
if (cp == NULL)
return NULL;
vmmngr_map_page (cp, (void *) _virt_addr); // and map it's virtual address to it's physical address
_virt_addr += BLOCK_SIZE; // tack on nu bytes to the virtual address; this will be our next allocation address
up = (heap_header *) cp;
up->s.alloc_sz = BLOCK_SIZE;
heap_free ((void *)(up+1));
return _heap_free;
}
/* external interface (public) routine implementation */
// void *malloc (unsigned int nbytes): Allocate nbytes from the heap
// Inputs: nbytes-number of bytes to allocate
// Returns: pointer to a block of memory of nbytes; NULL on error
void *heap_alloc (unsigned int nbytes) {
heap_header *p, *prev_p; // used to keep track of the current unit
unsigned int nunits; // this is the number of "allocation units" needed by nbytes of memory
nunits = (nbytes + sizeof (heap_header) - 1) / sizeof (heap_header) + 1; // see how much we will need to allocate for this call
// check to see if the list has been created yet; start it if not
if ((prev_p = _heap_free) == NULL) {
_heap_base.s.next = _heap_free = prev_p = &_heap_base; // point at the base of the memory
_heap_base.s.alloc_sz = 0; // and set it's allocation size to zero
}
// now enter a for loop to find a block fo memory
for (p = prev_p->s.next;; prev_p = p, p = p->s.next) {
// did we find a big enough block?
if (p->s.alloc_sz >= nunits) {
// the block is exact length
if (p->s.alloc_sz == nunits)
prev_p->s.next = p->s.next;
// the block needs to be cut
else {
p->s.alloc_sz -= nunits;
p += p->s.alloc_sz;
p->s.alloc_sz = nunits;
}
_heap_free = prev_p;
return (void *)(p+1);
}
// not enough space!! Try to get more from the kernel
if (p == _heap_free) {
// if the kernel has no more memory, return error!
if ((p = morecore ()) == NULL)
return NULL;
}
}
}
// void heap_free (void *ap): Free the block of memory at *ap from the heap
// Inputs: ap-memory block to free
// Returns: None
void heap_free (void *ap) {
heap_header *bp, *p;
bp = (heap_header *) ap-1;
for (p = _heap_free; !(bp > p && bp < p->s.next); p = p->s.next) {
if (p >= p->s.next && (bp > p || bp < p->s.next))
break;
}
// join to upper allocation
if (bp + bp->s.alloc_sz == p->s.next) {
bp->s.alloc_sz += p->s.next->s.alloc_sz;
bp->s.next = p->s.next->s.next;
}
else
bp->s.next = p->s.next;
if (p + p->s.alloc_sz == bp) {
p->s.alloc_sz += bp->s.alloc_sz;
p->s.next = bp->s.next;
}
else
p->s.next = bp;
_heap_free = p;
}
Code: Select all
int load_executable (char *cmd, int argCount, char *args) {
// print a message regarding load attempt
printf ("\nAttempting to load executable %s...\n", cmd);
// map a 512-byte section at 0x1000
unsigned char *executable = (unsigned char *) heap_alloc (512);
vmmngr_map_page ((void *) executable, (void *) 0x1000);
// read the file in
FILE exe_file_ptr = volOpenFile (cmd);
volReadFile (&exe_file_ptr, executable, 512);
volCloseFile (&exe_file_ptr);
// now cast the buffer and jump there
((flat_exe)executable)();
return 0;
}
Code: Select all
org 0x1000
bits 32
mov eax,0x12345678
ret
nasm test.asm -o b:\test.exe -f bin
It seems to cause this problem whenever I try to allocate multiple blocks. I have a little more info to gather and I will post any updates I have. Advice is, as always, very appreciated!