-
Notifications
You must be signed in to change notification settings - Fork 0
/
hw4.c
156 lines (135 loc) · 3.66 KB
/
hw4.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "./hw4-library/memlib.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "./hw4-library/mm.h"
struct memory_region{
size_t * start;
size_t * end;
};
struct memory_region global_mem;
struct memory_region stack_mem;
void walk_region_and_mark(void* start, void* end);
// PROVIDED BY US (DO NOT CHANGE)
// ------------------------------
// grabbing the address and size of the global memory region from proc
void init_global_range(){
int next = 0;
char file[100];
char * line=NULL;
size_t n=0;
size_t read_bytes=0;
size_t start, end;
sprintf(file, "/proc/%d/maps", getpid());
FILE * mapfile = fopen(file, "r");
if (mapfile==NULL){
perror("opening maps file failed\n");
exit(-1);
}
int counter=0;
while ((read_bytes = getline(&line, &n, mapfile)) != -1) {
// .data of hw4 executable
if (strstr(line, "hw4") != NULL && strstr(line,"rw-p")){
sscanf(line, "%lx-%lx", &start, &end);
global_mem.start = (void*) start;
global_mem.end = (void*) end;
break;
}
}
fclose(mapfile);
}
// marking related operations
int is_marked(unsigned int * chunk) {
return ((*chunk) & 0x2) > 0;
}
void mark(unsigned int * chunk) {
(*chunk)|=0x2;
}
void clear_mark(unsigned int * chunk) {
(*chunk)&=(~0x2);
}
// chunk related operations
#define chunk_size(c) ((*((unsigned int *)c))& ~(unsigned int)7 )
void* next_chunk(void* c) {
if(chunk_size(c) == 0) {
fprintf(stderr,"Panic, chunk is of zero size.\n");
}
if((c+chunk_size(c)) < mem_heap_hi())
return ((void*)c+chunk_size(c));
else
return 0;
}
int in_use(void *c) {
return *(unsigned int *)(c) & 0x1;
}
// FOR YOU TO IMPLEMENT
// --------------------
// the actual collection code
void sweep() {
void* chunk = mem_heap_lo();
// TODO
//Use mm_free to free memory
while (chunk < mem_heap_hi()&&chunk_size(chunk)) {
void* next = next_chunk(chunk);
if(is_marked(chunk))
clear_mark(chunk);
else if(in_use(chunk))
mm_free(chunk + 4);
chunk = next;
}
}
// determine if what "looks" like a pointer actually points to an
// in use block in the heap. if so, return a pointer to its header
void * is_pointer(void * ptr) {
// Here's a helpful print statement that shows some available memory operations and working with pointers
//printf("checking for pointeryness of %p between %p and %p\n",ptr, mem_heap_lo(), mem_heap_hi());
// TODO
if(ptr >= mem_heap_lo() && ptr <= mem_heap_hi()) {
void* chunk = mem_heap_lo();
while(chunk_size(chunk)) {
if (in_use(chunk) && ptr < chunk + chunk_size(chunk)) {
return chunk;
}
chunk = next_chunk(chunk);
}
}
return NULL;
}
// walk through memory specified by function arguments and mark
// each chunk
void walk_region_and_mark(void* start, void* end) {
//fprintf(stderr, "walking %p - %p\n", start, end);
// TODO
while (start < end) {
void* chunk = is_pointer(*(void**)start);
if (chunk == NULL) {
start = start + 8;
continue;
}
if (!is_marked(chunk)) {
mark(chunk);
walk_region_and_mark(chunk + 4, chunk + chunk_size(chunk));
}
start = start + 8;
}
}
// PROVIDED BY US (DO NOT CHANGE)
// ------------------------------
// standard initialization
void init_gc() {
size_t stack_var;
init_global_range();
// since the heap grows down, the end is found first
stack_mem.end=(size_t *)&stack_var;
}
void gc() {
size_t stack_var;
// grows down, so start is a lower address
stack_mem.start=(size_t *)&stack_var;
// walk memory regions
walk_region_and_mark(global_mem.start,global_mem.end);
walk_region_and_mark(stack_mem.start,stack_mem.end);
sweep();
}