Malloc Library Enhanced


Please check back regularly for updates!

For this assignment, you will enhance your malloc library in the following manner:

  1. Per-Core Malloc Arenas
    • There is at least one malloc arena per CPU core. Your library will detect the total number of CPU cores and create that many arenas.
    • Each thread allocates/deallocates from one of these per-cpu arenas.
    • Per-thread data:
      • You can use the __thread to declare thread-specific global data. For example, for keeping a pointer to the 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.

  2. 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.

  3. Print Malloc Statistics

    You must print statistics for each arena when the program calls malloc_stats() (see the manpage for more details). Some of the fields can be:

    • 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.
  4. Optional (Extra credit)

Testing


In addition to the test binary, you should try and run some other popular programs like bash, zsh, vim, etc., to see if you library continues to work as expected.

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.