dbCa: iocInit wait for local CA links to connect

This commit is contained in:
Michael Davidsaver
2025-09-20 14:18:12 -05:00
parent 098b3968d6
commit a46bd5ae88
5 changed files with 62 additions and 15 deletions
+29 -6
View File
@@ -40,6 +40,7 @@
/* We can't include dbStaticLib.h here */
#define dbCalloc(nobj,size) callocMustSucceed(nobj,size,"dbCalloc")
#include <epicsAtomic.h>
#include "db_access_routines.h"
#include "dbCa.h"
#include "dbCaPvt.h"
@@ -64,6 +65,7 @@ extern int dbServiceIsolate;
static ELLLIST workList = ELLLIST_INIT; /* Work list for dbCaTask */
static epicsMutexId workListLock; /*Mutual exclusions semaphores for workList*/
static epicsEventId workListEvent; /*wakeup event for dbCaTask*/
static size_t initOutstanding;
static int removesOutstanding = 0;
#define removesOutstandingWarning 10000
@@ -340,7 +342,7 @@ static void dbCaLinkInitImpl(int isolate)
dbCaCtl = ctlPause;
dbCaWorker = epicsThreadCreateOpt("dbCaLink", dbCaTask, NULL, &opts);
/* wait for worker to startup and initialize dbCaClientContext */
/* wait for worker to startup, initialize dbCaClientContext, and connect local CA */
epicsEventMustWait(startStopEvent);
}
@@ -369,11 +371,12 @@ void dbCaPause(void)
epicsEventSignal(workListEvent);
}
}
void dbCaAddLinkCallback(struct link *plink,
dbCaCallback connect, dbCaCallback monitor, void *userPvt)
void dbCaAddLinkCallbackOpt(struct dbLocker *locker, struct link *plink,
dbCaCallback connect, dbCaCallback monitor, void *userPvt,
unsigned flags)
{
caLink *pca;
(void)locker; /* Passed for symmetry with dbDbAddLink(). So far unused. */
assert(!plink->value.pv_link.pvt);
@@ -385,6 +388,10 @@ void dbCaAddLinkCallback(struct link *plink,
pca->connect = connect;
pca->monitor = monitor;
pca->userPvt = userPvt;
pca->flags = flags;
if(flags & DBCA_CALLBACK_INIT_WAIT)
epicsAtomicIncrSizeT(&initOutstanding);
epicsMutexMustLock(pca->lock);
plink->lset = &dbCa_lset;
@@ -394,15 +401,22 @@ void dbCaAddLinkCallback(struct link *plink,
epicsMutexUnlock(pca->lock);
}
void dbCaAddLinkCallback(struct link *plink,
dbCaCallback connect, dbCaCallback monitor, void *userPvt)
{
dbCaAddLinkCallbackOpt(NULL, plink, connect, monitor, userPvt, 0);
}
long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType)
{
dbCaAddLinkCallback(plink, 0, 0, NULL);
dbCaAddLinkCallbackOpt(locker, plink, 0, 0, NULL, 0);
return 0;
}
void dbCaRemoveLink(struct dbLocker *locker, struct link *plink)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
(void)locker; /* Passed for symmetry with dbDbRemoveLink(). So far unused. */
if (!pca) return;
epicsMutexMustLock(pca->lock);
@@ -962,6 +976,10 @@ static void eventCallback(struct event_handler_args arg)
}
}
done:
if(pca->flags & DBCA_CALLBACK_INIT_WAIT) {
pca->flags &= ~DBCA_CALLBACK_INIT_WAIT;
addAction(pca, CA_INIT_WAIT);
}
epicsMutexUnlock(pca->lock);
if (monitor) monitor(userPvt);
}
@@ -1099,7 +1117,9 @@ static void dbCaTask(void *arg)
dbCaClientContext = ca_current_context ();
SEVCHK(ca_add_exception_event(exceptionCallback,NULL),
"ca_add_exception_event");
epicsEventSignal(startStopEvent);
if(epicsAtomicGetSizeT(&initOutstanding)==0)
epicsEventSignal(startStopEvent);
// else: defer to CA_INIT_WAIT
/* channel access event loop */
while (TRUE){
@@ -1255,6 +1275,9 @@ static void dbCaTask(void *arg)
db_process(prec);
dbScanUnlock(prec);
}
if ((link_action & CA_INIT_WAIT) && epicsAtomicDecrSizeT(&initOutstanding)==0) {
epicsEventSignal(startStopEvent);
}
}
SEVCHK(ca_flush_io(), "dbCaTask");
}
+21
View File
@@ -21,6 +21,19 @@
#include "epicsMutex.h"
#include "epicsTypes.h"
#include "link.h"
#include "shareLib.h"
#include "libCaAPI.h"
#ifndef INC_cadef_H
/* Copy some definitions so this header to be included from
* places where cadef.h and db_access.h can not.
*/
typedef void * chid;
typedef void * evid;
LIBCA_API extern const unsigned short dbr_value_size[];
LIBCA_API short epicsShareAPI ca_field_type (chid chan);
#define MAX_UNITS_SIZE 8
#endif
/* link_action mask */
#define CA_CLEAR_CHANNEL 0x1
@@ -32,6 +45,7 @@
#define CA_GET_ATTRIBUTES 0x40
#define CA_SYNC 0x1000
#define CA_DBPROCESS 0x2000
#define CA_INIT_WAIT 0x4000
/* write type */
#define CA_PUT 0x1
#define CA_PUT_CALLBACK 0x2
@@ -63,6 +77,7 @@ typedef struct caLink
dbCaCallback connect;
dbCaCallback monitor;
void *userPvt;
unsigned flags;
/* The following are for write request */
short putType;
dbCaCallback putCallback;
@@ -97,4 +112,10 @@ typedef struct caLink
unsigned long nUpdate;
}caLink;
#define DBCA_CALLBACK_INIT_WAIT (1)
void dbCaAddLinkCallbackOpt(struct dbLocker *locker, struct link *plink,
dbCaCallback connect, dbCaCallback monitor,
void *userPvt, unsigned flags);
#endif /* INC_dbCaPvt_H */
+4 -2
View File
@@ -31,7 +31,7 @@
#include "dbAccessDefs.h"
#include "dbAddr.h"
#include "dbBase.h"
#include "dbCa.h"
#include "dbCaPvt.h"
#include "dbCommon.h"
#include "dbConstLink.h"
#include "dbDbLink.h"
@@ -125,7 +125,9 @@ void dbInitLink(struct link *plink, short dbfType)
if (dbfType == DBF_INLINK)
plink->value.pv_link.pvlMask |= pvlOptInpNative;
dbCaAddLink(NULL, plink, dbfType);
int isLocal = dbChannelTest(plink->value.pv_link.pvname)==0;
dbCaAddLinkCallbackOpt(NULL, plink, NULL, NULL, NULL, isLocal ? DBCA_CALLBACK_INIT_WAIT : 0);
if (dbfType == DBF_FWDLINK) {
char *pperiod = strrchr(plink->value.pv_link.pvname, '.');