Malloc lab
隐式列表 78 / 100 points
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
team_t team = {
/* Team name */
"Cranberry", // 蔓越莓
/* First member's full name */
"Lizi",
/* First member's email address */
"liansekong@gmail.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""};
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
#define WSIZE 4
#define DSIZE 8
// bytes
#define CHUNKSIZE (1 << 12) // 4096 bytes -> 4kb page size
#define MAX(x, y) ((x) > (y) ? (x) : (y))
// Pack a size and allocated bit into a word
#define PACK(size, alloc) ((size) | (alloc))
// Read and write a word at address p
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
// Read the size and allocated fields from address p
// Size 为整个块大小
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
// bp指向第一个有效载荷字节
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *find_fit(size_t asize);
static void place(void *bp, size_t size);
void *mm_malloc(size_t size);
char *heap_listp;
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)
{
return -1;
}
PUT(heap_listp, 0); // 起始位置
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); // 序言块 8/1
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); // 序言块 8/1
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); // 结尾块 0/1
// 指向第二个序言块
heap_listp += (2 * WSIZE);
if (extend_heap(CHUNKSIZE) == NULL)
return -1;
// printf("init finsh!\n");
return 0;
}
/**
* 首次匹配
*/
static void *find_fit(size_t asize)
{
char *start_bp = heap_listp + DSIZE;
while (GET_SIZE(HDRP(start_bp)) > 0)
{
if (GET_ALLOC(HDRP(start_bp)) == 0 && (GET_SIZE(HDRP(start_bp)) >= asize))
{
return start_bp;
}
start_bp = NEXT_BLKP(start_bp);
}
return NULL;
}
/**
* 设置分配块
* 1. 设置分配位为1
* 2. 分割空闲块
*/
static void place(void *bp, size_t size)
{
size_t cur_bk_size = GET_SIZE(HDRP(bp));
if (cur_bk_size - size >= DSIZE * 2)
{
PUT(HDRP(bp), PACK(size, 1));
PUT(FTRP(bp), PACK(size, 1));
PUT(HDRP(NEXT_BLKP(bp)), PACK(cur_bk_size - size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(cur_bk_size - size, 0));
}
else
{
PUT(HDRP(bp), PACK(cur_bk_size, 1));
PUT(FTRP(bp), PACK(cur_bk_size, 1));
}
}
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
if (size == 0)
{
return NULL;
}
// payload + padding + hdr + ftr
// Double word algin
size_t asize = ALIGN(size) + DSIZE;
size_t extend_size;
char *bp;
// 寻找空闲块
if ((bp = find_fit(asize)) != NULL)
{
place(bp, asize);
return bp;
}
// 无空闲列表,则向系统申请分配内存, 最小单位为 4kb
extend_size = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extend_size)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *bp)
{
// 获取当前块的大小
size_t size = GET_SIZE(HDRP(bp));
// 设置头尾为未分配
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
// 合并
coalesce(bp);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL)
{
return mm_malloc(size);
}
if (size == 0)
{
mm_free(ptr);
return NULL;
}
size_t asize = ALIGN(size) + DSIZE;
size_t cur_bk_size = GET_SIZE(HDRP(ptr));
if (cur_bk_size == asize)
{
return ptr;
}
else if (cur_bk_size < asize)
{
// expand
char *new_ptr = mm_malloc(size);
memcpy(new_ptr, ptr, cur_bk_size - DSIZE);
mm_free(ptr);
return new_ptr;
}
else
{
// shrink
if (cur_bk_size - asize <= 2 * DSIZE)
{
return ptr;
}
else
{
place(ptr, asize);
return ptr;
}
}
}
// 1. 堆初始化时调用
// 2. mm_malloc不能找到一个合适的匹配块时
static void *extend_heap(size_t size)
{
size_t asize = size % CHUNKSIZE == 0 ? size : ((size / CHUNKSIZE) + 1) * CHUNKSIZE;
char *bp;
if ((bp = mem_sbrk(asize)) == (void *)-1)
{
return NULL;
}
// 分配block时bp指向块的头部表, bp前一个块为之前的结尾块(0/1)
// 此时将之前的结尾块当作头部,现在分配块的最后一个word设为结尾块
PUT(HDRP(bp), PACK(asize, 0));
PUT(FTRP(bp), PACK(asize, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
return coalesce(bp);
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(FTRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc)
{
return bp;
}
if (prev_alloc && !next_alloc)
{
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (!prev_alloc && next_alloc)
{
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
else
{
size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
return bp;
}分离列表
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
team_t team = {
/* Team name */
"Cranberry", // 蔓越莓
/* First member's full name */
"Lizi",
/* First member's email address */
"liansekong@gmail.com",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""
};
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
#define WSIZE 4
#define DSIZE 8
#define MINI_BLOCK_SIZE 16
// SEG_LIST
#define SEG_LIST_LEN 15
// 4096 bytes -> 4kb page size
#define CHUNKSIZE (1 << 12)
#define MAX(x, y) ((x) > (y) ? (x) : (y))
// Pack a size and allocated bit into a word
#define PACK(size, alloc) ((size) | (alloc))
// Read and write a word at address p
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
// Read the size and allocated fields from address p
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
// bp指向第一个有效载荷字节
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
#define PREV(bp) ((char *)(bp))
#define SUCC(bp) ((char *)(bp) + WSIZE)
// 分离空闲链表
// 根据下标获取分离空闲列表的元素
#define ITEM_OF_FREE_LIST(listp, index) ((listp) + ((index) * (WSIZE) * 4))
#define PREV_FREE_BLKP(bp) (GET(bp))
#define SUCC_FREE_BLKP(bp) (GET((char *)(bp) + WSIZE))
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *find_fit(size_t asize);
static void place(void *bp, size_t size);
static size_t find_index(size_t size);
static void disconnect(void *bp);
void *mm_malloc(size_t size);
static void place_free(void *bp);
char *seg_listp;
char *heap_listp;
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
/**
* 分离空闲列表:seg_list
* 1. 每个列表头为: 4 Word
* * Header: size (32) + allocated bit (001)
* * Prev: 上一个空闲列表的地址
* * Succ: 下一个空心列表的地址
* * Footer: size (32) + allocated bit (001)
* 2. 列表的元素为:
* * Header: size (32) + allocated bit (001)
* * Prev: 上一个空闲列表的地址
* * Succ: 下一个空心列表的地址
* * Payload
* * Footer: size (32) + allocated bit (001)
*/
if ((seg_listp = mem_sbrk(SEG_LIST_LEN * WSIZE * 4)) == (void *)-1)
{
return -1;
}
seg_listp = seg_listp + WSIZE; // 指向首个列表的块位置
// 初始化空闲列表
for (size_t i = 0; i < SEG_LIST_LEN; i++)
{
char *bp = ITEM_OF_FREE_LIST(seg_listp, i);
PUT(HDRP(bp), PACK(4 * WSIZE, 1));
PUT(FTRP(bp), PACK(4 * WSIZE, 1));
PUT(PREV(bp), 0);
PUT(SUCC(bp), 0);
}
// 初始化隐式列表
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)
{
return -1;
}
PUT(heap_listp, 0); // 起始位置
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); // 序言块 8/1
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); // 序言块 8/1
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); // 结尾块 0/1
// 指向普通块起始位置
heap_listp += (2 * WSIZE);
char *bp;
if ((bp = extend_heap(CHUNKSIZE)) == NULL) {
return -1;
}
return 0;
}
/**
* find_fit - 寻找空闲块
* 策略: 首次匹配
*
*/
static void *find_fit(size_t asize) {
size_t index = find_index(asize);
for (size_t i = index; i < SEG_LIST_LEN; i++)
{
char *cur_free_bp = ITEM_OF_FREE_LIST(seg_listp, i);
char *succ_free_bp = SUCC_FREE_BLKP(cur_free_bp);
while (succ_free_bp != 0)
{
if (succ_free_bp != 0 && GET_SIZE(HDRP(succ_free_bp)) >= asize)
{
return succ_free_bp;
}
succ_free_bp = SUCC_FREE_BLKP(succ_free_bp);
}
}
return NULL;
}
/**
* - disconnect 断开在空闲链表中的连接
*
*/
static void disconnect(void *bp)
{
char *prev_free_bp = PREV_FREE_BLKP(bp);
char *succ_free_bp = SUCC_FREE_BLKP(bp);
PUT(SUCC(prev_free_bp), succ_free_bp);
if (succ_free_bp != 0)
{
PUT(PREV(succ_free_bp), prev_free_bp);
}
}
/**
* Allocated block
* hdr (4bytes): size(29bit) allocated bit(001)(3bit)
* payload
* padding
* ftr (4bytes): size(29bit) allocated bit(001)(3bit)
*
* Free block
* hdr (4bytes): size(29bit) allocated bit(000)(3bit) (010) 代表前一个块
* succ
* payload
* padding
* ftr (4bytes): size(29bit) allocated bit(001)(3bit)
*/
static void place(void *bp, size_t size) {
disconnect(bp);
size_t cur_bk_size = GET_SIZE(HDRP(bp));
size_t remaining_size = cur_bk_size - size;
if (remaining_size >= MINI_BLOCK_SIZE) {
PUT(HDRP(bp), PACK(size, 1));
PUT(FTRP(bp), PACK(size, 1));
PUT(HDRP(NEXT_BLKP(bp)), PACK(remaining_size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(remaining_size, 0));
place_free(NEXT_BLKP(bp));
}
else
{
PUT(HDRP(bp), PACK(cur_bk_size, 1));
PUT(FTRP(bp), PACK(cur_bk_size, 1));
}
}
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
if (size == 0) {
return NULL;
}
size_t asize = ALIGN(size) + DSIZE;
size_t extend_size;
char *bp;
if ((bp = find_fit(asize)) != NULL) {
place(bp, asize);
return bp;
}
// 无空闲列表,则向系统申请分配内存, 最小单位为 4kb
extend_size = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extend_size)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
static void place_free(void *bp)
{
size_t index = find_index(GET_SIZE(HDRP(bp)));
char *start_bp = ITEM_OF_FREE_LIST(seg_listp, index);
// 根据DIFO策略寻找合适位置
while (SUCC_FREE_BLKP(start_bp)!= 0)
{
if (SUCC_FREE_BLKP(start_bp) > (unsigned int)bp)
{
break;
}
start_bp = SUCC_FREE_BLKP(start_bp);
}
// 在合适位置建立链接start_bp_succ
char *start_bp_succ = SUCC_FREE_BLKP(start_bp);
PUT(SUCC(start_bp), bp);
PUT(PREV(bp), start_bp);
PUT(SUCC(bp), start_bp_succ);
if (start_bp_succ != 0) {
PUT(PREV(start_bp_succ), bp);
}
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *bp) {
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL) {
return mm_malloc(size);
}
if (size == 0) {
mm_free(ptr);
return NULL;
}
size_t asize = ALIGN(size) + DSIZE;
size_t cur_bk_size = GET_SIZE(HDRP(ptr));
if (cur_bk_size == asize) {
return ptr;
} else if (cur_bk_size < asize)
{
char *new_ptr = mm_malloc(size);
memcpy(new_ptr, ptr, cur_bk_size - DSIZE);
mm_free(ptr);
return new_ptr;
} else {
// shrink
size_t remaining_size = cur_bk_size - asize;
if (remaining_size >= MINI_BLOCK_SIZE)
{
PUT(HDRP(ptr), PACK(size, 1));
PUT(FTRP(ptr), PACK(size, 1));
PUT(HDRP(NEXT_BLKP(ptr)), PACK((remaining_size), 0));
PUT(FTRP(NEXT_BLKP(ptr)), PACK((remaining_size), 0));
coalesce(NEXT_BLKP(ptr));
}
return ptr;
}
}
static void *extend_heap(size_t size) {
size_t asize = size % CHUNKSIZE == 0 ? size : ((size / CHUNKSIZE) + 1) * CHUNKSIZE;
char *bp;
if ((bp = mem_sbrk(asize)) == (void *)-1)
{
return NULL;
}
PUT(HDRP(bp), PACK(asize, 0));
PUT(FTRP(bp), PACK(asize, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(bp)));
if (!prev_alloc)
{
disconnect(PREV_BLKP(bp));
asize += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(asize, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(asize, 0));
bp = PREV_BLKP(bp);
}
place_free(bp);
return bp;
}
static void *coalesce(void *bp) {
size_t size = GET_SIZE(HDRP(bp));
size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
if (prev_alloc && next_alloc)
{
place_free(bp);
return bp;
}
if (prev_alloc && !next_alloc)
{
disconnect(NEXT_BLKP(bp));
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
place_free(bp);
} else if (!prev_alloc && next_alloc) {
disconnect(PREV_BLKP(bp));
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
place_free(bp);
} else
{
disconnect(NEXT_BLKP(bp));
disconnect(PREV_BLKP(bp));
size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
place_free(bp);
}
return bp;
}
static size_t find_index(size_t size)
{
if (size <= 16)
return 0;
if (size <= 32)
return 1;
if (size <= 64)
return 2;
if (size <= 80)
return 3;
if (size <= 120)
return 4;
if (size <= 240)
return 5;
if (size <= 480)
return 6;
if (size <= 960)
return 7;
if (size <= 1920)
return 8;
if (size <= 3840)
return 9;
if (size <= 4096)
return 10;
if (size <= 15360)
return 11;
if (size <= 30720)
return 12;
if (size <= 61440)
return 13;
else
return 14;
}转载请注明出处