#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: dbg_log ("memory allocation failed\n") return 0 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. dbg_log ("range memory allocation failed") 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 (): dbg_log ("limit reached: allocation not allowed") 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)