-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathmempool.c
134 lines (118 loc) · 3.01 KB
/
mempool.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
/*
* Copyright (c) 2014 Wu, Xingbo <wuxb45@gmail.com>
*
* All rights reserved. No warranty, explicit or implicit, provided.
*/
#define _GNU_SOURCE
#define _LARGEFILE64_SOURCE
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include "mempool.h"
#define MEMPOOL_UNIT (1024 * 1024 * 2)
struct Mempool {
bool using_mmap;
uint64_t pos;
uint64_t max;
uint8_t * space;
};
static const bool USING_MALLOC = false;
void *
huge_alloc(const uint64_t cap)
{
const size_t hcap = ((cap + MEMPOOL_UNIT - 1) / MEMPOOL_UNIT) * MEMPOOL_UNIT;
if (hcap != cap) return NULL;
if (USING_MALLOC) {
return aligned_alloc(MEMPOOL_UNIT, cap);
} else {
void * const m = mmap(NULL, cap, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
if (m == MAP_FAILED) {
void * const m2 = mmap(NULL, cap, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (m2 == MAP_FAILED) { return NULL; }
else { return m2; }
} else {
return m;
}
}
}
void
huge_free(void * const ptr, const uint64_t cap)
{
if (USING_MALLOC) {
free(ptr);
} else {
munmap(ptr, cap);
}
}
static bool
space_alloc_mmap(struct Mempool * const mempool, const size_t cap)
{
const size_t hcap = ((cap + MEMPOOL_UNIT - 1) / MEMPOOL_UNIT) * MEMPOOL_UNIT;
assert(hcap >= cap);
void * const m = huge_alloc(hcap);
// MAP_UNINITIALIZED need kernel configuration: CONFIG_MMAP_ALLOW_UNINITIALIZED. it's unsafe
if (m) {
mempool->using_mmap = true;
mempool->space = m;
mempool->max = (uint64_t)hcap;
return true;
} else {
mempool->using_mmap = false;
mempool->space = (typeof(mempool->space))malloc(cap);
mempool->max = (uint64_t)cap;
return (mempool->space)?true:false;
}
}
struct Mempool *
mempool_new(const size_t cap)
{
struct Mempool * const p = (typeof(p))malloc(sizeof(*p));
if (p == NULL) { return NULL;}
p->pos = 0;
const bool r = space_alloc_mmap(p, cap);
if (r == false) {
free(p);
return NULL;
}
return p;
}
uint8_t *
mempool_alloc(struct Mempool * const p, const size_t cap)
{
const size_t hcap = ((cap + 8u) & (~7u));
if ((p == NULL) || ((p->pos + hcap) > p->max)) {
fprintf(stderr, "mempool_alloc() failed(1): pos: %lu, cap: %zu, max: %lu\n", p?p->pos:~0, cap, p?p->max:~0);
fflush(stderr);
return NULL;
}
const uint64_t pos = __sync_fetch_and_add(&(p->pos), hcap);
if ((pos + hcap) > p->max) {
fprintf(stderr, "mempool_alloc() failed(2): pos: %lu, cap: %zu, max: %lu\n", p->pos, cap, p->max);
fflush(stderr);
return NULL;
}
uint8_t * const r = p->space + pos;
return r;
}
void
mempool_free(struct Mempool * const p)
{
if (p->using_mmap) {
huge_free(p->space, p->max);
} else {
free(p->space);
}
free(p);
}
void
mempool_show(struct Mempool * const p)
{
fprintf(stdout, "mempool: pos: %lu, max: %lu\n", p->pos, p->max);
}