void print_sequential_allocated(void* node, void** next_hdr) {
  int flag = FALSE;
  void* page_ptr = BASEADDR(node);

  while (BASEADDR(node) == page_ptr) {
    void* checker = CONTROL_BLOCK_FIRST_NODE(root_page->ptr);
    while (checker != NULL) {
      if (checker == node) {
        flag = TRUE;
        break;
      }
      checker = NEXT(checker);
    }
    if (flag == TRUE) {
      break;
    }

    int page_id;
    if ((void*) BASEADDR(node) == root_page->ptr) {
      page_id = root_page->id;
    } else {
      page_id = (*((kma_page_t**) BASEADDR(node)))->id; 
    }

    printf("%2d ALLOCATED | hdr = %11p; size %4x; next_hdr = %11p\n",
           page_id,
           node,
           SIZE(node),
           node + ALLOC_HEADER_SIZE + SIZE(node));
    *next_hdr = node + ALLOC_HEADER_SIZE + SIZE(node);
    node += ALLOC_HEADER_SIZE + SIZE(node);
  }
}
Exemple #2
0
// need to insert into list on same page as buffer
void insertIntoFreeList(void* buffer, int bufferSize)
{
  int freeBufferIndex = getFreeBufferIndex(bufferSize);
  void** freeBufferList = getFreeBufferPointer(freeBufferIndex);
  bufferData_t* currentBuffer = (bufferData_t*)*freeBufferList;
  bufferData_t* pastBuffer = NULL;

  // handle case where list is empty
  if (currentBuffer == NULL)
  {
    *freeBufferList = buffer;
    currentBuffer = (bufferData_t*)*freeBufferList;
    assert(currentBuffer != NULL);
    currentBuffer->nextFreeBuffer = NULL;
    currentBuffer->bufferSize = bufferSize;
    return;
  }

  // now handle case where there are elements in free list
  size_t inputBufferPage = getPageNumber(BASEADDR(buffer));
  size_t currentPageNum = getPageNumber(BASEADDR(currentBuffer));
  assert(currentBuffer != NULL);
  while (currentBuffer->nextFreeBuffer != NULL && currentPageNum < inputBufferPage)
  {
    pastBuffer = currentBuffer;
    currentBuffer = currentBuffer->nextFreeBuffer;
    assert(currentBuffer != NULL);
    currentPageNum = getPageNumber(BASEADDR(currentBuffer));
  }
 
  if (currentBuffer->nextFreeBuffer == NULL)
  {
    // reached end of list, insert at end
    currentBuffer->nextFreeBuffer = buffer;
    currentBuffer = (bufferData_t*)buffer;
    currentBuffer->nextFreeBuffer = NULL;
    currentBuffer->bufferSize = bufferSize;
  }
  else
  {
    // in middle of list but past where we want to input buffer
    if (pastBuffer == NULL)
    {
      // we want to insert buffer at start of free list
      *freeBufferList = buffer;
      ((bufferData_t*)buffer)->nextFreeBuffer = (void*)currentBuffer;
      ((bufferData_t*)buffer)->bufferSize = bufferSize;
    }
    else
    {
      // we want to insert list between pastBuffer and currentBuffer
      assert(pastBuffer != NULL);
      pastBuffer->nextFreeBuffer = buffer;
      ((bufferData_t*)buffer)->nextFreeBuffer = (void*)currentBuffer;
      ((bufferData_t*)buffer)->bufferSize = bufferSize;
    }

  }
}
void dump() {
  if (root_page == NULL) {
    printf("       EMPTY |\n");
    return;
  }

  void* prev = NULL;
  void* node = CONTROL_BLOCK_FIRST_NODE(root_page->ptr);
  void* next_hdr = NULL;
  kma_page_t* page = NULL;
  kma_page_t* prev_page = NULL;

  while (node != NULL) {
    prev_page = page;

    int page_id;

    if ((void*) BASEADDR(node) == root_page->ptr) {
      page = root_page;
      page_id = root_page->id;
    } else {
      page = *((kma_page_t**) BASEADDR(node));
      page_id = (*((kma_page_t**) BASEADDR(node)))->id; 
    }

    if (prev == NULL) {
      if (node > root_page->ptr + CONTROL_BLOCK_SIZE) {
        print_sequential_allocated(root_page->ptr + CONTROL_BLOCK_SIZE, &next_hdr);
      }
    } else if (prev_page != page) {
      print_sequential_allocated(page->ptr + CONTROL_BLOCK_SIZE, &next_hdr);
    } else {
      kma_size_t diff = node - (prev + ALLOC_HEADER_SIZE + SIZE(prev));
      if (diff > 0) {
        print_sequential_allocated(prev + ALLOC_HEADER_SIZE + SIZE(prev), &next_hdr);
      }
    }

    // if (prev_page == page && next_hdr != NULL) {
    //   assert(next_hdr == node);
    // }

    printf("%2d     FREED | hdr = %11p; size %4x; next_hdr = %11p; PREV = %11p; NEXT = %11p\n",
           page_id,
           node,
           SIZE(node),
           node + ALLOC_HEADER_SIZE + SIZE(node),
           PREV(node),
           NEXT(node));

    next_hdr = node + ALLOC_HEADER_SIZE + SIZE(node);

    prev = node;
    node = NEXT(node);
  }
}
Exemple #4
0
// call after unset bitmap for this buffer
void coalesceFreeMemory(void** pointer, int* bufferSize)
{
  // calculate buddy location
  void* startOfPage = BASEADDR(*pointer);
  // check if buddy is free
  void* buddyPtr = getBuddyPointer(startOfPage, *pointer, *bufferSize);
  if (!checkIfBitmapSet(buddyPtr,*bufferSize))
  {
    // can coalesce!
    // need to remove it from freeList
    // handle inserting back in in kma_free
    removeFromFreeList(buddyPtr,*bufferSize);
    *bufferSize = *bufferSize*2;
    if (buddyPtr < *pointer)
    {
      *pointer = buddyPtr;
    }

    if (*bufferSize != PAGESIZE)
    {
      coalesceFreeMemory(pointer, bufferSize);
    }
  }
  // base case is either buddy isn't free of full page free
  
}
Exemple #5
0
void kma_free(void* ptr, kma_size_t size)
{
  size = roundUp(size);
  kma_page_t *page = *((kma_page_t **) BASEADDR(ptr));
  if (diff(size) == 8) { //if 8196, free the page
    free_page(page);
    PAGE_COUNT--;
  } else {
    page->size += size;
    if (page->size == PAGESIZE - sizeof(kma_page_t*)) {
      derefPage(page->ptr, size); //if page is made of free buffers, derefence the buffer in freelist
      free_page(page);
      PAGE_COUNT--;
    } else {  //not all free, give the buffer back to freelist
      insertAtHead(ptr, size);
    }
  }
  //free everything
  if(PAGE_COUNT == 1) {
    free_page(FREEPAGE);
    INIT = FALSE;
    PAGE_COUNT = 0;
    FREE_LIST_HEAD = NULL;
  }
}
Exemple #6
0
/* Computes the location of a blocks buddy. This function relies on if the block
   is an even or odd multiple of its size away from the beginning, which indicates
   if the buddy will be on the left or the right. */
