176404edcSAsim Jamshed #include <stdio.h>
276404edcSAsim Jamshed #include <stdlib.h>
376404edcSAsim Jamshed #include <stdint.h>
476404edcSAsim Jamshed #include <string.h>
576404edcSAsim Jamshed #include <assert.h>
676404edcSAsim Jamshed #include <sys/mman.h>
776404edcSAsim Jamshed #include <unistd.h>
876404edcSAsim Jamshed #ifdef HUGETABLE
976404edcSAsim Jamshed #include <hugetlbfs.h>
1076404edcSAsim Jamshed #endif
1176404edcSAsim Jamshed #include "debug.h"
1276404edcSAsim Jamshed #include "memory_mgt.h"
1376404edcSAsim Jamshed //#define SYS_MALLOC
1476404edcSAsim Jamshed 
1576404edcSAsim Jamshed typedef struct tag_mem_chunk
1676404edcSAsim Jamshed {
1776404edcSAsim Jamshed 	int mc_free_chunks;
1876404edcSAsim Jamshed 	struct tag_mem_chunk *mc_next;
1976404edcSAsim Jamshed } mem_chunk;
2076404edcSAsim Jamshed 
2176404edcSAsim Jamshed typedef mem_chunk *mem_chunk_t;
2276404edcSAsim Jamshed 
2376404edcSAsim Jamshed #ifdef HUGETABLE
2476404edcSAsim Jamshed typedef enum { MEM_NORMAL, MEM_HUGEPAGE};
2576404edcSAsim Jamshed #endif
2676404edcSAsim Jamshed 
2776404edcSAsim Jamshed typedef struct mem_pool
2876404edcSAsim Jamshed {
2976404edcSAsim Jamshed 	u_char *mp_startptr;      /* start pointer */
3076404edcSAsim Jamshed 	mem_chunk_t mp_freeptr;   /* pointer to the start memory chunk */
3176404edcSAsim Jamshed 	int mp_free_chunks;       /* number of total free chunks */
3276404edcSAsim Jamshed 	int mp_total_chunks;       /* number of total free chunks */
3376404edcSAsim Jamshed 	int mp_chunk_size;        /* chunk size in bytes */
3476404edcSAsim Jamshed 	int mp_type;
3576404edcSAsim Jamshed 
3676404edcSAsim Jamshed } mem_pool;
3776404edcSAsim Jamshed 
3876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
3976404edcSAsim Jamshed 	mem_pool *
MPCreate(int chunk_size,size_t total_size,int is_hugepage)4076404edcSAsim Jamshed MPCreate(int chunk_size, size_t total_size, int is_hugepage)
4176404edcSAsim Jamshed {
4276404edcSAsim Jamshed 	mem_pool_t mp;
4376404edcSAsim Jamshed 
4476404edcSAsim Jamshed 	if (chunk_size < sizeof(mem_chunk)) {
4576404edcSAsim Jamshed 		TRACE_ERROR("The chunk size should be larger than %lu. current: %d\n",
4676404edcSAsim Jamshed 				sizeof(mem_chunk), chunk_size);
4776404edcSAsim Jamshed 		return NULL;
4876404edcSAsim Jamshed 	}
4976404edcSAsim Jamshed 	if (chunk_size % 4 != 0) {
5076404edcSAsim Jamshed 		TRACE_ERROR("The chunk size should be multiply of 4!\n");
5176404edcSAsim Jamshed 		return NULL;
5276404edcSAsim Jamshed 	}
5376404edcSAsim Jamshed 
5476404edcSAsim Jamshed 	//assert(chunk_size <= 2*1024*1024);
5576404edcSAsim Jamshed 
5676404edcSAsim Jamshed 	if ((mp = calloc(1, sizeof(mem_pool))) == NULL) {
5776404edcSAsim Jamshed 		perror("calloc failed");
5876404edcSAsim Jamshed 		exit(0);
5976404edcSAsim Jamshed 	}
6076404edcSAsim Jamshed 	mp->mp_type = is_hugepage;
6176404edcSAsim Jamshed 	mp->mp_chunk_size = chunk_size;
6276404edcSAsim Jamshed 	mp->mp_free_chunks = ((total_size + (chunk_size -1))/chunk_size);
6376404edcSAsim Jamshed 	mp->mp_total_chunks = mp->mp_free_chunks;
6476404edcSAsim Jamshed 	total_size = chunk_size * ((size_t)mp->mp_free_chunks);
6576404edcSAsim Jamshed 
6676404edcSAsim Jamshed #ifndef SYS_MALLOC
6776404edcSAsim Jamshed 
6876404edcSAsim Jamshed 	/* allocate the big memory chunk */
6976404edcSAsim Jamshed #ifdef HUGETABLE
7076404edcSAsim Jamshed 	if (is_hugepage == MEM_HUGEPAGE) {
7176404edcSAsim Jamshed 		mp->mp_startptr = get_huge_pages(total_size, NULL);
7276404edcSAsim Jamshed 		if (!mp->mp_startptr) {
7376404edcSAsim Jamshed 			TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size);
7476404edcSAsim Jamshed 			assert(0);
75*c6a5549bSAsim Jamshed 			free(mp);
7676404edcSAsim Jamshed 			return (NULL);
7776404edcSAsim Jamshed 		}
7876404edcSAsim Jamshed 	} else {
7976404edcSAsim Jamshed #endif
8076404edcSAsim Jamshed 		int res = posix_memalign((void **)&mp->mp_startptr, getpagesize(), total_size);
8176404edcSAsim Jamshed 		if (res != 0) {
8276404edcSAsim Jamshed 			TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size);
8376404edcSAsim Jamshed 			assert(0);
84*c6a5549bSAsim Jamshed 			free(mp);
8576404edcSAsim Jamshed 			return (NULL);
8676404edcSAsim Jamshed 		}
8776404edcSAsim Jamshed #ifdef HUGETABLE
8876404edcSAsim Jamshed 	}
8976404edcSAsim Jamshed #endif
9076404edcSAsim Jamshed 
9176404edcSAsim Jamshed 	/* try mlock only for superuser */
9276404edcSAsim Jamshed 	if (geteuid() == 0) {
9376404edcSAsim Jamshed 		if (mlock(mp->mp_startptr, total_size) < 0)
9476404edcSAsim Jamshed 			TRACE_ERROR("m_lock failed, size=%ld\n", total_size);
9576404edcSAsim Jamshed 	}
9676404edcSAsim Jamshed 
9776404edcSAsim Jamshed 	mp->mp_freeptr = (mem_chunk_t)mp->mp_startptr;
9876404edcSAsim Jamshed 	mp->mp_freeptr->mc_free_chunks = mp->mp_free_chunks;
9976404edcSAsim Jamshed 	mp->mp_freeptr->mc_next = NULL;
10076404edcSAsim Jamshed 
10176404edcSAsim Jamshed #endif // SYS_MALLOC
10276404edcSAsim Jamshed 
10376404edcSAsim Jamshed 	return mp;
10476404edcSAsim Jamshed }
10576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
10676404edcSAsim Jamshed 	void *
MPAllocateChunk(mem_pool_t mp)10776404edcSAsim Jamshed MPAllocateChunk(mem_pool_t mp)
10876404edcSAsim Jamshed {
10976404edcSAsim Jamshed 
11076404edcSAsim Jamshed #ifdef SYS_MALLOC
11176404edcSAsim Jamshed 	return malloc(mp->mp_chunk_size);
11276404edcSAsim Jamshed #else
11376404edcSAsim Jamshed 	mem_chunk_t p = mp->mp_freeptr;
11476404edcSAsim Jamshed 
11576404edcSAsim Jamshed 	if (mp->mp_free_chunks == 0)  {
11676404edcSAsim Jamshed 		TRACE_INFO("mp_free_chunks: %u\n", mp->mp_free_chunks);
11776404edcSAsim Jamshed 		return (NULL);
11876404edcSAsim Jamshed 	}
11976404edcSAsim Jamshed 	assert(p->mc_free_chunks > 0 && p->mc_free_chunks <= p->mc_free_chunks);
12076404edcSAsim Jamshed 
12176404edcSAsim Jamshed 	p->mc_free_chunks--;
12276404edcSAsim Jamshed 	mp->mp_free_chunks--;
12376404edcSAsim Jamshed 	if (p->mc_free_chunks) {
12476404edcSAsim Jamshed 		/* move right by one chunk */
12576404edcSAsim Jamshed 		mp->mp_freeptr = (mem_chunk_t)((u_char *)p + mp->mp_chunk_size);
12676404edcSAsim Jamshed 		mp->mp_freeptr->mc_free_chunks = p->mc_free_chunks;
12776404edcSAsim Jamshed 		mp->mp_freeptr->mc_next = p->mc_next;
12876404edcSAsim Jamshed 	}
12976404edcSAsim Jamshed 	else {
13076404edcSAsim Jamshed 		mp->mp_freeptr = p->mc_next;
13176404edcSAsim Jamshed 	}
13276404edcSAsim Jamshed 
13376404edcSAsim Jamshed 	return p;
13476404edcSAsim Jamshed #endif
13576404edcSAsim Jamshed }
13676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
13776404edcSAsim Jamshed 	void
MPFreeChunk(mem_pool_t mp,void * p)13876404edcSAsim Jamshed MPFreeChunk(mem_pool_t mp, void *p)
13976404edcSAsim Jamshed {
14076404edcSAsim Jamshed #ifdef SYS_MALLOC
14176404edcSAsim Jamshed 	return free(p);
14276404edcSAsim Jamshed #else
14376404edcSAsim Jamshed 	mem_chunk_t mcp = (mem_chunk_t)p;
14476404edcSAsim Jamshed 
14576404edcSAsim Jamshed 	//	assert((u_char*)p >= mp->mp_startptr &&
14676404edcSAsim Jamshed 	//		   (u_char *)p < mp->mp_startptr + mp->mp_total_size);
14776404edcSAsim Jamshed 	assert(((u_char *)p - mp->mp_startptr) % mp->mp_chunk_size == 0);
14876404edcSAsim Jamshed 	//	assert(*((u_char *)p + (mp->mp_chunk_size-1)) == 'a');
14976404edcSAsim Jamshed 	//	*((u_char *)p + (mp->mp_chunk_size-1)) = 'f';
15076404edcSAsim Jamshed 
15176404edcSAsim Jamshed 	mcp->mc_free_chunks = 1;
15276404edcSAsim Jamshed 	mcp->mc_next = mp->mp_freeptr;
15376404edcSAsim Jamshed 	mp->mp_freeptr = mcp;
15476404edcSAsim Jamshed 	mp->mp_free_chunks++;
15576404edcSAsim Jamshed #endif
15676404edcSAsim Jamshed }
15776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
15876404edcSAsim Jamshed 	void
MPDestroy(mem_pool_t mp)15976404edcSAsim Jamshed MPDestroy(mem_pool_t mp)
16076404edcSAsim Jamshed {
16176404edcSAsim Jamshed #ifdef HUGETABLE
16276404edcSAsim Jamshed 	if(mp->mp_type == MEM_HUGEPAGE) {
16376404edcSAsim Jamshed 		free_huge_pages(mp->mp_startptr);
16476404edcSAsim Jamshed 	} else {
16576404edcSAsim Jamshed #endif
16676404edcSAsim Jamshed 		free(mp->mp_startptr);
16776404edcSAsim Jamshed #ifdef HUGETABLE
16876404edcSAsim Jamshed 	}
16976404edcSAsim Jamshed #endif
17076404edcSAsim Jamshed 	free(mp);
17176404edcSAsim Jamshed }
17276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
17376404edcSAsim Jamshed 	int
MPGetFreeChunks(mem_pool_t mp)17476404edcSAsim Jamshed MPGetFreeChunks(mem_pool_t mp)
17576404edcSAsim Jamshed {
17676404edcSAsim Jamshed 	return mp->mp_free_chunks;
17776404edcSAsim Jamshed }
17876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
17976404edcSAsim Jamshed 	uint32_t
MPIsDanger(mem_pool_t mp)18076404edcSAsim Jamshed MPIsDanger(mem_pool_t mp)
18176404edcSAsim Jamshed {
18276404edcSAsim Jamshed #define DANGER_THREASHOLD 0.95
18376404edcSAsim Jamshed #define SAFE_THREASHOLD 0.90
18476404edcSAsim Jamshed 	uint32_t danger_num = mp->mp_total_chunks * DANGER_THREASHOLD;
18576404edcSAsim Jamshed 	uint32_t safe_num = mp->mp_total_chunks * SAFE_THREASHOLD;
18676404edcSAsim Jamshed 	if (danger_num < mp->mp_total_chunks - mp->mp_free_chunks) {
18776404edcSAsim Jamshed 		return mp->mp_total_chunks - mp->mp_free_chunks - safe_num;
18876404edcSAsim Jamshed 	}
18976404edcSAsim Jamshed 	return 0;
19076404edcSAsim Jamshed }
19176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
19276404edcSAsim Jamshed 	uint32_t
MPIsOverSafeline(mem_pool_t mp)19376404edcSAsim Jamshed MPIsOverSafeline(mem_pool_t mp)
19476404edcSAsim Jamshed {
19576404edcSAsim Jamshed #define SAFELINE 0.90
19676404edcSAsim Jamshed 	uint32_t safe_num = mp->mp_total_chunks * SAFELINE;
19776404edcSAsim Jamshed 	if (safe_num < mp->mp_total_chunks - mp->mp_free_chunks) {
19876404edcSAsim Jamshed 		return 1;
19976404edcSAsim Jamshed 	}
20076404edcSAsim Jamshed 	return 0;
20176404edcSAsim Jamshed }
20276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
203