First stab at interrupt-driven serial.
[pintos-anon] / src / threads / palloc.c
index 0b771fdb21f6451c008a61a5012124d2e0be9e10..29cb54fa1b864ffce0792c29661ec3d01274da38 100644 (file)
@@ -1,17 +1,24 @@
-#include "palloc.h"
+#include "threads/palloc.h"
+#include <debug.h>
+#include <list.h>
 #include <stddef.h>
 #include <stdint.h>
-#include "debug.h"
-#include "init.h"
-#include "loader.h"
-#include "lib.h"
-#include "list.h"
-#include "mmu.h"
-#include "synch.h"
+#include <string.h>
+#include "threads/init.h"
+#include "threads/loader.h"
+#include "threads/mmu.h"
+#include "threads/synch.h"
 
 /* Page allocator.  Hands out memory in page-size chunks.
    See malloc.h for an allocator that hands out smaller
-   chunks. */
+   chunks.
+
+   We simply use a linked list of free pages.  It would be
+   straightforward to add all available memory to this free list
+   at initialization time.  In practice, though, that's really
+   slow because it causes the emulator we're running under to
+   have to fault in every page of memory.  So instead we only add
+   pages to the free list as needed. */
 
 /* A free page owned by the page allocator. */
 struct page
@@ -19,19 +26,27 @@ struct page
     list_elem free_elem;        /* Free list element. */
   };
 
+/* Keeps multiple threads away from free_pages and
+   uninit_start. */
 static struct lock lock;
+
+/* List of free pages. */
 static struct list free_pages;
+
+/* Range of pages (expressed as byte pointers to the beginnings
+   of pages) that we haven't added to the free list yet. */
 static uint8_t *uninit_start, *uninit_end;
 
+/* Initializes the page allocator. */
 void
 palloc_init (void) 
 {
+  extern char _start, _end;
+
   /* Kernel static code and data, in 4 kB pages.
-     
      We can figure this out because the linker records the start
      and end of the kernel as _start and _end.  See
-     kernel.lds. */
-  extern char _start, _end;
+     kernel.lds.S. */
   size_t kernel_pages = (&_end - &_start + 4095) / 4096;
 
   /* Then we know how much is available to allocate. */
@@ -43,6 +58,10 @@ palloc_init (void)
   list_init (&free_pages);
 }
 
+/* Obtains and returns a free page.  If PAL_ZERO is set in FLAGS,
+   then the page is filled with zeros.  If no pages are
+   available, returns a null pointer, unless PAL_ASSERT is set in
+   FLAGS, in which case the kernel panics. */
 void *
 palloc_get (enum palloc_flags flags)
 {
@@ -50,6 +69,10 @@ palloc_get (enum palloc_flags flags)
 
   lock_acquire (&lock);
 
+  /* If there's a page in the free list, take it.
+     Otherwise, if there's a page not yet added to the free list,
+     use it.
+     Otherwise, we're out of memory. */
   if (!list_empty (&free_pages))
     page = list_entry (list_pop_front (&free_pages), struct page, free_elem);
   else if (uninit_start < uninit_end) 
@@ -76,6 +99,7 @@ palloc_get (enum palloc_flags flags)
   return page;
 }
 
+/* Frees PAGE. */
 void
 palloc_free (void *page_) 
 {