diff --git a/run.exe b/run.exe index ec0091b..99be10f 100644 Binary files a/run.exe and b/run.exe differ diff --git a/src/main.c b/src/main.c index e9cdae1..2512cdb 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,18 @@ +#include "memory/allocator.h" + int main() { - return 0; + 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; } \ No newline at end of file diff --git a/src/memory/allocator.h b/src/memory/allocator.h new file mode 100644 index 0000000..e8c1ff1 --- /dev/null +++ b/src/memory/allocator.h @@ -0,0 +1,216 @@ +#include +#include +#include + +/* + 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"); + } +}