Compare commits
	
		
			10 Commits
		
	
	
		
			583fc634e4
			...
			46172adb32
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 46172adb32 | |||
| 9133082641 | |||
| 7fad0f984f | |||
| cdd6f1ebec | |||
| 938a0b3dc8 | |||
| f4c73354c5 | |||
| b7093a6f1c | |||
| 79b706d58c | |||
| 4603a79559 | |||
| 1442be32bb | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					main
 | 
				
			||||||
							
								
								
									
										31
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    // Use IntelliSense to learn about possible attributes.
 | 
				
			||||||
 | 
					    // Hover to view descriptions of existing attributes.
 | 
				
			||||||
 | 
					    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
				
			||||||
 | 
					    "version": "0.2.0",
 | 
				
			||||||
 | 
					    "configurations": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "Run main",
 | 
				
			||||||
 | 
					            "type": "cppdbg",
 | 
				
			||||||
 | 
					            "request": "launch",
 | 
				
			||||||
 | 
					            "program": "${workspaceFolder}/main",
 | 
				
			||||||
 | 
					            "stopAtEntry": false,
 | 
				
			||||||
 | 
					            "cwd": "${workspaceFolder}",
 | 
				
			||||||
 | 
					            "environment": [],
 | 
				
			||||||
 | 
					            "externalConsole": false,
 | 
				
			||||||
 | 
					            "MIMode": "gdb",
 | 
				
			||||||
 | 
					            "setupCommands": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "description": "Enable pretty-printing for gdb",
 | 
				
			||||||
 | 
					                    "text": "-enable-pretty-printing",
 | 
				
			||||||
 | 
					                    "ignoreFailures": true
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "description": "Set Disassembly Flavor to Intel",
 | 
				
			||||||
 | 
					                    "text": "-gdb-set disassembly-flavor intel",
 | 
				
			||||||
 | 
					                    "ignoreFailures": true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "cmake.configureOnOpen": false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
CC=clang
 | 
					CC=clang
 | 
				
			||||||
CFLAGS=-g -Wall -Werror -pedantic
 | 
					CFLAGS=-g -Wall -Wextra -Werror -pedantic
 | 
				
			||||||
SRC=*.c
 | 
					SRC=*.c
 | 
				
			||||||
OUT=main
 | 
					OUT=main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					# Custom dynamic memory allocator (WIP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ongoing attempt to create a custom dynamic memory allocator. This is not intended for production use. It is just an exercise for learning purposes.
 | 
				
			||||||
							
								
								
									
										138
									
								
								allocator.c
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								allocator.c
									
									
									
									
									
								
							@@ -8,12 +8,6 @@
 | 
				
			|||||||
#define FOOTER_MAGIC_01 2783946
 | 
					#define FOOTER_MAGIC_01 2783946
 | 
				
			||||||
