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