oceanbase

Форк
0
/
easy_mem_page.c 
229 строк · 7.2 Кб
1
#include "memory/easy_mem_page.h"
2
#include <malloc.h>
3

4
static easy_mem_page_t *easy_mem_rmqueue(easy_mem_zone_t *zone, uint32_t order);
5
static void easy_mem_expand(easy_mem_zone_t *zone, easy_mem_page_t *page,
6
                            int low, int high, easy_mem_area_t *area);
7
static void easy_mem_merge_buddy_page(easy_mem_zone_t *zone, easy_mem_page_t *page, uint32_t order);
8

9
static inline easy_mem_page_t *easy_mem_page_ptr(easy_mem_page_t *page, int index);
10
static inline easy_mem_page_t *easy_mem_index_to_page(easy_mem_zone_t *zone, int index);
11
static inline int easy_mem_page_to_index(easy_mem_zone_t *zone, easy_mem_page_t *page);
12
static inline int easy_mem_find_buddy_index(int page_idx, uint32_t order);
13
static inline int easy_mem_find_combined_index(int page_idx, uint32_t order);
14
static inline void easy_mem_set_page_free(easy_mem_zone_t *zone, easy_mem_page_t *page, int order);
15
static inline void easy_mem_set_page_used(easy_mem_zone_t *zone, easy_mem_page_t *page, int order);
16

17
// 内存初始化, 最大每zone 2G
18
easy_mem_zone_t *easy_mem_zone_create(int64_t max_size)
19
{
20
    easy_mem_zone_t         *zone;
21
    unsigned char           *memptr;
22
    int64_t                 size;
23
    uint32_t                n;
24
    int                     page_size, pos, order, asize;
25

26
    // min = 128k
27
    order = 0;
28
    size = EASY_MEM_PAGE_SIZE;
29

30
    while (size < max_size) {
31
        size <<= 1;
32
        order ++;
33
    }
34

35
    pos = (size / EASY_MEM_PAGE_SIZE) + sizeof(easy_mem_zone_t);
36
    page_size = easy_align(pos, EASY_MEM_PAGE_SIZE);
37
    asize = (1 << (EASY_MEM_MAX_ORDER + EASY_MEM_PAGE_SHIFT - 1));
38
    asize = easy_max(page_size, easy_min(asize, size));
39

40
    // alloc memory
41
    if ((memptr = (unsigned char *)memalign(EASY_MEM_PAGE_SIZE, asize + size)) == NULL) {
42
        return NULL;
43
    }
44

45
    // init
46
    zone = (easy_mem_zone_t *)memptr;
47
    memset(zone, 0, sizeof(easy_mem_zone_t));
48
    zone->curr = memptr + easy_align(pos, 32);
49
    zone->curr_end = memptr + page_size;
50

51
    zone->max_order = ((order >= EASY_MEM_MAX_ORDER) ? (EASY_MEM_MAX_ORDER - 1) : order);
52
    zone->mem_start = (unsigned char *)easy_align((unsigned long)zone->curr_end, asize);
53
    zone->mem_last = zone->mem_start;
54
    zone->mem_end = zone->mem_start + size;
55

56
    for (n = 0; n <= zone->max_order; n++) {
57
        easy_list_init(&zone->area[n].free_list);
58
    }
59

60
    return zone;
61
}
62

63
// 内存释放
64
void easy_mem_zone_destroy(easy_mem_zone_t *zone)
65
{
66
    easy_free(zone);
67
}
68

69
// 内存分配
70
easy_mem_page_t *easy_mem_alloc_pages(easy_mem_zone_t *zone, uint32_t order)
71
{
72
    easy_mem_page_t         *page;
73
    easy_mem_area_t         *area;
74

75
    if (order > zone->max_order)
76
        return NULL;
77

78
    // 有空的page直接分配
79
    if (zone->free_pages >= (1 << order))
80
        if ((page = easy_mem_rmqueue(zone, order)) != NULL)
81
            return page;
82

83
    // 加入freelist
84
    if (zone->mem_last < zone->mem_end) {
85
        page = (easy_mem_page_t *) zone->mem_last;
86
        zone->mem_last += ((1 << zone->max_order) << EASY_MEM_PAGE_SHIFT);
87

88
        zone->free_pages += (1 << zone->max_order);
89
        area = zone->area + zone->max_order;
90
        easy_list_add_head(&page->lru, &area->free_list);
91
        area->nr_free ++;
92

93
        return easy_mem_rmqueue(zone, order);
94
    }
95

96
    return NULL;
97
}
98

99
// 内存释放
100
void easy_mem_free_pages(easy_mem_zone_t *zone, easy_mem_page_t *page)
101
{
102
    unsigned long           page_idx;
103
    unsigned char           *ptr = (unsigned char *) page;
104

105
    if (ptr < zone->mem_start || ptr > (zone->mem_last - EASY_MEM_PAGE_SIZE))
106
        return;
107

108
    // page index
109
    page_idx = easy_mem_page_to_index(zone, page);
110

111
    if ((zone->page_flags[page_idx] & 0x80)) {
112
        easy_mem_merge_buddy_page(zone, page, (zone->page_flags[page_idx] & 0x0f));
113
    }
114
}
115

