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
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
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
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
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
00102
00103
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 }