Getting SharC to check some locking
[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 #ifdef __SHARC__
9 #pragma nosharc
10 #endif
11
12 #include <arch/types.h>
13 #include <ros/error.h>
14 #include <pmap.h>
15 #include <kmalloc.h>
16 #include <stdio.h>
17
18 #define kmallocdebug(args...)  printk(args)
19
20 char*BND(end, maxaddrpa_ptr + IVY_KERNBASE) boot_freemem;
21 static page_list_t pages_list;  //List of physical pages used by kmalloc
22
23 /*
24  * Allocate n bytes of physical memory aligned on an 
25  * align-byte boundary.  Align must be a power of two.
26  * Return kernel virtual address.  Returned memory is uninitialized.
27  *
28  * If we're out of memory, boot_alloc should panic.
29  * This function may ONLY be used during initialization,
30  * before the page_free_list has been set up.
31  */
32 void* boot_alloc(uint32_t n, uint32_t align)
33 {
34         extern char (SNT end)[];
35         void *v;
36
37         // Initialize boot_freemem if this is the first time.
38         // 'end' is a magic symbol automatically generated by the linker,
39         // which points to the end of the kernel's bss segment -
40         // i.e., the first virtual address that the linker
41         // did _not_ assign to any kernel code or global variables.
42         if (boot_freemem == 0) {
43                 boot_freemem = TC(end);
44         }
45
46         //      Step 1: round boot_freemem up to be aligned properly
47         boot_freemem = PTRROUNDUP(boot_freemem, align);
48
49         //      Step 2: save current value of boot_freemem as allocated chunk
50         v = boot_freemem;
51         //  Step 2.5: check if we can alloc
52         if (PADDR(boot_freemem + n) > maxaddrpa)
53                 panic("Out of memory in boot alloc, you fool!\n");
54         //      Step 3: increase boot_freemem to record allocation
55         boot_freemem += n;      
56         //      Step 4: return allocated chunk
57         return v;
58 }
59
60 void* boot_calloc(uint32_t _n, size_t sz, uint32_t align)
61 {
62         extern char (SNT end)[];
63         uint32_t n = _n *sz;
64         void *v;
65
66         // Initialize boot_freemem if this is the first time.
67         // 'end' is a magic symbol automatically generated by the linker,
68         // which points to the end of the kernel's bss segment -
69         // i.e., the first virtual address that the linker
70         // did _not_ assign to any kernel code or global variables.
71         if (boot_freemem == 0)
72                 boot_freemem = TC(end);
73
74         //      Step 1: round boot_freemem up to be aligned properly
75         boot_freemem = PTRROUNDUP(boot_freemem, align);
76
77         //      Step 2: save current value of boot_freemem as allocated chunk
78         v = boot_freemem;
79         //  Step 2.5: check if we can alloc
80         if (PADDR(boot_freemem + n) > maxaddrpa)
81                 panic("Out of memory in boot alloc, you fool!\n");
82         //      Step 3: increase boot_freemem to record allocation
83         boot_freemem += n;
84         //  Step 4: zero allocated chunk
85         memset(v,0,n);
86         //      Step 5: return allocated chunk
87         return v;
88 }
89
90 void kmalloc_init() 
91 {
92         LIST_INIT(&pages_list);
93 }
94
95 void* kmalloc(size_t size, int flags) 
96 {
97         int npages = ROUNDUP(size, PGSIZE) / PGSIZE;
98         
99         // Find 'npages' free consecutive pages
100         int first = -1;
101         kmallocdebug("naddrpages: %u\n", naddrpages);
102         kmallocdebug("npages: %u\n", npages);
103         for(int i=(naddrpages-1); i>=(npages-1); i--) {
104                 int j;
105                 for(j=i; j>=i-(npages-1); j--) {
106                         if( !page_is_free(j) )
107                                 break;
108                 }
109                 if( j == i-(npages-1)-1 ) {
110                         first = j+1;
111                         break;
112                 }
113         }
114         //If we couldn't find them, return NULL
115         if( first == -1 )
116                 return NULL;
117         
118         //Otherwise go ahead and allocate them to ourselves now
119         for(int i=0; i<npages; i++) {
120                 page_t* page;
121                 page_alloc_specific(&page, first+i);
122                 page->num_cons_links = npages-i;
123                 LIST_INSERT_HEAD(&pages_list, page, global_link);
124                 kmallocdebug("mallocing page: %u\n", first+i);
125                 kmallocdebug("at addr: %p\n", ppn2kva(first+i));
126         }
127         //And return the address of the first one
128         return ppn2kva(first);
129 }
130
131 void kfree(void *addr)
132 {
133         kmallocdebug("incoming address: %p\n", addr);
134         page_t* page = kva2page(addr);
135         int num_links = page->num_cons_links;
136         kmallocdebug("getting page: %u\n", page2ppn(page));
137         for(int i=0; i<num_links; i++) {
138                 page_t* p = ppn2page((page2ppn(page) + i));
139                 LIST_REMOVE(p, global_link);
140                 page_free(p);
141                 kmallocdebug("freeing page: %d\n", page2ppn(p));
142         }
143 }
144