Project 3: A Custom malloc()

Due: Sunday, July 12, 2015, at 11:59pm

Description

In our discussions of dynamic memory management we discussed the operation of the standard C library call, malloc(). Some implementations of malloc designate a region of a process’s address space from the symbol _end (where the code and global data ends) to brk as the heap. We will be taking a slightly different approach and asking the OS for a large region of memory to act as our heap.

As part of dynamic memory management, we also discussed various algorithms for the management of the empty spaces that may be created after a malloc()-managed heap has had some of it’s allocations freed. In this assignment, you are asked to create your own version of malloc based upon the buddy allocator scheme.

Details

The buddy allocation algorithm requires a large free space that we can repeatedly divided to find a reasonably-sized chunk to return. We will request this initial free space directly from the OS by requesting the OS allocate us many contiguous pages using the mmap() system call.

We will create an initial space of 1GiB by doing the following:

void * base = mmap(NULL, MAX_MEM, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);

We can easily set MAX_MEM to 2^30 by using a left shift trick:

1 30

The pointer base will now point to a region of 1GiB contiguously allocated in size that we can use for our buddy allocator.

We should treat the beginning of each region as a linked list node that contains whether this chunk is allocated or free, and in the case of a free block, have pointers to the next and previous node in the free space list so we may easily remove it during coalescing. Since two pointers and a free indicator would be 16 to 24 bytes on our architecture, we should not allocate less than this amount. Our minimum size chunk for any allocation will be 32 bytes.

When a block becomes used, we may allow the caller of malloc to overwrite the pointers, but we must always keep our indication of the memory being in use so we can check it when our buddy is freed and coalescing may occur. So of these 32 bytes, we can support at most a 31-byte malloc request assuming a 1-byte integer (char) is being used to track the allocation status.

If we need to allocate exactly 32 bytes, we must instead allocate a 64-byte region since we must always have 1 byte left over.

We must also build a table of 30-5=25 pointers to be the heads of the linked lists of our chunks of each power-of-two size we now support.

We have discussed in class how to discover a buddy for a given chunk using the XOR operation (^ in C). It is important to note that this only works when the base of the chunk is at address 0, which is never going to be the case for us as mmap will return an address from the memory-mapped area at high addresses in our address space. That means to use the XOR trick, we will always need to subtract base from the address to get the “offset” into our 1GiB region.

Requirements

You are to create two functions for this project.

  1. A malloc() replacement called void *my_buddy_malloc(int size) that allocates memory using the buddy allocation scheme.
  2. A free() called void my_free(void *ptr) that deallocates a pointer that was originally allocated by the malloc you wrote above.

Your free function should coalesce buddy free blocks as we described in class.

As you are developing, you will want to create a driver program that tests your calls to your mallocs and frees. A week before the due date, I will provide a sample driver program that must work. During grading, we will use a second driver program in addition to the first one in order to test that your code works.

Environment

For this project we will again be working on thoth.cs.pitt.edu

Hints/Notes


What to turn in

To create a tar.gz file, if your code is in a folder named project3, execute the following commands:

tar cvf USERNAME-project3.tar project3

gzip USERNAME-project3.tar

Where USERNAME is your username.

Then copy your file to:

~jrmst106/submit/449/