$search
00001 00002 #include <stddef.h> 00003 #include <stdio.h> 00004 #include <stdlib.h> 00005 00006 #include "tlsf.h" 00007 #include "tlsf_rtt.h" 00008 00009 #define RTL_TLSF_DEBUG 1 00010 00011 #define DEBUG_TLSF_ALLOC (1<<0) 00012 #define DEBUG_TLSF_FREE (1<<1) 00013 #define DEBUG_TLSF_TRACE (1<<20) 00014 00015 #ifdef RTL_TLSF_DEBUG 00016 # define _DBG(x, mask, fmt, args...) do{ if (mask & x) printf("%s: " fmt "\n", __FUNCTION__, ##args); } while(0); 00017 #else 00018 # define _DBG(x, mask, fmt, args...) do { } while(0); 00019 #endif 00020 00021 #define TLSF_POOL_MIN_SIZE 1*1014*1024 00022 00023 /* create a memory pool of sz and initialize it for use with TLSF */ 00024 int tlsf_rtt_init_mp(struct lua_tlsf_info *tlsf_inf, size_t sz) 00025 { 00026 tlsf_inf->L = NULL; 00027 tlsf_inf->mask = 0; 00028 tlsf_inf->pool2 = NULL; 00029 tlsf_inf->total_mem = 0; 00030 00031 if(sz < TLSF_POOL_MIN_SIZE) { 00032 fprintf(stderr, "error: requested tlsf pool size (0x%lx) too small\n", (unsigned long) sz); 00033 goto fail; 00034 } 00035 00036 tlsf_inf->pool = malloc(sz); 00037 00038 if(!tlsf_inf->pool) { 00039 fprintf(stderr, "error failed to allocate: 0x%lx bytes\n", (unsigned long) sz); 00040 goto fail; 00041 } 00042 00043 tlsf_inf->total_mem = rtl_init_memory_pool(sz, tlsf_inf->pool); 00044 return 0; 00045 fail: 00046 return -1; 00047 } 00048 00049 /* cleanup mempool */ 00050 void tlsf_rtt_free_mp(struct lua_tlsf_info *tlsf_inf) 00051 { 00052 rtl_destroy_memory_pool(tlsf_inf->pool); 00053 free(tlsf_inf->pool); 00054 00055 if(tlsf_inf->pool2) 00056 free(tlsf_inf->pool2); 00057 } 00058 00059 /* this hook will print a backtrace and reset itself */ 00060 static void tlsf_trace_hook(lua_State *L, lua_Debug *ar) 00061 { 00062 (void)ar; 00063 lua_sethook(L, tlsf_trace_hook, 0, 0); 00064 luaL_error(L, "memory allocation in TLSF trace mode"); 00065 } 00066 00067 /* tlsf based Lua allocator */ 00068 void* tlsf_alloc (void *ud, void *ptr, size_t osize, size_t nsize) 00069 { 00070 (void)osize; 00071 struct lua_tlsf_info *tlsf_inf = (struct lua_tlsf_info*) ud; 00072 00073 if (nsize == 0) { 00074 _DBG(DEBUG_TLSF_FREE, tlsf_inf->mask, "freeing 0x%lx, osize=%lu, nsize=%lu", 00075 (unsigned long) ptr, (unsigned long) osize, (unsigned long) nsize); 00076 rtl_free_ex(ptr, tlsf_inf->pool); 00077 return NULL; 00078 } else { 00079 if(DEBUG_TLSF_TRACE & tlsf_inf->mask) { 00080 lua_sethook(tlsf_inf->L, tlsf_trace_hook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, 1); 00081 } 00082 _DBG(DEBUG_TLSF_ALLOC, tlsf_inf->mask, "allocating 0x%lx, osize=%lu, nsize=%lu", 00083 (unsigned long) ptr, (unsigned long) osize, (unsigned long) nsize); 00084 return rtl_realloc_ex(ptr, nsize, tlsf_inf->pool); 00085 } 00086 } 00087 00088 int tlsf_rtt_incmem(struct lua_tlsf_info *tlsf_inf, size_t sz) 00089 { 00090 if(tlsf_inf->pool2 != NULL) 00091 luaL_error(tlsf_inf->L, "tlsf_rtt_incmem: region already increased, (increasing cur. only possible once)"); 00092 00093 if((tlsf_inf->pool2 = malloc(sz)) == NULL) 00094 luaL_error(tlsf_inf->L, "tlsf_rtt_incmem: failed to increase memory by %d bytes. Out of mem."); 00095 00096 tlsf_inf->total_mem += rtl_add_new_area(tlsf_inf->pool2, sz, tlsf_inf->pool); 00097 00098 return 0; 00099 } 00100 00101 /* store and retrieve the tlsf_info in the registry 00102 * this is required for the enabling and disabling 00103 * trace functions 00104 */ 00105 void set_context_tlsf_info(struct lua_tlsf_info* tlsf_inf) 00106 { 00107 lua_pushstring(tlsf_inf->L, "tlsf_info"); 00108 lua_pushlightuserdata(tlsf_inf->L, tlsf_inf); 00109 lua_rawset(tlsf_inf->L, LUA_REGISTRYINDEX); 00110 } 00111 00112 struct lua_tlsf_info* get_context_tlsf_info(lua_State *L) 00113 { 00114 lua_pushstring(L, "tlsf_info"); 00115 lua_rawget(L, LUA_REGISTRYINDEX); 00116 return (struct lua_tlsf_info*) lua_touserdata(L, -1); 00117 } 00118 00119 static int tlsf_trace(lua_State *L) 00120 { 00121 int argc, enable, ret; 00122 struct lua_tlsf_info *tlsf_inf = get_context_tlsf_info(L); 00123 ret = 0; 00124 argc = lua_gettop(L); 00125 00126 if(argc == 0) { 00127 lua_pushboolean(L, tlsf_inf->mask & DEBUG_TLSF_TRACE); 00128 ret = 1; 00129 goto out; 00130 } 00131 00132 enable = lua_toboolean(L, 1); 00133 00134 if(enable) { 00135 tlsf_inf->mask |= DEBUG_TLSF_TRACE; 00136 } else { 00137 lua_sethook(L, tlsf_trace_hook, 0, 1); 00138 tlsf_inf->mask &= ~DEBUG_TLSF_TRACE; 00139 } 00140 00141 out: 00142 return ret; 00143 } 00144 00145 static int tlsf_warn(lua_State *L) 00146 { 00147 int argc, enable, ret; 00148 struct lua_tlsf_info *tlsf_inf = get_context_tlsf_info(L); 00149 ret = 0; 00150 argc = lua_gettop(L); 00151 00152 if(argc == 0) { 00153 lua_pushboolean(L, tlsf_inf->mask & (DEBUG_TLSF_ALLOC | DEBUG_TLSF_FREE)); 00154 ret = 1; 00155 goto out; 00156 } 00157 00158 enable = lua_toboolean(L, 1); 00159 00160 if(enable) 00161 tlsf_inf->mask |= DEBUG_TLSF_ALLOC | DEBUG_TLSF_FREE; 00162 else 00163 tlsf_inf->mask &= ~(DEBUG_TLSF_ALLOC | DEBUG_TLSF_FREE); 00164 out: 00165 return ret; 00166 } 00167 00168 static int tlsf_stats(lua_State *L) 00169 { 00170 struct lua_tlsf_info *tlsf_inf = get_context_tlsf_info(L); 00171 00172 lua_pushinteger(L, rtl_get_used_size(tlsf_inf->pool)); 00173 lua_pushinteger(L, rtl_get_max_size(tlsf_inf->pool)); 00174 lua_pushinteger(L, tlsf_inf->total_mem); 00175 return 3; 00176 } 00177 00178 static const struct luaL_Reg tlsf_f [] = { 00179 {"stats", tlsf_stats }, 00180 {"warn", tlsf_warn }, 00181 {"trace", tlsf_trace }, 00182 {NULL, NULL} 00183 }; 00184 00185 void register_tlsf_api(lua_State *L) 00186 { 00187 luaL_register(L, "tlsf", tlsf_f); 00188 }