Compare commits

..

69 Commits

Author SHA1 Message Date
Andrew Johnson
b3f785964e Set snapshot for final 7.0.2 release 2018-12-17 17:40:49 -06:00
Andrew Johnson
bb4b23f658 Reminder to read external submodule release notes too 2018-12-17 17:39:31 -06:00
Andrew Johnson
8b31fba8cb Update version numbers of embedded modules 2018-12-17 17:20:01 -06:00
Andrew Johnson
8481ae3787 Set embedded modules' SHRLIB_VERSION from CONFIG variables 2018-12-17 17:19:10 -06:00
Andrew Johnson
46535bde64 Update git submodules 2018-12-17 16:47:36 -06:00
Andrew Johnson
6ee928109c Update Release Checklist
Remove To Do list (which didn't get discussed).
Add stuff about submodule versions and pushing tags.
List invididual module version number files to be updated at
final release time.
2018-12-17 16:39:09 -06:00
Andrew Johnson
cff13b9aa7 Update version numbers in documentation 2018-12-14 17:11:47 -06:00
Andrew Johnson
58aa30ab0a Merge 3.15 branch into 7.0
First direct merge since 3.16 branch closed.
2018-12-14 17:05:59 -06:00
Andrew Johnson
5f46d6dcee Release notes updated 2018-12-14 16:58:43 -06:00
Eric Norum
d41355e0fc Add error checking to the copy-back loop in truncateFile() 2018-12-14 16:06:38 -06:00
Eric Norum
a5aa5459e3 Drop extraneous extern "C" 2018-12-14 16:06:37 -06:00
Eric Norum
6201d37756 Remove epicsTempName() routine
It's unsafe and generates obnoxious warnings on modern compilers.
This also replaces internal useage with epicsTempFile().
There appears to be no external code that calls this routine.
2018-12-14 16:06:36 -06:00
Andrew Johnson
67599e54e4 Add ENABLE_ASAN mechanism for developer use 2018-12-13 16:31:05 -06:00
Andrew Johnson
7bc0d6922b Merge 3.16 branch into 7.0
Final merge from 3.16?
2018-12-12 17:38:55 -06:00
Andrew Johnson
02d7304b3f Build modules/database/test/std/link directory too 2018-12-12 17:02:02 -06:00
Andrew Johnson
7c90e6ed0b Reset version snapshot after tagging 2018-12-12 15:51:30 -06:00
Andrew Johnson
c5fd621337 Clear version snapshot for final release 2018-12-12 15:49:41 -06:00
Andrew Johnson
ea409e79be Link to Launchpad's milestone page for the bug list 2018-12-12 15:49:24 -06:00
Andrew Johnson
6d5f57daf1 Merge 3.16 branch into 7.0 2018-12-12 15:17:02 -06:00
Andrew Johnson
c59a18600a Add release notes for the QueueShow additions 2018-12-11 16:47:25 -06:00
Michael Davidsaver
d8d14b11db update PVA 2018-12-10 16:23:16 -08:00
Andrew Johnson
68f6f361e1 Merge 3.15 branch into 3.16 2018-12-10 10:47:57 -06:00
Andrew Johnson
84b7612036 Fix for lp: #1801145 recordtype defined after use in device
Add proper equals() method for DBD::Recfield and DBD::Recordtype.
In Parser::parse_recordtype() check for and re-use a declaration
(i.e. an empty recordtype object) when parsing a later definition
of the same recordtype.
2018-12-10 00:25:27 -06:00
Andrew Johnson
f3cf1df503 Merge 3.15 branch into 3.16 2018-12-07 14:07:57 -06:00
Andrew Johnson
9b385480d0 Rename new *QueuePrintStatus() and *QueueStatus iocsh commands to *Show
Also added symbol decorations for Windows builds.
2018-12-07 13:51:35 -06:00
Andrew Johnson
ec036cb26d Merged Martin Konrad's callbackQueueStatus branch into 3.16 2018-12-07 13:47:56 -06:00
Andrew Johnson
64d9d1a4c9 Fix field links to local menu anchors
Anchor IDs are different for XHTML vs HTML generation.
2018-12-07 13:16:06 -06:00
Andrew Johnson
e53244df1f Cherry-pick Dirk's dbState NULL checks from the 7.0 branch
Prevent segfaults in iocsh
2018-12-07 11:45:12 -06:00
Andrew Johnson
fe3d68b5f7 Merged 3.15 branch into 3.16 2018-12-06 17:32:43 -06:00
Andrew Johnson
49f5527cd7 iocsh: Add protection if realloc() fails 2018-12-06 16:35:30 -06:00
Andrew Johnson
ee90dffd40 Add flush to the iocsh errlog command 2018-12-06 16:33:20 -06:00
Andrew Johnson
6664ccfc64 Wiki to POD conversions for bi, bo, calc, calcout and dfanout
These still need going through to update and edit.
Conversions by Tony Pietryla, Argonne.
2018-12-05 16:55:13 -06:00
Andrew Johnson
444cac337c Add POD text for menuScan 2018-12-05 16:55:12 -06:00
Andrew Johnson
313afc4a4c Fix HTMLS generation from IOC menu*.dbd.pod files 2018-12-05 16:55:11 -06:00
Andrew Johnson
0fae0fcc17 Rename various dbd files to dbd.pod 2018-12-05 16:55:10 -06:00
Andrew Johnson
aab5693b45 Fix for CA link disconnect detection
dbCa's doLocked() method must run the callback even when the link
is disconnected to allow alarms to be triggered by softDev support.

Patch from Sebastian Marsching
Also removes testToDo from rec/test/regressTest.c

Fixes lp: #1798855
2018-12-05 00:59:36 -06:00
Martin Konrad
6f919c3991 Simpler implementation using spin lock rather than atomics 2018-12-04 12:00:26 -05:00
Martin Konrad
87761ebf29 Prevent data race between resetHighWaterMark() and put() 2018-12-03 15:59:14 -05:00
Martin Konrad
10d951e2d7 Fix incorrect value for highWaterMark in epicsRingBytes 2018-12-03 10:13:41 -05:00
Martin Konrad
d436561cb2 Add tests for highWaterMark feature 2018-12-03 10:13:41 -05:00
Ralph Lange
a43b805b65 ca/pcas: fix misleading error message (TCP name resolution) 2018-11-30 17:19:56 +01:00
Ralph Lange
0649a2f13f configure: silence tr1 namespace deprecation warnings on MSVC 2018-11-30 16:58:23 +01:00
Andrew Johnson
5e10b98a99 Added timeout to netget script
Not tested on Windows.
2018-11-29 13:17:01 -06:00
Andrew Johnson
fc90d347d1 Added EPICS_BASE_HOST_LIBS variable to pkg-config files 2018-11-29 12:59:52 -06:00
Andrew Johnson
64a4c556b4 Move pkg-config file creation to modules/database
Needed so EPICS_BASE_IOC_LIBS has been defined.
2018-11-29 12:55:47 -06:00
Andrew Johnson
34115f83ba Adjustment to netget test port settings, not a full fix though 2018-11-28 23:50:35 -06:00
Andrew Johnson
a38c1d07f5 Update PVA modules with Windows symbol fixes 2018-11-28 23:41:14 -06:00
Andrew Johnson
9e999d2bef Only create msi-copy for a Host build-arch 2018-11-27 14:11:11 -06:00
Michael Davidsaver
79690940b7 update PVA modules 2018-11-27 10:30:43 -08:00
Martin Konrad
040f9013f4 Remove unneeded epicsAtomic from callbackQueueSize 2018-11-27 10:45:35 -05:00
Martin Konrad
0f16977caf Make code compatible with ISO C90 2018-11-27 10:30:35 -05:00
Andrew Johnson
694f045332 Merge Bruce Hill's allow-gt-256-time-events branch into 3.16 2018-11-26 16:29:51 -06:00
Andrew Johnson
daad9b1ba1 Merge updates from 3.15 into 3.16 2018-11-26 15:34:32 -06:00
Andrew Johnson
937878e0a9 Merge Bruce Hill's EPICS-and-CA-version-from-CA-tools branch into 3.15 2018-11-20 10:22:43 -06:00
Andrew Johnson
6e536e1ee0 Fix msi-copy target for cross-build host arch's 2018-11-19 17:59:27 -06:00
Andrew Johnson
6ea6c6ff66 VxWorks: Don't use GCC 2.x for dependency file generation 2018-11-06 13:02:36 -06:00
Andrew Johnson
168d430921 Unify shebang line in tap-to-junit-xml 2018-11-06 10:15:06 -06:00
Bruce Hill
9a8860b771 Expand tabs and revert #include lines to <> instead of quotes. 2018-11-05 18:44:46 -08:00
Michael Davidsaver
693c1020f2 Test if disconnected CA link alarms 2018-11-04 22:20:20 -08:00
Michael Davidsaver
63ddb2d4fc fix mingw build 2018-11-04 22:00:00 -08:00
Bruce Hill
3d8e2d933d Include epicsStdio.h so driver report output can be redirected from iocsh 2018-11-04 20:57:58 -08:00
Andrew Johnson
5f3f87a365 Merge Bruce Hill's MAKEFLAGS-to-MFLAGS branch into 3.15
Added a couple other places where this needed to happen too.
2018-11-02 18:14:39 -05:00
Andrew Johnson
072dbd53e7 Adjust clean-tests rule
Only delete test-result files that actually exist.
2018-11-02 17:47:13 -05:00
Bruce Hill
43322335df Add -V flag to ca client tools to show EPICS and CA versions. 2018-10-31 22:22:19 -07:00
Bruce Hill
fcb5675040 Added release notes re handling of event numbers >= NUM_TIME_EVENTS. 2018-10-31 20:35:52 -07:00
Bruce Hill
3d88c8495b Added comments re handling of event numbers >= NUM_TIME_EVENTS. 2018-10-31 20:30:58 -07:00
Bruce Hill
215c5d954b Modify generalTimeGetEventPriority() to allow eventNumber > 256.
eventNumbers between 0 and NUM_TIME_EVENTS will continue to get checked for advancing timestamps.
Support for eventNumbers > NUM_TIME_EVENTS will be up to the generalTime provider.
2018-10-31 20:20:32 -07:00
Martin Konrad
59ec8d897d Expose callback queue status
This allows tools like iocStats to monitor the queue status of
the callback queues. This fixes lp:1786540.
2018-10-26 18:49:34 -04:00
Bruce Hill
b84ee89d87 Fix ECHO definition to not match variables in MAKEFLAGS by using MFLAGS instead.
Prior ECHO definition strips T_A=XXX command line variable definitions
from MAKEFLAGS but doesn't strip other variable definitions such as
INSTALL_LOCATION.  As a result, if you "make INSTALL_LOCATION=XXX"
the ECHO definition erroneously matches if your install location
contains 's'.   Changing the ECHO definition to MFLAGS avoids
all command line variable definitions.
2018-04-16 19:11:40 -07:00
100 changed files with 4434 additions and 2099 deletions

View File

@@ -15,7 +15,7 @@ addons:
script:
- .ci/travis-build.sh
env:
- CMPLR=gcc EXTRA=LINKER_USE_RPATH=ORIGIN
- CMPLR=gcc
- CMPLR=clang
- CMPLR=gcc STATIC=YES
- CMPLR=clang STATIC=YES

View File

@@ -24,9 +24,14 @@ LD = $(GNU_BIN)/$(CMPLR_PREFIX)ld$(CMPLR_SUFFIX) -r
CPP = $(CC) -x c -E
RANLIB = $(GNU_BIN)/$(CMPLR_PREFIX)ranlib$(CMPLR_SUFFIX)
# Requires at least GCC 4.8 or LLVM (clang) 3.1
ASAN_FLAGS_YES = -fsanitize=address
ASAN_LDFLAGS_YES = $(ASAN_FLAGS_YES)
PROF_CFLAGS_YES = -p
GPROF_CFLAGS_YES = -pg
CODE_CFLAGS = $(PROF_CFLAGS_$(PROFILE)) $(GPROF_CFLAGS_$(GPROF))
CODE_CFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
WARN_CFLAGS_YES = -Wall
WARN_CFLAGS_NO = -w
OPT_CFLAGS_YES = -O3
@@ -35,12 +40,14 @@ OPT_CFLAGS_NO = -g
PROF_CXXFLAGS_YES = -p
GPROF_CXXFLAGS_YES = -pg
CODE_CXXFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
CODE_CXXFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
WARN_CXXFLAGS_YES = -Wall
WARN_CXXFLAGS_NO = -w
OPT_CXXFLAGS_YES = -O3
OPT_CXXFLAGS_NO = -g
CODE_LDFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
CODE_LDFLAGS += $(ASAN_LDFLAGS_$(ENABLE_ASAN))
PIPE_CFLAGS_YES_YES = -pipe
PIPE_CFLAGS = $(PIPE_CFLAGS_$(GCC_PIPE)_$(GNU))

View File

@@ -44,8 +44,6 @@ FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG) $(QUESTION_FLAG)
MAKERPATH = $(PYTHON) $(TOOLS)/makeRPath.py
#---------------------------------------------------------------
# tools for installing libraries and products
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(QUIET_FLAG)

View File

@@ -61,10 +61,10 @@ EPICS_PATCH_LEVEL = 0
#EPICS_DEV_SNAPSHOT=-pre2
#EPICS_DEV_SNAPSHOT=-pre2-DEV
#EPICS_DEV_SNAPSHOT=-rc1
EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV
#EPICS_DEV_SNAPSHOT=
EPICS_DEV_SNAPSHOT=
# No changes should be needed below here

View File

@@ -38,8 +38,6 @@ BUILD_ARCHS = $(EPICS_HOST_ARCH) $(CROSS1) $(CROSS2)
# otherwise override this in os/CONFIG_SITE.<host_arch>.Common
PERL = perl -CSD
PYTHON = python
#-------------------------------------------------------
# Check configure/RELEASE file for consistency
CHECK_RELEASE_YES = checkRelease
@@ -78,11 +76,14 @@ COMMON_DIR = ../O.Common
IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
#-------------------------------------------------------
# Make echo output - suppress echoing if make's '-s' flag is set
# Silencing the build - suppress messages during 'make -s'
NOP = :
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
QUIET_FLAG := $(if $(findstring s,$(MAKEFLAGS)),-q,)
QUESTION_FLAG := $(if $(findstring q,$(MAKEFLAGS)),-i,)
ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
QUIET_FLAG := $(if $(findstring s,$(MFLAGS)),-q,)
#-------------------------------------------------------
# Convert 'make -q' flag into '-i' for genVersionHeader.pl
QUESTION_FLAG := $(if $(findstring q,$(MFLAGS)),-i,)
#-------------------------------------------------------
ifdef T_A
@@ -92,7 +93,7 @@ INSTALL_SHRLIB = $(INSTALL_LOCATION_LIB)/$(T_A)
INSTALL_TCLLIB = $(INSTALL_LOCATION_LIB)/$(T_A)
INSTALL_BIN = $(INSTALL_LOCATION_BIN)/$(T_A)
#Directories for libraries
# Directories for libraries
SHRLIB_SEARCH_DIRS = $(INSTALL_LIB)
#-------------------------------------------------------

View File

@@ -169,17 +169,10 @@ EPICS_SITE_VERSION =
GCC_PIPE = NO
# Set RPATH when linking executables and libraries.
# Must be either YES, NO, or ORIGIN. If you set this to NO you must also provide a
# Must be either YES or NO. If you set this to NO you must also provide a
# way for Base executables to find their shared libraries when they are
# run at build-time, e.g. set the LD_LIBRARY_PATH environment variable.
# ORIGIN is Linux specific.
LINKER_USE_RPATH = YES
# Only used when LINKER_USE_RPATH=ORIGIN
# The build time root of the relocatable tree.
# Linking to libraries under this root directory will be relative.
# Linking to libraries outside of this root will be absolute.
LINKER_ORIGIN_ROOT = $(INSTALL_LOCATION)
# Overrides for the settings above may appear in a CONFIG_SITE.local file
-include $(CONFIG)/CONFIG_SITE.local

View File

@@ -43,6 +43,7 @@ LOADABLE_LIBRARY += $(LOADABLE_LIBRARY_HOST)
OBJS += $(OBJS_HOST)
PROD += $(PROD_HOST)
SCRIPTS += $(SCRIPTS_HOST)
TARGETS += $(TARGETS_HOST)
TESTLIBRARY += $(TESTLIBRARY_HOST)
TESTSCRIPTS += $(TESTSCRIPTS_HOST)
TESTPROD += $(TESTPROD_HOST)
@@ -54,6 +55,7 @@ LOADABLE_LIBRARY += $(LOADABLE_LIBRARY_IOC)
OBJS += $(OBJS_IOC)
PROD += $(PROD_IOC)
SCRIPTS += $(SCRIPTS_IOC)
TARGETS += $(TARGETS_IOC)
TESTLIBRARY += $(TESTLIBRARY_IOC)
TESTSCRIPTS += $(TESTSCRIPTS_IOC)
TESTPROD += $(TESTPROD_IOC)
@@ -194,13 +196,6 @@ ifeq ($(EPICS_HOST_ARCH),$(T_A))
$(info Warning: RELEASE file consistency checks have been disabled)
endif
# $(FINAL_DIR) signals eventual install locations to makeRPath script
$(TESTPRODNAME): FINAL_DIR=.
$(PRODNAME): FINAL_DIR=$(INSTALL_BIN)
$(TESTSHRLIBNAME): FINAL_DIR=.
$(SHRLIBNAME): FINAL_DIR=$(INSTALL_SHRLIB)
$(LOADABLE_SHRLIBNAME): FINAL_DIR=$(INSTALL_SHRLIB)
#---------------------------------------------------------------
# The order of the following rules is
# VERY IMPORTANT !!!!
@@ -367,14 +362,17 @@ ifneq ($(TAPFILES),)
ifdef RUNTESTS_ENABLED
prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES)
endif
CURRENT_TAPFILES := $(wildcard $(TAPFILES))
CURRENT_JUNITFILES := $(wildcard $(JUNITFILES))
endif
clean-tests:
ifneq ($(TAPFILES),)
$(RM) $(TAPFILES)
ifneq ($(CURRENT_TAPFILES),)
$(RM) $(CURRENT_TAPFILES)
endif
ifneq ($(JUNITFILES),)
$(RM) $(JUNITFILES)
ifneq ($(CURRENT_JUNITFILES),)
$(RM) $(CURRENT_JUNITFILES)
endif
tapfiles: $(TESTSCRIPTS) $(TAPFILES)

View File

@@ -76,7 +76,7 @@ CPPFLAGS += $($(BUILD_CLASS)_CPPFLAGS) $(POSIX_CPPFLAGS) $(OPT_CPPFLAGS)\
$(USR_CPPFLAGS) $(CMD_CPPFLAGS) $(ARCH_DEP_CPPFLAGS) $(OP_SYS_CPPFLAGS)\
$(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS)
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
#--------------------------------------------------
# Although RTEMS uses gcc, it wants to use gcc its own way

View File

@@ -25,13 +25,11 @@ STATIC_LDLIBS_YES= -Wl,-Bdynamic
# Set runtime path for shared libraries if USE_RPATH=YES and STATIC_BUILD=NO
SHRLIBDIR_RPATH_LDFLAGS_YES_NO = $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_RPATH_LDFLAGS_ORIGIN_NO = $(shell $(MAKERPATH) -O '\$$ORIGIN' -F $(FINAL_DIR) -R $(LINKER_ORIGIN_ROOT) $(SHRLIB_DEPLIB_DIRS))
SHRLIBDIR_LDFLAGS += \
$(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Set runtime path for products if USE_RPATH=YES and STATIC_BUILD=NO
PRODDIR_RPATH_LDFLAGS_YES_NO = $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_RPATH_LDFLAGS_ORIGIN_NO = $(shell $(MAKERPATH) -O '\$$ORIGIN' -F $(FINAL_DIR) -R $(LINKER_ORIGIN_ROOT) $(PROD_DEPLIB_DIRS))
PRODDIR_LDFLAGS += \
$(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))

View File

