improved client scedualing fro fdManager based apps

This commit is contained in:
Jeff Hill
2003-02-20 17:27:04 +00:00
parent 077fe6e1f3
commit 3f680362bb
11 changed files with 353 additions and 217 deletions
+21 -3
View File
@@ -315,6 +315,23 @@ int epicsShareAPI ca_create_channel (
return caStatus;
}
{
CAFDHANDLER * pFunc = 0;
void * pArg = 0;
{
epicsGuard < ca_client_context_mutex >
autoMutex ( pcac->mutex );
if ( pcac->fdRegFuncNeedsToBeCalled ) {
pFunc = pcac->fdRegFunc;
pArg = pcac->fdRegArg;
pcac->fdRegFuncNeedsToBeCalled = false;
}
}
if ( pFunc ) {
( *pFunc ) ( pArg, pcac->sock, true );
}
}
try {
oldChannelNotify * pChanNotify =
new ( pcac->oldChannelNotifyFreeList )
@@ -432,8 +449,9 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
}
unsigned tmpType = static_cast < unsigned > ( type );
autoPtrDestroy < getCallback > pNotify
( new ( pChan->getClientCtx().getCallbackFreeList )
autoPtrFreeList < getCallback > pNotify
( pChan->getClientCtx().getCallbackFreeList,
new ( pChan->getClientCtx().getCallbackFreeList )
getCallback ( *pChan, pfunc, arg ) );
pChan->read ( tmpType, count, *pNotify );
pNotify.release ();
@@ -911,7 +929,7 @@ void epicsShareAPI ca_signal_formated ( long ca_status, const char *pfilenm,
*
*/
// extern "C"
int epicsShareAPI ca_add_fd_registration (CAFDHANDLER *func, void *arg)
int epicsShareAPI ca_add_fd_registration ( CAFDHANDLER * func, void * arg )
{
ca_client_context *pcac;
int caStatus = fetchClientContext ( &pcac );
+120 -11
View File
@@ -30,6 +30,7 @@
#include "envDefs.h"
#include "caDiagnostics.h"
#include "cadef.h"
#include "fdmgr.h"
#ifndef min
#define min(A,B) ((A)>(B)?(B):(A))
@@ -2214,23 +2215,28 @@ void monitorUpdateTest ( chid chan, unsigned interestLevel )
showProgressEnd ( interestLevel );
}
void verifyReasonableBeaconPeriod ( chid chan )
void verifyReasonableBeaconPeriod ( chid chan, unsigned interestLevel )
{
double beaconPeriod;
if ( ca_get_ioc_connection_count () > 0 ) {
double beaconPeriod;
assert ( ca_get_ioc_connection_count () > 0 );
showProgressBegin ( "verifyReasonableBeaconPeriod", interestLevel );
printf ( "Beacon anomalies detected since program start %u\n",
ca_beacon_anomaly_count () );
beaconPeriod = ca_beacon_period ( chan );
assert ( beaconPeriod >= 0.0 );
printf ( "Beacon anomalies detected since program start %u\n",
ca_beacon_anomaly_count () );
printf ( "Estimated beacon period for channel %s = %f sec.\n",
ca_name ( chan ), beaconPeriod );
beaconPeriod = ca_beacon_period ( chan );
assert ( beaconPeriod >= 0.0 );
printf ( "Estimated beacon period for channel %s = %f sec.\n",
ca_name ( chan ), beaconPeriod );
showProgressEnd ( interestLevel );
}
}
void verifyOldPend ( unsigned interestLevel)
void verifyOldPend ( unsigned interestLevel )
{
int status;
@@ -2371,6 +2377,106 @@ void eventClearAndMultipleMonitorTest ( chid chan, unsigned interestLevel )
monitorUpdateTest ( chan, interestLevel );
}
void fdcb ( void * parg )
{
ca_poll ();
}
void fdRegCB ( void * parg, int fd, int opened )
{
int status;
fdctx * mgrCtx = ( fdctx * ) parg;
if ( opened ) {
status = fdmgr_add_callback (
mgrCtx, fd, fdi_read, fdcb, 0 );
assert ( status >= 0 );
}
else {
status = fdmgr_clear_callback (
mgrCtx, fd, fdi_read );
assert ( status >= 0 );
}
}
void fdManagerVerify ( const char * pName, unsigned interestLevel )
{
int status;
fdctx * mgrCtx;
struct timeval tmo;
chid newChan;
evid subscription;
unsigned repCount = 0u;
unsigned eventCount = 0u;
epicsTimeStamp begin, end;
mgrCtx = fdmgr_init ();
assert ( mgrCtx );
showProgressBegin ( "fdManagerVerify", interestLevel );
status = ca_add_fd_registration ( fdRegCB, mgrCtx );
assert ( status == ECA_NORMAL );
status = ca_create_channel ( pName, 0, 0, 0, & newChan );
assert ( status == ECA_NORMAL );
while ( ca_state ( newChan ) != cs_conn ) {
tmo.tv_sec = 6000;
tmo.tv_usec = 0;
status = fdmgr_pend_event ( mgrCtx, & tmo );
assert ( status >= 0 );
}
status = ca_add_event ( DBR_FLOAT, newChan,
nUpdatesTester, & eventCount, & subscription );
assert ( status == ECA_NORMAL );
status = ca_flush_io ();
assert ( status == ECA_NORMAL );
while ( eventCount < 1 ) {
tmo.tv_sec = 6000;
tmo.tv_usec = 0;
status = fdmgr_pend_event ( mgrCtx, & tmo );
assert ( status >= 0 );
}
status = ca_clear_event ( subscription );
assert ( status == ECA_NORMAL );
status = ca_flush_io ();
assert ( status == ECA_NORMAL );
// look for infinite loop in fd manager schedualing
epicsTimeGetCurrent ( & begin );
eventCount = 0u;
while ( 1 ) {
double delay;
tmo.tv_sec = 1;
tmo.tv_usec = 0;
status = fdmgr_pend_event ( mgrCtx, & tmo );
assert ( status >= 0 );
epicsTimeGetCurrent ( & end );
delay = epicsTimeDiffInSeconds ( & end, & begin );
if ( delay >= 1.0 ) {
break;
}
assert ( eventCount++ < 100 );
}
status = ca_clear_channel ( newChan );
assert ( status == ECA_NORMAL );
status = ca_add_fd_registration ( 0, 0 );
assert ( status == ECA_NORMAL );
status = fdmgr_delete ( mgrCtx );
assert ( status >= 0 );
showProgressEnd ( interestLevel );
}
int acctst ( char *pName, unsigned interestLevel, unsigned channelCount,
unsigned repetitionCount, enum ca_preemptive_callback_select select )
{
@@ -2459,6 +2565,9 @@ int acctst ( char *pName, unsigned interestLevel, unsigned channelCount,
verifyHighThroughputReadCallback ( chan, interestLevel );
verifyHighThroughputWriteCallback ( chan, interestLevel );
verifyBadString ( chan, interestLevel );
if ( select != ca_enable_preemptive_callback ) {
fdManagerVerify ( pName, interestLevel );
}
/*
* CA pend event delay accuracy test
@@ -2485,7 +2594,7 @@ int acctst ( char *pName, unsigned interestLevel, unsigned channelCount,
verifyBlockingConnect ( pChans, channelCount, repetitionCount, interestLevel );
verifyClear ( pChans, interestLevel );
verifyReasonableBeaconPeriod ( chan );
verifyReasonableBeaconPeriod ( chan, interestLevel );
/*
* Verify that we can do IO with the new types for ALH
+139 -45
View File
@@ -29,21 +29,92 @@
extern epicsThreadPrivateId caClientContextId;
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
clientCtx ( * new cac ( *this, enablePreemptiveCallback ) ),
pCallbackGuard ( 0 ), ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
pndRecvCnt ( 0u ), ioSeqNo ( 0u )
pndRecvCnt ( 0u ), ioSeqNo ( 0u ), localPort ( 0 ),
fdRegFuncNeedsToBeCalled ( false ), noWakeupSincePend ( true )
{
if ( ! enablePreemptiveCallback ) {
this->pCallbackGuard = new epicsGuard < callbackMutex >
( this->clientCtx.callbackGuardFactory () );
static const unsigned short PORT_ANY = 0u;
this->sock = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( this->sock == INVALID_SOCKET ) {
this->printf (
"ca_client_context: unable to create "
"datagram socket because = \"%s\"\n",
SOCKERRSTR (SOCKERRNO));
throwWithLocation ( noSocket () );
}
{
osiSockIoctl_t yes = true;
int status = socket_ioctl ( this->sock,
FIONBIO, & yes); // X aCC 392
if ( status < 0 ) {
socket_close ( this->sock );
this->printf (
"%s: non blocking IO set fail because \"%s\"\n",
__FILE__, SOCKERRSTR ( SOCKERRNO ) );
throwWithLocation ( noSocket () );
}
}
// force a bind to an unconstrained address so we can obtain
// the local port number below
{
osiSockAddr addr;
memset ( (char *)&addr, 0 , sizeof ( addr ) );
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = epicsHTON32 ( INADDR_ANY );
addr.ia.sin_port = epicsHTON16 ( PORT_ANY ); // X aCC 818
int status = bind (this->sock, &addr.sa, sizeof (addr) );
if ( status < 0 ) {
socket_close (this->sock);
this->printf (
"CAC: unable to bind to an unconstrained "
"address because = \"%s\"\n",
SOCKERRSTR (SOCKERRNO));
throwWithLocation ( noSocket () );
}
}
{
osiSockAddr tmpAddr;
osiSocklen_t saddr_length = sizeof ( tmpAddr );
int status = getsockname ( this->sock, & tmpAddr.sa, & saddr_length );
if ( status < 0 ) {
socket_close ( this->sock );
this->printf ( "CAC: getsockname () error was \"%s\"\n", SOCKERRSTR (SOCKERRNO) );
throwWithLocation ( noSocket () );
}
if ( tmpAddr.sa.sa_family != AF_INET) {
socket_close ( this->sock );
this->printf ( "CAC: UDP socket was not inet addr family\n" );
throwWithLocation ( noSocket () );
}
this->localPort = epicsNTOH16 ( tmpAddr.ia.sin_port );
}
epics_auto_ptr < cac > pCAC (
new cac ( *this, enablePreemptiveCallback ) );
epics_auto_ptr < epicsGuard < callbackMutex > > pCBGuard;
if ( ! enablePreemptiveCallback ) {
pCBGuard.reset ( new epicsGuard < callbackMutex >
( pCAC->callbackGuardFactory () ) );
}
// multiple steps ensure exception safety
this->pCallbackGuard = pCBGuard;
this->pClientCtx = pCAC;
}
ca_client_context::~ca_client_context ()
{
delete this->pCallbackGuard;
delete & this->clientCtx;
if ( this->fdRegFunc ) {
( *this->fdRegFunc )
( this->fdRegArg, this->sock, false );
}
socket_close ( this->sock );
}
void ca_client_context::destroyChannel ( oldChannelNotify & chan )
@@ -101,6 +172,7 @@ void ca_client_context::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc,
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
this->fdRegFunc = pFunc;
this->fdRegArg = pArg;
this->fdRegFuncNeedsToBeCalled = true;
// should block here until releated callback in progress completes
}
@@ -160,7 +232,7 @@ void ca_client_context::exception ( int stat, const char *pCtx,
( *pFunc ) ( args );
}
else {
this->clientCtx.signal ( stat, pFile, lineNo, pCtx );
this->pClientCtx->signal ( stat, pFile, lineNo, pCtx );
}
}
@@ -192,7 +264,7 @@ void ca_client_context::exception ( int status, const char *pContext,
( *pFunc ) ( args );
}
else {
this->clientCtx.signal ( status, pFileName, lineNo,
this->pClientCtx->signal ( status, pFileName, lineNo,
"op=%u, channel=%s, type=%s, count=%lu, ctx=\"%s\"",
op, ca_name ( &chan ),
dbr_type_to_text ( static_cast <int> ( type ) ),
@@ -200,34 +272,6 @@ void ca_client_context::exception ( int status, const char *pContext,
}
}
void ca_client_context::fdWasCreated ( int fd )
{
CAFDHANDLER *pFunc;
void *pArg;
{
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
pFunc = this->fdRegFunc;
pArg = this->fdRegArg;
}
if ( pFunc ) {
( *pFunc ) ( pArg, fd, true );
}
}
void ca_client_context::fdWasDestroyed ( int fd )
{
CAFDHANDLER *pFunc;
void *pArg;
{
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
pFunc = this->fdRegFunc;
pArg = this->fdRegArg;
}
if ( pFunc ) {
( *pFunc ) ( pArg, fd, false );
}
}
void ca_client_context::show ( unsigned level ) const
{
::printf ( "ca_client_context at %p pndRecvCnt=%u ioSeqNo=%u\n",
@@ -235,9 +279,9 @@ void ca_client_context::show ( unsigned level ) const
this->pndRecvCnt, this->ioSeqNo );
if ( level > 0u ) {
this->mutex.show ( level - 1u );
this->clientCtx.show ( level - 1u );
this->pClientCtx->show ( level - 1u );
::printf ( "\tpreemptive callback is %s\n",
this->pCallbackGuard ? "disabled" : "enabled" );
this->pCallbackGuard.get() ? "disabled" : "enabled" );
::printf ( "\tthere are %u unsatisfied IO operations blocking ca_pend_io()\n",
this->pndRecvCnt );
::printf ( "\tthe current io sequence number is %u\n",
@@ -351,10 +395,36 @@ int ca_client_context::pendEvent ( const double & timeout )
this->flushRequest ();
{
bool cleanupNeeded = false;
{
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
if ( this->fdRegFunc ) {
cleanupNeeded = true;
}
}
if ( cleanupNeeded ) {
// send short udp message to wake up a file descriptor manager
// when a message arrives
osiSockAddr tmpAddr;
osiSocklen_t addrSize = sizeof ( tmpAddr.sa );
char buf = 0;
int status = 0;
do {
status = recvfrom ( this->sock, & buf, sizeof ( buf ),
0, & tmpAddr.sa, & addrSize );
} while ( status > 0 );
{
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
this->noWakeupSincePend = true;
}
}
}
// process at least once if preemptive callback is disabled
if ( this->pCallbackGuard ) {
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < callbackMutex > unguard ( *this->pCallbackGuard );
this->clientCtx.waitUntilNoRecvThreadsPending ();
this->pClientCtx->waitUntilNoRecvThreadsPending ();
}
double elapsed = epicsTime::getCurrent() - current;
@@ -368,7 +438,7 @@ int ca_client_context::pendEvent ( const double & timeout )
}
if ( delay >= CAC_SIGNIFICANT_DELAY ) {
if ( this->pCallbackGuard ) {
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < callbackMutex > unguard ( *this->pCallbackGuard );
epicsThreadSleep ( delay );
}
@@ -380,9 +450,10 @@ int ca_client_context::pendEvent ( const double & timeout )
return ECA_TIMEOUT;
}
void ca_client_context::blockForEventAndEnableCallbacks ( epicsEvent & event, double timeout )
void ca_client_context::blockForEventAndEnableCallbacks (
epicsEvent & event, const double & timeout )
{
if ( this->pCallbackGuard ) {
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < callbackMutex > unguard ( *this->pCallbackGuard );
event.wait ( timeout );
}
@@ -390,3 +461,26 @@ void ca_client_context::blockForEventAndEnableCallbacks ( epicsEvent & event, do
event.wait ( timeout );
}
}
void ca_client_context::messageArrivalNotify ()
{
bool sendNeeded = false;
{
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
if ( this->fdRegFunc && this->noWakeupSincePend ) {
this->noWakeupSincePend = false;
sendNeeded = true;
}
}
if ( sendNeeded ) {
// send short udp message to wake up a file descriptor manager
// when a message arrives
osiSockAddr tmpAddr;
tmpAddr.ia.sin_family = AF_INET;
tmpAddr.ia.sin_addr.s_addr = epicsHTON32 ( INADDR_LOOPBACK );
tmpAddr.ia.sin_port = epicsHTON16 ( this->localPort );
char buf = 0;
sendto ( this->sock, & buf, sizeof ( buf ),
0, & tmpAddr.sa, sizeof ( tmpAddr.sa ) );
}
}
+14 -35
View File
@@ -625,7 +625,7 @@ bool cac::lookupChannelAndTransferToTCP (
}
if ( newIIU ) {
piiu->start ( cbGuard );
piiu->start ();
}
return true;
@@ -1497,16 +1497,6 @@ void cac::selfTest () const
this->beaconTable.verify ();
}
void cac::notifyNewFD ( epicsGuard < callbackMutex > &, SOCKET sock ) const
{
this->notify.fdWasCreated ( sock );
}
void cac::notifyDestroyFD ( epicsGuard < callbackMutex > &, SOCKET sock ) const
{
this->notify.fdWasDestroyed ( sock );
}
void cac::disconnectNotify ( tcpiiu & iiu )
{
epicsGuard < cacMutex > guard ( this->mutex );
@@ -1620,34 +1610,15 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
void cac::waitUntilNoRecvThreadsPending ()
{
if ( ! this->preemptiveCallbackEnabled ) {
{
fd_set mask;
FD_ZERO ( & mask );
SOCKET maxFD = 0;
epicsGuard < cacMutex > guard ( this->mutex );
tsDLIter < tcpiiu > iter = this->serverList.firstIter ();
if ( this->pudpiiu ) {
this->pudpiiu->fdMaskSet ( mask, maxFD );
}
while ( iter.valid() ) {
iter->fdMaskSet ( mask, maxFD );
iter++;
}
struct timeval delay = { 0, 0 };
int status = select ( maxFD+1, & mask, 0, 0, & delay );
if ( status <= 0 ) {
return;
}
this->nRecvThreadsPending =
static_cast < unsigned > ( status );
epicsGuard < cacMutex > guard ( this->mutex );
while ( this->nRecvThreadsPending > 0 ) {
epicsGuardRelease < cacMutex > unguard ( guard );
this->recvThreadActivityComplete.wait ( 30.0 );
}
this->recvThreadActivityComplete.wait ( 0.1 );
}
}
void cac::signalRecvThreadActivity ()
void cac::messageProcessingCompleteNotify ()
{
if ( ! this->preemptiveCallbackEnabled ) {
bool signalNeeded = false;
@@ -1669,5 +1640,13 @@ void cac::signalRecvThreadActivity ()
}
}
void cac::messageArrivalNotify ()
{
if ( ! this->preemptiveCallbackEnabled ) {
epicsGuard < cacMutex > guard ( this->mutex );
this->nRecvThreadsPending++;
}
this->notify.messageArrivalNotify ();
}
+2 -3
View File
@@ -185,8 +185,6 @@ public:
cacMutex & mutexRef ();
void attachToClientCtx ();
void selfTest () const;
void notifyNewFD ( epicsGuard < callbackMutex > &, SOCKET ) const;
void notifyDestroyFD ( epicsGuard < callbackMutex > &, SOCKET ) const;
bool preemptiveCallbakIsEnabled () const;
double beaconPeriod ( const nciu & chan ) const;
static unsigned lowestPriorityLevelAbove ( unsigned priority );
@@ -194,7 +192,8 @@ public:
void initiateAbortShutdown ( tcpiiu & );
void disconnectNotify ( tcpiiu & );
void uninstallIIU ( tcpiiu & );
void signalRecvThreadActivity ();
void messageArrivalNotify ();
void messageProcessingCompleteNotify ();
private:
localHostName hostNameCache;
+5 -6
View File
@@ -213,16 +213,15 @@ class cacNotify { // X aCC 655
public:
virtual ~cacNotify () = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception ( int status, const char *pContext,
const char *pFileName, unsigned lineNo ) = 0;
virtual void exception ( int status, const char * pContext,
const char * pFileName, unsigned lineNo ) = 0;
// perhaps this should be phased out in deference to the exception mechanism
virtual int vPrintf ( const char *pformat, va_list args ) const = 0;
// this should probably be phased out (its not OS independent)
virtual void fdWasCreated ( int fd ) = 0;
virtual void fdWasDestroyed ( int fd ) = 0;
// backwards compatibility
virtual void attachToClientCtx () = 0;
virtual void blockForEventAndEnableCallbacks ( class epicsEvent & event, double timeout ) = 0;
virtual void blockForEventAndEnableCallbacks (
class epicsEvent & event, const double & timeout ) = 0;
virtual void messageArrivalNotify () = 0;
};
class cacService : public tsDLNode < cacService > { // X aCC 655
+27 -25
View File
@@ -33,6 +33,7 @@
#endif
#include "tsFreeList.h"
#include "epicsMemory.h"
#include "cxxCompilerDependencies.h"
#ifdef oldAccessh_restore_epicsExportSharedSymbols
@@ -146,7 +147,6 @@ public:
getCallback ( oldChannelNotify &chanIn,
caEventCallBackFunc *pFunc, void *pPrivate );
~getCallback ();
void destroy ();
void * operator new ( size_t size,
tsFreeList < class getCallback, 1024 > & );
epicsPlacementDeleteOperator (( void *,
@@ -250,10 +250,11 @@ public:
void exception ( int status, const char *pContext,
const char *pFileName, unsigned lineNo, oldChannelNotify &chan,
unsigned type, arrayElementCount count, unsigned op );
void blockForEventAndEnableCallbacks (
epicsEvent & event, const double & timeout );
CASG * lookupCASG ( unsigned id );
void installCASG ( CASG & );
void uninstallCASG ( CASG & );
void blockForEventAndEnableCallbacks ( epicsEvent & event, double timeout );
void selfTest ();
// perhaps these should be eliminated in deference to the exception mechanism
int printf ( const char *pformat, ... ) const;
@@ -267,6 +268,9 @@ public:
void destroyGetCallback ( getCallback & );
void destroyPutCallback ( putCallback & );
void destroySubscription ( oldSubscription & );
// exceptions
class noSocket {};
private:
tsFreeList < struct oldChannelNotify, 1024 > oldChannelNotifyFreeList;
tsFreeList < class getCopy, 1024 > getCopyFreeList;
@@ -276,18 +280,21 @@ private:
tsFreeList < struct CASG, 128 > casgFreeList;
mutable ca_client_context_mutex mutex;
epicsEvent ioDone;
cac & clientCtx;
epicsGuard < callbackMutex > * pCallbackGuard;
epics_auto_ptr < cac > pClientCtx;
epics_auto_ptr < epicsGuard < callbackMutex > > pCallbackGuard;
caExceptionHandler * ca_exception_func;
void * ca_exception_arg;
caPrintfFunc * pVPrintfFunc;
CAFDHANDLER * fdRegFunc;
void * fdRegArg;
void * fdRegArg;
SOCKET sock;
unsigned pndRecvCnt;
unsigned ioSeqNo;
// this should probably be phased out (its not OS independent)
void fdWasCreated ( int fd );
void fdWasDestroyed ( int fd );
ca_uint16_t localPort;
bool fdRegFuncNeedsToBeCalled;
bool noWakeupSincePend;
void messageArrivalNotify ();
void attachToClientCtx ();
ca_client_context ( const ca_client_context & );
ca_client_context & operator = ( const ca_client_context & );
@@ -497,11 +504,6 @@ inline void putCallback::operator delete ( void * pCadaver,
}
#endif
inline void getCallback::destroy ()
{
delete this;
}
inline void * getCallback::operator new ( size_t size,
tsFreeList < class getCallback, 1024 > & freeList )
{
@@ -518,60 +520,60 @@ inline void getCallback::operator delete ( void *pCadaver,
inline void ca_client_context::registerService ( cacService &service )
{
this->clientCtx.registerService ( service );
this->pClientCtx->registerService ( service );
}
inline cacChannel & ca_client_context::createChannel ( const char * name_str,
oldChannelNotify & chan, cacChannel::priLev pri )
{
return this->clientCtx.createChannel ( name_str, chan, pri );
return this->pClientCtx->createChannel ( name_str, chan, pri );
}
inline void ca_client_context::flushRequest ()
{
this->clientCtx.flushRequest ();
this->pClientCtx->flushRequest ();
}
inline unsigned ca_client_context::connectionCount () const
{
return this->clientCtx.connectionCount ();
return this->pClientCtx->connectionCount ();
}
inline unsigned ca_client_context::beaconAnomaliesSinceProgramStart () const
{
return this->clientCtx.beaconAnomaliesSinceProgramStart ();
return this->pClientCtx->beaconAnomaliesSinceProgramStart ();
}
inline CASG * ca_client_context::lookupCASG ( unsigned id )
{
return this->clientCtx.lookupCASG ( id );
return this->pClientCtx->lookupCASG ( id );
}
inline void ca_client_context::installCASG ( CASG &sg )
{
this->clientCtx.installCASG ( sg );
this->pClientCtx->installCASG ( sg );
}
inline void ca_client_context::uninstallCASG ( CASG &sg )
{
this->clientCtx.uninstallCASG ( sg );
this->pClientCtx->uninstallCASG ( sg );
}
inline void ca_client_context::vSignal ( int ca_status, const char *pfilenm,
int lineno, const char *pFormat, va_list args )
{
this->clientCtx.vSignal ( ca_status, pfilenm,
this->pClientCtx->vSignal ( ca_status, pfilenm,
lineno, pFormat, args );
}
inline void ca_client_context::selfTest ()
{
this->clientCtx.selfTest ();
this->pClientCtx->selfTest ();
}
inline bool ca_client_context::preemptiveCallbakIsEnabled () const
{
return this->clientCtx.preemptiveCallbakIsEnabled ();
return this->pClientCtx->preemptiveCallbakIsEnabled ();
}
inline bool ca_client_context::ioComplete () const
@@ -587,7 +589,7 @@ inline unsigned ca_client_context::sequenceNumberOfOutstandingIO () const
inline epicsGuard < callbackMutex > ca_client_context::callbackGuardFactory ()
{
return this->clientCtx.callbackGuardFactory ();
return this->pClientCtx->callbackGuardFactory ();
}
inline void ca_client_context_mutex::lock ()
+11 -36
View File
@@ -123,9 +123,8 @@ void tcpSendThread::run ()
this->iiu.sendDog.cancel ();
{
epicsGuard < callbackMutex > cbGuard ( this->cbMutex );
epicsGuard < cacMutex > guard ( this->iiu.cacRef.mutexRef() );
this->iiu.shutdown ( cbGuard, guard );
this->iiu.shutdown ( guard );
}
// wakeup user threads blocking for send backlog to be reduced
@@ -310,20 +309,9 @@ void tcpRecvThread::run ()
// file manager call backs works correctly. This does not
// appear to impact performance.
//
unsigned nBytesIn;
if ( this->iiu.cacRef.preemptiveCallbakIsEnabled() ) {
nBytesIn = pComBuf->fillFromWire ( this->iiu );
if ( nBytesIn == 0u ) {
continue;
}
}
else {
this->iiu.blockUntilBytesArePendingInOS ();
nBytesIn = 0u;
if ( this->iiu.state != tcpiiu::iiucs_connected &&
this->iiu.state != tcpiiu::iiucs_clean_shutdown ) {
break;
}
unsigned nBytesIn = pComBuf->fillFromWire ( this->iiu );
if ( nBytesIn == 0u ) {
continue;
}
// reschedule connection activity watchdog
@@ -333,19 +321,13 @@ void tcpRecvThread::run ()
// - it take also the callback lock
this->iiu.recvDog.messageArrivalNotify ();
this->iiu.cacRef.messageArrivalNotify ();
// only one recv thread at a time may call callbacks
// - pendEvent() blocks until threads waiting for
// this lock get a chance to run
epicsGuard < callbackMutex > guard ( this->cbMutex );
if ( ! this->iiu.cacRef.preemptiveCallbakIsEnabled() ) {
nBytesIn = pComBuf->fillFromWire ( this->iiu );
if ( this->iiu.state != tcpiiu::iiucs_connected &&
this->iiu.state != tcpiiu::iiucs_clean_shutdown ) {
break;
}
}
// force the receive watchdog to be reset every 5 frames
unsigned contiguousFrameCount = 0;
while ( nBytesIn ) {
@@ -381,7 +363,7 @@ void tcpRecvThread::run ()
nBytesIn = pComBuf->fillFromWire ( this->iiu );
}
this->iiu.cacRef.signalRecvThreadActivity ();
this->iiu.cacRef.messageProcessingCompleteNotify ();
}
if ( pComBuf ) {
@@ -398,9 +380,8 @@ void tcpRecvThread::run ()
// until it receives its blocking socket call interrupt
// signal.
{
epicsGuard < callbackMutex > cbGuard ( this->cbMutex );
epicsGuard < cacMutex > guard ( this->iiu.cacRef.mutexRef() );
this->iiu.shutdown ( cbGuard, guard );
this->iiu.shutdown ( guard );
}
}
@@ -547,10 +528,9 @@ tcpiiu::tcpiiu ( cac & cac, callbackMutex & cbMutex, double connectionTimeout,
// this must always be called by the udp thread when it holds
// the callback lock.
void tcpiiu::start ( epicsGuard < callbackMutex > & cbGuard )
void tcpiiu::start ()
{
this->recvThread.start ();
this->cacRef.notifyNewFD ( cbGuard, this->sock );
}
/*
@@ -634,19 +614,14 @@ void tcpiiu::initiateAbortShutdown ( epicsGuard < callbackMutex > & cbGuard,
}
this->discardingPendingData = true;
}
this->shutdown ( cbGuard, guard );
this->shutdown ( guard );
}
void tcpiiu::shutdown ( epicsGuard < callbackMutex > & cbGuard,
epicsGuard <cacMutex > & guard )
void tcpiiu::shutdown ( epicsGuard <cacMutex > & guard )
{
iiu_conn_state oldState = this->state;
if ( oldState != iiucs_abort_shutdown ) {
this->state = iiucs_abort_shutdown;
{
epicsGuardRelease < cacMutex > guardRelease ( guard );
this->cacRef.notifyDestroyFD ( cbGuard, this->sock );
}
//
// on HPUX close() and shutdown() are not enough so we must also
+9 -32
View File
@@ -135,10 +135,8 @@ udpiiu::udpiiu ( epicsTimerQueueActive & timerQueue, callbackMutex & cbMutex, ca
}
#endif
/*
* force a bind to an unconstrained address because we may end
* up receiving first
*/
// force a bind to an unconstrained address so we can obtain
// the local port number below
memset ( (char *)&addr, 0 , sizeof (addr) );
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = epicsHTON32 (INADDR_ANY);
@@ -241,31 +239,16 @@ void udpiiu::shutdown ()
void udpiiu::recvMsg ( callbackMutex & cbMutex )
{
osiSockAddr src;
int status;
osiSocklen_t src_size = sizeof ( src );
int status = recvfrom ( this->sock,
this->recvBuf, sizeof ( this->recvBuf ), 0,
& src.sa, & src_size );
if ( this->cacRef.preemptiveCallbakIsEnabled() ) {
osiSocklen_t src_size = sizeof ( src );
status = recvfrom ( this->sock, this->recvBuf, sizeof ( this->recvBuf ), 0,
&src.sa, &src_size );
}
else {
// peek first at the message so that file descriptor managers will wake up
// in single threaded applications
osiSocklen_t src_size = sizeof ( src );
char peek;
recvfrom ( this->sock, & peek, sizeof ( peek ), MSG_PEEK,
&src.sa, &src_size );
status = 0;
}
this->cacRef.messageArrivalNotify ();
{
epicsGuard < callbackMutex > guard ( cbMutex );
if ( ! this->cacRef.preemptiveCallbakIsEnabled() ) {
osiSocklen_t src_size = sizeof ( src );
status = recvfrom ( this->sock, this->recvBuf, sizeof ( this->recvBuf ), 0,
&src.sa, &src_size );
}
if ( status <= 0 ) {
if ( status == 0 ) {
@@ -303,7 +286,8 @@ void udpiiu::recvMsg ( callbackMutex & cbMutex )
(arrayElementCount) status, epicsTime::getCurrent() );
}
}
return;
this->cacRef.messageProcessingCompleteNotify ();
}
udpRecvThread::udpRecvThread ( udpiiu & iiuIn, callbackMutex & cbMutexIn,
@@ -331,7 +315,6 @@ void udpRecvThread::run ()
{
epicsGuard < callbackMutex > cbGuard ( this->cbMutex );
this->iiu.cacRef.notifyNewFD ( cbGuard, this->iiu.sock );
if ( ellCount ( & this->iiu.dest ) == 0 ) { // X aCC 392
genLocalExcep ( cbGuard, this->iiu.cacRef, ECA_NOSEARCHADDR, NULL );
}
@@ -340,13 +323,7 @@ void udpRecvThread::run ()
do {
this->iiu.recvMsg ( this->cbMutex );
this->iiu.cacRef.signalRecvThreadActivity ();
} while ( ! this->iiu.shutdownCmd );
{
epicsGuard < callbackMutex > cbGuard ( this->cbMutex );
this->iiu.cacRef.notifyDestroyFD ( cbGuard, this->iiu.sock );
}
}
/*
+3 -10
View File
@@ -99,7 +99,6 @@ public:
bool pushDatagramMsg ( const caHdr &hdr, const void *pExt, ca_uint16_t extsize);
void shutdown ();
double roundTripDelayEstimate () const;
void fdMaskSet ( fd_set & mask, SOCKET & maxFD ) const;
// exceptions
class noSocket {};
@@ -121,9 +120,9 @@ private:
SOCKET sock;
epics_auto_ptr < class searchTimer > pSearchTmr;
epics_auto_ptr < class repeaterSubscribeTimer > pRepeaterSubscribeTmr;
unsigned short repeaterPort;
unsigned short serverPort;
unsigned short localPort;
ca_uint16_t repeaterPort;
ca_uint16_t serverPort;
ca_uint16_t localPort;
bool shutdownCmd;
bool rtteActive;
bool lastReceivedSeqNoIsValid;
@@ -223,11 +222,5 @@ inline double udpiiu::roundTripDelayEstimate () const
return this->rtteMean;
}
inline void udpiiu::fdMaskSet ( fd_set & mask, SOCKET & maxFD ) const
{
maxFD = tsMax ( this->sock, maxFD );
FD_SET ( this->sock, & mask );
}
#endif // udpiiuh
+2 -11
View File
@@ -95,7 +95,7 @@ public:
comBufMemoryManager &, unsigned minorVersion, ipAddrToAsciiEngine & engineIn,
const cacChannel::priLev & priorityIn );
~tcpiiu ();
void start ( epicsGuard < callbackMutex > & );
void start ();
void initiateCleanShutdown ( epicsGuard < cacMutex > & );
void initiateAbortShutdown ( epicsGuard < callbackMutex > &,
epicsGuard <cacMutex > & );
@@ -134,8 +134,6 @@ public:
bool bytesArePendingInOS () const;
void fdMaskSet ( fd_set &, SOCKET & maxFd ) const;
private:
hostNameCache hostNameCacheInstance;
tcpRecvThread recvThread;
@@ -181,8 +179,7 @@ private:
void connect ();
const char * pHostName () const;
void blockUntilBytesArePendingInOS ();
void shutdown ( epicsGuard < callbackMutex > &,
epicsGuard <cacMutex > & );
void shutdown ( epicsGuard <cacMutex > & );
// send protocol stubs
void echoRequest ( epicsGuard < cacMutex > & );
@@ -250,12 +247,6 @@ inline unsigned tcpiiu::channelCount ()
return this->channelList.count ();
}
inline void tcpiiu::fdMaskSet ( fd_set & mask, SOCKET & maxFD ) const
{
maxFD = tsMax ( this->sock, maxFD );
FD_SET ( this->sock, & mask );
}
inline void tcpRecvThread::interruptSocketRecv ()
{
epicsThreadId threadId = this->thread.getId ();