Implicit Free List Design Worksheet

Below is part of the starter code for lab 4. Use it to answer the following questions.

/*
 * Each block has header and footer of the form:
 *
 *      63                  4  3  2  1  0
 *      ------------------------------------
 *     | s  s  s  s  ... s  s  0  0  0  a/f |
 *      ------------------------------------
 *
 * where s are the meaningful size bits and a/f is 1
 * if and only if the block is allocated. The list has the following form:
 *
 * begin                                                             end
 * heap                                                             heap
 *  -----------------------------------------------------------------
 * |  pad   | hdr(16:a) | ftr(16:a) | zero or more usr blks | hdr(0:a) |
 *  -----------------------------------------------------------------
 *          |       prologue        |                       | epilogue |
 *          |         block         |                       | block    |
 *
 * The allocated prologue and epilogue blocks are overhead that
 * eliminate edge conditions during coalescing.
 */
/* Read a word at address p */
/* (size_t is an unsigned integer type with width = system word size) */
#define GET(p)       (*(size_t *)(p))

/* Perform unscaled pointer arithmetic */
#define PADD(p, val) ((char *)(p) + (val))
#define PSUB(p, val) ((char *)(p) - (val))

/* Read the size and allocated fields from address p */
#define GET_SIZE(p)  (GET(p) & ~0xf)
#define GET_ALLOC(p) (GET(p) & 0x1)

/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp)       (PSUB(bp, 8))
#define FTRP(bp)       (PADD(bp, GET_SIZE(HDRP(bp)) - 16))

/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp)  (PADD(bp, GET_SIZE(HDRP(bp))))
#define PREV_BLKP(bp)  (PSUB(bp, GET_SIZE((PSUB(bp, 16)))))
  1. Why do PADD and PSUB cast p to a char* in order to perform "unscaled pointer arithmetic"?
  2. How do the masks in GET_SIZE and GET_ALLOC relate to the diagram of a block header/footer above?
  3. Why does FTRP(bp) need to use HDRP, GET_SIZE, 16, and PADD to get the address of the footer?
  4. Given a block pointer bp (i.e., a pointer to the payload of a block), write the code to check if the next block in the heap is free.

 

 

  1. When we add or substract from a pointer, the arithmetic is scaled (multiplied) by the size of the data. If this scale is 1, we can add or substract an exact number without having to worry about scaling. A char is 1 byte, so arithmetic on a char* will be multiplied by 1, thus adding or substracting the exact number.
  2. ~0xf generates the 64-bit mask 0xfffffff0, so & ~0xf will zero out the lower four bits (which we can see will always be 0s due to the size being a multiple of 16). & 0x1 will isolate just the lowest bit, which we can see indicates allocated or free.
  3. Given a block pointer (a pointer to the start of the payload), we know the footer is at the other end of the block. To find where that is we need the block size. Fortunately, the block size is stored in the header, and we know the header is right before the start of the payload. Hence GET_SIZE(HDRP(bp)). If we add this to bp, we will end up at the start of the payload of the next block. We further know that right before that address is the header for the next block, and right before the header is the footer of the current block. Thus, if we go two words back in memory (- 16), we'll arrive at the footer. So, we take the current block pointer, get the size, add that minus two words, and we have the address of the footer.
  4. GET_ALLOC(HDRP(NEXT_BLKP(bp))) == 0 compared the allocated/free bit of the header of the next block to 0 (which would indicate the block is free)