Reworked the ethernet driver to use kmalloc properly. Fixed up kmalloc.
[akaros.git] / kern / src / kmalloc.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 <arch/types.h>
9 #include <ros/error.h>
10 #include <pmap.h>
11 #include <kmalloc.h>
12
13 #define kmallocdebug(args...)  //printk(args)
14
15 static page_list_t pages_list;  //List of physical pages used by kmalloc
16 extern size_t naddrpage;
17
18 void kmalloc_init() {
19         LIST_INIT(&pages_list);
20 }
21
22 void* kmalloc(size_t size, int flags) {
23         int npages = ROUNDUP(size, PGSIZE) / PGSIZE;
24         
25         // Find 'npages' free consecutive pages
26         int first = -1;
27         kmallocdebug("naddrpage: %u\n", naddrpage);
28         kmallocdebug("npages: %u\n", npages);
29         for(int i=(naddrpage-1); i>=(npages-1); i--) {
30                 int j;
31                 for(j=i; j>=i-(npages-1); j--) {
32                         if( !page_is_free(j) )
33                                 break;
34                 }
35                 if( j == i-(npages-1)-1 ) {
36                         first = j+1;
37                         break;
38                 }
39         }
40         //If we couldn't find them, return NULL
41         if( first == -1 )
42                 return NULL;
43         /*
44         cprintf("Starting page check.\n");
45         for (int i = 0; i < naddrpage; i++) {
46                 page_t* page = ppn2page(i);
47                 if (((page->pp_link.le_next != NULL) && (page->pp_ref != 0)) || ((page->pp_link.le_next == NULL) && (page->pp_ref == 0))) {
48                         cprintf("Out of sync on page: %u\n", i);
49                         cprintf("-->pp_link: %p\n", page->pp_link);
50                         cprintf("-->pp_ref: %p\n", page->pp_ref);
51                 }
52         }
53         cprintf("Ending page check.\n");
54         */
55                 
56         //Otherwise go ahead and allocate them to ourselves now
57         for(int i=0; i<npages; i++) {
58                 page_t* page;
59                 page_alloc_specific(&page, first+i);
60                 page->pp_ref++; // Kevin doesnt like this.
61                 page->num_cons_links = npages-i;
62                 LIST_INSERT_HEAD(&pages_list, page, pp_link);
63                 kmallocdebug("mallocing page: %u\n", first+i);
64                 kmallocdebug("at addr: %p\n", ppn2kva(first+i));
65         }
66         //And return the address of the first one
67         return ppn2kva(first);
68 }
69 void kfree(void *addr) {
70         kmallocdebug("incoming address: %p\n", addr);
71         page_t* page = kva2page(addr);
72         int num_links = page->num_cons_links;
73         kmallocdebug("getting page: %u\n", page2ppn(page));
74         for(int i=0; i<num_links; i++) {
75                 page_t* p = ppn2page((page2ppn(page) + i));
76                 LIST_REMOVE(p, pp_link);
77                 page_decref(p);
78                 kmallocdebug("freeing page: %d\n", page2ppn(p));
79         }
80 }