116
///////////////////////////////////////////////////////////////////////////////////////////////////
117
static easy_mem_page_t *easy_mem_rmqueue(easy_mem_zone_t *zone, uint32_t order)
118
{
119
    easy_mem_area_t         *area;
120
    uint32_t                n;
121
    easy_mem_page_t         *page;
122

123
    for (n = order; n <= zone->max_order; n++) {
124
        area = zone->area + n;
125

126
        if (easy_list_empty(&area->free_list))
127
            continue;
128

129
        page = easy_list_entry(area->free_list.next, easy_mem_page_t, lru);
130
        easy_list_del(&page->lru);
131
        area->nr_free--;
132
        zone->free_pages -= (1 << order);
133
        easy_mem_expand(zone, page, order, n, area);
134
        easy_mem_set_page_used(zone, page, order);
135
        return page;
136
    }
137

138
    return NULL;
139
}
140

141
static void easy_mem_expand(easy_mem_zone_t *zone, easy_mem_page_t *page,
142
                            int low, int high, easy_mem_area_t *area)
143
{
144
    easy_mem_page_t         *newpage;
145
    unsigned long           size = 1 << high;
146

147
    while (high > low) {
148
        area--;
149
        high--;
150
        size >>= 1;
151
        newpage = easy_mem_page_ptr(page, size);
152
        easy_list_add_head(&newpage->lru, &area->free_list);
153
        area->nr_free ++;
154
        easy_mem_set_page_free(zone, newpage, high);
155
    }
156
}
157

158
static void easy_mem_merge_buddy_page(easy_mem_zone_t *zone, easy_mem_page_t *page, uint32_t order)
159
{
160
    int                     page_idx, buddy_idx, combined_idx, order_size;
161
    easy_mem_page_t         *buddy;
162

163
    order_size = 1 << order;
164
    page_idx = easy_mem_page_to_index(zone, page);
165
    zone->free_pages += order_size;
166

167
    while (order < zone->max_order) {
168
        buddy_idx = easy_mem_find_buddy_index(page_idx, order);
169

170
        if (zone->page_flags[buddy_idx] != order)
171
            break;
172

173
        buddy = easy_mem_index_to_page(zone, buddy_idx);
174
        easy_list_del(&buddy->lru);
175
        zone->area[order].nr_free --;
176
        zone->page_flags[buddy_idx] = 0;
177

178
        combined_idx = easy_mem_find_combined_index(page_idx, order);
179
        page = easy_mem_index_to_page(zone, combined_idx);
180
        page_idx = combined_idx;
181
        order ++;
182
    }
183

184
    easy_mem_set_page_free(zone, page, order);
185
    easy_list_add_head(&page->lru, &zone->area[order].free_list);
186
    zone->area[order].nr_free ++;
187
}
188

189
// inline function
190
static inline easy_mem_page_t *easy_mem_page_ptr(easy_mem_page_t *page, int index)
191
{
192
    return (easy_mem_page_t *)(((unsigned char *)page) + index * EASY_MEM_PAGE_SIZE);
193
}
194

195
static inline int easy_mem_page_to_index(easy_mem_zone_t *zone, easy_mem_page_t *page)
196
{
197
    return (((unsigned char *)page) - zone->mem_start) >> EASY_MEM_PAGE_SHIFT;
198
}
199

200
static inline easy_mem_page_t *easy_mem_index_to_page(easy_mem_zone_t *zone, int index)
201
{
202
    return (easy_mem_page_t *)(zone->mem_start + (index << EASY_MEM_PAGE_SHIFT));
203
}
204

205
static inline int easy_mem_find_buddy_index(int page_idx, uint32_t order)
206
{
207
    return page_idx ^ (1 << order);
208
}
209

210
static inline int easy_mem_find_combined_index(int page_idx, uint32_t order)
211
{
212
    return (page_idx & ~(1 << order));
213
}
214

215
static inline void easy_mem_set_page_free(easy_mem_zone_t *zone, easy_mem_page_t *page, int order)
216
{
217
    unsigned long           page_idx;
218

219
    page_idx = (((unsigned char *)page) - zone->mem_start) >> EASY_MEM_PAGE_SHIFT;
220
    zone->page_flags[page_idx] = (0x0f & order);
221
}
222

223
static inline void easy_mem_set_page_used(easy_mem_zone_t *zone, easy_mem_page_t *page, int order)
224
{
225
    unsigned long           page_idx;
226

227
    page_idx = (((unsigned char *)page) - zone->mem_start) >> EASY_MEM_PAGE_SHIFT;
228
    zone->page_flags[page_idx] = (0x80 | order);
229
}
230

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.