$ cd cso-labs/ # your team's git repo if you work in a team or your own git repo if you work individually $ git fetch upstream $ git merge upstream/masterThis creates a number of new files in subdirectory malloclab/. Note that:
int mm_init(void); void* mm_malloc(size_t size); void mm_free(void *ptr); void* mm_realloc(void *ptr, size_t size); void mm_checkheap(int verbose);The existing code in mm.c implements the simplest but still functionally correct malloc package that we could think of. Using this as a starting place, modify these functions (and possibly define others), so that they obey the following semantics:
mm_init: Before calling mm_malloc mm_realloc or mm_free, the application program (i.e., the trace-driven driver program that you will use to evaluate your implementation) calls mm_init to perform any necessary initializations, such as allocating the initial heap area. The return value should be -1 if there was a problem in performing the initialization, 0 otherwise.
mm_malloc: The mm_malloc routine returns a pointer to an allocated block payload of at least size bytes. The entire allocated block should lie within the heap region and should not overlap with any other allocated chunk.
We will comparing your implementation to the version of malloc supplied in the standard C library. Since the standard C library malloc always returns payload pointers that are aligned to 16 bytes, your malloc implementation should do likewise and always return 16-byte aligned pointers.
mm_free: The mm_free routine frees the block pointed to by ptr. It returns nothing. This routine is only guaranteed to work when the passed pointer ptr was returned by an earlier call to mm_malloc or mm_realloc and has not yet been freed.
mm_realloc: The mm_realloc routine returns a pointer to an allocated region of at least size bytes with the following constraints.
Lastly, mm_checkheap: The mm_cheapheap routine is an auxilary routine that checks the consistency of your heap. The function argument int verbose can be used to turn on/off verbose debug printing.
The malloc,free, realloc semantics match the the semantics of the C standard library's malloc, realloc, and free routines. Type man malloc for the complete documentation.
When implementing mm_init, mm_free, mm_mallocmm_realloc functions, you need to invoke the following functions which simulate the the memory system for your dynamic memory allocator. They are defined in memlib.c:
void *mem_sbrk(int incr): Expands the heap by incr bytes, where incr is a positive non-zero integer and returns a generic pointer to the first byte of the newly allocated heap area. The semantics are identical to the Unix sbrk function, except that mem_sbrk accepts only a positive non-zero integer argument.
void *mem_heap_lo(void): Returns a generic pointer to the first byte in the heap.
void *mem_heap_hi(void): Returns a generic pointer to the last byte in the heap.
size_t mem_heapsize(void): Returns the current size of the heap in bytes.
size_t mem_pagesize(void): Returns the system's page size in bytes
The tester mdriver reads a set of trace files, each of which contains a sequence of allocate, reallocate, and free events corresponding to some example application workload. It then calls your mm_malloc, mm_realloc, and mm_free routines according to the sequence of events.
To run the tester, type:
$ ./mdriver -V
The -V turns on verbose printing in the tester.
To run the tester on one specific tracefile instead of all of the default tracefiles, type:
$./mdriver -V -f tracefileThis is helpful when debugging failure with a particular tracefile. Type $./mdriver -h to see a full list of command line options.
Use simple workloads first to debug correctness: We provide two very simple trace files short{1,2}.rep to simplify debugging. Type mdriver -f short1.rep to test your memory allocator on one of these workloads first.
Use gdb. It will help you isolate and identify out of bounds memory references.
Understand every line of the malloc implementation in the textbook. The textbook has a detailed example of a simple allocator based on an implicit free list. Use this is a point of departure. Don't start working on your allocator until you understand everything about the simple implicit list allocator.
Encapsulate your pointer arithmetic in C preprocessor macros. Pointer arithmetic in memory managers is confusing and error-prone because of all the casting that is necessary. You can reduce the complexity significantly by writing macros for your pointer operations. See the textbook for examples.
Do your implementation in stages. The first 9 traces contain requests to malloc and free. The last 2 traces contain requests for realloc, malloc, and free. We recommend that you start by getting your malloc and free routines working correctly and efficiently on the first 9 traces. Only then should you turn your attention to the realloc implementation. For starters, build realloc on top of your existing malloc and free implementations. But to get really good performance, you will need to build a stand-alone realloc.
Use a profiler. You may find the gprof tool helpful for optimizing performance.
Correctness (15 points). You will receive full points if your solution passes the correctness tests performed by the tester program. You will receive partial credit for each correct trace.
Performance (40 points). Two performance metrics will be used to evaluate your solution:
Space utilization: The peak ratio between the aggregate amount of memory used by the tester (i.e., allocated via mm_malloc or mm_realloc but not yet freed via mm_free) and the size of the heap used by your allocator. The optimal ratio equals to 1. You should find good policies to minimize fragmentation in order to make this ratio as close as possible to the optimal.
Throughput: The average number of operations completed per second.
The tester program summarizes the performance of your allocator by computing a performance index, which is a weighted sum of the space utilization (U) and throughput (T)
Performance index = 0.6*U + 0.4*min(1, T/T_libc)where U is your space utilization, T is your throughput, and T_libc is the measured throughput of Standard C library's malloc on your system on the default traces.
Observing that both memory and CPU cycles are expensive system resources, we adopt this formula to encourage balanced optimization of both memory utilization and throughput. Ideally, the performance index will reach 100%. To receive a good score, you must achieve a balance between utilization and throughput.
Style (10 points).
You will be awarded 5 points for a good heap consistency checker and 5 points for good program structure and comments.