#include #include #include #include #include #include #include #ifdef HUGETABLE #include #endif #include "debug.h" #include "memory_mgt.h" //#define SYS_MALLOC typedef struct tag_mem_chunk { int mc_free_chunks; struct tag_mem_chunk *mc_next; } mem_chunk; typedef mem_chunk *mem_chunk_t; #ifdef HUGETABLE typedef enum { MEM_NORMAL, MEM_HUGEPAGE}; #endif typedef struct mem_pool { u_char *mp_startptr; /* start pointer */ mem_chunk_t mp_freeptr; /* pointer to the start memory chunk */ int mp_free_chunks; /* number of total free chunks */ int mp_total_chunks; /* number of total free chunks */ int mp_chunk_size; /* chunk size in bytes */ int mp_type; } mem_pool; /*----------------------------------------------------------------------------*/ mem_pool * MPCreate(int chunk_size, size_t total_size, int is_hugepage) { mem_pool_t mp; if (chunk_size < sizeof(mem_chunk)) { TRACE_ERROR("The chunk size should be larger than %lu. current: %d\n", sizeof(mem_chunk), chunk_size); return NULL; } if (chunk_size % 4 != 0) { TRACE_ERROR("The chunk size should be multiply of 4!\n"); return NULL; } //assert(chunk_size <= 2*1024*1024); if ((mp = calloc(1, sizeof(mem_pool))) == NULL) { perror("calloc failed"); exit(0); } mp->mp_type = is_hugepage; mp->mp_chunk_size = chunk_size; mp->mp_free_chunks = ((total_size + (chunk_size -1))/chunk_size); mp->mp_total_chunks = mp->mp_free_chunks; total_size = chunk_size * ((size_t)mp->mp_free_chunks); #ifndef SYS_MALLOC /* allocate the big memory chunk */ #ifdef HUGETABLE if (is_hugepage == MEM_HUGEPAGE) { mp->mp_startptr = get_huge_pages(total_size, NULL); if (!mp->mp_startptr) { TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size); assert(0); free(mp); return (NULL); } } else { #endif int res = posix_memalign((void **)&mp->mp_startptr, getpagesize(), total_size); if (res != 0) { TRACE_ERROR("posix_memalign failed, size=%ld\n", total_size); assert(0); free(mp); return (NULL); } #ifdef HUGETABLE } #endif /* try mlock only for superuser */ if (geteuid() == 0) { if (mlock(mp->mp_startptr, total_size) < 0) TRACE_ERROR("m_lock failed, size=%ld\n", total_size); } mp->mp_freeptr = (mem_chunk_t)mp->mp_startptr; mp->mp_freeptr->mc_free_chunks = mp->mp_free_chunks; mp->mp_freeptr->mc_next = NULL; #endif // SYS_MALLOC return mp; } /*----------------------------------------------------------------------------*/ void * MPAllocateChunk(mem_pool_t mp) { #ifdef SYS_MALLOC return malloc(mp->mp_chunk_size); #else mem_chunk_t p = mp->mp_freeptr; if (mp->mp_free_chunks == 0) { TRACE_INFO("mp_free_chunks: %u\n", mp->mp_free_chunks); return (NULL); } assert(p->mc_free_chunks > 0 && p->mc_free_chunks <= p->mc_free_chunks); p->mc_free_chunks--; mp->mp_free_chunks--; if (p->mc_free_chunks) { /* move right by one chunk */ mp->mp_freeptr = (mem_chunk_t)((u_char *)p + mp->mp_chunk_size); mp->mp_freeptr->mc_free_chunks = p->mc_free_chunks; mp->mp_freeptr->mc_next = p->mc_next; } else { mp->mp_freeptr = p->mc_next; } return p; #endif } /*----------------------------------------------------------------------------*/ void MPFreeChunk(mem_pool_t mp, void *p) { #ifdef SYS_MALLOC return free(p); #else mem_chunk_t mcp = (mem_chunk_t)p; // assert((u_char*)p >= mp->mp_startptr && // (u_char *)p < mp->mp_startptr + mp->mp_total_size); assert(((u_char *)p - mp->mp_startptr) % mp->mp_chunk_size == 0); // assert(*((u_char *)p + (mp->mp_chunk_size-1)) == 'a'); // *((u_char *)p + (mp->mp_chunk_size-1)) = 'f'; mcp->mc_free_chunks = 1; mcp->mc_next = mp->mp_freeptr; mp->mp_freeptr = mcp; mp->mp_free_chunks++; #endif } /*----------------------------------------------------------------------------*/ void MPDestroy(mem_pool_t mp) { #ifdef HUGETABLE if(mp->mp_type == MEM_HUGEPAGE) { free_huge_pages(mp->mp_startptr); } else { #endif free(mp->mp_startptr); #ifdef HUGETABLE } #endif free(mp); } /*----------------------------------------------------------------------------*/ int MPGetFreeChunks(mem_pool_t mp) { return mp->mp_free_chunks; } /*----------------------------------------------------------------------------*/ uint32_t MPIsDanger(mem_pool_t mp) { #define DANGER_THREASHOLD 0.95 #define SAFE_THREASHOLD 0.90 uint32_t danger_num = mp->mp_total_chunks * DANGER_THREASHOLD; uint32_t safe_num = mp->mp_total_chunks * SAFE_THREASHOLD; if (danger_num < mp->mp_total_chunks - mp->mp_free_chunks) { return mp->mp_total_chunks - mp->mp_free_chunks - safe_num; } return 0; } /*----------------------------------------------------------------------------*/ uint32_t MPIsOverSafeline(mem_pool_t mp) { #define SAFELINE 0.90 uint32_t safe_num = mp->mp_total_chunks * SAFELINE; if (safe_num < mp->mp_total_chunks - mp->mp_free_chunks) { return 1; } return 0; } /*----------------------------------------------------------------------------*/