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 * 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 * 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 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 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 174 MPGetFreeChunks(mem_pool_t mp) 175 { 176 return mp->mp_free_chunks; 177 } 178 /*----------------------------------------------------------------------------*/ 179 uint32_t 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 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