This homework is due on Wednesday, October 28, at 11:59:59 PM (Eastern daylight time). You must use submit to turn in your homework like so: submit cs421_jtang hw4 hw4.c
Your program must be named hw4.c, and it will be compiled on Ubuntu 14.04 as follows:
gcc --std=c99 -Wall -O2 -pthread -o hw4 hw4.c hw4_test.cThere must not be any compilation warnings in your submission; warnings will result in grading penalties. In addition, your code must be properly indented and have a file header comment, as described on the coding conventions page.
In this homework, you are writing a memory allocator from scratch. You will implement the first-fit algorithm. As proof that your code works, your program will run instructor-provided unit tests that will exercise all functions.
Your program will simulate a machine's memory system. The machine has 8 page frames, where each frame holds 32 bytes, for 256 bytes total. Declare this "memory" as a global array. When your program starts, initialize its contents to 0.
Implement the following function with this given signature:
/** * Display information about memory allocations. * * Display to standard output the following: * - Memory contents, one frame per line, 8 lines total. Display the * actual bytes stored in memory. If the byte is unprintable (ASCII * value less than 32 or greater than 126, then display a dot * instead. * - Memory allocations, one line of 32 characters, where each * character corresponds to a frame. Indicate reserved frames with * R, free memory with f. * * This is a thread-safe function. */ void my_malloc_stats(void);
Next, implement a first-fit memory allocator. You must implement these functions with these given signatures:
/** * Allocate and return a contiguous memory block that is within the * memory mapped region. * * The size of the returned block will be at least @a size bytes, * rounded up to the next 32-byte increment. * * This is a thread-safe function. * * @param size Number of bytes to allocate. If @c 0, your code may do * whatever it wants; my_malloc() of @c 0 is "implementation defined", * meaning it is up to you if you want to return @c NULL, segfault, * whatever. * * @return Pointer to allocated memory, or @c NULL if no space could * be found. If out of memory, set errno to @c ENOMEM. */ void *my_malloc(size_t size); /** * Deallocate a memory region that was returned by my_malloc(). * * If @a ptr is not a pointer returned by my_malloc(), then send a * SIGSEGV signal to the calling process. Likewise, calling my_free() * on a previously freed region results in a SIGSEGV. * * This is a thread-safe function. * * @param ptr Pointer to memory region to free. If @c NULL, do * nothing. */ void my_free(void *ptr);
For my_malloc()
, you are to implement a first-fit
allocation strategy. Because each page frame is 32
bytes, my_malloc()
must round up to the next 32-byte
boundary when reserving space, and the returned address must be
frame-aligned. Your functions allocate using the space reserved in
step 1 above.
For my_free()
, your program deallocates space that was
returned by my_malloc()
. Thus,
if my_malloc()
previously allocated 5 frames and
returned the address to the first frame,
calling my_free()
will deallocate all 5 frames (not
just the first).
In your code, add a comment block describing how you track which frames are allocated and how large each memory block is. Specifically, describe how your code would handle these two scenarios:
my_free()
would know to
deallocate 5 frames if the user had previously
called my_malloc()
for 130 bytes?
my_free()
know it needs to send a SEGFAULT
if the user tries to free a pointer that points into the middle
of a memory block?
Next, implement this function with this given signature:
/** * Allocate an array of memory and set it to zero. * * This allocates a contiguous memory block equal to @a nmemb times @a * size bytes, rounded up to the next 32-byte increment. The returned * memory will be initialized to 0. * * This is a thread-safe function. * * @param nmemb Number of elements to allocated. If @c 0, your code * may do whatever it wants. When @a nmemb is @c, it is * "implementation defined", meaning it is up to you if you want to * return @c NULL, segfault, whatever. * * @param size Number of bytes per element to allocate. If @c 0, your * code may do whatever it wants. When @a size is @c 0, it is * "implementation defined", meaning it is up to you if you want to * return @c NULL, segfault, whatever. * * @return Pointer to allocated memory, or @c NULL if no space could * be found. If out of memory, set errno to @c ENOMEM. */ void *my_calloc(size_t nmemb, size_t size);
Your my_calloc()
(if nmemb
and size
are not 0) should use the same first-fit allocation
strategy as my_malloc()
. Likewise, the returned pointer
must be frame-aligned.
The final step is to ensure that your functions are thread-safe. If a thread is in the middle of any the above functions, another thread calling one of these functions must block.
Within your Ubuntu VM, use the wget command to fetch the unit test code file http://www.csee.umbc.edu/~jtang/cs421.f15/homework/hw4_test.c. This file declares a function with the following signature:
/** * Unit test of your memory allocator implementation. This will spawn * one or more threads that will simultaneously allocate and free * memory regions. */ extern void hw4_test(void);In your
main()
function, after you have initialized
your memory, call hw4_test()
.
The grader will use a different unit test code file during
grading. You may not make any assumptions about
what hw4_test()
will do other than that its code
will compile and that it will not have compilation warnings.
Here is a sample output from running the program using the above hw4_test.c.
Memory contents: ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ Memory allocations: ffffffff Memory contents: CCCCCCCCAAAAAAAAAAAAAAAAAAAAAA.. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB B............................... ................................ ................................ ................................ ................................ ................................ Memory allocations: fRRfffff Out of memory! Reason: Cannot allocate memory Good, memory was zeroed. Memory contents: DDDDDDDDDDDDDDDD................ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB B............................... ................................ ................................ ................................ ................................ ................................ Memory allocations: RRRfffff Memory contents: DDDDDDDDDDDDDDDD................ FFFFFFFFFF...................... ................................ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG GGGGGG.......................... Memory allocations: RRRffRRR Caught signal 11: Segmentation fault!
malloc()
/calloc()
/realloc()
(or any of its ilk) or
free()
. Using any built-in memory allocator
will result in a zero for this assignment.
ALIGN
macro.
Sorry, there is no extra credit available for this assignment.