Adding SharC annotations. Type checker off
[akaros.git] / kern / src / kmalloc.c
index f832c31..556d33f 100644 (file)
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
 
-#include <arch/types.h>
+#ifdef __SHARC__
+#pragma nosharc
+#define SINIT(x) x
+#endif
+
+#include <ros/common.h>
 #include <ros/error.h>
 #include <pmap.h>
 #include <kmalloc.h>
+#include <stdio.h>
+
+#define kmallocdebug(args...)  //printk(args)
+
+char *RO BND(end, maxaddrpa_ptr + IVY_KERNBASE) boot_freemem;
+
+//List of physical pages used by kmalloc
+static spinlock_t pages_list_lock = 0;
+static page_list_t LCKD(&pages_list_lock)pages_list;
+
+/*
+ * Allocate n bytes of physical memory aligned on an 
+ * align-byte boundary.  Align must be a power of two.
+ * Return kernel virtual address.  Returned memory is uninitialized.
+ *
+ * If we're out of memory, boot_alloc should panic.
+ * This function may ONLY be used during initialization,
+ * before the page_free_list has been set up.
+ */
+void* boot_alloc(uint32_t n, uint32_t align)
+{
+       extern char (SNT RO end)[];
+       void *v;
+
+       // Initialize boot_freemem if this is the first time.
+       // 'end' is a magic symbol automatically generated by the linker,
+       // which points to the end of the kernel's bss segment -
+       // i.e., the first virtual address that the linker
+       // did _not_ assign to any kernel code or global variables.
+       if (boot_freemem == 0) {
+               boot_freemem = SINIT(TC(end));
+       }
+
+       //      Step 1: round boot_freemem up to be aligned properly
+       char RO*tmp = PTRROUNDUP(boot_freemem, align);
+       boot_freemem = SINIT(tmp);
+
+       //      Step 2: save current value of boot_freemem as allocated chunk
+       v = boot_freemem;
+       //  Step 2.5: check if we can alloc
+       if (PADDR(boot_freemem + n) > maxaddrpa)
+               panic("Out of memory in boot alloc, you fool!\n");
+       //      Step 3: increase boot_freemem to record allocation
+       boot_freemem = SINIT(boot_freemem + n);
+       //      Step 4: return allocated chunk
+       return v;
+}
 
-#define kmallocdebug(args...)  printk(args)
+void* boot_calloc(uint32_t _n, size_t sz, uint32_t align)
+{
+       extern char (SNT RO end)[];
+       uint32_t n = _n *sz;
+       void *v;
 
-static page_list_t pages_list; //List of physical pages used by kmalloc
-extern size_t naddrpage;
+       // Initialize boot_freemem if this is the first time.
+       // 'end' is a magic symbol automatically generated by the linker,
+       // which points to the end of the kernel's bss segment -
+       // i.e., the first virtual address that the linker
+       // did _not_ assign to any kernel code or global variables.
+       if (boot_freemem == 0)
+               boot_freemem = SINIT(TC(end));
 
-void kmalloc_init() {
+       //      Step 1: round boot_freemem up to be aligned properly
+       char RO*tmp = PTRROUNDUP(boot_freemem, align);
+       boot_freemem = SINIT(tmp);
+
+       //      Step 2: save current value of boot_freemem as allocated chunk
+       v = boot_freemem;
+       //  Step 2.5: check if we can alloc
+       if (PADDR(boot_freemem + n) > maxaddrpa)
+               panic("Out of memory in boot alloc, you fool!\n");
+       //      Step 3: increase boot_freemem to record allocation
+       boot_freemem = SINIT(boot_freemem + n);
+       //  Step 4: zero allocated chunk
+       memset(v,0,n);
+       //      Step 5: return allocated chunk
+       return v;
+}
+
+void kmalloc_init() 
+{
        LIST_INIT(&pages_list);
 }
 
-void* kmalloc(size_t size, int flags) {
+void* kmalloc(size_t size, int flags) 
+{
+       if (size == 0)
+               return NULL;
+
        int npages = ROUNDUP(size, PGSIZE) / PGSIZE;
        
        // Find 'npages' free consecutive pages
        int first = -1;
-       kmallocdebug("naddrpage: %u\n", naddrpage);
+       kmallocdebug("naddrpages: %u\n", naddrpages);
        kmallocdebug("npages: %u\n", npages);
-       for(int i=(naddrpage-1); i>=(npages-1); i--) {
+       for(int i=(naddrpages-1); i>=(npages-1); i--) {
                int j;
                for(j=i; j>=i-(npages-1); j--) {
                        if( !page_is_free(j) )
@@ -44,24 +127,33 @@ void* kmalloc(size_t size, int flags) {
        //Otherwise go ahead and allocate them to ourselves now
        for(int i=0; i<npages; i++) {
                page_t* page;
+
                page_alloc_specific(&page, first+i);
+               page_incref(page);
                page->num_cons_links = npages-i;
-               LIST_INSERT_HEAD(&pages_list, page, pp_link);
+
+               spin_lock_irqsave(&pages_list_lock);
+               LIST_INSERT_HEAD(&pages_list, page, page_link);
+               spin_unlock_irqsave(&pages_list_lock);
+
                kmallocdebug("mallocing page: %u\n", first+i);
                kmallocdebug("at addr: %p\n", ppn2kva(first+i));
        }
        //And return the address of the first one
        return ppn2kva(first);
 }
-void kfree(void *addr) {
+
+void kfree(void *addr)
+{
        kmallocdebug("incoming address: %p\n", addr);
        page_t* page = kva2page(addr);
        int num_links = page->num_cons_links;
        kmallocdebug("getting page: %u\n", page2ppn(page));
        for(int i=0; i<num_links; i++) {
                page_t* p = ppn2page((page2ppn(page) + i));
-               LIST_REMOVE(p, pp_link);
+               LIST_REMOVE(p, page_link);
                page_free(p);
                kmallocdebug("freeing page: %d\n", page2ppn(p));
        }
-}
\ No newline at end of file
+}
+