oceanbase

Форк
0
/
easy_mem_slab.c 
356 строк · 9.9 Кб
1
#include "memory/easy_mem_slab.h"
2

3
#define EASY_MEM_POS_END      (((uint16_t)(~0U))-0)
4

5
easy_mem_mgr_t          easy_mem_mgr_var = {0};
6
static void *easy_mem_slab_get_obj(easy_mem_cache_t *cache, easy_mem_slab_t *slab);
7
static void *easy_mem_cache_grow(easy_mem_cache_t *cache);
8
static void easy_mem_slab_put_obj(easy_mem_cache_t *cache, easy_mem_slab_t *slab, void *obj);
9
static inline easy_mem_cache_t *easy_mem_get_cache(unsigned char *obj);
10
static inline easy_mem_slab_t *easy_mem_virt_to_slab(int order, const void *obj);
11
static inline easy_mem_cache_t *easy_mem_cache_size(uint32_t size);
12

13
// 内存初始化
14
int easy_mem_slab_init(int start_alloc_size, int64_t max_size)
15
{
16
    int                     size, cache_num;
17

18
    if (easy_mem_mgr_var.started)
19
        return EASY_ERROR;
20

21
    // 初始化
22
    memset(&easy_mem_mgr_var, 0, sizeof(easy_mem_mgr_var));
23
    easy_mem_mgr_var.max_size = max_size;
24
    easy_mem_mgr_var.zone = easy_mem_zone_create(max_size);
25

26
    if (easy_mem_mgr_var.zone == NULL)
27
        return EASY_ERROR;
28

29
    // init
30
    cache_num = (easy_mem_mgr_var.zone->curr_end - easy_mem_mgr_var.zone->curr);
31
    cache_num /= sizeof(easy_mem_cache_t);
32
    cache_num --;
33

34
    size = EASY_MEM_SLAB_MIN;
35
    easy_list_init(&easy_mem_mgr_var.list);
36
    easy_mem_mgr_var.cache_max_num = easy_max(cache_num, 1024);
37
    easy_mem_mgr_var.caches = (easy_mem_cache_t *)easy_mem_mgr_var.zone->curr;
38

39
    // 分配mem_cache
40
    while(size <= start_alloc_size) {
41
        if (easy_mem_cache_create(size) == NULL)
42
            break;
43

44
        size <<= 1;
45
    }
46

47
    easy_mem_mgr_var.cache_fix_num = easy_mem_mgr_var.cache_num;
48
    easy_mem_mgr_var.started = 1;
49
    return EASY_OK;
50
}
51

52
// destroy
53
void easy_mem_slab_destroy()
54
{
55
    if (easy_mem_mgr_var.started) {
56
        easy_mem_zone_destroy(easy_mem_mgr_var.zone);
57
        memset(&easy_mem_mgr_var, 0, sizeof(easy_mem_mgr_var));
58
    }
59
}
60

61
// 内存分配
62
void *easy_mem_slab_realloc(void *ptr, size_t size)
63
{
64
    easy_mem_cache_t        *cache, *ncache;
65
    unsigned char           *obj;
66

67
    // free
68
    obj = (unsigned char *)ptr;
69

70
    if (size == 0 && obj != NULL) {
71
        if ((cache = easy_mem_get_cache(obj)) != NULL)
72
            easy_mem_cache_free(cache, obj);
73
        else
74
            easy_free(ptr);
75

76
        return NULL;
77
        // realloc
78
    } else if (obj != NULL) {
79
        if ((cache = easy_mem_get_cache(obj)) != NULL && size <= cache->buffer_size)
80
            return ptr;
81

82
        // 分配新的
83
        ncache = easy_mem_cache_size(size);
84

85
        if (ncache) {
86
            ptr = easy_mem_cache_alloc(ncache);
87
        } else if (cache) {
88
            ptr = easy_malloc(size);
89
        } else {
90
            ptr = easy_realloc(ptr, size);
91
        }
92

93
        // 把旧的memcpy到新的上
94
        if (cache) {
95
            memcpy(ptr, obj, cache->buffer_size);
96
            easy_mem_cache_free(cache, obj);
97
        }
98

99
        return ptr;
100
        // malloc
101
    } else {
102
        cache = easy_mem_cache_size(size);
103
        return (cache ? easy_mem_cache_alloc(cache) : malloc(size));
104
    }
105
}
106

