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_close (FIL* fp); /* Close an open file object */
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_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 */

View file

@ -297,6 +297,13 @@ CHANNELS_MONITOR_INV_HIDE = NO
# Values = NO, YES
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
# Activating any of these options also activates DEBUG and DEBUG_TRACE_BUFFER
# 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
SRC += $(LUASRC)
LUADEP = lua_exports.cpp
ifeq ($(USE_BIN_ALLOCATOR), YES)
CPPDEFS += -DUSE_BIN_ALLOCATOR
CPPSRC += bin_allocator.cpp
endif
endif
ifeq ($(SDCARD), YES)
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;
@ -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)
{
uint8_t rxchar ;

View file

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

View file

@ -682,6 +682,9 @@ const pm_char * eeBackupModel(uint8_t i_fileSrc)
if (result != FR_OK)
return SDCARD_ERROR(result);
}
else {
f_closedir(&archiveFolder);
}
buf[sizeof(MODELS_PATH)-1] = '/';
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) {
uint32_t next = (widx+1) & (N-1);
if (next != ridx) {
@ -69,6 +65,12 @@ class Fifo
return true;
}
}
bool empty() {
return (ridx == widx);
}
void flush() {
while (!empty()) {};
}
protected:
uint8_t fifo[N];

View file

@ -38,6 +38,7 @@
#include <stdio.h>
#include "opentx.h"
#include "stamp-opentx.h"
#include "bin_allocator.h"
#if !defined(SIMU)
extern "C" {
@ -1566,7 +1567,11 @@ void luaInit()
{
luaClose();
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) {
// install our panic handler
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 */
if (nsize == 0) {
if (ptr) { // avoid a bunch of NULL pointer free calls
// TRACE("free %p", ptr); FLUSH();
free(ptr);
}
return NULL;
}
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,
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 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) {
int inuse = stackinuse(L);
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 (inuse > LUAI_MAXSTACK || /* handling stack overflow? */
goodsize >= L->stacksize) /* would grow instead of shrink? */

View file

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

View file

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

View file

@ -55,6 +55,7 @@ class Open9xSim: public FXMainWindow
public:
Open9xSim(){};
Open9xSim(FXApp* a);
~Open9xSim();
long onKeypress(FXObject*,FXSelector,void*);
long onTimeout(FXObject*,FXSelector,void*);
void makeSnapshot(const FXDrawable* drawable);
@ -67,7 +68,7 @@ class Open9xSim: public FXMainWindow
bool firstTime;
public:
FXSlider *sliders[8];
FXSlider *sliders[NUM_STICKS];
FXKnob *knobs[NUM_POTS];
};
@ -127,6 +128,24 @@ Open9xSim::Open9xSim(FXApp* a):
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)
{
// Construct and create an FXImage object

View file

@ -323,6 +323,11 @@ void *main_thread(void *)
perMain();
sleep(10/*ms*/);
}
#if defined(LUA)
luaClose();
#endif
#ifdef SIMU_EXCEPTIONS
}
catch (...) {
@ -396,6 +401,14 @@ void StopEepromThread()
sem_post(eeprom_write_sem);
pthread_join(eeprom_thread_pid, NULL);
#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)
@ -546,6 +559,13 @@ FRESULT f_opendir (DIR * rep, const TCHAR * name)
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)
{
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 StartMainThread(bool tests=true);
void StopMainThread();
void StartEepromThread(const char *filename="eeprom.bin");
void StopEepromThread();
extern const char *eepromFile;
#if defined(PCBTARANIS) || defined(PCBACT)