forked from Bananymous/banan-os
				
			Kernel/LibC: add free function for FixedWidthAllocator
I have to rework the syscall API and allocators in process. For now this works well enough :)
This commit is contained in:
		
							parent
							
								
									890aa9aa15
								
							
						
					
					
						commit
						12e42f40c5
					
				| 
						 | 
				
			
			@ -17,7 +17,7 @@ namespace Kernel
 | 
			
		|||
		~FixedWidthAllocator();
 | 
			
		||||
 | 
			
		||||
		vaddr_t allocate();
 | 
			
		||||
		void deallocate(vaddr_t);
 | 
			
		||||
		bool deallocate(vaddr_t);
 | 
			
		||||
 | 
			
		||||
		uint32_t allocation_size() const { return m_allocation_size; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -26,8 +26,10 @@ namespace Kernel
 | 
			
		|||
		{
 | 
			
		||||
			node* prev { nullptr };
 | 
			
		||||
			node* next { nullptr };
 | 
			
		||||
			bool allocated { false };
 | 
			
		||||
		};
 | 
			
		||||
		vaddr_t address_of(const node*) const;
 | 
			
		||||
		vaddr_t address_of_node(const node*) const;
 | 
			
		||||
		node* node_from_address(vaddr_t) const;
 | 
			
		||||
		void allocate_page_for_node_if_needed(const node*);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,6 +57,7 @@ namespace Kernel
 | 
			
		|||
		BAN::ErrorOr<void> set_working_directory(BAN::StringView);
 | 
			
		||||
 | 
			
		||||
		BAN::ErrorOr<void*> allocate(size_t);
 | 
			
		||||
		void free(void*);
 | 
			
		||||
 | 
			
		||||
		void termid(char*) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
#define SYS_SEEK 6
 | 
			
		||||
#define SYS_OPEN 7
 | 
			
		||||
#define SYS_ALLOC 8
 | 
			
		||||
#define SYS_FREE 9
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,6 +87,9 @@ namespace Kernel
 | 
			
		|||
 | 
			
		||||
		node* node = m_free_list;
 | 
			
		||||
 | 
			
		||||
		ASSERT(!node->allocated);
 | 
			
		||||
		node->allocated = true;
 | 
			
		||||
 | 
			
		||||
		m_free_list = node->next;
 | 
			
		||||
		if (m_free_list)
 | 
			
		||||
			m_free_list->prev = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -100,23 +103,50 @@ namespace Kernel
 | 
			
		|||
 | 
			
		||||
		m_allocated++;
 | 
			
		||||
		allocate_page_for_node_if_needed(node);
 | 
			
		||||
		return address_of(node);
 | 
			
		||||
		return address_of_node(node);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void FixedWidthAllocator::deallocate(paddr_t addr)
 | 
			
		||||
	bool FixedWidthAllocator::deallocate(vaddr_t address)
 | 
			
		||||
	{
 | 
			
		||||
		(void)addr;
 | 
			
		||||
		ASSERT_NOT_REACHED();
 | 
			
		||||
		if (address % m_allocation_size)
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		node* node = node_from_address(address);
 | 
			
		||||
		if (node == nullptr)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if (!node->allocated)
 | 
			
		||||
		{
 | 
			
		||||
			dwarnln("deallocate called on unallocated address");
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		node->allocated = false;
 | 
			
		||||
 | 
			
		||||
		if (node->prev)
 | 
			
		||||
			node->prev->next = node->next;
 | 
			
		||||
		if (node->next)
 | 
			
		||||
			node->next->prev = node->prev;
 | 
			
		||||
 | 
			
		||||
		node->next = m_free_list;
 | 
			
		||||
		node->prev = nullptr;
 | 
			
		||||
 | 
			
		||||
		if (m_free_list)
 | 
			
		||||
			m_free_list->prev = node;
 | 
			
		||||
		m_free_list = node;
 | 
			
		||||
 | 
			
		||||
		m_allocated--;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vaddr_t FixedWidthAllocator::address_of(const node* node) const
 | 
			
		||||
	vaddr_t FixedWidthAllocator::address_of_node(const node* node) const
 | 
			
		||||
	{
 | 
			
		||||
		uint32_t index = node - (struct node*)m_nodes_page;
 | 
			
		||||
 | 
			
		||||
		uint32_t page_index = index / (PAGE_SIZE / sizeof(struct node));
 | 
			
		||||
		uint32_t page_index = index / (PAGE_SIZE / m_allocation_size);
 | 
			
		||||
		ASSERT(page_index < PAGE_SIZE / sizeof(vaddr_t));
 | 
			
		||||
 | 
			
		||||
		uint32_t offset = index % (PAGE_SIZE / sizeof(struct node));
 | 
			
		||||
		uint32_t offset = index % (PAGE_SIZE / m_allocation_size);
 | 
			
		||||
 | 
			
		||||
		vaddr_t page_begin = ((vaddr_t*)m_allocated_pages)[page_index];
 | 
			
		||||
		ASSERT(page_begin);
 | 
			
		||||
| 
						 | 
				
			
			@ -124,11 +154,38 @@ namespace Kernel
 | 
			
		|||
		return page_begin + offset * m_allocation_size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	FixedWidthAllocator::node* FixedWidthAllocator::node_from_address(vaddr_t address) const
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: This probably should be optimized from O(n) preferably to O(1) but I
 | 
			
		||||
		//       don't want to think about performance now.
 | 
			
		||||
		
 | 
			
		||||
		ASSERT(address % m_allocation_size == 0);
 | 
			
		||||
 | 
			
		||||
		vaddr_t page_begin = address / PAGE_SIZE * PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
		for (uint32_t page_index = 0; page_index < PAGE_SIZE / sizeof(vaddr_t); page_index++)
 | 
			
		||||
		{
 | 
			
		||||
			vaddr_t vaddr = ((vaddr_t*)m_allocated_pages)[page_index];
 | 
			
		||||
			if (vaddr != page_begin)
 | 
			
		||||
				continue;
 | 
			
		||||
			
 | 
			
		||||
			uint32_t offset = (address - page_begin) / m_allocation_size;
 | 
			
		||||
 | 
			
		||||
			node* result = (node*)m_nodes_page;
 | 
			
		||||
			result += page_index * PAGE_SIZE / m_allocation_size;
 | 
			
		||||
			result += offset;
 | 
			
		||||
			ASSERT(address_of_node(result) == address);
 | 
			
		||||
			return result;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void FixedWidthAllocator::allocate_page_for_node_if_needed(const node* node)
 | 
			
		||||
	{
 | 
			
		||||
		uint32_t index = node - (struct node*)m_nodes_page;
 | 
			
		||||
 | 
			
		||||
		uint32_t page_index = index / (PAGE_SIZE / sizeof(struct node));
 | 
			
		||||
		uint32_t page_index = index / (PAGE_SIZE / m_allocation_size);
 | 
			
		||||
		ASSERT(page_index < PAGE_SIZE / sizeof(vaddr_t));
 | 
			
		||||
 | 
			
		||||
		vaddr_t& page_vaddr = ((vaddr_t*)m_allocated_pages)[page_index];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -386,6 +386,14 @@ namespace Kernel
 | 
			
		|||
		return BAN::Error::from_errno(ENOMEM);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Process::free(void* ptr)
 | 
			
		||||
	{
 | 
			
		||||
		for (auto& allocator : m_fixed_width_allocators)
 | 
			
		||||
			if (allocator.deallocate((vaddr_t)ptr))
 | 
			
		||||
				return;
 | 
			
		||||
		dwarnln("free called on pointer that was not allocated");	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Process::termid(char* buffer) const
 | 
			
		||||
	{
 | 
			
		||||
		if (m_tty == nullptr)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,11 @@ namespace Kernel
 | 
			
		|||
		return (long)res.value();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void sys_free(void* ptr)
 | 
			
		||||
	{
 | 
			
		||||
		Process::current().free(ptr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	extern "C" long cpp_syscall_handler(int syscall, void* arg1, void* arg2, void* arg3)
 | 
			
		||||
	{
 | 
			
		||||
		Thread::current().set_in_syscall(true);
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +101,9 @@ namespace Kernel
 | 
			
		|||
		case SYS_ALLOC:
 | 
			
		||||
			ret = sys_alloc((size_t)arg1);
 | 
			
		||||
			break;
 | 
			
		||||
		case SYS_FREE:
 | 
			
		||||
			sys_free(arg1);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			Kernel::panic("Unknown syscall {}", syscall);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,7 +79,9 @@ void* calloc(size_t nmemb, size_t size)
 | 
			
		|||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void free(void*)
 | 
			
		||||
void free(void* ptr)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	if (ptr == nullptr)
 | 
			
		||||
		return;
 | 
			
		||||
	syscall(SYS_FREE, ptr);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,6 +74,12 @@ long syscall(long syscall, ...)
 | 
			
		|||
			ret = Kernel::syscall(SYS_ALLOC, bytes);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case SYS_FREE:
 | 
			
		||||
		{
 | 
			
		||||
			void* ptr = va_arg(args, void*);
 | 
			
		||||
			ret = Kernel::syscall(SYS_FREE, ptr);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		default:
 | 
			
		||||
			puts("LibC: Unhandeled syscall");
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,41 +3,23 @@
 | 
			
		|||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	void* ptr = malloc(10);
 | 
			
		||||
	if (ptr == NULL)
 | 
			
		||||
	for (int i = 0; i < 10; i++)
 | 
			
		||||
	{
 | 
			
		||||
		perror("malloc");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	*(int*)ptr = 5;
 | 
			
		||||
	putc('0' + *(int*)ptr, stdout);
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
	FILE* fp = fopen("/boot/grub/grub.cfg", "r");
 | 
			
		||||
	if (fp == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		perror("fopen");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (;;)
 | 
			
		||||
	{
 | 
			
		||||
		char buffer[128];
 | 
			
		||||
		size_t nread = fread(buffer, 1, sizeof(buffer) - 1, fp);
 | 
			
		||||
		if (nread == 0)
 | 
			
		||||
		int* ptrs[10];
 | 
			
		||||
		for (int j = 0; j < 10; j++)
 | 
			
		||||
		{
 | 
			
		||||
			if (ferror(fp))
 | 
			
		||||
				perror("fread");
 | 
			
		||||
			break;
 | 
			
		||||
			ptrs[j] = malloc(10);
 | 
			
		||||
			if (ptrs[j] == NULL)
 | 
			
		||||
			{
 | 
			
		||||
				perror("malloc");
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
			*ptrs[j] = j;
 | 
			
		||||
			putc('0' + *ptrs[j], stdout);
 | 
			
		||||
		}
 | 
			
		||||
		buffer[nread] = '\0';
 | 
			
		||||
		fputs(buffer, stdout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fclose(fp) == EOF)
 | 
			
		||||
	{
 | 
			
		||||
		perror("fclose");
 | 
			
		||||
		return 1;
 | 
			
		||||
		for (int j = 0; j < 10; j++)
 | 
			
		||||
			free(ptrs[j]);
 | 
			
		||||
		putc('\n', stdout);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue