diff --git a/src/ca/client/cac.cpp b/src/ca/client/cac.cpp index bdfc68c73..d13b5766c 100644 --- a/src/ca/client/cac.cpp +++ b/src/ca/client/cac.cpp @@ -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; diff --git a/src/ca/client/cac.h b/src/ca/client/cac.h index 99c3d3d27..7db5c6ddc 100644 --- a/src/ca/client/cac.h +++ b/src/ca/client/cac.h @@ -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 { diff --git a/src/ca/client/tcpiiu.cpp b/src/ca/client/tcpiiu.cpp index 9581baa4c..045f8d57e 100644 --- a/src/ca/client/tcpiiu.cpp +++ b/src/ca/client/tcpiiu.cpp @@ -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() }