Com: Allow runtime bypass of freeListLib

By environment or iocsh variable.
This commit is contained in:
Michael Davidsaver
2021-04-04 13:32:17 -07:00
parent d9052f7105
commit eea361bf5e
3 changed files with 53 additions and 19 deletions

View File

@@ -29,6 +29,8 @@
extern "C" {
#endif
LIBCOM_API extern int freeListBypass;
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int malloc);
LIBCOM_API void * epicsStdCall freeListCalloc(void *pvt);
LIBCOM_API void * epicsStdCall freeListMalloc(void *pvt);

View File

@@ -26,6 +26,20 @@
#include "epicsMutex.h"
#include "freeList.h"
#include "adjustment.h"
#include "errlog.h"
#include "epicsString.h"
#include "epicsAtomic.h"
#include "epicsExport.h"
/* Bypass free list and directly call malloc() every time? */
int freeListBypass
#ifdef EPICS_FREELIST_DEBUG
= 1;
#else
= 2; /* checks environment $EPICS_FREELIST_BYPASS */
#endif
epicsExportAddress(int, freeListBypass);
typedef struct allocMem {
struct allocMem *next;
@@ -44,10 +58,25 @@ LIBCOM_API void epicsStdCall
freeListInitPvt(void **ppvt,int size,int nmalloc)
{
FREELISTPVT *pfl;
int bypass = epicsAtomicGetIntT(&freeListBypass);
if(bypass==2) {
const char *str = getenv("EPICS_FREELIST_BYPASS");
if(str && epicsStrCaseCmp(str, "YES")==0) {
bypass = 1;
} else if(!str || str[0]=='\0' || epicsStrCaseCmp(str, "NO")==0) {
bypass = 0;
} else {
errlogPrintf(ERL_WARNING " EPICS_FREELIST_BYPASS expected to be YES, NO, or empty. Not \"%s\"\n", str);
}
epicsAtomicSetIntT(&freeListBypass, bypass);
}
pfl = callocMustSucceed(1,sizeof(FREELISTPVT), "freeListInitPvt");
pfl->size = adjustToWorstCaseAlignment(size);
pfl->nmalloc = nmalloc;
if(!bypass)
pfl->nmalloc = nmalloc; /* nmalloc==0 to bypass */
pfl->head = NULL;
pfl->mallochead = NULL;
pfl->nBlocksAvailable = 0u;
@@ -60,28 +89,26 @@ LIBCOM_API void epicsStdCall
LIBCOM_API void * epicsStdCall freeListCalloc(void *pvt)
{
FREELISTPVT *pfl = pvt;
# ifdef EPICS_FREELIST_DEBUG
return callocMustSucceed(1,pfl->size,"freeList Debug Calloc");
# else
void *ptemp;
ptemp = freeListMalloc(pvt);
if(ptemp) memset((char *)ptemp,0,pfl->size);
if(!pfl->nmalloc)
ptemp = calloc(1u, pfl->size);
else if(!!(ptemp = freeListMalloc(pvt)))
memset((char *)ptemp,0,pfl->size);
return(ptemp);
# endif
}
LIBCOM_API void * epicsStdCall freeListMalloc(void *pvt)
{
FREELISTPVT *pfl = pvt;
# ifdef EPICS_FREELIST_DEBUG
return callocMustSucceed(1,pfl->size,"freeList Debug Malloc");
# else
void *ptemp;
void **ppnext;
allocMem *pallocmem;
int i;
if(!pfl->nmalloc)
return malloc(pfl->size);
epicsMutexMustLock(pfl->lock);
ptemp = pfl->head;
if(ptemp==0) {
@@ -125,18 +152,18 @@ LIBCOM_API void * epicsStdCall freeListMalloc(void *pvt)
VALGRIND_MEMPOOL_FREE(pfl, ptemp);
VALGRIND_MEMPOOL_ALLOC(pfl, ptemp, pfl->size);
return(ptemp);
# endif
}
LIBCOM_API void epicsStdCall freeListFree(void *pvt,void*pmem)
{
FREELISTPVT *pfl = pvt;
# ifdef EPICS_FREELIST_DEBUG
memset ( pmem, 0xdd, pfl->size );
free(pmem);
# else
void **ppnext;
if(!pfl->nmalloc) {
free(pmem);
return;
}
VALGRIND_MEMPOOL_FREE(pvt, pmem);
VALGRIND_MEMPOOL_ALLOC(pvt, pmem, sizeof(void*));
@@ -146,7 +173,6 @@ LIBCOM_API void epicsStdCall freeListFree(void *pvt,void*pmem)
pfl->head = pmem;
pfl->nBlocksAvailable++;
epicsMutexUnlock(pfl->lock);
# endif
}
LIBCOM_API void epicsStdCall freeListCleanup(void *pvt)

View File

@@ -25,6 +25,7 @@
#include "taskwd.h"
#include "registry.h"
#include "epicsGeneralTime.h"
#include "freeList.h"
#include "libComRegister.h"
/* Register the PWD environment variable when the cd IOC shell function is
@@ -467,7 +468,11 @@ static void installLastResortEventProviderCallFunc(const iocshArgBuf *args)
installLastResortEventProvider();
}
static iocshVarDef asCheckClientIPDef[] = { { "asCheckClientIP", iocshArgInt, 0 }, { NULL, iocshArgInt, NULL } };
static iocshVarDef comDefs[] = {
{ "asCheckClientIP", iocshArgInt, 0 },
{ "freeListBypass", iocshArgInt, 0 },
{ NULL, iocshArgInt, NULL }
};
void epicsStdCall libComRegister(void)
{
@@ -504,6 +509,7 @@ void epicsStdCall libComRegister(void)
iocshRegister(&generalTimeReportFuncDef,generalTimeReportCallFunc);
iocshRegister(&installLastResortEventProviderFuncDef, installLastResortEventProviderCallFunc);
asCheckClientIPDef[0].pval = &asCheckClientIP;
iocshRegisterVariable(asCheckClientIPDef);
comDefs[0].pval = &asCheckClientIP;
comDefs[1].pval = &freeListBypass;
iocshRegisterVariable(comDefs);
}