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
 | 
			
		||||
CFLAGS=-g -Wall -Werror -pedantic
 | 
			
		||||
CFLAGS=-g -Wall -Wextra -Werror -pedantic
 | 
			
		||||
SRC=*.c
 | 
			
		||||
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_02 878512284
 | 
			
		||||
 | 
			
		||||
struct allocator {
 | 
			
		||||
  u8 *buf;
 | 
			
		||||
  u64 size;
 | 
			
		||||
  u64 used;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct block_boundary {
 | 
			
		||||
  u64 size;
 | 
			
		||||
  bool free;
 | 
			
		||||
@@ -24,34 +18,74 @@ struct block_boundary {
 | 
			
		||||
typedef struct block_boundary block_header;
 | 
			
		||||
typedef struct block_boundary block_footer;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  block_header header;
 | 
			
		||||
  u8 *data;
 | 
			
		||||
  block_footer footer;
 | 
			
		||||
} block_t;
 | 
			
		||||
struct allocator {
 | 
			
		||||
  u8 *buf;
 | 
			
		||||
  u64 size;
 | 
			
		||||
  u64 used;
 | 
			
		||||
  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 *allocator = (allocator_t *)malloc(sizeof(allocator_t));
 | 
			
		||||
 | 
			
		||||
  if (!allocator) {
 | 
			
		||||
    deinit_allocator(&allocator);
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  allocator->buf = (u8 *)malloc(size);
 | 
			
		||||
 | 
			
		||||
  if (!(allocator->buf)) {
 | 
			
		||||
    free(allocator);
 | 
			
		||||
    deinit_allocator(&allocator);
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  allocator->size = size;
 | 
			
		||||
  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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void deinit_allocator(allocator_t **allocator) {
 | 
			
		||||
  if (*allocator != NULL) {
 | 
			
		||||
    if ((*allocator)->free_blocks != NULL) {
 | 
			
		||||
      free((*allocator)->free_blocks);
 | 
			
		||||
      (*allocator)->free_blocks = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((*allocator)->buf != NULL) {
 | 
			
		||||
      free((*allocator)->buf);
 | 
			
		||||
      (*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);
 | 
			
		||||
void deinit_allocator(allocator_t **allocator);
 | 
			
		||||
void *alloc(allocator_t *allocator, u64 size);
 | 
			
		||||
void *allocate(allocator_t *allocator, u64 size);
 | 
			
		||||
 | 
			
		||||
#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