diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index 8fb6975..c761e9b 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -6,79 +6,96 @@ void initMemoryAllocation(uint32_t kernelEnd) { firstBlock = (MemoryBlock *)kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; + firstBlock->next = NULL; + firstBlock->last = NULL; + firstBlock->task = NULL; firstBlock->size = -1; } -void *mallocTask(uint32_t size, Task *task) { +#define getOffset() \ + (alignment ? alignmentBit - ((uint32_t)(current + 1) & (alignmentMask)) : 0) + +void memmove(uint8_t *to, uint8_t *from, uint32_t count) { + if (from > to) { + for (; count > 0; count--) { + *(to++) = *(from++); + } + return; + } + for (to += count - 1, from += count - 1; count > 0; count--) { + *(to--) = *(from--); + } +} + +void *mallocTaskAligned(uint32_t size, uint8_t alignment, Task *task) { MemoryBlock *current = firstBlock; - while (!(current->next == 0x00 || - current->state == FREE && current->size >= size)) { + uint32_t alignmentBit = 1 << alignment; + uint32_t alignmentMask = alignmentBit - 1; + uint32_t additionalOffset = getOffset(); + while (current->task || current->size < size + additionalOffset) { current = current->next; + additionalOffset = getOffset(); } - MemoryBlock *next; - if (current->next == 0x00) { - next = ((void *)(¤t[1]) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && - current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock *)(((void *)(current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; + uint32_t neededSize = size + additionalOffset; + if (current->size > neededSize + sizeof(MemoryBlock) * 2) { + MemoryBlock *next = current->next; + current->size = neededSize; + current->next = ((void *)(current + 1)) + neededSize; + current->next->last = current; current->next->next = next; - next->last = current->next; - next = current->next; - } else { - current->next = next; + if (next) { + current->next->size = (void *)next - (void *)(current->next + 1); + } else { + current->next->size = -1; + } + current->next->task = NULL; + if (next) { + next->last = current->next; + } } - current->size = ((void *)next) - (void *)(current + 1); - current->state = IN_USE; + if (additionalOffset) { + memmove((uint8_t *)current + additionalOffset, (uint8_t *)current, + sizeof(MemoryBlock)); + current = (void *)current + additionalOffset; + current->size = (void *)current->next - (void *)(current + 1); + current->last->next = current; + current->last->size = (void *)current - (void *)(current->last + 1); + } current->task = task; return (void *)(current + 1); } +void *mallocTask(uint32_t size, Task *task) { + return mallocTaskAligned(size, 0, task); +} + void *malloc(uint32_t size) { - return mallocTask(size, (Task *)getCurrentTask()); + return mallocTaskAligned(size, 0, getCurrentTask()); } void *mallocAligned(uint32_t size, uint8_t alignment) { - uint64_t buffer = (uint64_t)malloc(size + (1 << alignment)); - buffer >>= alignment - 1; - buffer <<= alignment - 1; - buffer += 1 << alignment; - return (void *)buffer; + return mallocTaskAligned(size, alignment, getCurrentTask()); } void mergeNextIfPossible(MemoryBlock *current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size += sizeof(MemoryBlock) + current->next->size; + if (current->next && !current->next->task) { current->next = current->next->next; + current->size = (void *)current->next - (void *)(current + 1); current->next->last = current; } } void free(void *location) { MemoryBlock *current = ((MemoryBlock *)location) - 1; - current->state = FREE; + current->task = NULL; for (uint32_t i = 0; i < current->size; i++) { ((uint8_t *)¤t[1])[i] = 0; } mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { + if (current->last && !current->last->task) { current = current->last; + mergeNextIfPossible(current); } - mergeNextIfPossible(current); // call this function twice in case a used - // block between 2 free blocks is freed mergeNextIfPossible(current); } diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index 8fb6975..c761e9b 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -6,79 +6,96 @@ void initMemoryAllocation(uint32_t kernelEnd) { firstBlock = (MemoryBlock *)kernelEnd; - firstBlock->next = 0x00; - firstBlock->last = 0x00; - firstBlock->state = FREE; + firstBlock->next = NULL; + firstBlock->last = NULL; + firstBlock->task = NULL; firstBlock->size = -1; } -void *mallocTask(uint32_t size, Task *task) { +#define getOffset() \ + (alignment ? alignmentBit - ((uint32_t)(current + 1) & (alignmentMask)) : 0) + +void memmove(uint8_t *to, uint8_t *from, uint32_t count) { + if (from > to) { + for (; count > 0; count--) { + *(to++) = *(from++); + } + return; + } + for (to += count - 1, from += count - 1; count > 0; count--) { + *(to--) = *(from--); + } +} + +void *mallocTaskAligned(uint32_t size, uint8_t alignment, Task *task) { MemoryBlock *current = firstBlock; - while (!(current->next == 0x00 || - current->state == FREE && current->size >= size)) { + uint32_t alignmentBit = 1 << alignment; + uint32_t alignmentMask = alignmentBit - 1; + uint32_t additionalOffset = getOffset(); + while (current->task || current->size < size + additionalOffset) { current = current->next; + additionalOffset = getOffset(); } - MemoryBlock *next; - if (current->next == 0x00) { - next = ((void *)(¤t[1]) + size); - next->last = current; - next->state = FREE; - next->next = 0x00; - next->size = -1; - } else { - next = current->next; - } - if (current->size > size + sizeof(MemoryBlock) * 2 && - current->next != 0x00) { - // segment the current block if it is big enough - current->next = (MemoryBlock *)(((void *)(current + 1)) + size); - current->next->size = current->size - sizeof(MemoryBlock) - size; - current->size = size; - current->next->state = FREE; + uint32_t neededSize = size + additionalOffset; + if (current->size > neededSize + sizeof(MemoryBlock) * 2) { + MemoryBlock *next = current->next; + current->size = neededSize; + current->next = ((void *)(current + 1)) + neededSize; + current->next->last = current; current->next->next = next; - next->last = current->next; - next = current->next; - } else { - current->next = next; + if (next) { + current->next->size = (void *)next - (void *)(current->next + 1); + } else { + current->next->size = -1; + } + current->next->task = NULL; + if (next) { + next->last = current->next; + } } - current->size = ((void *)next) - (void *)(current + 1); - current->state = IN_USE; + if (additionalOffset) { + memmove((uint8_t *)current + additionalOffset, (uint8_t *)current, + sizeof(MemoryBlock)); + current = (void *)current + additionalOffset; + current->size = (void *)current->next - (void *)(current + 1); + current->last->next = current; + current->last->size = (void *)current - (void *)(current->last + 1); + } current->task = task; return (void *)(current + 1); } +void *mallocTask(uint32_t size, Task *task) { + return mallocTaskAligned(size, 0, task); +} + void *malloc(uint32_t size) { - return mallocTask(size, (Task *)getCurrentTask()); + return mallocTaskAligned(size, 0, getCurrentTask()); } void *mallocAligned(uint32_t size, uint8_t alignment) { - uint64_t buffer = (uint64_t)malloc(size + (1 << alignment)); - buffer >>= alignment - 1; - buffer <<= alignment - 1; - buffer += 1 << alignment; - return (void *)buffer; + return mallocTaskAligned(size, alignment, getCurrentTask()); } void mergeNextIfPossible(MemoryBlock *current) { - if (current->next != 0x00 && current->next->state == FREE) { - current->size += sizeof(MemoryBlock) + current->next->size; + if (current->next && !current->next->task) { current->next = current->next->next; + current->size = (void *)current->next - (void *)(current + 1); current->next->last = current; } } void free(void *location) { MemoryBlock *current = ((MemoryBlock *)location) - 1; - current->state = FREE; + current->task = NULL; for (uint32_t i = 0; i < current->size; i++) { ((uint8_t *)¤t[1])[i] = 0; } mergeNextIfPossible(current); - if (current->last != 0x00 && current->last->state == FREE) { + if (current->last && !current->last->task) { current = current->last; + mergeNextIfPossible(current); } - mergeNextIfPossible(current); // call this function twice in case a used - // block between 2 free blocks is freed mergeNextIfPossible(current); } diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index 30d4d9f..7ccbcb7 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -4,6 +4,7 @@ #include #define STACK_SIZE 0x100000 +#define INTERRUPT_TASK 0x1 Task *currentTask; ListElement *scheduledTasks = NULL; @@ -33,6 +34,7 @@ Task *last = currentTask; currentTask = popBeginning(&scheduledTasks); while (currentTask == 0) { + currentTask = INTERRUPT_TASK; asm("sti"); asm("hlt"); currentTask = popBeginning(&scheduledTasks);