fixed a bug where the callback control gaurd was used from a different thread

than the one that created it
This commit is contained in:
Jeff Hill
2007-01-11 21:45:58 +00:00
parent 6ed4f091b2
commit cde78f0b70
12 changed files with 119 additions and 167 deletions

View File

@@ -40,13 +40,12 @@ CASG::~CASG ()
}
void CASG::destructor (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( this->verify ( guard ) ) {
this->reset ( cbGuard, guard );
this->reset ( guard );
this->client.uninstallCASG ( guard, *this );
this->magic = 0;
}
@@ -65,7 +64,7 @@ bool CASG::verify ( epicsGuard < epicsMutex > & ) const
* CASG::block ()
*/
int CASG::block (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > * pcbGuard,
epicsGuard < epicsMutex > & guard,
double timeout )
{
@@ -110,9 +109,15 @@ int CASG::block (
break;
}
{
if ( pcbGuard ) {
epicsGuardRelease < epicsMutex > unguard ( guard );
{
epicsGuardRelease < epicsMutex > uncbGuard ( *pcbGuard );
this->sem.wait ( remaining );
}
}
else {
epicsGuardRelease < epicsMutex > unguard ( guard );
epicsGuardRelease < epicsMutex > uncbGuard ( cbGuard );
this->sem.wait ( remaining );
}
@@ -124,18 +129,17 @@ int CASG::block (
delay = cur_time - beg_time;
}
this->reset ( cbGuard, guard );
this->reset ( guard );
return status;
}
void CASG::reset (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->destroyCompletedIO ( guard );
this->destroyPendingIO ( cbGuard, guard );
this->destroyPendingIO ( guard );
}
// lock must be applied
@@ -150,13 +154,11 @@ void CASG::destroyCompletedIO (
}
void CASG::destroyPendingIO (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
syncGroupNotify * pNotify;
while ( ( pNotify = this->ioPendingList.first () ) ) {
pNotify->cancel ( cbGuard, guard );
while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
pNotify->cancel ( guard );
// cancel must release the guard while
// canceling put callbacks so we
// must double check list membership
@@ -201,7 +203,6 @@ void CASG::show (
}
bool CASG::ioComplete (
epicsGuard < epicsMutex > & /* cbGuard */,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );

View File

@@ -364,16 +364,15 @@ int epicsShareAPI ca_create_channel (
int epicsShareAPI ca_clear_channel ( chid pChan )
{
ca_client_context & cac = pChan->getClientCtx ();
epicsGuard < epicsMutex > * pCBGuard = cac.pCallbackGuard.get();
if ( pCBGuard ) {
epicsGuard < epicsMutex > guard ( cac.mutex );
cac.destroyChannel ( *pCBGuard, guard, *pChan );
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
pChan->eliminateExcessiveSendBacklog ( guard );
}
else {
epicsGuard < epicsMutex > cbGuard ( cac.cbMutex );
epicsGuard < epicsMutex > guard ( cac.mutex );
cac.destroyChannel ( cbGuard, guard, *pChan );
catch ( cacChannel::notConnected & ) {
// intentionally ignored
}
pChan->destructor ( guard );
cac.oldChannelNotifyFreeList.release ( pChan );
return ECA_NORMAL;
}

View File

@@ -43,6 +43,8 @@ epicsShareDef epicsThreadPrivateId caClientCallbackThreadId;
static epicsThreadOnceId cacOnce = EPICS_THREAD_ONCE_INIT;
const unsigned ca_client_context :: flushBlockThreshold = 0x58000;
extern "C" void cacExitHandler ( void *)
{
epicsThreadPrivateDelete ( caClientCallbackThreadId );
@@ -65,6 +67,7 @@ cacService * ca_client_context::pDefaultService = 0;
epicsMutex * ca_client_context::pDefaultServiceInstallMutex;
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
createdByThread ( epicsThreadGetIdSelf () ),
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
pndRecvCnt ( 0u ), ioSeqNo ( 0u ), callbackThreadsPending ( 0u ),
@@ -189,22 +192,6 @@ ca_client_context::~ca_client_context ()
}
}
void ca_client_context::destroyChannel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
oldChannelNotify & chan )
{
try {
chan.eliminateExcessiveSendBacklog (
&cbGuard, guard );
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
}
chan.destructor ( cbGuard, guard );
this->oldChannelNotifyFreeList.release ( & chan );
}
void ca_client_context::destroyGetCopy (
epicsGuard < epicsMutex > & guard, getCopy & gc )
{
@@ -663,7 +650,7 @@ void ca_client_context::callbackProcessingCompleteNotify ()
cacChannel & ca_client_context::createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
oldChannelNotify & chan, cacChannel::priLev pri )
cacChannelNotify & chan, cacChannel::priLev pri )
{
guard.assertIdenticalMutex ( this->mutex );
return this->pServiceContext->createChannel (
@@ -753,32 +740,41 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
{
oldChannelNotify & chan = pMon->channel ();
ca_client_context & cac = chan.getClientCtx ();
epicsGuard < epicsMutex > * pCBGuard = cac.pCallbackGuard.get();
if ( pCBGuard ) {
cac.clearSubscriptionPrivate ( *pCBGuard, *pMon );
}
else {
epicsGuard < epicsMutex > cbGuard ( cac.cbMutex );
cac.clearSubscriptionPrivate ( cbGuard, *pMon );
}
return ECA_NORMAL;
}
void ca_client_context::clearSubscriptionPrivate (
epicsGuard < epicsMutex > & cbGuard, oldSubscription & subscr )
{
epicsGuard < epicsMutex > guard ( this->mutex );
oldChannelNotify & chan = subscr.channel ();
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
// if this stalls out on a live circuit then an exception
// can be forthcoming which we must ignore as the clear
// request must always be successful
chan.eliminateExcessiveSendBacklog (
& cbGuard, guard );
chan.eliminateExcessiveSendBacklog ( guard );
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
}
subscr.cancel ( cbGuard, guard );
pMon->cancel ( guard );
return ECA_NORMAL;
}
void ca_client_context :: eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & guard, cacChannel & chan )
{
if ( chan.requestMessageBytesPending ( guard ) >
ca_client_context :: flushBlockThreshold ) {
if ( this->pCallbackGuard.get() &&
this->createdByThread == epicsThreadGetIdSelf () ) {
// we need to be very careful about lock hierarchy
// inversion in this situation
epicsGuardRelease < epicsMutex > unguard ( guard );
{
epicsGuardRelease < epicsMutex > cbunguard (
* this->pCallbackGuard.get() );
{
epicsGuard < epicsMutex > nestedGuard ( this->mutex );
chan.flush ( nestedGuard );
}
}
}
else {
chan.flush ( guard );
}
}
}

View File

@@ -497,15 +497,15 @@ void cac::transferChanToVirtCircuit (
if ( ! sockAddrAreIdentical ( &addr, &chanAddr ) ) {
char acc[64];
pChan->getPIIU(guard)->getHostName ( guard, acc, sizeof ( acc ) );
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
msgForMultiplyDefinedPV ( this->ipToAEngine,
*this, pChan->pName ( guard ), acc );
// It is possible for the ioInitiate call below to
// call the callback directly if queue quota is exceeded.
// This callback takes the callback lock and therefore we
// must release the primary mutex here to avoid a lock
// hierarchy inversion.
epicsGuardRelease < epicsMutex > unguard ( guard );
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
msgForMultiplyDefinedPV ( this->ipToAEngine,
*this, pChan->pName ( guard ), acc );
pMsg->ioInitiate ( addr );
}
return;
@@ -566,19 +566,16 @@ void cac::transferChanToVirtCircuit (
}
void cac::destroyChannel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
nciu & chan )
{
guard.assertIdenticalMutex ( this->mutex );
cbGuard.assertIdenticalMutex ( this->cbMutex );
// uninstall channel so that recv threads
// will not start a new callback for this channel's IO.
if ( this->chanTable.remove ( chan ) != & chan ) {
throw std::logic_error ( "Invalid channel identifier" );
}
chan.~nciu ();
this->channelFreeList.release ( & chan );
}
@@ -642,12 +639,10 @@ netReadNotifyIO & cac::readNotifyRequest (
return *pIO.release();
}
baseNMIU * cac::destroyIO (
epicsGuard < epicsMutex > & cbGuard,
bool cac::destroyIO (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn, nciu & chan )
{
cbGuard.assertIdenticalMutex ( this->cbMutex );
guard.assertIdenticalMutex ( this->mutex );
baseNMIU * pIO = this->ioTable.remove ( idIn );
@@ -660,8 +655,9 @@ baseNMIU * cac::destroyIO (
// this uninstalls from the list and destroys the IO
pIO->exception ( guard, *this,
ECA_CHANDESTROY, chan.pName ( guard ) );
return true;
}
return pIO;
return false;
}
void cac::ioShow (

View File

@@ -135,9 +135,7 @@ public:
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannelNotify &, cacChannel::priLev );
void destroyChannel (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
nciu & );
epicsGuard < epicsMutex > &, nciu & );
void initiateConnect (
epicsGuard < epicsMutex > &, nciu &, netiiu * & );
nciu * lookupChannel (
@@ -156,8 +154,7 @@ public:
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem, unsigned mask,
cacStateNotify &, bool channelIsInstalled );
baseNMIU * destroyIO (
epicsGuard < epicsMutex > & cbGuard,
bool destroyIO (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn,
nciu & chan );

View File

@@ -64,25 +64,28 @@ void getCopy::completion (
unsigned size = dbr_size_n ( typeIn, countIn );
memcpy ( this->pValue, pDataIn, size );
this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
this->cacCtx.destroyGetCopy ( guard, *this );
}
else {
this->exception ( guard, ECA_INTERNAL,
"bad data type match in get copy back response",
typeIn, countIn);
}
this->cacCtx.destroyGetCopy ( guard, *this );
}
void getCopy::exception (
epicsGuard < epicsMutex > & guard,
int status, const char *pContext, unsigned /* typeIn */, arrayElementCount /* countIn */ )
{
oldChannelNotify & chanTmp ( this->chan );
unsigned typeTmp ( this->type );
arrayElementCount countTmp ( this->count );
this->cacCtx.destroyGetCopy ( guard, *this );
if ( status != ECA_CHANDESTROY ) {
this->cacCtx.exception ( guard, status, pContext,
__FILE__, __LINE__, this->chan, this->type,
this->count, CA_OP_GET );
__FILE__, __LINE__, chanTmp, typeTmp,
countTmp, CA_OP_GET );
}
this->cacCtx.destroyGetCopy ( guard, *this );
}
void getCopy::show ( unsigned level ) const

View File

@@ -76,27 +76,22 @@ nciu::~nciu ()
// channels are created by the user, and only destroyed by the user
// using this routine
void nciu::destroy (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard )
epicsGuard < epicsMutex > & guard )
{
while ( baseNMIU * pNetIO = this->eventq.first () ) {
assert ( this->cacCtx.destroyIO (
callbackControlGuard, mutualExclusionGuard,
pNetIO->getId (), *this ) );
guard, pNetIO->getId (), *this ) );
}
// if the claim reply has not returned yet then we will issue
// the clear channel request to the server when the claim reply
// arrives and there is no matching nciu in the client
if ( this->channelNode::isInstalledInServer ( mutualExclusionGuard ) ) {
this->getPIIU(mutualExclusionGuard)->clearChannelRequest (
mutualExclusionGuard, this->sid, this->id );
if ( this->channelNode::isInstalledInServer ( guard ) ) {
this->getPIIU(guard)->clearChannelRequest (
guard, this->sid, this->id );
}
this->piiu->uninstallChan ( mutualExclusionGuard, *this );
this->cacCtx.destroyChannel (
callbackControlGuard, mutualExclusionGuard, *this );
this->piiu->uninstallChan ( guard, *this );
this->cacCtx.destroyChannel ( guard, *this );
}
void * nciu::operator new ( size_t ) // X aCC 361
@@ -268,12 +263,16 @@ unsigned nciu::nameLen (
return this->nameLength;
}
void nciu::eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > * pCallbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard )
unsigned nciu::requestMessageBytesPending (
epicsGuard < epicsMutex > & guard )
{
this->piiu->eliminateExcessiveSendBacklog (
pCallbackGuard, mutualExclusionGuard );
return piiu->requestMessageBytesPending ( guard );
}
void nciu::flush (
epicsGuard < epicsMutex > & guard )
{
piiu->flush ( guard );
}
cacChannel::ioStatus nciu::read (
@@ -391,10 +390,9 @@ void nciu::subscribe (
}
void nciu::ioCancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, const ioid & idIn )
{
this->cacCtx.destroyIO ( cbGuard, guard, idIn, *this );
this->cacCtx.destroyIO ( guard, idIn, *this );
}
void nciu::ioShow (
@@ -577,7 +575,7 @@ void nciu::serviceShutdownNotify (
epicsGuard < epicsMutex > & mutualExclusionGuard )
{
this->setServerAddressUnknown ( noopIIU, mutualExclusionGuard );
this->notify().serviceShutdownNotify ( callbackControlGuard, mutualExclusionGuard );
this->notify().serviceShutdownNotify ( mutualExclusionGuard );
}
void channelNode::setRespPendingState (

View File

@@ -46,14 +46,13 @@
#include "cadef.h"
#include "syncGroup.h"
struct oldChannelNotify : public cacChannelNotify {
struct oldChannelNotify : private cacChannelNotify {
public:
oldChannelNotify (
epicsGuard < epicsMutex > &, struct ca_client_context &,
const char * pName, caCh * pConnCallBackIn,
void * pPrivateIn, capri priority );
void destructor (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
// legacy C API
@@ -114,9 +113,6 @@ public:
unsigned level ) const;
void initiateConnect (
epicsGuard < epicsMutex > & );
void eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > * pCallbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard );
void read (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
@@ -126,13 +122,15 @@ public:
unsigned type, arrayElementCount count, const void *pValue,
cacWriteNotify &, cacChannel::ioid *pId = 0 );
void ioCancel (
epicsGuard < epicsMutex > & callbackControl,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const cacChannel::ioid & );
void ioShow (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid &, unsigned level ) const;
ca_client_context & getClientCtx ();
void eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & );
void * operator new ( size_t size,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void * ,
@@ -151,7 +149,6 @@ private:
void connectNotify ( epicsGuard < epicsMutex > & );
void disconnectNotify ( epicsGuard < epicsMutex > & );
void serviceShutdownNotify (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard );
void accessRightsNotify (
epicsGuard < epicsMutex > &, const caAccessRights & );
@@ -263,7 +260,6 @@ public:
~oldSubscription ();
oldChannelNotify & channel () const;
void cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void * operator new ( size_t size,
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & );
@@ -301,10 +297,10 @@ public:
void replaceErrLogHandler ( caPrintfFunc * ca_printf_func );
cacChannel & createChannel (
epicsGuard < epicsMutex > &, const char * pChannelName,
oldChannelNotify &, cacChannel::priLev pri );
cacChannelNotify &, cacChannel::priLev pri );
void flush ( epicsGuard < epicsMutex > & );
void eliminateExcessiveSendBacklog (
oldChannelNotify & chan, epicsGuard < epicsMutex > & guard );
epicsGuard < epicsMutex > &, cacChannel & );
int pendIO ( const double & timeout );
int pendEvent ( const double & timeout );
bool ioComplete () const;
@@ -339,14 +335,14 @@ public:
void vSignal ( int ca_status, const char * pfilenm,
int lineno, const char *pFormat, va_list args );
bool preemptiveCallbakIsEnabled () const;
void destroyChannel ( epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, oldChannelNotify & chan );
void destroyGetCopy ( epicsGuard < epicsMutex > &, getCopy & );
void destroyGetCallback ( epicsGuard < epicsMutex > &, getCallback & );
void destroyPutCallback ( epicsGuard < epicsMutex > &, putCallback & );
void destroySubscription ( epicsGuard < epicsMutex > &, oldSubscription & );
epicsMutex & mutexRef () const;
// legacy C API
friend int epicsShareAPI ca_create_channel (
const char * name_str, caCh * conn_func, void * puser,
capri priority, chid * chanptr );
@@ -365,8 +361,6 @@ public:
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
evid *monixptr );
// legacy C API
friend int epicsShareAPI ca_flush_io ();
friend int epicsShareAPI ca_clear_subscription ( evid pMon );
friend int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid );
@@ -389,6 +383,7 @@ private:
mutable epicsMutex cbMutex;
epicsEvent ioDone;
epicsEvent callbackThreadActivityComplete;
epicsThreadId createdByThread;
epics_auto_ptr < epicsGuard < epicsMutex > > pCallbackGuard;
epics_auto_ptr < cacContext > pServiceContext;
caExceptionHandler * ca_exception_func;
@@ -409,8 +404,6 @@ private:
void callbackProcessingCompleteNotify ();
cacContext & createNetworkContext (
epicsMutex & mutualExclusion, epicsMutex & callbackControl );
void clearSubscriptionPrivate (
epicsGuard < epicsMutex > & cbGuard, oldSubscription & subscr );
ca_client_context ( const ca_client_context & );
ca_client_context & operator = ( const ca_client_context & );
@@ -419,6 +412,7 @@ private:
friend void cacExitHandler ( void *);
static cacService * pDefaultService;
static epicsMutex * pDefaultServiceInstallMutex;
static const unsigned flushBlockThreshold;
};
int fetchClientContext ( ca_client_context * * ppcac );
@@ -448,20 +442,11 @@ inline void oldChannelNotify::initiateConnect (
this->io.initiateConnect ( guard );
}
inline void oldChannelNotify::eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > * pCallbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard )
{
this->io.eliminateExcessiveSendBacklog (
pCallbackGuard, mutualExclusionGuard );
}
inline void oldChannelNotify::ioCancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & id )
{
this->io.ioCancel ( cbGuard, guard, id );
this->io.ioCancel ( guard, id );
}
inline void oldChannelNotify::ioShow (
@@ -471,6 +456,12 @@ inline void oldChannelNotify::ioShow (
this->io.ioShow ( guard, id, level );
}
inline void oldChannelNotify::eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & guard )
{
this->cacCtx.eliminateExcessiveSendBacklog ( guard, this->io );
}
inline void * oldChannelNotify::operator new ( size_t size,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & freeList )
{
@@ -500,10 +491,9 @@ inline void oldSubscription::operator delete ( void *pCadaver,
#endif
inline void oldSubscription::cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
this->chan.ioCancel ( cbGuard, guard, this->id );
this->chan.ioCancel ( guard, this->id );
}
inline oldChannelNotify & oldSubscription::channel () const
@@ -569,12 +559,5 @@ inline unsigned ca_client_context::sequenceNumberOfOutstandingIO (
// perhaps on SMP systems THERE should be lock/unlock around this
return this->ioSeqNo;
}
inline void ca_client_context::eliminateExcessiveSendBacklog (
oldChannelNotify & chan, epicsGuard < epicsMutex > & guard )
{
chan.eliminateExcessiveSendBacklog (
this->pCallbackGuard.get(), guard );
}
#endif // ifndef oldAccessh

View File

@@ -65,11 +65,10 @@ oldChannelNotify::~oldChannelNotify ()
}
void oldChannelNotify::destructor (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
this->io.destroy ( cbGuard, guard );
this->io.destroy ( guard );
// no need to worry about a connect preempting here because
// the io (the nciu) has been destroyed above
if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) {
@@ -119,13 +118,9 @@ void oldChannelNotify::disconnectNotify (
}
void oldChannelNotify::serviceShutdownNotify (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard )
epicsGuard < epicsMutex > & guard )
{
this->cacCtx.destroyChannel (
callbackControlGuard,
mutualExclusionGuard,
*this );
this->disconnectNotify ( guard );
}
void oldChannelNotify::accessRightsNotify (
@@ -287,8 +282,7 @@ int epicsShareAPI ca_array_get ( chtype type,
}
unsigned tmpType = static_cast < unsigned > ( type );
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
pChan->eliminateExcessiveSendBacklog (
pChan->getClientCtx().pCallbackGuard.get(), guard );
pChan->eliminateExcessiveSendBacklog ( guard );
autoPtrFreeList < getCopy, 0x400, epicsMutexNOOP > pNotify
( pChan->getClientCtx().getCopyFreeList,
new ( pChan->getClientCtx().getCopyFreeList )
@@ -355,8 +349,7 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
unsigned tmpType = static_cast < unsigned > ( type );
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
pChan->eliminateExcessiveSendBacklog (
pChan->getClientCtx().pCallbackGuard.get(), guard );
pChan->eliminateExcessiveSendBacklog ( guard );
autoPtrFreeList < getCallback, 0x400, epicsMutexNOOP > pNotify
( pChan->getClientCtx().getCallbackFreeList,
new ( pChan->getClientCtx().getCallbackFreeList )
@@ -427,8 +420,7 @@ int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
return ECA_BADTYPE;
}
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
pChan->eliminateExcessiveSendBacklog (
pChan->getClientCtx().pCallbackGuard.get(), guard );
pChan->eliminateExcessiveSendBacklog ( guard );
unsigned tmpType = static_cast < unsigned > ( type );
autoPtrFreeList < putCallback, 0x400, epicsMutexNOOP > pNotify
( pChan->getClientCtx().putCallbackFreeList,
@@ -491,8 +483,7 @@ int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
int caStatus;
try {
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
pChan->eliminateExcessiveSendBacklog (
pChan->getClientCtx().pCallbackGuard.get(), guard );
pChan->eliminateExcessiveSendBacklog ( guard );
pChan->io.write ( guard, tmpType, count, pValue );
caStatus = ECA_NORMAL;
}
@@ -569,8 +560,7 @@ int epicsShareAPI ca_create_subscription (
// can be forthcoming which we must ignore (this is a
// special case preserving legacy ca_create_subscription
// behavior)
pChan->eliminateExcessiveSendBacklog (
pChan->getClientCtx().pCallbackGuard.get(), guard );
pChan->eliminateExcessiveSendBacklog ( guard );
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored (its ok to subscribe when not connected)

View File

@@ -68,7 +68,6 @@ public:
virtual bool ioPending (
epicsGuard < epicsMutex > & guard ) = 0;
virtual void cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard ) = 0;
virtual void show (
epicsGuard < epicsMutex > &,
@@ -92,7 +91,6 @@ public:
void begin ( epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count );
void cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
protected:
@@ -135,7 +133,6 @@ public:
void begin ( epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pValueIn );
void cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
protected:
@@ -170,16 +167,13 @@ struct CASG : public chronIntIdRes < CASG >, private casgRecycle {
public:
CASG ( epicsGuard < epicsMutex > &, ca_client_context & cacIn );
void destructor (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
bool ioComplete (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
bool verify ( epicsGuard < epicsMutex > & ) const;
int block ( epicsGuard < epicsMutex > & cbGuard,
int block ( epicsGuard < epicsMutex > * pcbGuard,
epicsGuard < epicsMutex > & guard, double timeout );
void reset ( epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void reset ( epicsGuard < epicsMutex > & guard );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
void show ( unsigned level ) const;
void get ( epicsGuard < epicsMutex > &, chid pChan,
@@ -214,7 +208,6 @@ private:
epicsGuard < epicsMutex > &, syncGroupReadNotify & io );
void destroyPendingIO (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void destroyCompletedIO (
epicsGuard < epicsMutex > & guard );

View File

@@ -38,8 +38,7 @@ void syncGroupReadNotify::begin (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount count )
{
this->chan->getClientCtx().
eliminateExcessiveSendBacklog ( *this->chan, guard );
this->chan->eliminateExcessiveSendBacklog ( guard );
this->ioComplete = false;
boolFlagManager mgr ( this->idIsValid );
this->chan->read ( guard, type, count, *this, &this->id );
@@ -47,11 +46,10 @@ void syncGroupReadNotify::begin (
}
void syncGroupReadNotify::cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
if ( this->idIsValid ) {
this->chan->ioCancel ( cbGuard, guard, this->id );
this->chan->ioCancel ( guard, this->id );
this->idIsValid = false;
}
}

View File

@@ -36,8 +36,7 @@ void syncGroupWriteNotify::begin (
epicsGuard < epicsMutex > & guard, unsigned type,
arrayElementCount count, const void * pValueIn )
{
this->chan->getClientCtx().eliminateExcessiveSendBacklog (
*this->chan, guard );
this->chan->eliminateExcessiveSendBacklog ( guard );
this->ioComplete = false;
boolFlagManager mgr ( this->idIsValid );
this->chan->write ( guard, type, count,
@@ -46,11 +45,10 @@ void syncGroupWriteNotify::begin (
}
void syncGroupWriteNotify::cancel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
if ( this->idIsValid ) {
this->chan->ioCancel ( cbGuard, guard, this->id );
this->chan->ioCancel ( guard, this->id );
this->idIsValid = false;
}
}