diff --git a/.gitignore b/.gitignore index cda2256..afcc3bf 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ manual/*.toc *.crf *.d *.plg +*.xml # *.sct *.tra *.lnp diff --git a/README.md b/README.md index d1c4a02..6e8965a 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,12 @@ This directory contains starter code of each lab. ### `submission` This directory contains template files for project submissions. + +Within manual_code: + +#### `template` +This directory contains the code the group edited for this project. + +The directory kernel contains the code used for memory management. + +The directory app contains the file ae_mem.c which contains our testing code. diff --git a/manual_code/lab1/template/.cproject b/manual_code/lab1/template/.cproject new file mode 100644 index 0000000..fac20cf --- /dev/null +++ b/manual_code/lab1/template/.cproject @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/manual_code/lab1/template/.project b/manual_code/lab1/template/.project new file mode 100644 index 0000000..86da93a --- /dev/null +++ b/manual_code/lab1/template/.project @@ -0,0 +1,27 @@ + + + SVC + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.arm.debug.ds.nature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/manual_code/lab1/template/SVC.launch b/manual_code/lab1/template/SVC.launch new file mode 100644 index 0000000..c7417f7 --- /dev/null +++ b/manual_code/lab1/template/SVC.launch @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/manual_code/lab1/template/src/.project b/manual_code/lab1/template/src/.project new file mode 100644 index 0000000..f7d6de6 --- /dev/null +++ b/manual_code/lab1/template/src/.project @@ -0,0 +1,11 @@ + + + src + + + + + + + + diff --git a/manual_code/lab1/template/src/app/ae_mem.c b/manual_code/lab1/template/src/app/ae_mem.c index 0db6243..6447fcd 100644 --- a/manual_code/lab1/template/src/app/ae_mem.c +++ b/manual_code/lab1/template/src/app/ae_mem.c @@ -24,37 +24,348 @@ #include "Serial.h" #include "printf.h" -int test_mem(void) { - void *p[4]; - int n; +int test_coales(void) { + U32 result = 0; + if (countNodes()==1){ + result |= BIT(0); + } - U32 result = 0; + void *p[4]; - p[0] = mem_alloc(8); + p[0] = mem_alloc(12); + p[1] = mem_alloc(24); + p[2] = mem_alloc(48); - if (p[0] != NULL) { - result |= BIT(0); + if (countNodes()==4){ + result |= BIT(1); } - p[1] = mem_alloc(8); + mem_dealloc(p[1]); + if (countNodes()==4){ + result |= BIT(2); + } + + mem_dealloc(p[0]); + if (countNodes()==3){ + result |= BIT(3); + } + + mem_dealloc(p[2]); + if (countNodes()==1){ + result |= BIT(4); + } - if (p[1] != NULL && p[1] != p[0]) { - result |= BIT(1); + return result == 31; +} + +int test_reuse_freed(void) { + void *p[4]; + U32 result = 0; + if (countNodes()==1){ + result |= BIT(0); + } + + p[0] = mem_alloc(12); + p[1] = mem_alloc(24); + p[2] = mem_alloc(48); + + if (countNodes()==4){ + result |= BIT(1); } mem_dealloc(p[0]); - n = mem_count_extfrag(128); - if (n == 1) { - result |= BIT(2); + if (countNodes()==4){ + result |= BIT(2); + } + + p[3] = mem_alloc(12); + if (countNodes()==4){ + result |= BIT(3); + } + + mem_dealloc(p[1]); + mem_dealloc(p[2]); + mem_dealloc(p[3]); + if (countNodes()==1){ + result |= BIT(4); + } + + if(memLeakCheck()==1){ + result |= BIT(5); + } + + return result == 63; +} + +int test_reuse_freed_2(void) { + void *p[4]; + U32 result = 0; + if (countNodes()==1){ + result |= BIT(0); + } + + p[0] = mem_alloc(12); + p[1] = mem_alloc(24); + p[2] = mem_alloc(48); + + if (countNodes()==4){ + result |= BIT(1); } mem_dealloc(p[1]); - n = mem_count_extfrag(128); - if (n == 0) { - result |= BIT(3); + if (countNodes()==4){ + result |= BIT(2); + } + + p[3] = mem_alloc(20); + if (countNodes()==4){ + result |= BIT(3); + } + + mem_dealloc(p[0]); + mem_dealloc(p[2]); + mem_dealloc(p[3]); + if (countNodes()==1){ + result |= BIT(4); + } + + if(memLeakCheck()==1){ + result |= BIT(5); + } + + return result == 63; +} + +int test_malloc_new_node(void) { + void *p[4]; + U32 result = 0; + if (countNodes()==1){ + result |= BIT(0); + } + + p[0] = mem_alloc(12); + p[1] = mem_alloc(60); + p[2] = mem_alloc(48); + + if (countNodes()==4){ + result |= BIT(1); } - return result; + + mem_dealloc(p[1]); + if (countNodes()==4){ + result |= BIT(2); + } + + p[3] = mem_alloc(12); + if (countNodes()==5){ + result |= BIT(3); + } + + mem_dealloc(p[3]); + if (countNodes()==4){ + result |= BIT(4); + } + + mem_dealloc(p[0]); + mem_dealloc(p[2]); + if (countNodes()==1){ + result |= BIT(5); + } + + if(memLeakCheck()==1){ + result |= BIT(6); + } + + return result == 127; } + +int test_mem_leak(){ + void *p[4]; + U32 result = 0; + if(memLeakCheck()==1){ + result |= BIT(0); + } + + p[0] = mem_alloc(12); + + if(memLeakCheck()==1){ + result |= BIT(1); + } + + mem_dealloc(p[0]); + + if(memLeakCheck()==1){ + result |= BIT(2); + } + + return result == 7; +} + +int test_extfrag(void){ + U32 result = 0; + if (countNodes() == 1){ + result |= BIT(0); + } + + void *p[10]; + + p[0] = mem_alloc(12); + p[1] = mem_alloc(12); + p[2] = mem_alloc(12); + p[3] = mem_alloc(12); + p[4] = mem_alloc(16); + p[5] = mem_alloc(12); + p[6] = mem_alloc(18); + + if (countNodes() == 8){ + result |= BIT(1); + } + + mem_dealloc(p[2]); + p[7] = mem_alloc(15); + + if (countNodes() == 9){ + result |= BIT(2); + } + + mem_dealloc(p[4]); + p[8] = mem_alloc(18); + + if (countNodes() == 10){ + result |= BIT(3); + } + + if (mem_count_extfrag(12+12) == 0){ + result |= BIT(4); + } + + if (mem_count_extfrag(13+12) == 1){ + result |= BIT(5); + } + + if (mem_count_extfrag(17+12) == 2){ + result |= BIT(6); + } + + mem_dealloc(p[0]); + mem_dealloc(p[1]); + + mem_dealloc(p[3]); + + mem_dealloc(p[5]); + mem_dealloc(p[6]); + mem_dealloc(p[7]); + mem_dealloc(p[8]); + + return result == 127; +} + +int test_utilization(void) { + unsigned int totalUsed = 0; + unsigned int counter = 0; + unsigned int regionSize = 1048576; + unsigned int magicSize = 1070585247; + + while(1){ + if (mem_alloc(regionSize) == NULL) { + break; + } + totalUsed += regionSize; + counter++; + if(totalUsed > magicSize){ + return -1; + } + } + + unsigned int numAllocs = counter; + return 0; +} + +int test_throughput(void){ + for(int i = 0; i < 200; i++){ + test_reuse_freed_2(); + } + return 1; +} + +int test4mock(){ + void *p[15]; + p[0] = mem_alloc(8); + p[1] = mem_alloc(8); + p[2] = mem_alloc(8); + p[3] = mem_alloc(8); + p[4] = mem_alloc(8); + p[5] = mem_alloc(8); + p[6] = mem_alloc(8); + p[7] = mem_alloc(8); + p[8] = mem_alloc(8); + p[9] = mem_alloc(8); + + mem_dealloc(p[0]); + mem_dealloc(p[2]); + mem_dealloc(p[4]); + mem_dealloc(p[6]); + mem_dealloc(p[8]); + + printf("Extfrag Regions: %d\r\n", mem_count_extfrag(8+12+1)); + printf("Extfrag Regions: %d\r\n", mem_count_extfrag(8+12)); + + p[10] = mem_alloc(8); + p[11] = mem_alloc(8); + p[12] = mem_alloc(8); + p[13] = mem_alloc(8); + p[14] = mem_alloc(8); + + printf("Extfrag Regions: %d\r\n", mem_count_extfrag(8+12+1)); + printf("Extfrag Regions: %d\r\n", mem_count_extfrag(8+12)); + + return 1; +} + +int test_mem(void) { +// Function Tests: +// U32 result = 0; +// +// if(test_mem_leak()){ +// result |= BIT(0); +// } +// if(test_coales()){ +// result |= BIT(1); +// } +// if(test_reuse_freed()){ +// result |= BIT(2); +// } +// if(test_reuse_freed_2()){ +// result |= BIT(3); +// } +// if(test_malloc_new_node()){ +// result |= BIT(4); +// } +// if(test_extfrag()){ +// result |= BIT(5); +// } +// +// return result == 63; + +// Failing Testcase: + U32 result = 0; + if(test4Mock()){ + result |= BIT(0); + } + return 1; + +// Throughput Test: (function needs to be updated +// test_throughput(); +// return 1; + +// Utilization Test: Maxes out memory + int utilResult = test_utilization(); + return 1; + + +} + + /* *=========================================================================== * END OF FILE diff --git a/manual_code/lab1/template/src/kernel/k_mem.c b/manual_code/lab1/template/src/kernel/k_mem.c index 1357dc7..23e96f8 100644 --- a/manual_code/lab1/template/src/kernel/k_mem.c +++ b/manual_code/lab1/template/src/kernel/k_mem.c @@ -33,6 +33,19 @@ #include "printf.h" #endif /* DEBUG_0 */ + +/* + *========================================================================== + * STRUCTS + *========================================================================== + */ + +typedef struct Node { + unsigned int size; + int isFree; + struct Node *next; +} Node; + /* *========================================================================== * GLOBAL VARIABLES @@ -43,6 +56,7 @@ const U32 g_k_stack_size = KERN_STACK_SIZE; // task kernel stacks U32 g_k_stacks[MAX_TASKS][KERN_STACK_SIZE >> 2] __attribute__((aligned(8))); +Node* HEAD = NULL; /* *=========================================================================== @@ -50,34 +64,191 @@ U32 g_k_stacks[MAX_TASKS][KERN_STACK_SIZE >> 2] __attribute__((aligned(8))); *=========================================================================== */ +void print_list() { + Node* curr = HEAD; + while (curr) { + printf("location: 0x%x, size: %x, free: %x\r\n", (U32)curr, (U32)curr->size, curr->isFree); + curr = curr->next; + } +} + int k_mem_init(void) { unsigned int end_addr = (unsigned int) &Image$$ZI_DATA$$ZI$$Limit; -#ifdef DEBUG_0 - printf("k_mem_init: image ends at 0x%x\r\n", end_addr); - printf("k_mem_init: RAM ends at 0x%x\r\n", RAM_END); -#endif /* DEBUG_0 */ +//#ifdef DEBUG_0 +// printf("k_mem_init: image ends at 0x%x\r\n", end_addr); +// printf("k_mem_init: RAM ends at 0x%x\r\n", RAM_END); +//#endif /* DEBUG_0 */ + + //check if end addr is valid + unsigned int totalSize = 0xBFFFFFFF - end_addr; + if(totalSize <= 0) { + return RTX_ERR; + } + + // round end_addr to nearest 4 + if (end_addr % 4 != 0) { + end_addr = ((unsigned int)(end_addr / 4)) * 4 + 4; + } + + // cast end_addr to pointer given in end_addr + HEAD = (Node*) end_addr; + + // setup head + HEAD->size = totalSize - sizeof(Node); + HEAD->isFree = 1; + HEAD->next = NULL; + return RTX_OK; } void* k_mem_alloc(size_t size) { -#ifdef DEBUG_0 - printf("k_mem_alloc: requested memory size = %d\r\n", size); -#endif /* DEBUG_0 */ - return NULL; +//#ifdef DEBUG_0 +// printf("k_mem_alloc: requested memory size = %d\r\n", size); +//#endif /* DEBUG_0 */ + + if (size == 0) { + return NULL; + } + + // 4 byte align + if (size % 4 != 0) { + size = ((unsigned int)(size / 4)) * 4 + 4; + } + + Node* curr = HEAD; + + while(curr != NULL) { + if (size <= curr->size && curr->isFree) { + break; + } + curr = curr->next; + } + + // couldn't allocate since no free space + if (curr == NULL) { + return NULL; + } + + if (size == curr->size){ + curr->isFree=0; + return (void*)((U32)curr + sizeof(Node)); + } else if (size < curr->size && (curr->size < (size + sizeof(Node)))) { + curr->isFree=0; + return (void*)((U32)curr + sizeof(Node)); + } else { + //make a new node + // might need to use an unsigned depending on how types work + Node* newNode = (Node*)((unsigned int)curr + sizeof(Node) + size); + newNode->isFree = 1; + newNode->size = curr->size - size - sizeof(Node); + newNode->next = curr->next; + + curr->isFree=0; + curr->size = size; + curr->next = newNode; + // Cast curr to U32 to ensure pointer arithmetic works + // Pointer addition works by adding by increment of sizeof the pointer + // argument. If curr is of type Node* and we add sizeof(Node), we add + // sizeof(Node)^2 amount of bytes. + return (void*)((U32)curr + sizeof(Node)); + } +} + +Node* mergeNode(Node* first, Node* second) { + if (first > second) { + return NULL; + } + + Node* result = first; + result->size = first->size + second->size + sizeof(Node); + result->next = second->next; + + return result; } int k_mem_dealloc(void *ptr) { -#ifdef DEBUG_0 - printf("k_mem_dealloc: freeing 0x%x\r\n", (U32) ptr); -#endif /* DEBUG_0 */ +//#ifdef DEBUG_0 +// printf("k_mem_dealloc: freeing 0x%x\r\n", (U32) ptr); +//#endif /* DEBUG_0 */ + + Node* curr = HEAD; + Node* prev = NULL; + + while (ptr != (char*)curr + sizeof(Node)) { + if (curr->next == NULL) { + return RTX_ERR; + } + + prev = curr; + curr = curr->next; +// printf("0x%x\n", (U32)((char*)curr + sizeof(Node) + curr->size)); + } + + // Double free + if (curr->isFree > 0) { + return RTX_ERR; + } + + curr->isFree = 1; + + // Merge neighboring nodes + if (prev && prev->isFree > 0) { + curr = mergeNode(prev, curr); + } + + if (curr->next && curr->next->isFree > 0) { + curr = mergeNode(curr, curr->next); + } + +// print_list(); + return RTX_OK; } int k_mem_count_extfrag(size_t size) { -#ifdef DEBUG_0 - printf("k_mem_extfrag: size = %d\r\n", size); -#endif /* DEBUG_0 */ - return RTX_OK; +//#ifdef DEBUG_0 +// printf("k_mem_extfrag: size = %d\r\n", size); +//#endif /* DEBUG_0 */ + // return RTX_OK; + + unsigned int memRegionSize; + int regionCount = 0; + + Node* curNode = HEAD; // HEAD is global var + + while(curNode != NULL){ + memRegionSize = curNode->size + sizeof(Node); + if(curNode->isFree){ + if(memRegionSize < size){ + regionCount++; + } + } + curNode = curNode->next; // idk if this is the right way to goto next node + } + + return regionCount; +} + +int countNodes(){ + Node* n = HEAD; + int ret = 0; + while(n != NULL) { + ret += 1; + n = n->next; + } + return ret; +} + +int memLeakCheck(){ + unsigned int howMuchMem = 0; + Node* curNode = HEAD; + while(curNode != NULL){ + howMuchMem += curNode->size + sizeof(Node); + curNode = curNode->next; + } + unsigned int end_addr = (unsigned int) &Image$$ZI_DATA$$ZI$$Limit; + unsigned int totalSize = 0xBFFFFFFF - end_addr; + return howMuchMem == totalSize; } /* diff --git a/manual_code/lab1/template/src/kernel/k_mem.h b/manual_code/lab1/template/src/kernel/k_mem.h index ff3c3ce..fc6f02a 100644 --- a/manual_code/lab1/template/src/kernel/k_mem.h +++ b/manual_code/lab1/template/src/kernel/k_mem.h @@ -36,6 +36,8 @@ int k_mem_init (void); void *k_mem_alloc (size_t size); int k_mem_dealloc (void *ptr); int k_mem_count_extfrag (size_t size); +int countNodes (void); +int memLeakCheck (void); #endif // ! K_MEM_H_ /* diff --git a/manual_code/lab2/TM/.cproject b/manual_code/lab2/TM/.cproject index d13abe4..43168ad 100644 --- a/manual_code/lab2/TM/.cproject +++ b/manual_code/lab2/TM/.cproject @@ -105,7 +105,7 @@