/* Return a block of at least size bytes, or NULL if no such block can be found. */ void *malloc(size_t size) { void *heap_end, *heap_end_p; free_block_t *block; free_block_t **prev_p; /* Previous link so we can remove an element */ if (size == 0) { return NULL; } /* Add space for bookkeeping. */ size += sizeof(free_block_t); /* Word-align */ if (size % 4 != 0) { size &= ~3; size += 4; } /* Iterate through list of free blocks, using the first that is big enough for the request. */ for (block = free_list, prev_p = &free_list; block; prev_p = &(block->next), block = block->next) { if ( (int)( block->size - size ) >= (int)( MIN_ALLOC_SIZE+sizeof(free_block_t) ) ) { /* Block is too big, but can be split. */ free_block_t *new_block = (free_block_t*)(((byte*)block)+size); new_block->size = block->size - size; new_block->next = block->next; block->size = size - sizeof(free_block_t); *prev_p = new_block; return ((byte*)block)+sizeof(free_block_t); } else if (block->size >= size) { /* Block is big enough, but not so big that we can split it, so just return it */ *prev_p = block->next; return ((byte*)block)+sizeof(free_block_t); } /* Else, check the next block. */ } heap_end_p = syscall_memlimit(NULL); heap_end = syscall_memlimit((void*)((int)heap_end_p + size)); if(heap_end != NULL) { block = (free_block_t*)((int)prev_p - sizeof(size_t)); block->size += (int)heap_end - (int)heap_end_p; return malloc(size); } /* No heap space left. */ return NULL; }
/* Initialise the heap - malloc et al won't work unless this is called first. */ void heap_init() { void* heap_end; free_list = syscall_memlimit(NULL); /* Ew, casting-magic - increment with 1 instead of sizeof(free_block_t) */ free_list = (free_block_t*) ((uint32_t)free_list + 1); heap_end = syscall_memlimit(free_list); free_list->size = (int)heap_end - (int)free_list + 1 - sizeof(free_block_t); free_list->next = NULL; }
/* Return a block of at least size bytes, or NULL if no such block can be found. */ void *malloc(size_t size) { free_block_t *block; free_block_t **prev_p; /* Previous link so we can remove an element */ if (size == 0) { return NULL; } /* Ensure block is big enough for bookkeeping. */ size=MAX(MIN_ALLOC_SIZE,size); /* Iterate through list of free blocks, using the first that is big enough for the request. */ for (block = free_list, prev_p = &free_list; block; prev_p = &(block->next), block = block->next) { if ( (int)( block->size - size - sizeof(size_t) ) >= (int)( MIN_ALLOC_SIZE+sizeof(size_t) ) ) { /* Block is too big, but can be split. */ block->size -= size+sizeof(size_t); free_block_t *new_block = (free_block_t*)(((byte*)block)+block->size); new_block->size = size+sizeof(size_t); return ((byte*)new_block)+sizeof(size_t); } else if (block->size >= size + sizeof(size_t)) { /* Block is big enough, but not so big that we can split it, so just return it */ *prev_p = block->next; return ((byte*)block)+sizeof(size_t); } /* Else, check the next block. */ } /* No suitable free block was found, increase heap size. */ void *heap_end = syscall_memlimit(NULL); void *new_heap_end = syscall_memlimit(heap_end+size+sizeof(size_t)); if(new_heap_end - heap_end - size - sizeof(size_t) == 0) { block = (free_block_t *)heap_end; block->size = size + sizeof(size_t); return ((byte*)block)+sizeof(size_t); } else { /* Heap could not be increased sufficiently, set it back. */ syscall_memlimit(heap_end); } /* No heap space left. */ return NULL; }
/* Return a block of at least size bytes, or NULL if no such block can be found. */ void *malloc(unsigned int size) { free_block_t *block; free_block_t **prev_p; /* Previous link so we can remove an element */ void* heap_ptr; int free_size; if (size == 0) { return NULL; } heap_ptr = syscall_memlimit(NULL); printf("heap_ptr = %d \n",(int) heap_ptr); /* Ensure block is big enough for bookkeeping. */ size=MAX(MIN_ALLOC_SIZE,size); /* Word-align */ if (size % 4 != 0) { size &= ~3; size += 4; } /* Iterate through list of free blocks, using the first that is big enough for the request. */ for (block = free_list, prev_p = &free_list; block; prev_p = &(block->next), block = block->next) { if ( (int)( block->size - size - sizeof(size_t) ) >= (int)( MIN_ALLOC_SIZE+sizeof(size_t) ) ) { /* Block is too big, but can be split. */ block->size -= size+sizeof(size_t); free_block_t *new_block = (free_block_t*) (((byte*)block)+block->size); new_block->size = size+sizeof(size_t); return ((byte*)new_block)+sizeof(size_t); } else if (block->size >= size + sizeof(size_t)) { /* Block is big enough, but not so big that we can split it, so just return it */ *prev_p = block->next; return ((byte*)block)+sizeof(size_t); } /* Else, check the next block. */ } free_block_t* free_block = (free_block_t*) syscall_memlimit(heap_ptr + size + MIN_ALLOC_SIZE); if ((free_size = size % 4096) != 0) { free_block->size = free_size; free_block->next = free_list; free_list = free_block; } free_block_t* return_block = (free_block_t*) heap_ptr; return_block->size = size + MIN_ALLOC_SIZE; return heap_ptr + MIN_ALLOC_SIZE; }
int main() { char* a_string; /* Find the current (initial) heap end. */ a_string = syscall_memlimit(NULL); /* Extend the heap, and check that it worked. */ if (syscall_memlimit(a_string + STRING_LENGTH) == NULL) { /* It didn't work, so exit already. */ return 1; } /* Copy the source string to the dynamically allocated memory. */ for (size_t i = 0; i < STRING_LENGTH; i++) { a_string[i] = STRING_SOURCE[i]; } /* Write from the dynamically allocated memory. */ syscall_write(1, a_string, STRING_LENGTH); return 0; }
/* Return the block pointed to by ptr to the free pool. */ void free(void *ptr) { if (ptr != NULL) { /* Freeing NULL is a no-op */ free_block_t *block = (free_block_t*)((byte*)ptr-sizeof(free_block_t)); free_block_t *cur_block; free_block_t *prev_block; printf("free_list: %8.8x\nheap_end: %8.8x\nblock: %8.8x\n", (uint32_t)free_list, (uint32_t)syscall_memlimit(NULL), (uint32_t)block); /* Iterate through the free list, which is sorted by increasing address, and insert the newly freed block at the proper position. */ for (cur_block = free_list, prev_block = NULL; ; prev_block = cur_block, cur_block = cur_block->next) { if (cur_block > block || cur_block == NULL) { /* Insert block here. */ if (prev_block == NULL) { free_list = block; } else { prev_block->next = block; } printf("cur_block = %8.8x\n", (uint32_t)cur_block); block->next = cur_block; if (prev_block != NULL && (size_t)((byte*)block - (byte*)prev_block) == prev_block->size + sizeof(free_block_t)) { /* Merge with previous. */ prev_block->size += block->size + sizeof(free_block_t); prev_block->next = cur_block; block = prev_block; } if (cur_block != NULL && (size_t)((byte*)cur_block - (byte*)block) == block->size + sizeof(free_block_t)) { /* Merge with next. */ block->size += cur_block->size + sizeof(free_block_t); block->next = cur_block->next; } return; } } } }
/* Return a block of at least size bytes, or NULL if no such block can be found. */ void *malloc(size_t size) { free_block_t *block; free_block_t **prev_p; /* Previous link so we can remove an element */ void *old_end, *new_end; free_block_t *new_block, *tmp; if (size == 0) { return NULL; } if (mallptrs_size >= MAX_MALL_PTRS) { printf("Malloc: mallptrs array is filled up%s\n",""); return NULL; } /* Ensure block is big enough for bookkeeping. */ size=MAX(MIN_ALLOC_SIZE,size); /* Word-align */ if (size % 4 != 0) { size &= ~3; size += 4; } /* Iterate through list of free blocks, using the first that is big enough for the request. */ for (block = free_list, prev_p = &free_list; block; prev_p = &(block->next), block = block->next) { printf("Malloc: Free-list block: pointer %d, size %d, next %d\n" ,(uint32_t)block,block->size,(block->next != NULL)); if ( (int)( block->size - size - sizeof(size_t) ) >= (int)( MIN_ALLOC_SIZE+sizeof(size_t) ) ) { /* Block is too big, but can be split. */ block->size -= size+sizeof(size_t); free_block_t *new_block = (free_block_t*)(((byte*)block)+block->size); new_block->size = size+sizeof(size_t); /*return ((byte*)new_block)+sizeof(size_t);*/ return mallptrs_insert(((byte*)new_block)+sizeof(size_t)); } else if (block->size >= size + sizeof(size_t)) { /* Block is big enough, but not so big that we can split it, so just return it */ *prev_p = block->next; /*return ((byte*)block)+sizeof(size_t);*/ return mallptrs_insert(((byte*)block)+sizeof(size_t)); } /* Else, check the next block. */ } /* If no suitable free block was found, we must allocate a new one. */ /* If this is the first time, we get the addresse of our process's heap end, for bookkeeping. And initialize the mallptrs array. */ if (heap_start == NULL) { heap_start = syscall_memlimit(NULL); heap_end = heap_start; mallptrs_init(); printf("Malloc: Heap_start: %d\n", (uint32_t)heap_start); } printf("Malloc: Size: %d, heapend: %d\n", size, (uint32_t)heap_end); old_end = heap_end; heap_end = (void*)((uint32_t)heap_end + size+ sizeof(size_t)); /* Try and allocate more memory */ new_end = syscall_memlimit(heap_end); /* Check if it was possible to get more memory. */ if(new_end == NULL){ /* No heap space left. */ printf("Malloc: syscall_memlimit returned NULL%s\n",""); heap_end = (void*)((uint32_t)heap_end - size+ sizeof(size_t)); return NULL; } printf("Malloc: memlimit returned %d\n", (uint32_t)new_end); /* Make sure that the new end is not lower than what the user requested. */ if(new_end < heap_end) { printf("Malloc: new_end (%d) was lower than what was requested (%d)\n" ,(uint32_t)new_end,(uint32_t)heap_end); return NULL; } /* Make sure the new end is not lower than the old. It should not happen. */ if(old_end >= new_end) { printf("Malloc: new_end was lower or equal to the old_end%s\n",""); heap_end = (void*)((uint32_t)heap_end - size+ sizeof(size_t)); return NULL; } /* Create a new free block with the size we just allocated. */ new_block = (free_block_t*)((byte*)old_end); new_block->size = new_end - old_end; new_block->next = NULL; printf("Malloc: Created free block with size %d and address %d\n",new_block->size, (uint32_t)new_block); /* Attach it too the list of free blocks in a sorted manor. That is at the end. */ if (free_list == NULL) { printf("Malloc: free_list is null%s\n",""); free_list = new_block; } else { printf("Malloc: free_list is not null%s\n",""); tmp = free_list; while (tmp->next != NULL) { tmp = tmp->next; } tmp->next = new_block; printf("Malloc: out of loop%s\n",""); } /* Update the heap end to the new end address. */ heap_end = new_end; /* Recursively call malloc which should now find the free block we just created and fullfill the user request for more memory. */ return malloc(size); }
/* Return the block pointed to by ptr to the free pool. */ void free(void *ptr) { if (free != NULL) { /* Freeing NULL is a no-op */ free_block_t *block = (free_block_t*)((byte*)ptr-sizeof(size_t)); free_block_t *cur_block; free_block_t *prev_block; free_block_t *prev_prev_block; /* Iterate through the free list, which is sorted by increasing address, and insert the newly freed block at the proper position. */ for (cur_block = free_list, prev_block = prev_prev_block = NULL; ; prev_prev_block = prev_block, prev_block = cur_block, cur_block = cur_block->next) { if (cur_block > block || cur_block == NULL) { /* Insert block here. */ if (prev_block == NULL) { free_list = block; } else { prev_block->next = block; } block->next = cur_block; if (prev_block != NULL && (size_t)((byte*)block - (byte*)prev_block) == prev_block->size) { /* Merge with previous. */ prev_block->size += block->size; prev_block->next = cur_block; block = prev_block; } if (cur_block != NULL && (size_t)((byte*)cur_block - (byte*)block) == block->size) { /* Merge with next. */ block->size += cur_block->size; block->next = cur_block->next; } uint32_t heap = (uint32_t) syscall_memlimit(NULL); if((uint32_t)block + block->size == heap) { /* If block is the last on heap, remove block and decrease heap size. */ if(prev_block == block) { /* If merged with prev_block, we must update prev_prev_block. */ if(prev_prev_block == NULL) { free_list = block->next; } else { prev_prev_block->next = block->next; } } else { /* update prev_block. */ if(prev_block == NULL) { free_list = block->next; } else { prev_block->next = block->next; } } syscall_memlimit(block); } return; } } } }