44 #include "db_access_routines.h" 49 #include "dbChannel.h" 64 #include "menuConvert.h" 79 static int checkDatabase(
dbBase *pdbbase);
80 static void checkGeneralTime(
void);
81 static void initDrvSup(
void);
82 static void initRecSup(
void);
83 static void initDevSup(
void);
84 static void finishDevSup(
void);
85 static void initDatabase(
void);
86 static void initialProcess(
void);
87 static void exitDatabase(
void *
dummy);
95 static void iterateRecords(
recIterFunc func,
void *user);
113 static int iocBuild_1(
void)
116 errlogPrintf(
"iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
127 if (checkDatabase(pdbbase)) {
128 errlogPrintf(
"iocBuild: Aborting, bad database definition (DBD)!\n");
150 static int iocBuild_2(
void)
163 iterateRecords(prepareLinks,
NULL);
165 dbLockInitRecords(pdbbase);
178 dbProcessNotifyInit();
187 static int iocBuild_3(
void)
200 status = iocBuild_1();
201 if (status)
return status;
205 status = iocBuild_2();
206 if (status)
return status;
210 status = iocBuild_3();
223 status = iocBuild_1();
224 if (status)
return status;
226 dbCaLinkInitIsolated();
228 status = iocBuild_2();
229 if (status)
return status;
231 status = iocBuild_3();
260 "All initialization complete" :
303 static int checkDatabase(
dbBase *pdbbase)
308 errlogPrintf(
"checkDatabase: No database definitions loaded.\n");
314 errlogPrintf(
"checkDatabase: menuConvert not defined.\n");
317 if (pMenu->
nChoice <= menuConvertLINEAR) {
318 errlogPrintf(
"checkDatabase: menuConvert has too few choices.\n");
322 "menuConvertNO_CONVERSION")) {
323 errlogPrintf(
"checkDatabase: menuConvertNO_CONVERSION doesn't match.\n");
326 if (strcmp(pMenu->
papChoiceName[menuConvertSLOPE],
"menuConvertSLOPE")) {
327 errlogPrintf(
"checkDatabase: menuConvertSLOPE doesn't match.\n");
330 if (strcmp(pMenu->
papChoiceName[menuConvertLINEAR],
"menuConvertLINEAR")) {
331 errlogPrintf(
"checkDatabase: menuConvertLINEAR doesn't match.\n");
340 if (pMenu->
nChoice <= menuScanI_O_Intr) {
341 errlogPrintf(
"checkDatabase: menuScan has too few choices.\n");
345 "menuScanPassive")) {
346 errlogPrintf(
"checkDatabase: menuScanPassive doesn't match.\n");
351 errlogPrintf(
"checkDatabase: menuScanEvent doesn't match.\n");
355 "menuScanI_O_Intr")) {
356 errlogPrintf(
"checkDatabase: menuScanI_O_Intr doesn't match.\n");
359 if (pMenu->
nChoice <= SCAN_1ST_PERIODIC) {
360 errlogPrintf(
"checkDatabase: menuScan has no periodic choices.\n");
367 static void checkGeneralTime(
void)
373 static const char *
const tsfmt =
"%Y-%m-%d %H:%M:%S.%09f";
377 errlogPrintf(
"iocInit: Time provider has not yet synchronized.\n");
384 static void initDrvSup(
void)
403 static void initRecSup(
void)
414 if (!precordTypeLocation) {
415 errlogPrintf(
"iocInit record support for %s not found\n",
416 pdbRecordType->
name);
419 prset = precordTypeLocation->
prset;
420 pdbRecordType->
prset = prset;
427 static void initDevSup(
void)
450 static void finishDevSup(
void)
464 if (pdset && pdset->
init)
470 static void iterateRecords(
recIterFunc func,
void *user)
482 dbCommon *precord = pdbRecordNode->
precord;
484 if (!precord->name[0] ||
488 func(pdbRecordType, precord, user);
494 static void doInitRecord0(
dbRecordType *pdbRecordType, dbCommon *precord,
502 precord->rset = prset;
507 precord->pact =
FALSE;
510 if (precord->udf && precord->stat ==
UDF_ALARM)
511 precord->sevr = precord->udfs;
514 pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp);
515 precord->dset = pdevSup ? pdevSup->
pdset :
NULL;
521 static void doResolveLinks(
dbRecordType *pdbRecordType, dbCommon *precord,
525 short *link_ind = pdbRecordType->
link_ind;
529 for (j = 0; j < pdbRecordType->
no_links; j++) {
530 dbFldDes *pdbFldDes = papFldDes[link_ind[j]];
534 devSup *pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp);
548 static void doInitRecord1(
dbRecordType *pdbRecordType, dbCommon *precord,
559 static void initDatabase(
void)
562 iterateRecords(doInitRecord0,
NULL);
563 iterateRecords(doResolveLinks,
NULL);
564 iterateRecords(doInitRecord1,
NULL);
580 static void doRecordPini(
dbRecordType *rtype, dbCommon *precord,
void *user)
585 if (precord->pini != pphase->
pini)
return;
587 phas = precord->phas;
588 if (phas == pphase->
this) {
591 dbScanUnlock(precord);
592 }
else if (phas > pphase->
this && phas < pphase->next)
596 static void piniProcess(
int pini)
599 phase.
next = MIN_PHASE;
611 phase.
next = MAX_PHASE + 1;
612 iterateRecords(doRecordPini, &phase);
613 }
while (phase.
next != MAX_PHASE + 1);
620 piniProcess(menuPiniRUN);
624 piniProcess(menuPiniRUNNING);
628 piniProcess(menuPiniPAUSE);
632 piniProcess(menuPiniPAUSED);
640 static void initialProcess(
void)
643 piniProcess(menuPiniYES);
651 static void doCloseLinks(
dbRecordType *pdbRecordType, dbCommon *precord,
659 for (j = 0; j < pdbRecordType->
no_links; j++) {
671 dbRemoveLink(
NULL, plink);
676 (pdevSup = dbDSETtoDevSup(pdbRecordType, precord->dset)) &&
677 (pdsxt = pdevSup->
pdsxt) &&
687 precord->pact =
TRUE;
688 dbScanUnlock(precord);
692 static void doFreeRecord(
dbRecordType *pdbRecordType, dbCommon *precord,
697 for (j = 0; j < pdbRecordType->
no_links; j++) {
711 if (iocState ==
iocVoid)
return 0;
715 iterateRecords(doCloseLinks,
NULL);
737 iterateRecords(doFreeRecord,
NULL);
738 dbLockCleanupRecords(pdbbase);
742 dbProcessNotifyExit();
753 static void exitDatabase(
void *
dummy)
void initHookAnnounce(initHookState state)
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
The generalTime framework provides a mechanism for several time providers to be present within the sy...
epicsExportAddress(int, dbThreadRealtimeLock)
#define ellCount(PLIST)
Report the number of nodes in a list.
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
LIBCOM_API void epicsThreadRealtimeLock(void)
struct typed_rset * prset
Routines to get and set EPICS environment parameters.
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Miscellaneous macro definitions.
epicsUInt32 secPastEpoch
seconds since 0000 Jan 1, 1990
int errlogInit(int bufsize)
void dbInitDevSup(devSup *pdevSup, dset *pdset)
A doubly-linked list library.
#define ellNext(PNODE)
Find the next node in list.
LIBCOM_API size_t epicsStdCall epicsTimeToStrftime(char *pBuff, size_t bufLength, const char *pFormat, const epicsTimeStamp *pTS)
Convert epicsTimeStamp to string. See epicsTime::strftime()
epicsShareFunc struct drvet * registryDriverSupportFind(const char *name)
enum iocStateEnum getIocState(void)
long(* add_record)(struct dbCommon *precord)
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
Extended replacement for the Posix exit and atexit routines.
epicsShareFunc recordTypeLocation * registryRecordTypeFind(const char *name)
epicsShareFunc int coreRelease(void)
int errlogPrintf(const char *pFormat,...)
LIBCOM_API void epicsStdCall epicsSignalInstallSigHupIgnore(void)
epics::pvData::PVStructurePtr dummy
int initHookRegister(initHookFunction func)
long(* del_record)(struct dbCommon *precord)
int iocBuildIsolated(void)
int epicsStdCall epicsThreadIsOkToBlock(void)
EPICS time stamp, for use from C code.
int epicsStdCall epicsTimeGetEvent(epicsTimeStamp *pDest, int eventNumber)
Get time of event eventNumber into *pDest.
void(* recIterFunc)(dbRecordType *rtyp, dbCommon *prec, void *user)
#define ellInit(PLIST)
Initialize a list type.
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
void dbFreeLinkContents(struct link *plink)
long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
void epicsStdCall iocshFree(void)
OS-independent routines for ignoring Posix signals.
#define epicsAtExit(F, A)
Convenience macro to register a function and context value to be run when the process exits...
dbMenu * dbFindMenu(dbBase *pdbbase, const char *name)
epicsShareFunc dset * registryDeviceSupportFind(const char *name)
C++ and C descriptions for a thread.
#define DBRN_FLAGS_ISALIAS
#define ellFirst(PLIST)
Find the first node in list.