summaryrefslogblamecommitdiff
path: root/src/kernel/mem/mem.c
blob: 3310b7030699f58ba3b1298e332634778bb432c6 (plain) (tree)
1
2
3
4
5
6
7
8
9
                

                         
                   


                   
                      
 

                

                         

                                                                    


                                
                       









                                                                                                                                                    
                                                                                               





                                                 
                                     



                                                                                             

                                                                       
                                                                                                                      
                                        




                                                                
                                                                              
                                                                                                        





                                        
                                                                  











                                                   
                             




                                                                         
                                                                                                              

                                                                                                                                                                 





                                                                                        
 

































                                                                                                            
         

                          

 








                                                       

         
#include "mem.h"
#include <core/sys.h>
#include <core/monitor.h>
#include "paging.h"

#include <config.h>

#include "_dlmalloc.h"

#include "mem.h"

#define FREEPAGESTOKEEP 5

#define KHEAP_IDXSIZE 0x4000		// only used with heap.std.h
#define KHEAP_INITSIZE 0x00080000
#define KHEAP_MAXSIZE 0x08000000

size_t mem_placementAddr;
int _no_more_ksbrk = 0;


// ******************************
// 									PAGE ALLOCATION
// 															****************************
static struct freepage {
   size_t virt, phys;
} freepages[FREEPAGESTOKEEP];
uint32_t freepagecount = 0;

/*	For internal use only. Populates the cache of pages that can be given to requesters. */
static void get_free_pages() {
	static uint32_t locked = 0;
	uint32_t i;
	if (locked) return;
	locked = 1;
	while (freepagecount < FREEPAGESTOKEEP) {
		if (_no_more_ksbrk) {
			for (i = 0xFFFFF000; i >= 0xF0000000; i -= 0x1000) {
				if (pagedir_getPage(kernel_pagedir, i, 1)->frame == 0) break;
			}
			freepages[freepagecount].virt = i;
			uint32_t frame = frame_alloc();
			freepages[freepagecount].phys = frame * 0x1000;
			page_map(pagedir_getPage(kernel_pagedir, i, 0), freepages[freepagecount].phys / 0x1000, 0, 0);
			freepagecount++;
		} else {
			if (mem_placementAddr & 0xFFFFF000) {
				mem_placementAddr &= 0xFFFFF000;
				mem_placementAddr += 0x1000;
			}
			freepages[freepagecount].virt = (size_t)ksbrk(0x1000);
			freepages[freepagecount].phys = freepages[freepagecount].virt - K_HIGHHALF_ADDR;
			freepagecount++;
		}
	}
	locked = 0;
}

/*	Gives one page from the cache to someone requesting it. */
void* kmalloc_page(size_t *phys) {
	cli();
	get_free_pages();
	freepagecount--;
	*phys = freepages[freepagecount].phys;
	size_t tmp = freepages[freepagecount].virt;
	sti();
	return (void*)tmp;
}

void kfree_page(void* ptr) {
	size_t addr = (size_t)ptr;
	if (_no_more_ksbrk) {
		page_unmapFree(pagedir_getPage(kernel_pagedir, addr, 0));
	}
}

//***********************************
//										MEMORY ALLOCATION FOR DLMALLOC
//																	*************************

void* ksbrk(size_t size) {
	if (_no_more_ksbrk == 0) {		// ksbrk is NOT being called by dlmalloc
		if (size & 0x0FFF) {
			size = (size & 0xFFFFF000) + 0x1000;
		}
	}

	size_t tmp = mem_placementAddr;
	size_t er_begin, er_end, i;

	/* (DBG) monitor_write("<ksbrk ");
	monitor_writeHex(size);
	monitor_write(":");
	monitor_writeHex(tmp);
	monitor_write("> "); */

	mem_placementAddr += size;

	if (_no_more_ksbrk) {		//  paging enabled, we must allocate these pages
		if (tmp < mem_placementAddr) {
			er_begin = tmp;
			if (er_begin & 0x0FFF) er_begin = (er_begin & 0xFFFFF000) + 0x1000;
			er_end = mem_placementAddr;
			if (er_end & 0x0FFF) er_end = (er_end & 0xFFFFF000) + 0x1000;
			for (i = er_begin; i < er_end; i += 0x1000) {
				struct page *p = pagedir_getPage(kernel_pagedir, i, 1);
				size_t f = frame_alloc();
				page_map(p, f, 0, 0);
				/* (DBG) monitor_write("<map "); monitor_writeHex(i); monitor_write(" ");
				monitor_writeHex(f); monitor_write("> "); */
			}
		} else if (tmp > mem_placementAddr) {
			er_begin = (size_t)mem_placementAddr;
			if (er_begin & 0x0FFF) er_begin = (er_begin & 0xFFFFF000) + 0x1000;
			er_end = tmp;
			if (er_end & 0x0FFF) er_end = (er_end & 0xFFFFF000) + 0x1000;
			for (i = er_end - 0x1000; i >= er_begin; i -= 0x1000) {
				// (DBG) monitor_write("<unmap:"); monitor_writeHex(i); monitor_write("> ");
				page_unmapFree(pagedir_getPage(kernel_pagedir, i, 0));
			}
		}
	}

	return (void*)tmp;
}

void kbrk(void* ptr) {
	monitor_write("<kbrk ");
	monitor_writeHex(ptr);
	monitor_write(">\n");

	if ((size_t)ptr > (size_t)&end) {
		ksbrk(ptr - (size_t)mem_placementAddr);
	} else {
		PANIC("INVALID KBRK.");
	}
}