107
// 分配
108
void *easy_mem_cache_alloc(easy_mem_cache_t *cache)
109
{
110
    easy_list_t             *entry;
111
    easy_mem_slab_t         *slab;
112
    void                    *obj;
113

114
    obj = NULL;
115
    easy_spin_lock(&cache->lock);
116
    entry = cache->slabs_partial.next;
117

118
    if (entry == &cache->slabs_partial) {
119
        entry = cache->slabs_free.next;
120

121
        if (entry == &cache->slabs_free) {
122
            goto grow_done;
123
        }
124
    }
125

126
    // slab
127
    slab = easy_list_entry(entry, easy_mem_slab_t, list);
128
    obj = easy_mem_slab_get_obj(cache, slab);
129

130
    /* move slab to correct slab list */
131
    easy_list_del(&slab->list);
132

133
    if (slab->free == EASY_MEM_POS_END) {
134
        easy_list_add_head(&slab->list, &cache->slabs_full);
135
    } else {
136
        easy_list_add_head(&slab->list, &cache->slabs_partial);
137
    }
138

139
grow_done:
140
    easy_spin_unlock(&cache->lock);
141

142
    if (obj == NULL) obj = easy_mem_cache_grow(cache);
143

144
    return obj;
145
}
146

147
// 释放
148
void easy_mem_cache_free(easy_mem_cache_t *cache, void *obj)
149
{
150
    easy_mem_slab_t         *slab;
151

152
    easy_spin_lock(&cache->lock);
153
    slab = easy_mem_virt_to_slab(cache->order, obj);
154
    easy_mem_slab_put_obj(cache, slab, obj);
155

156
    // no use
157
    easy_list_del(&slab->list);
158

159
    if (slab->inuse == 0) {
160
        if (cache->free_objects > cache->free_limit) {
161
            cache->free_objects -= cache->num;
162
            slab->mem = NULL; // free mem
163
        } else {
164
            easy_list_add_head(&slab->list, &cache->slabs_free);
165
        }
166
    } else {
167
        easy_list_add_tail(&slab->list, &cache->slabs_partial);
168
    }
169

170
    easy_spin_unlock(&cache->lock);
171

172
    if (slab->mem == NULL) {
173
        easy_spin_lock(&easy_mem_mgr_var.lock);
174
        easy_mem_free_pages(easy_mem_mgr_var.zone, (easy_mem_page_t *)slab);
175
        easy_spin_unlock(&easy_mem_mgr_var.lock);
176
    }
177
}
178

179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
easy_mem_cache_t *easy_mem_cache_create(int buffer_size)
181
{
182
    easy_mem_cache_t        *cache = NULL;
183
    int                     order, size, left_over, num;
184

185
    easy_spin_lock(&easy_mem_mgr_var.lock);
186

187
    if (easy_mem_mgr_var.cache_num < easy_mem_mgr_var.cache_max_num) {
188
        cache = easy_mem_mgr_var.caches + easy_mem_mgr_var.cache_num;
189
        memset(cache, 0, sizeof(easy_mem_cache_t));
190

191
        // 计算slab_size大小
192
        left_over = 0;
193

194
        for (order = 0; order <= EASY_MEM_MAX_ORDER; order++) {
195
            size = (EASY_MEM_PAGE_SIZE << order);
196
            num = (size - sizeof(easy_mem_slab_t)) / (buffer_size + sizeof(uint16_t));
197
            left_over = size - num * buffer_size - sizeof(easy_mem_slab_t);
198
            cache->num = num;
199
            cache->order = order;
200

201
            if (left_over * 4 <= size) break;
202
        }
203

204
        cache->buffer_size = buffer_size;
205
        cache->offset = (size - cache->num * buffer_size);
206
        cache->free_limit = cache->num * 2;
207
        cache->free_objects = 0;
208
        cache->idx = easy_mem_mgr_var.cache_num;
209
        easy_list_init(&cache->slabs_full);
210
        easy_list_init(&cache->slabs_partial);
211
        easy_list_init(&cache->slabs_free);
212

213
        easy_mem_mgr_var.cache_num ++;
214
    }
215

216
    easy_spin_unlock(&easy_mem_mgr_var.lock);
217

218
    return cache;
219
}
220

221
///////////////////////////////////////////////////////////////////////////////////////////////////
222
static void *easy_mem_slab_get_obj(easy_mem_cache_t *cache, easy_mem_slab_t *slab)
223
{
224
    void                    *obj;
225
    uint16_t                next;
226

227
    obj = slab->mem + cache->buffer_size * slab->free;
228
    slab->inuse ++;
229
    next = slab->next_pos[slab->free];
230
    slab->free = next;
231

232
    return obj;
233
}
234

