diff --git a/kernel/include/kmalloc.h b/kernel/include/kmalloc.h index 8573c7c..d959f59 100644 --- a/kernel/include/kmalloc.h +++ b/kernel/include/kmalloc.h @@ -15,6 +15,32 @@ void* kzalloc(size_t size); // zeroed-out memory. Returns a pointer to allocated memory or NULL. void* kcalloc(size_t count, size_t size); +// 9 bytes in 8 bytes +#define TAG_SHIFT 56 +#define TAG_MASK ((uintptr_t)0xFF << TAG_SHIFT) +#define SIGN_BIT ((uintptr_t)1 << 55) + +typedef struct { + uintptr_t bits; +} tagged_ptr; + +static inline tagged_ptr tp_make(void* p, uint8_t tag) { + uintptr_t addr = (uintptr_t)p & ~TAG_MASK; + return (tagged_ptr){addr | ((uintptr_t)tag << TAG_SHIFT)}; +} + +static inline uint8_t tp_tag(tagged_ptr t) { + return (uint8_t)(t.bits >> TAG_SHIFT); +} + +static inline void* tp_ptr(tagged_ptr t) { + /* Bits 48..55 were untouched and still equal the canonical sign. + Copy bit 55 into bits 56..63. */ + uintptr_t addr = + (t.bits & SIGN_BIT) ? (t.bits | TAG_MASK) : (t.bits & ~TAG_MASK); + return (void*)addr; +} + // powers of 2 #define KMALLOC_MAX_SIZE 17 #define LOWEST_POWER 3 @@ -28,6 +54,12 @@ struct partialy_freelist { struct partialy_freelist* partialy_freelist_nextnode; }; +// this is used when object is too small to hold the big one in this case we use +// first object as pointer storage and dont allocate it +struct partialy_freelist_short { + struct partialy_freelist_short* partialy_freelist_nextnode; +}; + union freelists_list { struct freelist* freelists[KMALLOC_MAX_SIZE]; struct { diff --git a/kernel/src/kmalloc.c b/kernel/src/kmalloc.c index b59b730..7d7e7f8 100644 --- a/kernel/src/kmalloc.c +++ b/kernel/src/kmalloc.c @@ -58,6 +58,7 @@ void* kmalloc(size_t size) { size_t alloc_index; { + // TODO remove buildin uint8_t leading_zeros = __builtin_clzll(size); if (popcountll(size) == 1) { alloc_index = leading_zeros; @@ -73,6 +74,8 @@ void* kmalloc(size_t size) { } alloc_index -= LOWEST_POWER; } + size_t object_size = (1 << (alloc_index + LOWEST_POWER)); + struct freelist* selected_freelist = freelists_all_cpus[core_id].freelists[alloc_index]; if (selected_freelist != NULL) { @@ -100,14 +103,16 @@ void* kmalloc(size_t size) { // only one free object available if (selected_partialy_freelist ->partialy_freelist_nextnode != NULL) { - // next partialy free list available + // next partialy free list + // available partial_free_lists[core_id] .partialy_freelists[alloc_index] = selected_partialy_freelist ->partialy_freelist_nextnode; } else { - // no other partialy free list available + // no other partialy free list + // available partial_free_lists[core_id] .partialy_freelists[alloc_index] = NULL; @@ -129,35 +134,44 @@ void* kmalloc(size_t size) { } else { // slowest path - size_t object_size = (1 << (alloc_index+LOWEST_POWER)); - uint8_t page_count = object_size < PAGE_SIZE ? 1 : (object_size*2)/PAGE_SIZE; + uint8_t page_count = + object_size < PAGE_SIZE + ? 1 + : (object_size * 2) / PAGE_SIZE; void** alloc_addr = 0; { int ret; - ret = vmm_alloc((void**)&alloc_addr, page_count, 0); + ret = vmm_alloc((void**)&alloc_addr, page_count, + 0); if (ret != SUCCESS) { return NULL; } } // construct the linked list - // start at offset if object too small for partial free list pointer - for (size_t i = object_size < sizeof(struct partialy_freelist) ? object_size : 0; i=page_count*PAGE_SIZE) { - alloc_addr[i*object_size] = NULL; + // start at offset if object too small for partial free + // list pointer + for (size_t i = + object_size < sizeof(struct partialy_freelist) + ? object_size + : 0; + i < page_count * PAGE_SIZE; i += object_size) { + if ((i + 1) * object_size >= + page_count * PAGE_SIZE) { + alloc_addr[i * object_size] = NULL; } else { - alloc_addr[i*object_size] = alloc_addr + ((i+1)*object_size); + alloc_addr[i * object_size] = + alloc_addr + + ((i + 1) * object_size); } } - if (object_size < sizeof(struct partialy_freelist)) { - freelists_all_cpus[core_id].freelists[alloc_index] = (struct freelist*)(alloc_addr+(object_size*2)); - return alloc_addr+object_size; - } else { - freelists_all_cpus[core_id].freelists[alloc_index] = (struct freelist*)(alloc_addr+object_size); - return alloc_addr; - } + + freelists_all_cpus[core_id].freelists[alloc_index] = + (struct freelist*)(alloc_addr + object_size); + return alloc_addr; } } -} \ No newline at end of file +} +void* kfree(void* p) {} \ No newline at end of file