Exemplo n.º 1
0
void free(void *address) {
    struct heapnode *node = (struct heapnode *) ((uint32_t) address - BUDDY_HEADER_SIZE);

    acquire(&user_buddy.semaphore);
    buddy_merge(node, &user_buddy);
    release(&user_buddy.semaphore);
}
Exemplo n.º 2
0
void kfree(void *address) {
    struct heapnode *node = (struct heapnode *) ((uint8_t *) address - MM_HEADER_SIZE);

    acquire(&kernel_buddy.mutex);
    buddy_merge(node, &kernel_buddy);
    release(&kernel_buddy.mutex);
}
Exemplo n.º 3
0
void buddy_merge(struct heapnode *node, struct buddy *buddy) {
    struct heapnode *buddy_node = (struct heapnode *) ((uint32_t) node ^ (1 << node->order));     /* Note: this is not necessarily free */
    struct heapnode *curr_node = buddy->list[node->order];
    struct heapnode *prev_node = NULL;

    if (node->order >= buddy->max_order) {
        return;
    }

    /* Look for node and buddy */
    uint8_t found = 0;
    struct heapnode *node_curr_node = NULL;
    struct heapnode *node_prev_node = NULL;
    struct heapnode *buddy_curr_node = NULL;
    struct heapnode *buddy_prev_node = NULL;
    while (found < 2 && curr_node != NULL) {
        if (curr_node == node) {
            node_curr_node = curr_node;
            node_prev_node = prev_node;
            found += 1;
        }
        else if (curr_node == buddy_node) {
            buddy_curr_node = curr_node;
            buddy_prev_node = prev_node;
            found += 1;
        }

        prev_node = curr_node;
        curr_node = curr_node->next;
    }


    /* Buddy not free */
    if (buddy_curr_node == NULL) {
        if (node_curr_node == NULL) {
            node->next = buddy->list[node->order];
            buddy->list[node->order] = node;
        }
        return;
    }
    else {  /* Buddy free */
        /* Remove from list */
        if (buddy_prev_node == NULL) {
            buddy->list[node->order] = buddy_curr_node->next;
        }
        else {
            buddy_prev_node->next = buddy_curr_node->next;
        }

        /* Remove node if found */
        if (node_curr_node != NULL) {
            /* Remove from list */
            if (node_prev_node == NULL) {
                buddy->list[node->order] = node_curr_node->next;
            }
            else {
                node_prev_node->next = node_curr_node->next;
            }
        }

        /* Set parent node as the less of the two buddies */
        node = node < buddy_curr_node ? node : buddy_curr_node;

        node->order += 1;
        node->next = buddy->list[node->order];
        buddy->list[node->order] = node;

        /* Recurse */
        buddy_merge(node, buddy);
    }
}
Exemplo n.º 4
0
void buddy_merge(struct heapnode *node, struct buddy *buddy) {
    if (node->header.magic != MM_MAGIC) {
        fprintf(stderr, "OOPS: mm: attempted to merge invalid node 0x%x\r\n", node);
        return;
    }

    uint8_t order = node->header.order;

    /* There is only one node of maximum size */
    if (order == buddy->max_order) {
        buddy->list[buddy->max_order] = node;
        node->next = NULL;
        return;
    }

    /* Our buddy node covers the other half of this order of memory,
     * thus it will have the order bit in the opposite state of ours.
     * Note: this is not necessarily free */
    struct heapnode *buddy_node = (struct heapnode *) ((uintptr_t) node ^ (1 << order));
    struct heapnode *curr_node = buddy->list[order];
    struct heapnode *prev_node = NULL;

    /* Look for node and buddy */
    uint8_t found = 0;
    struct heapnode *node_curr_node = NULL;
    struct heapnode *node_prev_node = NULL;
    struct heapnode *buddy_curr_node = NULL;
    struct heapnode *buddy_prev_node = NULL;
    while (found < 2 && curr_node != NULL) {
        if (curr_node == node) {
            node_curr_node = curr_node;
            node_prev_node = prev_node;
            found += 1;
        }
        else if (curr_node == buddy_node) {
            buddy_curr_node = curr_node;
            buddy_prev_node = prev_node;
            found += 1;
        }

        prev_node = curr_node;
        curr_node = curr_node->next;
    }


    /* Buddy not free */
    if (buddy_curr_node == NULL) {
        /* If node already in list, leave it,
         * otherwise add it */
        if (node_curr_node == NULL) {
            node->next = buddy->list[order];
            buddy->list[order] = node;
        }
        return;
    }
    else {  /* Buddy free */
        if (buddy_node->header.order != order) {
            panic_print("mm: node->header.order != buddy_node->header.order, "
                        "node: 0x%x node->header.order: %d buddy_node: 0x%x, "
                        "buddy_node->header.order: %d", node, node->header.order,
                        buddy_node, buddy_node->header.order);
        }

        /* Remove buddy from list */
        if (buddy_prev_node == NULL) {
            buddy->list[order] = buddy_curr_node->next;
        }
        else {
            buddy_prev_node->next = buddy_curr_node->next;
        }

        /* Remove node if found */
        if (node_curr_node != NULL) {
            /* Remove node from list */
            if (node_prev_node == NULL) {
                buddy->list[order] = node_curr_node->next;
            }
            else {
                node_prev_node->next = node_curr_node->next;
            }
        }

        /* Set parent node as the less of the two buddies */
        node = node < buddy_curr_node ? node : buddy_curr_node;

        /* Merge the nodes simply by increasing the order
         * of the smaller node. */
        uint8_t new_order = order + 1;
        node->header.order = new_order;

        /* Put on higher order list */
        node->next = buddy->list[new_order];
        buddy->list[new_order] = node;

        /* Recurse */
        buddy_merge(node, buddy);
    }
}
Exemplo n.º 5
0
void* buddy_alloc(size_t size) {
    
    void* allocated_block = NULL;                  // The object to return
    void* allocated_block_from_merge = NULL;
    item* allocated_block_item = NULL;
    void* available_block = NULL; 
    item* available_block_item = NULL;
    int next_power_of_2 = 0;
    int calculated_level = 0;
    int j = 0;
    void *list = NULL;
    item *new_head;

    printf("Allocation request for %d\n", (int)size);

    //Calculate the power of 2 big enough to hold 'size'
    next_power_of_2 = get_next_power_of_2(size);
    calculated_level = get_level(next_power_of_2);

    d_printf("next_power_of_2 %d\n", next_power_of_2);
    d_printf("calculated_level %d\n", calculated_level);

    assert(calculated_level < freelist_object->max_level);

    // Check the free-list if there are any free blocks for that level in the freelist array
    // If not, find a block in the upper level.
    // Split the block
    // Assign the block to the return object.

    for (j = calculated_level; j <= freelist_object->max_level; j++) {

        list = freelist_object->freelist[j];
        if (list == NULL)
            continue;

        available_block_item = (item *)list;

        /* Detach it from it's current position in the free list array */
        new_head = available_block_item->next;

        if(new_head == NULL)
            freelist_object->freelist[j] = NULL;
        else
            freelist_object->freelist[j] = (void*)new_head;

        if(available_block_item == NULL) {

            printf("Memory full. Try evicting");
            return NULL;
        }

        d_printf("Big enough block %p found at level %d\n", available_block_item, j);

        /* Trim if a higher order block than necessary was allocated */
        allocated_block_item = available_block_item;

        while (j > calculated_level) {

            /* Perform the splitting iteratively */
            // , (int)(((item *)allocated_block)->size)
            // d_printf("Size : %ld\n", allocated_block_item->size);
            d_printf("Splitting %p at level %d ", available_block_item, j);
            --j;
            
            available_block_item = available_block_item + (1UL << j);
            available_block_item->size = (1UL << j);
            allocated_block_item->size = (1UL << j);
            d_printf("into %p and %p\n", allocated_block_item, available_block_item);

            /* Check if there is already free block of that level */
            /* If no, make this the first one */
            if(freelist_object->freelist[j] == NULL)
                freelist_object->freelist[j] = (void*)allocated_block_item;

            /* Else get the first one, link it to this block and make the block the first in that level */
            else {
                available_block_item->next = (item*)freelist_object->freelist[j];
                freelist_object->freelist[j] = (void*)allocated_block_item;
            }
            allocated_block_item = available_block_item;
        }

        d_printf("Block %p alloted out of the level %d\n", allocated_block_item, j);

        // Return the object if it does not cause internal fragmentatation
        if((1UL << calculated_level) - size == 0)
        {
            d_printf("No internal fragmentatation involved with this request size\n");
            allocated_block_item->in_use = true;
            allocated_block = (void*)allocated_block_item;
            return allocated_block;
        }

        //else invoke the buddy_exact_alloc method
        allocated_block = (void*)allocated_block_item;
        return buddy_exact_alloc(&allocated_block, size);
    }

    printf("No blocks found in higher levels of the free list. Exploring the lower levels and checking if something can be merged\n");
    available_block = (void*)available_block_item;
    allocated_block_from_merge = buddy_merge(size);
    if(allocated_block_from_merge == NULL) {
        printf("Memory full. Try evicting");
        return NULL;
    }
    d_printf("Block %p alloted out of the level %d\n", (item *)allocated_block_from_merge, get_level(((item *)allocated_block_from_merge)->size));
    return allocated_block_from_merge;
}