Fix conflict
[akaros.git] / kern / src / page_alloc.c
1 /* Copyright (c) 2009 The Regents of the University  of California. 
2  * See the COPYRIGHT files at the top of this source tree for full 
3  * license information.
4  * 
5  * Kevin Klues <klueska@cs.berkeley.edu>    
6  */
7
8 #include <sys/queue.h>
9 #include <page_alloc.h>
10 #include <pmap.h>
11 #include <string.h>
12
13 /**
14  * @brief Clear a Page structure.
15  *
16  * The result has null links and 0 refcount.
17  * Note that the corresponding physical page is NOT initialized!
18  */
19 static void page_clear(page_t *SAFE page)
20 {
21         memset(page, 0, sizeof(page_t));
22 }
23
24 /**
25  * @brief Allocates a physical page from a pool of unused physical memory
26  *
27  * Does NOT set the contents of the physical page to zero -
28  * the caller must do that if necessary.
29  *
30  * @param[out] page  set to point to the Page struct
31  *                   of the newly allocated page
32  *
33  * @return ESUCCESS on success
34  * @return -ENOMEM  otherwise
35  */
36 error_t page_alloc(page_t** page) 
37 {
38         //TODO: Put a lock around this
39         if(!LIST_EMPTY(&page_free_list)) {
40                 *page = LIST_FIRST(&page_free_list);
41                 LIST_REMOVE(*page, global_link);
42                 REMOVE_CACHE_COLORING_PAGE_FROM_FREE_LISTS(page);
43                 page_clear(*page);
44                 return ESUCCESS;
45         }
46         return -ENOMEM;
47 }
48
49 /*
50  * This macro defines multiple functions of the form:
51  * error_t _cache##_page_alloc(page_t** page, size_t color)
52  *
53  * Each of these functions operates on a different level of 
54  * of the cache heirarchy, and allocates a physical page
55  * from the list of pages corresponding to the supplied 
56  * color for the given cache.  
57  * 
58  * Does NOT set the contents of the physical page to zero -
59  * the caller must do that if necessary.
60  *
61  * color       -- the color from which to allocate a page
62  * *page       -- is set to point to the Page struct 
63  *                of the newly allocated page
64  *
65  * RETURNS 
66  *   ESUCCESS  -- on success
67  *   -ENOMEM   -- otherwise 
68  *
69  * error_t _cache##_page_alloc(page_t** page, size_t color)
70  * {
71  *       if(!LIST_EMPTY(&(_cache##_cache_colored_page_list)[(color)])) {
72  *        *(page) = LIST_FIRST(&(_cache##_cache_colored_page_list)[(color)]);
73  *               LIST_REMOVE(*page, global_link);
74  *               REMOVE_CACHE_COLORING_PAGE_FROM_FREE_LISTS(page);
75  *               page_clear(*page);
76  *               return ESUCCESS;
77  *       }
78  *       return -ENOMEM;
79  * }
80  */
81 DECLARE_CACHE_COLORED_PAGE_ALLOC_FUNCTIONS();
82
83 /*
84  * Allocates a specific physical page.
85  * Does NOT set the contents of the physical page to zero -
86  * the caller must do that if necessary.
87  *
88  * ppn         -- the page number to allocate
89  * *page       -- is set to point to the Page struct 
90  *                of the newly allocated page
91  *
92  * RETURNS 
93  *   ESUCCESS  -- on success
94  *   -ENOMEM   -- otherwise 
95  */
96 error_t page_alloc_specific(page_t** page, size_t ppn)
97 {
98         //TODO: Put a lock around this
99         page_t* sp_page = ppn2page(ppn);
100         if( sp_page->page_ref != 0 )
101                 return -ENOMEM;
102         *page = sp_page;
103         LIST_REMOVE(*page, global_link);
104         REMOVE_CACHE_COLORING_PAGE_FROM_FREE_LISTS(page);
105         page_clear(*page);
106         return 0;
107 }
108
109 /*
110  * Return a page to the free list.
111  * (This function should only be called when pp->page_ref reaches 0.)
112  */
113 error_t page_free(page_t* page) 
114 {
115         //TODO: Put a lock around this
116         page_clear(page);
117         LIST_INSERT_HEAD(&page_free_list, page, global_link);
118         INSERT_CACHE_COLORING_PAGE_ONTO_FREE_LISTS(page);       
119         return ESUCCESS;
120 }
121
122 /*
123  * Check if a page with the given pyhysical page # is free
124  */
125 int page_is_free(size_t ppn) {
126         //TODO: Put a lock around this
127         page_t* page = ppn2page(ppn);
128         if( page->page_ref == 0 )
129                 return TRUE;
130         return FALSE;
131 }
132
133 /*
134  * Increment the reference count on a page
135  */
136 void page_incref(page_t *page)
137 {
138         page->page_ref++;
139 }
140
141 /*
142  * Decrement the reference count on a page,
143  * freeing it if there are no more refs.
144  */
145 void page_decref(page_t *page)
146 {
147         if (--page->page_ref == 0)
148                 page_free(page);
149 }
150
151 /*
152  * Set the reference count on a page to a specific value
153  */
154 void page_setref(page_t *page, size_t val)
155 {
156         page->page_ref = val;
157 }
158
159 /*
160  * Get the reference count on a page
161  */
162 size_t page_getref(page_t *page)
163 {
164         return page->page_ref;
165 }
166