@@ -146,8 +146,10 @@ SHRLIB_CFLAGS =
SHRLIB_LDFLAGS =
#--------------------------------------------------
# Earlier versions of gcc don't understand -MF
HDEPENDS_COMPFLAGS = -MM > $@
# Don't use gcc 2.x for dependency generation
HDEPENDS_METHOD_2 = MKMF
HDEPENDS_METHOD = $(firstword $(HDEPENDS_METHOD_$(VX_GNU_MAJOR_VERSION)) COMP)
#--------------------------------------------------
# osithead use default stack, YES or NO override

View File

@@ -26,3 +26,5 @@ endif
# Needed to find dlls for base installed build tools (antelope,eflex,...)
PATH := $(EPICS_BASE_BIN):$(PATH)
# Silence the tr1 namespace deprecation warnings
USR_CXXFLAGS_WIN32 += -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING

View File

@@ -54,3 +54,7 @@ OPT_CXXFLAGS_YES += -g
# Tune GNU compiler output for a specific 32-bit cpu-type
# (e.g. generic, native, i386, i686, pentium2/3/4, prescott, k6, athlon etc.)
GNU_TUNE_CFLAGS = -mtune=generic
# Developers using a suitable compiler may enable its address sanitizer:
#ENABLE_ASAN = YES

View File

@@ -50,3 +50,7 @@ OPT_CXXFLAGS_YES += -g
# Tune GNU compiler output for a specific 64-bit cpu-type
# (e.g. generic, native, core2, nocona, k8, opteron, athlon64, barcelona etc.)
GNU_TUNE_CFLAGS = -mtune=generic
# Developers using a suitable compiler may enable its address sanitizer:
#ENABLE_ASAN = YES

View File

@@ -4,17 +4,17 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Known Problems in EPICS 7.0.1</title>
<title>Known Problems in EPICS 7.0.2</title>
</head>
<body>
<h1 style="text-align: center">EPICS 7.0.1: Known Problems</h1>
<h1 style="text-align: center">EPICS 7.0.2: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-7.0.1 tree. Download them, then use the GNU Patch program as
base-7.0.2 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-7.0.1</b>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-7.0.2</b>
% <b>patch -p1 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following problems were known by the developers at the time of this

View File

@@ -1,6 +1,6 @@
Installation Instructions
EPICS Base Release 7.0.1.1
EPICS Base Release 7.0.2
--------------------------------------------------------------------------

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 7.0.1.1</H2><BR>
<H2>EPICS Base Release 7.0.2</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>

View File

@@ -9,13 +9,18 @@
<body lang="en">
<p>These release notes describe changes that have been made since the previous
release of this series of EPICS Base. Note that changes which were merged up
release of this series of EPICS Base. <b>Note that changes which were merged up
from commits to new releases in an older Base series are not described at the
top of this file but have entries that appear lower down, under the series to
which they were originally committed. Thus it is important to read more than
which they were originally committed.</b> Thus it is important to read more than
just the first section to understand everything that has changed in each
release.</p>
<p>The external PVA submodules each have their own separate set of release notes
which should also be read to understand what has changed since an earlier
release.</p>
<h1 align="center">EPICS Release 7.0.2</h1>
<!-- Insert new items immediately below this template ...
@@ -108,9 +113,30 @@ code than documentation. Send questions to the tech-talk mailing list and we'll
be happy to try and answer them!</p>
<h2 align="center">Changes from the 3.16 branch since 3.16.1</h2>
<h2 align="center">Changes between 3.16.1 and 3.16.2</h2>
<!-- Insert inherited items immediately below here ... -->
<p>The list of tracked bugs fixed in this release can be found on the
<a href="https://launchpad.net/epics-base/+milestone/3.16.2">Launchpad Milestone
page for EPICS Base 3.16.2</a>.</p>
<h3>Status reporting for the callback and scanOnce task queues</h3>
<p>Two new iocsh commands and some associated underlying APIs have been added to
show the state of the queues that feed the three callback tasks and the scanOnce
task, including a high-water mark which can optionally be reset. The new iocsh
commands are <tt>callbackQueueShow</tt> and <tt>scanOnceQueueShow</tt>; both
take an optional integer argument which must be non-zero to reset the
high-water mark.</p>
<h3>Support for event codes greater than or equal to NUM_TIME_EVENTS</h3>
<p>Event numbers greater than or equal to NUM_TIME_EVENTS are now allowed if
supported by the registered event time provider, which must provide its own
advancing timestamp validation for such events.</p>
<p>Time events numbered 0 through (NUM_TIME_EVENTS-1) are still validated by
code in epicsGeneralTime.c that checks for advancing timestamps and enforces
that restriction.</p>
<h3>Type-safe Device and Driver Support Tables</h3>
@@ -894,6 +920,37 @@ of its CALLBACK objects.</p>
<!-- Insert inherited items immediately below here ... -->
<h3>Routine <tt>epicsTempName()</tt> removed from libCom</h3>
<p>This routine was a simple wrapper around the C89 function <tt>tmpnam()</tt>
which is now seen as unsafe and causes warning messages to be generated by
most modern compilers. The two internal uses of this function have been
modified to call <tt>epicsTempFile()</tt> instead. We were unable to find any
published code that used this function, so it was removed immediately instead
of being deprecated.</p>
<h3>DBD Parsing of Record Types</h3>
<p>The Perl DBD file parser has been made slightly more liberal; the order in
which DBD files must be parsed is now more flexible, so that a record type
definition can now be parsed after a device support that referred to that
record type. A warning message will be displayed when the device support is
seen, but the subsequent loading of the record type will be accepted without
triggering an error. See
<a href="https://bugs.launchpad.net/epics-base/+bug/1801145">Launchpad bug
#1801145</a>.</p>
<h3>menuScan and several record types documented with POD</h3>
<p>The EPICS Wiki pages describing a number of standard record types has been
converted into the Perl POD documentation format and added to the DBD files,
so at build-time an HTML version of these documents is generated and installed
into the htmls directory. Thanks to Tony Pietryla.</p>
<h3>CA client tools learned <tt>-V</tt> option</h3>
<p>This displays the version numbers of EPICS Base and the CA protocol.</p>
<h2 align="center">Changes made between 3.15.5 and 3.15.6</h2>

View File

@@ -248,24 +248,6 @@ made.</p>
</td>
</tr>
<tr>
<th colspan="3">To Do</th>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Discuss and resolve before final release:
<ul>
<li>Update version numbers in individual
<tt>modules/*/configure/*VERSION</tt> files?</li>
<li>Unifying module Release Notes for easier publication.</li>
<li>Unifying module documentation directories and Doxygen
config's.</li>
<li>Publishing releases on the new website.</li>
</ul>
</td>
</tr>
<tr>
<th colspan="3">Release Approval</th>
</tr>
@@ -282,18 +264,36 @@ made.</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Edit and commit changes to the EPICS version number file
configure/CONFIG_BASE_VERSION.</td>
<td>
<p>For each external submodule, check if the module's release version
number (and SHRLIB_VERSION setting) has been updated if appropriate,
and that its Release Notes have been updated to cover any changes.
Commit any fixes and tag the module if that hasn't already been
done.</p>
<p>Update all external submodules on the Base-7.0 branch and
commit.</p></td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Git:
<td>Edit and commit changes to the EPICS Base version number file and
the embedded module version files:
<ul>
<li>configure/CONFIG_BASE_VERSION </li>
<li>modules/libcom/configure/CONFIG_LIBCOM_VERSION</li>
<li>modules/ca/configure/CONFIG_CA_VERSION</li>
<li>modules/database/configure/CONFIG_DATABASE_VERSION</li>
</ul></td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the epics-base module in Git:
<blockquote><tt>
cd base-7.0<br />
git tag -m 'ANJ: Tagged for 7.0.2' R7.0.2</i>
</tt></blockquote>
</td>
Don't push the new tag to the Launchpad repository yet.</td>
</tr>
<tr>
<td>&nbsp;</td>
@@ -315,7 +315,12 @@ made.</p>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Test the tar file by extracting its contents and building it on at
least one supported platform</td>
least one supported platform. When this succeeds the new git tag can be
pushed to the Launchpad repository:
<blockquote><tt>
git push --follow-tags upstream 7.0
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
@@ -335,8 +340,8 @@ made.</p>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Copy the tar file and its <tt>.asc</tt> signature file to the Base
download area of the website.</td>
<td>Upload the tar file and its <tt>.asc</tt> signature file to the
Launchpad milestone for this release version.</td>
</tr>
<tr>
<td>&nbsp;</td>

View File

@@ -1,4 +1,4 @@
EPICS_CA_MAJOR_VERSION = 4
EPICS_CA_MINOR_VERSION = 13
EPICS_CA_MAINTENANCE_VERSION = 2
EPICS_CA_DEVELOPMENT_FLAG = 1
EPICS_CA_MAINTENANCE_VERSION = 3
EPICS_CA_DEVELOPMENT_FLAG = 0

View File

@@ -125,7 +125,7 @@ EXPANDVARS += EPICS_CA_DEVELOPMENT_FLAG
EXPANDFLAGS += $(foreach var,$(EXPANDVARS),-D$(var)="$(strip $($(var)))")
# shared library ABI version.
SHRLIB_VERSION = 4.13.1
SHRLIB_VERSION = $(EPICS_CA_MAJOR_VERSION).$(EPICS_CA_MINOR_VERSION).$(EPICS_CA_MAINTENANCE_VERSION)
include $(TOP)/configure/RULES

View File

@@ -34,6 +34,7 @@
#include <alarm.h>
#include <cadef.h>
#include <epicsGetopt.h>
#include "epicsVersion.h"
#include "tool_lib.h"
@@ -55,6 +56,7 @@ static void usage (void)
{
fprintf (stderr, "\nUsage: caget [options] <PV name> ...\n\n"
" -h: Help: Print this message\n"
" -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
" -c: Asynchronous get (use ca_get_callback and wait for completion)\n"
@@ -389,11 +391,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
while ((opt = getopt(argc, argv, ":taicnhsSe:f:g:l:#:d:0:w:p:F:")) != -1) {
while ((opt = getopt(argc, argv, ":taicnhsSVe:f:g:l:#:d:0:w:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
case 'V':
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
return 0;
case 't': /* Terse output mode */
complainIfNotPlainAndSet(&format, terse);
break;

View File

