Exemple #1
0
/* 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;
}
Exemple #2
0
/* 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;
}
Exemple #3
0
/* 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;
}
Exemple #4
0
/* 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;
}
Exemple #5
0
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;
}
Exemple #6
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;
      }
    }
  }
}
Exemple #7
0
/* 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);
}
Exemple #8
0
/* 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;
            }
        }
    }
}