allocheaderT* get_buddy(allocheaderT* alloc)
{
  int diff = (long int) alloc - (long int) BASEADDR(alloc);

  if ((diff / (alloc->size)) & 1) // odd
    return (allocheaderT*) ((long int) alloc - (long int) alloc->size);
  else
    return (allocheaderT*) ((long int) alloc + (long int) alloc->size);
}
Exemple #7
0
void* getBuffer(size_t size, void** entry) {
  void* cur = *entry;
  void* next = *(void **)cur;
  *(void **)cur = entry;
  *entry = next;
  kma_page_t * page = *((kma_page_t **) BASEADDR(cur));
  page->size -= size; 
  return cur + sizeof(void *);
}
Exemple #8
0
void derefPage(void* page, size_t size) {
  void** pre = FREE_LIST_HEAD + diff(size);
  void* cur = *pre;
  while (cur != NULL) {
    if (BASEADDR(cur) == page) {
      *pre = *(void **)cur; //remove from freelist
    } else {
      pre = cur; //move on
    }
    cur = *(void **)cur;
  }
}
Exemple #9
0
/**
 * Free memory
 **/
void
kma_free(void* ptr, kma_size_t size)
{
	addEntry(ptr, size);
	pageHeader* baseAdd = BASEADDR(ptr);
	baseAdd->blockCount--;
	pageHeader* firstPage = (pageHeader*)(mainPage->ptr);
	int totalPages = firstPage->pageCount;
	int count = 1;
	pageHeader* lastPage;
	for (; count; totalPages--)
	{
		lastPage = ((pageHeader*)((long int)firstPage + totalPages * PAGESIZE));
		count = 0;
		if (lastPage->blockCount == 0)
		{
			count = 1;
			block* tmp;
			for (tmp = firstPage->head; tmp != NULL; tmp = tmp->next)
			{
				if (BASEADDR(tmp) == lastPage)
				{
					deleteEntry(tmp);
				}
			}
			count = 1;
			if (lastPage == firstPage)
			{
				count = 0;
				mainPage = NULL;
			}
			free_page(lastPage->self);
			if (mainPage)
			{
				firstPage->pageCount--;
			}
		}
	}
}
Exemple #10
0
void alterBitMap(void* ptr, int sizeInBytes, bool setBits)
{
  BYTE byteValue;
  if (setBits)
  {
    byteValue = 255;
  }
  else
  {
    byteValue = 0;
  }

  // get base addr of page
  void* startOfPage = BASEADDR(ptr);
  size_t pageNumber = getPageNumber(startOfPage);
  assert(pageNumber >= 0);  

  int numBitsInBitmap = sizeInBytes/MIN_BUFFER_SIZE; 
  size_t bitmapIndex = getByteIndex(startOfPage, ptr);
  size_t bitmapOffset = getByteOffset(startOfPage, ptr);

  BYTE* bitmapLoc = &startOfManagedMemory->pages[pageNumber].bitmap[bitmapIndex];

  int i;
  if (bitmapOffset == 0)
  {
    // if offset is 0 then possible that we can set bytes at a time
    for (i=0; i < numBitsInBitmap/8; i++)
    {
      *bitmapLoc = byteValue;
      bitmapLoc = bitmapLoc + 1;
    }
  }
  // if there is a offset within a byte, then we know numBitsInBitmap < 8 because buffer has offset multiples of size 
  assert(bitmapOffset < 8);

  for (i=bitmapOffset; i < numBitsInBitmap % 8; i++)
  {
    if (setBits)
    {
      *bitmapLoc |= 1 << (7-i);
      printf("bitmap altered  %hhu\n", *bitmapLoc);
    }
    else
    {
      *bitmapLoc &= ~(1 << (7-i));
    }
  }
}
Exemple #11
0
void 
kma_free(void* ptr, kma_size_t size)
{
  void* internalPtr = (void*)(((BYTE*) ptr) - sizeof(bufferData_t));
  int bufferSize = getAmountOfMemoryToRequest(size);
  size_t pageNum = getPageNumber(BASEADDR(internalPtr));
  // unset bitmap
  unsetBitmap(internalPtr, bufferSize);
  // coalesce free buddies
  coalesceFreeMemory(&internalPtr, &bufferSize);
  if (bufferSize == PAGESIZE)
  {
    // can free page
    free_page(startOfManagedMemory->pages[pageNum].pageData);
    // right way would be to shift all pages after this over

    int pageIndex = pageNum + 1;
    while (startOfManagedMemory->pages[pageIndex].pageData != NULL)
    {
      memcpy((void*)&startOfManagedMemory->pages[pageIndex-1], (void*)&startOfManagedMemory->pages[pageIndex], sizeof(pageControlStruct_t*)); 
      pageIndex = pageIndex + 1;
    }

    // so that the last page in list isn't duplicated
    startOfManagedMemory->pages[pageIndex-1].pageData = NULL;

    int j;
    for (j=0; j < BITMAP_SIZE; j++)
    {
      startOfManagedMemory->pages[pageIndex-1].bitmap[j] = 0;
    }
  }

  if (onlyControlStructureLeft())
  {
    // everything gone except control structure
    // free page
    free_page(startOfManagedMemory->pages[0].pageData);
    startOfManagedMemory = NULL;
    return;
  }
  
  if (bufferSize != PAGESIZE)
  {
    // insert into free list
    insertIntoFreeList(internalPtr, bufferSize);
  }
}
void dump() {
  kma_size_t class_size = PAGESIZE;
  int i = 0;

  while (class_size > ALLOC_HEADER_SIZE) {
    printf("CLASS SIZE %#x\n", class_size);
    void* node = FIRST_FREE_NODE(i);
    while (node != NULL) {
      printf("%10s %p | BASEADDR(hdr) = %p; SIZE(hdr) = %#6x; NEXT(hdr) = %p;\n",
             IS_ALLOCATED(node) ? "ALLOCATED" : "FREE",
             node,
             BASEADDR(node),
             SIZE(node),
             NEXT(node));
      node = NEXT(node);
    }
    i++;
    class_size >>= 1;
  }
}
Exemple #13
0
bool checkIfBitmapSet(void* ptr, int sizeInBytes)
{
  void* startOfPage = BASEADDR(ptr);
  size_t pageNumber = getPageNumber(startOfPage);
  assert(pageNumber >= 0);  

  int numBitsInBitmap = sizeInBytes/MIN_BUFFER_SIZE; 
  size_t bitmapIndex = getByteIndex(startOfPage, ptr);
  size_t bitmapOffset = getByteOffset(startOfPage, ptr);

  BYTE* bitmapLoc = &startOfManagedMemory->pages[pageNumber].bitmap[bitmapIndex];

  int i;
  if (bitmapOffset == 0)
  {
    // if offset is 0 then possible that we can set bytes at a time
    for (i=0; i < numBitsInBitmap/8; i++)
    {
      if (*bitmapLoc != 0)
      {
        return TRUE;
      }
      bitmapLoc = bitmapLoc + 1;
    }
  }
  // if there is a offset within a byte, then we know numBitsInBitmap < 8 because buffer has offset multiples of size 
  assert(bitmapOffset < 8);

  for (i=bitmapOffset; i < numBitsInBitmap % 8; i++)
  {
      if ((*bitmapLoc & 1 << (7-i)) != 0)
      {
        return TRUE;
      }
  }


  // bitmap all 0s, can coalesce!
  return FALSE;
}
Exemple #14
0
/**
 * allocate memory
 **/
