Any ideas on how I could make my pmm return a aligned addr?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
RharryR
Posts: 17
Joined: Thu Feb 11, 2016 1:15 am
Location: Milingimbi Island, Australia

Any ideas on how I could make my pmm return a aligned addr?

Post by RharryR »

Howdy.
I have a nice physical allocator that seems to work fine. I have been using it in my kernel for at least 2 weeks without any issues.

Now, I would now like to setup paging in my kernel. I understand the theory, what it does and how it works. Now according to the wiki, I need my paging structures to be page-aligned. I dont really quite under stand what this means but I assume it means that the address is a multiple of 4096, please correct me if i am wrong.

Now I somehow would need to make my allocator be able to serve out page-aligned addresses, but I am not sure on the right way to do this.
Here is my allocator code, if you would like to take a peep:

Code: Select all

// kalloc.c
// Written by Harry Rigg
// Kernel memory allocator

#include <kernel/mem/kalloc.h>

void 
kalloc_init(void* mmloc, unsigned long mmsize)
{
	memory_map_entry_t* current_map = (memory_map_entry_t*) mmloc;
	
	memzone_t* last_looped;
	memzone_t* last_free;
	size_t last_size;
	int i=0;
	while(current_map < mmloc + mmsize)
	{
		if(current_map->type == 1)
		{
			memzone_t* append;
			append = (void*)current_map->base;
			append->flags =0;
			append->prev_h=last_looped;
			last_looped->next_h = append;
			last_looped = (void*) append;
			last_free = (void*) append;
			last_size = current_map->len;
			i++;
		}else{
			memzone_t* append = (void*)current_map->base;
			append->flags = 1;
			append->prev_h = last_looped;
			last_looped->next_h = append;
			last_looped = (void*) append;
		}
		current_map = (memory_map_entry_t*) ((uint32_t)current_map + current_map->size + sizeof(uint32_t));
	}
	// Add a EOM (End Of Memory) header at the end of the free memory
	memzone_t* eom = (void*) last_free + last_size - sizeof(memzone_t);
	// Set the flags to EOM
	eom->flags = 3;
	eom->next_h =0;
	eom->prev_h = last_free->prev_h;
	last_free->next_h = eom;
	return;
}

void* 
kmalloc(size_t size)
{
	memzone_t* this = (memzone_t*)0x0;
	for(int i; 1; i++)
	{	
		// Used?
		if(this->flags==1){
			this = (void*)this->next_h;
			continue;	// Already used
		}
		
		// End of memory?
		if(this->flags==3)
		{
			break;
		}
		
		// Big enough?
		if((this->next_h - (size_t)this) - sizeof(memzone_t) < size){
			this = (void*)this->next_h;
			continue;	// Too small
		}
		
		// This area of memory suits our needs
		
		// Create new header for the area left over
		memzone_t* split = (void*)this + sizeof(memzone_t) + size;
		split->flags = 0;
		split->prev_h = (void*)this;
		split->next_h = (void*)this->next_h;
		
		// Adjust some of this headers properties
		this->flags = 1;
		this->next_h = split;
		return (void*)this+sizeof(memzone_t);	
	}
	return (void*)-1;
}

void*
kcalloc(size_t size)
{
	void* ptr = kmalloc(size);
	memset(ptr, 0, size);
	return ptr;
}

void*
krealloc(void* ptr, size_t nsize)
{
	void* nptr = kmalloc(nsize);
	if(nptr == -1)
		return (void*)-1;
	memzone_t* fmz = (void*) ptr - sizeof(memzone_t);
	size_t this_size = (fmz->next_h - (size_t)fmz) - sizeof(memzone_t);
	memcpy(nptr, ptr, this_size);
	kfree(ptr);
	return nptr;
}

void 
kfree(void* alloc)
{
	memzone_t* this = (void*)alloc-sizeof(memzone_t);
	
	memzone_t* next = (void*) this->next_h;
	if(next->flags==1)
	{
		this->flags = 0;
		return;
	}
	
	while(1)
	{
		next = (void*) next->next_h;
		if(next->flags == 3)
			break;
		if(next->flags == 1)
			break;
	}
	this->next_h = (void*)next;
	this->flags = 0;
}
As you can see, I use a basic header system.

Should I check to see if a free header is page-aligned, and if it is not, do a bit of messing with sizes and pointers to make it page-aligned? Or would this be to slow.

I have a few ideas, I just dont know how I should do it.
Thanks in advance, Harry.

P.S. I dont want you to give me code or modify my code, I really want your ideas and theorys that I can build on :D
Also: If you notice any flaws in my allocator, spit em out at me :D
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Any ideas on how I could make my pmm return a aligned ad

Post by Combuster »

Write kmalloc() on top of a page allocator, instead of the other way around. Once you have paging, you don't need contiguous physical memory for any allocation.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
RharryR
Posts: 17
Joined: Thu Feb 11, 2016 1:15 am
Location: Milingimbi Island, Australia

Re: Any ideas on how I could make my pmm return a aligned ad

Post by RharryR »

Awesome, thanks :D When you say that do you mean make kmalloc dish out blocks with size of 4096 only? I see how this would work :D
MollenOS
Member
Member
Posts: 202
Joined: Wed Oct 26, 2011 12:00 pm

Re: Any ideas on how I could make my pmm return a aligned ad

Post by MollenOS »

RharryR wrote:Awesome, thanks :D When you say that do you mean make kmalloc dish out blocks with size of 4096 only? I see how this would work :D
Yes, that is exactly how you would do it, the phys-mem allocator should only keep track of (page-sized) blocks.
RharryR
Posts: 17
Joined: Thu Feb 11, 2016 1:15 am
Location: Milingimbi Island, Australia

Re: Any ideas on how I could make my pmm return a aligned ad

Post by RharryR »

Thanks so much! I got the allocator working great :) im had disable some of my drivers that use the old allocator, but ill re-enable them once I get the virtual memory allocator finished :)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Any ideas on how I could make my pmm return a aligned ad

Post by Combuster »

RharryR wrote:Awesome, thanks :D When you say that do you mean make kmalloc dish out blocks with size of 4096 only? I see how this would work :D
You would call that page_alloc rather than kmalloc.

Once you have that you can create the new kmalloc that uses page_alloc to grab a chunk of memory when it needs it, and then hands out little fragments from that.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Any ideas on how I could make my pmm return a aligned ad

Post by SpyderTL »

This works if your page size matches your alignment needs, but at some point, you may need to allocate a block of memory that is aligned to something smaller, like 4 or 16 bytes.

In this case, you can simply add your alignment size to your allocation size, and adjust your start address. For instance, to align to 16 bytes:

Code: Select all

address = malloc(size + 16);
address += (16 - (address mod 16)) mod 16;
You could put this logic inside your malloc function if you want to save a few bytes.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Post Reply