CS520
Fall 2005
Programming Assignment 3
Due Sunday October 23


The goal of the remaining programming assignments is to build a memory allocator that has an associated conservative garbage collector. The memory allocator will be designed and implemented for the Intel IA-32 architecture.

For Program 3 you should construct a test application that will be used to comprehensively test your allocator and collector.

The interface to the allocator is the following two functions:

memInitialize should be called exactly once at program startup and will initialize the allocator to hold the number of 32-bit words given by its single argument. The argument must be greater than zero, and may need to be above some threshold to allow the system to store its control information. (Note: This implies that some of the words will be consumed by the control information and therefore will not be available to the user.)

If memInitialize fails, it returns 0; else it returns 1. (Note: Since memInitialize can only be called once, there is no way to recover from the function failing; all subsequent calls will fail because an earlier call was made.)

memAllocate allocates a contiguous block of 32-bit words of the length given by its first argument. The argument must be non-negative. (Note: It could be zero.) If the allocation fails, it returns 0; else it returns the address of the base of the allocated block. The allocation may consume more words than the user requests, in order to store control information.

The second argument of memAllocate is either NULL or a pointer to a function that should be called when the block is eventually freed, if it is. (If NULL is passed as the second argument, then nothing special needs to be done if/when the block is freed.) The argument to be passed to the "finalize" function is the base address of the block being freed. A "finalize" function should not call memAllocate. If this happens, memAllocate should print an appropriate error message to stderr and then abort by calling exit(-1).

If a call to memAllocate is made and there is not enough unallocated memory left to fulfill the current request, then a conservative garbage collector will be invoked to try to identify allocated blocks that are no longer in use. The collector will mark all allocated blocks that appear to be in use and then will free the unmarked blocks. The marking phase will start by examining the global data memory and the stack frames for active function invocations. Any allocated block that is pointed to by one of those areas will then be examined to see if it points to any allocated blocks. And then any block that is pointed to from a marked block will then be examined. This process recurses until all blocks that are reachable are marked.

The garbage collector will assume that global memory is bounded by the address of the symbol "__data_start" and the value returned by a call to sbrk(0). memInitialize should make the call to sbrk before calling malloc to allocate space for the memory to be allocated.

The stack area to be examined is delimited by the top of stack at the time that memAllocate is called and by the frame for the topmost frame (the earliest frame created) on the stack. Assume that the topmost frame will have 0 in the "saved EBP" slot.

After the marking phase is done, adjacent blocks that are freed should be coalesced into one block. After freeing and coalescing all garbage blocks, if there is still not a free block big enough to satisfy the current request, then the call to memAllocate fails and it should return 0.

The garbage collector is conservative in that it will assume anything that appears to point to an allocated block actually does point to the block. That is, an integer might coincidentally contain a bit pattern that could be interpreted as a pointer to a block. The collector will go ahead and mark the block. So, the collector is conservative in the sense that any block that is actually pointed to will be marked, but some additional blocks that may not actually be pointed to will also be marked.

The collector will consider memory to be an array of 32-bit words. When scanning global memory or the stack, the collector will begin on a clean 4-byte boundary and will proceed one 32-bit word at a time.

A block should be considered to be pointed to if the base of the block is pointed to, if an internal word of the block is pointed to, or if the word immediately off either end of the block is pointed to.

For Program 3, all that you need to do is to implement a application that will be used to comprehensively test your allocator and garbage collector. This means that you need to think hard about how to test the allocator and garbage collector. (Yes, I am asking to think about testing before you write the code!) What tests need to be done to convince someone that your allocator works?

Here are some issues to consider:

This list is most likely not comprehensive, so be sure to do your own thinking and add to this list if necessary.

All your tests should be placed in the context of a single program. You can do a rudimentary test of your test program by executing it with memInitialize implemented as an empty function, and memAllocate allocated by an appropriate call to malloc. In this framework, obviously, there is no garbage collector so blocks will never be freed and the allocator will not fail (run out space) unless malloc fails.

Your test program will be graded by evaluating how comprehensive it is. To be sure I can understand how and what you are testing, your test application must be very fully documented! If I can't easily understand what you are doing, then you will not get credit for it. I suggest you start your code with a lengthy comment that describes the overall plan for your tests.

In addition, remember, you may lose points if your program is not properly structured. Readability is very important for this assignment.

Your code will be graded using an CIS Linux machine (e.g. turing.unh.edu) so be sure to test in that environment. I will use gcc to compile your code.

You should submit the source code for your test application in three files called testApp.c, testAppAsm.s and memAlloc.c:

Your program should be submitted for grading from a UNH CIS Linux machine (e.g. turing.unh.edu). To turn in this assignment, type:
~cs520/bin/submit prog3 testApp.c testAppAsm.s memAlloc.c

Please submit only the above three source files. Do not turn in any other files!

Submissions can be checked by typing:
~cs520/bin/scheck prog3

To receive full credit for the assignment, you must turn in your files prior to 8am on Monday October 24. Programming assignments may be handed in late at a penalty of 2 points for one day late, 5 points for two days late, 10 points for three days late, 20 points for four days late, and 40 points for five days late. No program may be turned in more than 5 days late.

Remember: as always you are expected to do your own work on this assignment.


Last modified on October 21, 2005.

Comments and questions should be directed to hatcher@unh.edu