/*
* 首先我采用的是用splay伸展树来组织空白快,由当然每个块要有头和尾及左右儿子
* 为了节省空间我用来自顶向下的splay这样可以省去father这一个,提高利用率
* | head | leftson | rightson| ................| tail|
* 当然splay树中的块都大于等于4字,最后优化的时候我把4字的块都取出来用
* 双向链表串起来
* 因为指针是双字的,为了提高利用率,因为总共分配的地址不多过2^32因此我们可以用
* 一个相对地址来存储左右节点,这样head+left+right+tail 就被压缩到了4字。
*
* 然后对于分配块通过书上提出的算法,我们只需要记录head即可,tail是可以省去的
* 这样我们通过head中的倒数第二位记录前面一个块是否被分配
*
* 对于2个字的空白块,我只保留了他的head和tail 然后放在那里即可,合并时候用到
* 他就可以了,然后我开辟了一个指针类似与记录信号性质我就记录2字的块,如果已经有
* 2字的块了,则再释放一个2字的块就忽视。
*
* 进一步优化 对于四字的块 我用双向链表串起来
*
* 这样还是有点缺陷,99分。
* 然后我想对于上一次申请的块,如果结尾还有p剩余,那么这次需要申请aszie大小,
* 实际上我只申请了 asize-p,把p那块接上去就可以了。
*
* 以上就是我大致的算法和优化的思想
* 实际中最麻烦的就是调试,printTree 和 printNode 是用来打印树和节点信息的
* 代码中镶嵌有很多printf语句都是调试的时候查看信息留下的
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mm.h"
#include "memlib.h"
/* If you want debugging output, use the following macro. When you hand
* in, remove the #define DEBUG line. */
#define DEBUG
#ifdef DEBUG
# define dbg_printf(...) printf(__VA_ARGS__)
#else
# define dbg_printf(...)
#endif
/* do not CHANGE the following! */
#ifdef DRIVER
/* create aliases for driver tests */
#define malloc mm_malloc
#define free mm_free
#define realloc mm_realloc
#define calloc mm_calloc
#endif /* def DRIVER */
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(p) (((size_t)(p) + (ALIGNMENT-1)) & ~0x7)
#define WSIZE 4
#define DSIZE 8
#define TSIZE 12
#define QSIZE 16
#define CHUNKSIZE (256)
#define BLOCK4 (4)
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
#define PACK(size, alloc) ((size) | (alloc))
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
#define GET_PRE_ALLOC(p) (GET(p) & 0x2) //倒数第二位存放迁移块是否被释放的信息
#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)))
//binary Tree
#define GET_LEFTSON(bp) (GET( LEFTSON(bp) ) )
#define GET_RIGHTSON(bp) (GET( RIGHTSON(bp) ) )
#define LEFTSON(bp) ( (char *)(bp) )
#define RIGHTSON(bp) ( (char *)(bp) + WSIZE )
#define CHANGE32(bp) ( ( (char *)bp - Tnode))
#define CHANGE64(bp) ( (Tnode + bp))
#define CHECKMIN(bp, t) (GET_SIZE(HDRP(bp)) < GET_SIZE(HDRP(t))) || ((GET_SIZE(HDRP(bp)) == GET_SIZE(HDRP(t))) && CHANGE32(bp)<CHANGE32(t))
#define null (0)
//function
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void place(void *bp, size_t asize);
static char * heap_listp;
static char * listp4;
static char * listp2;
static unsigned int root ;
static char * Tnode;
static char * LASTBLOCK= NULL; // 最后一个块的脚步,用来判断是否需要跟新申请的块合并
static int ok = 0;
static void printTree(unsigned int root, unsigned int fa);
static void printNode(unsigned int root);
static void insert(void * bp);
static void move(void *bp);
static void splay(void * bp);
static void * find_fit(size_t asize);
//static int find(void * bp);
// 自顶向下的splay
static void splay(void * bp){
//printf("splay:(%p):\n",bp);
//printf("splay root:%u\n",root);
if ( root == null )
return ;
// printTree(root, 0);
// printf("splay after \n");
char * L = NULL;
char * R = NULL;
char * y = NULL;
char * node = Tnode;
PUT( LEFTSON(node), null );
PUT( RIGHTSON(node), null );
L = R = node;
void
ICS Malloc Lab: Writing a Dynamic Storage Allocator
最新推荐文章于 2024-05-23 11:33:10 发布
这篇博客介绍了作者在ICS Malloc Lab中使用Splay伸展树实现动态存储分配器的过程。算法通过压缩数据结构减少空间浪费,利用头尾标志位记录分配状态,并优化了四字节块的处理。此外,还通过双向链表管理四字节块,以提高效率。文章详细阐述了算法设计和优化思想,并提供了调试辅助函数。
摘要由CSDN通过智能技术生成