#include "kernel.hh" void *Memory::palloc (): if use >= limit: return NULL FreePage *ret = junk_pages if !ret: ret = zero_pages zero_pages = ret->next else: junk_pages = ret->next return ret void *Memory::zalloc (): if use >= limit: 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 ret void Memory::pfree (void *page): FreePage *p = (FreePage *)page p->next = junk_pages junk_pages = p void Memory::zfree (void *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 = f->next_obj - 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 = 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 (self) Page *Memory::alloc_page (): Page *ret = (Page *)search_free (sizeof (Page), pages) ret->physical = zalloc () if !ret->physical: ret->free (this, pages) return ret Thread *Memory::alloc_thread (): Thread *ret = (Thread *)search_free (sizeof (Thread), 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 Memory *Memory::alloc_memory (): Memory *ret = (Memory *)search_free (sizeof (Memory), memories) ret->frees = NULL ret->pages = NULL ret->threads = NULL ret->memories = NULL ret->limit = ~0 ret->used = 0 Memory_arch_init (ret) return ret