aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/include/libk/kmalloc.h28
-rw-r--r--kernel/kernel/kernel.c13
-rw-r--r--kernel/libk/kmalloc.c572
3 files changed, 48 insertions, 565 deletions
diff --git a/kernel/include/libk/kmalloc.h b/kernel/include/libk/kmalloc.h
index f760ee1..85e247a 100644
--- a/kernel/include/libk/kmalloc.h
+++ b/kernel/include/libk/kmalloc.h
@@ -19,29 +19,17 @@
#ifndef __libk_kmalloc_h
#define __libk_kmalloc_h
-#include <stddef.h>
+#include <stdint.h>
-void *kmalloc(size_t);
-void *krealloc(void *, size_t);
-void *kcalloc(size_t, size_t);
-void kfree(void *);
+#define MIN_PAGES 4
-/** This is a boundary tag which is prepended to the
- * page or section of a page which we have allocated. It is
- * used to identify valid memory blocks that the
- * application is trying to free.
- */
-struct boundary_tag {
- unsigned int magic; //< It's a kind of ...
- unsigned int size; //< Requested size.
- unsigned int real_size; //< Actual size.
- int index; //< Location in the page table.
+typedef struct memory_chunk_t {
+ struct memory_chunk_t *next;
+ struct memory_chunk_t *prev;
- struct boundary_tag *split_left; //< Linked-list info for broken pages.
- struct boundary_tag *split_right; //< The same.
+ uint32_t size;
+} memory_chunk_t;
- struct boundary_tag *next; //< Linked list info.
- struct boundary_tag *prev; //< Linked list info.
-};
+void *kmalloc(uint32_t size);
#endif
diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c
index 4579a5d..9b5696b 100644
--- a/kernel/kernel/kernel.c
+++ b/kernel/kernel/kernel.c
@@ -44,12 +44,13 @@ kernel_main(uint32_t magic, multiboot_info_t *multiboot_info)
physical_mm_init();
virtual_mm_initialize();
- int *a;
- for (int i = 0; i < 3; i++) {
- a = kmalloc(1);
- printk("debug", "%d: Kmalloc allocated: 0x%x", i, a);
- *a = 79;
- }
+ /* int *x = physical_mm_allocate_block(); */
+ /* *x = 20; */
+ /* printk("debug", "x(%lu)", *x); */
+
+ /* virtual_mm_alloc_pages(1); */
+ /* void *x = kmalloc(12); */
+ /* printk("debug", "x(0x%x)", x); */
printk("\nKernel", "Started.");
diff --git a/kernel/libk/kmalloc.c b/kernel/libk/kmalloc.c
index 69e77ba..23b6c2e 100644
--- a/kernel/libk/kmalloc.c
+++ b/kernel/libk/kmalloc.c
@@ -17,564 +17,58 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <kernel/spinlock.h>
#include <libk/kmalloc.h>
#include <libk/stdio.h>
#include <mm/virtual_mm.h>
-#include <stdatomic.h>
+#include <stddef.h>
#include <stdint.h>
-static atomic_flag s_liballoc_lock;
+memory_chunk_t *starting_mc = NULL;
-#define liballoc_alloc virtual_mm_alloc_pages
-#define liballoc_free virtual_mm_free_pages
-
-#define printf printk_raw
-
-int
-liballoc_lock(void)
-{
- spinlock_acquire(&s_liballoc_lock);
- return 0;
-}
-
-int
-liballoc_unlock(void)
-{
- spinlock_release(&s_liballoc_lock);
- return 0;
-}
-
-/** Durand's Ridiculously Amazing Super Duper Memory functions. */
-
-#define DEBUG
-
-#define LIBALLOC_MAGIC 0xc001c0de
-#define MAXCOMPLETE 5
-#define MAXEXP 32
-#define MINEXP 8
-
-#define MODE_BEST 0
-#define MODE_INSTANT 1
-
-#define MODE MODE_BEST
-
-struct boundary_tag *l_freePages[MAXEXP]; //< Allowing for 2^MAXEXP blocks
-int l_completePages[MAXEXP]; //< Allowing for 2^MAXEXP blocks
-
-#ifdef DEBUG
-unsigned int l_allocated = 0; //< The real amount of memory allocated.
-unsigned int l_inuse = 0; //< The amount of memory in use (kmalloc'ed).
-#endif
-
-static int l_initialized = 0; //< Flag to indicate initialization.
-static int l_pageSize = 4096; //< Individual page size
-static unsigned int l_pageCount = 16; //< Minimum number of pages to allocate.
-
-// *********** HELPER FUNCTIONS *******************************
-
-/** Returns the exponent required to manage 'size' amount of memory.
- *
- * Returns n where 2^n <= size < 2^(n+1)
- */
-static inline unsigned int
-getexp(unsigned int size)
-{
- if (size < (1 << MINEXP)) {
-#ifdef DEBUG
- printf("getexp returns -1 for %i less than MINEXP\n", size);
-#endif
- return -1; // Smaller than the quantum.
- }
-
- int shift = MINEXP;
-
- while (shift < MAXEXP) {
- if (((unsigned int) 1 << shift) > size)
- break;
- shift += 1;
- }
-
-#ifdef DEBUG
- printf("getexp returns %i (%i bytes) for %i size\n",
- shift - 1,
- (1 << (shift - 1)),
- size);
-#endif
-
- return shift - 1;
-}
-
-static void *
-liballoc_memset(void *s, int c, size_t n)
-{
- size_t i;
- for (i = 0; i < n; i++)
- ((char *) s)[i] = c;
-
- return s;
-}
-
-static void *
-liballoc_memcpy(void *s1, const void *s2, size_t n)
+static memory_chunk_t *
+add_block(void *address, uint32_t size)
{
- char *cdest;
- char *csrc;
- unsigned int *ldest = (unsigned int *) s1;
- unsigned int *lsrc = (unsigned int *) s2;
-
- while (n >= sizeof(unsigned int)) {
- *ldest++ = *lsrc++;
- n -= sizeof(unsigned int);
- }
-
- cdest = (char *) ldest;
- csrc = (char *) lsrc;
+ memory_chunk_t *mc = address;
+ mc->next = NULL;
+ mc->prev = NULL;
- while (n > 0) {
- *cdest++ = *csrc++;
- n -= 1;
- }
+ uint32_t chunk_size = size - sizeof(memory_chunk_t);
+ printk("kmalloc", "size(0x%x) chunk_size(0x%x)");
- return s1;
+ mc->size = chunk_size;
+ printk("kmalloc",
+ "mc(0x%x) mc->size(0x%x) chunk_size(0x%x)",
+ mc,
+ mc->size,
+ chunk_size);
+ return mc;
}
-#ifdef DEBUG
static void
-dump_array(void)
-{
- int i = 0;
- struct boundary_tag *tag = NULL;
-
- printf("------ Free pages array ---------\n");
- printf("System memory allocated: %i\n", l_allocated);
- printf("Memory in used (kmalloc'ed): %i\n", l_inuse);
-
- for (i = 0; i < MAXEXP; i++) {
- printf("%.2i(%i): ", i, l_completePages[i]);
-
- tag = l_freePages[i];
- while (tag != NULL) {
- if (tag->split_left != NULL)
- printf("*");
- printf("%i", tag->real_size);
- if (tag->split_right != NULL)
- printf("*");
-
- printf(" ");
- tag = tag->next;
- }
- printf("\n");
- }
-
- printf("'*' denotes a split to the left/right of a tag\n");
-}
-#endif
-
-static inline void
-insert_tag(struct boundary_tag *tag, int index)
-{
- int realIndex;
-
- if (index < 0) {
- realIndex = getexp(tag->real_size - sizeof(struct boundary_tag));
- if (realIndex < MINEXP)
- realIndex = MINEXP;
- } else
- realIndex = index;
-
- tag->index = realIndex;
-
- if (l_freePages[realIndex] != NULL) {
- l_freePages[realIndex]->prev = tag;
- tag->next = l_freePages[realIndex];
- }
-
- l_freePages[realIndex] = tag;
-}
-
-static inline void
-remove_tag(struct boundary_tag *tag)
-{
- if (l_freePages[tag->index] == tag)
- l_freePages[tag->index] = tag->next;
-
- if (tag->prev != NULL)
- tag->prev->next = tag->next;
- if (tag->next != NULL)
- tag->next->prev = tag->prev;
-
- tag->next = NULL;
- tag->prev = NULL;
- tag->index = -1;
-}
-
-static inline struct boundary_tag *
-melt_left(struct boundary_tag *tag)
-{
- struct boundary_tag *left = tag->split_left;
-
- left->real_size += tag->real_size;
- left->split_right = tag->split_right;
-
- if (tag->split_right != NULL)
- tag->split_right->split_left = left;
-
- return left;
-}
-
-static inline struct boundary_tag *
-absorb_right(struct boundary_tag *tag)
-{
- struct boundary_tag *right = tag->split_right;
-
- remove_tag(right); // Remove right from free pages.
-
- tag->real_size += right->real_size;
-
- tag->split_right = right->split_right;
- if (right->split_right != NULL)
- right->split_right->split_left = tag;
-
- return tag;
-}
-
-static inline struct boundary_tag *
-split_tag(struct boundary_tag *tag)
-{
- unsigned int remainder
- = tag->real_size - sizeof(struct boundary_tag) - tag->size;
-
- struct boundary_tag *new_tag
- = (struct boundary_tag *) ((unsigned int) tag
- + sizeof(struct boundary_tag) + tag->size);
-
- new_tag->magic = LIBALLOC_MAGIC;
- new_tag->real_size = remainder;
-
- new_tag->next = NULL;
- new_tag->prev = NULL;
-
- new_tag->split_left = tag;
- new_tag->split_right = tag->split_right;
-
- if (new_tag->split_right != NULL)
- new_tag->split_right->split_left = new_tag;
- tag->split_right = new_tag;
-
- tag->real_size -= new_tag->real_size;
-
- insert_tag(new_tag, -1);
-
- return new_tag;
-}
-
-// ***************************************************************
-
-static struct boundary_tag *
-allocate_new_tag(unsigned int size)
+kmalloc_init(void)
{
- unsigned int pages;
- unsigned int usage;
- struct boundary_tag *tag;
-
- // This is how much space is required.
- usage = size + sizeof(struct boundary_tag);
-
- // Perfect amount of space
- pages = usage / l_pageSize;
- if ((usage % l_pageSize) != 0)
- pages += 1;
-
- // Make sure it's >= the minimum size.
- if (pages < l_pageCount)
- pages = l_pageCount;
+ int *initial_region = virtual_mm_alloc_pages(MIN_PAGES);
+ printk("debug", "%x", initial_region);
+ /* *initial_region = 10; */
- tag = (struct boundary_tag *) liballoc_alloc(pages);
+ /* memory_chunk_t *mc = (memory_chunk_t *) initial_region; */
+ /* mc->size = 10; */
+ /* printk("kmalloc", "mc->size(0x%x)", mc->size); */
- if (tag == NULL)
- return NULL; // uh oh, we ran out of memory.
-
- tag->magic = LIBALLOC_MAGIC;
- tag->size = size;
- tag->real_size = pages * l_pageSize;
- tag->index = -1;
-
- tag->next = NULL;
- tag->prev = NULL;
- tag->split_left = NULL;
- tag->split_right = NULL;
-
-#ifdef DEBUG
- printf("Resource allocated %x of %i pages (%i bytes) for %i size.\n",
- tag,
- pages,
- pages * l_pageSize,
- size);
-
- l_allocated += pages * l_pageSize;
-
- printf("Total memory usage = %i KB\n", (int) ((l_allocated / (1024))));
-#endif
-
- return tag;
+ /* starting_mc = add_block(initial_region, 4 * PAGE_SIZE); */
}
void *
-kmalloc(size_t size)
+kmalloc(uint32_t size)
{
- int index;
- void *ptr;
- struct boundary_tag *tag = NULL;
-
- liballoc_lock();
-
- if (l_initialized == 0) {
-#ifdef DEBUG
- printf("%s\n", "liballoc initializing.");
-#endif
- for (index = 0; index < MAXEXP; index++) {
- l_freePages[index] = NULL;
- l_completePages[index] = 0;
- }
- l_initialized = 1;
- }
-
- index = getexp(size) + MODE;
- if (index < MINEXP)
- index = MINEXP;
-
- // Find one big enough.
- tag = l_freePages[index]; // Start at the front of the list.
- while (tag != NULL) {
- // If there's enough space in this tag.
- if ((tag->real_size - sizeof(struct boundary_tag))
- >= (size + sizeof(struct boundary_tag))) {
-#ifdef DEBUG
- printf("Tag search found %i >= %i\n",
- (tag->real_size - sizeof(struct boundary_tag)),
- (size + sizeof(struct boundary_tag)));
-#endif
- break;
- }
-
- tag = tag->next;
- }
-
- // No page found. Make one.
- if (tag == NULL) {
- if ((tag = allocate_new_tag(size)) == NULL) {
- liballoc_unlock();
- return NULL;
- }
-
- index = getexp(tag->real_size - sizeof(struct boundary_tag));
- } else {
- remove_tag(tag);
-
- if ((tag->split_left == NULL) && (tag->split_right == NULL))
- l_completePages[index] -= 1;
- }
-
- // We have a free page. Remove it from the free pages list.
-
- tag->size = size;
-
- // Removed... see if we can re-use the excess space.
-
-#ifdef DEBUG
- printf("Found tag with %i bytes available (requested %i bytes, leaving %i), "
- "which has exponent: %i (%i bytes)\n",
- tag->real_size - sizeof(struct boundary_tag),
- size,
- tag->real_size - size - sizeof(struct boundary_tag),
- index,
- 1 << index);
-#endif
-
- unsigned int remainder
- = tag->real_size - size
- - sizeof(struct boundary_tag) * 2; // Support a new tag + remainder
-
- if (((int) (remainder)
- > 0) /*&& ( (tag->real_size - remainder) >= (1<<MINEXP))*/) {
- int childIndex = getexp(remainder);
-
- if (childIndex >= 0) {
-#ifdef DEBUG
- printf("Seems to be splittable: %i >= 2^%i .. %i\n",
- remainder,
- childIndex,
- (1 << childIndex));
-#endif
-
- struct boundary_tag *new_tag = split_tag(tag);
- (void) new_tag;
-
-#ifdef DEBUG
- printf("Old tag has become %i bytes, new tag is now %i bytes (%i exp)\n",
- tag->real_size,
- new_tag->real_size,
- new_tag->index);
-#endif
- }
- }
-
- ptr = (void *) ((unsigned int) tag + sizeof(struct boundary_tag));
-
-#ifdef DEBUG
- l_inuse += size;
- printf("kmalloc: %x, %i, %i\n",
- ptr,
- (int) l_inuse / 1024,
- (int) l_allocated / 1024);
- dump_array();
-#endif
-
- liballoc_unlock();
- return ptr;
-}
-
-void
-kfree(void *ptr)
-{
- int index;
- struct boundary_tag *tag;
-
- if (ptr == NULL)
- return;
-
- liballoc_lock();
-
- tag = (struct boundary_tag *) ((unsigned int) ptr
- - sizeof(struct boundary_tag));
-
- if (tag->magic != LIBALLOC_MAGIC) {
- liballoc_unlock(); // release the lock
- return;
- }
-
-#ifdef DEBUG
- l_inuse -= tag->size;
- printf("free: %x, %i, %i\n",
- ptr,
- (int) l_inuse / 1024,
- (int) l_allocated / 1024);
-#endif
-
- // MELT LEFT...
- while ((tag->split_left != NULL) && (tag->split_left->index >= 0)) {
-#ifdef DEBUG
- printf("Melting tag left into available memory. Left was %i, becomes %i "
- "(%i)\n",
- tag->split_left->real_size,
- tag->split_left->real_size + tag->real_size,
- tag->split_left->real_size);
-#endif
- tag = melt_left(tag);
- remove_tag(tag);
- }
-
- // MELT RIGHT...
- while ((tag->split_right != NULL) && (tag->split_right->index >= 0)) {
-#ifdef DEBUG
- printf("Melting tag right into available memory. This was was %i, becomes "
- "%i (%i)\n",
- tag->real_size,
- tag->split_right->real_size + tag->real_size,
- tag->split_right->real_size);
-#endif
- tag = absorb_right(tag);
- }
-
- // Where is it going back to?
- index = getexp(tag->real_size - sizeof(struct boundary_tag));
- if (index < MINEXP)
- index = MINEXP;
-
- // A whole, empty block?
- if ((tag->split_left == NULL) && (tag->split_right == NULL)) {
-
- if (l_completePages[index] == MAXCOMPLETE) {
- // Too many standing by to keep. Free this one.
- unsigned int pages = tag->real_size / l_pageSize;
-
- if ((tag->real_size % l_pageSize) != 0)
- pages += 1;
- if (pages < l_pageCount)
- pages = l_pageCount;
-
- liballoc_free(tag, pages);
-
-#ifdef DEBUG
- l_allocated -= pages * l_pageSize;
- printf("Resource freeing %x of %i pages\n", tag, pages);
- dump_array();
-#endif
-
- liballoc_unlock();
- return;
- }
-
- l_completePages[index] += 1; // Increase the count of complete pages.
- }
-
- // ..........
-
- insert_tag(tag, index);
-#ifdef DEBUG
- printf("Returning tag with %i bytes (requested %i bytes), which has "
- "exponent: %i\n",
- tag->real_size,
- tag->size,
- index);
- dump_array();
-#endif
-
- liballoc_unlock();
-}
-
-void *
-kcalloc(size_t nobj, size_t size)
-{
- int real_size;
- void *p;
-
- real_size = nobj * size;
-
- p = kmalloc(real_size);
-
- liballoc_memset(p, 0, real_size);
-
- return p;
-}
-
-void *
-krealloc(void *p, size_t size)
-{
- void *ptr;
- struct boundary_tag *tag;
- size_t real_size;
-
- if (size == 0) {
- kfree(p);
- return NULL;
- }
- if (p == NULL)
- return kmalloc(size);
-
- liballoc_lock(); // lockit
- tag = (struct boundary_tag *) ((unsigned int) p
- - sizeof(struct boundary_tag));
- real_size = tag->size;
- liballoc_unlock();
-
- if (real_size > size)
- real_size = size;
+ if (!starting_mc)
+ kmalloc_init();
- ptr = kmalloc(size);
- liballoc_memcpy(ptr, p, real_size);
- kfree(p);
+ /* printk("kmalloc", */
+ /* "Initialized region with starting_mc(0x%x) and size(0x%x)", */
+ /* starting_mc, */
+ /* starting_mc->size); */
- return ptr;
+ (void) size;
+ return NULL;
}