prof: samples userspace PCs
[akaros.git] / kern / src / page_alloc.c
index 2487d4a..a9f1aa1 100644 (file)
@@ -24,7 +24,7 @@
 static void __page_decref(page_t *CT(1) page);
 static error_t __page_alloc_specific(page_t** page, size_t ppn);
 
-#ifdef __CONFIG_PAGE_COLORING__
+#ifdef CONFIG_PAGE_COLORING
 #define NUM_KERNEL_COLORS 8
 #else
 #define NUM_KERNEL_COLORS 1
@@ -50,7 +50,7 @@ static void __page_init(struct page *page)
 {
        memset(page, 0, sizeof(page_t));
        page_setref(page, 1);
-       init_sem(&page->pg_sem, 0);
+       sem_init(&page->pg_sem, 0);
 }
 
 #define __PAGE_ALLOC_FROM_RANGE_GENERIC(page, base_color, range, predicate) \
@@ -153,6 +153,24 @@ error_t kpage_alloc(page_t** page)
        return ret;
 }
 
+/* Helper: allocates a refcounted page of memory for the kernel's use and
+ * returns the kernel address (kernbase), or 0 on error. */
+void *kpage_alloc_addr(void)
+{
+       struct page *a_page;
+       if (kpage_alloc(&a_page))
+               return 0;
+       return page2kva(a_page);
+}
+
+void *kpage_zalloc_addr(void)
+{
+       void *retval = kpage_alloc_addr();
+       if (retval)
+               memset(retval, 0, PGSIZE);
+       return retval;
+}
+
 /**
  * @brief Allocated 2^order contiguous physical pages.  Will increment the
  * reference count for the pages.
@@ -166,6 +184,7 @@ void *get_cont_pages(size_t order, int flags)
 {
        size_t npages = 1 << order;     
 
+       size_t naddrpages = max_paddr / PGSIZE;
        // Find 'npages' free consecutive pages
        int first = -1;
        spin_lock_irqsave(&colored_page_free_list_lock);
@@ -196,11 +215,27 @@ void *get_cont_pages(size_t order, int flags)
        return ppn2kva(first);
 }
 
+/**
+ * @brief Allocated 2^order contiguous physical pages.  Will increment the
+ * reference count for the pages. Get them from NUMA node node.
+ *
+ * @param[in] node which node to allocate from. Unimplemented.
+ * @param[in] order order of the allocation
+ * @param[in] flags memory allocation flags
+ *
+ * @return The KVA of the first page, NULL otherwise.
+ */
+void *get_cont_pages_node(int node, size_t order, int flags)
+{
+       return get_cont_pages(order, flags);
+}
+
 void free_cont_pages(void *buf, size_t order)
 {
        size_t npages = 1 << order;     
        spin_lock_irqsave(&colored_page_free_list_lock);
-       for (int i = kva2ppn(buf); i < kva2ppn(buf) + npages; i++) {
+       for (size_t i = kva2ppn(buf); i < kva2ppn(buf) + npages; i++) {
+               page_t* page = ppn2page(i);
                __page_decref(ppn2page(i));
                assert(page_is_free(i));
        }
@@ -274,7 +309,7 @@ static void page_release(struct kref *kref)
 {
        struct page *page = container_of(kref, struct page, pg_kref);
 
-       if (page->pg_flags & PG_BUFFER)
+       if (atomic_read(&page->pg_flags) & PG_BUFFER)
                free_bhs(page);
        /* Give our page back to the free list.  The protections for this are that
         * the list lock is grabbed by page_decref. */
@@ -300,21 +335,16 @@ void page_setref(page_t *page, size_t val)
 void lock_page(struct page *page)
 {
        /* when this returns, we have are the ones to have locked the page */
-       sleep_on(&page->pg_sem);
-       assert(!(page->pg_flags & PG_LOCKED));
-       page->pg_flags |= PG_LOCKED;
+       sem_down(&page->pg_sem);
+       assert(!(atomic_read(&page->pg_flags) & PG_LOCKED));
+       atomic_or(&page->pg_flags, PG_LOCKED);
 }
 
 /* Unlocks the page, and wakes up whoever is waiting on the lock */
 void unlock_page(struct page *page)
 {
-       struct kthread *sleeper;
-       page->pg_flags &= ~PG_LOCKED;
-       sleeper = __up_sem(&page->pg_sem);
-       if (sleeper) {
-               printk("Unexpected sleeper on a page!");        /* til we test this */
-               kthread_runnable(sleeper);
-       }
+       atomic_and(&page->pg_flags, ~PG_LOCKED);
+       sem_up(&page->pg_sem);
 }
 
 void print_pageinfo(struct page *page)
@@ -324,24 +354,27 @@ void print_pageinfo(struct page *page)
                printk("Null page\n");
                return;
        }
-       printk("Page %d (%08p), Flags: %08p Refcnt: %d\n", page2ppn(page), page2kva(page),
-              page->pg_flags, kref_refcnt(&page->pg_kref));
+       printk("Page %d (%p), Flags: 0x%08x Refcnt: %d\n", page2ppn(page),
+              page2kva(page), atomic_read(&page->pg_flags),
+              kref_refcnt(&page->pg_kref));
        if (page->pg_mapping) {
-               printk("\tMapped into object %08p at index %d\n",
+               printk("\tMapped into object %p at index %d\n",
                       page->pg_mapping->pm_host, page->pg_index);
        }
-       if (page->pg_flags & PG_BUFFER) {
+       if (atomic_read(&page->pg_flags) & PG_BUFFER) {
                struct buffer_head *bh = (struct buffer_head*)page->pg_private;
                i = 0;
                while (bh) {
-                       printk("\tBH %d: buffer: %08p, sector: %d, nr_sector: %d\n", i,
+                       printk("\tBH %d: buffer: %p, sector: %d, nr_sector: %d\n", i,
                               bh->bh_buffer, bh->bh_sector, bh->bh_nr_sector);
                        i++;
                        bh = bh->bh_next;
                }
                printk("\tPage is %sup to date\n",
-                      page->pg_flags & PG_UPTODATE ? "" : "not ");
+                      atomic_read(&page->pg_flags) & PG_UPTODATE ? "" : "not ");
        }
-       printk("\tPage is %slocked\n", page->pg_flags & PG_LOCKED ? "" : "un");
-       printk("\tPage is %s\n", page->pg_flags & PG_DIRTY ? "dirty" : "clean");
+       printk("\tPage is %slocked\n",
+              atomic_read(&page->pg_flags) & PG_LOCKED ? "" : "un");
+       printk("\tPage is %s\n",
+              atomic_read(&page->pg_flags) & PG_DIRTY ? "dirty" : "clean");
 }