1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-14 20:10:08 +03:00

Fixes #1791: Port Lua Bin Allocator to next:

* Bin Allocator
* Lua memory allocaton fixes
* Simulator memory leak fixes
This commit is contained in:
Damjan Adamic 2014-10-26 09:14:45 +01:00
parent 56a4cf5d26
commit c89381bae5
19 changed files with 294 additions and 13 deletions

View file

@ -3073,6 +3073,11 @@ FRESULT f_opendir (
} }
FRESULT f_closedir (DIR * rep)
{
//apparently nothing to do in FatFS
return FR_OK;
}
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View file

@ -209,6 +209,7 @@ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a
FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_opendir (DIR* dj, const TCHAR* path); /* Open an existing directory */ FRESULT f_opendir (DIR* dj, const TCHAR* path); /* Open an existing directory */
FRESULT f_closedir (DIR * rep);
FRESULT f_readdir (DIR* dj, FILINFO* fno); /* Read a directory item */ FRESULT f_readdir (DIR* dj, FILINFO* fno); /* Read a directory item */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */

View file

@ -297,6 +297,13 @@ CHANNELS_MONITOR_INV_HIDE = NO
# Values = NO, YES # Values = NO, YES
NANO = NO NANO = NO
# Use custom bin based allocator for Lua
# Values = NO, YES
# YES - use our bin based allocator
# NO - use default Lua allocator
USE_BIN_ALLOCATOR = NO
# Enable trace of events into Trace Buffer for debugging purposes # Enable trace of events into Trace Buffer for debugging purposes
# Activating any of these options also activates DEBUG and DEBUG_TRACE_BUFFER # Activating any of these options also activates DEBUG and DEBUG_TRACE_BUFFER
# Values = NO, YES # Values = NO, YES
@ -776,6 +783,10 @@ ifeq ($(PCB), TARANIS)
lua/src/lbaselib.c lua/src/linit.c lua/src/lmathlib.c lua/src/lbitlib.c lua/src/loadlib.c lua/src/lauxlib.c lua/src/ltablib.c lua/src/lcorolib.c lua/src/lbaselib.c lua/src/linit.c lua/src/lmathlib.c lua/src/lbitlib.c lua/src/loadlib.c lua/src/lauxlib.c lua/src/ltablib.c lua/src/lcorolib.c
SRC += $(LUASRC) SRC += $(LUASRC)
LUADEP = lua_exports.cpp LUADEP = lua_exports.cpp
ifeq ($(USE_BIN_ALLOCATOR), YES)
CPPDEFS += -DUSE_BIN_ALLOCATOR
CPPSRC += bin_allocator.cpp
endif
endif endif
ifeq ($(SDCARD), YES) ifeq ($(SDCARD), YES)
EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/taranis/diskio.cpp EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/taranis/diskio.cpp

View file

@ -274,6 +274,7 @@ void referenceSystemAudioFiles()
} }
} }
} }
f_closedir(&dir);
} }
sdAvailableSystemAudioFiles = availableAudioFiles; sdAvailableSystemAudioFiles = availableAudioFiles;
@ -395,6 +396,7 @@ void referenceModelAudioFiles()
} }
} }
} }
f_closedir(&dir);
} }
} }

111
radio/src/bin_allocator.cpp Normal file
View file

