base allocator logic
This commit is contained in:
216
src/memory/allocator.h
Normal file
216
src/memory/allocator.h
Normal 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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user