Homework 3 (Due Oct. 13, 2017)

Please check back regularly for updates!

10/9/17 10:30 AM:
  • Submission deadline updated to Friday, Oct. 13.
  • Malloc stats section updated with more information.
  • Added hints about per-thread malloc arenas.
  • Clarification regarding the functions to be implemented.

Implement a Malloc Library


For this assignment, you have to write a malloc library that provides the following dynamic memory allocation routines (as defined in man 3 malloc):

       #include 

       void *malloc(size_t size);
       void free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);
       struct mallinfo mallinfo();
       void malloc_stats();
      
Other relevant functions that are typically part of a malloc library should also be implemented as you find appropriate. Mention any additional functions that you have implement in your README. You have to implement a library that implements these functions to allocate and free dynamic memory.

You will need to know about memset and memcpy to implememt calloc and realloc respectively.

Allocation


  1. buddy allocation: You would keep a list of free blocks that can be used to satisfy a given memory request.
  2. Memory request:If no blocks are available on the free-list, you must ask kernel for more memory (using sbrk() systemcall). The memory request must always be multiple of PAGE_SIZE (use the sysconf(_SC_PAGESIZE) syscall). If sbrk fails, you must set errno to ENOMEM and return NULL;
  3. Alignment: The returned address from malloc, calloc and realloc must be aligned at 8-byte boundary.

Thread Safety


The library should be thread-safe, i.e., it should use proper locks, etc., to allow multiple threads to allocation/free memory.

Per-Thread Malloc Arenas:

  • Each thread allocates from it's own arena. That is, if there are four threads, there must be four separate arena.
  • If you'd like, you can instead use per-core arenas. In this case, your library will detect the total number of CPU cores and create that many arenas. Threads will then share arenas.
  • Per-thread data:
    • You can use the __thread to declare thread-specific global data. For example, for keeping a per-thread arena, you can use:
      __thread struct MyMallocArena *arena = NULL;
      ...
      void *malloc(size_t size) {
        ...
        if (arena == NULL) {
          initialize_arena(arena);
        }
        ...
        pthread_mutex_lock(&arena->lock);
        void *ptr = allocate_block(arena, size);
        pthread_mutex_unlock(&arena->lock);
        ...
        return ptr;
      }
      
    • An alternate strategy is to use pthread_key_create with pthread_get_specific and pthread_set_specific functions. The pthread_key_create functions allows you to also register a destructor that will be called when the thread exits. This destruction can be used to perform any thread-specific cleanup and/or memory-reclaimation. See the man pages for more details.

Support for fork


If a thread calls fork() to create a child process, can your library handle it? Try running a process with one thread calling fork() while other is calling malloc() continuously.

Testing


The hw3 directory contains a skeleton malloc.c, Makefile, and a basic test case.

Once you have everything ready, you can use the following benchmarks/tools to test out your malloc library.

Print Malloc Statistics


You must print the following statistics for each arena when the program calls malloc_stats() (see the manpage for more details):

  • Total size of arena allocated with sbrk/mmap
  • Total number of arenas
  • For each arena:
    • Total number of blocks
    • Used blocks
    • Free blocks
    • Total allocation requests
    • Total free requests
Note that you will need to write your own definitions for struct mallinfo mallinfo() which would return the struct that your library has been maintaining. For example, at the end of a malloc call, before returning the pointer to the user, you'd do something like:
            stats.uordblks += size;
      
Similarly for free, etc. If there are any member fields that are unclear or irrelevant, you can ignore them and mention it in your README. I hope this is useful.

Deliverables


Your submission should contain a file for each function wrapper (i.e. malloc.c, free.c, realloc.c, calloc.c, mallinfo.c, etc.) that contains definitions for malloc, free, realloc, calloc, mallinfo, etc. These file must not have main() and shouldn't have any debugging output. There should be separate header/C files for all utility functions. For example, all code to manage a linked list should be in a separate .c file with a corresponding .h file. A Makefile should be provided with a rule lib that generates libmalloc.so from this file.

You must also provide a README file that contains:

  • Design overview: A brief description of your overall code structure; important data structures (e.g., the free-node list); approach for managing arenas; allocation scheme; and any other important details.
  • Design decisions that you made.
  • Known bugs and errors

Conventions

  • One file per wrapper (malloc.c, free.c, etc.)
  • Makefile that allows compiling individual units.

Extra credit


Debugging, Hints and Resources


Memory debuggers:


See Also


  • alloca
  • Lock-free data structures