CSAPP中的堆管理器实现

144 篇文章 19 订阅

堆管理器实现代码,heap.h

#ifndef _HEAP_IMPL_
#define _HEAP_IMPL_

#include <stdio.h>
#include <stdlib.h>

// Basic constants and macros.
#define WSIZE               4         // Word and header/footer size(bytes)
#define DSIZE               8         // Double word size(bytes)
#define CHUNKSIZE           (1<<12)   // Extend heap by this amount(bytes)

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

// Pack a size and allocate bit into a word
#define PACK(size, alloc)   ((size)|(alloc))

// Read and write a word at addres 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)

// Given block ptr bp, compute address of its header and footer
#define HDRP(bp)            ((char*)(bp)-WSIZE)
#define FTRP(bp)            ((char*)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)

// Given block ptr bp, compute address of next and previous blocks.

#define NEXT_BLKP(bp)       ((char*)(bp) + GET_SIZE(((char*)(bp) - WSIZE)))
#define PREV_BLKP(bp)       ((char*)(bp) - GET_SIZE(((char*)(bp) - DSIZE)))

int mm_init(void);
void mm_free(void *bp);
void* mm_malloc(size_t size);

#endif

heap.c

#include "heap.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

// private glabal variables
static char *mem_heap;        // points to first byte of heap.
static char *mem_brk;         // points to last byte of heap plus 1.
static char *mem_max_addr;    // max legal heap addr plus 1.
static void *heap_listp;
#define MAX_HEAP              (16*1024*1024)

static void mem_init(void)
{
    mem_heap     = (char *)malloc(MAX_HEAP);
    if(mem_heap == NULL)
    {
        fprintf(stderr, "failure to malloc.\n");
        return;
    }
    mem_brk      = (char *)mem_heap;
    mem_max_addr = (char*)(mem_heap + MAX_HEAP);
}


// mem_sbrk:simple model of the sbrk function. extens the heap by incr bytes and returns
// the start address of the new area.in this model, the heap cannot be shrunk.
void *mem_sbrk(int incr)
{
    char *old_brk = mem_brk;

    if((incr < 0) || ((mem_brk + incr) > mem_max_addr))
    {
        errno = ENOMEM;
        fprintf(stderr, "Error: mem_sbrk failed, run out of memory ...\n");
        return (void*)-1;
    }

    mem_brk += incr;

    return (void*)old_brk;
}

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)
    {
        return bp;
    }
    else 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(FTRP(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;
}

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

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

    size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;

    if((long)(bp = mem_sbrk(size)) == -1)
    {
        return NULL;
    }

    // initialize free block header/footer and the epilogue header.  PUT(HDRP(bp), PACK(size, 0));
    PUT(HDRP(bp), PACK(size, 0));
    PUT(FTRP(bp), PACK(size, 0));
    PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));

    // coalesce if the previous block was free.
    return coalesce(bp);
}

int mm_init(void)
{
	void *bp;
    mem_init();
    // create the initial empty heap.
    if((heap_listp = mem_sbrk(4*WSIZE)) == (void*)-1)
    {
        return -1;
    }

    PUT(heap_listp + (0*WSIZE), 0);
    PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1));
    PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1));
    PUT(heap_listp + (3*WSIZE), PACK(0, 1));
    heap_listp += 2*WSIZE;

    if((bp = extend_heap(CHUNKSIZE/WSIZE)) == NULL)
    {
        fprintf(stderr, "%s line %d, failure.\n", __func__, __LINE__);
        return -1;
    }

    return 0;
}

static void *find_fit(size_t asize)
{
    void *bp;
    for(bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp=NEXT_BLKP(bp))
    {
        if(GET_SIZE(HDRP(bp)) >= asize && GET_ALLOC(HDRP(bp))!=1)
        {
            return bp;
        }
    }
    return NULL;
}

static void place(void *bp, size_t asize)
{
    size_t bsize = GET_SIZE(HDRP(bp));
    if ((bsize - asize) > 2*DSIZE)
    {
        PUT(HDRP(bp), PACK(asize, 1));
        PUT(FTRP(bp), PACK(asize, 1));
        bp = NEXT_BLKP(bp);
        PUT(HDRP(bp), PACK(bsize - asize, 0));
        PUT(FTRP(bp), PACK(bsize - asize, 0));
    }
    else
    {
        PUT(HDRP(bp), PACK(asize, 1));
        PUT(FTRP(bp), PACK(asize, 1));
    }
}

void *mm_malloc(size_t size)
{
    size_t asize;             // adjusted block size.
    size_t extendsize;        // amount to extend heap of no fit.
    char *bp;

    // ignore spurious requests.
    if(size == 0)
    {
        return NULL;
    }

    if(size <= DSIZE)
    {
        asize = 2*DSIZE;
    }
    else
    {
        asize = DSIZE *((size + (DSIZE) + (DSIZE-1)) / DSIZE);
    }

    // search the free list for a fit
    if((bp = find_fit(asize))!=NULL)
    {
        place(bp, asize);
        return bp;
    }

    // no fit found, get more memory and place the block.
    extendsize = MAX(asize, CHUNKSIZE);
    if((bp = extend_heap(extendsize/WSIZE)) == NULL)
    {
        return NULL;
    }

    place(bp, asize);

    return bp;
}

main.c

#include "heap.h"
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	void *bp;
	mm_init();

	while(1)
	{
	    bp = mm_malloc(400);
	    fprintf(stderr, "alloc %p.\n", bp);
	    mm_free(bp);
	}
	return 0;
}

运行过程:


多线程:

#include "heap.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

static pthread_mutex_t mutex;
static void *write_msg_server(void *param)
{
    void *bp;

    while(1)
    {
        pthread_mutex_lock(&mutex);
        bp = mm_malloc(400);  
        printf("%s line %d, bp=%p.\n", __func__, __LINE__, bp);
        mm_free(bp);
        pthread_mutex_unlock(&mutex);
    }     
    return 0;
}

static void *read_msg_server(void *param)
{
    void *bp;

    while(1)
    {
        pthread_mutex_lock(&mutex);
        bp = mm_malloc(400);  
        printf("%s line %d, bp=%p.\n", __func__, __LINE__, bp);
        mm_free(bp);
        pthread_mutex_unlock(&mutex);
    }     
    return 0;
}


int main(void)
{
    int ret;
    void *bp;
    mm_init();

    pthread_t pthread_read;
    pthread_t pthread_write;
    pthread_mutex_init(&mutex, NULL);
    
    int err = pthread_create(&pthread_read, NULL, read_msg_server, NULL);
    if(err != 0)
    {
        perror("create pthread failure.");
        return -1;
    }
 
    err = pthread_create(&pthread_write, NULL, write_msg_server, NULL);
    if(err != 0)
    {
        perror("create pthread failure.");
        return -1;
    }

    pthread_join(pthread_write, NULL);
    pthread_join(pthread_read, NULL);

    return 0;
}

运行


结束

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值