1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-11-04 22:54:03 +02:00
iris/memory.ccp
2009-07-23 12:06:32 +02:00

147 lines
3.6 KiB
COBOL

#pypp 0
#include "kernel.hh"
extern unsigned _end
static void clear_page (unsigned page, unsigned num = 1):
for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i:
((unsigned *)page)[i] = 0
#if 0
static unsigned free_begin
static unsigned free_end
unsigned init_memory (unsigned mem):
free_begin = ((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK
free_end = (0x80000000 + mem) & PAGE_MASK
return (free_end - free_begin) >> PAGE_BITS
unsigned phys_alloc (unsigned num):
if free_begin + num * PAGE_SIZE > free_end:
panic (0xaaaaaaaa, "out of memory")
unsigned ret = free_begin
free_begin += num * PAGE_SIZE
clear_page (ret, num)
return ret
void phys_free (unsigned page, unsigned num):
// Not supported.
#else
struct FreePages:
FreePages *prev, *next
unsigned num
static FreePages *first_free
unsigned init_memory (unsigned mem):
first_free = (FreePages *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
first_free->prev = NULL
first_free->next = NULL
first_free->num = ((mem & PAGE_MASK) - ((unsigned)first_free - 0x80000000)) >> PAGE_BITS
return first_free->num
unsigned phys_alloc (unsigned num):
FreePages *choice = NULL
for FreePages *p = first_free; p; p = p->next:
if p->num < num:
continue
if choice && choice->num < p->num:
continue
choice = p
if !choice:
// TODO: reorganizing may work to allow allocation.
panic (0x01100223, "out of large enough memory")
return 0
if choice->num == num:
if choice->prev:
choice->prev->next = choice->next
else:
first_free = choice->next
if choice->next:
choice->next->prev = choice->prev
clear_page ((unsigned)choice, num)
return (unsigned)choice
choice->num -= num
unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS)
clear_page (ret, num)
return ret
void phys_free (unsigned page, unsigned num):
return
unsigned size = num << PAGE_BITS
if !first_free || (unsigned)first_free > page:
// This is the first free block.
FreePages *n = (FreePages *)page
n->prev = NULL
if (unsigned)first_free == page + size:
// It fits exactly before the previous first free block.
n->next = first_free->next
n->num = num + first_free->num
else:
// It is a new block.
n->next = first_free
n->num = num
first_free = n
if n->next:
n->next->prev = n
return
FreePages *p
for p = first_free; p->next && (unsigned)p->next < page; p = p->next:
// Do nothing.
// The new block should be inserted directly after p.
if (unsigned)p->next == page + size:
// It can be merged with the block after it: do that.
FreePages *n = (FreePages *)page
n->prev = p
n->next = p->next->next
if n->next:
n->next->prev = n
n->num = num + p->next->num
p->next = n
if (unsigned)p + (p->num << PAGE_BITS) == (unsigned)n:
// It can also be merged with the page before it: do that as well.
p->num += n->num
p->next = n->next
if p->next:
p->next->prev = p
return
// The new block cannot be merged with the block after it.
if (unsigned)p + (p->num << PAGE_BITS) == page:
// But it can be merged with the one before it: do that.
p->num += num
return
// The new block cannot be merged at all.
FreePages *n = (FreePages *)page
n->next = p->next
n->prev = p
if n->next:
n->next->prev = n
p->next = n
n->num = num
#endif
unsigned raw_zalloc ():
return phys_alloc (1)
void raw_pfree (unsigned page):
return phys_free (page, 1)
unsigned Memory::zalloc ():
if !use ():
assert (false)
return NULL
return raw_zalloc ()
void Memory::pfree (unsigned page):
unuse ()
return raw_pfree (page)
unsigned Memory::palloc ():
return zalloc ()
void Memory::zfree (unsigned page):
pfree (page)