fix testdbCaWaitForEvent()

sync with CA context thread(s) as well as dbCa worker.
This commit is contained in:
Michael Davidsaver
2025-10-17 16:18:43 -07:00
committed by mdavidsaver
parent bbc4c6358e
commit 71e4635d34
9 changed files with 57 additions and 5 deletions

View File

@@ -717,6 +717,18 @@ int epicsStdCall ca_context_status ( ca_client_context * pcac, unsigned level )
return ECA_NORMAL;
}
extern "C"
LIBCA_API
void dbCaSyncLocal(void);
void dbCaSyncLocal(void)
{
if(struct ca_client_context * ctxt = ca_current_context()) {
// bounce for access to private data member
ctxt->sync();
}
}
/*
* ca_current_context ()
*

View File

@@ -728,6 +728,12 @@ epicsMutex & ca_client_context::mutexRef () const
return this->mutex;
}
void ca_client_context::sync()
{
// bounce through vtable
this->pServiceContext->sync();
}
cacContext & ca_client_context::createNetworkContext (
epicsMutex & mutexIn, epicsMutex & cbMutexIn )
{

View File

@@ -398,6 +398,8 @@ void cac::flush ( epicsGuard < epicsMutex > & guard )
}
}
void cac::sync() {}
unsigned cac::circuitCount (
epicsGuard < epicsMutex > & guard ) const
{

View File

@@ -115,6 +115,7 @@ public:
// IO management
void flush ( epicsGuard < epicsMutex > & guard );
void sync ();
bool executeResponse ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, caHdrLargeArray &, char *pMsgBody );

View File

@@ -279,6 +279,7 @@ public:
cacChannel::priLev = cacChannel::priorityDefault ) = 0;
virtual void flush (
epicsGuard < epicsMutex > & ) = 0;
virtual void sync () = 0;
virtual unsigned circuitCount (
epicsGuard < epicsMutex > & ) const = 0;
virtual void selfTest (

View File

@@ -349,6 +349,7 @@ public:
void destroyPutCallback ( epicsGuard < epicsMutex > &, putCallback & );
void destroySubscription ( epicsGuard < epicsMutex > &, oldSubscription & );
epicsMutex & mutexRef () const;
void sync();
template < class T >
void whenThereIsAnExceptionDestroySyncGroupIO ( epicsGuard < epicsMutex > &, T & );

View File

@@ -207,6 +207,7 @@ private:
cacChannel::priLev );
void flush (
epicsGuard < epicsMutex > & );
void sync ();
unsigned circuitCount (
epicsGuard < epicsMutex > & ) const;
void selfTest (

View File

@@ -209,9 +209,9 @@ void testdbCaWaitForEventCB(void *raw)
{
struct waitPvt *pvt = raw;
epicsMutexMustLock(pvt->pca->lock);
epicsMutexMustLock(workListLock);
epicsEventMustTrigger(pvt->evt);
epicsMutexUnlock(pvt->pca->lock);
epicsMutexUnlock(workListLock);
}
static
@@ -239,8 +239,6 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
dbScanUnlock(plink->precord);
epicsEventMustWait(evt);
/* ensure worker has finished executing */
dbCaSync();
dbScanLock(plink->precord);
epicsMutexMustLock(pca->lock);
@@ -250,8 +248,15 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
pca->userPvt = NULL;
}
epicsEventDestroy(evt);
epicsMutexUnlock(pca->lock);
/* ensure worker has finished executing */
dbCaSync();
epicsMutexMustLock(workListLock); /* lock to ensure that epicsEventMustTrigger() has returned */
epicsEventDestroy(evt);
epicsMutexUnlock(workListLock);
caLinkDec(pca);
dbScanUnlock(plink->precord);
}
@@ -266,6 +271,10 @@ void testdbCaWaitForUpdateCount(DBLINK *plink, unsigned long cnt)
testdbCaWaitForEvent(plink, cnt, testEventCount);
}
// private access to access.cpp
LIBCA_API
void dbCaSyncLocal(void);
/* Block until worker thread has processed all previously queued actions.
* Does not prevent additional actions from being queued.
*/
@@ -274,6 +283,8 @@ void dbCaSync(void)
epicsEventId wake;
caLink templink;
dbCaSyncLocal();
/* we only partially initialize templink.
* It has no link field and no subscription
* so the worker must handle it early

View File

@@ -399,6 +399,23 @@ void dbContext::flush (
}
}
static
void dbContextDummyExtraLabor(void *) {}
void dbContext::sync()
{
// ctx created lazily on first subscription
{
epicsGuard<epicsMutex> G(mutex);
if(!ctx)
return;
}
// assumes dbContext makes no other use of extra labor
db_add_extra_labor_event(ctx, dbContextDummyExtraLabor, NULL);
db_post_extra_labor(ctx);
db_flush_extra_labor_event(ctx);
}
unsigned dbContext::circuitCount (
epicsGuard < epicsMutex > & guard ) const
{