//Coalesce free blocks if possible static void *coalesce(void *bp) { size_t prev_alloc = block_free(block_prev(get_header(bp))); size_t next_alloc = block_free(block_next(get_header(bp))); size_t size = block_size(get_header(bp)); if(prev_alloc && next_alloc) return bp; else if(prev_alloc && !next_alloc) { size += block_size(block_next(get_header(bp))); PUT(get_header(bp), PACK(size, 0)); PUT(get_footer(bp), PACK(size, 0)); } else if(!prev_alloc && next_alloc) { size += block_size(block_prev(get_header(bp))); PUT(get_header(prev_bp(bp)), PACK(size, 0)); PUT(get_footer(bp), PACK(size, 0)); bp = prev_bp(bp); } else if(!prev_alloc && !next_alloc) { size += block_size(block_next(get_header(bp))) + block_size(block_prev(get_header(bp))); PUT(get_header(prev_bp(bp)), PACK(size, 0)); PUT(get_footer(next_bp(bp)), PACK(size, 0)); bp = prev_bp(bp); } checkheap(1); return bp; }
void expand_right(block_header_t* block) { /* Get next block */ block_footer_t* ftr = get_footer(block); block_header_t* next_hdr = (block_header_t*)((uintptr_t)ftr + sizeof(block_footer_t)); if((uintptr_t)next_hdr >= (uintptr_t)(HEAP_END)) return; if(next_hdr->magic != HEAP_HEADER_MAGIC) panic("Kernel heap corrupted", 0); /* If block is free, expand it */ if(next_hdr->flags == 0) { block_footer_t* next_ftr = get_footer(next_hdr); next_ftr->header = block; block->size += next_hdr->size; block_footer_t* oui = get_footer(block); /* Routine checks. */ if(oui->magic != HEAP_FOOTER_MAGIC) panic("Kernel heap corrupted during expand", 0); if(oui->header->magic != HEAP_HEADER_MAGIC) panic("Kernel heap corrupted during expand (2)", 0); } }
uintptr_t* kalloc(uint32_t asize) { uint32_t size; if(!kernel_heap) return 0; // Align allocation size on uint32_t uint8_t mod = asize % 4; if(mod > 0) size = asize + 4 - (uint32_t)mod; else size = asize; uint32_t required_size = size + 2*(sizeof(block_footer_t) + sizeof(block_header_t)); block_header_t* blk = kernel_heap->heap_begin; // Iterate in our heap, and stops when we found a block, or there is no remaining blocks while((blk->size < required_size ||blk->flags == 1) && next_block(blk)) blk = next_block(blk); // We found a block ! if(blk->size >= required_size && blk->flags == 0 && blk->magic == HEAP_HEADER_MAGIC) { if(blk->size == required_size) { blk->flags = 1; return block_data_space(blk); } else { // Update block data block_footer_t* footer = get_footer(blk); uint32_t old_size = blk->size; blk->size = size + sizeof(block_header_t) + sizeof(block_footer_t); blk->flags = 1; // Create footer for block block_footer_t* new_footer = (block_footer_t*)((uintptr_t)blk + blk->size - sizeof(block_footer_t)); new_footer->header = blk; new_footer->magic = HEAP_FOOTER_MAGIC; // Create new block next to it block_header_t* new_block = (block_header_t*)((uintptr_t)new_footer + sizeof(block_footer_t)); new_block->magic = HEAP_HEADER_MAGIC; new_block->flags = 0; new_block->size = old_size - blk->size; // Update footer data to link to the newly created block footer->header = new_block; block_footer_t* check = get_footer(new_block); block_footer_t* check2 = get_footer(blk); return block_data_space(blk); } } else { panic("Kernel heap out of memory\n", 0); return 0; } }
//Placing the allocated block in the free block static void place(void *bp, size_t size) { size_t bsize = block_size(get_header(bp)); if((bsize-size) >= (2*DSIZE)) { PUT(get_header(bp), PACK(size, 1)); PUT(get_footer(bp), PACK(size, 1)); bp = next_bp(bp); PUT(get_header(bp), PACK(bsize-size, 0)); PUT(get_footer(bp), PACK(bsize-size, 0)); } else { PUT(get_header(bp), PACK(bsize, 1)); PUT(get_footer(bp), PACK(bsize, 1)); } }
//Extend the heap static void *extend_heap(size_t words) { //Even number of words to maintain alignment size_t size = (words % 2) ? ((words + 1) * WSIZE) : (words * WSIZE); uint32_t *bp = mem_sbrk(size); if((long)bp == -1) return NULL; PUT(get_header(bp), PACK(size, 0)); PUT(get_footer(bp), PACK(size, 0)); PUT(block_next(get_header(bp)), PACK(0,1)); return coalesce(bp); }
/// <summary> /// Does what you'd expect the malloc C standard library to do, check /// the requirements document for more details. /// <summary> /// <param name='size'> How many bytes the user needs to allocate </param> /// <return> /// A properely aligned pointer to a block of memory whose size at /// is at least equal to the size requested by the caller. /// </return> void *my_malloc(size_t size) { uint8_t *user_data; /* The pointer we will return to the user */ uint8_t *new_block; /* Used to point to the block added by grow_heap */ uint8_t *sliced_block; /* Used to point to the left-over of a block */ struct block_header *header, *footer, *slice_header; int slice_list;/* Which list the slice belongs to */ if(size <= 0) return NULL; size += sizeof(struct block_header) * 2; /* The header+footer */ size = (size+7) & ~7;/* Align the size to 8-byte boundary */ /* Identify which list to pick from */ int list_num = pick_list(size); DEBUG_PRINT("size requested: %zd\n", size); DEBUG_PRINT("List picked: %d\n", list_num); user_data = extract_free_block(list_num, size); /* If no list had enough space */ if(user_data == NULL) { if((new_block = grow_heap(size)) == NULL) { DEBUG_PRINT("%s\n", "-------------------------------------"); errno = ENOMEM; return NULL; } add_free_block_to_list(list_num, new_block); user_data = extract_free_block(list_num, size); } assert(user_data != NULL); DEBUG_PRINT("%s\n", "Found a block!"); /* If we can slice, add the left-over back to our lists */ sliced_block = slice_block(user_data, size); if(sliced_block != NULL) { slice_header = (struct block_header *) sliced_block; slice_list = pick_list(slice_header->block_size); add_free_block_to_list(slice_list, sliced_block); } /* Mark the block as allocated */ header = (struct block_header *) user_data; SET_ALLOC(header); footer = get_footer(user_data); SET_ALLOC(footer); user_data = user_data + 8;/* Now points past the header */ DEBUG_PRINT("%s\n", "-------------------------------------"); return user_data; }
bool CMessage::validate() { if (m_header->canary != HEADER_CANARY) { log_error("Header Canary : expected 0x%08X, found 0x%08X", HEADER_CANARY, m_header->canary); return false; } message_footer* footer = get_footer(); if (footer->canary != FOOTER_CANARY) { log_error("Footer Canary : expected 0x%08X, found 0x%08X", FOOTER_CANARY, footer->canary); return false; } if (m_header->size != footer->size) { log_error("Size : header 0x%08X, footer 0x%08X", m_header->size, footer->size); return false; } if (m_header->session != footer->session) { log_error("Session : header 0x%08X, footer 0x%08X", m_header->session, footer->session); return false; } return true; }
void expand_left(block_header_t* block) { /* Get previous block */ block_footer_t* prev_ftr = (block_footer_t*)((uintptr_t)block - sizeof(block_footer_t)); if((uintptr_t)prev_ftr <= (uintptr_t)(HEAP_BEGIN + sizeof(heap_t))) return; block_header_t* prev_hdr = prev_ftr->header; if(prev_hdr->magic != HEAP_HEADER_MAGIC) panic("Kernel heap corrupted", 0); /* If block is free, expand it */ if(prev_hdr->flags == 0) { block_footer_t* ftr = get_footer(block); ftr->header = prev_hdr; prev_hdr->size += block->size; } }
static int process_data(server *srv, connection *con, plugin_data *p, buffer *filename, chunkqueue *cq, off_t range_start) { int err; size_t len; //off_t *abs_off; vhd_state_t *state; vhd_context_t *vhd; err = 0; state = &p->state; vhd = &state->vhd; //abs_off = range_start + con->range_offset; //abs_off = state->abs_off; DEBUGLOG("so", "Absolute Offset", state->abs_off); DEBUGLOG("sd", "Current Virtual Block = ", state->curr_virt_blk); if (state->curr_virt_blk != -1) { DEBUGLOG("s", "Process Block"); err = process_block(srv, cq, state, &(state->abs_off)); goto done; } if (state->abs_off < 0 + sizeof(vhd_footer_t)) { err = get_footer(srv, cq, state, &(state->abs_off)); goto done; } if (((off_t)state->abs_off) < vhd->footer.data_offset + sizeof(vhd_header_t)) { err = get_header(srv, cq, state, &(state->abs_off)); goto done; } if (((off_t)state->abs_off) < vhd->header.table_offset + state->bat_buf_size) { err = get_bat(srv, cq, state, &(state->abs_off)); if (err) goto done; if (state->vhd_ready) err = prepare_for_write(srv, state, filename, state->abs_off); goto done; } if (state->blocks_written < state->blocks_allocated) { LOG("sdd", "BUG!", state->blocks_written, state->blocks_allocated); err = -EINVAL; goto done; } // TODO: we could actually validate the primary footer at the end len = chunkqueue_avail(cq); DEBUGLOG("sd", "Discarding the remainder", len); discard_bytes(srv, cq, len); state->abs_off += len; if (state->zero_unalloc) { err = zero_unallocated(srv, state); state->zero_unalloc = 0; } done: con->range_offset = state->abs_off - range_start; return err; }