From 3612e92ecaa7690c8db27b825abadcb58221a80b Mon Sep 17 00:00:00 2001 From: Santiago Lo Coco Date: Sun, 26 Sep 2021 10:52:29 -0300 Subject: [PATCH] Add KR (not working) and Buddy MM (working) Co-authored-by: Ezequiel Bellver Co-authored-by: Juan Barmasch --- Kernel/memManagerBuddy.c | 457 ++++++++++++++++++++++++++++++++++++++- Kernel/memManagerKR.c | 177 +++++++++++++++ 2 files changed, 627 insertions(+), 7 deletions(-) diff --git a/Kernel/memManagerBuddy.c b/Kernel/memManagerBuddy.c index 26f9633..58a099f 100644 --- a/Kernel/memManagerBuddy.c +++ b/Kernel/memManagerBuddy.c @@ -1,13 +1,456 @@ -#ifdef BUDDY +// #ifdef BUDDY +#include +#include +#include +#include +#include +#define MANAGED_MEMORY_SIZE 1024 * 1024 * 64 -#include "memManager.h" +// https://github.com/sdpetrides/BuddyAllocator -char initMemoryManager(void *const restrict memoryForMemoryManager, void *const restrict managedMemory) { - return 1; +// char initMemoryManager(void *const restrict memoryForMemoryManager, void *const restrict managedMemory) { +// return 1; +// } + +// void * memMalloc(const size_t memoryToAllocate) { +// return NULL; +// } + +typedef struct meta { + unsigned char allo : 1; // 0000000_ - allocated + unsigned char left : 1; // 000000_0 - first or second + unsigned char size : 6; // ______00 - n where (2^n)-1 is the block size +} Meta; + +static char myblock[MANAGED_MEMORY_SIZE]; + +void unpack(Meta * m, int pos); + +/* Fills myblock with zeros and creates first metadata */ +void init_block() { + memset(&myblock, '\0', MANAGED_MEMORY_SIZE); + memset(&myblock, 54, 1); } -void * memMalloc(const size_t memoryToAllocate) { - return NULL; +/* Returns log base 2 of a double d */ +double log2(double d) { + return log(d) / log(2); } -#endif \ No newline at end of file +/* Returns the level a reqSize will fit in */ +int size_to_n(size_t reqSize) { + reqSize+=1; + double d = log2((double)reqSize); + return (int)ceil(d); +} + +/* Returns the position of the next block of the correct size */ +int jump_next(int n, int pos) { + int bits = pos>>(n); + bits+=1; + int ret = bits<<(n); + + if (ret == MANAGED_MEMORY_SIZE) { + return ret; + } else { + return ret; + } + +} + +/* Returns the position of the left half of a pair */ +int jump_back(int n, int pos) { + int bits = pos>>(n); + bits-=1; + return bits<<(n); +} + +/* Fills a Meta struct with metadata at pos */ +void unpack(Meta * m, int pos) { + memset(m, myblock[pos], 1); +} + +/* Returns whether position at level n is left or right partner */ +int is_left(int n, int pos) { + + // Manipulate bits to set nth bit on + int k = 1; + k<<=(n); + + // Manipulate bits to zero bits above n + unsigned int p = (unsigned int)pos; + p<<=(31-n); + p>>=(31-n); + + if (k == p) { + return 0; // Right + } else { + return 1; // Left + } +} + +/* Mergee two unallocated blocks with same size */ +void merge(int pos, int pos2, int n) { + + // Create new meta and set size field + char newMeta = (n+1)<<2; + + // Set left field + if (is_left(n+1, pos)) { + newMeta+=2; + } + + // Add new meta + myblock[pos] = newMeta; + + // Delete meta on right partner + myblock[pos2] = 0; +} + +/* MYmymalloc */ +void * mymalloc(size_t reqSize) { + + // Check if too big + if (reqSize > MANAGED_MEMORY_SIZE - 1) { + fprintf(stderr, "Error: Requested size too large\n"); + } + + // Traverse heap to find block of correct size - algo(n) + int n = size_to_n(reqSize); + int pos = 0; + unsigned char c = 0; + Meta * m = memset(&c, 0, 1); + + while (pos < MANAGED_MEMORY_SIZE) { + // Read metadata + unpack(m, pos); + + // Debugging + if (m->size == 0) { + exit(0); + } + + if (n <= m->size) { + if (m->allo == 1) { + // Jump + pos = jump_next(n, pos); + continue; + } else if (m->size == n) { + // Allocate + myblock[pos]+=1; + pos+=1; + return (void*)((long int)&myblock+pos); + } else { + // Partition + + // Get partner position + int partner = jump_next((m->size)-1, pos); + + // Set Left + char meta_1 = 2; + char meta_2 = 0; + + // Set Size + char s = ((m->size)-1)<<2; + meta_1 = (meta_1 | s); + meta_2 = (meta_2 | s); + + // Fill in metadata + myblock[pos] = meta_1; + myblock[partner] = meta_2; + + // Continue on same position with new size of block + continue; + } + } else { + // Jump + pos = jump_next(n, pos); + continue; + } + } + + fprintf(stderr, "Error: Did not allocate %d\n", pos); + + return 0; +} + +/* MYmyfree */ +void myfree(void * ptr) { + + // Error Checking + if (ptr <= (void *)&myblock || ptr > (void *)(&myblock + MANAGED_MEMORY_SIZE)) { + fprintf(stderr, "Error en free\n"); + return; + } + + // Get position + // int pos = (int)(ptr-(void *)&myblock-1); + int pos = (int)((char *)ptr-(char *)&myblock-1); + + // Check if valid metadata location + if (pos%2 == 1 || myblock[pos] == 0) { + fprintf(stderr, "Error con metadata\n"); + return; + } + + + // Initialize variables for merge + unsigned char c1 = 0; + unsigned char c2 = 0; + Meta * m1 = memset(&c1, 0, 1); + Meta * m2 = memset(&c2, 0, 1); + unpack(m1,pos); + + // Change allocated field + myblock[pos] = myblock[pos] - 1; + + while (pos >= 0 && pos <= 8196){ + // Read metadata + unpack(m1,pos); + + if (m1->left) { // Left Partner + + // Get position of other partner and read metadata + int pos2 = jump_next(m1->size, pos); + + if (pos2 >= 0 && pos2 <= MANAGED_MEMORY_SIZE - 2) { + unpack(m2,pos2); + } else { + break; + } + + // Merge or break + if (m2->allo || m2->size != m1->size) { + break; + } else { + merge(pos, pos2, m1->size); + } + + } else { // Right Partner + + // Get position of other partner and read metadata + int pos2 = jump_back(m2->size,pos); + + if (pos2 >= 0 && pos2 <= MANAGED_MEMORY_SIZE -2) { + unpack(m2,pos2); + } else { + break; + } + + // Merge or break + if (m2->allo || m2->size != m1->size) { + break; + } else { + merge(pos2, pos, m1->size); + } + } + } +} + +int rando[20] = { + 56, 73, 2, 8, 76, + 56, 66, 21, 13, 4, + 99, 80, 25, 6, 38, + 10, 64, 12, 32, 71 +}; + +/* testA: mymalloc() 1 byte 3000 times, then myfree() the 3000 1 byte pointers one by one */ +void testA() { + int i = 0; + char * p[3000]; + + while (i < 3000) { + p[i] = (char *)mymalloc(sizeof(char)*1); + i++; + } + + i = 0; + + while (i < 3000) { + myfree(p[i]); + i++; + } + + return; +} + +/* testB: mymalloc() 1 byte and immediately myfree it 3000 times in a row */ +void testB() { + int i = 0; + char * p; + + while (i < 3000) { + p = (char *)mymalloc(sizeof(char)*1); + myfree(p); + i++; + } + + return; +} + +/* testC: Randomly choose between a 1 byte mymalloc() or myfree() 6000 times */ +void testC() { + int i = 1; + int j = 0; + char * p[6000]; + + p[0] = (char *)mymalloc(sizeof(char)*1); + + while (i+j < 1000) { + + if ((i+j)%2 != 0) { + p[i] = (char *)mymalloc(sizeof(char)*1); + i++; + } else if (p[j] != 0) { + myfree(p[j]); + j++; + } else { + p[i] = (char *)mymalloc(sizeof(char)*1); + i++; + } + } + + while (j <= i) { + myfree(p[j]); + j++; + } + + return; +} + +/* testD: Randomly choose between a randomly-sized mymalloc() or myfree 6000 times */ +void testD() { + int i = 1; + int j = 0; + char * p[6000]; + + p[0] = (char *)mymalloc(sizeof(char)*(20)); + + while (i+j < 6000) { + + if ((i+j)%2 != 0) { + p[i] = (char *)mymalloc(sizeof(char)*(((i%2)+1)*20)); + i++; + } else if (p[j] != 0) { + myfree(p[j]); + j++; + } else { + p[i] = (char *)mymalloc(sizeof(char)*(((i%2)+1)*20)); + i++; + } + } + + while (j <= i) { + myfree(p[j]); + j++; + } + + return; +} + +/* testE: mymalloc 100 2bytes and myfrees 100 2bytes 10 times */ +void testE() { + int i = 0; + int j = 0; + int k = 0; + int m = 0; + char * p[6000]; + + while (i < 6000) { + k = 0; + while (k < 100) { + p[i] = (char *)mymalloc(sizeof(char)*(2)); + i++; k++; + } + + m = 0; + while (m < 100) { + myfree(p[j]); + j++; m++; + } + } + + return; +} + +/* testF: mymalloc 2000 2bytes, myfrees 1000 2bytes, mymalloc 2000 2bytes, myfrees 3000 2bytes */ +void testF() { + int i = 0; + int j = 0; + char * p[6000]; + + + while (i < 2000) { + p[i] = (char *)mymalloc(sizeof(char)*(2)); + i++; + } + + while (j < 1000) { + myfree(p[j]); + j++; + } + + while (i < 2000) { + p[i] = (char *)mymalloc(sizeof(char)*(2)); + i++; + } + + while (j < 4000) { + myfree(p[j]); + j++; + } + + return; +} + + +int main(int argc, char const *argv[]) { + + // Inititialize variables for workflow + int i, j; + + // Loop through fptr array + for (j = 0; j < 6; j++) { + + // Initialize time elapsed + double time_elapsed_in_seconds = 0.0; + + // Run the fuction 100 times and calculate total time elapsed + for (i = 0; i < 100; i++) { + + // Initialize myblock + init_block(); + + clock_t start = clock(); + switch(j) { + case 0: + testA(); + break; + case 1: + testB(); + break; + case 2: + testC(); + break; + case 3: + testD(); + break; + case 4: + testE(); + break; + case 5: + testF(); + break; + } + clock_t end = clock(); + time_elapsed_in_seconds+=(end - start)/(double)CLOCKS_PER_SEC; + } + + // Print the after execution time of 100 runs + printf("Time Elapsed test%d: %f secs\n", j, time_elapsed_in_seconds/100); + } + + return 0; +} + +// #endif \ No newline at end of file diff --git a/Kernel/memManagerKR.c b/Kernel/memManagerKR.c index 925c81d..2adec13 100644 --- a/Kernel/memManagerKR.c +++ b/Kernel/memManagerKR.c @@ -1,2 +1,179 @@ #ifndef BUDDY + +#include +#include +#include +#include +#include + +typedef long Align; /* for alignment to long boundary */ +union header +{ /* block header */ + struct + { + union header *ptr; /* next block if on free list */ + unsigned size; /* size of this block */ + } s; + Align x; /* force alignment of blocks */ +}; +typedef union header Header; + +// static Header base; /* empty list to get started */ +static Header *base; /* empty list to get started */ +static Header *freep = NULL; /* start of free list */ + +char initMemoryManager(void * managedMemory) { + // freep = (Header *) managedMemory; + // freep->s.ptr = NULL; + // freep->s.size = ; + + base = (Header *) managedMemory; +} + +/* memMalloc: general-purpose storage allocator */ +void * +memMalloc(unsigned nbytes) +{ + Header *p, *prevp; + Header *moreroce(unsigned); + unsigned nunits; + // nunits = (nbytes + sizeof(Header) - 1) / sizeof(header) + 1; + nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; + if ((prevp = freep) == NULL) + { /* no free list yet */ + // base.s.ptr = freeptr = prevptr = &base; + // base.s.ptr = &base; + // base.s.size = 0; + base->s.ptr = base; + base->s.size = 0; + } + for (p = prevp->s.ptr;; prevp = p, p = p->s.ptr) + { + if (p->s.size >= nunits) + { /* big enough */ + if (p->s.size == nunits) /* exactly */ + prevp->s.ptr = p->s.ptr; + else + { /* allocate tail end */ + p->s.size -= nunits; + p += p->s.size; + p->s.size = nunits; + } + freep = prevp; + return (void *)(p + 1); + } + // if (p == freep) /* wrapped around free list */ + // if ((p = morecore(nunits)) == NULL) + // return NULL; /* none left */ + } +} + +// #define NALLOC 1024 /* minimum #units to request */ + +// /* morecore: ask system for more memory */ +// static Header *morecore(unsigned nu) +// { +// char *cp, *sbrk(int); +// Header *up; +// if (nu < NALLOC) +// nu = NALLOC; +// cp = sbrk(nu * sizeof(Header)); +// if (cp == (char *)-1) /* no space at all */ +// return NULL; +// up = (Header *)cp; +// up->s.size = nu; +// free((void *)(up + 1)); +// return freep; +// } + +/* free: put block ap in free list */ +void free(void *ap) +{ + Header *bp, *p; + bp = (Header *)ap - 1; /* point to block header */ + for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) + if (p >= p->s.ptr && (bp > p || bp < p->s.ptr)) + break; /* freed block at start or end of arena */ + if (bp + bp->s.size == p->s.ptr) + { /* join to upper nbr */ + bp->s.size += p->s.ptr->s.size; + bp->s.ptr = p->s.ptr->s.ptr; + } + else + bp->s.ptr = p->s.ptr; + if (p + p->s.size == bp) + { /* join to lower nbr */ + p->s.size += bp->s.size; + p->s.ptr = bp->s.ptr; + } + else + p->s.ptr = bp; + freep = p; +} + +char testOne() { + void * alloc1 = memMalloc(100); + void * alloc2 = memMalloc(200); + void * alloc3 = memMalloc(300); + + memset(alloc1, 1, 100); + memset(alloc2, 2, 200); + memset(alloc3, 3, 300); + + for (int i = 0; i < 600; i++) { + if (i < 100) { + assert(*((char *) alloc1+i) == 1); + } else if (i < 300) { + assert(*((char *) alloc1+i) == 2); + } else if (i < 600) { + assert(*((char *) alloc1+i) == 3); + } + } + + return EXIT_SUCCESS; +} + +static unsigned long int next = 1; +int rand(void) // RAND_MAX assumed to be 32767 +{ + next = next * 1103515245 + 12345; + return (unsigned int)(next/65536) % 32768; +} + +/* +char testTwo() { + void * ptr; + while (ptr != NULL){ + ptr = memMalloc((rand() % 2000) + 1); + if (!((char *) memoryManager->nextAddress >= memoryManager->initialAddress)) { + printStringLen(13, "allocRand1 -- ERROR", 31); + new_line(); + return EXIT_FAILURE; + } + if (!((char *) memoryManager->nextAddress <= memoryManager->initialAddress + MANAGED_MEMORY_SIZE)) { + printStringLen(13, "allocRand2 -- ERROR", 31); + new_line(); + return EXIT_FAILURE; + } + // if (!((char *) memoryManager->lastAddress >= memoryManager->initialAddress)) { + // } + // if (!((char *) memoryManager->lastAddress <= memoryManager->initialAddress + MANAGED_MEMORY_SIZE)) { + // } + } + + return EXIT_SUCCESS; + +} +*/ + +char mem[1024]; + +int main() { + initMemoryManager(mem); + if (testOne() == EXIT_FAILURE) + return EXIT_FAILURE; + // if (testTwo() == EXIT_FAILURE) + // return EXIT_FAILURE; +} + #endif \ No newline at end of file