X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Fpalloc.c;fp=src%2Fthreads%2Fpalloc.c;h=0b771fdb21f6451c008a61a5012124d2e0be9e10;hb=828d300fd2039b686b69244c2bd6f8b87645086d;hp=62e24cada4756dfa5917f74fac03512ce7626ad4;hpb=5929545c4fd9c31423b929d4d9631132e2697472;p=pintos-anon diff --git a/src/threads/palloc.c b/src/threads/palloc.c index 62e24ca..0b771fd 100644 --- a/src/threads/palloc.c +++ b/src/threads/palloc.c @@ -5,15 +5,22 @@ #include "init.h" #include "loader.h" #include "lib.h" +#include "list.h" #include "mmu.h" +#include "synch.h" + +/* Page allocator. Hands out memory in page-size chunks. + See malloc.h for an allocator that hands out smaller + chunks. */ /* A free page owned by the page allocator. */ struct page { - struct page *next; /* Next free page, or null at end of chain. */ + list_elem free_elem; /* Free list element. */ }; -static struct page *free_pages; +static struct lock lock; +static struct list free_pages; static uint8_t *uninit_start, *uninit_end; void @@ -25,12 +32,15 @@ palloc_init (void) and end of the kernel as _start and _end. See kernel.lds. */ extern char _start, _end; - size_t kernel_pages; - kernel_pages = (&_end - &_start + 4095) / 4096; + size_t kernel_pages = (&_end - &_start + 4095) / 4096; /* Then we know how much is available to allocate. */ uninit_start = ptov (LOADER_KERN_BASE + kernel_pages * PGSIZE); uninit_end = ptov (ram_pages * PGSIZE); + + /* Initialize other variables. */ + lock_init (&lock, "palloc"); + list_init (&free_pages); } void * @@ -38,16 +48,20 @@ palloc_get (enum palloc_flags flags) { struct page *page; - if (free_pages == NULL && uninit_start < uninit_end) + lock_acquire (&lock); + + if (!list_empty (&free_pages)) + page = list_entry (list_pop_front (&free_pages), struct page, free_elem); + else if (uninit_start < uninit_end) { - palloc_free (uninit_start); + page = (struct page *) uninit_start; uninit_start += PGSIZE; } + else + page = NULL; - page = free_pages; if (page != NULL) { - free_pages = page->next; if (flags & PAL_ZERO) memset (page, 0, PGSIZE); } @@ -56,6 +70,8 @@ palloc_get (enum palloc_flags flags) if (flags & PAL_ASSERT) PANIC ("palloc_get: out of pages"); } + + lock_release (&lock); return page; } @@ -64,10 +80,13 @@ void palloc_free (void *page_) { struct page *page = page_; - ASSERT((uintptr_t) page % PGSIZE == 0); + + ASSERT (page == pg_round_down (page)); #ifndef NDEBUG memset (page, 0xcc, PGSIZE); #endif - page->next = free_pages; - free_pages = page; + + lock_acquire (&lock); + list_push_front (&free_pages, &page->free_elem); + lock_release (&lock); }