#pypp 0 #include "kernel.hh" // TODO: avoid recursion. bool Memory::use (): if used >= limit: return false if !parent || parent->use (): ++used return true return false void Memory::unuse (): --used return parent->unuse () unsigned Memory::palloc (): if !use (): return NULL FreePage *ret = junk_pages if !ret: ret = zero_pages zero_pages = ret->next else: junk_pages = ret->next return (unsigned)ret unsigned Memory::zalloc (): if !use (): return NULL FreePage *ret = zero_pages if !ret: ret = junk_pages for unsigned i = 1; i < PAGE_SIZE; ++i: ((unsigned *)ret)[i] = 0 junk_pages = ret->next else: zero_pages = ret->next ret->next = NULL return (unsigned)ret void Memory::pfree (unsigned page): FreePage *p = (FreePage *)page p->next = junk_pages junk_pages = p void Memory::zfree (unsigned page): FreePage *p = (FreePage *)page p->next = zero_pages zero_pages = p void *Memory::search_free (unsigned size, void **first): Free *f unsigned s = 0 for f = frees; f; f = f->next: if f->next_obj: s = (unsigned)f->next_obj - (unsigned)f 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 if obj->next_obj: 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 f->next = (Free *)*first f->prev = NULL if f->next: f->next->prev = f *first = f 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 parent->pfree ((unsigned)self) Page *Memory::alloc_page (): Page *ret = (Page *)search_free (sizeof (Page), (void **)&pages) ret->physical = 0 return ret Thread *Memory::alloc_thread (): Thread *ret = (Thread *)search_free (sizeof (Thread), (void **)&threads) ret->address_space = this ret->pc = 0 ret->sp = 0 Thread_arch_init (ret) ret->schedule_prev = NULL ret->schedule_next = NULL return ret 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 Memory *Memory::alloc_memory (): Memory *ret = (Memory *)search_free (sizeof (Memory), (void **)&memories) ret->parent = this ret->frees = NULL ret->pages = NULL ret->threads = NULL ret->memories = NULL ret->limit = ~0 ret->used = 0 Memory_arch_init (ret) return ret 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) page->free_obj (this) 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 // 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 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) mem->free_obj (this)