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

214 lines
5.6 KiB
Plaintext
Raw Normal View History

#pypp 0
#include "kernel.hh"
extern unsigned _end
2009-07-20 01:23:45 +03:00
2009-07-23 13:06:32 +03:00
static void clear_page (unsigned page, unsigned num = 1):
2009-12-18 10:00:38 +02:00
page = (page & ~0xc0000000) | 0xa0000000
2009-07-23 13:06:32 +03:00
for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i:
2009-07-20 01:23:45 +03:00
((unsigned *)page)[i] = 0
2009-12-11 10:43:42 +02:00
if *((unsigned *)page) != 0 || ((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1] != 0:
dpanic (0, "clear_page didn't work")
2009-07-20 01:23:45 +03:00
2009-12-27 01:12:35 +02:00
#if 0
2009-07-23 13:06:32 +03:00
2009-07-20 01:23:45 +03:00
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:
2009-07-25 01:54:12 +03:00
dbg_log ("memory allocation failed\n")
2009-07-24 15:25:53 +03:00
return 0
2009-07-20 01:23:45 +03:00
unsigned ret = free_begin
free_begin += num * PAGE_SIZE
2009-07-23 13:06:32 +03:00
clear_page (ret, num)
2009-07-20 01:23:45 +03:00
return ret
void phys_free (unsigned page, unsigned num):
// Not supported.
2009-08-24 22:02:35 +03:00
#ifndef NDEBUG
2009-12-26 15:17:06 +02:00
/*void check_impl (kObject *o, unsigned num, char const *msg):
// for ; o; o = (kObject *)o->next:
// if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end:
*/ // panic (num, msg)
bool check_free (kObject *o, unsigned size):
return true
2009-10-10 02:31:10 +03:00
void print_free ():
2009-08-24 22:02:35 +03:00
#endif
2009-07-23 13:06:32 +03:00
#else
struct kFreePages:
kFreePages *prev, *next
2009-07-20 01:23:45 +03:00
unsigned num
static kFreePages *first_free
2009-07-20 01:23:45 +03:00
unsigned init_memory (unsigned mem):
first_free = (kFreePages *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
2009-07-20 01:23:45 +03:00
first_free->prev = NULL
first_free->next = NULL
2009-12-11 10:43:42 +02:00
first_free->num = ((mem & PAGE_MASK) - ((unsigned)first_free & ~0xc0000000)) >> PAGE_BITS
2009-12-18 10:00:38 +02:00
//dbg_log ("initial memory: ")
//dbg_log_num ((unsigned)first_free & ~0xc0000000)
//dbg_log ("+")
//dbg_log_num (first_free->num)
//dbg_log ("\n")
2009-07-20 01:23:45 +03:00
return first_free->num
unsigned phys_alloc (unsigned num):
kFreePages *choice = NULL
for kFreePages *p = first_free; p; p = p->next:
2009-07-20 01:23:45 +03:00
if p->num < num:
continue
if choice && choice->num < p->num:
continue
2009-08-24 22:02:35 +03:00
if p->num == num:
if p->prev:
p->prev->next = p->next
else:
first_free = p->next
if p->next:
p->next->prev = p->prev
clear_page ((unsigned)p, num)
2009-12-18 10:00:38 +02:00
//dbg_log ("allocating ")
//dbg_log_num ((unsigned)p & ~0xc0000000)
//dbg_log ("+")
//dbg_log_num (num << PAGE_BITS)
//dbg_log ("\n")
2009-08-24 22:02:35 +03:00
return (unsigned)p
2009-07-20 01:23:45 +03:00
choice = p
if !choice:
// TODO: reorganizing may work to allow allocation.
2009-08-24 22:02:35 +03:00
dpanic (0x03948859, "range memory allocation failed")
2009-07-20 01:23:45 +03:00
return 0
choice->num -= num
unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS)
clear_page (ret, num)
2009-12-18 10:00:38 +02:00
//dbg_log ("allocating ")
//dbg_log_num (ret & ~0xc0000000)
//dbg_log ("+")
//dbg_log_num (num << PAGE_BITS)
//dbg_log ("\n")
2009-07-20 01:23:45 +03:00
return ret
void phys_free (unsigned page, unsigned num):
2009-12-18 10:00:38 +02:00
//dbg_log ("free ")
//dbg_log_num (page & ~0xc0000000)
//dbg_log ("+")
//dbg_log_num (num)
//dbg_log ("\n")
2009-07-20 01:23:45 +03:00
unsigned size = num << PAGE_BITS
if !first_free || (unsigned)first_free > page:
// This is the first free block.
kFreePages *n = (kFreePages *)page
2009-07-20 01:23:45 +03:00
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
kFreePages *p
2009-07-20 01:23:45 +03:00
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.
kFreePages *n = (kFreePages *)page
2009-07-20 01:23:45 +03:00
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.
kFreePages *n = (kFreePages *)page
2009-07-20 01:23:45 +03:00
n->next = p->next
n->prev = p
if n->next:
n->next->prev = n
p->next = n
n->num = num
2009-08-24 22:02:35 +03:00
#ifndef NDEBUG
2009-10-10 02:31:10 +03:00
bool check_free (kObject *o, unsigned size):
for kFreePages *p = first_free; p; p = p->next:
if (unsigned)o + size > (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
return false
return true
void print_free ():
dbg_log ("Free pages: ")
for kFreePages *p = first_free; p; p = p->next:
dbg_log_num ((unsigned)p)
dbg_log (":")
dbg_log_num (p->num, 4)
dbg_log ("->")
dbg_log ("NULL\n")
2009-08-24 22:02:35 +03:00
#endif
#endif
#ifndef NDEBUG
void check_memory (kMemory *mem, unsigned num, char const *msg):
check_impl (mem->pages, num, msg)
check_impl (mem->threads, num, msg)
check_impl (mem->receivers, num, msg)
2009-10-10 02:31:10 +03:00
for kReceiver *r = mem->receivers; r; r = (kReceiver *)r->next:
check_impl (r->messages, num, msg)
2009-08-24 22:02:35 +03:00
check_impl (mem->capses, num, msg)
check_impl (mem->memories, num, msg)
for kMemory *m = mem->memories; m; m = (kMemory *)m->next:
check_memory (m, num, msg)
void check (unsigned num, char const *msg):
check_memory (&top_memory, num, msg)
2009-10-10 02:31:10 +03:00
top_memory.check (num)
2009-07-20 01:23:45 +03:00
#endif
unsigned raw_zalloc ():
2009-07-20 01:23:45 +03:00
return phys_alloc (1)
void raw_pfree (unsigned page):
2009-07-20 01:23:45 +03:00
return phys_free (page, 1)
unsigned kMemory::zalloc ():
if !use ():
2009-08-24 22:02:35 +03:00
dpanic (0x34638920, "limit reached: allocation not allowed")
dbg_log ("limit reached: allocation not allowed\n")
return NULL
return raw_zalloc ()
void kMemory::pfree (unsigned page):
unuse ()
return raw_pfree (page)
unsigned kMemory::palloc ():
2009-07-20 01:23:45 +03:00
return zalloc ()
void kMemory::zfree (unsigned page):
2009-07-20 01:23:45 +03:00
pfree (page)