ca: large array free list is optional

This commit is contained in:
Michael Davidsaver
2017-03-18 15:45:03 -04:00
parent 3009f88f64
commit 2096c60652
3 changed files with 43 additions and 62 deletions

View File

@@ -54,6 +54,12 @@ static const char pVersionCAC[] =
"@(#) " EPICS_VERSION_STRING
", CA Client Library " __DATE__;
// when set, respect EPICS_CA_MAX_ARRAY_BYTES
// when clear, ignore it
extern "C" {
int caLimitArray;
}
// TCP response dispatch table
const cac::pProtoStubTCP cac::tcpJumpTableCAC [] =
{
@@ -218,9 +224,11 @@ cac::cac (
throw std::bad_alloc ();
}
freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 );
if ( ! this->tcpLargeRecvBufFreeList ) {
throw std::bad_alloc ();
if(caLimitArray) {
freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 );
if ( ! this->tcpLargeRecvBufFreeList ) {
throw std::bad_alloc ();
}
}
unsigned bufsPerArray = this->maxRecvBytesTCP / comBuf::capacityBytes ();
if ( bufsPerArray > 1u ) {
@@ -231,9 +239,7 @@ cac::cac (
catch ( ... ) {
osiSockRelease ();
delete [] this->pUserName;
if ( this->tcpSmallRecvBufFreeList ) {
freeListCleanup ( this->tcpSmallRecvBufFreeList );
}
freeListCleanup ( this->tcpSmallRecvBufFreeList );
if ( this->tcpLargeRecvBufFreeList ) {
freeListCleanup ( this->tcpLargeRecvBufFreeList );
}
@@ -318,7 +324,9 @@ cac::~cac ()
}
freeListCleanup ( this->tcpSmallRecvBufFreeList );
freeListCleanup ( this->tcpLargeRecvBufFreeList );
if ( this->tcpLargeRecvBufFreeList ) {
freeListCleanup ( this->tcpLargeRecvBufFreeList );
}
delete [] this->pUserName;

View File

@@ -51,6 +51,7 @@
class netWriteNotifyIO;
class netReadNotifyIO;
class netSubscription;
class tcpiiu;
// used to control access to cac's recycle routines which
// should only be indirectly invoked by CAC when its lock
@@ -193,12 +194,6 @@ public:
const char *pformat, va_list args ) const;
double connectionTimeout ( epicsGuard < epicsMutex > & );
// buffer management
char * allocateSmallBufferTCP ();
void releaseSmallBufferTCP ( char * );
unsigned largeBufferSizeTCP () const;
char * allocateLargeBufferTCP ();
void releaseLargeBufferTCP ( char * );
unsigned maxContiguousFrames ( epicsGuard < epicsMutex > & ) const;
// misc
@@ -355,6 +350,8 @@ private:
cac ( const cac & );
cac & operator = ( const cac & );
friend class tcpiiu;
};
inline const char * cac::userNamePointer () const
@@ -385,35 +382,6 @@ inline void cac::attachToClientCtx ()
this->notify.attachToClientCtx ();
}
inline char * cac::allocateSmallBufferTCP ()
{
// this locks internally
return ( char * ) freeListMalloc ( this->tcpSmallRecvBufFreeList );
}
inline void cac::releaseSmallBufferTCP ( char *pBuf )
{
// this locks internally
freeListFree ( this->tcpSmallRecvBufFreeList, pBuf );
}
inline unsigned cac::largeBufferSizeTCP () const
{
return this->maxRecvBytesTCP;
}
inline char * cac::allocateLargeBufferTCP ()
{
// this locks internally
return ( char * ) freeListMalloc ( this->tcpLargeRecvBufFreeList );
}
inline void cac::releaseLargeBufferTCP ( char *pBuf )
{
// this locks internally
freeListFree ( this->tcpLargeRecvBufFreeList, pBuf );
}
inline unsigned cac::beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & guard ) const
{

View File

@@ -690,7 +690,7 @@ tcpiiu::tcpiiu (
curDataBytes ( 0ul ),
comBufMemMgr ( comBufMemMgrIn ),
cacRef ( cac ),
pCurData ( cac.allocateSmallBufferTCP () ),
pCurData ( (char*) freeListMalloc(this->cacRef.tcpSmallRecvBufFreeList) ),
pSearchDest ( pSearchDestIn ),
mutex ( mutexIn ),
cbMutex ( cbMutexIn ),
@@ -714,9 +714,12 @@ tcpiiu::tcpiiu (
socketHasBeenClosed ( false ),
unresponsiveCircuit ( false )
{
if(!pCurData)
throw std::bad_alloc();
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( this->sock == INVALID_SOCKET ) {
cac.releaseSmallBufferTCP ( this->pCurData );
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData);
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
@@ -1027,10 +1030,10 @@ tcpiiu :: ~tcpiiu ()
// free message body cache
if ( this->pCurData ) {
if ( this->curDataMax <= MAX_TCP ) {
this->cacRef.releaseSmallBufferTCP ( this->pCurData );
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData);
}
else if ( this->curDataMax <= cacRef.largeBufferSizeTCP()) {
this->cacRef.releaseLargeBufferTCP ( this->pCurData );
else if ( this->cacRef.tcpLargeRecvBufFreeList ) {
freeListFree(this->cacRef.tcpLargeRecvBufFreeList, this->pCurData);
}
else {
free ( this->pCurData );
@@ -1208,30 +1211,32 @@ bool tcpiiu::processIncoming (
char * newbuf = NULL;
arrayElementCount newsize;
if ( this->curMsg.m_postsize <= this->cacRef.largeBufferSizeTCP() ) {
newbuf = this->cacRef.allocateLargeBufferTCP ();
newsize = this->cacRef.largeBufferSizeTCP();
}
#ifndef NO_HUGE
else {
if ( !this->cacRef.tcpLargeRecvBufFreeList ) {
// round size up to multiple of 4K
newsize = ((this->curMsg.m_postsize-1)|0xfff)+1;
if (this->curDataMax > this->cacRef.largeBufferSizeTCP()) {
// expand existing huge buffer
newbuf = (char*)realloc(this->pCurData, newsize);
} else {
// trade up from small or large
if ( this->curDataMax <= MAX_TCP ) {
// small -> large
newbuf = (char*)malloc(newsize);
} else {
// expand large to larger
newbuf = (char*)realloc(this->pCurData, newsize);
}
} else if ( this->curMsg.m_postsize <= this->cacRef.maxRecvBytesTCP ) {
newbuf = (char*) freeListMalloc(this->cacRef.tcpLargeRecvBufFreeList);
newsize = this->cacRef.maxRecvBytesTCP;
}
#endif
if ( newbuf) {
if (this->curDataMax <= MAX_TCP) {
this->cacRef.releaseSmallBufferTCP ( this->pCurData );
} else if (this->curDataMax <= this->cacRef.largeBufferSizeTCP()) {
this->cacRef.releaseLargeBufferTCP ( this->pCurData );
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData );
} else if (this->cacRef.tcpLargeRecvBufFreeList) {
freeListFree(this->cacRef.tcpLargeRecvBufFreeList, this->pCurData );
} else {
// called realloc()
}