base allocator logic

This commit is contained in:
Jose Luis Montañes Ojados
2026-02-15 20:57:19 +01:00
parent 74b426e12d
commit c90883ac27
3 changed files with 232 additions and 1 deletions

BIN
run.exe

Binary file not shown.

View File

@@ -1,3 +1,18 @@
#include "memory/allocator.h"
int main() { int main() {
JLANG_memory_allocator *allocPtr = JLANG_CreateAllocator();
printf("allocatorPtr=%p\n", allocPtr);
printf("memoryPtr=%p\n", allocPtr->memory);
printf("size=%zu\n", allocPtr->size);
JLANG_visualize(allocPtr);
void *var1 = JLANG_malloc(allocPtr, 512);
printf("var1Ptr=%p\n", var1);
JLANG_visualize(allocPtr);
return 0; return 0;
} }

216
src/memory/allocator.h Normal file
View File

@@ -0,0 +1,216 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
Custom Memory Allocator
Implementacion custom de un memory allocator que opera sobre un array de bytes usandolo como "heap"
*/
#define JLANG_OK 0
#define JLANG_ERR 1
#define JLANG_FREE 0
#define JLANG_HEADER 1
#define JLANG_PAYLOAD 2
/*
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si está en uso.
Se añadirá al principio de cada bloque
[BLOCK_METADATA] + [BLOCK_BYTES]
*/
typedef struct
{
size_t size; // 8 bytes
int in_use; // 4 bytes
// --- aquí el compilador mete 4 bytes invisibles ---
} JLANG_metadata;
/*
La estructura de Memory Allocator se encarga de almancenar el array de memoria y el tamaño de esta.
*/
typedef struct
{
char *memory; // 8 bytes
size_t size; // 8 bytes
} JLANG_memory_allocator;
void *JLANG_CreateAllocator()
{
// Allocate memory in heap for JLANG_memory_allocator
JLANG_memory_allocator *allocator = (JLANG_memory_allocator *)malloc(sizeof(JLANG_memory_allocator));
// Assign default free bytes
allocator->memory = (char *)malloc(1 * 1024);
allocator->size = 1 * 1024;
// ensure all memory is zero
for (int i = 0; i < 1 * 1024; i++)
{
allocator->memory[i] = 0;
}
return allocator;
}
size_t JLANG_used(void *ptr)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size)
{
used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
}
return used;
}
void *JLANG_last_free(void *ptr)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size)
{
used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
}
return currentHeader;
}
void *JLANG_malloc(void *ptr, size_t size)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// 1. Hay bloques disponibles??
size_t used = JLANG_used(ptr);
size_t available = allocPtr->size - used;
// chequear si hay suficiente espacio libre
if (available > size + sizeof(JLANG_metadata))
{
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
freeHeader->size = size;
freeHeader->in_use = 1;
return (char *)freeHeader + sizeof(JLANG_metadata);
}
return NULL; // TODO
}
/*
Debug Visualization
[FF FF FF FF FF FF FF ]
*/
int _ceil(float v)
{
int n = (int)v;
float r = v - n;
if (r > 0)
{
return n + 1;
}
return n;
}
void JLANG_visualize(void *ptr)
{
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Step 1. Get byte type
char *byteMapPtr = (char *)malloc(allocPtr->size);
memset(byteMapPtr, 0, allocPtr->size);
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
long used = 0;
while (used < allocPtr->size)
{
long blockIndex = (char *)currentHeader - (char *)allocPtr->memory;
printf("blockIndex=%u\n", blockIndex);
used += sizeof(JLANG_metadata) + currentHeader->size;
/*
HEADER
blockIndex + sizeof(JLANG_metadata)
*/
if (currentHeader->size > 0)
{
byteMapPtr[blockIndex] = JLANG_HEADER;
for (int i = 0; i < sizeof(JLANG_metadata); i++)
{
byteMapPtr[blockIndex + i] = JLANG_HEADER;
}
/*
PAYLOAD
*/
for (int i = 0; i < currentHeader->size; i++)
{
byteMapPtr[blockIndex + sizeof(JLANG_metadata) + i] = JLANG_PAYLOAD;
}
} else {
break;
}
// Jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
}
// Step 2. Draw
int bytePerRow = 40;
int totalRows = _ceil(allocPtr->size / bytePerRow);
printf("totalRows=%d\n", totalRows);
char *currentMemPtr = allocPtr->memory;
for (int i = 0; i < totalRows; i++)
{
printf("[");
for (int n = 0; n < bytePerRow; n++)
{
int index = n + i * bytePerRow;
switch (byteMapPtr[index])
{
case JLANG_HEADER:
printf("\033[46m");
break;
case JLANG_FREE:
printf("\033[32m");
break;
default:
printf("\033[41m");
break;
}
printf("%.2x", (unsigned char) *(currentMemPtr + (n + i * bytePerRow)));
if (n < bytePerRow - 1)
{
printf(" ");
}
printf("\033[0m");
}
printf("]\n");
}
}