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