qaqqaq

/*
 * mm-naive.c - The fastest, least memory-efficient malloc package.
 * 
 * In this naive approach, a block is allocated by simply incrementing
 * the brk pointer.  A block is pure payload. There are no headers or
 * footers.  Blocks are never coalesced or reused. Realloc is
 * implemented directly using mm_malloc and mm_free.
 *
 * NOTE TO STUDENTS: Replace this header comment with your own header
 * comment that gives a high level description of your solution.
 */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>

#include "mm.h"
#include "memlib.h"

/*********************************************************
 * NOTE TO STUDENTS: Before you do anything else, please
 * provide your team information in the following struct.
 ********************************************************/
team_t team = {
    /* Team name */
    "张心",
    /* First member's full name */
    "张心",
    /* First member's email address */
    "1472390784@qq.com",
    /* Second member's full name (leave blank if none) */
    "",
    /* Second member's email address (leave blank if none) */
    ""
};

/* 基本常量和宏 */
#define WSIZE 4             /* 字和头/脚大小(字节) */
#define DSIZE 8             /* 双字大小(字节) */
#define CHUNKSIZE (1<<12)   /* 按此数量(字节)扩展堆 */

#define MAX(x,y) ((x) > (y) ? (x) : (y))

/* 将size和alloc的位打包成一个字 */
#define PACK(size,alloc) ((size) | (alloc))

/* 读和写地址p的字 */
#define GET(p)      (*(unsigned int *)(p))
#define PUT(p,val)  (*(unsigned int *)(p) = (val))

/* 从地址p读取大小和分配的位 */
#define GET_SIZE(p)     (GET(p) & ~0x7)
#define GET_ALLOC(p)    (GET(p) & 0x1)

/* 给定块ptr bp,计算其头和脚的地址 */
#define HDRP(bp)    ((char *)(bp) - WSIZE)
#define FTRP(bp)    ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)

/* 给定块ptr bp,计算下一个和上一个块的地址 */
#define NEXT_BLKP(bp)   ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp)   ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))

/* 链表操作 */
#define NEXT_LINK_RP(bp) ((char *)(bp))
#define PREV_LINK_RP(bp) ((char *)(bp) + WSIZE)

static char * heap_listp;
static char * block_list_start;

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 asize);

static void _remove(char *bp);
static void _insert(char *bp);
static char *find_list_root(size_t size);   /** 查找该大小所在的链表 **/

#define SIZE_0 1
#define SIZE_1 2
#define SIZE_2 4
#define SIZE_3 8
#define SIZE_4 16
#define SIZE_5 32
#define SIZE_6 64
#define SIZE_7 128
#define SIZE_8 256
#define SIZE_9 512
#define SIZE_10 1024
#define SIZE_11 2048
#define SIZE_12 4096

/* 
 * mm_init - initialize the malloc package.
 */
int mm_init(void)
{
    /* 创建初始的空堆 */
    if((heap_listp = mem_sbrk(18*WSIZE)) == (void *)-1)
        return -1;
    PUT(heap_listp,0);                          /* 对齐填充 */
    PUT(heap_listp + (1*WSIZE),0);              /* 2^0=1 */
    PUT(heap_listp + (2*WSIZE),0);              /* 2^1=2 */
    PUT(heap_listp + (3*WSIZE),0);              /* 2^2=4*/
    PUT(heap_listp + (4*WSIZE),0);              /* 2^3=8*/
    PUT(heap_listp + (5*WSIZE),0);              /* 2^4=16*/
    PUT(heap_listp + (6*WSIZE),0);              /* 2^5=32*/
    PUT(heap_listp + (7*WSIZE),0);              /* 2^6=64*/
    PUT(heap_listp + (8*WSIZE),0);              /* 2^7=128*/
    PUT(heap_listp + (9*WSIZE),0);              /* 2^8=256*/
    PUT(heap_listp + (10*WSIZE),0);             /* 2^9=512*/
    PUT(heap_listp + (11*WSIZE),0);             /* 2^10=1024*/
    PUT(heap_listp + (12*WSIZE),0);             /* 2^11=2048*/
    PUT(heap_listp + (13*WSIZE),0);             /* 2^12=4096*/
    PUT(heap_listp + (14*WSIZE),0);             /* >4096*/
    PUT(heap_listp + (15*WSIZE),PACK(DSIZE,1));  /* 序言头 */
    PUT(heap_listp + (16*WSIZE),PACK(DSIZE,1));  /* 序言尾 */
    PUT(heap_listp + (17*WSIZE),PACK(0,1));      /* 结尾块 */

    block_list_start = heap_listp + (1*WSIZE);

    heap_listp += (16*WSIZE);
    
    /* 用一个CHUNKSIZE字节的空闲块扩展空堆 */
    if(extend_heap(CHUNKSIZE/DSIZE) == NULL)
        return -1;

    return 0;
}

