This is Unofficial EPICS BASE Doxygen Site
iocInit.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * Copyright (c) 2013 Helmholtz-Zentrum Berlin
7 * für Materialien und Energie GmbH.
8 * EPICS BASE is distributed subject to a Software License Agreement found
9 * in file LICENSE that is included with this distribution.
10 \*************************************************************************/
11 /*
12  * Original Author: Marty Kraimer
13  * Date: 06-01-91
14  */
15 
16 
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <limits.h>
24 
25 #include "dbDefs.h"
26 #include "ellLib.h"
27 #include "envDefs.h"
28 #include "epicsExit.h"
29 #include "epicsGeneralTime.h"
30 #include "epicsPrint.h"
31 #include "epicsSignal.h"
32 #include "epicsThread.h"
33 #include "errMdef.h"
34 #include "iocsh.h"
35 #include "taskwd.h"
36 
37 #include "caeventmask.h"
38 
39 #include "epicsExport.h" /* defines epicsExportSharedSymbols */
40 #include "alarm.h"
41 #include "asDbLib.h"
42 #include "callback.h"
43 #include "dbAccess.h"
44 #include "db_access_routines.h"
45 #include "dbAddr.h"
46 #include "dbBase.h"
47 #include "dbBkpt.h"
48 #include "dbCa.h"
49 #include "dbChannel.h"
50 #include "dbCommon.h"
51 #include "dbFldTypes.h"
52 #include "dbLock.h"
53 #include "dbNotify.h"
54 #include "dbScan.h"
55 #include "dbServer.h"
56 #include "dbStaticLib.h"
57 #include "dbStaticPvt.h"
58 #include "devSup.h"
59 #include "drvSup.h"
60 #include "epicsRelease.h"
61 #include "initHooks.h"
62 #include "iocInit.h"
63 #include "link.h"
64 #include "menuConvert.h"
65 #include "menuPini.h"
66 #include "recGbl.h"
67 #include "recSup.h"
68 #include "registryDeviceSupport.h"
69 #include "registryDriverSupport.h"
70 #include "registryJLinks.h"
71 #include "registryRecordType.h"
72 
73 static enum iocStateEnum iocState = iocVoid;
74 static enum {
76 } iocBuildMode;
77 
78 /* define forward references*/
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);
88 
89 /*
90  * Iterate through all record instances (but not aliases),
91  * calling a function for each one.
92  */
93 typedef void (*recIterFunc)(dbRecordType *rtyp, dbCommon *prec, void *user);
94 
95 static void iterateRecords(recIterFunc func, void *user);
96 
99 
101 {
102  return iocState;
103 }
104 
105 /*
106  * Initialize EPICS on the IOC.
107  */
108 int iocInit(void)
109 {
110  return iocBuild() || iocRun();
111 }
112 
113 static int iocBuild_1(void)
114 {
115  if (iocState != iocVoid) {
116  errlogPrintf("iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
117  return -1;
118  }
119  errlogInit(0);
121 
122  if (!epicsThreadIsOkToBlock()) {
124  }
125 
126  errlogPrintf("Starting iocInit\n");
127  if (checkDatabase(pdbbase)) {
128  errlogPrintf("iocBuild: Aborting, bad database definition (DBD)!\n");
129  return -1;
130  }
133 
134  coreRelease();
135  iocState = iocBuilding;
136 
137  checkGeneralTime();
138  taskwdInit();
139  callbackInit();
141 
142  return 0;
143 }
144 
145 static void prepareLinks(dbRecordType *rtyp, dbCommon *prec, void *junk)
146 {
147  dbInitRecordLinks(rtyp, prec);
148 }
149 
150 static int iocBuild_2(void)
151 {
153 
154  initDrvSup();
156 
157  initRecSup();
159 
160  initDevSup();
161  initHookAnnounce(initHookAfterInitDevSup); /* used by autosave pass 0 */
162 
163  iterateRecords(prepareLinks, NULL);
164 
165  dbLockInitRecords(pdbbase);
166  initDatabase();
167  dbBkptInit();
168  initHookAnnounce(initHookAfterInitDatabase); /* used by autosave pass 1 */
169 
170  finishDevSup();
172 
173  scanInit();
174  if (asInit()) {
175  errlogPrintf("iocBuild: asInit Failed.\n");
176  return -1;
177  }
178  dbProcessNotifyInit();
179  epicsThreadSleep(.5);
181 
182  initialProcess();
184  return 0;
185 }
186 
187 static int iocBuild_3(void)
188 {
190 
191  iocState = iocBuilt;
193  return 0;
194 }
195 
196 int iocBuild(void)
197 {
198  int status;
199 
200  status = iocBuild_1();
201  if (status) return status;
202 
203  dbCaLinkInit();
204 
205  status = iocBuild_2();
206  if (status) return status;
207 
208  dbInitServers();
209 
210  status = iocBuild_3();
211 
214 
215  if (!status) iocBuildMode = buildServers;
216  return status;
217 }
218 
220 {
221  int status;
222 
223  status = iocBuild_1();
224  if (status) return status;
225 
226  dbCaLinkInitIsolated();
227 
228  status = iocBuild_2();
229  if (status) return status;
230 
231  status = iocBuild_3();
232  if (!status) iocBuildMode = buildIsolated;
233  return status;
234 }
235 
236 int iocRun(void)
237 {
238  if (iocState != iocPaused && iocState != iocBuilt) {
239  errlogPrintf("iocRun: IOC not paused\n");
240  return -1;
241  }
243 
244  /* Enable scan tasks and some driver support functions. */
245  scanRun();
246  dbCaRun();
248  if (iocState == iocBuilt)
250 
251  if (iocBuildMode == buildServers) {
252  dbRunServers();
254  }
255 
256  if (iocState == iocBuilt)
258 
259  errlogPrintf("iocRun: %s\n", iocState == iocBuilt ?
260  "All initialization complete" :
261  "IOC restarted");
262  iocState = iocRunning;
264  return 0;
265 }
266 
267 int iocPause(void)
268 {
269  if (iocState != iocRunning) {
270  errlogPrintf("iocPause: IOC not running\n");
271  return -1;
272  }
274 
275  if (iocBuildMode == buildServers) {
276  dbPauseServers();
278  }
279 
280  dbCaPause();
281  scanPause();
283 
284  iocState = iocPaused;
285  errlogPrintf("iocPause: IOC suspended\n");
287  return 0;
288 }
289 
290 /*
291  * Database sanity checks
292  *
293  * This is not an attempt to sanity-check the whole .dbd file, only
294  * two menus normally get modified by users: menuConvert and menuScan.
295  *
296  * The menuConvert checks were added to flag problems with IOCs
297  * converted from 3.13.x, where the SLOPE choice didn't exist.
298  *
299  * The menuScan checks make sure the user didn't fiddle too much
300  * when creating new periodic scan choices.
301  */
302 
303 static int checkDatabase(dbBase *pdbbase)
304 {
305  const dbMenu *pMenu;
306 
307  if (!pdbbase) {
308  errlogPrintf("checkDatabase: No database definitions loaded.\n");
309  return -1;
310  }
311 
312  pMenu = dbFindMenu(pdbbase, "menuConvert");
313  if (!pMenu) {
314  errlogPrintf("checkDatabase: menuConvert not defined.\n");
315  return -1;
316  }
317  if (pMenu->nChoice <= menuConvertLINEAR) {
318  errlogPrintf("checkDatabase: menuConvert has too few choices.\n");
319  return -1;
320  }
321  if (strcmp(pMenu->papChoiceName[menuConvertNO_CONVERSION],
322  "menuConvertNO_CONVERSION")) {
323  errlogPrintf("checkDatabase: menuConvertNO_CONVERSION doesn't match.\n");
324  return -1;
325  }
326  if (strcmp(pMenu->papChoiceName[menuConvertSLOPE], "menuConvertSLOPE")) {
327  errlogPrintf("checkDatabase: menuConvertSLOPE doesn't match.\n");
328  return -1;
329  }
330  if (strcmp(pMenu->papChoiceName[menuConvertLINEAR], "menuConvertLINEAR")) {
331  errlogPrintf("checkDatabase: menuConvertLINEAR doesn't match.\n");
332  return -1;
333  }
334 
335  pMenu = dbFindMenu(pdbbase, "menuScan");
336  if (!pMenu) {
337  errlogPrintf("checkDatabase: menuScan not defined.\n");
338  return -1;
339  }
340  if (pMenu->nChoice <= menuScanI_O_Intr) {
341  errlogPrintf("checkDatabase: menuScan has too few choices.\n");
342  return -1;
343  }
344  if (strcmp(pMenu->papChoiceName[menuScanPassive],
345  "menuScanPassive")) {
346  errlogPrintf("checkDatabase: menuScanPassive doesn't match.\n");
347  return -1;
348  }
349  if (strcmp(pMenu->papChoiceName[menuScanEvent],
350  "menuScanEvent")) {
351  errlogPrintf("checkDatabase: menuScanEvent doesn't match.\n");
352  return -1;
353  }
354  if (strcmp(pMenu->papChoiceName[menuScanI_O_Intr],
355  "menuScanI_O_Intr")) {
356  errlogPrintf("checkDatabase: menuScanI_O_Intr doesn't match.\n");
357  return -1;
358  }
359  if (pMenu->nChoice <= SCAN_1ST_PERIODIC) {
360  errlogPrintf("checkDatabase: menuScan has no periodic choices.\n");
361  return -1;
362  }
363 
364  return 0;
365 }
366 
367 static void checkGeneralTime(void)
368 {
369  epicsTimeStamp ts;
370 
371  epicsTimeGetCurrent(&ts);
372  if (ts.secPastEpoch < 2*24*60*60) {
373  static const char * const tsfmt = "%Y-%m-%d %H:%M:%S.%09f";
374  char buff[40];
375 
376  epicsTimeToStrftime(buff, sizeof(buff), tsfmt, &ts);
377  errlogPrintf("iocInit: Time provider has not yet synchronized.\n");
378  }
379 
380  epicsTimeGetEvent(&ts, 1); /* Prime gtPvt.lastEventProvider for ISRs */
381 }
382 
383 
384 static void initDrvSup(void) /* Locate all driver support entry tables */
385 {
386  drvSup *pdrvSup;
387 
388  for (pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList); pdrvSup;
389  pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) {
390  struct drvet *pdrvet = registryDriverSupportFind(pdrvSup->name);
391 
392  if (!pdrvet) {
393  errlogPrintf("iocInit: driver %s not found\n", pdrvSup->name);
394  continue;
395  }
396  pdrvSup->pdrvet = pdrvet;
397 
398  if (pdrvet->init)
399  pdrvet->init();
400  }
401 }
402 
403 static void initRecSup(void)
404 {
405  dbRecordType *pdbRecordType;
406 
407  for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
408  pdbRecordType;
409  pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
410  recordTypeLocation *precordTypeLocation =
411  registryRecordTypeFind(pdbRecordType->name);
412  rset *prset;
413 
414  if (!precordTypeLocation) {
415  errlogPrintf("iocInit record support for %s not found\n",
416  pdbRecordType->name);
417  continue;
418  }
419  prset = precordTypeLocation->prset;
420  pdbRecordType->prset = prset;
421  if (prset->init) {
422  prset->init();
423  }
424  }
425 }
426 
427 static void initDevSup(void)
428 {
429  dbRecordType *pdbRecordType;
430 
431  for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
432  pdbRecordType;
433  pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
434  devSup *pdevSup;
435 
436  for (pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
437  pdevSup;
438  pdevSup = (devSup *)ellNext(&pdevSup->node)) {
439  dset *pdset = registryDeviceSupportFind(pdevSup->name);
440 
441  if (!pdset) {
442  errlogPrintf("device support %s not found\n",pdevSup->name);
443  continue;
444  }
445  dbInitDevSup(pdevSup, pdset); /* Calls pdset->init(0) */
446  }
447  }
448 }
449 
450 static void finishDevSup(void)
451 {
452  dbRecordType *pdbRecordType;
453 
454  for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
455  pdbRecordType;
456  pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
457  devSup *pdevSup;
458 
459  for (pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
460  pdevSup;
461  pdevSup = (devSup *)ellNext(&pdevSup->node)) {
462  dset *pdset = pdevSup->pdset;
463 
464  if (pdset && pdset->init)
465  pdset->init(1);
466  }
467  }
468 }
469 
470 static void iterateRecords(recIterFunc func, void *user)
471 {
472  dbRecordType *pdbRecordType;
473 
474  for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
475  pdbRecordType;
476  pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
477  dbRecordNode *pdbRecordNode;
478 
479  for (pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
480  pdbRecordNode;
481  pdbRecordNode = (dbRecordNode *)ellNext(&pdbRecordNode->node)) {
482  dbCommon *precord = pdbRecordNode->precord;
483 
484  if (!precord->name[0] ||
485  pdbRecordNode->flags & DBRN_FLAGS_ISALIAS)
486  continue;
487 
488  func(pdbRecordType, precord, user);
489  }
490  }
491  return;
492 }
493 
494 static void doInitRecord0(dbRecordType *pdbRecordType, dbCommon *precord,
495  void *user)
496 {
497  rset *prset = pdbRecordType->prset;
498  devSup *pdevSup;
499 
500  if (!prset) return; /* unlikely */
501 
502  precord->rset = prset;
503  precord->mlok = epicsMutexMustCreate();
504  ellInit(&precord->mlis);
505 
506  /* Reset the process active field */
507  precord->pact = FALSE;
508 
509  /* Initial UDF severity */
510  if (precord->udf && precord->stat == UDF_ALARM)
511  precord->sevr = precord->udfs;
512 
513  /* Init DSET NOTE that result may be NULL */
514  pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp);
515  precord->dset = pdevSup ? pdevSup->pdset : NULL;
516 
517  if (prset->init_record)
518  prset->init_record(precord, 0);
519 }
520 
521 static void doResolveLinks(dbRecordType *pdbRecordType, dbCommon *precord,
522  void *user)
523 {
524  dbFldDes **papFldDes = pdbRecordType->papFldDes;
525  short *link_ind = pdbRecordType->link_ind;
526  int j;
527 
528  /* For all the links in the record type... */
529  for (j = 0; j < pdbRecordType->no_links; j++) {
530  dbFldDes *pdbFldDes = papFldDes[link_ind[j]];
531  DBLINK *plink = (DBLINK*)((char*)precord + pdbFldDes->offset);
532 
533  if (ellCount(&precord->rdes->devList) > 0 && pdbFldDes->isDevLink) {
534  devSup *pdevSup = dbDTYPtoDevSup(pdbRecordType, precord->dtyp);
535 
536  if (pdevSup) {
537  struct dsxt *pdsxt = pdevSup->pdsxt;
538  if (pdsxt && pdsxt->add_record) {
539  pdsxt->add_record(precord);
540  }
541  }
542  }
543 
544  dbInitLink(plink, pdbFldDes->field_type);
545  }
546 }
547 
548 static void doInitRecord1(dbRecordType *pdbRecordType, dbCommon *precord,
549  void *user)
550 {
551  rset *prset = pdbRecordType->prset;
552 
553  if (!prset) return; /* unlikely */
554 
555  if (prset->init_record)
556  prset->init_record(precord, 1);
557 }
558 
559 static void initDatabase(void)
560 {
561  dbChannelInit();
562  iterateRecords(doInitRecord0, NULL);
563  iterateRecords(doResolveLinks, NULL);
564  iterateRecords(doInitRecord1, NULL);
565 
566  epicsAtExit(exitDatabase, NULL);
567  return;
568 }
569 
570 /*
571  * Process database records at initialization ordered by phase
572  * if their pini (process at init) field is set.
573  */
574 typedef struct {
575  int this;
576  int next;
578 } phaseData_t;
579 
580 static void doRecordPini(dbRecordType *rtype, dbCommon *precord, void *user)
581 {
582  phaseData_t *pphase = (phaseData_t *)user;
583  int phas;
584 
585  if (precord->pini != pphase->pini) return;
586 
587  phas = precord->phas;
588  if (phas == pphase->this) {
589  dbScanLock(precord);
590  dbProcess(precord);
591  dbScanUnlock(precord);
592  } else if (phas > pphase->this && phas < pphase->next)
593  pphase->next = phas;
594 }
595 
596 static void piniProcess(int pini)
597 {
598  phaseData_t phase;
599  phase.next = MIN_PHASE;
600  phase.pini = pini;
601 
602  /* This scans through the whole database as many times as needed.
603  * During the first pass it is unlikely to find any records with
604  * PHAS = MIN_PHASE, but during each iteration it looks for the
605  * phase value of the next pass to run. Note that PHAS fields can
606  * be changed at runtime, so we have to look for the lowest value
607  * of PHAS each time.
608  */
609  do {
610  phase.this = phase.next;
611  phase.next = MAX_PHASE + 1;
612  iterateRecords(doRecordPini, &phase);
613  } while (phase.next != MAX_PHASE + 1);
614 }
615 
616 static void piniProcessHook(initHookState state)
617 {
618  switch (state) {
619  case initHookAtIocRun:
620  piniProcess(menuPiniRUN);
621  break;
622 
624  piniProcess(menuPiniRUNNING);
625  break;
626 
627  case initHookAtIocPause:
628  piniProcess(menuPiniPAUSE);
629  break;
630 
632  piniProcess(menuPiniPAUSED);
633  break;
634 
635  default:
636  break;
637  }
638 }
639 
640 static void initialProcess(void)
641 {
642  initHookRegister(piniProcessHook);
643  piniProcess(menuPiniYES);
644 }
645 
646 
647 /*
648  * set DB_LINK and CA_LINK to PV_LINK
649  * Delete record scans
650  */
651 static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
652  void *user)
653 {
654  devSup *pdevSup;
655  struct dsxt *pdsxt;
656  int j;
657  int locked = 0;
658 
659  for (j = 0; j < pdbRecordType->no_links; j++) {
660  dbFldDes *pdbFldDes =
661  pdbRecordType->papFldDes[pdbRecordType->link_ind[j]];
662  DBLINK *plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
663 
664  if (plink->type == CA_LINK ||
665  plink->type == JSON_LINK ||
666  (plink->type == DB_LINK && iocBuildMode == buildIsolated)) {
667  if (!locked) {
668  dbScanLock(precord);
669  locked = 1;
670  }
671  dbRemoveLink(NULL, plink);
672  }
673  }
674 
675  if (precord->dset &&
676  (pdevSup = dbDSETtoDevSup(pdbRecordType, precord->dset)) &&
677  (pdsxt = pdevSup->pdsxt) &&
678  pdsxt->del_record) {
679  if (!locked) {
680  dbScanLock(precord);
681  locked = 1;
682  }
683  scanDelete(precord); /* Being consistent... */
684  pdsxt->del_record(precord);
685  }
686  if (locked) {
687  precord->pact = TRUE;
688  dbScanUnlock(precord);
689  }
690 }
691 
692 static void doFreeRecord(dbRecordType *pdbRecordType, dbCommon *precord,
693  void *user)
694 {
695  int j;
696 
697  for (j = 0; j < pdbRecordType->no_links; j++) {
698  dbFldDes *pdbFldDes =
699  pdbRecordType->papFldDes[pdbRecordType->link_ind[j]];
700  DBLINK *plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
701 
702  dbFreeLinkContents(plink);
703  }
704 
705  epicsMutexDestroy(precord->mlok);
706  free(precord->ppnr); /* may be allocated in dbNotify.c */
707 }
708 
709 int iocShutdown(void)
710 {
711  if (iocState == iocVoid) return 0;
712 
714 
715  iterateRecords(doCloseLinks, NULL);
717 
718  if (iocBuildMode == buildIsolated) {
719  /* stop and "join" threads */
720  scanStop();
722  callbackStop();
724  } else {
725  dbStopServers();
726  }
727 
728  dbCaShutdown(); /* must be before dbFreeRecord and dbChannelExit */
730 
731  if (iocBuildMode == buildIsolated) {
732  /* free resources */
734  scanCleanup();
735  callbackCleanup();
736 
737  iterateRecords(doFreeRecord, NULL);
738  dbLockCleanupRecords(pdbbase);
739 
740  asShutdown();
741  dbChannelExit();
742  dbProcessNotifyExit();
743  iocshFree();
744  }
745 
746  iocState = iocVoid;
747  iocBuildMode = buildServers;
748 
750  return 0;
751 }
752 
753 static void exitDatabase(void *dummy)
754 {
755  iocShutdown();
756 }
Definition: devSup.h:117
void initHookAnnounce(initHookState state)
Definition: initHooks.c:76
void epicsStdCall epicsThreadSetOkToBlock(int isOkToBlock)
The generalTime framework provides a mechanism for several time providers to be present within the sy...
char ** papChoiceName
Definition: dbBase.h:28
int this
Definition: iocInit.c:575
epicsExportAddress(int, dbThreadRealtimeLock)
ELLLIST drvList
Definition: dbBase.h:173
rset * prset
Definition: dbBase.h:163
#define FALSE
Definition: dbDefs.h:32
iocStateEnum
Definition: iocInit.h:16
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
Definition: dbBase.h:32
struct drvet * pdrvet
Definition: dbBase.h:35
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
Definition: epicsMutex.cpp:127
pvd::Status status
void * precord
Definition: dbBase.h:116
LIBCOM_API void epicsThreadRealtimeLock(void)
Definition: osdThread.c:425
struct typed_rset * prset
int iocBuild(void)
Definition: iocInit.c:196
Driver support routines.
Routines to get and set EPICS environment parameters.
ELLLIST recordTypeList
Definition: dbBase.h:172
int dbThreadRealtimeLock
Definition: iocInit.c:97
short * link_ind
Definition: dbBase.h:156
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
int iocShutdown(void)
Definition: iocInit.c:709
#define NULL
Definition: catime.c:38
DEVSUPFUN init
Definition: devSup.h:143
Miscellaneous macro definitions.
Definition: drvSup.h:45
char * name
Definition: dbBase.h:40
ELLNODE node
Definition: dbBase.h:146
ELLNODE node
Definition: dbBase.h:39
epicsUInt32 secPastEpoch
seconds since 0000 Jan 1, 1990
Definition: epicsTime.h:34
int errlogInit(int bufsize)
Definition: errlog.c:524
struct dsxt * pdsxt
Definition: dbBase.h:45
void dbInitDevSup(devSup *pdevSup, dset *pdset)
Definition: dbStaticRun.c:47
A doubly-linked list library.
long(* init)()
Definition: recSup.h:70
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
LIBCOM_API size_t epicsStdCall epicsTimeToStrftime(char *pBuff, size_t bufLength, const char *pFormat, const epicsTimeStamp *pTS)
Convert epicsTimeStamp to string. See epicsTime::strftime()
Definition: epicsTime.cpp:1120
epicsShareFunc struct drvet * registryDriverSupportFind(const char *name)
Device support routines.
Definition: devSup.h:140
enum iocStateEnum getIocState(void)
Definition: iocInit.c:100
long(* add_record)(struct dbCommon *precord)
Definition: devSup.h:122
int flags
Definition: dbBase.h:119
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
Extended replacement for the Posix exit and atexit routines.
ELLLIST devList
Definition: dbBase.h:149
epicsShareFunc recordTypeLocation * registryRecordTypeFind(const char *name)
Definition: dbBase.h:38
epicsShareFunc int coreRelease(void)
Definition: epicsRelease.c:21
long(* init_record)()
Definition: recSup.h:71
DRVSUPFUN init
Definition: drvSup.h:48
ELLNODE node
Definition: dbBase.h:115
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
char * name
Definition: dbBase.h:151
LIBCOM_API void epicsStdCall epicsSignalInstallSigHupIgnore(void)
Definition: osdSignal.cpp:16
epics::pvData::PVStructurePtr dummy
Definition: pvAccess.cpp:72
int initHookRegister(initHookFunction func)
Definition: initHooks.c:51
epicsUInt16 epicsEnum16
Definition: epicsTypes.h:47
Definition: dbBase.h:24
short no_links
Definition: dbBase.h:154
long(* del_record)(struct dbCommon *precord)
Definition: devSup.h:127
epicsEnum16 pini
Definition: iocInit.c:577
int iocBuildIsolated(void)
Definition: iocInit.c:219
int epicsStdCall epicsThreadIsOkToBlock(void)
ELLNODE node
Definition: dbBase.h:33
EPICS time stamp, for use from C code.
Definition: epicsTime.h:33
int iocInit(void)
Definition: iocInit.c:108
int nChoice
Definition: dbBase.h:27
ELLLIST recList
Definition: dbBase.h:148
#define TRUE
Definition: dbDefs.h:27
void taskwdInit(void)
Definition: taskwd.c:167
int epicsStdCall epicsTimeGetEvent(epicsTimeStamp *pDest, int eventNumber)
Get time of event eventNumber into *pDest.
void(* recIterFunc)(dbRecordType *rtyp, dbCommon *prec, void *user)
Definition: iocInit.c:93
int iocRun(void)
Definition: iocInit.c:236
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
void dbFreeLinkContents(struct link *plink)
Definition: dbStaticLib.c:109
unsigned int isDevLink
Definition: dbBase.h:89
Definition: dbBase.h:170
initHookState
Definition: initHooks.h:25
dbFldDes ** papFldDes
Definition: dbBase.h:161
Definition: recSup.h:67
long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
Definition: dbStaticLib.c:2151
void epicsStdCall iocshFree(void)
Definition: iocsh.cpp:231
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...
Definition: epicsExit.h:70
dbMenu * dbFindMenu(dbBase *pdbbase, const char *name)
Definition: dbStaticLib.c:3012
epicsShareFunc dset * registryDeviceSupportFind(const char *name)
int prec
Definition: reader.c:29
C++ and C descriptions for a thread.
unsigned short offset
Definition: dbBase.h:100
int asInit(void)
Definition: asDbLib.c:152
int asShutdown(void)
Definition: asDbLib.c:157
dbfType field_type
Definition: dbBase.h:86
char * name
Definition: dbBase.h:34
int iocPause(void)
Definition: iocInit.c:267
#define DBRN_FLAGS_ISALIAS
Definition: dbBase.h:111
int next
Definition: iocInit.c:576
#define UDF_ALARM
Definition: alarm.h:108
Exporting IOC objects.
dset * pdset
Definition: dbBase.h:44
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89