235
static void *easy_mem_cache_grow(easy_mem_cache_t *cache)
236
{
237
    easy_mem_zone_t         *z;
238
    easy_mem_slab_t         *slab;
239
    void                    *obj;
240
    unsigned char           *ptr;
241
    unsigned long           page_idx;
242
    uint32_t                i;
243

244
    z = easy_mem_mgr_var.zone;
245
    easy_spin_lock(&easy_mem_mgr_var.lock);
246
    slab = (easy_mem_slab_t *)easy_mem_alloc_pages(z, cache->order);
247
    easy_spin_unlock(&easy_mem_mgr_var.lock);
248

249
    // 分配不出来
250
    if (slab == NULL)
251
        return NULL;
252

253
    // init
254
    slab->mem = (unsigned char *)slab + cache->offset;
255
    slab->inuse = 0;
256
    slab->free = 0;
257
    slab->cache_idx = cache->idx;
258

259
    // set page flags
260
    if (cache->buffer_size > EASY_MEM_PAGE_SIZE) {
261
        ptr = (unsigned char *)slab->mem;
262

263
        for (i = 0; i < cache->num; i++) {
264
            page_idx = (ptr - z->mem_start) >> EASY_MEM_PAGE_SHIFT;
265
            z->page_flags[page_idx] = (0x80 | cache->order);
266
            ptr += cache->buffer_size;
267
        }
268
    } else {
269
        page_idx = ((unsigned char *)slab - z->mem_start) >> EASY_MEM_PAGE_SHIFT;
270
        memset(z->page_flags + page_idx, (0x80 | cache->order), (1 << cache->order));
271
    }
272

273
    // num
274
    for (i = 0; i < cache->num; i++) {
275
        slab->next_pos[i] = i + 1;
276
    }
277

278
    slab->next_pos[i - 1] = EASY_MEM_POS_END;
279
    cache->free_objects += cache->num;
280

281
    // 分配
282
    obj = easy_mem_slab_get_obj(cache, slab);
283

284
    easy_spin_lock(&cache->lock);
285

286
    if (slab->free == EASY_MEM_POS_END) {
287
        easy_list_add_head(&slab->list, &cache->slabs_full);
288
    } else {
289
        easy_list_add_head(&slab->list, &cache->slabs_partial);
290
    }
291

292
    easy_spin_unlock(&cache->lock);
293

294
    return obj;
295
}
296

297
// 根据obj定位出slab的位置
298
static inline easy_mem_slab_t *easy_mem_virt_to_slab(int order, const void *obj)
299
{
300
    unsigned long           a = (1 << (EASY_MEM_PAGE_SHIFT + order));
301
    return (easy_mem_slab_t *)(((unsigned long)obj) & ~(a - 1));
302
}
303

304
static void easy_mem_slab_put_obj(easy_mem_cache_t *cache, easy_mem_slab_t *slab, void *obj)
305
{
306
    uint16_t                idx;
307

308
    idx = (unsigned)((unsigned char *)obj - slab->mem) / cache->buffer_size;
309
    slab->next_pos[idx] = slab->free;
310
    slab->free = idx;
311
    slab->inuse--;
312
}
313

314
static inline easy_mem_cache_t *easy_mem_get_cache(unsigned char *obj)
315
{
316
    int                     order;
317
    easy_mem_slab_t         *slab;
318

319
    if (obj < easy_mem_mgr_var.zone->mem_start || obj >= easy_mem_mgr_var.zone->mem_end)
320
        return NULL;
321

322
    // order
323
    order = (obj - easy_mem_mgr_var.zone->mem_start) >> EASY_MEM_PAGE_SHIFT;
324
    order = (easy_mem_mgr_var.zone->page_flags[order] & 0x0f);
325
    slab = easy_mem_virt_to_slab(order, obj);
326
    return &easy_mem_mgr_var.caches[slab->cache_idx];
327
}
328

329
static inline easy_mem_cache_t *easy_mem_cache_size(uint32_t size)
330
{
331
    int                     flag, start, mid, end;
332

333
    start = 0;
334
    mid = 1;
335
    end = easy_mem_mgr_var.cache_num - 1;
336

337
    // 大于最大
338
    if (size > easy_mem_mgr_var.caches[end].buffer_size)
339
        return NULL;
340

341
    while (start != end) {
342
        mid = ((start + end) >> 1);
343
        flag = easy_mem_mgr_var.caches[mid].buffer_size - size;
344

345
        if (flag > 0)
346
            end = mid;
347
        else if (flag < 0)
348
            start = mid + 1;
349
        else {
350
            start = mid;
351
            break;
352
        }
353
    }
354

355
    return &easy_mem_mgr_var.caches[start];
356
}
357

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

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

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

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