static void *extend_heap(size_t words)
{
char *bp;
size_t size;
/* Allocate an even number of words to maintain alignmnet */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
PUT(HDRP(bp), PACK(size, 0)); /* Free block header */
PUT(FTRP(bp), PACK(size, 0)); /* Free block footer */
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* New epilogue header */
/*Coalesce if the previous block was free */
return coalesce(bp);
}
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
정렬 정책을 준수해야 하므로 요청 사이즈 words가 2로 나눠 떨어지도록 맞춰준다. if ((long)(bp = mem_sbrk(size)) == -1) return NULL;
힙이 해당 사이즈를 할당할 수 있다면 (없으면 NULL) static void *find_fit(size_t asize)
{
/* First-fit search */
void *bp;
for (bp = free_listp; GET_ALLOC(HDRP(bp)) == 0; bp = NEXT_FRBLKP(bp))
{
if (asize <= GET_SIZE(HDRP(bp)))
return bp;
}
return NULL;
}
GET_ALLOC(HDRP(bp)) == 0
조건을 적어준다.
static void remove_free_block(void *bp)
{
if(PREV_FRBLKP(bp))
NEXT_FRBLKP(PREV_FRBLKP(bp)) = NEXT_FRBLKP(bp);
else
free_listp = NEXT_FRBLKP(bp);
PREV_FRBLKP(NEXT_FRBLKP(bp)) = PREV_FRBLKP(bp);
}
static void *find_fit(size_t asize)
{
/* First-fit search */
void *bp;
for (bp = free_listp; GET_ALLOC(HDRP(bp)) == 0; bp = NEXT_FRBLKP(bp))
{
if (asize <= GET_SIZE(HDRP(bp)))
return bp;
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t csize = GET_SIZE(HDRP(bp));
if ((csize - asize) < WSIZE * 4)
{ /* 블록 크키가 작아 다른 블록 할당할 수 없을 때(not split) */
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
remove_free_block(bp);
}
else
{ /* 블록 크기가 다른 블록을 할당할 수 있을 만큼 클 때(split) */
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
remove_free_block(bp);
csize -= asize;
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(csize, 0));
PUT(FTRP(bp), PACK(csize, 0));
coalesce(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);
}
void *mm_malloc(size_t size)
{
size_t asize;
size_t extendsize;
char *bp;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignmnet reqs. */
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;
}
{
/* Create the initial empty heap. */
if ((heap_listp = mem_sbrk(6 * WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); /* Alignment padding */
PUT(heap_listp + (1 * WSIZE), PACK(2 * WSIZE, 1)); /* Prologue header */
PUT(heap_listp + (2 * WSIZE), PACK(2 * WSIZE, 1)); /* Prologue footer */
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2 * WSIZE); /* 포인터를 Prolouge 헤더 바로 다음으로 옮긴다 */
free_listp = heap_listp;
if (extend_heap(4) == NULL){
return -1;
}
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE / WSIZE) == NULL) /* 최대 할당 크기를 넘었을 때 */
return -1;
return 0;
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp))) || PREV_BLKP(bp) == bp;
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
/* If the previous block is free, then coalesce the current block (bp) and the previous block */
if (!prev_alloc && next_alloc) { /* Case 2 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
bp = PREV_BLKP(bp);
remove_free_block(bp);
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (prev_alloc && !next_alloc){ /* Case 3 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
remove_free_block(NEXT_BLKP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (!prev_alloc && !next_alloc){ /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)))
+ GET_SIZE(HDRP(NEXT_BLKP(bp)));
remove_free_block(PREV_BLKP(bp));
remove_free_block(NEXT_BLKP(bp));
bp = PREV_BLKP(bp);
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
/* case 1 : insert into free blocks*/
insert_free_block(bp);
return bp;
}
[ ] next-fit
[ ] 블록 삭제해보기
[] 더 작을 때 split 할지 안할지
모르겠는 것
왜, free list 초기화 할 때, root에 해당하는 것 하나 두고, 그 뒤에 하나 더 블록을 붙일까? 함 보자 어떻게 구현했는지
root를 만들 때 왜, pointer 2개를 구현하는지? root는 next만 있으면 되는 거 아닌가?
왜 prologu footer 뒤에 root free block 을 안두고, prologue header 뒤에 두나 생각했는데 이전에 짜둔 로직이 이제 payload 시작점을 prologue header, footer 사이에 두잖아. 거기서 이제
왜 안되는지 모르겠으나, padding 없이 prologue를 맨 앞에 두면 안된다 자리수를 맞춰준다 하더라도
일단 나는 padding 없어지고 프롤로그 헤더를 땡기면 왜그런지 몰라도 오류나서 패딩 그대로 만들어두고 루트 프리 노드에는 헤더와 풋터는 만들어주지 않았다. 그냥 next 포인터만 만들어주고 싶었는데 더블 워드 경계를 지켜야 해서 prev 포인터도 만들어 줬다.
#define NEXT_FREE(bp) (*(void **bp))
는
void *mm_malloc(size_t size)
{
size_t asize;
size_t extendsize;
char *bp;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignmnet reqs. */
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;
}
하는 값의 의미는 뭐지
//PREV_BLK(bp) == bp: epilogue block을 만났을 때. Extend했을 때 epilogue를 만나는 유일한 경우 - // size_t PREV_ALLOC = GET_ALLOC(HDRP(PREV_BLK(bp))) || PREV_BLK(bp) == bp;
하는 값의 의미는 뭐지 //PREV_BLK(bp) == bp: epilogue block을 만났을 때. Extend했을 때 epilogue를 만나는 유일한 경우
static void insert_free_block(void *bp)
{
NEXT_FRBLKP(bp) = free_listp;
PREV_FRBLKP(free_listp) = bp;
PREV_FRBLKP(bp) = NULL;
free_listp = bp;
}
bp의 next로 root를 두고
bp의 prev는 null로 둔다.
root의 prev를 bp로 둔다
루트를 bp로 설정한다
NEXT_FRBLKP(bp) = free_listp;
PREV_FRBLKP(free_listp) = bp;
PREV_FRBLKP(bp) = NULL;
free_listp = bp;
init 함수안에 if (extend_heap(4) == NULL){
return -1;
}
이걸 함으로서 82점에서 85점이 되는데 왜 그렇게 되는지 잘모르겠습니다.. 어떤거 때문에 저 코드를 넣으셨는지 궁금합니다.