OrocosComponentLibrary  2.7.0
tlsf_rtt.c
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 }