#define FOOTER_MAGIC_02 878512284
 | 
					#define FOOTER_MAGIC_02 878512284
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct allocator {
 | 
					 | 
				
			||||||
  u8 *buf;
 | 
					 | 
				
			||||||
  u64 size;
 | 
					 | 
				
			||||||
  u64 used;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct block_boundary {
 | 
					struct block_boundary {
 | 
				
			||||||
  u64 size;
 | 
					  u64 size;
 | 
				
			||||||
  bool free;
 | 
					  bool free;
 | 
				
			||||||
@@ -24,34 +18,74 @@ struct block_boundary {
 | 
				
			|||||||
typedef struct block_boundary block_header;
 | 
					typedef struct block_boundary block_header;
 | 
				
			||||||
typedef struct block_boundary block_footer;
 | 
					typedef struct block_boundary block_footer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					struct allocator {
 | 
				
			||||||
  block_header header;
 | 
					  u8 *buf;
 | 
				
			||||||
  u8 *data;
 | 
					  u64 size;
 | 
				
			||||||
  block_footer footer;
 | 
					  u64 used;
 | 
				
			||||||
} block_t;
 | 
					  u64 block_count;
 | 
				
			||||||
 | 
					  u64 free_max_size;
 | 
				
			||||||
 | 
					  u64 free_count;
 | 
				
			||||||
 | 
					  block_header **free_blocks; // Array of pointers
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
allocator_t *init_allocator(u64 size) {
 | 
					allocator_t *init_allocator(u64 size) {
 | 
				
			||||||
  allocator_t *allocator = (allocator_t *)malloc(sizeof(allocator_t));
 | 
					  allocator_t *allocator = (allocator_t *)malloc(sizeof(allocator_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!allocator) {
 | 
					  if (!allocator) {
 | 
				
			||||||
 | 
					    deinit_allocator(&allocator);
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  allocator->buf = (u8 *)malloc(size);
 | 
					  allocator->buf = (u8 *)malloc(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!(allocator->buf)) {
 | 
					  if (!(allocator->buf)) {
 | 
				
			||||||
    free(allocator);
 | 
					    deinit_allocator(&allocator);
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  allocator->size = size;
 | 
					  allocator->size = size;
 | 
				
			||||||
  allocator->used = 0;
 | 
					  allocator->used = 0;
 | 
				
			||||||
 | 
					  allocator->block_count = allocator->free_count = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Each memory block has a header and footer, so the maximum number of blocks
 | 
				
			||||||
 | 
					  // that can be added to the buffer can be calculated by assuming blocks of
 | 
				
			||||||
 | 
					  // size 0 (i.e. only containing a header and a footer)
 | 
				
			||||||
 | 
					  allocator->free_max_size =
 | 
				
			||||||
 | 
					      size / (sizeof(block_header) + sizeof(block_footer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  allocator->free_blocks = (block_header **)malloc(allocator->free_max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!(allocator->free_blocks)) {
 | 
				
			||||||
 | 
					    deinit_allocator(&allocator);
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  block_header *header = (block_header *)allocator->buf;
 | 
				
			||||||
 | 
					  block_footer *footer =
 | 
				
			||||||
 | 
					      (block_footer *)(allocator->buf + size - sizeof(block_footer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  header->size = size;
 | 
				
			||||||
 | 
					  footer->size = size - sizeof(block_footer);
 | 
				
			||||||
 | 
					  header->free = footer->free = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  header->magic_01 = HEADER_MAGIC_01;
 | 
				
			||||||
 | 
					  header->magic_02 = HEADER_MAGIC_02;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  footer->magic_01 = FOOTER_MAGIC_01;
 | 
				
			||||||
 | 
					  footer->magic_02 = FOOTER_MAGIC_02;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  allocator->free_blocks[0] = header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return allocator;
 | 
					  return allocator;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void deinit_allocator(allocator_t **allocator) {
 | 
					void deinit_allocator(allocator_t **allocator) {
 | 
				
			||||||
  if (*allocator != NULL) {
 | 
					  if (*allocator != NULL) {
 | 
				
			||||||
 | 
					    if ((*allocator)->free_blocks != NULL) {
 | 
				
			||||||
 | 
					      free((*allocator)->free_blocks);
 | 
				
			||||||
 | 
					      (*allocator)->free_blocks = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((*allocator)->buf != NULL) {
 | 
					    if ((*allocator)->buf != NULL) {
 | 
				
			||||||
      free((*allocator)->buf);
 | 
					      free((*allocator)->buf);
 | 
				
			||||||
      (*allocator)->buf = NULL;
 | 
					      (*allocator)->buf = NULL;
 | 
				
			||||||
@@ -62,4 +96,82 @@ void deinit_allocator(allocator_t **allocator) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *alloc(allocator_t *allocator, u64 size) {}
 | 
					void *allocate(allocator_t *allocator, u64 size) {
 | 
				
			||||||
 | 
					  u64 min_size_required = size + sizeof(block_header) + sizeof(block_footer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!allocator || allocator->used == allocator->size ||
 | 
				
			||||||
 | 
					      min_size_required > allocator->size - allocator->used) {
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  block_header *header = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  u64 block_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (u64 i = 0; i < allocator->free_count; ++i) {
 | 
				
			||||||
 | 
					    block_header *current = allocator->free_blocks[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (current->size == min_size_required) {
 | 
				
			||||||
 | 
					      header = current;
 | 
				
			||||||
 | 
					      block_index = i;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!header || (header && current->size < header->size &&
 | 
				
			||||||
 | 
					                    current->size > min_size_required)) {
 | 
				
			||||||
 | 
					      header = current;
 | 
				
			||||||
 | 
					      block_index = i;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (header) {
 | 
				
			||||||
 | 
					    u8 *header_start = (u8 *)header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    block_footer *footer =
 | 
				
			||||||
 | 
					        (block_footer *)(header_start + header->size - sizeof(block_footer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u64 old_size = header->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool create_new_block = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If allocating exactly the required size will leave enough memory to
 | 
				
			||||||
 | 
					    // create another block, set the header size to min_size_required
 | 
				
			||||||
 | 
					    if (old_size - min_size_required >
 | 
				
			||||||
 | 
					        sizeof(block_header) + sizeof(block_footer)) {
 | 
				
			||||||
 | 
					      header->size = min_size_required;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      create_new_block = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    header->free = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (create_new_block) {
 | 
				
			||||||
 | 
					      footer->size -= header->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      block_header *new_header = (block_header *)(header_start + header->size);
 | 
				
			||||||
 | 
					      new_header->size = old_size - header->size;
 | 
				
			||||||
 | 
					      new_header->magic_01 = header->magic_01;
 | 
				
			||||||
 | 
					      new_header->magic_02 = header->magic_02;
 | 
				
			||||||
 | 
					      new_header->free = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      allocator->free_blocks[block_index] = new_header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      block_footer *new_footer =
 | 
				
			||||||
 | 
					          (block_footer *)(header_start + header->size - sizeof(block_footer));
 | 
				
			||||||
 | 
					      new_footer->size = header->size - sizeof(block_footer);
 | 
				
			||||||
 | 
					      new_footer->magic_01 = footer->magic_01;
 | 
				
			||||||
 | 
					      new_footer->magic_02 = footer->magic_02;
 | 
				
			||||||
 | 
					      new_footer->free = false;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      footer->free = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      --(allocator->free_count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allocator->used += header->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (void *)(header_start + sizeof(block_header));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,6 @@ typedef struct allocator allocator_t;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
allocator_t *init_allocator(u64 size);
 | 
					allocator_t *init_allocator(u64 size);
 | 
				
			||||||
void deinit_allocator(allocator_t **allocator);
 | 
					void deinit_allocator(allocator_t **allocator);
 | 
				
			||||||
void *alloc(allocator_t *allocator, u64 size);
 | 
					void *allocate(allocator_t *allocator, u64 size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // !ALLOCATOR_H
 | 
					#endif // !ALLOCATOR_H
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include "allocator.h"
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BUF_SIZE 10 * 1024 * 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i32 main(void) {
 | 
				
			||||||
 | 
					  allocator_t *allocator = init_allocator(BUF_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!allocator) {
 | 
				
			||||||
 | 
					    return EXIT_FAILURE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  i32 *num = (i32 *)allocate(allocator, sizeof(i32));
 | 
				
			||||||
 | 
					  *num = 25;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  deinit_allocator(&allocator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return EXIT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user