void*
kma_malloc(kma_size_t size)
{
	// if the requested size is greater than a page, ignore it
	if ((size + sizeof(void*)) > PAGESIZE)
	{
		return NULL;
	}
	// if there are no allocated page, then initate the page
	if (!mainPage)
	{
		mainPage = get_page();
		initPage(mainPage);
	}
	// find suitable space
	void* firstFit1 = firstFit(size);
	pageHeader* base = BASEADDR(firstFit1);
	// increase block count
	base->blockCount++;
	// return block address
	return firstFit1;
}
void coalesce(void* hdr) {
  int again = FALSE;
  kma_size_t size = SIZE(hdr);

  void* prev = PREV(hdr);
  void* next = NEXT(hdr);

  /* If the previous free block is adjacent and in the same page, coalesce */

  if (prev != NULL &&
      BASEADDR(prev) == BASEADDR(hdr) &&
      prev + ALLOC_HEADER_SIZE + SIZE(prev) == hdr) {
    size += SIZE(prev) + ALLOC_HEADER_SIZE;
    NEXT(prev) = next;
    if (next != NULL) {
      PREV(next) = prev;
    }
    SIZE(prev) = size;
    hdr = prev;
    again = TRUE;
  }

  /* If the next free block is adjacent and in the same page, coalesce */

  if (next != NULL &&
      BASEADDR(hdr) == BASEADDR(next) &&
      hdr + ALLOC_HEADER_SIZE + SIZE(hdr) == next) {
    size += SIZE(next) + ALLOC_HEADER_SIZE;
    NEXT(hdr) = NEXT(next);
    if (NEXT(next) != NULL) {
      PREV(NEXT(next)) = hdr;
    }
    SIZE(hdr) = size;
    again = TRUE;
  }

  /* If coalescing has ocurred, try to do it again */

  if (again == TRUE) {
    coalesce(hdr);
  } else {
    /* If not, attempt to free page */

    kma_size_t page_size;

    if (BASEADDR(hdr) == root_page->ptr) {
      page_size = root_page->size;
    } else {
      page_size = (*((kma_page_t**) BASEADDR(hdr)))->size;
    }

    /* If the block takes up the whole page, it is ready to be freed */

    if (SIZE(hdr) == page_size - CONTROL_BLOCK_SIZE - ALLOC_HEADER_SIZE) {
      /* Remove the block from the linked list */

      if (PREV(hdr) != NULL) {
        NEXT(PREV(hdr)) = NEXT(hdr);
      } else {
        CONTROL_BLOCK_FIRST_NODE(root_page->ptr) = NEXT(hdr);
      }
      if (NEXT(hdr) != NULL) {
        PREV(NEXT(hdr)) = PREV(hdr);
      }

      /* If the page is the root page, make the page of the next free
         block the new root page, otherwise simply free the page */

      if (BASEADDR(hdr) == root_page->ptr) {
        kma_page_t* root_page_temp = root_page;
        if (NEXT(hdr) != NULL) {
          root_page = *((kma_page_t**) BASEADDR(NEXT(hdr)));
          CONTROL_BLOCK_FIRST_NODE(root_page->ptr) = NEXT(hdr);
        } else {
          root_page = NULL;
        }
        free_page(root_page_temp);
      } else {
        free_page(*((kma_page_t**) BASEADDR(hdr)));
      }
    }
  }
}
Exemple #16
0
void kma_free(void* ptr, kma_size_t size)
{
  pageheaderT* page = (pageheaderT*) (BASEADDR(ptr)+sizeof(allocheaderT));
  freelistL* buffer = get_required_buffer(size, page);
  allocheaderT* alloc = buffer->first_block;

  // can't do any of this entire page is allocated to one chunk.
  if (round_up(size) != PAGESIZE)
  {
    // creating new free buffer
    allocheaderT* new_alloc = (allocheaderT*) (ptr);
    new_alloc->start = ALLOC_START(new_alloc);
    new_alloc->size = round_up(size);
    new_alloc->next = NULL;

    // insert buffer as first item if empty
    if (alloc == NULL)
      buffer->first_block = new_alloc;
    // insert buffer as first item when not empty
    else if ((long int) alloc > (long int) new_alloc)
    {
      new_alloc->next = alloc;
      buffer->first_block = new_alloc;
    }
    // find the appropriate location and insert the bufer
    else
    {
      while (alloc->next != NULL)
      {
        if ((long int) alloc->next > (long int) new_alloc)
        {
          new_alloc->next = alloc->next;
          alloc->next = new_alloc;
          break;
        }
        else
          alloc = alloc->next;
      } 
    coalesce(page);
    }
  }

  // if no more elements have been allocated to this page, free it.
  page->used -= 1;

  if (page->used == 0)
  {
    // case 1: freed first page, but there are still some pages existing.
    if (page->page == first_page && page->next != NULL)
    {
      kma_page_t* temp = page->next->page;
      free_page(first_page);
      first_page = temp;
    }
    // case 2: all pages are being freed.
    else if (page->page == first_page)
    {
      free_page(first_page);
      first_page = NULL;
    }
    // case 3: freeing any other page
    else
    {
      pageheaderT* temp = PAGE_HEADER(first_page);
      pageheaderT* prev = NULL;

      while (temp != page)
      {
        prev = temp;
        temp = temp->next;
      }
      prev->next = page->next;
      free_page(page->page);
    }
  }
}