1 #include "threads/palloc.h"
7 #include "threads/init.h"
8 #include "threads/loader.h"
9 #include "threads/mmu.h"
10 #include "threads/synch.h"
12 /* Page allocator. Hands out memory in page-size chunks.
13 See malloc.h for an allocator that hands out smaller
16 We simply use a linked list of free pages. It would be
17 straightforward to add all available memory to this free list
18 at initialization time. In practice, though, that's really
19 slow because it causes the emulator we're running under to
20 have to fault in every page of memory. So instead we only add
21 pages to the free list as needed. */
23 /* A free page owned by the page allocator. */
26 list_elem free_elem; /* Free list element. */
29 /* Keeps multiple threads away from free_pages and
31 static struct lock lock;
33 /* List of free pages. */
34 static struct list free_pages;
36 /* Range of pages (expressed as byte pointers to the beginnings
37 of pages) that we haven't added to the free list yet. */
38 static uint8_t *uninit_start, *uninit_end;
40 /* Initializes the page allocator. */
44 extern char _start, _end;
46 /* Kernel static code and data, in 4 kB pages.
47 We can figure this out because the linker records the start
48 and end of the kernel as _start and _end. See
50 size_t kernel_pages = (&_end - &_start + 4095) / 4096;
52 /* Then we know how much is available to allocate. */
53 uninit_start = ptov (LOADER_KERN_BASE + kernel_pages * PGSIZE);
54 uninit_end = ptov (ram_pages * PGSIZE);
56 /* Initialize other variables. */
57 lock_init (&lock, "palloc");
58 list_init (&free_pages);
61 /* Obtains and returns a free page. If PAL_ZERO is set in FLAGS,
62 then the page is filled with zeros. If no pages are
63 available, returns a null pointer, unless PAL_ASSERT is set in
64 FLAGS, in which case the kernel panics. */
66 palloc_get (enum palloc_flags flags)
72 /* If there's a page in the free list, take it.
73 Otherwise, if there's a page not yet added to the free list,
75 Otherwise, we're out of memory. */
76 if (!list_empty (&free_pages))
77 page = list_entry (list_pop_front (&free_pages), struct page, free_elem);
78 else if (uninit_start < uninit_end)
80 page = (struct page *) uninit_start;
81 uninit_start += PGSIZE;
89 memset (page, 0, PGSIZE);
93 if (flags & PAL_ASSERT)
94 PANIC ("palloc_get: out of pages");
104 palloc_free (void *page_)
106 struct page *page = page_;
108 ASSERT (page == pg_round_down (page));
110 memset (page, 0xcc, PGSIZE);
113 lock_acquire (&lock);
114 list_push_front (&free_pages, &page->free_elem);
115 lock_release (&lock);