Introduction to Computer Systems

Download Report

Transcript Introduction to Computer Systems

Dynamic Memory Allocation
(II) Implementation
1
Outline
•
•
•
•
Implementation of a simple allocator
Explicit Free List
Segregated Free List
Suggested reading: 9.9
2
Review
header
Format of
allocated and
free blocks
boundary tag
(footer)
4
1 word
size
00a
payload and
padding
a = 1: allocated block
a = 0: free block
size: block size
size
0 0a
payload: application data
(allocated blocks only)
4 4
4 6
6 4
4
3
Implementing a Simple Allocator
1 int mm_init(void);
2 void *mm_malloc(size_t size);
3 void mm_free(void *bp);
4
Initialize
1
2
3
4
5
/* private global variables */
static void *mem_heap; /* points to first byte of the heap */
static void *mem_brk;
/* points to last byte of the heap */
static void *mem_max_addr; /* max virtual address for the heap */
5
Initialize
6 /*
7 * mem_init - initializes the memory system model
8 */
9 void mem_init(void)
10 {
11
mem_heap = (char *)Malloc(MAX_HEAP);
12
mem_brk = (char *)mem_heap;
13
mem_max_addr = (char *) (mem_heap + MAX_HEAP);
14 }
15
6
Initialize
16 /*
17 * mem_sbrk - simple model of the sbrk function. Extends the
18 * heap by incr bytes and returns the start address of the new
19 * area. In this model, the heap cannot be shrunk.
20 */
7
Initialize
21 void *mem_sbrk(int incr)
22 {
23
void *old_brk = mem_brk;
24
25
if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) {
26
errno = ENOMEM;
27
fprintf(stderr, “ERROR: mem_sbrk failed. Ran out of memory
…\n”)
28
return (void *)-1;
29
}
30
mem_brk += incr;
31
return old_brk;
8
32 }
Data Structure
9
Macros
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* Basic constants and macros */
#define WSIZE 4 /* word 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 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))
10
Macros
15
/* Read the size and allocated fields from address p */
16
#define GET_SIZE(p) (GET(p) & ˜0x7)
17
#define GET_ALLOC(p) (GET(p) & 0x1)
18
19
/* Given block ptr bp, compute address of its header and footer */
20
#define HDRP(bp) ((char *)(bp) - WSIZE)
21
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
22
23
/* Given block ptr bp, compute address of next and previous blocks */
24
#define NEXT_BLKP(bp) ((char *)(bp) +GET_SIZE(((char *)(bp)-WSIZE)))
25
#define PREV_BLKP(bp) ((void *)(bp) - GET_SIZE(((void *)(bp) - DSIZE)))
11
mm_init()
1 int mm_init(void)
2 {
3
/* create the initial empty heap */
4
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *) -1)
5
return -1;
6
PUT(heap_listp, 0);
/* alignment padding */
7
PUT(heap_listp+(1*WSIZE), PACK(DSIZE, 1)); /* prologue header */
8
PUT(heap_listp+(2*WSIZE), PACK(DSIZE, 1)); /* prologue footer */
9
PUT(heap_listp+(3*WSIZE), PACK(0, 1));
/* epilogue header */
10
heap_listp += (2*WIZE);
11
12
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
13
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
14
return -1;
15
return 0;
16 }
12
mm_init()
1 static void *extend_heap(size_t words)
2 {
3
char *bp;
4
size_t size;
5
6
/* Allocate an even number of words to maintain alignment */
7
size = (words % 2) ? (words+1) * WSIZE : words * WSIZE;
8
if ((long)(bp = mem_sbrk(size)) == -1)
9
return NULL;
10
11
/* Initialize free block header/footer and the epilogue header */
12
PUT(HDRP(bp), PACK(size, 0));
/* free block header */
13
PUT(FTRP(bp), PACK(size, 0));
/* free block footer */
14
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* new epilogue header */
15
16
/* Coalesce if the previous block was free */
17
return coalesce(bp);
13
18 }
mm_free()
1 void mm_free(void *bp)
2 {
3
size_t size = GET_SIZE(HDRP(bp));
4
5
PUT(HDRP(bp), PACK(size, 0));
6
PUT(FTRP(bp), PACK(size, 0));
7
coalesce(bp);
8 }
9
14
mm_free()
10 static void *coalesce(void *bp)
11 {
12
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
13
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
14
size_t size = GET_SIZE(HDRP(bp));
15
16
if (prev_alloc && next_alloc) { /* Case 1 */
17
return bp;
18
}
19
20
else if (prev_alloc && !next_alloc) { /* Case 2 */
21
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
22
PUT(HDRP(bp), PACK(size, 0));
23
PUT(FTRP(bp), PACK(size,0));
24
return(bp);
25
}
26
15
mm_free()
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 }
else if (!prev_alloc && next_alloc) { /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
return(PREV_BLKP(bp));
}
else { /* Case 4 */
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));
return(PREV_BLKP(bp));
}
16
mm_malloc()
1 void *mm_malloc (size_t size)
2 {
3
size_t asize; /* adjusted block size */
4
size_t extendsize; /* amount to extend heap if no fit */
5
char *bp;
6
7
/* Ignore spurious requests */
8
if (size <= 0)
9
return NULL;
10
11
/* Adjust block size to include overhead and alignment reqs. */
12
if (size <= DSIZE)
13
asize = 2*DSIZE;
14
else
15
asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
16
17
mm_malloc()
17
18
19
20
21
22
23
24
25
26
27
28
29 }
/* 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;
18
mm_alloc()
1.static void *find_fit(size_t asize)
2.{
3.
void *bp ;
4.
5.
/* first fit search */
6.
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0 ; bp = NEXT_BLKP(bp) ) {
7.
if (!GET_ALLOC(HDRP(bp)) && (asize<=GET_SIZE(HDRP(bp)))) {
8.
return bp;
9.
}
10.
}
11.
return NULL; /*no fit */
12. }
19
mm_alloc()
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
static void place(void *bp, size_t asize)
{
size_t csize = GET_SIZE(HDRP(bp)) ;
if ( (csize –asize) >= (DSIZE + OVERHEAD) ) {
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) ;
} else {
PUT(HDRP(bp), PACK(csize, 1) ;
PUT(FTRP(bp), PACK(csize, 1) ;
}
}
20
Explicit free lists
A
B
C
Forward links
A
4
B
4 4
4 6
6 4
C
4 4
4
Back links
21
Explicit free lists
• Explicit list among the free blocks using
pointers within the free blocks
• Use data space for link pointers
– Typically doubly linked
– Still need boundary tags for coalescing
– It is important to realize that links are not
necessarily in the same order as the blocks
22
Explicit free lists
23
Freeing with explicit free lists
• Where to put the newly freed block in the
free list
– LIFO (last-in-first-out) policy
• insert freed block at the beginning of the free list
• pro: simple and constant time
• con: studies suggest fragmentation is worse than
address ordered.
24
Freeing with explicit free lists
• Where to put the newly freed block in the
free list
– Address-ordered policy
• insert freed blocks so that free list blocks are always in
address order
– i.e. addr(pred) < addr(curr) < addr(succ)
• con: requires search
• pro: studies suggest fragmentation is better than LIFO
25
Segregated Storage
• Each size “class” has its own collection
of blocks
– Often have separate collection for every small
size (2,3,4,…)
– For larger sizes typically have a collection for
each power of 2
26
Segregated Storage
1-2
3
4
5-8
9-16
27
Simple segregated storage
• Separate heap and free list for each size
class
• No splitting
• To allocate a block of size n:
– if free list for size n is not empty,
• allocate first block on list (note, list can be implicit or
explicit)
– if free list is empty,
• get a new page
• create new free list from all blocks in page
• allocate first block on list
– constant time
28
Simple segregated storage
• To free a block:
– Add to free list
• Tradeoffs:
– fast, but can fragment badly
29
Segregated fits
• Array of free lists, each one for some size
class
30
Segregated fits
• To allocate a block of size n:
– search appropriate free list for block of size m > n
– if an appropriate block is found:
• split block and place fragment on appropriate
list (optional)
– if no block is found, try next larger class
– repeat until block is found
– if no blocks is found in all classes, try more heap
memory
31
Segregated fits
• To free a block:
– coalesce and place on appropriate list (optional)
• Tradeoffs
– faster search than sequential fits (i.e., log time
for power of two size classes)
– controls fragmentation
• A simple first-fit approximates a best-fit over entire
heap
– coalescing can increase search times
• deferred coalescing can help
32
Buddy Systems
• A special case of segregated fits
– Each size is power of 2
• Initialize
– A heap of size 2m
33
Buddy Systems
• Allocate
– Roundup to power of 2 such as 2k
– Find a free block of size 2j (k  j  m)
– Split the block in half until j=k
• Each remaining half block (buddy) is placed on the
appreciate free list
• Free
– Continue coalescing with the free buddies
34
Next
•
•
•
•
•
•
Physical and Virtual Addressing
Address Spaces
VM as a Tool for Caching
VM as a Tool for Memory Management
VM as a Tool for Memory Protection
Suggested reading: 9.1~9.5
35