OrocosComponentLibrary  2.8.3
tlsf_rtt.c
1 
2 #include <stddef.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 
6 #include "tlsf.h"
7 #include "tlsf_rtt.h"
8 
9 #define RTL_TLSF_DEBUG 1
10 
11 #define DEBUG_TLSF_ALLOC (1<<0)
12 #define DEBUG_TLSF_FREE (1<<1)
13 #define DEBUG_TLSF_TRACE (1<<20)
14 
15 #ifdef RTL_TLSF_DEBUG
16 # define _DBG(x, mask, fmt, args...) do{ if (mask & x) printf("%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
17 #else
18 # define _DBG(x, mask, fmt, args...) do { } while(0);
19 #endif
20 
21 #define TLSF_POOL_MIN_SIZE 1*1014*1024
22 
23 /* create a memory pool of sz and initialize it for use with TLSF */
24 int tlsf_rtt_init_mp(struct lua_tlsf_info *tlsf_inf, size_t sz)
25 {
26  tlsf_inf->L = NULL;
27  tlsf_inf->mask = 0;
28  tlsf_inf->pool2 = NULL;
29  tlsf_inf->total_mem = 0;
30 
31  if(sz < TLSF_POOL_MIN_SIZE) {
32  fprintf(stderr, "error: requested tlsf pool size (0x%lx) too small\n", (unsigned long) sz);
33  goto fail;
34  }
35 
36  tlsf_inf->pool = malloc(sz);
37 
38  if(!tlsf_inf->pool) {
39  fprintf(stderr, "error failed to allocate: 0x%lx bytes\n", (unsigned long) sz);
40  goto fail;
41  }
42 
43  tlsf_inf->total_mem = rtl_init_memory_pool(sz, tlsf_inf->pool);
44  return 0;
45  fail:
46  return -1;
47 }
48 
49 /* cleanup mempool */
50 void tlsf_rtt_free_mp(struct lua_tlsf_info *tlsf_inf)
51 {
52  rtl_destroy_memory_pool(tlsf_inf->pool);
53  free(tlsf_inf->pool);
54 
55  if(tlsf_inf->pool2)
56  free(tlsf_inf->pool2);
57 }
58 
59 /* this hook will print a backtrace and reset itself */
60 static void tlsf_trace_hook(lua_State *L, lua_Debug *ar)
61 {
62  (void)ar;
63  lua_sethook(L, tlsf_trace_hook, 0, 0);
64  luaL_error(L, "memory allocation in TLSF trace mode");
65 }
66 
67 /* tlsf based Lua allocator */
68 void* tlsf_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
69 {
70  (void)osize;
71  struct lua_tlsf_info *tlsf_inf = (struct lua_tlsf_info*) ud;
72 
73  if (nsize == 0) {
74  _DBG(DEBUG_TLSF_FREE, tlsf_inf->mask, "freeing 0x%lx, osize=%lu, nsize=%lu",
75  (unsigned long) ptr, (unsigned long) osize, (unsigned long) nsize);
76  rtl_free_ex(ptr, tlsf_inf->pool);
77  return NULL;
78  } else {
79  if(DEBUG_TLSF_TRACE & tlsf_inf->mask) {
80  lua_sethook(tlsf_inf->L, tlsf_trace_hook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, 1);
81  }
82  _DBG(DEBUG_TLSF_ALLOC, tlsf_inf->mask, "allocating 0x%lx, osize=%lu, nsize=%lu",
83  (unsigned long) ptr, (unsigned long) osize, (unsigned long) nsize);
84  return rtl_realloc_ex(ptr, nsize, tlsf_inf->pool);
85  }
86 }
87 
88 int tlsf_rtt_incmem(struct lua_tlsf_info *tlsf_inf, size_t sz)
89 {
90  if(tlsf_inf->pool2 != NULL)
91  luaL_error(tlsf_inf->L, "tlsf_rtt_incmem: region already increased, (increasing cur. only possible once)");
92 
93  if((tlsf_inf->pool2 = malloc(sz)) == NULL)
94  luaL_error(tlsf_inf->L, "tlsf_rtt_incmem: failed to increase memory by %d bytes. Out of mem.");
95 
96  tlsf_inf->total_mem += rtl_add_new_area(tlsf_inf->pool2, sz, tlsf_inf->pool);
97 
98  return 0;
99 }
100 
101 /* store and retrieve the tlsf_info in the registry
102  * this is required for the enabling and disabling
103  * trace functions
104  */
105 void set_context_tlsf_info(struct lua_tlsf_info* tlsf_inf)
106 {
107  lua_pushstring(tlsf_inf->L, "tlsf_info");
108  lua_pushlightuserdata(tlsf_inf->L, tlsf_inf);
109  lua_rawset(tlsf_inf->L, LUA_REGISTRYINDEX);
110 }
111 
112 struct lua_tlsf_info* get_context_tlsf_info(lua_State *L)
113 {
114  lua_pushstring(L, "tlsf_info");
115  lua_rawget(L, LUA_REGISTRYINDEX);
116  return (struct lua_tlsf_info*) lua_touserdata(L, -1);
117 }
118 
119 static int tlsf_trace(lua_State *L)
120 {
121  int argc, enable, ret;
122  struct lua_tlsf_info *tlsf_inf = get_context_tlsf_info(L);
123  ret = 0;
124  argc = lua_gettop(L);
125 
126  if(argc == 0) {
127  lua_pushboolean(L, tlsf_inf->mask & DEBUG_TLSF_TRACE);
128  ret = 1;
129  goto out;
130  }
131 
132  enable = lua_toboolean(L, 1);
133 
134  if(enable) {
135  tlsf_inf->mask |= DEBUG_TLSF_TRACE;
136  } else {
137  lua_sethook(L, tlsf_trace_hook, 0, 1);
138  tlsf_inf->mask &= ~DEBUG_TLSF_TRACE;
139  }
140 
141 out:
142  return ret;
143 }
144 
145 static int tlsf_warn(lua_State *L)
146 {
147  int argc, enable, ret;
148  struct lua_tlsf_info *tlsf_inf = get_context_tlsf_info(L);
149  ret = 0;
150  argc = lua_gettop(L);
151 
152  if(argc == 0) {
153  lua_pushboolean(L, tlsf_inf->mask & (DEBUG_TLSF_ALLOC | DEBUG_TLSF_FREE));
154  ret = 1;
155  goto out;
156  }
157 
158  enable = lua_toboolean(L, 1);
159 
160  if(enable)
161  tlsf_inf->mask |= DEBUG_TLSF_ALLOC | DEBUG_TLSF_FREE;
162  else
163  tlsf_inf->mask &= ~(DEBUG_TLSF_ALLOC | DEBUG_TLSF_FREE);
164  out:
165  return ret;
166 }
167 
168 static int tlsf_stats(lua_State *L)
169 {
170  struct lua_tlsf_info *tlsf_inf = get_context_tlsf_info(L);
171 
172  lua_pushinteger(L, rtl_get_used_size(tlsf_inf->pool));
173  lua_pushinteger(L, rtl_get_max_size(tlsf_inf->pool));
174  lua_pushinteger(L, tlsf_inf->total_mem);
175  return 3;
176 }
177 
178 static const struct luaL_Reg tlsf_f [] = {
179  {"stats", tlsf_stats },
180  {"warn", tlsf_warn },
181  {"trace", tlsf_trace },
182  {NULL, NULL}
183 };
184 
185 void register_tlsf_api(lua_State *L)
186 {
187  luaL_register(L, "tlsf", tlsf_f);
188 }