1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <sys/mman.h>
7 #include <unistd.h>
8 #ifdef HUGETABLE
9 #include <hugetlbfs.h>
10 #endif
11 #include "debug.h"
12 #include "memory_mgt.h"
13 //#define SYS_MALLOC
14
15 typedef struct tag_mem_chunk
16 {
17 int mc_free_chunks;
18 struct tag_mem_chunk *mc_next;
19 } mem_chunk;
20
21 typedef mem_chunk *mem_chunk_t;
22
23 #ifdef HUGETABLE
24 typedef enum { MEM_NORMAL, MEM_HUGEPAGE};
25 #endif
26
27 typedef struct mem_pool
28 {
29 u_char *mp_startptr; /* start pointer */
30 mem_chunk_t mp_freeptr; /* pointer to the start memory chunk */
31 int mp_free_chunks; /* number of total free chunks */
32 int mp_total_chunks; /* number of total free chunks */
33 int mp_chunk_size; /* chunk size in bytes */
34 int mp_type;
35
36 } mem_pool;
37
38 /*----------------------------------------------------------------------------*/
39 mem_pool *
MPCreate(int chunk_size,size_t total_size,int is_hugepage)40 MPCreate(int chunk_size, size_t total_size, int is_hugepage)
41 {
42 mem_pool_t mp;
43
44 if (chunk_size < sizeof(mem_chunk)) {
45 TRACE_ERROR("The chunk size should be larger than %lu. current: %d\n",
46 sizeof(mem_chunk), chunk_size);
47 return NULL;
48 }
49 if (chunk_size % 4 != 0) {
50 TRACE_ERROR("The chunk size should be multiply of 4!\n");
51 return NULL;
52 }
53
54 //assert(chunk_size <= 2*1024*1024);
55
56 if ((mp = calloc(1, sizeof(mem_pool))) == NULL) {
57 perror("calloc failed");
58 exit(0);
59 }
60 mp->mp_type = is_hugepage;
61 mp->mp_chunk_size = chunk_size;
62 mp->mp_free_chunks = ((total_size + (chunk_size -1))/chunk_size);
63 mp->mp_total_chunks = mp->mp_free_chunks;
64 total_size = chunk_size * ((size_t)mp->mp_free_chunks);
65
66 #ifndef SYS_MALLOC
67
68 /* allocate the big memory chunk */
69 #ifdef HUGETABLE
70 if (is_hugepage == MEM_HUGEPAGE) {
71 mp->mp_startptr = get_huge_pages(total_size, NULL);
72 if (!mp->mp_startptr) {
73 TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size);
74 assert(0);
75 free(mp);
76 return (NULL);
77 }
78 } else {
79 #endif
80 int res = posix_memalign((void **)&mp->mp_startptr, getpagesize(), total_size);
81 if (res != 0) {
82 TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size);
83 assert(0);
84 free(mp);
85 return (NULL);
86 }
87 #ifdef HUGETABLE
88 }
89 #endif
90
91 /* try mlock only for superuser */
92 if (geteuid() == 0) {
93 if (mlock(mp->mp_startptr, total_size) < 0)
94 TRACE_ERROR("m_lock failed, size=%ld\n", total_size);
95 }
96
97 mp->mp_freeptr = (mem_chunk_t)mp->mp_startptr;
98 mp->mp_freeptr->mc_free_chunks = mp->mp_free_chunks;
99 mp->mp_freeptr->mc_next = NULL;
100
101 #endif // SYS_MALLOC
102
103 return mp;
104 }
105 /*----------------------------------------------------------------------------*/
106 void *
MPAllocateChunk(mem_pool_t mp)107 MPAllocateChunk(mem_pool_t mp)
108 {
109
110 #ifdef SYS_MALLOC
111 return malloc(mp->mp_chunk_size);
112 #else
113 mem_chunk_t p = mp->mp_freeptr;
114
115 if (mp->mp_free_chunks == 0) {
116 TRACE_INFO("mp_free_chunks: %u\n", mp->mp_free_chunks);
117 return (NULL);
118 }
119 assert(p->mc_free_chunks > 0 && p->mc_free_chunks <= p->mc_free_chunks);
120
121 p->mc_free_chunks--;
122 mp->mp_free_chunks--;
123 if (p->mc_free_chunks) {
124 /* move right by one chunk */
125 mp->mp_freeptr = (mem_chunk_t)((u_char *)p + mp->mp_chunk_size);
126 mp->mp_freeptr->mc_free_chunks = p->mc_free_chunks;
127 mp->mp_freeptr->mc_next = p->mc_next;
128 }
129 else {
130 mp->mp_freeptr = p->mc_next;
131 }
132
133 return p;
134 #endif
135 }
136 /*----------------------------------------------------------------------------*/
137 void
MPFreeChunk(mem_pool_t mp,void * p)138 MPFreeChunk(mem_pool_t mp, void *p)
139 {
140 #ifdef SYS_MALLOC
141 return free(p);
142 #else
143 mem_chunk_t mcp = (mem_chunk_t)p;
144
145 // assert((u_char*)p >= mp->mp_startptr &&
146 // (u_char *)p < mp->mp_startptr + mp->mp_total_size);
147 assert(((u_char *)p - mp->mp_startptr) % mp->mp_chunk_size == 0);
148 // assert(*((u_char *)p + (mp->mp_chunk_size-1)) == 'a');
149 // *((u_char *)p + (mp->mp_chunk_size-1)) = 'f';
150
151 mcp->mc_free_chunks = 1;
152 mcp->mc_next = mp->mp_freeptr;
153 mp->mp_freeptr = mcp;
154 mp->mp_free_chunks++;
155 #endif
156 }
157 /*----------------------------------------------------------------------------*/
158 void
MPDestroy(mem_pool_t mp)159 MPDestroy(mem_pool_t mp)
160 {
161 #ifdef HUGETABLE
162 if(mp->mp_type == MEM_HUGEPAGE) {
163 free_huge_pages(mp->mp_startptr);
164 } else {
165 #endif
166 free(mp->mp_startptr);
167 #ifdef HUGETABLE
168 }
169 #endif
170 free(mp);
171 }
172 /*----------------------------------------------------------------------------*/
173 int
MPGetFreeChunks(mem_pool_t mp)174 MPGetFreeChunks(mem_pool_t mp)
175 {
176 return mp->mp_free_chunks;
177 }
178 /*----------------------------------------------------------------------------*/
179 uint32_t
MPIsDanger(mem_pool_t mp)180 MPIsDanger(mem_pool_t mp)
181 {
182 #define DANGER_THREASHOLD 0.95
183 #define SAFE_THREASHOLD 0.90
184 uint32_t danger_num = mp->mp_total_chunks * DANGER_THREASHOLD;
185 uint32_t safe_num = mp->mp_total_chunks * SAFE_THREASHOLD;
186 if (danger_num < mp->mp_total_chunks - mp->mp_free_chunks) {
187 return mp->mp_total_chunks - mp->mp_free_chunks - safe_num;
188 }
189 return 0;
190 }
191 /*----------------------------------------------------------------------------*/
192 uint32_t
MPIsOverSafeline(mem_pool_t mp)193 MPIsOverSafeline(mem_pool_t mp)
194 {
195 #define SAFELINE 0.90
196 uint32_t safe_num = mp->mp_total_chunks * SAFELINE;
197 if (safe_num < mp->mp_total_chunks - mp->mp_free_chunks) {
198 return 1;
199 }
200 return 0;
201 }
202 /*----------------------------------------------------------------------------*/
203