-
Notifications
You must be signed in to change notification settings - Fork 0
/
dynamic_memory.c
136 lines (127 loc) · 4.3 KB
/
dynamic_memory.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dynamic_memory.h"
#define FIRST_TABLE_SIZE 1024
#define FIRST_TABLE_SHIFT 22
#define SECOND_TABLE_SIZE 1024
#define SECOND_TABLE_SHIFT 12
#define ALLOCATE_UNIT_SIZE 4096
typedef uint8_t allocate_unit[ALLOCATE_UNIT_SIZE];
typedef allocate_unit* allocate_unit_table[SECOND_TABLE_SIZE];
static allocate_unit_table* aut_table[FIRST_TABLE_SIZE];
static int get_idxs(int* fidx_s, int* sidx_s, int* fidx_e, int* sidx_e, uint32_t addr, uint32_t size) {
if (size == 0) return 0;
size--;
if (size > UINT32_MAX - addr) return 0;
*fidx_s = (addr >> FIRST_TABLE_SHIFT) % FIRST_TABLE_SIZE;
*sidx_s = (addr >> SECOND_TABLE_SHIFT) % SECOND_TABLE_SIZE;
*fidx_e = ((addr + size) >> FIRST_TABLE_SHIFT) % FIRST_TABLE_SIZE;
*sidx_e = ((addr + size) >> SECOND_TABLE_SHIFT) % SECOND_TABLE_SIZE;
return 1;
}
void dmemory_read(void* dest, uint32_t addr, uint32_t size) {
if (size > 0 && size - 1 > UINT32_MAX - addr) size = UINT32_MAX - addr + 1;
uint8_t* destu8 = (uint8_t*)dest;
int fidx_s, sidx_s, fidx_e, sidx_e;
if (!get_idxs(&fidx_s, &sidx_s, &fidx_e, &sidx_e, addr, size)) return;
uint32_t read_offset = addr % ALLOCATE_UNIT_SIZE;
uint32_t read_size = ALLOCATE_UNIT_SIZE - read_offset;
int i, j;
for (i = fidx_s; i <= fidx_e; i++) {
int jmin = (i == fidx_s ? sidx_s : 0);
int jmax = (i == fidx_e ? sidx_e : SECOND_TABLE_SIZE - 1);
for (j = jmin; j <= jmax; j++) {
if (read_size > size) read_size = size;
if (aut_table[i] != NULL && (*aut_table[i])[j] != NULL) {
memcpy(destu8, *(*aut_table[i])[j] + read_offset, read_size);
}
destu8 += read_size;
size -= read_size;
read_offset = 0;
read_size = ALLOCATE_UNIT_SIZE;
}
}
}
void dmemory_write(void* src, uint32_t addr, uint32_t size) {
if (size > 0 && size - 1 > UINT32_MAX - addr) size = UINT32_MAX - addr + 1;
uint8_t* srcu8 = (uint8_t*)src;
int fidx_s, sidx_s, fidx_e, sidx_e;
if (!get_idxs(&fidx_s, &sidx_s, &fidx_e, &sidx_e, addr, size)) return;
uint32_t write_offset = addr % ALLOCATE_UNIT_SIZE;
uint32_t write_size = ALLOCATE_UNIT_SIZE - write_offset;
int i, j;
for (i = fidx_s; i <= fidx_e; i++) {
int jmin = (i == fidx_s ? sidx_s : 0);
int jmax = (i == fidx_e ? sidx_e : SECOND_TABLE_SIZE - 1);
for (j = jmin; j <= jmax; j++) {
if (write_size > size) write_size = size;
if (aut_table[i] != NULL && (*aut_table[i])[j] != NULL) {
memcpy(*(*aut_table[i])[j] + write_offset, srcu8, write_size);
}
srcu8 += write_size;
size -= write_size;
write_offset = 0;
write_size = ALLOCATE_UNIT_SIZE;
}
}
}
void dmemory_allocate(uint32_t addr, uint32_t size) {
int fidx_s, sidx_s, fidx_e, sidx_e;
if (!get_idxs(&fidx_s, &sidx_s, &fidx_e, &sidx_e, addr, size)) return;
int i, j;
for (i = fidx_s; i <= fidx_e; i++) {
int jmin = (i == fidx_s ? sidx_s : 0);
int jmax = (i == fidx_e ? sidx_e : SECOND_TABLE_SIZE - 1);
if (aut_table[i] == NULL) {
aut_table[i] = malloc(sizeof(*aut_table[i]));
if (aut_table[i] == NULL) {
perror("malloc");
exit(1);
}
for (j = 0; j < SECOND_TABLE_SIZE; j++) (*aut_table[i])[j] = NULL;
}
for (j = jmin; j <= jmax; j++) {
if ((*aut_table[i])[j] == NULL) {
(*aut_table[i])[j] = calloc(1, sizeof(*(*aut_table[i])[j]));
if ((*aut_table[i])[j] == NULL) {
perror("calloc");
exit(1);
}
}
}
}
}
void dmemory_deallocate(uint32_t addr, uint32_t size) {
int fidx_s, sidx_s, fidx_e, sidx_e;
if (!get_idxs(&fidx_s, &sidx_s, &fidx_e, &sidx_e, addr, size)) return;
int i, j;
for (i = fidx_s; i <= fidx_e; i++) {
int jmin = (i == fidx_s ? sidx_s : 0);
int jmax = (i == fidx_e ? sidx_e : SECOND_TABLE_SIZE - 1);
if (aut_table[i] != NULL) {
for (j = jmin; j <= jmax; j++) {
free((*aut_table[i])[j]);
(*aut_table[i])[j] = NULL;
}
if (jmin == 0 && jmax == SECOND_TABLE_SIZE - 1) {
free(aut_table[i]);
aut_table[i] = NULL;
}
}
}
}
int dmemory_is_allocated(uint32_t addr, uint32_t size) {
int fidx_s, sidx_s, fidx_e, sidx_e;
if (size == 0) return 1;
if (!get_idxs(&fidx_s, &sidx_s, &fidx_e, &sidx_e, addr, size)) return 0;
int i, j;
for (i = fidx_s; i <= fidx_e; i++) {
int jmin = (i == fidx_s ? sidx_s : 0);
int jmax = (i == fidx_e ? sidx_e : SECOND_TABLE_SIZE - 1);
for (j = jmin; j <= jmax; j++) {
if (aut_table[i] == NULL || (*aut_table[i])[j] == NULL) return 0;
}
}
return 1;
}