@ -0,0 +1,111 @@
#include <stdlib.h>
#include <string.h>
#include "opentx.h"
#include "bin_allocator.h"
BinAllocator_slots1 slots1;
BinAllocator_slots2 slots2;
#if defined(DEBUG)
int SimulateMallocFailure = 0; //set this to simulate allocation failure
#endif
bool bin_free(void * ptr)
{
//return TRUE if ours
return slots1.free(ptr) || slots2.free(ptr);
}
void * bin_malloc(size_t size) {
//try to allocate from our space
void * res = slots1.malloc(size);
return res ? res : slots2.malloc(size);
}
void * bin_realloc(void * ptr, size_t size)
{
if (ptr == 0) {
//no previous data, try our malloc
return bin_malloc(size);
}
else {
if (! (slots1.is_member(ptr) || slots2.is_member(ptr)) ) {
// not our data, leave it to libc realloc
return 0;
}
//we have existing data
// if it fits in current slot, return it
// TODO if new size is smaller, try to relocate in smaller slot
if ( slots1.can_fit(ptr, size) ) {
// TRACE("OUR realloc %p[%lu] fits in slot1", ptr, size); FLUSH();
return ptr;
}
if ( slots2.can_fit(ptr, size) ) {
// TRACE("OUR realloc %p[%lu] fits in slot2", ptr, size); FLUSH();
return ptr;
}
//we need a bigger slot
void * res = bin_malloc(size);
if (res == 0) {
// we don't have the space, use libc malloc
// TRACE("bin_malloc [%lu] FAILURE", size); FLUSH();
res = malloc(size);
if (res == 0) {
TRACE("libc malloc [%lu] FAILURE", size); FLUSH();
return 0;
}
}
//copy data
memcpy(res, ptr, slots1.size(ptr) + slots2.size(ptr));
bin_free(ptr);
return res;
}
}
void *bin_l_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
{
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
if (ptr) { // avoid a bunch of NULL pointer free calls
if (!bin_free(ptr)) {
// not our range, use libc allocator
// TRACE("libc free %p", ptr); FLUSH();
free(ptr);
}
}
return NULL;
}
else {
#if defined(DEBUG)
if (SimulateMallocFailure < 0 ) {
//delayed failure
if (++SimulateMallocFailure == 0) {
SimulateMallocFailure = 1;
}
}
if ( SimulateMallocFailure > 0) {
// simulate one malloc failure
TRACE("bin_l_alloc(): simulating malloc failure at %p[%lu]", ptr, nsize); FLUSH();
return 0;
}
#endif // #if defined(DEBUG)
// try our allocator, if it fails use libc allocator
void * res = bin_realloc(ptr, nsize);
if (res && ptr) {
// TRACE("OUR realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize); FLUSH();
}
if (res == 0) {
res = realloc(ptr, nsize);
// TRACE("libc realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize); FLUSH();
// if (res == 0 ){
// TRACE("realloc FAILURE %lu", nsize);
// dumpFreeMemory();
// }
}
return res;
}
}

78
radio/src/bin_allocator.h Normal file
View file

@ -0,0 +1,78 @@
#ifndef binallocator_h
#define binallocator_h
#include "debug.h"
template <int SIZE_SLOT, int NUM_BINS> class BinAllocator {
private:
PACK(struct Bin {
char data[SIZE_SLOT];
bool Used;
});
struct Bin Bins[NUM_BINS];
int NoUsedBins;
public:
BinAllocator() : NoUsedBins(0) {
memclear(Bins, sizeof(Bins));
}
bool free(void * ptr) {
for (size_t n = 0; n < NUM_BINS; ++n) {
if (ptr == Bins[n].data) {
Bins[n].Used = false;
--NoUsedBins;
// TRACE("\tBinAllocator<%d> free %lu ------", SIZE_SLOT, n); FLUSH();
return true;
}
}
return false;
}
bool is_member(void * ptr) {
return (ptr >= Bins[0].data && ptr <= Bins[NUM_BINS-1].data);
}
void * malloc(size_t size) {
if (size > SIZE_SLOT) {
// TRACE("BinAllocator<%d> malloc [%lu] size > SIZE_SLOT", SIZE_SLOT, size); FLUSH();
return 0;
}
if (NoUsedBins >= NUM_BINS) {
// TRACE("BinAllocator<%d> malloc [%lu] no free slots", SIZE_SLOT, size); FLUSH();
return 0;
}
for (size_t n = 0; n < NUM_BINS; ++n) {
if (!Bins[n].Used) {
Bins[n].Used = true;
++NoUsedBins;
// TRACE("\tBinAllocator<%d> malloc %lu[%lu]", SIZE_SLOT, n, size); FLUSH();
return Bins[n].data;
}
}
// TRACE("BinAllocator<%d> malloc [%lu] no free slots", SIZE_SLOT , size); FLUSH();
return 0;
}
size_t size(void * ptr) {
return is_member(ptr) ? SIZE_SLOT : 0;
}
bool can_fit(void * ptr, size_t size) {
return is_member(ptr) && size <= SIZE_SLOT; //todo is_member check is redundant
}
unsigned int capacity() { return NUM_BINS; }
unsigned int size() { return NoUsedBins; }
};
#if defined(SIMU)
typedef BinAllocator<39,300> BinAllocator_slots1;
typedef BinAllocator<79,100> BinAllocator_slots2;
#else
typedef BinAllocator<29,200> BinAllocator_slots1;
typedef BinAllocator<91,50> BinAllocator_slots2;
#endif
#if defined(USE_BIN_ALLOCATOR)
extern BinAllocator_slots1 slots1;
extern BinAllocator_slots2 slots2;
// wrapper for our BinAllocator for Lua
void *bin_l_alloc (void *ud, void *ptr, size_t osize, size_t nsize);
#endif //#if defined(USE_BIN_ALLOCATOR)
#endif //binallocator_h