/* 
 * 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)
{
    size_t asize;       /* 调整后的块大小 */
    size_t extendsize;  /* 如果不合适,扩展堆的数量 */
    char *bp;

    /* 忽略请求 */
    if(size == 0)
        return NULL;

    /* 调整块大小以包括开销和对齐要求 */
    if(size <= DSIZE)
        asize = 2*DSIZE;
    else
        asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);

    /* 在空闲块中搜索合适的 */
    if((bp = find_fit(asize)) != NULL){
        place(bp,asize);
        return bp;
    }

    /* 没有找到合适的,获得更多内存并放置内存块 */
    extendsize = MAX(asize,CHUNKSIZE);
    if((bp = extend_heap(extendsize/DSIZE)) == 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));
    PUT(NEXT_LINK_RP(bp),0);
    PUT(PREV_LINK_RP(bp),0);

    coalesce(bp);
}

/*
 * mm_realloc - Implemented simply in terms of mm_malloc and mm_free
 */
void *mm_realloc(void *ptr, size_t size)
{
    void *newptr=ptr;
    size_t total_size=0;
    size_t asize;

   /* 如果ptr为NULL,调用等价与mm_malloc(size) */
    if(ptr == NULL) {
        newptr = mm_malloc(size);
        return newptr;
    }

    /* 如果size等于0,则调用等价与mm_free(ptr) */
    if(size == 0) {
        mm_free(ptr);
        return 0;
    }


    //计算分配空间的实际大小asize,不小于2*DSIZE,要对齐  
    if(size <= DSIZE)
        asize = 2*DSIZE;
    else
        asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);

    /* 原先的size大小满足,直接返回原来的块 */
    if(GET_SIZE(HDRP(ptr))>=asize){
        return ptr;
    }
    /* 否则先检查ptr的下一个块是否为空闲块,
    如果是空闲块则看看ptr加上下一个块(空闲块)的大小是否满足asize
    满足就可以合并该块。
     */
    else if (!GET_ALLOC(HDRP(NEXT_BLKP(ptr)))
        && (GET_SIZE(HDRP(ptr))+GET_SIZE(HDRP(NEXT_BLKP(ptr)))>=asize)){
        total_size = GET_SIZE(HDRP(ptr))+GET_SIZE(HDRP(NEXT_BLKP(ptr)));
        _remove(NEXT_BLKP(ptr));
        PUT(HDRP(ptr),PACK(total_size,1));
        PUT(FTRP(ptr),PACK(total_size,1));
    }else if (!GET_ALLOC(HDRP(PREV_BLKP(ptr)))
        && (GET_SIZE(HDRP(ptr))+GET_SIZE(HDRP(PREV_BLKP(ptr)))>=asize))
    {
        total_size = GET_SIZE(HDRP(ptr))+GET_SIZE(HDRP(PREV_BLKP(ptr)));
        size_t oldsize = GET_SIZE(HDRP(ptr));
        _remove(PREV_BLKP(ptr));
        PUT(FTRP(ptr),PACK(total_size,1));
        PUT(HDRP(PREV_BLKP(ptr)),PACK(total_size,1));
        newptr = PREV_BLKP(ptr);
        memmove(newptr,ptr,oldsize-2*DSIZE);
    }
    else {
        newptr=mm_malloc(asize);
        memcpy(newptr,ptr,GET_SIZE(HDRP(ptr)));
        mm_free(ptr);
    }
    return newptr;
}


