fixed the following issues with detection of flow control mode
o the flow control contig frame thresh should be based on max array size o it appears that the wakeup mechanism for the send thread, who sends the flow control on/off messages was broken o looking at full buffers isnt a perfect detection scheme compared to the simpler approach of just checking to see if bytes are pending in the socket before calling recv
This commit is contained in:
@@ -143,6 +143,7 @@ cac::cac (
|
||||
initializingThreadsId ( epicsThreadGetIdSelf() ),
|
||||
initializingThreadsPriority ( epicsThreadGetPrioritySelf() ),
|
||||
maxRecvBytesTCP ( MAX_TCP ),
|
||||
maxContigFrames ( contiguousMsgCountWhichTriggersFlowControl ),
|
||||
beaconAnomalyCount ( 0u ),
|
||||
iiuExistenceCount ( 0u )
|
||||
{
|
||||
@@ -215,6 +216,11 @@ cac::cac (
|
||||
if ( ! this->tcpLargeRecvBufFreeList ) {
|
||||
throw std::bad_alloc ();
|
||||
}
|
||||
unsigned bufsPerArray = this->maxRecvBytesTCP / comBuf::capacityBytes ();
|
||||
if ( bufsPerArray > 1u ) {
|
||||
maxContigFrames = bufsPerArray *
|
||||
contiguousMsgCountWhichTriggersFlowControl;
|
||||
}
|
||||
}
|
||||
catch ( ... ) {
|
||||
osiSockRelease ();
|
||||
|
||||
@@ -198,6 +198,7 @@ public:
|
||||
unsigned largeBufferSizeTCP () const;
|
||||
char * allocateLargeBufferTCP ();
|
||||
void releaseLargeBufferTCP ( char * );
|
||||
unsigned maxContiguousFrames ( epicsGuard < epicsMutex > & ) const;
|
||||
|
||||
// misc
|
||||
const char * userNamePointer () const;
|
||||
@@ -272,6 +273,7 @@ private:
|
||||
epicsThreadId initializingThreadsId;
|
||||
unsigned initializingThreadsPriority;
|
||||
unsigned maxRecvBytesTCP;
|
||||
unsigned maxContigFrames;
|
||||
unsigned beaconAnomalyCount;
|
||||
unsigned iiuExistenceCount;
|
||||
|
||||
@@ -442,5 +444,11 @@ inline const char * cac :: pLocalHostName ()
|
||||
return _refLocalHostName->pointer ();
|
||||
}
|
||||
|
||||
inline unsigned cac ::
|
||||
maxContiguousFrames ( epicsGuard < epicsMutex > & ) const
|
||||
{
|
||||
return maxContigFrames;
|
||||
}
|
||||
|
||||
#endif // ifdef cach
|
||||
|
||||
|
||||
+35
-14
@@ -468,6 +468,7 @@ void tcpRecvThread::run ()
|
||||
if ( ! pComBuf ) {
|
||||
pComBuf = new ( this->iiu.comBufMemMgr ) comBuf;
|
||||
}
|
||||
|
||||
statusWireIO stat;
|
||||
pComBuf->fillFromWire ( this->iiu, stat );
|
||||
|
||||
@@ -497,7 +498,6 @@ void tcpRecvThread::run ()
|
||||
callbackManager mgr ( this->ctxNotify, this->cbMutex );
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->iiu.mutex );
|
||||
|
||||
|
||||
// route legacy V42 channel connect through the recv thread -
|
||||
// the only thread that should be taking the callback lock
|
||||
@@ -506,19 +506,6 @@ void tcpRecvThread::run ()
|
||||
pChan->connect ( mgr.cbGuard, guard );
|
||||
}
|
||||
|
||||
if ( stat.bytesCopied == pComBuf->capacityBytes () ) {
|
||||
if ( this->iiu.contigRecvMsgCount >=
|
||||
contiguousMsgCountWhichTriggersFlowControl ) {
|
||||
this->iiu.busyStateDetected = true;
|
||||
}
|
||||
else {
|
||||
this->iiu.contigRecvMsgCount++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->iiu.contigRecvMsgCount = 0u;
|
||||
this->iiu.busyStateDetected = false;
|
||||
}
|
||||
this->iiu.unacknowledgedSendBytes = 0u;
|
||||
|
||||
bool protocolOK = false;
|
||||
@@ -542,6 +529,40 @@ void tcpRecvThread::run ()
|
||||
sendWakeupNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// we dont feel comfortable calling this with a lock applied
|
||||
// (it might block for longer than we like)
|
||||
//
|
||||
// we would prefer to improve efficency by trying, first, a
|
||||
// recv with the new MSG_DONTWAIT flag set, but there isnt
|
||||
// universal support
|
||||
//
|
||||
bool bytesArePending = this->iiu.bytesArePendingInOS ();
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->iiu.mutex );
|
||||
if ( bytesArePending ) {
|
||||
if ( ! this->iiu.busyStateDetected ) {
|
||||
this->iiu.contigRecvMsgCount++;
|
||||
if ( this->iiu.contigRecvMsgCount >=
|
||||
this->iiu.cacRef.maxContiguousFrames ( guard ) ) {
|
||||
this->iiu.busyStateDetected = true;
|
||||
sendWakeupNeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if no bytes are pending then we must immediately
|
||||
// switch off flow control w/o waiting for more
|
||||
// data to arrive
|
||||
this->iiu.contigRecvMsgCount = 0u;
|
||||
if ( this->iiu.busyStateDetected ) {
|
||||
sendWakeupNeeded = true;
|
||||
this->iiu.busyStateDetected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( sendWakeupNeeded ) {
|
||||
this->iiu.sendThreadFlushEvent.signal ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user