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