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();
 | 
							~FixedWidthAllocator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		vaddr_t allocate();
 | 
							vaddr_t allocate();
 | 
				
			||||||
		void deallocate(vaddr_t);
 | 
							bool deallocate(vaddr_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uint32_t allocation_size() const { return m_allocation_size; }
 | 
							uint32_t allocation_size() const { return m_allocation_size; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,8 +26,10 @@ namespace Kernel
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			node* prev { nullptr };
 | 
								node* prev { nullptr };
 | 
				
			||||||
			node* next { 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*);
 | 
							void allocate_page_for_node_if_needed(const node*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,7 @@ namespace Kernel
 | 
				
			||||||
		BAN::ErrorOr<void> set_working_directory(BAN::StringView);
 | 
							BAN::ErrorOr<void> set_working_directory(BAN::StringView);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<void*> allocate(size_t);
 | 
							BAN::ErrorOr<void*> allocate(size_t);
 | 
				
			||||||
 | 
							void free(void*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void termid(char*) const;
 | 
							void termid(char*) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#define SYS_SEEK 6
 | 
					#define SYS_SEEK 6
 | 
				
			||||||
#define SYS_OPEN 7
 | 
					#define SYS_OPEN 7
 | 
				
			||||||
#define SYS_ALLOC 8
 | 
					#define SYS_ALLOC 8
 | 
				
			||||||
 | 
					#define SYS_FREE 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,9 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		node* node = m_free_list;
 | 
							node* node = m_free_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ASSERT(!node->allocated);
 | 
				
			||||||
 | 
							node->allocated = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m_free_list = node->next;
 | 
							m_free_list = node->next;
 | 
				
			||||||
		if (m_free_list)
 | 
							if (m_free_list)
 | 
				
			||||||
			m_free_list->prev = nullptr;
 | 
								m_free_list->prev = nullptr;
 | 
				
			||||||
| 
						 | 
					@ -100,23 +103,50 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m_allocated++;
 | 
							m_allocated++;
 | 
				
			||||||
		allocate_page_for_node_if_needed(node);
 | 
							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;
 | 
							if (address % m_allocation_size)
 | 
				
			||||||
		ASSERT_NOT_REACHED();
 | 
								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 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));
 | 
							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];
 | 
							vaddr_t page_begin = ((vaddr_t*)m_allocated_pages)[page_index];
 | 
				
			||||||
		ASSERT(page_begin);
 | 
							ASSERT(page_begin);
 | 
				
			||||||
| 
						 | 
					@ -124,11 +154,38 @@ namespace Kernel
 | 
				
			||||||
		return page_begin + offset * m_allocation_size;
 | 
							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)
 | 
						void FixedWidthAllocator::allocate_page_for_node_if_needed(const node* node)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uint32_t index = node - (struct node*)m_nodes_page;
 | 
							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));
 | 
							ASSERT(page_index < PAGE_SIZE / sizeof(vaddr_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		vaddr_t& page_vaddr = ((vaddr_t*)m_allocated_pages)[page_index];
 | 
							vaddr_t& page_vaddr = ((vaddr_t*)m_allocated_pages)[page_index];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -386,6 +386,14 @@ namespace Kernel
 | 
				
			||||||
		return BAN::Error::from_errno(ENOMEM);
 | 
							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
 | 
						void Process::termid(char* buffer) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (m_tty == nullptr)
 | 
							if (m_tty == nullptr)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +63,11 @@ namespace Kernel
 | 
				
			||||||
		return (long)res.value();
 | 
							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)
 | 
						extern "C" long cpp_syscall_handler(int syscall, void* arg1, void* arg2, void* arg3)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Thread::current().set_in_syscall(true);
 | 
							Thread::current().set_in_syscall(true);
 | 
				
			||||||
| 
						 | 
					@ -96,6 +101,9 @@ namespace Kernel
 | 
				
			||||||
		case SYS_ALLOC:
 | 
							case SYS_ALLOC:
 | 
				
			||||||
			ret = sys_alloc((size_t)arg1);
 | 
								ret = sys_alloc((size_t)arg1);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case SYS_FREE:
 | 
				
			||||||
 | 
								sys_free(arg1);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			Kernel::panic("Unknown syscall {}", syscall);
 | 
								Kernel::panic("Unknown syscall {}", syscall);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,9 @@ void* calloc(size_t nmemb, size_t size)
 | 
				
			||||||
	return ptr;
 | 
						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);
 | 
								ret = Kernel::syscall(SYS_ALLOC, bytes);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							case SYS_FREE:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								void* ptr = va_arg(args, void*);
 | 
				
			||||||
 | 
								ret = Kernel::syscall(SYS_FREE, ptr);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			puts("LibC: Unhandeled syscall");
 | 
								puts("LibC: Unhandeled syscall");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,41 +3,23 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main()
 | 
					int main()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void* ptr = malloc(10);
 | 
						for (int i = 0; i < 10; i++)
 | 
				
			||||||
	if (ptr == NULL)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		perror("malloc");
 | 
							int* ptrs[10];
 | 
				
			||||||
		return 1;
 | 
							for (int j = 0; j < 10; j++)
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*(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)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (ferror(fp))
 | 
								ptrs[j] = malloc(10);
 | 
				
			||||||
				perror("fread");
 | 
								if (ptrs[j] == NULL)
 | 
				
			||||||
			break;
 | 
								{
 | 
				
			||||||
 | 
									perror("malloc");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								*ptrs[j] = j;
 | 
				
			||||||
 | 
								putc('0' + *ptrs[j], stdout);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		buffer[nread] = '\0';
 | 
							for (int j = 0; j < 10; j++)
 | 
				
			||||||
		fputs(buffer, stdout);
 | 
								free(ptrs[j]);
 | 
				
			||||||
	}
 | 
							putc('\n', stdout);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (fclose(fp) == EOF)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		perror("fclose");
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue