1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 02:15:27 +03:00
iris/alloc.ccp

295 lines
7.3 KiB
Plaintext
Raw Normal View History

2009-05-19 00:18:23 +03:00
#pypp 0
2009-05-18 10:30:27 +03:00
#include "kernel.hh"
2009-05-20 23:07:56 +03:00
// TODO: avoid recursion.
2009-05-19 00:18:23 +03:00
bool Memory::use ():
if used >= limit:
return false
if !parent || parent->use ():
++used
return true
return false
void Memory::unuse ():
2009-05-22 23:48:49 +03:00
--used
2009-05-19 00:18:23 +03:00
return parent->unuse ()
2009-05-22 23:48:49 +03:00
unsigned Memory::palloc ():
2009-05-19 00:18:23 +03:00
if !use ():
2009-05-18 10:30:27 +03:00
return NULL
FreePage *ret = junk_pages
if !ret:
ret = zero_pages
zero_pages = ret->next
else:
junk_pages = ret->next
2009-05-22 23:48:49 +03:00
return (unsigned)ret
2009-05-18 10:30:27 +03:00
2009-05-22 23:48:49 +03:00
unsigned Memory::zalloc ():
2009-05-19 00:18:23 +03:00
if !use ():
2009-05-18 10:30:27 +03:00
return NULL
FreePage *ret = zero_pages
if !ret:
ret = junk_pages
2009-05-23 21:55:31 +03:00
for unsigned i = 1; i < (PAGE_SIZE >> 2); ++i:
2009-05-18 10:30:27 +03:00
((unsigned *)ret)[i] = 0
junk_pages = ret->next
else:
zero_pages = ret->next
ret->next = NULL
2009-05-22 23:48:49 +03:00
return (unsigned)ret
2009-05-18 10:30:27 +03:00
2009-05-22 23:48:49 +03:00
void Memory::pfree (unsigned page):
2009-05-18 10:30:27 +03:00
FreePage *p = (FreePage *)page
p->next = junk_pages
junk_pages = p
2009-05-22 23:48:49 +03:00
void Memory::zfree (unsigned page):
2009-05-18 10:30:27 +03:00
FreePage *p = (FreePage *)page
p->next = zero_pages
zero_pages = p
2009-05-19 00:18:23 +03:00
void *Memory::search_free (unsigned size, void **first):
2009-05-18 10:30:27 +03:00
Free *f
unsigned s = 0
for f = frees; f; f = f->next:
if f->next_obj:
2009-05-19 00:18:23 +03:00
s = (unsigned)f->next_obj - (unsigned)f
2009-05-18 10:30:27 +03:00
else:
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK)
if s >= size:
break
if !f:
f = (Free *)palloc ()
if !f:
return NULL
f->marker = ~0
f->next = frees
f->prev = NULL
frees = f
if f->next:
f->next->prev = f
f->next_obj = NULL
f->prev_obj = NULL
s = PAGE_SIZE
// We have a free block, possibly too large.
if s >= size + sizeof (Free):
// Create the new object at the end and keep the Free.
Free *obj = (Free *)((unsigned)f + s - size)
obj->next_obj = f->next_obj
2009-05-19 00:18:23 +03:00
if obj->next_obj:
2009-05-18 10:30:27 +03:00
obj->next_obj->prev_obj = obj
obj->prev_obj = f
f->next_obj = obj
f = obj
else:
if f->prev:
f->prev->next = f->next
else:
frees = f->next
if f->next:
f->next->prev = f->prev
2009-05-19 00:18:23 +03:00
f->next = (Free *)*first
2009-05-18 10:30:27 +03:00
f->prev = NULL
if f->next:
f->next->prev = f
2009-05-19 00:18:23 +03:00
*first = f
2009-05-18 10:30:27 +03:00
return f
void Object_base::free_obj (Memory *parent):
Free *self
// Merge with previous, if it exists and is a Free.
if prev_obj && prev_obj->is_free ():
self = (Free *)prev_obj
self->next_obj = next_obj
if next_obj:
next_obj->prev_obj = self
else:
self = (Free *)this
self->next = parent->frees
self->prev = NULL
if self->next:
self->next->prev = self
parent->frees = self
self->marker = ~0
// Merge with next, if it exists and is a Free.
if self->next_obj && self->next_obj->is_free ():
self->next_obj = self->next_obj->next_obj
if self->next_obj:
self->next_obj->prev_obj = self
// Free page if the resulting object is the only thing in it.
if !self->prev_obj && !self->next_obj:
if self->next:
self->next->prev = self->prev
if self->prev:
self->prev->next = self->next
else:
parent->frees = self->next
2009-05-22 23:48:49 +03:00
parent->pfree ((unsigned)self)
2009-05-18 10:30:27 +03:00
Page *Memory::alloc_page ():
2009-05-19 00:18:23 +03:00
Page *ret = (Page *)search_free (sizeof (Page), (void **)&pages)
2009-05-22 23:48:49 +03:00
ret->physical = 0
2009-05-18 10:30:27 +03:00
return ret
Thread *Memory::alloc_thread ():
2009-05-19 00:18:23 +03:00
Thread *ret = (Thread *)search_free (sizeof (Thread), (void **)&threads)
2009-05-18 10:30:27 +03:00
ret->address_space = this
ret->pc = 0
ret->sp = 0
Thread_arch_init (ret)
ret->schedule_prev = NULL
ret->schedule_next = NULL
return ret
2009-05-20 23:07:56 +03:00
Message *Memory::alloc_message (Capability *source):
Message *ret = (Message *)search_free (sizeof (Message), (void **)&source->target->messages)
for unsigned i = 0; i < 4; ++i:
ret->capabilities[i] = NULL
ret->data[i] = 0
ret->protected_data = source->protected_data
return ret
Receiver *Memory::alloc_receiver ():
Receiver *ret = (Receiver *)search_free (sizeof (Receiver), (void **)&receivers)
ret->owner = NULL
ret->prev_owned = NULL
ret->next_owned = NULL
ret->capabilities = NULL
ret->messages = NULL
return ret
Capability *Memory::alloc_capability (Receiver *target, Capability **parent, unsigned protected_data):
Capability *ret = (Capability *)search_free (sizeof (Capability), (void **)&capabilities)
ret->target = target
ret->children = NULL
ret->sibling_prev = NULL
ret->sibling_next = parent ? *parent : NULL
if ret->sibling_next:
ret->sibling_next->sibling_prev = ret
ret->protected_data = protected_data
return ret
2009-05-18 10:30:27 +03:00
Memory *Memory::alloc_memory ():
2009-05-19 00:18:23 +03:00
Memory *ret = (Memory *)search_free (sizeof (Memory), (void **)&memories)
ret->parent = this
2009-05-18 10:30:27 +03:00
ret->frees = NULL
ret->pages = NULL
ret->threads = NULL
ret->memories = NULL
ret->limit = ~0
ret->used = 0
Memory_arch_init (ret)
return ret
2009-05-19 00:18:23 +03:00
void Memory::free_page (Page *page):
if page->prev:
page->prev->next = page->next
else:
pages = page->next
if page->next:
page->next->prev = page->prev
unuse ()
pfree (page->physical)
2009-05-20 23:07:56 +03:00
page->free_obj (this)
2009-05-19 00:18:23 +03:00
void Memory::free_thread (Thread *thread):
if thread->prev:
thread->prev->next = thread->next
else:
threads = thread->next
if thread->next:
thread->next->prev = thread->prev
2009-05-20 23:07:56 +03:00
// Unschedule.
if thread->schedule_prev:
thread->schedule_prev->schedule_next = thread->schedule_next
else if first_scheduled == thread:
first_scheduled = thread->schedule_next
if thread->schedule_next:
thread->schedule_next->schedule_prev = thread->schedule_prev
thread->free_obj (this)
void Memory::free_message (Message *message):
for unsigned i = 0; i < 4; ++i:
free_capability (message->capabilities[i])
message->free_obj (this)
void Memory::free_receiver (Receiver *receiver):
if receiver->prev_owned:
receiver->prev_owned->next_owned = receiver->next_owned
else:
receiver->owner->receivers = receiver->next_owned
if receiver->next_owned:
receiver->next_owned->prev_owned = receiver->prev_owned
while receiver->capabilities:
receiver->capabilities->invalidate ()
while receiver->messages:
free_message (receiver->messages)
receiver->free_obj (this)
void Memory::free_capability (Capability *capability):
if capability->sibling_prev:
capability->sibling_prev->sibling_next = capability->sibling_next
else:
capability->target->capabilities = capability->sibling_next
if capability->sibling_next:
capability->sibling_next->sibling_prev = capability->sibling_prev
// The sibling_prev link is used here to point to the parent.
// This method is used to avoid recursion.
capability->sibling_prev = NULL
Capability *c = capability
while c->children:
c->children->sibling_prev = c
c = c->children
while c:
Capability *next = c->sibling_next
if !next:
next = c->sibling_prev
if next:
next->sibling_prev = c->sibling_prev
c->free_obj (this)
c = next
void Capability::invalidate ():
if sibling_prev:
sibling_prev->sibling_next = sibling_next
else:
target->capabilities = sibling_next
if sibling_next:
sibling_next->sibling_prev = sibling_prev
// The sibling_prev link is used here to point to the parent.
// This method is used to avoid recursion.
sibling_prev = NULL
Capability *c = this
while c->children:
c->children->sibling_prev = c
c = c->children
while c:
Capability *next = c->sibling_next
if !next:
next = c->sibling_prev
if next:
next->sibling_prev = c->sibling_prev
c->target = NULL
c->children = NULL
c->sibling_prev = NULL
c->sibling_next = NULL
c->protected_data = 0
c = next
2009-05-19 00:18:23 +03:00
void Memory::free_memory (Memory *mem):
if mem->prev:
mem->prev->next = mem->next
else:
memories = mem->next
if mem->next:
mem->next->prev = mem->prev
while mem->pages:
free_page (mem->pages)
while mem->threads:
free_thread (mem->threads)
while mem->memories:
free_memory (mem->memories)
Memory_arch_free (mem)
2009-05-20 23:07:56 +03:00
mem->free_obj (this)