kernel/src/allocator/allocator.c
void * heap_alloc(heap_t * heap, uint32_t size) {
    // first get the bin index that this chunk size should be in
    int index = get_bin_index(size);
    // now use this bin to try and find a good fitting chunk!
    bin_t * temp = (bin_t *)heap->bins[index];

    node_t * found = get_best_fit(temp, size);

    // while no chunk if found advance through the bins until we
    // find a chunk or get to the wilderness
    while (found == NULL) {
        if (index + 1 >= BIN_COUNT) return NULL;

        temp = heap->bins[++index];
        found = get_best_fit(temp, size);
    }

    // if the difference between the found chunk and the requested chunk
    // is bigger than the overhead (metadata size) + the min alloc size
    // then we should split this chunk, otherwise just return the chunk
    if ((found->size - size) > (overhead + MIN_ALLOC_SZ)) {
        // do the math to get where to split at, then set its metadata
        node_t * split = (node_t *)(((char *)found + overhead) + size);
        split->size = found->size - size - (overhead);
        split->hole = 1;

        create_foot(split);  // create a footer for the split

        // now we need to get the new index for this split chunk
        // place it in the correct bin
        int new_idx = get_bin_index(split->size);
        add_node(heap->bins[new_idx], split);

        found->size = size;  // set the found chunks size
        create_foot(found);  // since size changed, remake foot
    }


    found->hole = 0;                        // not a hole anymore
    remove_node(heap->bins[index], found);  // remove it from its bin

    // these following lines are checks to determine if the heap should
    // be expanded or contracted
    // ==========================================
    node_t * wild = get_wilderness(heap);
    if (wild->size < MIN_WILDERNESS) {
        int success = expand(heap);
        if (success == 0) { return NULL; }
    } else if (wild->size > MAX_WILDERNESS) {
        contract(heap);
    }
    // ==========================================

    // since we don't need the prev and next fields when the chunk
    // is in use by the user, we can clear these and return the
    // address of the next field
    found->prev = NULL;
    found->next = NULL;


#ifdef MEM_DEBUG
    heap->bytes_allocated += found->size;
    TRACE("[MEM DEBUG] ALLOC %i bytes at 0x%x", found->size, &found->next);
#endif

    return &found->next;
}
// ========================================================
// this is the allocation function of the heap, it takes
// the heap struct pointer and the size of the chunk we
// want. this function will search through the bins until
// it finds a suitable chunk. it will then split the chunk
// if neccesary and return the start of the chunk
// ========================================================
this is the allocation function of the heap, it takes
the heap struct pointer and the size of the chunk we
want. this function will search through the bins until
it finds a suitable chunk. it will then split the chunk
if neccesary and return the start of the chunk
this is the allocation function of the heap it takes the heap struct pointer and the size of the chunk we want . this function will search through the bins until it finds a suitable chunk . it will then split the chunk if neccesary and return the start of the chunk
void * heap_alloc(heap_t * heap, uint32_t size) {
    int index = get_bin_index(size);
    bin_t * temp = (bin_t *)heap->bins[index];
    node_t * found = get_best_fit(temp, size);
    while (found == NULL) {
        if (index + 1 >= BIN_COUNT) return NULL;
        temp = heap->bins[++index];
        found = get_best_fit(temp, size);
    }
    if ((found->size - size) > (overhead + MIN_ALLOC_SZ)) {
        node_t * split = (node_t *)(((char *)found + overhead) + size);
        split->size = found->size - size - (overhead);
        split->hole = 1;
        create_foot(split);  
        int new_idx = get_bin_index(split->size);
        add_node(heap->bins[new_idx], split);
        found->size = size;  
        create_foot(found);  
    }
    found->hole = 0;                        
    remove_node(heap->bins[index], found);  
    node_t * wild = get_wilderness(heap);
    if (wild->size < MIN_WILDERNESS) {
        int success = expand(heap);
        if (success == 0) { return NULL; }
    } else if (wild->size > MAX_WILDERNESS) {
        contract(heap);
    }
    found->prev = NULL;
    found->next = NULL;
#ifdef MEM_DEBUG
    heap->bytes_allocated += found->size;
    TRACE("[MEM DEBUG] ALLOC %i bytes at 0x%x", found->size, &found->next);
#endif
    return &found->next;
}
void * heap_alloc ( heap_t * heap , uint32_t size ) { int index = get_bin_index ( size ) ; bin_t * temp = ( bin_t * ) heap -> bins [ index ] ; node_t * found = get_best_fit ( temp , size ) ; while ( found == NULL ) { if ( index + 1 >= BIN_COUNT ) return NULL ; temp = heap -> bins [ ++ index ] ; found = get_best_fit ( temp , size ) ; } if ( ( found -> size - size ) > ( overhead + MIN_ALLOC_SZ ) ) { node_t * split = ( node_t * ) ( ( ( char * ) found + overhead ) + size ) ; split -> size = found -> size - size - ( overhead ) ; split -> hole = 1 ; create_foot ( split ) ; int new_idx = get_bin_index ( split -> size ) ; add_node ( heap -> bins [ new_idx ] , split ) ; found -> size = size ; create_foot ( found ) ; } found -> hole = 0 ; remove_node ( heap -> bins [ index ] , found ) ; node_t * wild = get_wilderness ( heap ) ; if ( wild -> size < MIN_WILDERNESS ) { int success = expand ( heap ) ; if ( success == 0 ) { return NULL ; } } else if ( wild -> size > MAX_WILDERNESS ) { contract ( heap ) ; } found -> prev = NULL ; found -> next = NULL ; #ifdef MEM_DEBUG heap -> bytes_allocated += found -> size ; TRACE ( " " , found -> size , & found -> next ) ; #endif return & found -> next ; }
this is the allocation function of the heap, it takes
the heap struct pointer and the size of the chunk we
want.
this is the allocation function of the heap it takes the heap struct pointer and the size of the chunk we want .
// first get the bin index that this chunk size should be in // now use this bin to try and find a good fitting chunk! // while no chunk if found advance through the bins until we // find a chunk or get to the wilderness // if the difference between the found chunk and the requested chunk // is bigger than the overhead (metadata size) + the min alloc size // then we should split this chunk, otherwise just return the chunk // do the math to get where to split at, then set its metadata // create a footer for the split // now we need to get the new index for this split chunk // place it in the correct bin // set the found chunks size // since size changed, remake foot // not a hole anymore // remove it from its bin // these following lines are checks to determine if the heap should // be expanded or contracted // ========================================== // ========================================== // since we don't need the prev and next fields when the chunk // is in use by the user, we can clear these and return the // address of the next field