View file

@ -137,6 +137,13 @@ static void dispw_256( register uint32_t address, register uint32_t lines )
} }
} }
extern Fifo<512> uart3TxFifo;
void debugFlush()
{
uart3TxFifo.flush();
}
void debugTask(void* pdata) void debugTask(void* pdata)
{ {
uint8_t rxchar ; uint8_t rxchar ;

View file

@ -52,6 +52,8 @@
#define TRACE_WARNING(...) do { printf("-W- " __VA_ARGS__); fflush(stdout); } while(0) #define TRACE_WARNING(...) do { printf("-W- " __VA_ARGS__); fflush(stdout); } while(0)
#define TRACE_WARNING_WP(...) do { printf(__VA_ARGS__); fflush(stdout); } while(0) #define TRACE_WARNING_WP(...) do { printf(__VA_ARGS__); fflush(stdout); } while(0)
#define TRACE_ERROR(...) do { printf("-E- " __VA_ARGS__); fflush(stdout); } while(0) #define TRACE_ERROR(...) do { printf("-E- " __VA_ARGS__); fflush(stdout); } while(0)
#define FLUSH()
inline void dump(void * data, unsigned int size) inline void dump(void * data, unsigned int size)
{ {
unsigned char *uchar_data = (unsigned char *)data; unsigned char *uchar_data = (unsigned char *)data;
@ -78,6 +80,7 @@ extern "C" {
void debugPuts(const char *string, ...); void debugPuts(const char *string, ...);
void dump(unsigned char *data, unsigned int size); void dump(unsigned char *data, unsigned int size);
void debugFlush();
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -92,7 +95,7 @@ void dump(unsigned char *data, unsigned int size);
#define TRACE_WARNING(...) debugPuts("-W- " __VA_ARGS__) #define TRACE_WARNING(...) debugPuts("-W- " __VA_ARGS__)
#define TRACE_WARNING_WP(...) debugPuts(__VA_ARGS__) #define TRACE_WARNING_WP(...) debugPuts(__VA_ARGS__)
#define TRACE_ERROR(...) debugPuts("-E- " __VA_ARGS__) #define TRACE_ERROR(...) debugPuts("-E- " __VA_ARGS__)
#define FLUSH() debugFlush();
void debugTask(void* pdata); void debugTask(void* pdata);
#else #else
@ -106,6 +109,7 @@ void debugTask(void* pdata);
#define TRACE_WARNING(...) { } #define TRACE_WARNING(...) { }
#define TRACE_WARNING_WP(...) { } #define TRACE_WARNING_WP(...) { }
#define TRACE_ERROR(...) { } #define TRACE_ERROR(...) { }
#define FLUSH()
#endif #endif

View file

@ -682,6 +682,9 @@ const pm_char * eeBackupModel(uint8_t i_fileSrc)
if (result != FR_OK) if (result != FR_OK)
return SDCARD_ERROR(result); return SDCARD_ERROR(result);
} }
else {
f_closedir(&archiveFolder);
}
buf[sizeof(MODELS_PATH)-1] = '/'; buf[sizeof(MODELS_PATH)-1] = '/';
strcpy(strcat_modelname(&buf[sizeof(MODELS_PATH)], i_fileSrc), STR_MODELS_EXT); strcpy(strcat_modelname(&buf[sizeof(MODELS_PATH)], i_fileSrc), STR_MODELS_EXT);

View file

@ -47,10 +47,6 @@ class Fifo
{ {
} }
bool empty() {
return (ridx == widx);
}
void push(uint8_t byte) { void push(uint8_t byte) {
uint32_t next = (widx+1) & (N-1); uint32_t next = (widx+1) & (N-1);
if (next != ridx) { if (next != ridx) {
@ -69,6 +65,12 @@ class Fifo
return true; return true;
} }
} }
bool empty() {
return (ridx == widx);
}
void flush() {
while (!empty()) {};
}
protected: protected:
uint8_t fifo[N]; uint8_t fifo[N];

View file

@ -38,6 +38,7 @@
#include <stdio.h> #include <stdio.h>
#include "opentx.h" #include "opentx.h"
#include "stamp-opentx.h" #include "stamp-opentx.h"
#include "bin_allocator.h"
#if !defined(SIMU) #if !defined(SIMU)
extern "C" { extern "C" {
@ -1566,7 +1567,11 @@ void luaInit()
{ {
luaClose(); luaClose();
if (luaState != INTERPRETER_PANIC) { if (luaState != INTERPRETER_PANIC) {
L = luaL_newstate(); #if defined(USE_BIN_ALLOCATOR)
L = lua_newstate(bin_l_alloc, NULL); //we use our own allocator!
#else
L = lua_newstate(l_alloc, NULL); //we use Lua default allocator
#endif
if (L) { if (L) {
// install our panic handler // install our panic handler
lua_atpanic(L, &custom_lua_atpanic); lua_atpanic(L, &custom_lua_atpanic);

View file

@ -954,10 +954,13 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
} }
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud; (void)osize; /* not used */ (void)ud; (void)osize; /* not used */
if (nsize == 0) { if (nsize == 0) {
free(ptr); if (ptr) { // avoid a bunch of NULL pointer free calls
// TRACE("free %p", ptr); FLUSH();
free(ptr);
}
return NULL; return NULL;
} }
else else

View file

@ -93,6 +93,8 @@ LUALIB_API int (luaL_len) (lua_State *L, int idx);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r); const char *r);
LUALIB_API void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);

View file

@ -205,6 +205,12 @@ static int stackinuse (lua_State *L) {
void luaD_shrinkstack (lua_State *L) { void luaD_shrinkstack (lua_State *L) {
int inuse = stackinuse(L); int inuse = stackinuse(L);
int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
if ((L->stacksize - goodsize) < 40) {
//skip shrink
// TRACE("luaD_shrinkstack(skip): L->stacksize: %d, goodsize: %d", L->stacksize, goodsize);
return;
}
// TRACE("luaD_shrinkstack(): L->stacksize: %d, goodsize: %d", L->stacksize, goodsize);
if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */
goodsize >= L->stacksize) /* would grow instead of shrink? */ goodsize >= L->stacksize) /* would grow instead of shrink? */

View file

@ -11,10 +11,10 @@
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <inttypes.h>
#include "luaconf.h" #include "luaconf.h"
#include "debug.h"
#define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "2" #define LUA_VERSION_MINOR "2"

View file

@ -11,9 +11,9 @@
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>
#include "debug.h" #if defined(SDCARD)
#define USE_FATFS #define USE_FATFS
#endif
/* /*
** ================================================================== ** ==================================================================

View file

@ -55,6 +55,7 @@ class Open9xSim: public FXMainWindow
public: public:
Open9xSim(){}; Open9xSim(){};
Open9xSim(FXApp* a); Open9xSim(FXApp* a);
~Open9xSim();
long onKeypress(FXObject*,FXSelector,void*); long onKeypress(FXObject*,FXSelector,void*);
long onTimeout(FXObject*,FXSelector,void*); long onTimeout(FXObject*,FXSelector,void*);
void makeSnapshot(const FXDrawable* drawable); void makeSnapshot(const FXDrawable* drawable);
@ -67,7 +68,7 @@ class Open9xSim: public FXMainWindow
bool firstTime; bool firstTime;
public: public:
FXSlider *sliders[8]; FXSlider *sliders[NUM_STICKS];
FXKnob *knobs[NUM_POTS]; FXKnob *knobs[NUM_POTS];
}; };
@ -127,6 +128,24 @@ Open9xSim::Open9xSim(FXApp* a):
getApp()->addTimeout(this,2,100); getApp()->addTimeout(this,2,100);
} }
Open9xSim::~Open9xSim()
{
StopMainThread();
StopEepromThread();
delete bmp;
delete sliders[0];
delete sliders[1];
delete sliders[2];
delete sliders[3];
for(int i=0; i<NUM_POTS; i++){
delete knobs[i];
}
delete bmf;
}
void Open9xSim::makeSnapshot(const FXDrawable* drawable) void Open9xSim::makeSnapshot(const FXDrawable* drawable)
{ {
// Construct and create an FXImage object // Construct and create an FXImage object

View file

@ -323,6 +323,11 @@ void *main_thread(void *)
perMain(); perMain();
sleep(10/*ms*/); sleep(10/*ms*/);
} }
#if defined(LUA)
luaClose();
#endif
#ifdef SIMU_EXCEPTIONS #ifdef SIMU_EXCEPTIONS
} }
catch (...) { catch (...) {
@ -396,6 +401,14 @@ void StopEepromThread()
sem_post(eeprom_write_sem); sem_post(eeprom_write_sem);
pthread_join(eeprom_thread_pid, NULL); pthread_join(eeprom_thread_pid, NULL);
#endif #endif
#ifdef __APPLE__
//TODO free semaphore eeprom_write_sem
#else
sem_destroy(eeprom_write_sem);
free(eeprom_write_sem);
#endif
if (fp) fclose(fp);
} }
#if defined(PCBTARANIS) #if defined(PCBTARANIS)
@ -546,6 +559,13 @@ FRESULT f_opendir (DIR * rep, const TCHAR * name)
return FR_OK; return FR_OK;
} }
FRESULT f_closedir (DIR * rep)
{
TRACE("f_closedir(%p)", rep);
simu::closedir((simu::DIR *)rep->fs);
return FR_OK;
}
FRESULT f_readdir (DIR * rep, FILINFO * fil) FRESULT f_readdir (DIR * rep, FILINFO * fil)
{ {
if (!rep->fs) return FR_NO_FILE; if (!rep->fs) return FR_NO_FILE;

View file

@ -356,7 +356,9 @@ void simuSetTrim(uint8_t trim, bool state);
void simuSetSwitch(uint8_t swtch, int8_t state); void simuSetSwitch(uint8_t swtch, int8_t state);
void StartMainThread(bool tests=true); void StartMainThread(bool tests=true);
void StopMainThread();
void StartEepromThread(const char *filename="eeprom.bin"); void StartEepromThread(const char *filename="eeprom.bin");
void StopEepromThread();
extern const char *eepromFile; extern const char *eepromFile;
#if defined(PCBTARANIS) || defined(PCBACT) #if defined(PCBTARANIS) || defined(PCBACT)