@@ -23,6 +23,7 @@
#include <stdio.h>
#include <epicsStdlib.h>
#include "epicsVersion.h"
#include <cadef.h>
#include <epicsGetopt.h>
@@ -36,12 +37,14 @@ void usage (void)
{
fprintf (stderr, "\nUsage: cainfo [options] <PV name> ...\n\n"
" -h: Help: Print this message\n"
" -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
" -s <level>: Call ca_client_status with the specified interest level\n"
" -p <prio>: CA priority (0-%u, default 0=lowest)\n"
"\nExample: cainfo my_channel another_channel\n\n"
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
fprintf (stderr, "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
}
@@ -137,11 +140,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
while ((opt = getopt(argc, argv, ":nhw:s:p:")) != -1) {
while ((opt = getopt(argc, argv, ":nhVw:s:p:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
case 'V':
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
return 0;
case 'w': /* Set CA timeout value */
if(epicsScanDouble(optarg, &caTimeout) != 1)
{

View File

@@ -26,6 +26,7 @@
#include <stdio.h>
#include <epicsStdlib.h>
#include <string.h>
#include "epicsVersion.h"
#include <cadef.h>
#include <epicsGetopt.h>
@@ -44,7 +45,8 @@ void usage (void)
{
fprintf (stderr, "\nUsage: camonitor [options] <PV name> ...\n"
"\n"
" -h: Help; Print this message\n"
" -h: Help: Print this message\n"
" -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
" -m <msk>: Specify CA event mask to use. <msk> is any combination of\n"
@@ -209,11 +211,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
while ((opt = getopt(argc, argv, ":nhm:sSe:f:g:l:#:0:w:t:p:F:")) != -1) {
while ((opt = getopt(argc, argv, ":nhVm:sSe:f:g:l:#:0:w:t:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
case 'V':
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
return 0;
case 'n': /* Print ENUM as index numbers */
enumAsNr=1;
break;

View File

@@ -37,6 +37,7 @@
#include <epicsGetopt.h>
#include <epicsEvent.h>
#include <epicsString.h>
#include "epicsVersion.h"
#include "tool_lib.h"
@@ -59,6 +60,7 @@ void usage (void)
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value> ...\n"
" caput -a [options] <PV name> <no of values> <PV value> ...\n\n"
" -h: Help: Print this message\n"
" -V: Version: Show EPICS and CA versions\n"
"Channel Access options:\n"
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
" -c: Asynchronous put (use ca_put_callback and wait for completion)\n"
@@ -281,11 +283,14 @@ int main (int argc, char *argv[])
LINE_BUFFER(stdout); /* Configure stdout buffering */
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
while ((opt = getopt(argc, argv, ":cnlhatsVS#:w:p:F:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
return 0;
case 'V':
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
return 0;
case 'n': /* Force interpret ENUM as index number */
enumAsNr = 1;
enumAsString = 0;

View File

@@ -25,7 +25,7 @@ INSTALL_LOCATION = $(TOP)
BASE_CPPFLAGS += -DUSE_TYPED_RSET
# Shared library ABI version.
SHRLIB_VERSION = 3.17.0
SHRLIB_VERSION = $(EPICS_DATABASE_MAJOR_VERSION).$(EPICS_DATABASE_MINOR_VERSION).$(EPICS_DATABASE_MAINTENANCE_VERSION)
# CONFIG_SITE files contain other build configuration settings
include $(TOP)/configure/CONFIG_SITE

View File

@@ -1,4 +1,4 @@
EPICS_DATABASE_MAJOR_VERSION = 3
EPICS_DATABASE_MINOR_VERSION = 17
EPICS_DATABASE_MAINTENANCE_VERSION = 1
EPICS_DATABASE_DEVELOPMENT_FLAG = 1
EPICS_DATABASE_MAINTENANCE_VERSION = 2
EPICS_DATABASE_DEVELOPMENT_FLAG = 0

View File

@@ -25,11 +25,6 @@ INC += databaseVersionNum.h
PROD_LIBS = Com
EPICS_DATABASE_MAJOR_VERSION = 3
EPICS_DATABASE_MINOR_VERSION = 17
EPICS_DATABASE_MAINTENANCE_VERSION = 0
EPICS_DATABASE_DEVELOPMENT_FLAG = 1
include $(IOCDIR)/as/Makefile
include $(IOCDIR)/bpt/Makefile
include $(IOCDIR)/db/Makefile

View File

@@ -61,7 +61,7 @@ DBDINC += menuScan
DBDINC += dbCommon
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
HTMLS += $(patsubst %.dbd.pod,%.html,$(menusPod))
HTMLS += $(patsubst %.dbd.pod,%.html,$(dbMenusPod))
dbCore_SRCS += dbLock.c
dbCore_SRCS += dbAccess.c

View File

@@ -54,6 +54,7 @@ typedef struct cbQueueSet {
epicsEventId semWakeUp;
epicsRingPointerId queue;
int queueOverflow;
int queueOverflows;
int shutdown;
int threadsConfigured;
int threadsRunning;
@@ -103,6 +104,51 @@ int callbackSetQueueSize(int size)
return 0;
}
int callbackQueueStatus(const int reset, callbackQueueStats *result)
{
int ret;
if (!callbackIsInit) return -1;
if (result) {
int prio;
result->size = callbackQueueSize;
for(prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
epicsRingPointerId qId = callbackQueue[prio].queue;
result->numUsed[prio] = epicsRingPointerGetUsed(qId);
result->maxUsed[prio] = epicsRingPointerGetHighWaterMark(qId);
result->numOverflow[prio] = epicsAtomicGetIntT(&callbackQueue[prio].queueOverflows);
}
ret = 0;
} else {
ret = -2;
}
if (reset) {
int prio;
for(prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
epicsRingPointerResetHighWaterMark(callbackQueue[prio].queue);
}
}
return ret;
}
void callbackQueueShow(const int reset)
{
callbackQueueStats stats;
if (callbackQueueStatus(reset, &stats) == -1) {
fprintf(stderr, "Callback system not initialized, yet. Please run "
"iocInit before using this command.\n");
} else {
int prio;
printf("PRIORITY HIGH-WATER MARK ITEMS IN Q Q SIZE %% USED Q OVERFLOWS\n");
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
double qusage = 100.0 * stats.numUsed[prio] / stats.size;
printf("%8s %15d %10d %6d %6.1f %11d\n",
threadNamePrefix[prio], stats.maxUsed[prio],
stats.numUsed[prio], stats.size, qusage,
stats.numOverflow[prio]);
}
}
}
int callbackParallelThreads(int count, const char *prio)
{
if (callbackIsInit) {
@@ -290,6 +336,7 @@ int callbackRequest(CALLBACK *pcallback)
if (!pushOK) {
epicsInterruptContextMessage(fullMessage[priority]);
mySet->queueOverflow = TRUE;
epicsAtomicIncrIntT(&mySet->queueOverflows);
return S_db_bufFull;
}
epicsEventSignal(mySet->semWakeUp);

View File

@@ -48,6 +48,13 @@ typedef epicsCallback CALLBACK;
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
typedef struct callbackQueueStats {
int size;
int numUsed[NUM_CALLBACK_PRIORITIES];
int maxUsed[NUM_CALLBACK_PRIORITIES];
int numOverflow[NUM_CALLBACK_PRIORITIES];
} callbackQueueStats;
#define callbackSetCallback(PFUN, PCALLBACK) \
( (PCALLBACK)->callback = (PFUN) )
#define callbackSetPriority(PRIORITY, PCALLBACK) \
@@ -73,6 +80,8 @@ epicsShareFunc void callbackCancelDelayed(CALLBACK *pcallback);
epicsShareFunc void callbackRequestProcessCallbackDelayed(
CALLBACK *pCallback, int Priority, void *pRec, double seconds);
epicsShareFunc int callbackSetQueueSize(int size);
epicsShareFunc int callbackQueueStatus(const int reset, callbackQueueStats *result);
epicsShareFunc void callbackQueueShow(const int reset);
epicsShareFunc int callbackParallelThreads(int count, const char *prio);
#ifdef __cplusplus

View File

@@ -703,7 +703,12 @@ static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
caLink *pca;
long status;
pcaGetCheck
assert(plink);
if (plink->type != CA_LINK) return -1;
pca = (caLink *)plink->value.pv_link.pvt;
assert(pca);
epicsMutexMustLock(pca->lock);
assert(pca->plink);
status = rtn(plink, priv);
epicsMutexUnlock(pca->lock);
return status;

View File

@@ -20,6 +20,7 @@
#include "cantProceed.h"
#include "epicsAssert.h"
#include "epicsString.h"
#include "epicsStdio.h"
#include "errlog.h"
#include "freeList.h"
#include "gpHash.h"

View File

@@ -296,6 +296,17 @@ static void scanOnceSetQueueSizeCallFunc(const iocshArgBuf *args)
scanOnceSetQueueSize(args[0].ival);
}
/* scanOnceQueueShow */
static const iocshArg scanOnceQueueShowArg0 = { "reset",iocshArgInt};
static const iocshArg * const scanOnceQueueShowArgs[1] =
{&scanOnceQueueShowArg0};
static const iocshFuncDef scanOnceQueueShowFuncDef =
{"scanOnceQueueShow",1,scanOnceQueueShowArgs};
static void scanOnceQueueShowCallFunc(const iocshArgBuf *args)
{
scanOnceQueueShow(args[0].ival);
}
/* scanppl */
static const iocshArg scanpplArg0 = { "rate",iocshArgDouble};
static const iocshArg * const scanpplArgs[1] = {&scanpplArg0};
@@ -335,6 +346,17 @@ static void callbackSetQueueSizeCallFunc(const iocshArgBuf *args)
callbackSetQueueSize(args[0].ival);
}
/* callbackQueueShow */
static const iocshArg callbackQueueShowArg0 = { "reset", iocshArgInt};
static const iocshArg * const callbackQueueShowArgs[1] =
{&callbackQueueShowArg0};
static const iocshFuncDef callbackQueueShowFuncDef =
{"callbackQueueShow",1,callbackQueueShowArgs};
static void callbackQueueShowCallFunc(const iocshArgBuf *args)
{
callbackQueueShow(args[0].ival);
}
/* callbackParallelThreads */
static const iocshArg callbackParallelThreadsArg0 = { "no of threads", iocshArgInt};
static const iocshArg callbackParallelThreadsArg1 = { "priority", iocshArgString};
@@ -441,12 +463,14 @@ void dbIocRegister(void)
iocshRegister(&dbLockShowLockedFuncDef,dbLockShowLockedCallFunc);
iocshRegister(&scanOnceSetQueueSizeFuncDef,scanOnceSetQueueSizeCallFunc);
iocshRegister(&scanOnceQueueShowFuncDef,scanOnceQueueShowCallFunc);
iocshRegister(&scanpplFuncDef,scanpplCallFunc);
iocshRegister(&scanpelFuncDef,scanpelCallFunc);
iocshRegister(&postEventFuncDef,postEventCallFunc);
iocshRegister(&scanpiolFuncDef,scanpiolCallFunc);
iocshRegister(&callbackSetQueueSizeFuncDef,callbackSetQueueSizeCallFunc);
iocshRegister(&callbackQueueShowFuncDef,callbackQueueShowCallFunc);
iocshRegister(&callbackParallelThreadsFuncDef,callbackParallelThreadsCallFunc);
/* Needed before callback system is initialized */

View File

@@ -24,6 +24,7 @@
#include "cantProceed.h"
#include "dbDefs.h"
#include "ellLib.h"
#include "epicsAtomic.h"
#include "epicsEvent.h"
#include "epicsMutex.h"
#include "epicsPrint.h"
@@ -63,6 +64,7 @@ static volatile enum ctl scanCtl;
static int onceQueueSize = 1000;
static epicsEventId onceSem;
static epicsRingBytesId onceQ;
static int onceQOverruns = 0;
static epicsThreadId onceTaskId;
static void *exitOnce;
@@ -676,6 +678,7 @@ int scanOnceCallback(struct dbCommon *precord, once_complete cb, void *usr)
if (!pushOK) {
if (newOverflow) errlogPrintf("scanOnce: Ring buffer overflow\n");
newOverflow = FALSE;
epicsAtomicIncrIntT(&onceQOverruns);
} else {
newOverflow = TRUE;
}
@@ -722,6 +725,40 @@ int scanOnceSetQueueSize(int size)
return 0;
}
int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result)
{
int ret;
if (!onceQ) return -1;
if (result) {
result->size = epicsRingBytesSize(onceQ) / sizeof(onceEntry);
result->numUsed = epicsRingBytesUsedBytes(onceQ) / sizeof(onceEntry);
result->maxUsed = epicsRingBytesHighWaterMark(onceQ) / sizeof(onceEntry);
result->numOverflow = epicsAtomicGetIntT(&onceQOverruns);
ret = 0;
} else {
ret = -2;
}
if (reset) {
epicsRingBytesResetHighWaterMark(onceQ);
}
return ret;
}
void scanOnceQueueShow(const int reset)
{
scanOnceQueueStats stats;
if (scanOnceQueueStatus(reset, &stats) == -1) {
fprintf(stderr, "scanOnce system not initialized, yet. Please run "
"iocInit before using this command.\n");
} else {
double qusage = 100.0 * stats.numUsed / stats.size;
printf("PRIORITY HIGH-WATER MARK ITEMS IN Q Q SIZE %% USED Q OVERFLOWS\n");
printf("%8s %15d %10d %6d %6.1f %11d\n", "scanOnce", stats.maxUsed,
stats.numUsed, stats.size, qusage,
epicsAtomicGetIntT(&onceQOverruns));
}
}
static void initOnce(void)
{
if ((onceQ = epicsRingBytesLockedCreate(sizeof(onceEntry)*onceQueueSize)) == NULL) {

View File

@@ -42,6 +42,13 @@ struct dbCommon;
typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio);
typedef void (*once_complete)(void *usr, struct dbCommon*);
typedef struct scanOnceQueueStats {
int size;
int numUsed;
int maxUsed;
int numOverflow;
} scanOnceQueueStats;
epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
@@ -57,6 +64,8 @@ epicsShareFunc double scanPeriod(int scan);
epicsShareFunc int scanOnce(struct dbCommon *);
epicsShareFunc int scanOnceCallback(struct dbCommon *, once_complete cb, void *usr);
epicsShareFunc int scanOnceSetQueueSize(int size);
epicsShareFunc int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result);
epicsShareFunc void scanOnceQueueShow(const int reset);
/*print periodic lists*/
epicsShareFunc int scanppl(double rate);

View File

@@ -1,11 +1,48 @@
#*************************************************************************
# Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=head1 Menu menuScan
This menu is used for the C<SCAN> field of all record types.
The set of periodic scan rates may be modified for an individual IOC by
copying the F<menuScan.dbd> file from Base into the IOC's source
directory and changing it to contain the desired scan rates.
The scan periods are extracted from the choice strings at runtime, which
must be expressed as a number with any of the following units appended:
=over 4
second
seconds
minute
minutes
hour
hours
Hertz
Hz
=back
At IOC start-up a separate scan thread will be created for each period,
with thread priority increasing further down the list, so faster periods
should appear after slower ones.
Scan rates that cannot be achieved will generate a warning message from
the C<iocInit> command.
=menu menuScan
=cut
menu(menuScan) {
choice(menuScanPassive,"Passive")
choice(menuScanEvent,"Event")

View File

@@ -1,134 +0,0 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
recordtype(bi) {
include "dbCommon.dbd"
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup("40 - Input")
interest(1)
}
field(VAL,DBF_ENUM) {
prompt("Current Value")
promptgroup("40 - Input")
asl(ASL0)
pp(TRUE)
}
field(ZSV,DBF_MENU) {
prompt("Zero Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(OSV,DBF_MENU) {
prompt("One Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(COSV,DBF_MENU) {
prompt("Change of State Svr")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(ZNAM,DBF_STRING) {
prompt("Zero Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(ONAM,DBF_STRING) {
prompt("One Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(RVAL,DBF_ULONG) {
prompt("Raw Value")
pp(TRUE)
}
field(ORAW,DBF_ULONG) {
prompt("prev Raw Value")
special(SPC_NOMOD)
interest(3)
}
field(MASK,DBF_ULONG) {
prompt("Hardware Mask")
special(SPC_NOMOD)
interest(1)
}
field(LALM,DBF_USHORT) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_USHORT) {
prompt("Last Value Monitored")
special(SPC_NOMOD)
interest(3)
}
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SVAL,DBF_ULONG) {
prompt("Simulation Value")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuSimm)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("CALLBACK *simpvt")
}
}

View File

@@ -0,0 +1,491 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Binary Input Record (bi)
This record type is normally used to obtain a binary value of 0 or 1. Most
device support modules obtain values from hardware and place the value in
RVAL. For these devices, record processing sets VAL = (0,1) if RVAL is (0,
not 0). Device support modules may optionally read a value directly from
VAL.
Soft device modules are provided to obtain input via database or channel
access links via dbPutField or dbPutLink requests. Two soft device support
modules are provided: C<Soft Channel> and C<Raw Soft Channel>. The first
allows VAL to be an arbitrary unsigned short integer. The second reads the
value into RVAL just like normal hardware modules.
=head2 Parameter Fields
The binary input's fields fall into the following categories:
=over
=item *
scan Parameters
=item *
read and convert parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
run-time parameters
=back
=recordtype bi
=cut
recordtype(bi) {
=head3 Scan Parameters
The binary input record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Note that I/O event scanning is only supported for those
card types that interrupt.
=fields SCAN
=head3 Read and Convert Parameters
The read and convert fields determine where the binary input gets its
input from and how to convert the raw signal to engineering units. The INP
field contains the address from where device support retrieves the value.
If the binary input record gets its value from hardware, the address of the
card must be entered in the INP field, and the name of the device support
module must be entered in the DTYP field. See L<Address Specification> for
information on the format of the hardware address. Be aware that the format
differs between types of cards. You can see a list of device support
modules currently supported at the user's local site by using C<dbst>
utility (R3.13).
For records that specify C<Soft Channel> or C<Raw Soft Channel> device
support routines, the INP field can be a channel or a database link, or a
constant. If a constant, VAL can be changed directly by dbPuts. See
L<Address Specification> for information on the format of database and
channel access addresses. Also, see L<Device Support for Soft Records> in
this chapter for information on soft device support.
If the record gets its values from hardware or uses the C<Raw Soft Channel>
device support, the device support routines place the value in the RVAL
field which is then converted using the process described in the next
section.
=fields INP, DTYP, ZNAM, ONAM, RVAL, VAL
=head3 Conversion Fields
The VAL field is set equal to (0,1) if the RVAL field is (0, not 0), unless
the device support module reads a value directly into VAL or the
C<Soft Channel> device support is used. The value can also be fetched as one of
the strings specified in the ZNAM or ONAM fields. The ZNAM field has a
string that corresponds to the 0 state, so when the value is fetched as
this string, C<put_enum_str> will return a 0. The ONAM field hold the
string that corresponds to the 1 state, so when the value is fetched as
this string, C<put_enum_str> returns a 1.
=fields ZNAM, ONAM
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. The
C<get_enum_str> record support routine can retrieve the state string
corresponding to the VAL's state. If the value is 1, C<get_enum_str> will
return the string in the ONAM field; and if 0, C<get_enum_str> will return
the ZNAM string.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
=fields ZNAM, ONAM, NAME, DESC
=head3 Alarm Parameters
These parameters are used to determine if the binary input is in alarm
condition and to determine the severity of that condition. The possible
alarm conditions for binary inputs are the SCAN, READ state alarms, and the
change of state alarm. The SCAN and READ alarms are called by the device
supprt routines.
The user can choose the severity of each state in the ZSV and OSV fields.
The possible values for these fields are C<NO_ALARM>, C<MINOR>, and
C<MAJOR>. The ZSV field holds the severity for the zero state; OSV, for
the one state. COSV causes an alarm whenever the state changes between
0 and 1 and the severity is configured as MINOR or MAJOR.
See L<Alarm Specification> for a complete explanation of the discrete alarm
states. L<Alarm Fields> lists other fields related to alarms that are
common to all record types.
=fields ZSV, OSV, COSV
=head3 Run-time Parameters and Simulation Mode Parameters
These parameters are used by the run-time code for processing the binary
input. They are not configured using a database configuration tool.
ORAW is used to determine if monitors should be triggered for RVAL at the same
time they are triggered for VAL.
MASK is given a value by ithe device support routines. This value is used to
manipulate the record's value, but is only the concern of the hardware device
support routines.
The LALM fields holds the value of the last occurence of the change of
state alarm. It is used to implement the change of state alarm, and thus
only has meaning if COSV is MAJOR or MINOR.
The MSLT field is used by the C<process> record support routine to
determine if archive and value change monitors are invoked. They are if MSLT
is not equal to VAL.
=fields ORAW, MASK, LALM, MLST
The following fields are used to operate the binary input in simulation
mode. See L<Fields Common to Many Record Types> for more information on
these fields.
=fields SIOL, SVAL, SIML, SIMM, SIMS
=cut
include "dbCommon.dbd"
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup("40 - Input")
interest(1)
}
field(VAL,DBF_ENUM) {
prompt("Current Value")
promptgroup("40 - Input")
asl(ASL0)
pp(TRUE)
}
field(ZSV,DBF_MENU) {
prompt("Zero Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(OSV,DBF_MENU) {
prompt("One Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(COSV,DBF_MENU) {
prompt("Change of State Svr")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(ZNAM,DBF_STRING) {
prompt("Zero Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(ONAM,DBF_STRING) {
prompt("One Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(RVAL,DBF_ULONG) {
prompt("Raw Value")
pp(TRUE)
}
field(ORAW,DBF_ULONG) {
prompt("prev Raw Value")
special(SPC_NOMOD)
interest(3)
}
field(MASK,DBF_ULONG) {
prompt("Hardware Mask")
special(SPC_NOMOD)
interest(1)
}
field(LALM,DBF_USHORT) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_USHORT) {
prompt("Last Value Monitored")
special(SPC_NOMOD)
interest(3)
}
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SVAL,DBF_ULONG) {
prompt("Simulation Value")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuSimm)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("CALLBACK *simpvt")
}
=head2 Record Support
=head3 Record Support Routines
=head2 C<init_record>
This routine initializes SIMM with the value of SIML if SIML type is a
CONSTANT link or creates a channel access link if SIML type is PV_LINK.
SVAL is likewise initialized if SIOL is a CONSTANT or PV_LINK.
This routine next checks to see that device support is available and a
device support routine is defined. If neither exist, an error is issued and
processing is terminated.
If device support includes C<init_record>, it is called.
=head2 C<process>
See next section.
=head2 C<get_value>
Fills in the values of struct valueDes so that they refer to VAL.
=head2 C<get_enum_str>
Retrieves ASCII string corresponding to VAL.
=head2 C<get_enum_strs>
Retrieves ASCII strings for ZNAM and ONAM.
=head2 C<put_enum_str>
Check if string matches ZNAM or ONAM, and if it does, sets VAL.
=head2 Record Processing
Routine process implements the following algorithm:
=over 1
=item 1.
Check to see that the appropriate device support module exists. If it
doesn't, an error message is issued and processing is terminated with
the PACT field still set to TRUE. This ensures that processes will no
longer be called for this record. Thus error storms will not occur.
=item 2.
C<readValue> is called. See L<Input Records> for details.
=item 3.
If PACT has been changed to TRUE, the device support read routine has
started but has not completed reading a new input value. In this case, the
processing routine merely returns, leaving PACT TRUE.
=item 4.
Convert.
=back
=over 1
=item *
status = read_bi
=item *
PACT = TRUE
=item *
TIME = tslocaltime
=item *
if status is 0, then set VAL=(0,1) if RVAL is (0, not 0) and UDF = False.
=item *
if status is 2, set status = 0
=back
=over 1
=item 5.
Check alarms: This routine checks to see if the new VAL causes the alarm
status and severity to change. If so, NSEV, NSTA and LALM are set. Note
that if VAL is greater than 1, no checking is performed.
=item 6.
Check if monitors should be invoked:
=back
=over 1
=item *
Alarm monitors are invoked if the alarm status or severity has changed.
=item *
Archive and value change monitors are invoked if MSLT is not equal to VAL.
=item *
Monitors for RVAL are checked whenever other monitors are invoked.
=item *
NSEV and NSTA are reset to 0.
=back
=over 1
=item 7.
Scan forward link if necessary, set PACT FALSE, and return.
=back
=head2 Device Support
=head3 Fields of Interest to Device Support
Each binary input record must have an associated set of device support
routines. The primary resposibility of the device support routines is to
obtain a new raw input value whenever C<read_bi> is called. The device
support routines are primarily interested in the following fields:
=fields PACT, DPVT, UDF, NSEV, NSTA, VAL, INP, RVAL, MASK
=head3 Device Support routines
Device support consists of the following routines:
=head2 C<report(FILE fp, paddr)>
Not currently used.
=head2 C<init()>
This routine is called once during IOC initialization.
=head2 C<init_record(precord)>
This routine is optional. If provided, it is called by the record support
C<init_record> routine.
=head2 C<get_ioint_info(int cmd, struct dbCommon *precord, IOSCANPVT *ppvt)>
This routine is called by the C<ioEventScan> system each time the record is
added or deleted from an I/O event scan list. C<cmd> has the value (0,1) if
the record is being (added to, deleted from) and I/O event list. It must be
provided for any device type that can use the ioEvent scanner.
=head2 C<read_bi(precord)>
This routine must provide a new input value. It returns the following
values:
=over
=item 0:
Success. A new raw value is placed in RVAL. The record support module
forces VAL to be (0,1) if RVAL is (0, not 0).
=item 2:
Success, but don't modify VAL.
=item Other:
Error.
=back
=head3 Device Support for Soft Records
Two soft device support modules, Soft Channel and Raw Soft Channel, are
provided for input records not related to actual hardware devices. The INP
link type must be either CONSTANT, DB_LINK, or CA_LINK.
=head3 Soft Channel
C<read_bi> always returns a value of 2, which means that no conversion is
performed.
If the INP link type is CONSTANT, then the constant value is stored in VAL
by C<init_record>, and the UDF is set to FALSE. VAL can be changed via
C<dbPut> requests. If the INP link type is PV_LINK, the C<dbCaAddInlink> is
called by C<init_record>.
C<read_bi> calls C<recGbleGetLinkValue> to read the current value of VAL.
See L<Soft Input> for details.
If the return status of C<recGblGetLinkValue> is zero, then C<read_bi> sets
UDF to FALSE. The status of C<recGblGetLinkValue> is returned.
=head3 Raw Soft Channel
This module is like the previous except that values are read into RVAL.
C<read_bi> returns a value of 0. Thus the record processing routine will
force VAL to be 0 or 1.
=cut
}

View File

@@ -1,182 +0,0 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
recordtype(bo) {
include "dbCommon.dbd"
field(VAL,DBF_ENUM) {
prompt("Current Value")
promptgroup("50 - Output")
asl(ASL0)
pp(TRUE)
}
field(OMSL,DBF_MENU) {
prompt("Output Mode Select")
promptgroup("50 - Output")
interest(1)
menu(menuOmsl)
}
field(DOL,DBF_INLINK) {
prompt("Desired Output Loc")
promptgroup("40 - Input")
interest(1)
}
field(OUT,DBF_OUTLINK) {
prompt("Output Specification")
promptgroup("50 - Output")
interest(1)
}
field(HIGH,DBF_DOUBLE) {
prompt("Seconds to Hold High")
promptgroup("30 - Action")
interest(1)
}
field(ZNAM,DBF_STRING) {
prompt("Zero Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(ONAM,DBF_STRING) {
prompt("One Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(RVAL,DBF_ULONG) {
prompt("Raw Value")
pp(TRUE)
}
field(ORAW,DBF_ULONG) {
prompt("prev Raw Value")
special(SPC_NOMOD)
interest(3)
}
field(MASK,DBF_ULONG) {
prompt("Hardware Mask")
special(SPC_NOMOD)
interest(1)
}
field(RPVT,DBF_NOACCESS) {
prompt("Record Private")
special(SPC_NOMOD)
interest(4)
extra("void * rpvt")
}
field(WDPT,DBF_NOACCESS) {
prompt("Watch Dog Timer ID")
special(SPC_NOMOD)
interest(4)
extra("void * wdpt")
}
field(ZSV,DBF_MENU) {
prompt("Zero Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(OSV,DBF_MENU) {
prompt("One Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(COSV,DBF_MENU) {
prompt("Change of State Sevr")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(RBV,DBF_ULONG) {
prompt("Readback Value")
special(SPC_NOMOD)
}
field(ORBV,DBF_ULONG) {
prompt("Prev Readback Value")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_USHORT) {
prompt("Last Value Monitored")
special(SPC_NOMOD)
interest(3)
}
field(LALM,DBF_USHORT) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(SIOL,DBF_OUTLINK) {
prompt("Simulation Output Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("CALLBACK *simpvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID outpt action")
promptgroup("50 - Output")
interest(2)
menu(menuIvoa)
}
field(IVOV,DBF_USHORT) {
prompt("INVALID output value")
promptgroup("50 - Output")
interest(2)
}
}
variable(boHIGHprecision, int)
variable(boHIGHlimit, double)

View File

@@ -0,0 +1,611 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Binary Output Record (bo)
The normal use for this record type is to store a simple bit (0 or 1) value
to be sent to a Digital Output module. It can also be used to write binary
values into other records via database or channel access links. This record
can implement both latched and momentary binary outputs depending on how
the HIGH field is configured.
=head2 Parameter Fields
The binary output's fields fall into the following categories:
=over 1
=item *
scan parameters
=item *
convert and write parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
run-time parameters
=back
=recordtype bo
=cut
recordtype(bo) {
=head3 Scan Parameters
The binary output record has the standard fields for specifying under what
circumstances the record will be processed. The fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Note that I/O event scanning is only supported for those card
types that interrupt.
=fields SCAN
=head3 Desired Output Parameters
The binary output record must specify where its desired output originates.
The desired output needs to be in engineering units.
The first field that determines where the desired output originates is the
output mode select (OMSL) field, which can have two possible values:
C<losed_loop> or C<supervisory>. If C<supervisory> is specified, the value
in the VAL field can be set externally via dbPuts at run-time. If
C<closed_loop> is specified, the VAL field's value is obtained from the
address specified in the desired output location (DOL) field which can be a
database link, a channel access link, or a constant. To achieve continuous
control, a database link to a control algorithm record should be entered in
the DOL field.
L<Address Specification> presents more information on database addresses
and links. L<Scanning Specification> explaines the effect of database
linkage on scanning.
=fields DOL, OMSL
=head3 Convert and Write Parameters
These parameters are used to determine where the binary output writes to
and how to convert the engineering units to a raw signal. After VAL is set
and forced to be either 1 or 0, as the result of either a dbPut or a new
value being retrieved from the link in the DOL field, then what happens
next depends on which device support routine is used and how the HIGH field
is configured.
If the C<Soft Channel> device support routine is specified, then the device
support routine writes the VAL field's value to the address specified in
the OUT field. Otherwise, RVAL is the value written by the device support
routines after being converted.
If VAL is equal to 0, then the record processing routine sets RVAL equal to
zero. When VAL is not equal to 0, then RVAL is set equal to the value
contained in the MASK field. (MASK is set by the device support routines
and is of no concern to the user.) Also, when VAL is not 0 and after RVAL is
set equal to MASK, the record processing routine checks to see if the HIGH
field is greater than 0. If it is, then the routine will process the record
again with VAL set to 0 after the number of seconds specified by HIGH.
Thus, HIGH implements a momentary output which changes the state of the
device back to 0 after I<N> number of seconds.
=fields DTYP, OUT, VAL, RVAL, HIGH, ZNAM, ONAM
=head3 Conversion Parameters
The ZNAM field has the string that corresponds to the 0 state, and the ONAM
field holds the string that corresponds to the 1 state. These fields, other
than being used to tell the operator what each state represents, are used
to perform conversions if the value fetched by DOL is a string. If it is,
VAL is set to the state which corresponds to that string. For instance, if the
value fetched is the string "Off" and the ZNAM string is "Off," then VAL is
set to 0.
After VAL is set, if VAL is equal to 0, then the record processing routine
sets RVAL equal to zero. When VAL is not equal to 0, then RVAL is set equal
to the value contained in the MASK field. (Mask is set by the device
support routines and is of no concern to the user.) Also when VAL is equal
to 1 and after RVAL is set equal to MASK, the record processing routine checks
to see if the HIGH field is greater than 0. If it is, then the routine
processes the record again with VAL=0 after the number of seconds specified
by HIGH. Thus, HIGH implements a latched output which changes the state of
the device or link to 1, then changes it back to 0 after I<N> number of seconds.
=fields ZNAM, ONAM, HIGH
=head3 Output Specification
The OUT field specifies where the binary output record writes its output.
It must specify the address of an I/O card if the record sends its output
to hardware, and the DTYP field must contain the corresponding device
support module. Be aware that the address format differs according to the
I/O bus used. See L<Address Specification> for information on the format of
hardware addresses. You can see a list of device support modules currently
supported at the user's local site by using the C<dbst> utility in R3.13.
Otherwise, if the record is configured to use the soft device support
modules, then it can be either a database link, a channel access link, or a
constant. Be aware that nothing will be written when OUT is a constant. See
L<Address Specification> for information on the format of the database and
channel access addresses. Also, see L<Device Support For Soft Records> in
this chapter for more on output to other records.
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator, The
C<get_enum_str> record support routine can retrieve the state string
corresponding to the VAL's state. So, if the value is 1, C<get_enum_str>
will return the string in the ONAM field: and if 0, C<get_enum_str> will
return the ZNAM string.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
=fields ZNAM, ONAM, NAME, DESC
=head3 Alarm Parameters
These parameters are used to determine the binary output's alarm condition
and to determine the severity of that condition. The possible alarm
conditions for binary outputs are the SCAN, READ, INVALID and state alarms.
The user can configure the state alarm conditions using these fields.
The possible values for these fields are C<NO_ALARM>, C<MINOR>, and
C<MAJOR>. The ZSV holds the severity for the zero state; OSV for the one
state. COSV is used to cause an alarm whenever the state changes between
states (0-1, 1-0) and its severity is configured as MINOR or MAJOR.
See L<Invalid Alarm Output Action> for more information on the IVOA and
IVOV fields. L<Alarm Fields> lists other fields related to alarms that are
common to all record types.
=fields ZSV, OSV, COSV, IVOA, IVOV
=head3 Run-Time and Simulation Mode Parameters
These parameters are used by the run-time code for processiong the binary
output. They are not configurable using a configuration tool. They
represent the current state of the binary output.
ORAW is used to determine if monitors should be triggered for RVAL at the
same time they are triggered for VAL.
MASK is given a value by the device support routines and should not concern
the user.
The RBV field is also set by device support. It is the actual read back
value obtained from the hardware itself or from the associated device
driver.
The ORBV field is used to decide if monitors should be triggered
for RBV at the same time monitors are triggered for changes in VAL.
The LALM field holds the value of the last occurrence of the change of
state alarm. It is used to implement the change of state alarm, and thus
only has meaning if COSV is MINOR or MAJOR.
The MLST is used by the C<process> record support routine to determine if
archive and value change monitors are invoked. They are if MLST is not
equal to VAL.
The WPDT field is a private field for honoring seconds to hold HIGH.
=fields ORAW, MASK, RBV, ORBV, LALM, MLST, RPVT, WDPT
The following fields are used to operate the binary output in the
simulation mode. See L<Fields Common to Many Record Types> for more
information on these fields.
=fields SIOL, SIML, SIMM, SIMS
=cut
include "dbCommon.dbd"
field(VAL,DBF_ENUM) {
prompt("Current Value")
promptgroup("50 - Output")
asl(ASL0)
pp(TRUE)
}
field(OMSL,DBF_MENU) {
prompt("Output Mode Select")
promptgroup("50 - Output")
interest(1)
menu(menuOmsl)
}
field(DOL,DBF_INLINK) {
prompt("Desired Output Loc")
promptgroup("40 - Input")
interest(1)
}
field(OUT,DBF_OUTLINK) {
prompt("Output Specification")
promptgroup("50 - Output")
interest(1)
}
field(HIGH,DBF_DOUBLE) {
prompt("Seconds to Hold High")
promptgroup("30 - Action")
interest(1)
}
field(ZNAM,DBF_STRING) {
prompt("Zero Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(ONAM,DBF_STRING) {
prompt("One Name")
promptgroup("80 - Display")
pp(TRUE)
interest(1)
size(26)
prop(YES)
}
field(RVAL,DBF_ULONG) {
prompt("Raw Value")
pp(TRUE)
}
field(ORAW,DBF_ULONG) {
prompt("prev Raw Value")
special(SPC_NOMOD)
interest(3)
}
field(MASK,DBF_ULONG) {
prompt("Hardware Mask")
special(SPC_NOMOD)
interest(1)
}
field(RPVT,DBF_NOACCESS) {
prompt("Record Private")
special(SPC_NOMOD)
interest(4)
extra("void * rpvt")
}
field(WDPT,DBF_NOACCESS) {
prompt("Watch Dog Timer ID")
special(SPC_NOMOD)
interest(4)
extra("void * wdpt")
}
field(ZSV,DBF_MENU) {
prompt("Zero Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(OSV,DBF_MENU) {
prompt("One Error Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(COSV,DBF_MENU) {
prompt("Change of State Sevr")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(RBV,DBF_ULONG) {
prompt("Readback Value")
special(SPC_NOMOD)
}
field(ORBV,DBF_ULONG) {
prompt("Prev Readback Value")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_USHORT) {
prompt("Last Value Monitored")
special(SPC_NOMOD)
interest(3)
}
field(LALM,DBF_USHORT) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(SIOL,DBF_OUTLINK) {
prompt("Simulation Output Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("CALLBACK *simpvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID outpt action")
promptgroup("50 - Output")
interest(2)
menu(menuIvoa)
}
field(IVOV,DBF_USHORT) {
prompt("INVALID output value")
promptgroup("50 - Output")
interest(2)
}
=head2 Record Support
=head3 Record Support Routines
=head2 C<init_record>
This routine initializes SIMM if SIML is a constant or creates a channel
access link if SIML is PV_LINK. If SIOL is a PV_LINK a channel access link
is created.
This routine next checks to see that device support is available. The
routine next checks to see if the device support write routine is defined.
If either device support or the device support write routine does not
exist, and error message is issued and processing is terminated.
If DOL is a constant, then VAL is initialized to 1 if its value is nonzero
or initialzed to 0 if DOL is zero, and UDF is set to FALSE.
If device support includes C<init_record>, it is called. VAL is set using
RVAL, and UDF is set to FALSE.
=head2 C<process>
See next section.
=head2 C<get_value>
Fills in the values of struct valueDes so that they refer to VAL.
=head2 C<get_enum_str>
Retrieves ASCII string corresponding to VAL.
=head2 C<get_enum_strs>
Retrieves ASCII strings for ZNAM and ONAM.
=head2 C<put_enum_str>
Checks if string matches ZNAM or ONAM, and if it does, sets VAL.
=head2 Record Processing
Routine process implements the following algorithm:
=over 1
=item 1.
Check to see that the appropriate device support module exists. If it
doesn't, an error message is issued and processing is terminated with
the PACT field still set to TRUE. This ensures that processes will no
longer be called for this record. Thus error storms will not occur.
=item 2.
If PACT is FALSE
=back
=over
=item *
If DOL is DB_LINK and OMSL is CLOSED_LOOP
=over
=item *
get values from DOL
=item *
check for link alarm
=item *
force VAL to be 0 or 1
=item *
if MASK is defined
=over
=item *
if VAL is 0 set RVAL = 0
=back
=item *
else set RVAL = MASK
=back
=back
=over
=item 3.
Check alarms: This routine checks to see if the new VAL causes the alarm
status and severity to change. If so, NSEV, NSTA, and LALM are set.
=item 4.
Check severity and write the new value. See L<Invalid Alarm Output Action>
for more information on how INVALID alarms affect output.
=item 5.
If PACT has been changed to TRUE, the device support write output routine
has started but has not completed writing the new value. in this case, the
processing routine merely returns, leaving PACT TRUE.
=item 6.
Check WAIT. If VAL is 1 and WAIT is greater than 0, process again with a
VAL=0 after WAIT seconds.
=item 7.
Check to see if monitors should be invoked.
=back
=over 1
=item *
Alarm monitors are invoked if the alarm status or severity has changed.
=item *
Archive and value change monitors are invoked if MLST is not equal to VAL.
=item *
Monitors for RVAL and for RBV are checked whenever other monitors are
invoked.
=item *
NSEV and NSTA are reset to 0.
=back
=over
=item 8
Scan forward link if necessary, set PACT FALSE, and return
=back
=head2 Device support
=head3 Fields Of Interest To Device Support
Each binary output record must have an associated set of device support
routines. The primary responsibility of the device support routines is to
write a new value whenever C<write_bo> is called. The device support routines
are primarily interested in the following fields:
=fields PACT, DPVT, NSEV, NSTA, VAL, OUT, RVAL, MASK, RBV
=head3 Decive Support Routines
Device support consists of the following routines:
=head2 C<report(FILE fp, paddr)>
Not currently used.
=head2 C<init()>
This routine is called once during IOC initialization.
=head2 C<init_record(precord)>
This routine is optional. If provided, it is called by record support
C<init_record> routine. It should determine MASK if it is needed.
=over
=item *
0: Success. RVAL modified (VAL will be set accordingly)
=item *
2: Success. VAL modified
=item *
other: Error
=back
=head2 C<get_ioint_info(int cmd, struct dbCommon *precord, IOSCANPVT *ppvt)>
This routine is called by the ioEventScan system each time the record is
added or deleted from an I/O event scan list. C<cmd> has the value (0,1) if
the record is being (added to, deleted from) an I/O event list. It must be
provided for any device type that can use the ioEvent scanner.
=head2 C<write_bo(precord)>
This routine must output a new value. It returns the following values:
=over
=item *
0: Success
=item *
other: Error.
=back
=head2 Device Support For Soft Records
Two soft device support modules C<Soft Channel> and C<Raw Soft Channel> are
provided for output records not related to actual hardware devices. The OUT
link type must be either CONSTANT, DB_LINK, or CA_LINK.
=head3 Soft Channel
This module writes the current value of VAL.
If the OUT link type is PV_LINK, then C<dbCaAddInlink> is called by
C<init_record>. C<init_record> always returns a value of 2, which means
that no conversion will ever be attempted. C<write_bo> calls
C<recGblPutLinkValue> to write the current value of VAL. See L<Soft Output>
for details.
=head3 Raw Soft Channel
This module is like the previous except that it writes the current value of
RVAL
=cut
}
variable(boHIGHprecision, int)
variable(boHIGHlimit, double)

View File

@@ -1,324 +0,0 @@
#*************************************************************************
# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
recordtype(calc) {
include "dbCommon.dbd"
field(VAL,DBF_DOUBLE) {
prompt("Result")
promptgroup("50 - Output")
asl(ASL0)
}
field(CALC,DBF_STRING) {
prompt("Calculation")
promptgroup("30 - Action")
special(SPC_CALC)
pp(TRUE)
size(80)
initial("0")
}
field(INPA,DBF_INLINK) {
prompt("Input A")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPB,DBF_INLINK) {
prompt("Input B")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPC,DBF_INLINK) {
prompt("Input C")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPD,DBF_INLINK) {
prompt("Input D")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPE,DBF_INLINK) {
prompt("Input E")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPF,DBF_INLINK) {
prompt("Input F")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPG,DBF_INLINK) {
prompt("Input G")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPH,DBF_INLINK) {
prompt("Input H")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPI,DBF_INLINK) {
prompt("Input I")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPJ,DBF_INLINK) {
prompt("Input J")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPK,DBF_INLINK) {
prompt("Input K")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPL,DBF_INLINK) {
prompt("Input L")
promptgroup("42 - Input G-L")
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Rng")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HIHI,DBF_DOUBLE) {
prompt("Hihi Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOLO,DBF_DOUBLE) {
prompt("Lolo Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HIGH,DBF_DOUBLE) {
prompt("High Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOW,DBF_DOUBLE) {
prompt("Low Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(AFTC, DBF_DOUBLE) {
prompt("Alarm Filter Time Constant")
promptgroup("70 - Alarm")
interest(1)
}
field(AFVL, DBF_DOUBLE) {
prompt("Alarm Filter Value")
special(SPC_NOMOD)
interest(3)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup("70 - Alarm")
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup("80 - Display")
interest(1)
}
field(A,DBF_DOUBLE) {
prompt("Value of Input A")
pp(TRUE)
}
field(B,DBF_DOUBLE) {
prompt("Value of Input B")
pp(TRUE)
}
field(C,DBF_DOUBLE) {
prompt("Value of Input C")
pp(TRUE)
}
field(D,DBF_DOUBLE) {
prompt("Value of Input D")
pp(TRUE)
}
field(E,DBF_DOUBLE) {
prompt("Value of Input E")
pp(TRUE)
}
field(F,DBF_DOUBLE) {
prompt("Value of Input F")
pp(TRUE)
}
field(G,DBF_DOUBLE) {
prompt("Value of Input G")
pp(TRUE)
}
field(H,DBF_DOUBLE) {
prompt("Value of Input H")
pp(TRUE)
}
field(I,DBF_DOUBLE) {
prompt("Value of Input I")
pp(TRUE)
}
field(J,DBF_DOUBLE) {
prompt("Value of Input J")
pp(TRUE)
}
field(K,DBF_DOUBLE) {
prompt("Value of Input K")
pp(TRUE)
}
field(L,DBF_DOUBLE) {
prompt("Value of Input L")
pp(TRUE)
}
field(LA,DBF_DOUBLE) {
prompt("Prev Value of A")
special(SPC_NOMOD)
interest(3)
}
field(LB,DBF_DOUBLE) {
prompt("Prev Value of B")
special(SPC_NOMOD)
interest(3)
}
field(LC,DBF_DOUBLE) {
prompt("Prev Value of C")
special(SPC_NOMOD)
interest(3)
}
field(LD,DBF_DOUBLE) {
prompt("Prev Value of D")
special(SPC_NOMOD)
interest(3)
}
field(LE,DBF_DOUBLE) {
prompt("Prev Value of E")
special(SPC_NOMOD)
interest(3)
}
field(LF,DBF_DOUBLE) {
prompt("Prev Value of F")
special(SPC_NOMOD)
interest(3)
}
field(LG,DBF_DOUBLE) {
prompt("Prev Value of G")
special(SPC_NOMOD)
interest(3)
}
field(LH,DBF_DOUBLE) {
prompt("Prev Value of H")
special(SPC_NOMOD)
interest(3)
}
field(LI,DBF_DOUBLE) {
prompt("Prev Value of I")
special(SPC_NOMOD)
interest(3)
}
field(LJ,DBF_DOUBLE) {
prompt("Prev Value of J")
special(SPC_NOMOD)
interest(3)
}
field(LK,DBF_DOUBLE) {
prompt("Prev Value of K")
special(SPC_NOMOD)
interest(3)
}
field(LL,DBF_DOUBLE) {
prompt("Prev Value of L")
special(SPC_NOMOD)
interest(3)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
%#include "postfix.h"
field(RPCL,DBF_NOACCESS) {
prompt("Reverse Polish Calc")
special(SPC_NOMOD)
interest(4)
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
}
}

View File

@@ -0,0 +1,948 @@
#*************************************************************************
# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Calculation Record (calc)
The calculation or "Calc" record is used to perform algebraic, relational,
and logical operations on values retrieved from other records. The result
of its operations can then be accessed by another record so that it can
then be used.
=head2 Parameter Fields
The fields in the record fall into the following categories:
=over 1
=item *
scan parameters
=item *
read parameters
=item *
expression parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
monitor parameters
=item *
run-time parameters
=back
=recordtype calc
=cut
recordtype(calc) {
=head3 Scan Parameters
The Calc record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Since the Calc record supports no direct interfaces to
hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot
be C<I/O Intr>.
=fields SCAN
=head3 Read Parameters
The read parameters for the Calc record consist of 12 input links INPA,
INPB, ... INPL. The fields can be database links, channel access links, or
constants. If they are links, they must specify another record's field or a
channel access link. If they are constants, they will be initialized with
the value they are configured with and can be changed via C<dbPuts>. They
cannot be hardware addresses.
See L<Address Specification> for information on how to specify database
links.
=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
=head3 Expression
At the core of the Calc record lies the CALC and RPCL fields. The CALC field
contains the infix expresion which the record routine will use when it
processes the record. The resulting value is placed in the VAL field and
can be accessed from there. The CALC expression is actually converted to
opcode and stored as Reverse Polish Notation in the RPCL field. It is this
expression which is actually used to calculate VAL. The Reverse Polish
expression is evaluated more efficiently during run-time than an infix
expression. CALC can be changed at run-time, and a special record routine
calls a function to convert it to Reverse Polish Notation.
The infix expressions that can be used are very similar to the C expression
syntax, but with some additions and subtle differences in operator meaning
and precedence. The string may contain a series of expressions separated by
a semi-colon character ";" any one of which may actually provide the
calculation result; however, all of the other expressions included must
assign their result to a variable. All alphabetic elements described below
are case independent, so upper and lower case letters may be used and mixed
in the variable and function names as desired. Spaces may be used anywhere
within an expression except between characters that make up a single
expression element.
The range of expressions supported by the calculation record are separated
into literals, constants, operands, algebraic operators, trigonometric operators,
relational operators, logical operators, the assignment operator,
parentheses and commas, and the question mark or '?:' operator.
=fields CALC, RPCL
=head3 Literals
=over 1
=item *
Standard double precision floating point numbers
=item *
Inf: Infinity
=item *
Nan: Not a Number
=back
=head3 Constants
=over 1
=item *
PI: returns the mathematical constant E<pi>
=item *
D2R: evaluates to E<pi>/180 which, when used as a multiplier, converts an
angle from degrees to radians
=item *
R2D: evaluates to 180/E<pi> which as a multiplier converts an angle from
radians to degrees
=back
=head3 Operands
The expression uses the values retrieved from the INPx links as operands,
though constants can be used as operands too. These values retrieved from
the input links are stored in the A-L fields. The values to be used in the
expression are simply referenced by the field letter. For instance, the
value obtained from INPA link is stored in the field A, and the value
obtained from INPB is stored in field B. The field names can be included in
the expression which will operate on their respective values, as in A+B.
Also, the RNDM nullary function can be included as an operand in the
expression in order to generate a random number between 0 and 1.
=fields A, B, C, D, E, F, G, H, I, J, K, L
The keyword VAL returns the current contents of the VAL field (which can be
written to by a CA put, so it might I<not> be the result from the last time
the expression was evaluated).
=head3 Algebraic Operators
=over 1
=item *
ABS: Absolute value (unary)
=item *
SQR: Square root (unary)
=item *
MIN: Minimum (any number of args)
=item *
MAX: Maximum (any number of args)
=item *
FINITE: returns non-zero if none of the arguments are NaN or Inf (any
number of args)
=item *
ISNAN: returns non-zero if any of the arguments is NaN or Inf (any number
of args)
=item *
CEIL: Ceiling (unary)
=item *
FLOOR: Floor (unary)
=item *
LOG: Log base 10 (unary)
=item *
LOGE: Natural log (unary)
=item *
LN: Natural log (unary)
=item *
EXP: Exponential function (unary)
=item *
^ : Exponential (binary)
=item *
** : Exponential (binary)
=item *
+ : Addition (binary)
=item *
- : Subtraction (binary)
=item *
* : Multiplication (binary)
=item *
/ : Division (binary)
=item *
% : Modulo (binary)
=item *
NOT: Negate (unary)
=back
=head3 Trigonometric Operators
=over 1
=item *
SIN: Sine
=item *
SINH: Hyperbolic sine
=item *
ASIN: Arc sine
=item *
COS: Cosine
=item *
COSH: Hyperbolic cosine
=item *
ACOS: Arc cosine
=item *
TAN: Tangent
=item *
TANH: Hyperbolic tangent
=item *
ATAN: Arc tangent
=back
=head3 Relational Operators
=over 1
=item *
>= : Greater than or equal to
=item *
> : Greater than
=item *
<= : Less than or equal to
=item *
< : Less than
=item *
# : Not equal to
=item *
= : Equal to
=back
=head3 Logical Operators
=over 1
=item *
&& : And
=item *
|| : Or
=item *
! : Not
=back
=head3 Bitwise Operators
=over 1
=item *
| : Bitwise Or
=item *
& : Bitwise And
=item *
OR : Bitwise Or
=item *
AND : Bitwise And
=item *
XOR : Bitwise Exclusive Or
=item *
~ : One's Complement
=item *
<< : Left shift
=item *
>> : Right shift
=back
=head3 Assignment Operator
=over 1
=item *
:= : assigns a value (right hand side) to a variable (i.e. field)
=back
=head3 Parantheses, Comma, and Semicolon
The open and close parentheses are supported. Nested parentheses are
supported.
The comma is supported when used to separate the arguments of a binary
function.
The semicolon is used to separate expressions. Although only one
traditional calculation expression is allowed, multiple assignment
expressions are allowed.
=head3 Conditional Expression
The C language's question mark operator is supported. The format is:
C<condition ? True result : False result>
=head3 Expression Examples
=head3 Algebraic
C<A + B + 10>
=over 1
=item *
Result is A + B + 10
=back
=head3 Relational
C<(A + B) < (C + D)>
=over 1
=item *
Result is 1 if (A + B) < (C + D)
=item *
Result is 0 if (A + B) >= (C + D)
=back
=head3 Question Mark
C<(A + B) < (C + D) ? E : F + L + 10>
=over 1
=item *
Result is E if (A + B) < (C + D)
=item *
Result is F + L + 10 if (A + B) >= (C + D)
=back
Prior to Base 3.14.9 it was legal to omit the : and the second (else) part
of the conditional, like this:
C<(A + B)<(C + D) ? E>
=over 1
=item
Result is E if (A + B)<(C + D)
=item
Result is unchanged if (A + B)>=(C + D)
From 3.14.9 onwards, this expresion must be written as
C<(A + B) < (C + D) ? E : VAL>
=back
=head3 Logical
C<A&B>
=over 1
=item *
Causes the following to occur:
=over 1
=item *
Convert A to integer
=item *
Convert B to integer
=item *
Bitwise And A and B
=item *
Convert result to floating point
=back
=back
=head3 Assignment
C<sin(a); a:=a+D2R>
=over 1
=item *
Causes the Calc record to output the successive values of a sine curve in
1 degree intervals.
=back
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. These
fields are used to display VAL and other parameters of the calculation
record either textually or graphically.
The EGU field contains a string of up to 16 characters which is supplied by
the user and which describes the values being operated upon. The string is
retrieved whenever the routine C<get_units> is called. The EGU string is
solely for an operator's sake and does not have to be used.
The HOPR and LOPR fields only refer to the limits of the VAL, HIHI, HIGH,
LOW and LOLO fields. PREC controls the precision of the VAL field.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
=fields EGU, PREC, HOPR, LOPR, NAME, DESC
=head3 Alarm Parameters
The possible alarm conditions for the Calc record are the SCAN, READ,
Calculation, and limit alarms. The SCAN and READ alarms are called by the
record support routines. The Calculation alarm is called by the record
processing routine when the CALC expression is an invalid one, upon which
an error message is generated.
The following alarm parameters which are configured by the user, define the
limit alarms for the VAL field and the severity corresponding to those
conditions.
The HYST field defines an alarm deadband for each limit. See L<Alarm Specification>
for a complete explanation of alarms of these fields. L<Alarm Fields>
lists other fields related to alarms that are common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
=head3 Monitor Parameters
These paramaeters are used to determine when to send monitors for the value
fields. These monitors are sent when the value field exceeds the last
monitored field by the appropriate deadband, the ADEL for archiver monitors
and the MDEL field for all other types of monitors. If these fields have a
value of zero, everytime the value changes, monitors are triggered; if they have a
value of -1, everytime the record is scanned, monitors are triggered. See
L<Monitor Specification> for a complete explanation of monitors.
=fields ADEL, MDEL
=head3 Run-time Parameters
These fields are not configurable using a configuration tool and none are
modifiable at run-time. They are used to process the record.
The LALM field is used to implement the hysteresis factor for the alarm
limits.
The LA-LL fields are used to decide when to trigger monitors for the
corresponding fields. For instance, if LA does not equal the value A,
monitors for A are triggered. The MLST and ALST fields are used in the same
manner for the VAL field.
=fields LALM, ALST, MLST, LA, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL
=cut
include "dbCommon.dbd"
field(VAL,DBF_DOUBLE) {
prompt("Result")
promptgroup("50 - Output")
asl(ASL0)
}
field(CALC,DBF_STRING) {
prompt("Calculation")
promptgroup("30 - Action")
special(SPC_CALC)
pp(TRUE)
size(80)
initial("0")
}
field(INPA,DBF_INLINK) {
prompt("Input A")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPB,DBF_INLINK) {
prompt("Input B")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPC,DBF_INLINK) {
prompt("Input C")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPD,DBF_INLINK) {
prompt("Input D")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPE,DBF_INLINK) {
prompt("Input E")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPF,DBF_INLINK) {
prompt("Input F")
promptgroup("41 - Input A-F")
interest(1)
}
field(INPG,DBF_INLINK) {
prompt("Input G")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPH,DBF_INLINK) {
prompt("Input H")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPI,DBF_INLINK) {
prompt("Input I")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPJ,DBF_INLINK) {
prompt("Input J")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPK,DBF_INLINK) {
prompt("Input K")
promptgroup("42 - Input G-L")
interest(1)
}
field(INPL,DBF_INLINK) {
prompt("Input L")
promptgroup("42 - Input G-L")
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Rng")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HIHI,DBF_DOUBLE) {
prompt("Hihi Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOLO,DBF_DOUBLE) {
prompt("Lolo Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HIGH,DBF_DOUBLE) {
prompt("High Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOW,DBF_DOUBLE) {
prompt("Low Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(AFTC, DBF_DOUBLE) {
prompt("Alarm Filter Time Constant")
promptgroup("70 - Alarm")
interest(1)
}
field(AFVL, DBF_DOUBLE) {
prompt("Alarm Filter Value")
special(SPC_NOMOD)
interest(3)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup("70 - Alarm")
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup("80 - Display")
interest(1)
}
field(A,DBF_DOUBLE) {
prompt("Value of Input A")
pp(TRUE)
}
field(B,DBF_DOUBLE) {
prompt("Value of Input B")
pp(TRUE)
}
field(C,DBF_DOUBLE) {
prompt("Value of Input C")
pp(TRUE)
}
field(D,DBF_DOUBLE) {
prompt("Value of Input D")
pp(TRUE)
}
field(E,DBF_DOUBLE) {
prompt("Value of Input E")
pp(TRUE)
}
field(F,DBF_DOUBLE) {
prompt("Value of Input F")
pp(TRUE)
}
field(G,DBF_DOUBLE) {
prompt("Value of Input G")
pp(TRUE)
}
field(H,DBF_DOUBLE) {
prompt("Value of Input H")
pp(TRUE)
}
field(I,DBF_DOUBLE) {
prompt("Value of Input I")
pp(TRUE)
}
field(J,DBF_DOUBLE) {
prompt("Value of Input J")
pp(TRUE)
}
field(K,DBF_DOUBLE) {
prompt("Value of Input K")
pp(TRUE)
}
field(L,DBF_DOUBLE) {
prompt("Value of Input L")
pp(TRUE)
}
field(LA,DBF_DOUBLE) {
prompt("Prev Value of A")
special(SPC_NOMOD)
interest(3)
}
field(LB,DBF_DOUBLE) {
prompt("Prev Value of B")
special(SPC_NOMOD)
interest(3)
}
field(LC,DBF_DOUBLE) {
prompt("Prev Value of C")
special(SPC_NOMOD)
interest(3)
}
field(LD,DBF_DOUBLE) {
prompt("Prev Value of D")
special(SPC_NOMOD)
interest(3)
}
field(LE,DBF_DOUBLE) {
prompt("Prev Value of E")
special(SPC_NOMOD)
interest(3)
}
field(LF,DBF_DOUBLE) {
prompt("Prev Value of F")
special(SPC_NOMOD)
interest(3)
}
field(LG,DBF_DOUBLE) {
prompt("Prev Value of G")
special(SPC_NOMOD)
interest(3)
}
field(LH,DBF_DOUBLE) {
prompt("Prev Value of H")
special(SPC_NOMOD)
interest(3)
}
field(LI,DBF_DOUBLE) {
prompt("Prev Value of I")
special(SPC_NOMOD)
interest(3)
}
field(LJ,DBF_DOUBLE) {
prompt("Prev Value of J")
special(SPC_NOMOD)
interest(3)
}
field(LK,DBF_DOUBLE) {
prompt("Prev Value of K")
special(SPC_NOMOD)
interest(3)
}
field(LL,DBF_DOUBLE) {
prompt("Prev Value of L")
special(SPC_NOMOD)
interest(3)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
%#include "postfix.h"
field(RPCL,DBF_NOACCESS) {
prompt("Reverse Polish Calc")
special(SPC_NOMOD)
interest(4)
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
}
=head2 Record Support
=head3 Record Support Routines
=head2 C<init_record>
For each constant input link, the corresponding value field is initialized
with the constant value if the input link is CONSTANT or a channel access
link is created if the input link is a PV_LINK.
A routine postfix is called to convert the infix expression in CALC to
Reverse Polish Notation. The result is stored in RPCL.
=head2 C<process>
See next section.
=head2 C<special>
This is called if CALC is changed. C<special> calls postfix.
=head2 C<get_value>
Fills in the values of struct valueDes so that the refer to VAL.
=head2 C<get_units>
Retrieves EGU.
=head2 C<get_precision>
Retrieves PREC.
=head2 C<get_graphic_double>
Sets the upper display and lower display limits for a field. If the field
is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and LOPR, else
if the field has upper and lower limits defined they will be used, else the
upper and lower maximum values for the field will be used.
=head2 C<get_control_double>
Sets the upper control and the lower control limits for a field. If the
field is VAL, HIHI, HIGH, LOW, or LOLO, the limits are set to HOPR and
LOPR, else if the field has upper and lower limits defined they will be
used, else the upper and lower maximum values for the field type will be
used.
=head2 C<get_alarm_double>
Sets the following values:
=over 1
upper_alarm_limit = HIHI
upper_warning_limit = HIGH
lower_warning_limit = LOW
lower_alarm_limit = LOLO
=back
=head3 Record Processing
Routine process implements the following algorithm:
=over 1
=item 1.
Fetch all arguments.
=item 2.
Call routine C<calcPerform>, which calculates VAL from the postfix version of
the expression given in CALC. If C<calcPerform> returns success UDF is set to
FALSE.
=item 3.
Check alarms. This routine checks to see if the new VAL causes the alarm
status and severity to change. If so, NSEV, NSTA, and LALM are set. It also
honors the alarm hysteresis factor (HYST). Thus the value must change by
at least HYST before the alarm status and severity changes.
=item 4.
Check to see if monitors should be invoked.
=back
=over 1
=item *
Alarm monitors are invoked if the alarm status or severity has changed.
=item *
Archive and values change monitors are invoked if ADEL and MDEL conditions
are met.
=item *
Monitors for A-L are checked whenever other monitors are invoked.
=item *
NSEV and NSTA are reset to 0.
=back
=over
=item 5.
Scan forward link if necessary, set PACT FALSE, and return.
=back
=cut
}

View File

@@ -1,530 +0,0 @@
#*************************************************************************
# Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(calcoutOOPT) {
choice(calcoutOOPT_Every_Time,"Every Time")
choice(calcoutOOPT_On_Change,"On Change")
choice(calcoutOOPT_When_Zero,"When Zero")
choice(calcoutOOPT_When_Non_zero,"When Non-zero")
choice(calcoutOOPT_Transition_To_Zero,"Transition To Zero")
choice(calcoutOOPT_Transition_To_Non_zero,"Transition To Non-zero")
}
menu(calcoutDOPT) {
choice(calcoutDOPT_Use_VAL,"Use CALC")
choice(calcoutDOPT_Use_OVAL,"Use OCAL")
}
menu(calcoutINAV) {
choice(calcoutINAV_EXT_NC,"Ext PV NC")
choice(calcoutINAV_EXT,"Ext PV OK")
choice(calcoutINAV_LOC,"Local PV")
choice(calcoutINAV_CON,"Constant")
}
recordtype(calcout) {
include "dbCommon.dbd"
field(RPVT,DBF_NOACCESS) {
prompt("Record Private")
special(SPC_NOMOD)
interest(4)
extra("struct rpvtStruct *rpvt")
}
field(VAL,DBF_DOUBLE) {
prompt("Result")
promptgroup("50 - Output")
asl(ASL0)
}
field(PVAL,DBF_DOUBLE) {
prompt("Previous Value")
}
field(CALC,DBF_STRING) {
prompt("Calculation")
promptgroup("30 - Action")
special(SPC_CALC)
pp(TRUE)
size(80)
initial("0")
}
field(CLCV,DBF_LONG) {
prompt("CALC Valid")
interest(1)
}
field(INPA,DBF_INLINK) {
prompt("Input A")
special(SPC_MOD)
promptgroup("41 - Input A-F")
interest(1)
}
field(INPB,DBF_INLINK) {
prompt("Input B")
special(SPC_MOD)
promptgroup("41 - Input A-F")
interest(1)
}
field(INPC,DBF_INLINK) {
prompt("Input C")
special(SPC_MOD)
promptgroup("41 - Input A-F")
interest(1)
}
field(INPD,DBF_INLINK) {
prompt("Input D")
special(SPC_MOD)
promptgroup("41 - Input A-F")
interest(1)
}
field(INPE,DBF_INLINK) {
prompt("Input E")
special(SPC_MOD)
promptgroup("41 - Input A-F")
interest(1)
}
field(INPF,DBF_INLINK) {
prompt("Input F")
special(SPC_MOD)
promptgroup("41 - Input A-F")
interest(1)
}
field(INPG,DBF_INLINK) {
prompt("Input G")
special(SPC_MOD)
promptgroup("42 - Input G-L")
interest(1)
}
field(INPH,DBF_INLINK) {
prompt("Input H")
special(SPC_MOD)
promptgroup("42 - Input G-L")
interest(1)
}
field(INPI,DBF_INLINK) {
prompt("Input I")
special(SPC_MOD)
promptgroup("42 - Input G-L")
interest(1)
}
field(INPJ,DBF_INLINK) {
prompt("Input J")
special(SPC_MOD)
promptgroup("42 - Input G-L")
interest(1)
}
field(INPK,DBF_INLINK) {
prompt("Input K")
special(SPC_MOD)
promptgroup("42 - Input G-L")
interest(1)
}
field(INPL,DBF_INLINK) {
prompt("Input L")
special(SPC_MOD)
promptgroup("42 - Input G-L")
interest(1)
}
field(OUT,DBF_OUTLINK) {
prompt("Output Specification")
special(SPC_MOD)
promptgroup("50 - Output")
interest(1)
}
field(INAV,DBF_MENU) {
prompt("INPA PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INBV,DBF_MENU) {
prompt("INPB PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INCV,DBF_MENU) {
prompt("INPC PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INDV,DBF_MENU) {
prompt("INPD PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INEV,DBF_MENU) {
prompt("INPE PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INFV,DBF_MENU) {
prompt("INPF PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INGV,DBF_MENU) {
prompt("INPG PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INHV,DBF_MENU) {
prompt("INPH PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INIV,DBF_MENU) {
prompt("INPI PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INJV,DBF_MENU) {
prompt("INPJ PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INKV,DBF_MENU) {
prompt("INPK PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(INLV,DBF_MENU) {
prompt("INPL PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
initial("1")
}
field(OUTV,DBF_MENU) {
prompt("OUT PV Status")
special(SPC_NOMOD)
interest(1)
menu(calcoutINAV)
}
field(OOPT,DBF_MENU) {
prompt("Output Execute Opt")
promptgroup("50 - Output")
interest(1)
menu(calcoutOOPT)
}
field(ODLY,DBF_DOUBLE) {
prompt("Output Execute Delay")
promptgroup("50 - Output")
asl(ASL0)
interest(1)
}
field(DLYA,DBF_USHORT) {
prompt("Output Delay Active")
special(SPC_NOMOD)
asl(ASL0)
}
field(DOPT,DBF_MENU) {
prompt("Output Data Opt")
promptgroup("30 - Action")
interest(1)
menu(calcoutDOPT)
}
field(OCAL,DBF_STRING) {
prompt("Output Calculation")
promptgroup("30 - Action")
special(SPC_CALC)
pp(TRUE)
size(80)
initial("0")
}
field(OCLV,DBF_LONG) {
prompt("OCAL Valid")
interest(1)
}
field(OEVT,DBF_STRING) {
prompt("Event To Issue")
promptgroup("30 - Action")
special(SPC_MOD)
asl(ASL0)
size(40)
}
%#include "dbScan.h"
field(EPVT, DBF_NOACCESS) {
prompt("Event private")
special(SPC_NOMOD)
interest(4)
extra("EVENTPVT epvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID output action")
promptgroup("50 - Output")
interest(2)
menu(menuIvoa)
}
field(IVOV,DBF_DOUBLE) {
prompt("INVALID output value")
promptgroup("50 - Output")
interest(2)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Rng")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HIHI,DBF_DOUBLE) {
prompt("Hihi Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOLO,DBF_DOUBLE) {
prompt("Lolo Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HIGH,DBF_DOUBLE) {
prompt("High Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOW,DBF_DOUBLE) {
prompt("Low Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup("70 - Alarm")
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup("80 - Display")
interest(1)
}
field(A,DBF_DOUBLE) {
prompt("Value of Input A")
pp(TRUE)
}
field(B,DBF_DOUBLE) {
prompt("Value of Input B")
pp(TRUE)
}
field(C,DBF_DOUBLE) {
prompt("Value of Input C")
pp(TRUE)
}
field(D,DBF_DOUBLE) {
prompt("Value of Input D")
pp(TRUE)
}
field(E,DBF_DOUBLE) {
prompt("Value of Input E")
pp(TRUE)
}
field(F,DBF_DOUBLE) {
prompt("Value of Input F")
pp(TRUE)
}
field(G,DBF_DOUBLE) {
prompt("Value of Input G")
pp(TRUE)
}
field(H,DBF_DOUBLE) {
prompt("Value of Input H")
pp(TRUE)
}
field(I,DBF_DOUBLE) {
prompt("Value of Input I")
pp(TRUE)
}
field(J,DBF_DOUBLE) {
prompt("Value of Input J")
pp(TRUE)
}
field(K,DBF_DOUBLE) {
prompt("Value of Input K")
pp(TRUE)
}
field(L,DBF_DOUBLE) {
prompt("Value of Input L")
pp(TRUE)
}
field(OVAL,DBF_DOUBLE) {
prompt("Output Value")
asl(ASL0)
}
field(LA,DBF_DOUBLE) {
prompt("Prev Value of A")
special(SPC_NOMOD)
interest(3)
}
field(LB,DBF_DOUBLE) {
prompt("Prev Value of B")
special(SPC_NOMOD)
interest(3)
}
field(LC,DBF_DOUBLE) {
prompt("Prev Value of C")
special(SPC_NOMOD)
interest(3)
}
field(LD,DBF_DOUBLE) {
prompt("Prev Value of D")
special(SPC_NOMOD)
interest(3)
}
field(LE,DBF_DOUBLE) {
prompt("Prev Value of E")
special(SPC_NOMOD)
interest(3)
}
field(LF,DBF_DOUBLE) {
prompt("Prev Value of F")
special(SPC_NOMOD)
interest(3)
}
field(LG,DBF_DOUBLE) {
prompt("Prev Value of G")
special(SPC_NOMOD)
interest(3)
}
field(LH,DBF_DOUBLE) {
prompt("Prev Value of H")
special(SPC_NOMOD)
interest(3)
}
field(LI,DBF_DOUBLE) {
prompt("Prev Value of I")
special(SPC_NOMOD)
interest(3)
}
field(LJ,DBF_DOUBLE) {
prompt("Prev Value of J")
special(SPC_NOMOD)
interest(3)
}
field(LK,DBF_DOUBLE) {
prompt("Prev Value of K")
special(SPC_NOMOD)
interest(3)
}
field(LL,DBF_DOUBLE) {
prompt("Prev Value of L")
special(SPC_NOMOD)
interest(3)
}
field(POVL,DBF_DOUBLE) {
prompt("Prev Value of OVAL")
asl(ASL0)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
%#include "postfix.h"
field(RPCL,DBF_NOACCESS) {
prompt("Reverse Polish Calc")
special(SPC_NOMOD)
interest(4)
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
}
field(ORPC,DBF_NOACCESS) {
prompt("Reverse Polish OCalc")
special(SPC_NOMOD)
interest(4)
extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
}
}
variable(calcoutODLYprecision, int)
variable(calcoutODLYlimit, double)

File diff suppressed because it is too large Load Diff

View File

@@ -1,204 +0,0 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(dfanoutSELM) {
choice(dfanoutSELM_All,"All")
choice(dfanoutSELM_Specified,"Specified")
choice(dfanoutSELM_Mask,"Mask")
}
recordtype(dfanout) {
include "dbCommon.dbd"
field(VAL,DBF_DOUBLE) {
prompt("Desired Output")
promptgroup("40 - Input")
asl(ASL0)
pp(TRUE)
}
field(SELM,DBF_MENU) {
prompt("Select Mechanism")
promptgroup("30 - Action")
interest(1)
menu(dfanoutSELM)
}
field(SELN,DBF_USHORT) {
prompt("Link Selection")
interest(1)
initial("1")
}
field(SELL,DBF_INLINK) {
prompt("Link Selection Loc")
promptgroup("30 - Action")
interest(1)
}
field(OUTA,DBF_OUTLINK) {
prompt("Output Spec A")
promptgroup("50 - Output")
interest(1)
}
field(OUTB,DBF_OUTLINK) {
prompt("Output Spec B")
promptgroup("50 - Output")
interest(1)
}
field(OUTC,DBF_OUTLINK) {
prompt("Output Spec C")
promptgroup("50 - Output")
interest(1)
}
field(OUTD,DBF_OUTLINK) {
prompt("Output Spec D")
promptgroup("50 - Output")
interest(1)
}
field(OUTE,DBF_OUTLINK) {
prompt("Output Spec E")
promptgroup("50 - Output")
interest(1)
}
field(OUTF,DBF_OUTLINK) {
prompt("Output Spec F")
promptgroup("50 - Output")
interest(1)
}
field(OUTG,DBF_OUTLINK) {
prompt("Output Spec G")
promptgroup("50 - Output")
interest(1)
}
field(OUTH,DBF_OUTLINK) {
prompt("Output Spec H")
promptgroup("50 - Output")
interest(1)
}
field(DOL,DBF_INLINK) {
prompt("Desired Output Loc")
promptgroup("40 - Input")
interest(1)
}
field(OMSL,DBF_MENU) {
prompt("Output Mode Select")
promptgroup("50 - Output")
interest(1)
menu(menuOmsl)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HIHI,DBF_DOUBLE) {
prompt("Hihi Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOLO,DBF_DOUBLE) {
prompt("Lolo Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HIGH,DBF_DOUBLE) {
prompt("High Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOW,DBF_DOUBLE) {
prompt("Low Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup("70 - Alarm")
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup("80 - Display")
interest(1)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
}

View File

@@ -0,0 +1,454 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Data Fanout Record (dfanout)
The Data Fanout or "dfanout" record is used to forward data to up to
eight other records. It's similar to the fanout record except that the
capability to forward data has been added to it. If has no associated
device support.
=head2 Parameter Fields
The fields in this record can be classified into the following categories:
=over
=item *
scan parameters
=item *
desired output parameters
=item *
write parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
monitor parameters
=item *
run-time and simulation mode parameters
=back
=recordtype dfanout
=cut
menu(dfanoutSELM) {
choice(dfanoutSELM_All,"All")
choice(dfanoutSELM_Specified,"Specified")
choice(dfanoutSELM_Mask,"Mask")
}
recordtype(dfanout) {
=head3 Scan Parameters
The data fanout record has the standard fields for specifying under what
circumstances it will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Since the data fanout record supports no direct interfaces
to hardware, it cannot be scanned on I/O interrupt, so its SCAN field
cannot be C<I/O Intr>.
=head3 Desired Output Parameters
The data fanout record must specify where the desired output value
originates, i.e., the data which is to be fowarded to the records in its
output links. The output mode select (OMSL) field determines whether the
output originates from another record or from run-time database access.
When set to C<closed_loop>, the desired output is retrieved from the link
specified in the desired output (DOL) field, which can specify either a
database or a channel access link, and placed into the VAL field. When set
to C<supervisory>, the desired output can be written to the VAL field via
dbPuts at run-time.
The DOL field can also be a constant in which case the VAL field is
initialized to the constant value.
Note that there are no conversion parameters, so the desired output value
undergoes no conversions before it is sent out to the output links.
=fields DOL, OMSL, VAL
=head3 Write Parameters
The OUTA-OUTH fields specify where VAL is to be sent. Each field that is to
forward data must specify an address to another record. See
L<Address Specification> for information on specifying links.
The SELL, SELM, and SELN fields specify which output links are to be
used.
=head4 Menu dfanoutSELM
SELM is a menu, with three choices:
=menu dfanoutSELM
If SELM=="All", then all output links are used, and the values of
SELL and SELN are ignored.
If SELM=="Specified", then the value of SELN is used to specify a single
link which will be used. If SELN==0, then no link will be used; if SELN==1,
then OUTA will be used, and so on.
SELN can either have its value set directly, or have its values retrieved
from another EPICS PV. If SELL is a valid PV link, then SELN will be set to
the values of the linked PV.
If SELM=="Mask", then SELN will be treated as a bit mask. If bit one of
SELN is set, then OUTA will be used, if bit two is set, OUTB will be used.
Thus if SELN==5, OUTC and OUTA will be used.
=fields OUTA, OUTB, OUTC, OUTD, OUTE, OUTF, OUTG, OUTH
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. They
display the value and other parameters of the data fanout record either
textually or graphically.
The EGU field can contain a string of up to 16 characters describing the
value on the VAL field.
The HOPR and LOPR fields determine the upper and lower display limits for
graphic displays and the upper and lower control limits for control
displays. They apply to the VAL, HIHI, HIGH, LOW, and LOLO fields. The
record support routines C<get_graphic_double> or C<get_control_double>
retrieve HOPR and LOPR.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
=fields EGU, HOPR, LOPR, NAME, DESC
=head3 Alarm Parameters
The possible alarm conditions for data fanouts are the SCAN, READ, INVALID,
and limit alarms. The SCAN and READ alarms are called by the record
routines. The limit alarms are configured by the user in the HIHI, LOLO,
HIGH, and LOW fields using floating point values. The limit alarms apply
only to the VAL field. The severity for each of these limits is specified
in the corresponding field (HHSV, LLSV, HSV, LSV) and can be either
NO_ALARM, MINOR, or MAJOR. In the hysteresis field (HYST) can be entered a
number which serves as the deadband on the limit alarms.
See L<Alarm Specification> for a complete explanation of alarms and these
fields. L<Alarm Fields> lists other fields related to alarms that are
common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
=head3 Monitor Parameters
These parameters are used to determine when to send monitors placed on the
VAL field. These monitors are sent when the value field exceeds the last
monitored fields by the specified deadband, ADEL for archivers monitors and
MDEL for all other types of monitors. If these fields have a value of zero,
everytime the value changes, a monitor will be triggered; if they have a
value of -1, everytime the record is scanned, monitors are triggered. See
L<Monitor Specification> for a complete explanation of monitors.
=fields ADEL, MDEL
=head3 Run-Time Parameters and Simulation Mode Parameters
These parameters are used by the run-time code for processing the data
fanout record. Ther are not configurable. They are used to implement the
hysteresis factors for monitor callbacks.
=fields LALM, ALST, MLST
=cut
include "dbCommon.dbd"
field(VAL,DBF_DOUBLE) {
prompt("Desired Output")
promptgroup("40 - Input")
asl(ASL0)
pp(TRUE)
}
field(SELM,DBF_MENU) {
prompt("Select Mechanism")
promptgroup("30 - Action")
interest(1)
menu(dfanoutSELM)
}
field(SELN,DBF_USHORT) {
prompt("Link Selection")
interest(1)
initial("1")
}
field(SELL,DBF_INLINK) {
prompt("Link Selection Loc")
promptgroup("30 - Action")
interest(1)
}
field(OUTA,DBF_OUTLINK) {
prompt("Output Spec A")
promptgroup("50 - Output")
interest(1)
}
field(OUTB,DBF_OUTLINK) {
prompt("Output Spec B")
promptgroup("50 - Output")
interest(1)
}
field(OUTC,DBF_OUTLINK) {
prompt("Output Spec C")
promptgroup("50 - Output")
interest(1)
}
field(OUTD,DBF_OUTLINK) {
prompt("Output Spec D")
promptgroup("50 - Output")
interest(1)
}
field(OUTE,DBF_OUTLINK) {
prompt("Output Spec E")
promptgroup("50 - Output")
interest(1)
}
field(OUTF,DBF_OUTLINK) {
prompt("Output Spec F")
promptgroup("50 - Output")
interest(1)
}
field(OUTG,DBF_OUTLINK) {
prompt("Output Spec G")
promptgroup("50 - Output")
interest(1)
}
field(OUTH,DBF_OUTLINK) {
prompt("Output Spec H")
promptgroup("50 - Output")
interest(1)
}
field(DOL,DBF_INLINK) {
prompt("Desired Output Loc")
promptgroup("40 - Input")
interest(1)
}
field(OMSL,DBF_MENU) {
prompt("Output Mode Select")
promptgroup("50 - Output")
interest(1)
menu(menuOmsl)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(HIHI,DBF_DOUBLE) {
prompt("Hihi Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOLO,DBF_DOUBLE) {
prompt("Lolo Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HIGH,DBF_DOUBLE) {
prompt("High Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(LOW,DBF_DOUBLE) {
prompt("Low Alarm Limit")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup("70 - Alarm")
pp(TRUE)
interest(1)
prop(YES)
menu(menuAlarmSevr)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup("70 - Alarm")
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup("80 - Display")
interest(1)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
=head2 Record Support
=head3 Record Support Routines
=head2 C<init_record()>
This routine initializes all output links that are defined. Then it initializes
DOL if DOL is a constant or a PV_LINK. When initializing the output links
and the DOL link, a non-zero value is returned if an error occurs.
=head2 C<process()>
See next section.
=head2 C<get_value()>
This routine fills in the members of C<struct valueDes> with the VAL fields
value and characteristics.
=head2 C<get_units()>
The routine copies the string specified in the EGU field to the location
specified by a pointer which is passed to the routine.
=head2 C<get_graphic_double()>
If the referenced field is VAL, HIHI, HIGH, LOW, or LOLO, this routine sets
the C<upper_disp_limit> member of the C<dbr_grDouble> structure to the
HOPR and the C<lower_disp_limit> member to the LOPR. If the referenced
field is not one of the above fields, then C<recGblGetControlDouble()>
routine is called.
=head2 C<get_control_double()>
Same as the C<get_graphic_double> routine except that it uses the
C<dbr_ctrlDouble> structure.
=head2 C<get_alarm_double()>
This sets the members of the C<dbr_alDouble> structure to the specified
alarm limits if the referenced field is VAL:
=over
upper_alarm_limit = HIHI
upper_warning_limit = HIGH
lower_warning_limit = LOW
lower_alarm_limit = LOLO
=back
If the referenced field is not VAL, the C<recGblGetAlarmDouble()> routine
is called.
=head3 Record Processing
=over
=item 1.
The C<process()> routine first retrieves a value for DOL and places it in
VAL if OMSL is set to colsed loop mode. If an error occurs, then UDF is set
to FALSE.
=item 2.
PACT is set TRUE
=item 3.
VAL is then sent to all the records specified in the OUTA-OUTH fields by
calling C<recGblePutLinkValue()> for each link.
=item 4.
Alarms are checked and monitors are called if conditions apply.
=item 5.
The data fanout's own forward link is then processed.
=item 6.
PACT is set FALSE, and the C<process()> routine returns. A -1 is returned
if there was an error writing values to one of the output links.
=back
=cut
}

View File

@@ -62,59 +62,23 @@
#include "epicsThread.h"
#include "epicsExit.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "dbStaticLib.h"
#include "subRecord.h"
#include "dbAccess.h"
#include "asDbLib.h"
#include "iocInit.h"
#include "iocsh.h"
#include "osiFileName.h"
#include "epicsInstallDir.h"
extern "C" int softIoc_registerRecordDeviceDriver(struct dbBase *pdbbase);
#define DBD_BASE "dbd/softIoc.dbd"
#define EXIT_BASE "db/softIocExit.db"
#define DBD_FILE_REL "../../" DBD_BASE
#define EXIT_FILE_REL "../../" EXIT_BASE
#define DBD_FILE EPICS_BASE "/" DBD_BASE
#define EXIT_FILE EPICS_BASE "/" EXIT_BASE
#define DBD_FILE EPICS_BASE "/dbd/softIoc.dbd"
#define EXIT_FILE EPICS_BASE "/db/softIocExit.db"
const char *arg0;
const char *base_dbd = DBD_FILE;
const char *exit_db = EXIT_FILE;
static void preparePath(void)
{
FILE *fp;
char *prefix = epicsGetExecDir();
char *dbd, *exit;
if(!prefix) return;
dbd = (char*)malloc(strlen(prefix) + strlen(DBD_FILE_REL) + 1);
if(dbd) {
dbd[0] = '\0';
strcat(dbd, prefix);
strcat(dbd, DBD_FILE_REL);
printf("Testing '%s'\n", dbd);
if((fp = fopen(dbd, "rb"))!=NULL) {
fclose(fp);
base_dbd = dbd;
}
}
exit = (char*)malloc(strlen(prefix) + strlen(EXIT_FILE_REL) + 1);
if(exit) {
exit[0] = '\0';
strcat(exit, prefix);
strcat(exit, EXIT_FILE_REL);
if((fp = fopen(exit, "rb"))!=NULL) {
fclose(fp);
exit_db = exit;
}
}
}
static void exitSubroutine(subRecord *precord) {
epicsExitLater((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
@@ -132,7 +96,6 @@ static void usage(int status) {
int main(int argc, char *argv[])
{
preparePath();
char *dbd_file = const_cast<char*>(base_dbd);
char *macros = NULL;
char xmacro[PVNAME_STRINGSZ + 4];

View File

@@ -97,7 +97,7 @@ sub ParseDBD {
my $rtyp = $dbd->recordtype($record_type);
if (!defined $rtyp) {
$rtyp = DBD::Recordtype->new($record_type);
warn "Device using undefined record type '$record_type', place-holder created\n";
warn "Device using unknown record type '$record_type', declaration created\n";
$dbd->add($rtyp);
}
$rtyp->add_device(DBD::Device->new($link_type, $dset, $choice));
@@ -218,7 +218,12 @@ sub parse_breaktable {
sub parse_recordtype {
my ($dbd, $record_type) = @_;
pushContext("recordtype($record_type)");
my $rtyp = DBD::Recordtype->new($record_type);
# Re-use a matching declaration record type if one exists
my $rtyp = $dbd->recordtype($record_type);
if (!defined($rtyp) || $rtyp->fields) {
# Earlier record type is not a declaration, don't re-use it
$rtyp = DBD::Recordtype->new($record_type);
}
while(1) {
parseCommon($rtyp);
if (m/\G field \s* \( \s* $RXstr \s* , \s* $RXstr \s* \) \s* \{/xgc) {

View File

@@ -130,7 +130,18 @@ sub attribute {
}
sub equals {
dieContext("Record field objects are not comparable");
my ($l, $r) = @_;
return 1 if $l eq $r;
return 0 if
$l->{NAME} ne $r->{NAME} ||
$l->{DBF_TYPE} ne $r->{DBF_TYPE};
my ($la, $ra) = ($l->{ATTR_INDEX}, $r->{ATTR_INDEX});
my @keys = sort keys %$la;
return 0 if join(',', @keys) ne join(',', sort keys %$ra);
foreach my $k (@keys) {
return 0 if $la->{$k} ne $ra->{$k};
}
return 1;
}
sub check_valid {

View File

@@ -104,9 +104,19 @@ sub pod {
sub equals {
my ($new, $known) = @_;
return 0 if ! $known->fields;
return 1 if ! $new->fields;
dieContext("Duplicate definition of record type '$known->{NAME}'");
return 1 if $new eq $known;
return 0 if $new->{NAME} ne $known->{NAME};
return 1 if ! $new->fields; # Later declarations always match
# NB: Definition after declaration is handled in parse_recordtype()
my @nf = @{$new->{FIELD_LIST}};
my @kf = @{$known->{FIELD_LIST}};
return 0 if scalar @nf != scalar @kf;
while (@nf) {
my $nf = shift @nf;
my $kf = shift @kf;
return 0 if ! $nf->equals($kf);
}
return 1;
}
sub toDeclaration {

View File

@@ -40,4 +40,27 @@ PERL_SCRIPTS += registerRecordDeviceDriver.pl
HTMLS += dbdToHtml.html
# Build Package Config Files
FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION))
C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CPPFLAGS))))
C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CFLAGS))))
PKGVARS += FINAL_LOCATION OS_CLASS CMPLR_CLASS C_CFLAGS LDFLAGS LDLIBS
PKGVARS += EPICS_VERSION EPICS_REVISION EPICS_MODIFICATION EPICS_PATCH_LEVEL
PKGVARS += CC CCC CPP AR LD
PKGVARS += EPICS_BASE_HOST_LIBS EPICS_BASE_IOC_LIBS
EXPANDFLAGS += $(foreach var,$(PKGVARS),-D$(var)="$(strip $($(var)))")
PKGCONFIG += epics-base-$(T_A).pc
ifeq ($(T_A),$(EPICS_HOST_ARCH))
PKGCONFIG += epics-base.pc
endif
EXPAND += $(PKGCONFIG:%=%@)
CLEANS += epics-base-$(T_A).pc@
include $(TOP)/configure/RULES
epics-base-$(T_A).pc@: ../epics-base-arch.pc@
@$(RM) $@
@$(CP) $< $@

View File

@@ -127,6 +127,33 @@ if ($opt_D) { # Output dependencies only
open my $out, '>', $opt_o or
die "Can't create $opt_o: $!\n";
my $podHtml;
my $idify;
if ($::XHTML) {
$podHtml = Pod::Simple::XHTML->new();
$podHtml->html_doctype(<< '__END_DOCTYPE');
<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
__END_DOCTYPE
$podHtml->html_header_tags($podHtml->html_header_tags .
"\n<link rel='stylesheet' href='style.css' type='text/css'>");
$idify = sub {
my $title = shift;
return $podHtml->idify($title, 1);
}
} else { # Fall back to HTML
$podHtml = Pod::Simple::HTML->new();
$podHtml->html_css('style.css');
$idify = sub {
my $title = shift;
return Pod::Simple::HTML::esc($podHtml->section_escape($title));
}
}
# Parse the Pod text from the root DBD object
my $pod = join "\n", '=for html <div class="pod">', '',
map {
@@ -156,22 +183,6 @@ my $pod = join "\n", '=for html <div class="pod">', '',
} $dbd->pod,
'=for html </div>', '';
my $podHtml;
if ($::XHTML) {
$podHtml = Pod::Simple::XHTML->new();
$podHtml->html_doctype(<< '__END_DOCTYPE');
<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
__END_DOCTYPE
$podHtml->html_header_tags($podHtml->html_header_tags .
"\n<link rel='stylesheet' href='style.css' type='text/css'>");
} else { # Fall back to HTML
$podHtml = Pod::Simple::HTML->new();
$podHtml->html_css('style.css');
}
$podHtml->force_title(encode_entities($title));
$podHtml->perldoc_url_prefix('');
$podHtml->perldoc_url_postfix('.html');
@@ -249,7 +260,7 @@ sub fieldTableRow {
if ($type eq 'MENU') {
my $mn = $fld->attribute('menu');
my $menu = $dbd->menu($mn);
my $url = $menu ? "#Menu_$mn" : "${mn}.html";
my $url = $menu ? '#' . &$idify("Menu $mn") : "${mn}.html";
$html .= " (<a href='$url'>$mn</a>)";
}
$html .= '</td><td class="cell">';
@@ -377,6 +388,8 @@ can be found in the aai and aSub record types.
If you look at the L<aoRecord.dbd.pod> file you'll see that the POD there starts
by documenting a record-specific menu definition. The "menu" keyword generates a
table that lists all the choices found in the named menu.
table that lists all the choices found in the named menu. Any MENU fields in the
field tables that refer to a locally-defined menu will generate a link to a
document section which must be titled "Menu [menuName]".
=cut

View File

@@ -12,6 +12,7 @@ ARCH=@ARCH@
OS_CLASS=@OS_CLASS@
CMPLR_CLASS=@CMPLR_CLASS@
EPICS_BASE_HOST_LIBS=@EPICS_BASE_HOST_LIBS@
EPICS_BASE_IOC_LIBS=@EPICS_BASE_IOC_LIBS@
# Directories

View File

@@ -14,6 +14,7 @@ DIRS += ioc/db
DIRS += ioc/dbtemplate
DIRS += std/rec
DIRS += std/link
DIRS += std/filters
DIRS += tools

View File

@@ -114,6 +114,7 @@ TESTPROD_HOST += regressTest
regressTest_SRCS += regressTest.c
regressTest_SRCS += regressTest_registerRecordDeviceDriver.cpp
TESTFILES += $(COMMON_DIR)/regressTest.dbd ../regressArray1.db ../regressHex.db ../regressLinkMS.db
TESTFILES += ../badCaLink.db
TESTS += regressTest
TARGETS += $(COMMON_DIR)/simmTest.dbd

View File

@@ -0,0 +1,4 @@
record(ai, "ai:disconn") {
field(INP , "invalid CA")
field(UDF , "0")
}

View File

@@ -18,7 +18,8 @@ $ENV{EPICS_CAS_INTF_ADDR_LIST} = 'localhost';
$ENV{EPICS_PVA_AUTO_ADDR_LIST} = 'NO';
$ENV{EPICS_PVA_ADDR_LIST} = 'localhost';
$ENV{EPICS_PVA_SERVER_PORT} = 55076;
$ENV{EPICS_PVAS_SERVER_PORT} = 55075;
$ENV{EPICS_PVA_BROADCAST_PORT} = 55076;
$ENV{EPICS_PVAS_INTF_ADDR_LIST} = 'localhost';
my $bin = "@TOP@/bin/@ARCH@";
@@ -28,12 +29,14 @@ my $prefix = "test-$$";
my $ioc = EPICS::IOC->new();
#$ioc->debug(1);
$SIG{__DIE__} = $SIG{'INT'} = $SIG{'QUIT'} = sub {
$SIG{__DIE__} = $SIG{INT} = $SIG{QUIT} = $SIG{ALRM} = sub {
$ioc->kill
if ref($ioc) eq 'EPICS::IOC' && $ioc->started;
BAIL_OUT('Caught signal');
};
alarm 30;
my $softIoc = "$bin/softIocPVA$exe";
$softIoc = "$bin/softIoc$exe"
unless -x $softIoc;
@@ -59,7 +62,7 @@ note("CA server configuration:\n",
my $caget = "$bin/caget$exe";
SKIP: {
skip "caget not available", 1 unless -x $caget;
my $caVersion = `$caget $pv`;
my $caVersion = `$caget -w5 $pv`;
like($caVersion, qr/$pv \s+ \Q$version\E/x,
'Got same BaseVersion from caget');
}
@@ -73,7 +76,7 @@ SKIP: {
skip "pvget not available", 1
unless -x $pvget;
my $pvaVersion = `$pvget $pv`;
my $pvaVersion = `$pvget -w5 $pv`;
like($pvaVersion, qr/$pv \s .* \Q$version\E/x,
'Got same BaseVersion from pvget');
}

View File

@@ -8,6 +8,7 @@
#include <testMain.h>
#include <dbAccess.h>
#include <errlog.h>
#include <alarm.h>
#include <calcoutRecord.h>
#include <waveformRecord.h>
@@ -123,12 +124,26 @@ void testLinkMS(void)
testdbCleanup();
}
/* lp:1798855 disconnected CA link must alarm */
static
void testCADisconn(void)
{
testDiag("In testCADisconn()");
startRegressTestIoc("badCaLink.db");
testdbPutFieldOk("ai:disconn.PROC", DBF_LONG, 1);
testdbGetFieldEqual("ai:disconn.SEVR", DBF_LONG, INVALID_ALARM);
testdbGetFieldEqual("ai:disconn.STAT", DBF_LONG, LINK_ALARM);
}
MAIN(regressTest)
{
testPlan(31);
testPlan(34);
testArrayLength1();
testHexConstantLinks();
testLinkMS();
testCADisconn();
return testDone();
}

View File

@@ -2,7 +2,7 @@
use lib '@TOP@/lib/perl';
use Test::More tests => 17;
use Test::More tests => 23;
use DBD::Recordtype;
use DBD::Recfield;
@@ -13,6 +13,11 @@ isa_ok $rtyp, 'DBD::Recordtype';
is $rtyp->name, 'test', 'Record name';
is $rtyp->fields, 0, 'No fields yet';
is $rtyp->equals($rtyp), 1, 'A declaration == itself';
my $rt2 = DBD::Recordtype->new('test');
is $rtyp->equals($rt2), 1, 'A declaration == a different declaration';
my $fld1 = DBD::Recfield->new('NAME', 'DBF_STRING');
$fld1->add_attribute("size", "41");
$fld1->check_valid;
@@ -26,6 +31,18 @@ is $rtyp->fields, 1, 'First field added';
$rtyp->add_field($fld2);
is $rtyp->fields, 2, 'Second field added';
is $rtyp->equals($rtyp), 1, 'A definition == itself';
is $rt2->equals($rtyp), 1, 'A declaration == a definition';
$rt2->add_field($fld1);
my $fld3 = DBD::Recfield->new('DTYP', 'DBF_DEVICE');
$fld3->check_valid;
$rt2->add_field($fld3);
is $rt2->equals($rtyp), 1, 'Identical definitions are equal';
$fld3->add_attribute("pp", "TRUE");
is $rt2->equals($rtyp), 0, 'Different definitions are not equal';
my @fields = $rtyp->fields;
is_deeply \@fields, [$fld1, $fld2], 'Field list';

View File

@@ -1,4 +1,4 @@
EPICS_LIBCOM_MAJOR_VERSION = 3
EPICS_LIBCOM_MINOR_VERSION = 17
EPICS_LIBCOM_MAINTENANCE_VERSION = 1
EPICS_LIBCOM_DEVELOPMENT_FLAG = 1
EPICS_LIBCOM_MAINTENANCE_VERSION = 2
EPICS_LIBCOM_DEVELOPMENT_FLAG = 0

View File

@@ -66,7 +66,7 @@ EXPANDVARS += EPICS_LIBCOM_DEVELOPMENT_FLAG
EXPANDFLAGS += $(foreach var,$(EXPANDVARS),-D$(var)="$(strip $($(var)))")
# shared library ABI version.
SHRLIB_VERSION = 3.17.0
SHRLIB_VERSION = $(EPICS_LIBCOM_MAJOR_VERSION).$(EPICS_LIBCOM_MINOR_VERSION).$(EPICS_LIBCOM_MAINTENANCE_VERSION)
include $(TOP)/configure/RULES

View File

@@ -98,7 +98,6 @@ int num_backtracking, bol_needed;
FILE *temp_action_file;
FILE *backtrack_file;
int end_of_buffer_state;
char action_file_name[256>L_tmpnam?256:L_tmpnam];
char **input_files;
int num_input_files;
char *program_name;
@@ -210,10 +209,7 @@ void flexend(int status)
else if ( fclose( temp_action_file ) )
flexfatal( "error occurred when closing temporary action file" );
else if ( unlink( action_file_name ) )
flexfatal( "error occurred when deleting temporary action file" );
}
}
if ( status != 0 && outfile_created )
{
@@ -598,15 +594,11 @@ get_next_arg: /* used by -C and -S flags in lieu of a "continue 2" control */
if ( (skelfile = fopen( skelname, "r" )) == NULL )
lerrsf( "can't open skeleton file %s", skelname );
epicsTempName ( action_file_name, sizeof ( action_file_name ) );
if ( action_file_name[0] == '\0' )
if ( ( temp_action_file = epicsTempFile () ) == NULL )
{
lerrsf( "can't create temporary file name", "" );
lerrsf( "can't create temporary action file", "" );
}
if ( ( temp_action_file = fopen ( action_file_name, "w" ) ) == NULL )
lerrsf( "can't open temporary action file %s", action_file_name );
lastdfa = lastnfa = num_rules = numas = numsnpairs = tmpuses = 0;
numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;

View File

@@ -350,7 +350,6 @@ extern int yymore_really_used, reject_really_used;
* temp_action_file - temporary file to hold actions
* backtrack_file - file to summarize backtracking states to
* infilename - name of input file
* action_file_name - name of the temporary file
* input_files - array holding names of input files
* num_input_files - size of input_files array
* program_name - name with which program was invoked
@@ -359,7 +358,6 @@ extern int yymore_really_used, reject_really_used;
extern int datapos, dataline, linenum;
extern FILE *skelfile, *yyin, *temp_action_file, *backtrack_file;
extern char *infilename;
extern char action_file_name[];
extern char **input_files;
extern int num_input_files;
extern char *program_name;

View File

@@ -1164,13 +1164,8 @@ void make_tables(void)
if ( ferror( temp_action_file ) )
flexfatal( "error occurred when writing temporary action file" );
else if ( fclose( temp_action_file ) )
flexfatal( "error occurred when closing temporary action file" );
temp_action_file = fopen( action_file_name, "r" );
if ( temp_action_file == NULL )
flexfatal( "could not re-open temporary action file" );
else if ( fseek( temp_action_file, 0L, SEEK_SET) != 0 )
flexfatal( "error occurred when rewinding temporary action file" );
/* copy prolog from action_file to output file */
action_out();

View File

@@ -601,12 +601,12 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
macPushScope(handle);
macInstallMacros(handle, defines);
wasOkToBlock = epicsThreadIsOkToBlock();
epicsThreadSetOkToBlock(1);
/*
* Read commands till EOF or exit
*/
argc = 0;
wasOkToBlock = epicsThreadIsOkToBlock();
epicsThreadSetOkToBlock(1);
for (;;) {
/*
* Read a line
@@ -681,15 +681,15 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
redirect = NULL;
for (;;) {
if (argc >= argvCapacity) {
char **av;
argvCapacity += 50;
av = (char **)realloc (argv, argvCapacity * sizeof *argv);
if (av == NULL) {
int newCapacity = argvCapacity + 20;
char **newv = (char **)realloc (argv, newCapacity * sizeof *argv);
if (newv == NULL) {
fprintf (epicsGetStderr(), "Out of memory!\n");
argc = -1;
break;
}
argv = av;
argv = newv;
argvCapacity = newCapacity;
}
c = line[icin++];
if (c == '\0')
@@ -838,16 +838,14 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
break;
}
if (iarg >= argBufCapacity) {
void *np;
argBufCapacity += 20;
np = realloc (argBuf, argBufCapacity * sizeof *argBuf);
if (np == NULL) {
int newCapacity = argBufCapacity + 20;
void *newBuf = realloc(argBuf, newCapacity * sizeof *argBuf);
if (newBuf == NULL) {
fprintf (epicsGetStderr(), "Out of memory!\n");
argBufCapacity -= 20;
break;
}
argBuf = (iocshArgBuf *)np;
argBuf = (iocshArgBuf *) newBuf;
argBufCapacity = newCapacity;
}
if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) {
argBuf[iarg].aval.ac = argc-iarg;
@@ -892,7 +890,7 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
errlogFlush();
if (readlineContext)
epicsReadlineEnd(readlineContext);
epicsThreadSetOkToBlock( wasOkToBlock);
epicsThreadSetOkToBlock(wasOkToBlock);
return 0;
}

View File

@@ -236,6 +236,7 @@ static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs};
static void errlogCallFunc(const iocshArgBuf *args)
{
errlog(args[0].sval);
errlogFlush();
}
/* iocLogPrefix */

View File

@@ -27,7 +27,6 @@
*/
epicsShareFunc enum TF_RETURN truncateFile (const char *pFileName, unsigned long size)
{
char tmpName[256>L_tmpnam?256:L_tmpnam];
long filePos;
FILE *pFile;
FILE *ptmp;
@@ -67,18 +66,10 @@ epicsShareFunc enum TF_RETURN truncateFile (const char *pFileName, unsigned lon
return TF_OK;
}
epicsTempName ( tmpName, sizeof (tmpName) );
if ( tmpName[0] == '\0' ) {
fprintf (stderr,"Unable to create tmp file name?\n");
fclose (pFile);
return TF_ERROR;
}
ptmp = fopen (tmpName, "w");
ptmp = epicsTempFile();
if (!ptmp) {
fprintf (stderr,
"File access problems to `%s' because `%s'\n",
tmpName,
"File access problems to temp file because `%s'\n",
strerror(errno));
fclose (pFile);
return TF_ERROR;
@@ -89,48 +80,59 @@ epicsShareFunc enum TF_RETURN truncateFile (const char *pFileName, unsigned lon
c = getc (pFile);
if (c==EOF) {
fprintf (stderr,
"File access problems to `%s' because `%s'\n",
pFileName,
"File access problems to temp file because `%s'\n",
strerror(errno));
fclose (pFile);
fclose (ptmp);
remove (tmpName);
return TF_ERROR;
}
status = putc (c, ptmp);
if (status==EOF) {
fprintf(stderr,
"File access problems to `%s' because `%s'\n",
tmpName,
"File access problems to temp file because `%s'\n",
strerror(errno));
fclose (pFile);
fclose (ptmp);
remove (tmpName);
return TF_ERROR;
}
charNo++;
}
fclose (pFile);
fclose (ptmp);
status = remove (pFileName);
if (status!=TF_OK) {
pFile = fopen(pFileName, "w");
if (!pFile) {
fprintf (stderr,
"Unable to remove `%s' during truncate because `%s'\n",
"File access problems to `%s' because `%s'\n",
pFileName,
strerror(errno));
remove (tmpName);
fclose (ptmp);
return TF_ERROR;
}
status = rename (tmpName, pFileName);
if (status!=TF_OK) {
fprintf (stderr,
"Unable to rename %s to `%s' because `%s'\n",
tmpName,
pFileName,
strerror(errno));
remove (tmpName);
return TF_ERROR;
rewind (ptmp);
charNo = 0u;
while (charNo<size) {
c = getc (ptmp);
if (c==EOF) {
fprintf (stderr,
"File access problems to temp file because `%s'\n",
strerror(errno));
fclose (pFile);
fclose (ptmp);
return TF_ERROR;
}
status = putc (c, pFile);
if (status==EOF) {
fprintf(stderr,
"File access problems to `%s' because `%s'\n",
pFileName,
strerror(errno));
fclose (pFile);
fclose (ptmp);
return TF_ERROR;
}
charNo++;
}
fclose(ptmp);
fclose(pFile);
return TF_OK;
}

View File

@@ -14,29 +14,7 @@
#ifndef unixFileNameH
#define unixFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ":"
#define OSI_PATH_SEPARATOR "/"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* unixFileNameH */

View File

@@ -123,7 +123,6 @@ Com_SRCS += osdMonotonic.c
Com_SRCS += osdProcess.c
Com_SRCS += osdNetIntf.c
Com_SRCS += osdMessageQueue.c
Com_SRCS += osdgetexec.c
Com_SRCS += devLibVME.c
Com_SRCS += devLibVMEOSD.c

View File

@@ -225,14 +225,14 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
gtProvider *ptp;
int status = S_time_noProvider;
epicsTimeStamp ts;
STATIC_ASSERT ( epicsTimeEventBestTime == -1 );
generalTime_Init();
IFDEBUG(2)
printf("generalTimeGetEventPriority(eventNum=%d)\n", eventNumber);
if ((eventNumber < 0 || eventNumber >= NUM_TIME_EVENTS) &&
(eventNumber != epicsTimeEventBestTime))
if (eventNumber < epicsTimeEventBestTime)
return S_time_badEvent;
epicsMutexMustLock(gtPvt.eventListLock);
@@ -245,7 +245,9 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
if (pPrio)
*pPrio = ptp->priority;
if (eventNumber == epicsTimeEventBestTime) {
if (eventNumber >= NUM_TIME_EVENTS) {
*pDest = ts;
} else if (eventNumber == epicsTimeEventBestTime) {
if (epicsTimeGreaterThanEqual(&ts,
&gtPvt.lastProvidedBestTime)) {
*pDest = ts;

View File

@@ -17,7 +17,11 @@ extern "C" {
#endif
#define NUM_TIME_EVENTS 256
/* Time Events are numbered 0 through (NUM_TIME_EVENTS-1) */
/* Time Events numbered 0 through (NUM_TIME_EVENTS-1) are validated by */
/* code in epicsGeneralTime.c that tests for advancing timestamps and */
/* enforces that restriction. Event numbers greater than or equal to */
/* NUM_TIME_EVENTS are now allowed if supported by a custom time provider */
/* which should provide its own advancing timestamp validation. */
epicsShareFunc void generalTime_Init(void);

View File

@@ -20,7 +20,6 @@
extern "C" {
#endif
epicsShareFunc void epicsShareAPI epicsTempName(char *pbuf, size_t bufLen);
epicsShareFunc FILE * epicsShareAPI epicsTempFile(void);
#ifdef __cplusplus

View File

@@ -1,50 +0,0 @@
#include <string.h>
#include <stdlib.h>
#include <mach-o/dyld.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
uint32_t max = 64u;
char *ret = NULL;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
/* cf. "man 3 dyld" */
if(_NSGetExecutablePath(ret, &max)==0) {
/* max left unchanged */
ret[max-1] = '\0';
break;
}
/* max has been updated with required size */
}
/* TODO: _NSGetExecutablePath() doesn't follow symlinks */
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -1,54 +0,0 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = PATH_MAX;
char *ret = NULL;
ssize_t n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = readlink("/proc/self/exe", ret, max);
if(n == -1) {
free(ret);
ret = NULL;
break;
} else if(n < max) {
/* readlink() never adds a nil */
ret[n] = '\0';
break;
}
max += 64;
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -21,28 +21,6 @@
#define epicsExportSharedSymbols
#include "epicsTempFile.h"
//
// epicsTempName
//
// allow the teporary file directory to be set with the
// TMP environment varianble
//
extern "C"
epicsShareFunc void epicsShareAPI epicsTempName (
char * pNameBuf, size_t nameBufLength )
{
if ( nameBufLength ) {
pNameBuf[0] = '\0';
char * pName = _tempnam ( "c:\\tmp", "epics" );
if ( pName ) {
if ( nameBufLength > strlen ( pName ) ) {
strncpy ( pNameBuf, pName, nameBufLength );
}
free ( pName );
}
}
}
//
// epicsTmpFile
//

View File

@@ -1,52 +0,0 @@
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = 128;
char *ret = NULL;
DWORD n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = GetModuleFileName(NULL, ret, max);
if(n == 0) {
free(ret);
ret = NULL;
break;
} else if(n < max) {
ret[n] = '\0';
break;
}
max += 64;
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '\\');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -15,29 +15,7 @@
#ifndef osiFileNameH
#define osiFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ";"
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* osiFileNameH */

View File

@@ -14,29 +14,7 @@
#ifndef osiFileNameH
#define osiFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ";"
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* osiFileNameH */

View File

@@ -1,14 +0,0 @@
#include <stdlib.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
return NULL;
}
char *epicsGetExecDir(void)
{
return NULL;
}

View File

@@ -1,68 +0,0 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = PATH_MAX;
char *ret = NULL;
ssize_t n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = readlink("/proc/curproc/file", ret, max);
if(n == -1) {
free(ret);
ret = NULL;
break;
} else if(n < max) {
/* readlink() never adds a nil */
ret[n] = '\0';
break;
}
max += 64;
}
if(!ret) {
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
ret = malloc(max);
if(ret) {
sysctl(mib, 4, ret, &cb, NULL, 0);
/* TODO: error check */
}
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -13,22 +13,6 @@
#define epicsExportSharedSymbols
#include "epicsTempFile.h"
extern "C"
epicsShareFunc void epicsShareAPI epicsTempName (
char * pNameBuf, size_t nameBufLength )
{
if ( nameBufLength ) {
pNameBuf[0] = '\0';
char nameBuf[L_tmpnam];
if ( tmpnam ( nameBuf ) ) {
if ( nameBufLength > strlen ( nameBuf ) ) {
strncpy ( pNameBuf, nameBuf, nameBufLength );
}
}
}
}
extern "C"
epicsShareFunc FILE * epicsShareAPI epicsTempFile ( void )
{

View File

@@ -1,30 +0,0 @@
#include <string.h>
#include <stdlib.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
const char *raw = getexecname();
char *ret = NULL;
/* manpage says getexecname() might return a relative path. we treat this as an error */
if(raw[0]=='/') {
ret = strdup(raw);
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -38,6 +38,7 @@ typedef struct ringPvt {
volatile int nextPut;
volatile int nextGet;
int size;
int highWaterMark;
volatile char buffer[1]; /* actually larger */
}ringPvt;
@@ -47,6 +48,7 @@ epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesCreate(int size)
if(!pring)
return NULL;
pring->size = size + SLOP;
pring->highWaterMark = 0;
pring->nextGet = 0;
pring->nextPut = 0;
pring->lock = 0;
@@ -118,7 +120,7 @@ epicsShareFunc int epicsShareAPI epicsRingBytesPut(
{
ringPvt *pring = (ringPvt *)id;
int nextGet, nextPut, size;
int freeCount, copyCount, topCount;
int freeCount, copyCount, topCount, used;
if (pring->lock) epicsSpinLock(pring->lock);
nextGet = pring->nextGet;
@@ -131,8 +133,9 @@ epicsShareFunc int epicsShareAPI epicsRingBytesPut(
if (pring->lock) epicsSpinUnlock(pring->lock);
return 0;
}
if (nbytes)
if (nbytes) {
memcpy ((void *)&pring->buffer[nextPut], value, nbytes);
}
nextPut += nbytes;
}
else {
@@ -143,8 +146,9 @@ epicsShareFunc int epicsShareAPI epicsRingBytesPut(
}
topCount = size - nextPut;
copyCount = (nbytes > topCount) ? topCount : nbytes;
if (copyCount)
if (copyCount) {
memcpy ((void *)&pring->buffer[nextPut], value, copyCount);
}
nextPut += copyCount;
if (nextPut == size) {
int nLeft = nbytes - copyCount;
@@ -155,6 +159,10 @@ epicsShareFunc int epicsShareAPI epicsRingBytesPut(
}
pring->nextPut = nextPut;
used = nextPut - nextGet;
if (used < 0) used += pring->size;
if (used > pring->highWaterMark) pring->highWaterMark = used;
if (pring->lock) epicsSpinUnlock(pring->lock);
return nbytes;
}
@@ -224,3 +232,20 @@ epicsShareFunc int epicsShareAPI epicsRingBytesIsFull(epicsRingBytesId id)
{
return (epicsRingBytesFreeBytes(id) <= 0);
}
epicsShareFunc int epicsShareAPI epicsRingBytesHighWaterMark(epicsRingBytesIdConst id)
{
ringPvt *pring = (ringPvt *)id;
return pring->highWaterMark;
}
epicsShareFunc void epicsShareAPI epicsRingBytesResetHighWaterMark(epicsRingBytesId id)
{
ringPvt *pring = (ringPvt *)id;
int used;
if (pring->lock) epicsSpinLock(pring->lock);
used = pring->nextGet - pring->nextPut;
if (used < 0) used += pring->size;
pring->highWaterMark = used;
if (pring->lock) epicsSpinUnlock(pring->lock);
}

View File

@@ -24,6 +24,7 @@ extern "C" {
#include "shareLib.h"
typedef void *epicsRingBytesId;
typedef void const *epicsRingBytesIdConst;
epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesCreate(int nbytes);
/* Same, but secured by a spinlock */
@@ -39,6 +40,8 @@ epicsShareFunc int epicsShareAPI epicsRingBytesUsedBytes(epicsRingBytesId id);
epicsShareFunc int epicsShareAPI epicsRingBytesSize(epicsRingBytesId id);
epicsShareFunc int epicsShareAPI epicsRingBytesIsEmpty(epicsRingBytesId id);
epicsShareFunc int epicsShareAPI epicsRingBytesIsFull(epicsRingBytesId id);
epicsShareFunc int epicsShareAPI epicsRingBytesHighWaterMark(epicsRingBytesIdConst id);
epicsShareFunc void epicsShareAPI epicsRingBytesResetHighWaterMark(epicsRingBytesId id);
#ifdef __cplusplus
}

View File

@@ -90,3 +90,15 @@ epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id)
voidPointer *pvoidPointer = reinterpret_cast<voidPointer*>(id);
return((pvoidPointer->isFull()) ? 1 : 0);
}
epicsShareFunc int epicsShareAPI epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id)
{
voidPointer const *pvoidPointer = reinterpret_cast<voidPointer const*>(id);
return(pvoidPointer->getHighWaterMark());
}
epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPointerId id)
{
voidPointer *pvoidPointer = reinterpret_cast<voidPointer*>(id);
pvoidPointer->resetHighWaterMark();
}

View File

@@ -40,18 +40,22 @@ public: /* Functions */
int getSize() const;
bool isEmpty() const;
bool isFull() const;
int getHighWaterMark() const;
void resetHighWaterMark();
private: /* Prevent compiler-generated member functions */
/* default constructor, copy constructor, assignment operator */
epicsRingPointer();
epicsRingPointer(const epicsRingPointer &);
epicsRingPointer& operator=(const epicsRingPointer &);
int getUsedNoLock() const;
private: /* Data */
epicsSpinId lock;
volatile int nextPush;
volatile int nextPop;
int size;
int highWaterMark;
T * volatile * buffer;
};
@@ -59,6 +63,7 @@ extern "C" {
#endif /*__cplusplus */
typedef void *epicsRingPointerId;
typedef void const *epicsRingPointerIdConst;
epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size);
/* Same, but secured by a spinlock */
@@ -74,6 +79,8 @@ epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id)
epicsShareFunc int epicsShareAPI epicsRingPointerGetSize(epicsRingPointerId id);
epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id);
epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id);
epicsShareFunc int epicsShareAPI epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id);
epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPointerId id);
/* This routine was incorrectly named in previous releases */
#define epicsRingPointerSize epicsRingPointerGetSize
@@ -95,7 +102,8 @@ epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id);
template <class T>
inline epicsRingPointer<T>::epicsRingPointer(int sz, bool locked) :
lock(0), nextPush(0), nextPop(0), size(sz+1), buffer(new T* [sz+1])
lock(0), nextPush(0), nextPop(0), size(sz+1), highWaterMark(0),
buffer(new T* [sz+1])
{
if (locked)
lock = epicsSpinCreate();
@@ -121,6 +129,8 @@ inline bool epicsRingPointer<T>::push(T *p)
}
buffer[next] = p;
nextPush = newNext;
int used = getUsedNoLock();
if (used > highWaterMark) highWaterMark = used;
if (lock) epicsSpinUnlock(lock);
return(true);
}
@@ -161,12 +171,19 @@ inline int epicsRingPointer<T>::getFree() const
return n;
}
template <class T>
inline int epicsRingPointer<T>::getUsedNoLock() const
{
int n = nextPush - nextPop;
if (n < 0) n += size;
return n;
}
template <class T>
inline int epicsRingPointer<T>::getUsed() const
{
if (lock) epicsSpinLock(lock);
int n = nextPush - nextPop;
if (n < 0) n += size;
int n = getUsedNoLock();
if (lock) epicsSpinUnlock(lock);
return n;
}
@@ -196,6 +213,20 @@ inline bool epicsRingPointer<T>::isFull() const
return((count == 0) || (count == size));
}
template <class T>
inline int epicsRingPointer<T>::getHighWaterMark() const
{
return highWaterMark;
}
template <class T>
inline void epicsRingPointer<T>::resetHighWaterMark()
{
if (lock) epicsSpinLock(lock);
highWaterMark = getUsedNoLock();
if (lock) epicsSpinUnlock(lock);
}
#endif /* __cplusplus */
#endif /* INCepicsRingPointerh */

View File

@@ -232,11 +232,6 @@ osiSockTest_SRCS += osiSockTest.c
testHarness_SRCS += osiSockTest.c
TESTS += osiSockTest
TESTPROD_HOST += testexecname
testexecname_SRCS += testexecname.c
# no point in including in testHarness. Not implemented for RTEMS/vxWorks.
TESTS += testexecname
ifeq ($(BUILD_CLASS),HOST)
ifneq ($(OS_CLASS),WIN32)
# This test can only be run on a build host, and is broken on Windows

View File

@@ -30,7 +30,8 @@ typedef struct info {
epicsRingBytesId ring;
}info;
static void check(epicsRingBytesId ring, int expectedFree)
static void check(epicsRingBytesId ring, int expectedFree,
int expectedHighWaterMark)
{
int expectedUsed = RINGSIZE - expectedFree;
int expectedEmpty = (expectedUsed == 0);
@@ -39,11 +40,14 @@ static void check(epicsRingBytesId ring, int expectedFree)
int nUsed = epicsRingBytesUsedBytes(ring);
int isEmpty = epicsRingBytesIsEmpty(ring);
int isFull = epicsRingBytesIsFull(ring);
int highWaterMark = epicsRingBytesHighWaterMark(ring);
testOk(nFree == expectedFree, "Free: %d == %d", nFree, expectedFree);
testOk(nUsed == expectedUsed, "Used: %d == %d", nUsed, expectedUsed);
testOk(isEmpty == expectedEmpty, "Empty: %d == %d", isEmpty, expectedEmpty);
testOk(isFull == expectedFull, "Full: %d == %d", isFull, expectedFull);
testOk(highWaterMark == expectedHighWaterMark, "HighWaterMark: %d == %d",
highWaterMark, expectedHighWaterMark);
}
MAIN(ringBytesTest)
@@ -55,7 +59,7 @@ MAIN(ringBytesTest)
char get[RINGSIZE+1];
epicsRingBytesId ring;
testPlan(245);
testPlan(292);
pinfo = calloc(1,sizeof(info));
if (!pinfo) {
@@ -70,50 +74,54 @@ MAIN(ringBytesTest)
if (!ring) {
testAbort("epicsRingBytesCreate failed");
}
check(ring, RINGSIZE);
check(ring, RINGSIZE, 0);
for (i = 0 ; i < sizeof(put) ; i++)
put[i] = i;
for(i = 0 ; i < RINGSIZE ; i++) {
n = epicsRingBytesPut(ring, put, i);
testOk(n==i, "ring put %d", i);
check(ring, RINGSIZE-i);
check(ring, RINGSIZE-i, i);
n = epicsRingBytesGet(ring, get, i);
testOk(n==i, "ring get %d", i);
check(ring, RINGSIZE);
check(ring, RINGSIZE, i);
testOk(memcmp(put,get,i)==0, "get matches write");
}
epicsRingBytesResetHighWaterMark(ring);
for(i = 0 ; i < RINGSIZE ; i++) {
n = epicsRingBytesPut(ring, put+i, 1);
testOk(n==1, "ring put 1, %d", i);
check(ring, RINGSIZE-1-i);
check(ring, RINGSIZE-1-i, i + 1);
}
n = epicsRingBytesPut(ring, put+RINGSIZE, 1);
testOk(n==0, "put to full ring");
check(ring, 0);
check(ring, 0, RINGSIZE);
for(i = 0 ; i < RINGSIZE ; i++) {
n = epicsRingBytesGet(ring, get+i, 1);
testOk(n==1, "ring get 1, %d", i);
check(ring, 1+i);
check(ring, 1+i, RINGSIZE);
}
testOk(memcmp(put,get,RINGSIZE)==0, "get matches write");
n = epicsRingBytesGet(ring, get+RINGSIZE, 1);
testOk(n==0, "get from empty ring");
check(ring, RINGSIZE);
check(ring, RINGSIZE, RINGSIZE);
epicsRingBytesResetHighWaterMark(ring);
n = epicsRingBytesPut(ring, put, RINGSIZE+1);
testOk(n==0, "ring put beyond ring capacity (%d, expected 0)",n);
check(ring, RINGSIZE);
check(ring, RINGSIZE, 0);
n = epicsRingBytesPut(ring, put, 1);
testOk(n==1, "ring put %d", 1);
check(ring, RINGSIZE-1);
check(ring, RINGSIZE-1, 1);
n = epicsRingBytesPut(ring, put, RINGSIZE);
testOk(n==0, "ring put beyond ring capacity (%d, expected 0)",n);
check(ring, RINGSIZE-1);
check(ring, RINGSIZE-1, 1);
n = epicsRingBytesGet(ring, get, 1);
testOk(n==1, "ring get %d", 1);
check(ring, RINGSIZE);
check(ring, RINGSIZE, 1);
epicsRingBytesDelete(ring);
epicsEventDestroy(consumerEvent);

View File

@@ -64,6 +64,7 @@ static void testSingle(void)
testOk1(epicsRingPointerGetFree(ring)==rsize);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==0);
testOk1(epicsRingPointerGetHighWaterMark(ring)==0);
testOk1(epicsRingPointerPop(ring)==NULL);
@@ -75,6 +76,10 @@ static void testSingle(void)
testOk1(epicsRingPointerGetFree(ring)==rsize-1);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==1);
testOk1(epicsRingPointerGetHighWaterMark(ring)==1);
epicsRingPointerResetHighWaterMark(ring);
testOk1(epicsRingPointerGetHighWaterMark(ring)==1);
testDiag("Fill it up");
for(i=2; i<2*rsize; i++) {
@@ -92,6 +97,7 @@ static void testSingle(void)
testOk1(epicsRingPointerGetFree(ring)==0);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==rsize);
testOk1(epicsRingPointerGetHighWaterMark(ring)==rsize);
testDiag("Drain it out");
for(i=1; i<2*rsize; i++) {
@@ -108,6 +114,7 @@ static void testSingle(void)
testOk1(epicsRingPointerGetFree(ring)==rsize);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==0);
testOk1(epicsRingPointerGetHighWaterMark(ring)==rsize);
testDiag("Fill it up again");
for(i=2; i<2*rsize; i++) {
@@ -236,7 +243,7 @@ MAIN(ringPointerTest)
{
int prio = epicsThreadGetPrioritySelf();
testPlan(37);
testPlan(42);
testSingle();
if (prio)
epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityScanLow);

View File

@@ -1,24 +0,0 @@
#include <string.h>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <osiFileName.h>
MAIN(testexecname)
{
testPlan(1);
{
char *buf = epicsGetExecName();
if(!buf) {
testSkip(1, "epicsGetExecName() not available for this target");
} else {
char *loc = strstr(buf, "testexecname");
testOk(!!loc, "Find \"testexecname\" in \"%s\"", buf);
}
}
return testDone();
}

View File

@@ -39,8 +39,6 @@ PERL_SCRIPTS += tap-to-junit-xml.pl
PERL_SCRIPTS += useManifestTool.pl
PERL_SCRIPTS += genVersionHeader.pl
PERL_SCRIPTS += makeRPath.py
HTMLS = style.css
HTMLS += EPICS/Getopts.html
HTMLS += EPICS/Path.html
@@ -50,27 +48,4 @@ HTMLS += munch.html
HTMLS += podToHtml.html
HTMLS += podRemove.html
# Build Package Config Files
FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION))
C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CPPFLAGS))))
C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CFLAGS))))
PKGVARS += FINAL_LOCATION OS_CLASS CMPLR_CLASS C_CFLAGS LDFLAGS LDLIBS
PKGVARS += EPICS_VERSION EPICS_REVISION EPICS_MODIFICATION EPICS_PATCH_LEVEL
PKGVARS += CC CCC CPP AR LD
PKGVARS += EPICS_BASE_IOC_LIBS
EXPANDFLAGS += $(foreach var,$(PKGVARS),-D$(var)="$(strip $($(var)))")
PKGCONFIG += epics-base-$(T_A).pc
ifeq ($(T_A),$(EPICS_HOST_ARCH))
PKGCONFIG += epics-base.pc
endif
EXPAND += $(PKGCONFIG:%=%@)
CLEANS += epics-base-$(T_A).pc@
include $(TOP)/configure/RULES
epics-base-$(T_A).pc@: ../epics-base-arch.pc@
@$(RM) $@
@$(CP) $< $@

View File

@@ -1,37 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import sys
import os
from argparse import ArgumentParser
if os.environ.get('EPICS_DEBUG_RPATH','')=='YES':
sys.stderr.write('%s'%sys.argv)
P = ArgumentParser()
P.add_argument('-F','--final',default=os.getcwd(), help='Final install location for ELF file')
P.add_argument('-R','--root',default='/')
P.add_argument('-O', '--origin', default='$ORIGIN')
P.add_argument('path', nargs='*')
args = P.parse_args()
fdir = os.path.abspath(args.final)
output = []
for path in args.path:
path = os.path.abspath(path)
if args.root and os.path.relpath(path, args.root).startswith('../'):
pass # absolute rpath
else:
# some older binutils don't seem to handle $ORIGIN correctly
# when locating dependencies of libraries. So also provide
# the absolute path for internal use by 'ld' only.
output.append('-Wl,-rpath-link,'+path)
path = os.path.relpath(path, fdir)
output.append('-Wl,-rpath,'+os.path.join(args.origin, path))
print(' '.join(output))

View File

@@ -1,4 +1,4 @@
#!/usr/bin/perl
#!/usr/bin/env perl
=head1 NAME
tap-to-junit-xml - convert perl-style TAP test output to JUnit-style XML