static void *extend_heap(size_t dwords)
{
    char *bp;
    size_t size;

    /* 分配偶数个双字保存对齐。 */
    size = (dwords % 2) ? (dwords+1) * DSIZE: dwords * DSIZE;
    if((long)(bp = mem_sbrk(size)) == -1)
        return NULL;

    /* 初始化空闲块头/尾和结尾 */
    PUT(HDRP(bp),PACK(size,0));         /* 空闲块头 */
    PUT(FTRP(bp),PACK(size,0));         /* 空闲块脚 */
    PUT(NEXT_LINK_RP(bp),0);
    PUT(PREV_LINK_RP(bp),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(HDRP(NEXT_BLKP(bp)));
    size_t size = GET_SIZE(HDRP(bp));

    if(prev_alloc && next_alloc){               /* 1)前面的块和后面的块都是已分配的 */
        
    }
    else if(prev_alloc && !next_alloc){         /* 2)前面的块是已分配的,后面的块是空闲的 */
        size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
        _remove(NEXT_BLKP(bp));
        PUT(HDRP(bp),PACK(size,0));
        PUT(FTRP(bp),PACK(size,0));
    }
    else if(!prev_alloc && next_alloc){         /* 3)前面的块是空闲的,而后面的块是已分配的 */
        size += GET_SIZE(HDRP(PREV_BLKP(bp)));
        _remove(PREV_BLKP(bp));
        PUT(FTRP(bp),PACK(size,0));
        PUT(HDRP(PREV_BLKP(bp)),PACK(size,0));
        bp = PREV_BLKP(bp);
    }
    else{                                       /* 4)前面的和后面的块都是空闲的 */
        size += GET_SIZE(HDRP(PREV_BLKP(bp)))
            + GET_SIZE(FTRP(NEXT_BLKP(bp)));
        _remove(PREV_BLKP(bp));
        _remove(NEXT_BLKP(bp));
        PUT(HDRP(PREV_BLKP(bp)),PACK(size,0));
        PUT(FTRP(NEXT_BLKP(bp)),PACK(size,0));
        bp = PREV_BLKP(bp);
    }
    _insert(bp);
    return bp;
}

static void *find_fit(size_t asize)
{
    char *root = find_list_root(asize);

    for(root;root != block_list_start+(14*WSIZE);root+=WSIZE){
        char *bp = GET(root);

        while(bp != NULL){
            if(GET_SIZE(HDRP(bp)) >= asize) return bp;
            bp = GET(NEXT_LINK_RP(bp));
        }
    }
    
    return NULL;
}

static void place(void *bp,size_t asize)
{
    size_t csize = GET_SIZE(HDRP(bp));
    _remove(bp);
    if((csize - asize) >= (2*DSIZE)){
        PUT(HDRP(bp),PACK(asize,1));
        PUT(FTRP(bp),PACK(asize,1));

        bp = NEXT_BLKP(bp);

        PUT(HDRP(bp),PACK(csize - asize,0));
        PUT(FTRP(bp),PACK(csize - asize,0));
        PUT(NEXT_LINK_RP(bp),0);
        PUT(PREV_LINK_RP(bp),0);
        coalesce(bp);
    }else{
        PUT(HDRP(bp),PACK(csize,1));
        PUT(FTRP(bp),PACK(csize,1));

    }
}

static void _remove(char *bp){

    char *root = find_list_root(GET_SIZE(HDRP(bp)));
    char *next = GET(NEXT_LINK_RP(bp));
    char *prev = GET(PREV_LINK_RP(bp));

    /* root根节点 */
    if(prev == NULL){
        if(next != NULL) PUT(PREV_LINK_RP(next),0);
        PUT(root,next);
    }else{
        if(next != NULL) PUT(PREV_LINK_RP(next),prev);
        PUT(NEXT_LINK_RP(prev),next);
    }
    PUT(NEXT_LINK_RP(bp),0);
    PUT(PREV_LINK_RP(bp),0);
}

static void _insert(char *bp){

    char *root = find_list_root(GET_SIZE(HDRP(bp)));
    char *prev = root;
    char *next = GET(root);

    //根据块大小排序,遍历到合适的位置
    while(next != NULL){
        if(GET_SIZE(HDRP(next))>=GET_SIZE(HDRP(bp))) break;
        prev = next;
        next = GET(NEXT_LINK_RP(next));
    }

    //只有一个节点的情况
    if(prev == root){
        PUT(root,bp);
        PUT(NEXT_LINK_RP(bp),next);
        PUT(PREV_LINK_RP(bp),NULL);
        if(next!=NULL) PUT(PREV_LINK_RP(next),bp);
    }else{
        PUT(NEXT_LINK_RP(prev),bp);
        PUT(PREV_LINK_RP(bp),prev);
        PUT(NEXT_LINK_RP(bp),next);
        if(next!=NULL) PUT(PREV_LINK_RP(next),bp);
    }

}

static char *find_list_root(size_t size){
    int i = 0;
    if(size <= SIZE_0) i = 0;
    else if(size <= SIZE_1) i = 1;
    else if(size <= SIZE_2) i = 2;
    else if(size <= SIZE_3) i = 3;
    else if(size <= SIZE_4) i = 4;
    else if(size <= SIZE_5) i = 5;
    else if(size <= SIZE_6) i = 6;
    else if(size <= SIZE_7) i = 7;
    else if(size <= SIZE_8) i = 8;
    else if(size <= SIZE_9) i = 9;
    else if(size <= SIZE_10) i = 10;
    else if(size <= SIZE_11) i = 11;
    else if(size <= SIZE_12) i = 12;
    else i = 13;

    return block_list_start + (i * WSIZE);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值