Compare commits
95 Commits
R3.15.0.1
...
R3.14.12.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a3e7414b3 | ||
|
|
9ab6f89604 | ||
|
|
570993e32b | ||
|
|
93be1400c1 | ||
|
|
176ee926ad | ||
|
|
2d52067484 | ||
|
|
66209118f6 | ||
|
|
d6dab34ae9 | ||
|
|
4b44881744 | ||
|
|
42f4c3a0a5 | ||
|
|
2ad468dd38 | ||
|
|
2bf4b36639 | ||
|
|
6814b09fad | ||
|
|
2d3a828acd | ||
|
|
4ae048572a | ||
|
|
e49210a3ea | ||
|
|
d25eff3af7 | ||
|
|
01f0fdbf1e | ||
|
|
3219ea0608 | ||
|
|
fb983fe382 | ||
|
|
ffa96d36e1 | ||
|
|
515f882c7b | ||
|
|
d3b6d01807 | ||
|
|
f2891d72e5 | ||
|
|
75a5f19d2e | ||
|
|
98deef5004 | ||
|
|
c187d8c13a | ||
|
|
1289f99e30 | ||
|
|
ef5d88d3e5 | ||
|
|
93449dccb8 | ||
|
|
863e8fdd3b | ||
|
|
ee9c0ba409 | ||
|
|
7f82c2f32e | ||
|
|
e0bc071de3 | ||
|
|
593e313fab | ||
|
|
34744264e1 | ||
|
|
5ac686fafd | ||
|
|
7e347b2de9 | ||
|
|
5bc15b72a1 | ||
|
|
880db9d4af | ||
|
|
58c031238b | ||
|
|
f824246baa | ||
|
|
f9a0c82a63 | ||
|
|
a4edc46a5f | ||
|
|
738b8ca55f | ||
|
|
c767958539 | ||
|
|
8400e74606 | ||
|
|
451c4cc854 | ||
|
|
038a1140f4 | ||
|
|
89d000be08 | ||
|
|
a0798939b3 | ||
|
|
a5999242b0 | ||
|
|
9e484306d6 | ||
|
|
835199a45d | ||
|
|
0df6f849d6 | ||
|
|
75e32c9086 | ||
|
|
b7018dd16d | ||
|
|
3498a6d4e0 | ||
|
|
f90f021309 | ||
|
|
c1203076f2 | ||
|
|
753622315c | ||
|
|
910ab38af6 | ||
|
|
0e990bbe0c | ||
|
|
ef5688f8de | ||
|
|
d622bbad05 | ||
|
|
416cf68fd1 | ||
|
|
cbde3ea9fd | ||
|
|
6f9c2db8a8 | ||
|
|
01276d952f | ||
|
|
809633d698 | ||
|
|
1f573172b3 | ||
|
|
d6f72900f8 | ||
|
|
5b1d3a7725 | ||
|
|
7d79a83519 | ||
|
|
6fd9fb3066 | ||
|
|
28c7fe12f3 | ||
|
|
36be0aa783 | ||
|
|
69d8be78d3 | ||
|
|
fc61cc34ce | ||
|
|
e889336458 | ||
|
|
7cac267a4b | ||
|
|
71079ede4b | ||
|
|
26173c1e0d | ||
|
|
9c1b8ba952 | ||
|
|
c574722a9b | ||
|
|
4790578953 | ||
|
|
7e6e38060f | ||
|
|
709b6ef2f3 | ||
|
|
169b30081a | ||
|
|
a19e1d21da | ||
|
|
1ac8ff6378 | ||
|
|
5c2ef73c4a | ||
|
|
958aa02320 | ||
|
|
c93c7b5e36 | ||
|
|
b993e29fad |
@@ -63,7 +63,8 @@ DBEXPAND = $(call PATH_FILTER, $(TOOLS)/dbExpand$(HOSTEXE))
|
||||
DBTORECORDTYPEH = $(call PATH_FILTER, $(TOOLS)/dbToRecordtypeH$(HOSTEXE))
|
||||
DBTOMENUH = $(call PATH_FILTER, $(TOOLS)/dbToMenuH$(HOSTEXE))
|
||||
REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
|
||||
CONVERTRELEASE=$(PERL) $(TOOLS)/convertRelease.pl
|
||||
CONVERTRELEASE = $(PERL) $(TOOLS)/convertRelease.pl
|
||||
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
|
||||
|
||||
#-------------------------------------------------------
|
||||
# tools for installing libraries and products
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
|
||||
# Copyright (c) 2012 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.
|
||||
@@ -30,11 +30,11 @@ EPICS_MODIFICATION = 12
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included if zero
|
||||
EPICS_PATCH_LEVEL = 2
|
||||
EPICS_PATCH_LEVEL = 4
|
||||
|
||||
# This will end in -DEV between official releases
|
||||
EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-DEV
|
||||
EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre2
|
||||
#EPICS_DEV_SNAPSHOT=-pre2-DEV
|
||||
|
||||
@@ -76,9 +76,12 @@ INSTALL_DB = $(INSTALL_LOCATION)/db
|
||||
INSTALL_CONFIG = $(INSTALL_LOCATION)/configure
|
||||
INSTALL_JAVA = $(INSTALL_LOCATION)/javalib
|
||||
|
||||
#Directory for OS independant build created files
|
||||
# Directory for OS independant build created files
|
||||
COMMON_DIR = ../O.Common
|
||||
|
||||
# IOC's absolute path to $(TOP), may be overridden inside the application
|
||||
IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Make echo output - suppress echoing if make's '-s' flag is set
|
||||
NOP = :
|
||||
@@ -371,6 +374,7 @@ INSTALL_LIB_INSTALLS = $(addprefix $(INSTALL_LIB)/,$(notdir $(LIB_INSTALLS)))
|
||||
# Installed file permissions
|
||||
BIN_PERMISSIONS = 555
|
||||
LIB_PERMISSIONS = 444
|
||||
SHRLIB_PERMISSIONS = 555
|
||||
INSTALL_PERMISSIONS = 444
|
||||
|
||||
#---------------------------------------------------------------
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
# aix-ppc (IBM compiler used for host builds)
|
||||
# aix-ppc-gnu (GNU compiler used for host builds)
|
||||
# cygwin-x86 (cygwin compiler used for host builds)
|
||||
# cygwin-x86_64 (cygwin compiler used for host builds)
|
||||
# darwin-ppc (PowerPC based Apple running OSX)
|
||||
# darwin-ppcx86 (Universal binaries for both CPUs)
|
||||
# darwin-x86 (Intel based Apple running OSX)
|
||||
@@ -41,6 +42,7 @@
|
||||
# win32-x86-cygwin (WIN32 API with cygwin GNU compiler used for host builds)
|
||||
# win32-x86-mingw (MinGW compiler used for host builds)
|
||||
# windows-x64 (MS Visual C++ compiler used for host builds)
|
||||
# windows-x64-mingw (MinGW compiler used for host builds)
|
||||
|
||||
# Debugging builds
|
||||
# linux-x86-debug (GNU compiler with -g option for host builds)
|
||||
@@ -72,6 +74,7 @@
|
||||
# linux-cris (Axis GNU crosscompiler on linux-x86 host)
|
||||
# linux-cris_v10 (Axis GNU crosscompiler on linux-x86 host)
|
||||
# linux-cris_v32 (Axis GNU crosscompiler on linux-x86 host)
|
||||
# linux-microblaze
|
||||
# linux-xscale_be
|
||||
# vxWorks-486
|
||||
# vxWorks-68040
|
||||
@@ -119,9 +122,9 @@ CROSS_COMPILER_HOST_ARCHS=
|
||||
# NOTE: os/CONFIG.$(EPICS_HOST_ARCH).$(EPICS_HOST_ARCH) files and
|
||||
# os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(EPICS_HOST_ARCH) files may override
|
||||
#
|
||||
# NOTE WIN32: YES results in a DLL. Valid settings are
|
||||
# SHARED_LIBRARIES=YES and STATIC_BUILD=NO
|
||||
# SHARED_LIBRARIES=NO and STATIC_BUILD=YES
|
||||
# NOTE Windows: YES results in a DLL. Valid settings are
|
||||
# SHARED_LIBRARIES=YES and STATIC_BUILD=NO
|
||||
# SHARED_LIBRARIES=NO and STATIC_BUILD=YES
|
||||
#
|
||||
SHARED_LIBRARIES=YES
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ $(COMMON_DIR)/%Record.h: $(COMMON_DIR)/%Record.dbd
|
||||
$(COMMON_DIR)/%Record.h: %Record.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
echo "$@ : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTORECORDTYPEH) $(DBDFLAGS) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
@@ -244,7 +244,7 @@ $(COMMON_DIR)/menu%.h: $(COMMON_DIR)/menu%.dbd
|
||||
$(COMMON_DIR)/menu%.h: menu%.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
echo "$@ : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTOMENUH) $(DBDFLAGS) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
@@ -269,7 +269,7 @@ $(COMMON_DIR)/%.dbd: $(COMMON_DIR)/%Include.dbd
|
||||
$(COMMON_DIR)/%.dbd: %Include.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
echo "$@ : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
$(ECHO) "Expanding dbd"
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBEXPAND) $(DBDFLAGS) -o $(notdir $@) $<
|
||||
@@ -368,17 +368,14 @@ $(foreach file, $(DB_INSTALLS), $(eval $(call DB_INSTALLS_template, $(file))))
|
||||
|
||||
##################################################### register record,device,driver support
|
||||
|
||||
IOC_INST_TOP := $(firstword $(IOCS_APPL_TOP) \
|
||||
$(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION) ) )
|
||||
|
||||
%_registerRecordDeviceDriver.cpp: $(COMMON_DIR)/%.dbd
|
||||
@$(RM) $@ $*.tmp
|
||||
$(REGISTERRECORDDEVICEDRIVER) $< $(basename $@) $(IOC_INST_TOP) > $*.tmp
|
||||
$(REGISTERRECORDDEVICEDRIVER) $< $(basename $@) $(IOCS_APPL_TOP) > $*.tmp
|
||||
$(MV) $*.tmp $@
|
||||
|
||||
%_registerRecordDeviceDriver.cpp: %.dbd
|
||||
@$(RM) $@ $*.tmp
|
||||
$(REGISTERRECORDDEVICEDRIVER) $< $(basename $@) $(IOC_INST_TOP) > $*.tmp
|
||||
$(REGISTERRECORDDEVICEDRIVER) $< $(basename $@) $(IOCS_APPL_TOP) > $*.tmp
|
||||
$(MV) $*.tmp $@
|
||||
|
||||
.PRECIOUS: %_registerRecordDeviceDriver.cpp
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2013 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 Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#RULES.ioc
|
||||
|
||||
include $(CONFIG)/RULES_DIRS
|
||||
|
||||
build$(DIVIDER)$(ARCH) build: buildInstall
|
||||
@@ -15,23 +15,18 @@ install$(DIVIDER)$(ARCH) install: buildInstall
|
||||
$(ARCH): buildInstall
|
||||
|
||||
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(ARCH))
|
||||
buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS)
|
||||
buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS)
|
||||
|
||||
clean$(DIVIDER)$(ARCH) clean:
|
||||
clean$(DIVIDER)$(ARCH) clean:
|
||||
$(RM) cdCommands envPaths dllPath.bat
|
||||
|
||||
else
|
||||
buildInstall$(DIVIDER)$(ARCH) buildInstall:
|
||||
clean$(DIVIDER)$(ARCH) clean:
|
||||
else
|
||||
buildInstall$(DIVIDER)$(ARCH) buildInstall:
|
||||
clean$(DIVIDER)$(ARCH) clean:
|
||||
endif
|
||||
|
||||
cdCommands envPaths dllPath.bat: $(wildcard $(TOP)/configure/RELEASE*) \
|
||||
$(TOP)/configure/CONFIG $(INSTALL_BIN)
|
||||
ifeq ($(IOCS_APPL_TOP),)
|
||||
$(PERL) $(TOOLS)/convertRelease.pl -a $(ARCH) $@
|
||||
else
|
||||
$(PERL) $(TOOLS)/convertRelease.pl -a $(ARCH) -t $(IOCS_APPL_TOP) $@
|
||||
endif
|
||||
$(wildcard $(TOP)/configure/CONFIG_SITE*) $(INSTALL_BIN)
|
||||
$(CONVERTRELEASE) -a $(ARCH) -t $(IOCS_APPL_TOP) $@
|
||||
|
||||
realclean:
|
||||
$(RM) cdCommands envPaths dllPath.bat
|
||||
|
||||
@@ -322,10 +322,10 @@ $(OBJLIB_MUNCHNAME):%.munch : %_ctdt$(OBJ) %$(OBJ)
|
||||
@$(RM) $@
|
||||
$(MUNCH_CMD)
|
||||
|
||||
runtests: $(TESTSCRIPTS_$(BUILD_CLASS))
|
||||
runtests: $(TESTSCRIPTS)
|
||||
-$(PERL) -MTest::Harness -e 'runtests @ARGV if @ARGV;' $^
|
||||
|
||||
testspec: $(TESTSCRIPTS_$(BUILD_CLASS))
|
||||
testspec: $(TESTSCRIPTS)
|
||||
@$(RM) $@
|
||||
@echo OS-class: $(OS_CLASS) > $@
|
||||
@echo Target-arch: $(T_A) >> $@
|
||||
@@ -383,7 +383,7 @@ $(INSTALL_LIB)/%.lib: %.lib
|
||||
|
||||
$(INSTALL_SHRLIBS): $(INSTALL_SHRLIB)/%: %
|
||||
$(ECHO) "Installing shared library $@"
|
||||
@$(INSTALL_LIBRARY) -d -m $(LIB_PERMISSIONS) $< $(INSTALL_SHRLIB)
|
||||
@$(INSTALL_LIBRARY) -d -m $(SHRLIB_PERMISSIONS) $< $(INSTALL_SHRLIB)
|
||||
ifneq ($(SHRLIB_SUFFIX),$(SHRLIB_SUFFIX_BASE))
|
||||
ifneq (,$(strip $(SHRLIB_VERSION)))
|
||||
@$(RM) $(subst $(SHRLIB_SUFFIX),$(SHRLIB_SUFFIX_BASE),$@)
|
||||
|
||||
0
configure/RULES_TARGET
Executable file → Normal file
0
configure/RULES_TARGET
Executable file → Normal file
@@ -64,11 +64,11 @@ help:
|
||||
@echo " rebuild - Same as clean install"
|
||||
@echo " archclean - Removes O.<arch> dirs but not O.Common dir"
|
||||
@echo "\"Partial\" build targets supported by Makefiles:"
|
||||
@echo " inc.<arch> - Installs <arch> only header files."
|
||||
@echo " build.<arch> - Builds and installs <arch> only."
|
||||
@echo " install.<arch> - Builds and installs <arch> only."
|
||||
@echo " clean.<arch> - Cleans <arch> binaries in O.<arch> dirs only."
|
||||
@echo " uninstall.<arch> - Remove bin & lib directories for <arch> only."
|
||||
@echo " inc$(DIVIDER)<arch> - Installs <arch> only header files."
|
||||
@echo " build$(DIVIDER)<arch> - Builds and installs <arch> only."
|
||||
@echo " install$(DIVIDER)<arch> - Builds and installs <arch> only."
|
||||
@echo " clean$(DIVIDER)<arch> - Cleans <arch> binaries in O.<arch> dirs only."
|
||||
@echo " uninstall$(DIVIDER)<arch> - Remove bin & lib directories for <arch> only."
|
||||
@echo "Targets supported by top level Makefile:"
|
||||
@echo " archuninstall - Remove bin & lib directories created by this hostarch."
|
||||
@echo " uninstall - Remove install directories created by this hostarch."
|
||||
|
||||
0
configure/Sample.Makefile
Executable file → Normal file
0
configure/Sample.Makefile
Executable file → Normal file
@@ -20,8 +20,8 @@ OBJ = .o
|
||||
LIB_PREFIX = lib
|
||||
LIB_SUFFIX = .a
|
||||
SHRLIB_SUFFIX_BASE = .so
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE).$(SHRLIB_VERSION)
|
||||
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE).$(LOADABLE_SHRLIB_VERSION)
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)$(addprefix .,$(SHRLIB_VERSION))
|
||||
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)$(addprefix .,$(LOADABLE_SHRLIB_VERSION))
|
||||
LOADABLE_SHRLIB_PREFIX = lib
|
||||
|
||||
#-------------------------------------------------------
|
||||
@@ -50,7 +50,7 @@ SHRLIB_LDLIBS = $(addprefix -l, $($*_LDLIBS) $(LIB_LIBS) $(USR_LIBS))\
|
||||
$(LDLIBS)
|
||||
|
||||
SHRLIB_DEPLIB_DIRS = $(foreach word,$(sort $(dir $($*_DEPLIBS) $(SHRLIB_DEPLIBS))), \
|
||||
$(shell $(PERL) $(TOOLS)/fullPathName.pl $(word)))
|
||||
$(shell $(FULLPATHNAME) $(word)))
|
||||
|
||||
SHRLIBDIR_LDFLAGS += $(SHRLIB_DEPLIB_DIRS:%=-L%)
|
||||
|
||||
@@ -73,7 +73,7 @@ PROD_LDLIBS += $($(firstword $(LDLIBS_STATIC_$(STATIC_BUILD)) \
|
||||
$(LDLIBS_SHARED_$(SHARED_LIBRARIES))))
|
||||
|
||||
PROD_DEPLIB_DIRS = $(foreach word,$(sort $(dir $($*_DEPLIBS) $(PROD_DEPLIBS))), \
|
||||
$(shell $(PERL) $(TOOLS)/fullPathName.pl $(word)))
|
||||
$(shell $(FULLPATHNAME) $(word)))
|
||||
|
||||
PRODDIR_LDFLAGS += $(PROD_DEPLIB_DIRS:%=-L%)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ OS_CLASS = cygwin32
|
||||
ARCH_CLASS = x86
|
||||
|
||||
# Definitions used when COMMANDLINE_LIBRARY is READLINE
|
||||
LDLIBS_READLINE = -lreadline -lcurses
|
||||
LDLIBS_READLINE = -lreadline
|
||||
|
||||
POSIX_CPPFLAGS = -D_POSIX_THREADS -D_POSIX_TIMERS
|
||||
#POSIX_CPPFLAGS += -D_POSIX_SOURCE
|
||||
|
||||
14
configure/os/CONFIG.Common.cygwin-x86_64
Normal file
14
configure/os/CONFIG.Common.cygwin-x86_64
Normal file
@@ -0,0 +1,14 @@
|
||||
# CONFIG.Common.cygwin-x86_64
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for cygwin-x86_64 target builds
|
||||
# Sites may override these definitions in CONFIG_SITE.Common.cygwin-x86_64
|
||||
#-------------------------------------------------------
|
||||
|
||||
include $(CONFIG)/os/CONFIG.Common.cygwin-x86
|
||||
|
||||
ARCH_DEP_CFLAGS = -m64
|
||||
ARCH_DEP_LDFLAGS = -m64
|
||||
|
||||
@@ -41,6 +41,7 @@ ARCH_DEP_LDFLAGS += $(ARCH_DEP_FLAGS)
|
||||
#--------------------------------------------------
|
||||
# Operating system flags
|
||||
OP_SYS_CFLAGS += -isysroot $(SDK_DIR) -D__IPHONE_OS_VERSION_MIN_REQUIRED=30200
|
||||
OP_SYS_LDFLAGS += -isysroot $(SDK_DIR)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Always compile in debugging symbol table information
|
||||
@@ -53,13 +54,15 @@ OPT_CXXFLAGS_YES += -g
|
||||
|
||||
CC_GNU = gcc
|
||||
CCC_GNU = g++
|
||||
CC_LLVM = llvm-gcc
|
||||
CCC_LLVM = llvm-g++
|
||||
|
||||
CC_LLVM_GNU = llvm-gcc
|
||||
CCC_LLVM_GNU = llvm-g++
|
||||
|
||||
CC_CLANG = clang
|
||||
CCC_CLANG = clang++
|
||||
|
||||
CC = $(firstword $(wildcard $(GNU_BIN)/$(CC_$(COMPILER))) $(CC_$(COMPILER)))
|
||||
CCC = $(firstword $(wildcard $(GNU_BIN)/$(CCC_$(COMPILER))) $(CCC_$(COMPILER)))
|
||||
# Convert the iOS platform to lowercase for passing to xcrun's sdk parameter
|
||||
XCRUN_SDK_BASE = $(shell echo $(IOS_PLATFORM) | tr A-Z a-z)
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Linker flags
|
||||
@@ -70,7 +73,7 @@ OP_SYS_LDFLAGS += -dynamic -Z -L$(SDK_DIR)/usr/lib -L$(SDK_DIR)/usr/lib/system
|
||||
# Shared libraries
|
||||
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)
|
||||
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
|
||||
-install_name $(shell perl $(TOOLS)/fullPathName.pl $(INSTALL_LIB))/$@ \
|
||||
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
|
||||
-compatibility_version $(EPICS_VERSION).$(EPICS_REVISION) \
|
||||
-current_version $(SHRLIB_VERSION)
|
||||
SHRLIB_SUFFIX_BASE = .dylib
|
||||
@@ -93,13 +96,14 @@ vpath %.m $(USR_VPATH) $(ALL_SRC_DIRS)
|
||||
#--------------------------------------------------
|
||||
# Header dependency file generation
|
||||
#
|
||||
# Use compiler when ARCH_CLASS is a single arch value
|
||||
# otherwise use perl script command
|
||||
SINGLE_ARCH=$(filter 1,$(words $(ARCH_CLASS)))
|
||||
HDEPENDS_CFLAGS = $(if $(SINGLE_ARCH),$(HDEPENDS_CFLAGS_$(HDEPENDS)))
|
||||
HDEPENDS_METHOD = $(if $(SINGLE_ARCH),CFLAGS,CMD)
|
||||
HDEPENDS_METHOD = CMD
|
||||
|
||||
#--------------------------------------------------
|
||||
# Allow site overrides
|
||||
-include $(CONFIG)/os/CONFIG_SITE.Common.iosCommon
|
||||
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).iosCommon
|
||||
|
||||
#--------------------------------------------------
|
||||
# Find the Xcode compilers for the specified SDK just once
|
||||
CC := $(shell xcrun -sdk $(XCRUN_SDK_BASE) -find $(CC_$(COMPILER)))
|
||||
CCC := $(shell xcrun -sdk $(XCRUN_SDK_BASE) -find $(CCC_$(COMPILER)))
|
||||
|
||||
@@ -17,7 +17,7 @@ ifeq ($(BUILD_CLASS),CROSS)
|
||||
|
||||
# prefix of compiler tools
|
||||
CMPLR_SUFFIX =
|
||||
CMPLR_PREFIX = $(GNU_TARGET)-
|
||||
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
|
||||
|
||||
# Provide a link-time path for shared libraries
|
||||
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
|
||||
|
||||
@@ -93,6 +93,7 @@ VX_GNU_VERSION_6.5 = 3.4.4
|
||||
VX_GNU_VERSION_6.6 = 4.1.2
|
||||
VX_GNU_VERSION_6.7 = 4.1.2
|
||||
VX_GNU_VERSION_6.8 = 4.1.2
|
||||
VX_GNU_VERSION_6.9 = 4.3.3
|
||||
VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
|
||||
|
||||
VX_GNU_MAJOR_VERSION = $(basename $(basename $(VX_GNU_VERSION)))
|
||||
@@ -134,6 +135,7 @@ NM_DIR_6.5 = $(WORKBENCH_BIN)
|
||||
NM_DIR_6.6 = $(WORKBENCH_BIN)
|
||||
NM_DIR_6.7 = $(GNU_BIN)
|
||||
NM_DIR_6.8 = $(UTILITIES_BIN)
|
||||
NM_DIR_6.9 = $(UTILITIES_BIN)
|
||||
NM_DIR = $(firstword $(NM_DIR_$(VXWORKS_VERSION)) $(GNU_BIN))
|
||||
|
||||
NM = $(NM_DIR)/$(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
|
||||
|
||||
15
configure/os/CONFIG.Common.windows-x64-mingw
Normal file
15
configure/os/CONFIG.Common.windows-x64-mingw
Normal file
@@ -0,0 +1,15 @@
|
||||
# CONFIG.Common.windows-x64-mingw
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for windows-x64-mingw target builds
|
||||
# Sites may override these definitions in CONFIG_SITE.Common.windows-x64-mingw
|
||||
#-------------------------------------------------------
|
||||
|
||||
include $(CONFIG)/os/CONFIG.Common.win32-x86-mingw
|
||||
|
||||
ARCH_CLASS = x64
|
||||
|
||||
ARCH_DEP_CFLAGS = -m64
|
||||
ARCH_DEP_LDFLAGS = -m64
|
||||
10
configure/os/CONFIG.cygwin-x86_64.Common
Normal file
10
configure/os/CONFIG.cygwin-x86_64.Common
Normal file
@@ -0,0 +1,10 @@
|
||||
# CONFIG.cygwin-x86_64.Common
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for cygwin-x86_64 host archs
|
||||
# Sites may override these definitions in CONFIG_SITE.cygwin-x86_64.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
include $(CONFIG)/os/CONFIG.cygwin-x86.Common
|
||||
11
configure/os/CONFIG.cygwin-x86_64.cygwin-x86_64
Normal file
11
configure/os/CONFIG.cygwin-x86_64.cygwin-x86_64
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG.cygwin-x86_64.cygwin-x86_64
|
||||
#
|
||||
# $Revision-Id$
|
||||
#
|
||||
# Definitions for cygwin-x86_64 host - cygwin-x86_64 target builds
|
||||
# Sites may override these definitions in CONFIG_SITE.cygwin-x86_64.cygwin-x86_64
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include common gnu compiler definitions
|
||||
include $(CONFIG)/os/CONFIG.cygwin-x86.cygwin-x86
|
||||
|
||||
@@ -59,15 +59,17 @@ COMMANDLINE_LIBRARY=READLINE
|
||||
|
||||
GNU_DIR = /usr
|
||||
|
||||
CC = $(GNU_BIN)/cc
|
||||
CCC = $(GNU_BIN)/c++
|
||||
# Apple soft-links these compilers to clang/clang++
|
||||
CC = cc
|
||||
CCC = c++
|
||||
GNU = NO
|
||||
|
||||
#
|
||||
# Darwin shared libraries
|
||||
#
|
||||
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)
|
||||
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
|
||||
-install_name $(shell perl $(TOOLS)/fullPathName.pl $(INSTALL_LIB))/$@ \
|
||||
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
|
||||
-compatibility_version $(EPICS_VERSION).$(EPICS_REVISION) \
|
||||
-current_version $(SHRLIB_VERSION)
|
||||
SHRLIB_SUFFIX_BASE = .dylib
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
# Include common gnu compiler definitions
|
||||
include $(CONFIG)/CONFIG.gnuCommon
|
||||
|
||||
# gcc, g++, ar, ld, and ranlib must be in user's path
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
AR = ar -rc
|
||||
LD = ld -r
|
||||
RANLIB = ranlib
|
||||
RES=.coff
|
||||
RCCMD = windres $(INCLUDES) $< $@
|
||||
CMPLR_PREFIX =
|
||||
|
||||
CC = $(CMPLR_PREFIX)gcc
|
||||
CCC = $(CMPLR_PREFIX)g++
|
||||
AR = $(CMPLR_PREFIX)ar -rc
|
||||
LD = $(CMPLR_PREFIX)ld -r
|
||||
RANLIB = $(CMPLR_PREFIX)ranlib
|
||||
RES = .coff
|
||||
RCCMD = $(CMPLR_PREFIX)windres $(INCLUDES) $< $@
|
||||
|
||||
# No -fPIC avoids "-fPIC ignored for target (all code is position independent)"
|
||||
SHRLIB_CFLAGS =
|
||||
@@ -26,4 +27,4 @@ LOADABLE_SHRLIB_LDFLAGS = -shared -Wl,--out-implib,$(LIB_PREFIX)$*$(LIB_SUFFIX)
|
||||
# Override linking with gcc library from CONFIG.gnuCommon
|
||||
GNU_LDLIBS_YES =
|
||||
|
||||
OP_SYS_LDLIBS = -lws2_32
|
||||
OP_SYS_LDLIBS = -lws2_32
|
||||
|
||||
11
configure/os/CONFIG.windows-x64-mingw.Common
Normal file
11
configure/os/CONFIG.windows-x64-mingw.Common
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG.windows-x64-mingw.Common
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for windows-x64-mingw host archs
|
||||
# Sites may override these definitions in CONFIG_SITE.windows-x64-mingw.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
include $(CONFIG)/os/CONFIG.win32-x86-mingw.Common
|
||||
|
||||
11
configure/os/CONFIG.windows-x64-mingw.windows-x64-mingw
Normal file
11
configure/os/CONFIG.windows-x64-mingw.windows-x64-mingw
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG.windows-x64-mingw.windows-x64-mingw
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for windows-x64-mingw target archs
|
||||
# Sites may override these definitions in CONFIG_SITE.windows-x64-mingw.windows-x64-mingw
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include common gnu compiler definitions
|
||||
include $(CONFIG)/os/CONFIG.win32-x86-mingw.win32-x86-mingw
|
||||
@@ -5,21 +5,22 @@
|
||||
|
||||
# Where to find RTEMS
|
||||
#
|
||||
RTEMS_VERSION=4.9.2
|
||||
RTEMS_BASE=/usr/local/rtems/rtems-$(RTEMS_VERSION)
|
||||
RTEMS_VERSION = 4.10.2
|
||||
RTEMS_BASE = /usr/local/rtems/rtems-$(RTEMS_VERSION)
|
||||
|
||||
# Cross-compile toolchain in $(RTEMS_TOOLS)/bin
|
||||
#
|
||||
RTEMS_TOOLS=$(RTEMS_BASE)
|
||||
RTEMS_TOOLS = $(RTEMS_BASE)
|
||||
|
||||
|
||||
# If you're using neither BOOTP/DHCP nor FLASH to pick up your IOC
|
||||
# network configuration you must uncomment and specify your Internet
|
||||
# network configuration you must uncomment and specify your Internet
|
||||
# Domain Name here
|
||||
#
|
||||
#OP_SYS_CFLAGS += -DRTEMS_NETWORK_CONFIG_DNS_DOMAINNAME=<domainname>
|
||||
|
||||
#
|
||||
# Specify your desired command-line-input library
|
||||
# Select the command-line-input library to use
|
||||
#
|
||||
COMMANDLINE_LIBRARY = EPICS
|
||||
#COMMANDLINE_LIBRARY = LIBTECLA
|
||||
#COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
@@ -7,4 +7,7 @@
|
||||
|
||||
# If readline is installed uncomment the following line
|
||||
# to add command-line editing and history support
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
#COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
# Uncomment the following line if readline has problems
|
||||
#LDLIBS_READLINE= -lreadline -lcurses
|
||||
|
||||
14
configure/os/CONFIG_SITE.Common.cygwin-x86_64
Normal file
14
configure/os/CONFIG_SITE.Common.cygwin-x86_64
Normal file
@@ -0,0 +1,14 @@
|
||||
# CONFIG_SITE.Common.cygwin-x86_64
|
||||
#
|
||||
# $Revision-Id$
|
||||
#
|
||||
# Site Specific definitions for cygwin-x86_64 target
|
||||
# Only the local epics system manager should modify this file
|
||||
|
||||
# If readline is installed uncomment the following line
|
||||
# to add command-line editing and history support
|
||||
#COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
# Uncomment the following line if readline has problems
|
||||
#LDLIBS_READLINE = -lreadline -lcurses
|
||||
|
||||
@@ -7,17 +7,31 @@
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Select which CPU architecture(s) to include in your MacOS binaries:
|
||||
# i386
|
||||
# x86_64 - Needs MacOS 10.4 with the Universal SDK, or 10.5 and later
|
||||
# i386, x86_64, or both (fat binaries).
|
||||
|
||||
ARCH_CLASS = i386
|
||||
#ARCH_CLASS = x86_64
|
||||
#ARCH_CLASS = i386
|
||||
ARCH_CLASS = x86_64
|
||||
#ARCH_CLASS = i386 x86_64
|
||||
|
||||
#
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
# Uncomment the following 3 lines to build with Apple's GCC instead of CLANG.
|
||||
#
|
||||
#CC = clang
|
||||
#CCC = clang++
|
||||
#GNU_LDLIBS_YES =
|
||||
#CC = gcc
|
||||
#CCC = g++
|
||||
#GNU = YES
|
||||
|
||||
|
||||
# To use MacPorts GCC uncomment (and modify if necessary) the following:
|
||||
|
||||
#GNU_DIR = /opt/local
|
||||
#CC = $(GNU_BIN)/gcc -m64
|
||||
#CCC = $(GNU_BIN)/g++ -m64
|
||||
#GNU = YES
|
||||
|
||||
# If you see this or similar errors while building in the src/cap5 directory
|
||||
# gcc: error: unrecognized option '-no-cpp-precomp'
|
||||
# the problem is due to the ccflags configuration that your version of Perl
|
||||
# was built with. You can replace the Cap5_CFLAGS setting in the Makefile
|
||||
# with a hand-edited set of flags for building that Perl library, or ignore
|
||||
# this problem if you don't need to use Channel Access from Perl.
|
||||
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
# CONFIG_SITE.Common.ios-arm
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Site-specific settings for ios-arm target builds
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Which ARM instruction set(s) to generate code for:
|
||||
# Most iOS devices can run programs compiled for both the
|
||||
# ARMv6 and ARMv7 instruction sets. ARMv7 code is usually
|
||||
# more efficient, but the older devices listed below can only
|
||||
# use the ARMv6 instruction set. Including both architectures
|
||||
# generates a Universal binary, which is larger and takes
|
||||
# longer to compile but runs efficiently on all devices.
|
||||
# Most iOS devices can run programs compiled for older
|
||||
# instruction sets, although the newer instructions are
|
||||
# more efficient.
|
||||
#
|
||||
# ARMv6-only devices: iPhone 1 or 3G, iPod Touch Gen 1 or 2
|
||||
# Apple's compilers can build for multiple architectures,
|
||||
# generating a Universal binary. This is larger and takes
|
||||
# longer to compile, but runs efficiently on all devices.
|
||||
#
|
||||
ARCH_CLASS = armv7
|
||||
# Xcode 4.5 dropped support for the ARMv6.
|
||||
#
|
||||
# ARMv8 (arm64) devices: iPhone 5S
|
||||
# ARMv7s devices: iPhone 5 and 5C, iPad Gen 4
|
||||
# ARMv7 devices: iPhone 3GS, 4 and 4S, iPod Touch Gen 3 to 5
|
||||
# iPad Gen 1 to 3, iPad Mini, Apple TV Gen 2 and 3
|
||||
# ARMv6 devices: iPhone 1 and 3G, iPod Touch Gen 1 and 2
|
||||
|
||||
#ARCH_CLASS = arm64
|
||||
#ARCH_CLASS = armv7s arm64
|
||||
ARCH_CLASS = armv7 armv7s arm64
|
||||
#ARCH_CLASS = armv7 armv7s
|
||||
#ARCH_CLASS = armv7
|
||||
#ARCH_CLASS = armv6 armv7
|
||||
#ARCH_CLASS = armv6
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# CONFIG_SITE.Common.iosCommon
|
||||
#
|
||||
# $Revision-Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Site-specific settings for Apple iOS builds
|
||||
#-------------------------------------------------------
|
||||
@@ -12,16 +11,20 @@
|
||||
#IOS_VERSION = 4.1
|
||||
#IOS_VERSION = 4.2
|
||||
#IOS_VERSION = 4.3
|
||||
IOS_VERSION = 5.0
|
||||
#IOS_VERSION = 5.0
|
||||
#IOS_VERSION = 5.1
|
||||
#IOS_VERSION = 6.0
|
||||
#IOS_VERSION = 6.1
|
||||
IOS_VERSION = 7.0
|
||||
|
||||
|
||||
# Which compiler to use:
|
||||
# CLANG is preferred for recent versions of Xcode
|
||||
# LLVM uses the llvm-gcc and llvm-g++ compilers
|
||||
# CLANG is required for Xcode 5.0 and later
|
||||
# LLVM_GNU uses the llvm-gcc and llvm-g++ compilers
|
||||
# GNU is needed for older versions of Xcode
|
||||
|
||||
COMPILER = CLANG
|
||||
#COMPILER = LLVM
|
||||
#COMPILER = LLVM_GNU
|
||||
#COMPILER = GNU
|
||||
|
||||
|
||||
|
||||
@@ -38,3 +38,4 @@ COMMANDLINE_LIBRARY = READLINE
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
@@ -38,3 +38,4 @@ COMMANDLINE_LIBRARY = READLINE
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
@@ -20,6 +20,7 @@ VXWORKS_VERSION = 5.5
|
||||
#VXWORKS_VERSION = 6.6
|
||||
#VXWORKS_VERSION = 6.7
|
||||
#VXWORKS_VERSION = 6.8
|
||||
#VXWORKS_VERSION = 6.9
|
||||
|
||||
|
||||
# Sites may override the following path for a particular host
|
||||
@@ -40,6 +41,7 @@ WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
|
||||
#WORKBENCH_VERSION = 2.6
|
||||
#WORKBENCH_VERSION = 3.0
|
||||
#WORKBENCH_VERSION = 3.2
|
||||
#WORKBENCH_VERSION = 3.3
|
||||
|
||||
|
||||
# Utilities Version number, required from vxWorks 6.8 and later
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# CONFIG_SITE.windows-x64-mingw.windows-x64-mingw
|
||||
#
|
||||
# $Revision-Id$
|
||||
#
|
||||
# Site Specific definitions for windows-x64-mingw target
|
||||
# Only the local epics system manager should modify this file
|
||||
|
||||
# Prefix for mingw compiler from cygwin
|
||||
#CMPLR_PREFIX = x86_64-w64-mingw32-
|
||||
@@ -3,15 +3,192 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
|
||||
<title>EPICS Base R3.14.12.2-DEV Release Notes</title>
|
||||
<title>EPICS Base R3.14.12.4-pre1 Release Notes</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1 align="center">EPICS Base Release 3.14.12.2-DEV</h1>
|
||||
<h1 align="center">EPICS Base Release 3.14.12.4-pre1</h1>
|
||||
|
||||
<h2 align="center">Changes between 3.14.12.3 and 3.14.12.4</h2>
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Added support for 64-bit Cygwin and MinGW targets</h3>
|
||||
|
||||
<p>Both windows-x64-mingw and cygwin-x86_64 build targets are now provided.</p>
|
||||
|
||||
<h3>CAS: GDD Reference Count Underflow</h3>
|
||||
|
||||
<p>Thanks to Bruce Hill a source of an underflow in a GDD reference count in the
|
||||
CAS code has been fixed.</p>
|
||||
|
||||
<h3>Support for Apple Xcode 5.0</h3>
|
||||
|
||||
<p>This adds the ability to build for iOS 7.0 and the ARMv8 64-bit CPU on the
|
||||
newest iPhone 5S device.</p>
|
||||
|
||||
<h3>Reading TSEL field</h3>
|
||||
|
||||
<p>The TSEL link field has two complementary uses; it is read to fetch a
|
||||
time-stamp event number for the TSE field, or if pointed to the .TIME field of
|
||||
another record the record's timestamp is copied directly from the target record.
|
||||
However with the latter usage if the TSEL link is itself read back instead of
|
||||
pointing to the .TIME field the link appears to have changed to point to the VAL
|
||||
field. This is due to an internal detail, and makes it impossible to save the
|
||||
TSEL field's value using autosave. This has been fixed, and now the TSEL field
|
||||
should always read back the same PV that it was pointed to.</p>
|
||||
|
||||
<h3>dbLoadTemplate variable limits adjustable</h3>
|
||||
|
||||
<p>The <tt>dbLoadTemplate</tt> command used to allocate a fixed amount of memory
|
||||
for the template macro values that it used to 5000 bytes, and also limited the
|
||||
number of variables that could defined to 100. These limits can now be changed
|
||||
at runtime using the variable <tt>dbTemplateMaxVars</tt> which sets the maximum
|
||||
number of macro variables that can be used; the amount of memory allocated for
|
||||
value storage is 50 times this number. This variable is registered as an iocsh
|
||||
variable in the base.dbd file, and can be adjusted as necessary before each
|
||||
individual call to <tt>dbLoadTemplate</tt>.</p>
|
||||
|
||||
<p>The code now checks for and prevents any attempt to define more than the set
|
||||
number of variables, but it does not check for overruns of the storage buffer.
|
||||
This means that template files which define many long macro value strings could
|
||||
still cause a buffer overflow and crash the IOC at startup, but increasing the
|
||||
variable is all that is needed to allow that template file to be loaded.</p>
|
||||
|
||||
<h3>Improvements to dbpf</h3>
|
||||
|
||||
<p>It is now possible to use the <tt>dbpf</tt> command to put a long string
|
||||
value into a UCHAR array field, previously only CHAR arrays were supported by
|
||||
this command even though through Channel Access could put a long string to
|
||||
either type. The error message printed by <tt>dbpf</tt> when a value conversion
|
||||
fails has also been significantly improved.</p>
|
||||
|
||||
<h3>Support for VxWorks 6.9</h3>
|
||||
|
||||
<p>Various changes have been made that were needed to allow Base to build and
|
||||
run properly on VxWorks 6.9.</p>
|
||||
|
||||
<h3>Improvements to aToIPAddr()</h3>
|
||||
|
||||
<p>The libCom routine aToIPAddr() and the vxWorks implementation of the
|
||||
associated hostToIPAddr() function have been modified to be able to look up
|
||||
hostnames that begin with one or more digits. The epicsSockResolveTest program
|
||||
was added to check this functionality.</p>
|
||||
|
||||
<h4>Added osdFindSymbol for Windows</h4>
|
||||
|
||||
<p>Dirk Zimoch implemented the epicsLoadLibrary(), epicsLoadError() and
|
||||
epicsFindSymbol() routines for Windows OS targets.</p>
|
||||
|
||||
<h4>More dbStatic commands accept "" or "*" to mean 'all'</h4>
|
||||
|
||||
<p>The IOC commands dbDumpRecordType, dbDumpMenu and dbDumpRecord will now
|
||||
accept either an empty string or any string beginning with an asterisk '*' to
|
||||
mean all record types or menus. Previously the 'all' option for these commands
|
||||
required passing in a NULL value, which could be done from the vxWorks shell but
|
||||
was not possible from iocsh.</p>
|
||||
|
||||
<h4>VxWorks sysAtReboot Registration</h4>
|
||||
|
||||
<p>The increasing intelligence of the GNU compiler and linker broke the method
|
||||
that was being used by the VxWorks code to register a reboot hook that can close
|
||||
down TCP connections nicely before the network stack gets disabled. This has
|
||||
been fixed and no longer uses a C++ static contructor to execute that code.</p>
|
||||
|
||||
<h4>IOCS_APPL_TOP and INSTALL_LOCATION</h4>
|
||||
|
||||
<p>An IOC application that sets INSTALL_LOCATION in its configure/CONFIG_SITE
|
||||
file no longer has to set IOCS_APPL_TOP there as well, unless the IOC uses a
|
||||
different path than the build host to reach the application's top directory in
|
||||
its filesystem. The IOCS_APPL_TOP variable now defaults to the value of
|
||||
INSTALL_LOCATION, so setting the latter automatically sets the former. This
|
||||
change fixes <a href="https://bugs.launchpad.net/bugs/1165257">Launchpad bug
|
||||
1165257</a>.</p>
|
||||
|
||||
<h4>devLibVME.h</h4>
|
||||
|
||||
<p>Moved the declaration of bcopyLongs() from this header into RTEMS/osdVME.h.
|
||||
Its original location broke the build for vxWorks 6.9 (the int nlongs argument
|
||||
becomes size_t in 6.9, thus conflicting with this declaration). The only local
|
||||
implementation of this routine is found in RTEMS/devLibVMEOSD.c, but it is not
|
||||
used anywhere in Base.</p>
|
||||
|
||||
<h4>Allow empty database files</h4>
|
||||
|
||||
<p>The IOC used to report an error if dbLoadRecords or dbLoadDatabase was asked
|
||||
to load an empty file or one containing just whitespace and/or comments. Such
|
||||
files are now permitted, simplifying the task of automated database generation
|
||||
programs which might discover they have nothing to output.</p>
|
||||
|
||||
<h4>High-Resolution Time Provider on MacOS</h4>
|
||||
|
||||
<p>MacOS does not provide the clock_gettime() API with CLOCK_REALTIME that other
|
||||
Posix systems implement, so we previously used gettimeofday() to fetch the
|
||||
current date & time from the OS. That older routine only provides the time with
|
||||
a resolution of 1 microsecond though, whereas clock_gettime() gives results with
|
||||
a nanosecond resolution. This release uses a new MachTime time provider on
|
||||
MacOS which uses the Mach Kernel's CALENDAR_CLOCK service to fetch the time, and
|
||||
provides nanosecond resolution.</p>
|
||||
|
||||
<h4>Time drift in periodic scans</h4>
|
||||
|
||||
<p>The implementation of the periodic scan code has been modified to remove
|
||||
long-term drift associated with OS thread sheduling. The new code keeps scan
|
||||
times much more closely tied to the system clock tick, only allowing the scan
|
||||
period to drift if the record processing time takes longer to execute than the
|
||||
interval between scans. If this happens the scan thread is made to wait for an
|
||||
additional half-period but at most 1 second before the records are scanned
|
||||
again, to allow lower priority threads some time to process on a preemptive
|
||||
priority scheduled OS. After 10 repeated over-runs a warning will be logged,
|
||||
with an increasing delay between messages up to hourly.</p>
|
||||
|
||||
<p>This fixes <a href="https://bugs.launchpad.net/bugs/597054">launchpad bug
|
||||
597054</a>.</p>
|
||||
|
||||
<h2 align="center">Changes between 3.14.12.2 and 3.14.12.3</h2>
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
<h4>Hex literals in CALC expressions</h4>
|
||||
|
||||
<p>In previous releases, CALC expressions could contain hexadecimal literal
|
||||
integers on a target if the OS implementation of strtod() allows them (the
|
||||
vxWorks implementation does not). Now hex literal integers can be used in CALC
|
||||
expressions on all architectures. Hexadecimal floating point literals may have
|
||||
worked on some architectures in the past, but will no longer be accepted.</p>
|
||||
|
||||
<h4>CAS: Added propertyEventMask support</h4>
|
||||
|
||||
<p>Server tools should now be able to detect subscriptions to and send updates
|
||||
for DBE_PROPERTY events, using a casEventMask value returned by the new
|
||||
caServer::propertyEventMask() method.</p>
|
||||
|
||||
<h4>caRepeater now built by default</h4>
|
||||
|
||||
<p>Previously caRepeater was only built for host architectures, so builds for
|
||||
cross-compiled but workstation-type targets like linux-arm did not build it.
|
||||
Explicit exceptions prevent it being built on architectures like vxWorks, RTEMS
|
||||
and iOS which do not support normal executable programs.</p>
|
||||
|
||||
<h4>Array Subroutine (aSub) record type fixes</h4>
|
||||
|
||||
<ul>
|
||||
<li>Changing the number of valid elements in a VALx field now triggers
|
||||
monitors</li>
|
||||
<li>The NEVx fields now post monitors, following the EFLG setting</li>
|
||||
<li>The artificial limit of 10,000,000 array elements has been removed</li>
|
||||
</ul>
|
||||
|
||||
<h4>Problem with NAN values in MLST/ALST fields</h4>
|
||||
|
||||
<p>The ai, ao, calc, calcout, dfanout, sel and sub record types could stop
|
||||
posting monitors if they got NAN values in their MLST or ALST fields. A change
|
||||
has been included so this should no longer be the case.</p>
|
||||
|
||||
<h4>MacOS build defaults changed</h4>
|
||||
|
||||
<p>The default build settings for darwin-x86 targets have been changed to match
|
||||
the latest version of XCode; see configure/os/CONFIG_SITE.Common.darwin-x86
|
||||
if you need to revert back to building with GCC or to include the i386 CPU
|
||||
architecture.</p>
|
||||
|
||||
<h4>Build problem with db dependencies</h4>
|
||||
|
||||
@@ -28,19 +205,55 @@ itself have now been added. Both the Shell and Perl versions of the startup
|
||||
EpicsHostArch scripts now recognize both arm6l and arm7l CPUs and return the
|
||||
generic linux-arm host architecture name for them.</p>
|
||||
|
||||
<h4>New Microblaze Target Architecture</h4>
|
||||
|
||||
<p>A new cross-compiled target architecture is included for the Xilinx
|
||||
Microblaze FPGA soft-core CPU architecture running Linux.</p>
|
||||
|
||||
<h4>Win32 Numeric string to enum/menu/device conversions</h4>
|
||||
|
||||
<p>Microsoft's C run-time library has a bug in the sscanf() function such that
|
||||
the "%n" format specifier does not always work. The string to enum, menu and
|
||||
device conversion functions have been modified to avoid this problem, but a
|
||||
numeric string will no longer be converted properly on any architecture if it
|
||||
has trailing whitespace characters.</p>
|
||||
|
||||
<h4>Launchpad Bugs Resolved</h4>
|
||||
|
||||
<p>The following are links to bugs in the Launchpad bug tracker that have been
|
||||
fixed in this release:</p>
|
||||
|
||||
<ul>
|
||||
<li>1090009
|
||||
<a href="https://bugs.launchpad.net/bugs/1090009">
|
||||
osdSufficentSpaceInPoolQuery fails on vxWorks 2 GB system</a></li>
|
||||
<li>999167
|
||||
<a href="https://launchpad.net/bugs/999167">
|
||||
Missing epicsShareFunc for casStatsFetch</a></li>
|
||||
<li>950555
|
||||
<a href="https://launchpad.net/bugs/950555">
|
||||
String substitution removes part of path when linking versioned shared
|
||||
libraries</a></li>
|
||||
<li>907761
|
||||
<a href="https://launchpad.net/bugs/907761">
|
||||
reading only 1st char of link in "long string" ($) syntax fails in read
|
||||
error</a></li>
|
||||
<li>903448
|
||||
<a href="https://launchpad.net/bugs/903448">
|
||||
RHEL5 nss ldap update cause stack size related failure</a></li>
|
||||
RHEL5 nss ldap update cause stack size related failure</a>
|
||||
<p>
|
||||
This bug fix changed the stack sizes for both Posix and Windows targets as
|
||||
follows:</p>
|
||||
<table>
|
||||
<tr><th>epicsThreadStackSizeClass</th><th>New Stack Size</th></tr>
|
||||
<tr><td>epicsThreadStackSmall</td>
|
||||
<td>0x10000 × sizeof (void *)</td></tr>
|
||||
<tr><td>epicsThreadStackMedium</td>
|
||||
<td>0x20000 × sizeof (void *)</td></tr>
|
||||
<tr><td>epicsThreadStackBig</td>
|
||||
<td>0x40000 × sizeof (void *)</td></tr>
|
||||
</table></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h4>Calcout and Seq record timestamps</h4>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/* share/src/as/asDbLib.c */
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2012 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 Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* Author: Marty Kraimer Date: 02-11-94*/
|
||||
@@ -69,18 +67,23 @@ static long asDbAddRecords(void)
|
||||
|
||||
int epicsShareAPI asSetFilename(const char *acf)
|
||||
{
|
||||
if(pacf) free ((void *)pacf);
|
||||
if(acf) {
|
||||
pacf = calloc(1,strlen(acf)+1);
|
||||
if(!pacf) {
|
||||
errMessage(0,"asSetFilename calloc failure");
|
||||
} else {
|
||||
strcpy(pacf,acf);
|
||||
}
|
||||
if (pacf)
|
||||
free (pacf);
|
||||
if (acf) {
|
||||
pacf = calloc(1, strlen(acf)+1);
|
||||
if (!pacf) {
|
||||
errMessage(0, "asSetFilename calloc failure");
|
||||
} else {
|
||||
strcpy(pacf, acf);
|
||||
if (*pacf != '/' && !strchr(pacf, ':')) {
|
||||
printf("asSetFilename: Warning - relative paths won't usually "
|
||||
"work\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pacf = NULL;
|
||||
pacf = NULL;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epicsShareAPI asSetSubstitutions(const char *substitutions)
|
||||
|
||||
0
src/as/asHost.rc
Executable file → Normal file
0
src/as/asHost.rc
Executable file → Normal file
0
src/as/asIoc.rc
Executable file → Normal file
0
src/as/asIoc.rc
Executable file → Normal file
@@ -25,8 +25,6 @@
|
||||
#include "cac.h"
|
||||
#include "sgAutoPtr.h"
|
||||
|
||||
casgRecycle::~casgRecycle () {}
|
||||
|
||||
CASG::CASG ( epicsGuard < epicsMutex > & guard, ca_client_context & cacIn ) :
|
||||
client ( cacIn ), magic ( CASG_MAGIC )
|
||||
{
|
||||
@@ -38,12 +36,13 @@ CASG::~CASG ()
|
||||
}
|
||||
|
||||
void CASG::destructor (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
|
||||
if ( this->verify ( guard ) ) {
|
||||
this->reset ( guard );
|
||||
this->reset ( cbGuard, guard );
|
||||
this->client.uninstallCASG ( guard, *this );
|
||||
this->magic = 0;
|
||||
}
|
||||
@@ -127,36 +126,37 @@ int CASG::block (
|
||||
delay = cur_time - beg_time;
|
||||
}
|
||||
|
||||
this->reset ( guard );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void CASG::reset (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
this->destroyCompletedIO ( guard );
|
||||
this->destroyPendingIO ( guard );
|
||||
this->destroyCompletedIO ( cbGuard, guard );
|
||||
this->destroyPendingIO ( cbGuard, guard );
|
||||
}
|
||||
|
||||
// lock must be applied
|
||||
void CASG::destroyCompletedIO (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
syncGroupNotify * pNotify;
|
||||
while ( ( pNotify = this->ioCompletedList.get () ) ) {
|
||||
pNotify->destroy ( guard, * this );
|
||||
pNotify->destroy ( cbGuard, guard );
|
||||
}
|
||||
}
|
||||
|
||||
void CASG::destroyPendingIO (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
|
||||
pNotify->cancel ( guard );
|
||||
pNotify->cancel ( cbGuard, guard );
|
||||
// cancel must release the guard while
|
||||
// canceling put callbacks so we
|
||||
// must double check list membership
|
||||
@@ -166,7 +166,7 @@ void CASG::destroyPendingIO (
|
||||
else {
|
||||
this->ioCompletedList.remove ( *pNotify );
|
||||
}
|
||||
pNotify->destroy ( guard, *this );
|
||||
pNotify->destroy ( cbGuard, guard );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,10 +201,11 @@ void CASG::show (
|
||||
}
|
||||
|
||||
bool CASG::ioComplete (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
this->destroyCompletedIO ( guard );
|
||||
this->destroyCompletedIO ( cbGuard, guard );
|
||||
return this->ioPendingList.count () == 0u;
|
||||
}
|
||||
|
||||
@@ -212,9 +213,9 @@ void CASG::put ( epicsGuard < epicsMutex > & guard, chid pChan,
|
||||
unsigned type, arrayElementCount count, const void * pValue )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
sgAutoPtr < syncGroupWriteNotify > pNotify ( guard, *this, this->ioPendingList );
|
||||
sgAutoPtr < syncGroupWriteNotify > pNotify ( guard, *this );
|
||||
pNotify = syncGroupWriteNotify::factory (
|
||||
this->freeListWriteOP, *this, pChan );
|
||||
this->freeListWriteOP, *this, & CASG :: recycleWriteNotifyIO, pChan );
|
||||
pNotify->begin ( guard, type, count, pValue );
|
||||
pNotify.release ();
|
||||
}
|
||||
@@ -223,9 +224,9 @@ void CASG::get ( epicsGuard < epicsMutex > & guard, chid pChan,
|
||||
unsigned type, arrayElementCount count, void *pValue )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
sgAutoPtr < syncGroupReadNotify > pNotify ( guard, *this, this->ioPendingList );
|
||||
sgAutoPtr < syncGroupReadNotify > pNotify ( guard, *this );
|
||||
pNotify = syncGroupReadNotify::factory (
|
||||
this->freeListReadOP, *this, pChan, pValue );
|
||||
this->freeListReadOP, *this, & CASG :: recycleReadNotifyIO, pChan, pValue );
|
||||
pNotify->begin ( guard, type, count );
|
||||
pNotify.release ();
|
||||
}
|
||||
@@ -241,20 +242,20 @@ void CASG::completionNotify (
|
||||
}
|
||||
}
|
||||
|
||||
void CASG::recycleSyncGroupWriteNotify (
|
||||
epicsGuard < epicsMutex > & guard, syncGroupWriteNotify & io )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
this->freeListWriteOP.release ( & io );
|
||||
}
|
||||
|
||||
void CASG::recycleSyncGroupReadNotify (
|
||||
epicsGuard < epicsMutex > & guard, syncGroupReadNotify & io )
|
||||
void CASG :: recycleReadNotifyIO ( epicsGuard < epicsMutex > & guard,
|
||||
syncGroupReadNotify & io )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
this->freeListReadOP.release ( & io );
|
||||
}
|
||||
|
||||
void CASG :: recycleWriteNotifyIO ( epicsGuard < epicsMutex > & guard,
|
||||
syncGroupWriteNotify & io )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
this->freeListWriteOP.release ( & io );
|
||||
}
|
||||
|
||||
int CASG :: printFormated ( const char *pformat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
@@ -295,13 +296,6 @@ void CASG::exception (
|
||||
}
|
||||
}
|
||||
|
||||
void * CASG::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void CASG::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -165,7 +165,8 @@ $Date$</span></small></p>
|
||||
<li><a href="#ca_pend_io">block for certain requests to complete</a></li>
|
||||
<li><a href="#ca_test_io">test to see if certain requests have
|
||||
completed</a></li>
|
||||
<li><a href="#ca_pend_event">process CA client library background activities</a></li>
|
||||
<li><a href="#ca_pend_event">process CA client library background
|
||||
activities</a></li>
|
||||
<li><a href="#ca_flush_io">flush outstanding requests to the server</a></li>
|
||||
<li><a href="#ca_add_exception_event">replace the default exception
|
||||
handler</a></li>
|
||||
@@ -454,26 +455,20 @@ Environment</a> below.</p>
|
||||
|
||||
<h3><a name="firewall">Firewalls</a></h3>
|
||||
|
||||
<p>If you want channel access clients on a machine to be able to see
|
||||
beacons and replies to broadcast PV search requests you need to permit
|
||||
inbound UDP packets with source port EPICS_CA_SERVER_PORT (default is 5064)
|
||||
or destination port EPICS_CA_REPEATER_PORT (default is 5065). On systems
|
||||
using iptables this can be accomplished by rules like</p>
|
||||
|
||||
<pre>
|
||||
-A INPUT -s 192.168.0.0/22 -p udp --sport 5064 -j ACCEPT
|
||||
-A INPUT -s 192.168.0.0/22 -p udp --dport 5065 -j ACCEPT
|
||||
</pre>
|
||||
<p>If you want channel access clients on a machine to be able to see beacons
|
||||
and replies to broadcast PV search requests, you need to permit inbound UDP
|
||||
packets with source port EPICS_CA_SERVER_PORT (default is 5064) or destination
|
||||
port EPICS_CA_REPEATER_PORT (default is 5065). On systems using iptables this
|
||||
can be accomplished by rules like</p>
|
||||
<pre> -A INPUT -s 192.168.0.0/22 -p udp --sport 5064 -j ACCEPT
|
||||
-A INPUT -s 192.168.0.0/22 -p udp --dport 5065 -j ACCEPT</pre>
|
||||
|
||||
<p>If you want channel access servers (e.g. "soft IOCs") on a machine to be
|
||||
able to see clients you need to permit inbound TCP or UDP packets with source
|
||||
port EPICS_CA_SERVER_PORT (default is 5064). On systems using iptables this
|
||||
can be accomplished by rules like</p>
|
||||
|
||||
<pre>
|
||||
-A INPUT -s 192.168.0.0/22 -p udp --dport 5064 -j ACCEPT
|
||||
-A INPUT -s 192.168.0.0/22 -p tcp --dport 5064 -j ACCEPT
|
||||
</pre>
|
||||
able to be seen by clients, you need to permit inbound TCP or UDP packets with
|
||||
destination port EPICS_CA_SERVER_PORT (default is 5064). On systems using
|
||||
iptables this can be accomplished by rules like</p>
|
||||
<pre> -A INPUT -s 192.168.0.0/22 -p udp --dport 5064 -j ACCEPT
|
||||
-A INPUT -s 192.168.0.0/22 -p tcp --dport 5064 -j ACCEPT</pre>
|
||||
|
||||
<p>In all cases the "-s 192.168.0.0/22" specifies the range of addresses from
|
||||
which you wish to accept packets.</p>
|
||||
@@ -498,9 +493,8 @@ broadcast address of that subnet is added to the list. For each point to point
|
||||
interface found, the destination address of that link is added to the list.
|
||||
This automatic server address list initialization can be disabled if the EPICS
|
||||
environment variable EPICS_CA_AUTO_ADDR_LIST exists and its value is either
|
||||
of "no" or "NO". The typical default is to enable network interface
|
||||
introspection driven initialization with EPICS_CA_AUTO_ADDR_LIST set to "YES"
|
||||
or "yes".</p>
|
||||
"no" or "NO". The typical default is to enable network interface introspection
|
||||
driven initialization with EPICS_CA_AUTO_ADDR_LIST set to "YES" or "yes".</p>
|
||||
|
||||
<p>Following network interface introspection, any IP addresses specified in the
|
||||
EPICS environment variable EPICS_CA_ADDR_LIST are added to the list of
|
||||
@@ -511,8 +505,8 @@ CA servers unless a CA proxy (gateway) is installed. The addresses in
|
||||
EPICS_CA_ADDR_LIST may be dotted IP addresses or host names if the local OS has
|
||||
support for host name to IP address translation. When multiple names are added
|
||||
to EPICS_CA_ADDR_LIST they must be separated by white space. There is no
|
||||
requirement that the addresses specified in the EPICS_CA_ADDR_LIST be
|
||||
broadcast addresses, but this will often be the most convenient choice.</p>
|
||||
requirement that the addresses specified in the EPICS_CA_ADDR_LIST be broadcast
|
||||
addresses, but this will often be the most convenient choice.</p>
|
||||
|
||||
<p>For any IP addresses specified in the EPICS environment variable
|
||||
EPICS_CA_NAME_SERVERS, TCP connections are opened and used for CA client name
|
||||
@@ -560,7 +554,7 @@ default to EPICS_CA_SERVER_PORT.</p>
|
||||
<p>Frequently vxWorks systems boot by default with routes limiting access only
|
||||
to the local subnet. If a EPICS system is operating in a WAN environment it may
|
||||
be necessary to configure routes into the vxWorks system which enable a vxWorks
|
||||
based CA server to respond to requests originating outside it's subnet. These
|
||||
based CA server to respond to requests originating outside its subnet. These
|
||||
routing restrictions can also apply to vxWorks base CA clients communicating
|
||||
with off subnet servers. An EPICS system manager can implement an rudimentary,
|
||||
but robust, form of access control for a particular host by not providing
|
||||
@@ -865,8 +859,8 @@ the contents of EPICS_CA_ADDR_LIST is used to augment the list. Otherwise, the
|
||||
list is not augmented.</p>
|
||||
|
||||
<p>The EPICS_CAS_BEACON_PORT parameter specifies the destination port for
|
||||
server beacons. The only exception to this occurs when ports are specified
|
||||
in EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If
|
||||
server beacons. The only exception to this occurs when ports are specified in
|
||||
EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If
|
||||
EPICS_CAS_BEACON_PORT is not specified then beacons are sent to the port
|
||||
specified in EPICS_CA_REPEATER_PORT.</p>
|
||||
|
||||
@@ -874,7 +868,7 @@ specified in EPICS_CA_REPEATER_PORT.</p>
|
||||
|
||||
<p>The parameter EPICS_CAS_INTF_ADDR_LIST allows a ca server to bind itself to,
|
||||
and therefore accept messages only over, a limited set of the local host's
|
||||
network interfaces (each specified by it's IP address). On UNIX systems type
|
||||
network interfaces (each specified by its IP address). On UNIX systems type
|
||||
"netstat -i" (type "ipconfig" on windows) to see a list of the local host's
|
||||
network interfaces. Specifically, UDP search messages addressed to both the IP
|
||||
addresses in EPICS_CAS_INTF_ADDR_LIST and also to the broadcast addresses of
|
||||
@@ -1885,7 +1879,7 @@ order to connect to this new beacon-out-of-range server. The typical situation
|
||||
where a client would not see the server's beacon might be when the client isnt
|
||||
on the same IP subnet as the server, and the client's EPICS_CA_ADDR_LIST was
|
||||
modified to include a destination address for the server, but the server's
|
||||
beacon address list was not modified so that it's beacons are received by the
|
||||
beacon address list was not modified so that its beacons are received by the
|
||||
client.</p>
|
||||
|
||||
<h4><a name="Server1">A Server's IP Address Was Changed</a></h4>
|
||||
@@ -1938,8 +1932,8 @@ Termination Appear to be Ignored</a></h3>
|
||||
<p>Short lived CA client applications that issue a CA put request and then
|
||||
immediately exit the process (return from <code>main</code> or call
|
||||
<code>exit</code>) may find that there request isn't executed. To guarantee
|
||||
that the request is sent call <code>ca_flush</code> followed by
|
||||
<code>ca_context_destroy</code> prior to terminating the process.</p>
|
||||
that the request is sent call <code>ca_flush_io()</code> followed by
|
||||
<code>ca_context_destroy()</code> prior to terminating the process.</p>
|
||||
|
||||
<h3><a name="Problems">ENOBUFS Messages</a></h3>
|
||||
|
||||
@@ -2017,8 +2011,8 @@ OS and even between different versions of the same OS.</p>
|
||||
<p>If the subscription update producer in the server produces subscription
|
||||
updates faster than the subscription update consumer in the client consumes
|
||||
them, then events have to be discarded if the buffering in the server
|
||||
isn't allowed to grow to an infinite size. This is a law of nature
|
||||
- based on queuing theory of course.</p>
|
||||
isn't allowed to grow to an infinite size. This is a law of nature –
|
||||
based on queuing theory of course.</p>
|
||||
|
||||
<p>What is done depends on the version of the CA server. All server versions
|
||||
place quotas on the maximum number of subscription updates allowed on the
|
||||
@@ -2040,10 +2034,10 @@ server to resume with subscription updates. This prevents slow clients from
|
||||
getting time warped, but also guarantees that intervening events are discarded
|
||||
until the slow client catches up.</p>
|
||||
|
||||
<p>There is currently no message on the IOC's console when a
|
||||
particular client is slow on the uptake. A message of this type used to exist
|
||||
many years ago, but it was a source of confusion (and what we will call
|
||||
message noise) so it was removed. </p>
|
||||
<p>There is currently no message on the IOC's console when a particular client
|
||||
is slow on the uptake. A message of this type used to exist many years ago, but
|
||||
it was a source of confusion (and what we will call message noise) so it was
|
||||
removed.</p>
|
||||
|
||||
<p>There is unfortunately no field in the protocol allowing the server to
|
||||
indicate that an intervening subscription update was discarded. We should
|
||||
@@ -2320,7 +2314,7 @@ int main ( int argc, char ** argv )
|
||||
|
||||
<p>Certain CA client initiated requests asynchronously execute an application
|
||||
supplied call back in the client process when a response arrives. The functions
|
||||
ca_put_callback, ca_get_callback, and ca_add_event all request notification of
|
||||
ca_put_callback, ca_get_callback, and ca_create_subscription all request notification of
|
||||
asynchronous completion via this mechanism. The <code>event_handler_args
|
||||
</code>structure is passed <em>by value</em> to the application supplied
|
||||
callback. In this structure the <code>dbr</code> field is a void pointer to any
|
||||
@@ -2355,8 +2349,8 @@ void myCallback ( struct event_handler_args args )
|
||||
<h3><a name="Channel1">Channel Access Exceptions</a></h3>
|
||||
|
||||
<p>When the server detects a failure, and there is no client call back function
|
||||
attached to the request, an exception handler is executed in the client.
|
||||
The default exception handler prints a message on the console and exits if the
|
||||
attached to the request, an exception handler is executed in the client. The
|
||||
default exception handler prints a message on the console and exits if the
|
||||
exception condition is severe. Certain internal exceptions within the CA client
|
||||
library, and failures detected by the SEVCHK macro may also cause the exception
|
||||
handler to be invoked. To modify this behavior see <a
|
||||
@@ -2423,12 +2417,12 @@ same process).</p>
|
||||
all OS (in past releases the library was thread safe only on vxWorks). When the
|
||||
client library is initialized the programmer may specify if preemptive callback
|
||||
is to be enabled. Preemptive callback is disabled by default. If preemptive
|
||||
callback is enabled, then the user's callback functions might be called by
|
||||
CA's auxiliary threads when the main initiating channel access thread is not
|
||||
inside of a function in the channel access client library. Otherwise, the
|
||||
user's callback functions will be called only when the main initiating channel
|
||||
access thread is executing inside of the CA client library. When the CA client
|
||||
library invokes a user's callback function, it will always wait for the current
|
||||
callback is enabled, then the user's callback functions might be called by CA's
|
||||
auxiliary threads when the main initiating channel access thread is not inside
|
||||
of a function in the channel access client library. Otherwise, the user's
|
||||
callback functions will be called only when the main initiating channel access
|
||||
thread is executing inside of the CA client library. When the CA client library
|
||||
invokes a user's callback function, it will always wait for the current
|
||||
callback to complete prior to executing another callback function. Programmers
|
||||
enabling preemptive callback should be familiar with using mutex locks to
|
||||
create a reliable multi-threaded program.</p>
|
||||
@@ -2457,10 +2451,10 @@ address space (process) to be independent of each other. For example, the
|
||||
database CA links and the sequencer are designed to not use the same CA client
|
||||
library threads, network circuits, and data structures. Each thread that calls
|
||||
<a href="#ca_context_create">ca_context_create()</a> for the first time either
|
||||
directly or implicitly when calling any CA library function for the first
|
||||
time, creates a CA client library context. A CA client library context contains
|
||||
all of the threads, network circuits, and data structures required to connect
|
||||
and communicate with the channels that a CA client application has created. The
|
||||
directly or implicitly when calling any CA library function for the first time,
|
||||
creates a CA client library context. A CA client library context contains all
|
||||
of the threads, network circuits, and data structures required to connect and
|
||||
communicate with the channels that a CA client application has created. The
|
||||
priority of auxiliary threads spawned by the CA client library are at fixed
|
||||
offsets from the priority of the thread that called <a
|
||||
href="#ca_context_create">ca_context_create()</a>. An application specific
|
||||
@@ -2530,9 +2524,9 @@ questionable practice for the following reasons.</p>
|
||||
<ul>
|
||||
<li>The vxWorks shell thread runs at the very highest priority in the system
|
||||
and therefore socket calls are made at a priority that is above the
|
||||
priority of tNetTask - a practice that has caused the WRS IP kernel
|
||||
to get sick in the past. That symptom was observed some time ago, but we
|
||||
don't know if WRS has fixed the problem.</li>
|
||||
priority of tNetTask. This has caused problems with the WRS IP kernel in
|
||||
the past. That symptom was observed some time ago, but we don't know if
|
||||
WRS has fixed the problem.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>The vxWorks shell thread runs at the very highest priority in the system
|
||||
@@ -2648,7 +2642,7 @@ get called in the correct order.</p>
|
||||
resources used by the client library such as sockets and allocated memory are
|
||||
automatically released by the system when the process exits and
|
||||
ca_context_destroy() hasn't been called, but on light weight systems such as
|
||||
vxWorks or RTEMS no cleanup occurs unless the application call
|
||||
vxWorks or RTEMS no cleanup occurs unless the application calls
|
||||
ca_context_destroy().</p>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -2661,16 +2655,10 @@ ca_context_destroy().</p>
|
||||
|
||||
<h3><code><a name="ca_create_channel">ca_create_channel()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
typedef void ( *pCallBack ) (
|
||||
struct connection_handler_args );
|
||||
int ca_create_channel
|
||||
(
|
||||
const char *PROCESS_VARIABLE_NAME,
|
||||
caCh *USERFUNC,
|
||||
void *PUSER,
|
||||
capri priority,
|
||||
chid *PCHID
|
||||
);</pre>
|
||||
typedef void ( caCh ) (struct connection_handler_args);
|
||||
int ca_create_channel (const char *PVNAME,
|
||||
caCh *USERFUNC, void *PUSER,
|
||||
capri PRIORITY, chid *PCHID );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
@@ -2685,7 +2673,7 @@ on a channel.</p>
|
||||
|
||||
<p>The circuit may be initially connected or disconnected depending on the
|
||||
state of the network and the location of the channel. A channel will only enter
|
||||
a connected state after server's address is determined, and only if channel
|
||||
a connected state after the server's address is determined, and only if channel
|
||||
access successfully establishes a virtual circuit through the network to the
|
||||
server. Channel access routines that send a request to a server will return
|
||||
ECA_DISCONNCHID if the channel is currently disconnected.</p>
|
||||
@@ -2695,7 +2683,7 @@ a connected state.</p>
|
||||
<ul>
|
||||
<li>The first and simplest method requires that you call ca_pend_io(), and
|
||||
wait for successful completion, prior to using a channel that was created
|
||||
specifying a nil connection call back function pointer.</li>
|
||||
specifying a nill connection call back function pointer.</li>
|
||||
<li>The second method requires that you register a connection handler by
|
||||
supplying a valid connection callback function pointer. This connection
|
||||
handler is called whenever the connection state of the channel changes. If
|
||||
@@ -2719,7 +2707,7 @@ time.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>PROCESS_VARIABLE_NAME</code></dt>
|
||||
<dt><code>PVNAME</code></dt>
|
||||
<dd>A nil terminated process variable name string. EPICS process control
|
||||
function block database variable names are of the form "<record
|
||||
name>.<field name>". If the field name and the period separator
|
||||
@@ -2731,10 +2719,10 @@ time.</p>
|
||||
<dt><code>USERFUNC</code></dt>
|
||||
<dd>Optional address of the user's call back function to be run when the
|
||||
connection state changes. Casual users of channel access may decide to
|
||||
set this field to nil or 0 if they do not need to have a call back
|
||||
set this field to nill or 0 if they do not need to have a call back
|
||||
function run in response to each connection state change event.
|
||||
<p>The following structure is passed <em>by value </em>to the user's
|
||||
connection connection callback function. The <code>op</code> field will
|
||||
connection callback function. The <code>op</code> field will
|
||||
be set by the CA client library to <code>CA_OP_CONN_UP</code> when the
|
||||
channel connects, and to <code>CA_OP_CONN_DOWN</code> when the channel
|
||||
disconnects. See <code><a href="#ca_puser">ca_puser</a></code> if the
|
||||
@@ -2751,7 +2739,7 @@ time.</p>
|
||||
<dd>The value of this void pointer argument is retained in
|
||||
storage associated with the specified channel. See the MACROS manual page
|
||||
for reading and writing this field. Casual users of channel access may
|
||||
wish to set this field to nil or 0.</dd>
|
||||
wish to set this field to nill or 0.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PRIORITY</code></dt>
|
||||
@@ -2818,29 +2806,27 @@ subscriptions (monitors) registered with the channel.</p>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_put ( chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_array_put ( chtype TYPE,
|
||||
unsigned long COUNT,
|
||||
int ca_array_put ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, const void *PVALUE);
|
||||
typedef void ( *pCallBack ) (struct event_handler_args );
|
||||
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
|
||||
int ca_put_callback ( chtype TYPE,
|
||||
chid CHID, const void *PVALUE,
|
||||
pCallBack PFUNC, void *USERARG );
|
||||
int ca_array_put_callback ( chtype TYPE,
|
||||
unsigned long COUNT,
|
||||
caEventCallBackFunc PFUNC, void *USERARG );
|
||||
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, const void *PVALUE,
|
||||
pCallBack PFUNC, void *USERARG );</pre>
|
||||
caEventCallBackFunc PFUNC, void *USERARG );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Write a scalar or array value to a process variable.</p>
|
||||
|
||||
<p>When ca_array_put or ca_put are invoked the client will receive no response
|
||||
<p>When ca_put or ca_array_put are invoked the client will receive no response
|
||||
unless the request can not be fulfilled in the server. If unsuccessful an
|
||||
exception handler is run on the client side.</p>
|
||||
|
||||
<p>When ca_array_put_callback are invoked the user supplied asynchronous call
|
||||
back is called only after the initiated write operation, and all actions
|
||||
resulting from the initiating write operation, complete.</p>
|
||||
<p>When ca_put_callback or ca_array_put_callback are invoked the user supplied
|
||||
asynchronous call back is called only after the initiated write operation, and
|
||||
all actions resulting from the initiating write operation, complete.</p>
|
||||
|
||||
<p>If unsuccessful the call back function is invoked indicating failure status.
|
||||
</p>
|
||||
@@ -2861,7 +2847,7 @@ This allows several requests to be efficiently combined into one message.</p>
|
||||
<h4>Description (IOC Database Specific)</h4>
|
||||
|
||||
<p>A CA put request causes the record to process if the record's SCAN field is
|
||||
set to passive, and the field being written has it's process passive attribute
|
||||
set to passive, and the field being written has its process passive attribute
|
||||
set to true. If such a record is already processing when a put request is
|
||||
initiated the specified field is written immediately, and the record is
|
||||
scheduled to process again as soon as it finishes processing. Earlier instances
|
||||
@@ -2869,20 +2855,19 @@ of multiple put requests initiated while the record is being processing may be
|
||||
discarded, but the last put request initiated is always written and
|
||||
processed.</p>
|
||||
|
||||
<p>A CA put <span style="font-style: italic;">callback</span> request causes
|
||||
the record to process if the record's SCAN field is set to passive, and the
|
||||
field being written has it's process passive attribute set to true. For such a
|
||||
record, the user's put callback function is not called until after the record,
|
||||
and any records that the record links to, finish processing. If such a record
|
||||
is already processing when a put <span
|
||||
style="font-style: italic;">callback</span> request is initiated the put <span
|
||||
style="font-style: italic;">callback</span> request is postponed until the
|
||||
record, and any records it links to, finish processing.</p>
|
||||
<p>A CA put <em>callback</em> request causes the record to process if the
|
||||
record's SCAN field is set to passive, and the field being written has its
|
||||
process passive attribute set to true. For such a record, the user's put
|
||||
callback function is not called until after the record, and any records that
|
||||
the record links to, finish processing. If such a record is already processing
|
||||
when a put <em>callback</em> request is initiated the put <em>callback</em>
|
||||
request is postponed until the record, and any records it links to, finish
|
||||
processing.</p>
|
||||
|
||||
<p>If the record's SCAN field is not set to passive, or the field being written
|
||||
has it's process passive attribute set to false then the CA put or CA put
|
||||
callback request cause the specified field to be immediately written, but they
|
||||
do not cause the record to be processed.</p>
|
||||
has its process passive attribute set to false then the CA put or CA put
|
||||
<em>callback</em> request cause the specified field to be immediately written,
|
||||
but they do not cause the record to be processed.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
@@ -2948,18 +2933,19 @@ int ca_get ( chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_array_get ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, void *PVALUE );
|
||||
typedef void ( *pCallBack ) (struct event_handler_args );
|
||||
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
|
||||
int ca_get_callback ( chtype TYPE,
|
||||
chid CHID, pCallBack USERFUNC, void *USERARG);
|
||||
chid CHID,
|
||||
caEventCallBackFunc USERFUNC, void *USERARG);
|
||||
int ca_array_get_callback ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID,
|
||||
pCallBack USERFUNC, void *USERARG );</pre>
|
||||
caEventCallBackFunc USERFUNC, void *USERARG);</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Read a scalar or array value from a process variable.</p>
|
||||
|
||||
<p>When ca_get or ca_array_get are invoked the returned channel value cant be
|
||||
<p>When ca_get or ca_array_get are invoked the returned channel value can't be
|
||||
assumed to be stable in the application supplied buffer until after ECA_NORMAL
|
||||
is returned from ca_pend_io. If a connection is lost outstanding ca get
|
||||
requests are not automatically reissued following reconnect.</p>
|
||||
@@ -3051,11 +3037,10 @@ when a CA get request is initiated.</p>
|
||||
|
||||
<h3><code><a name="ca_add_event">ca_create_subscription()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
typedef void ( *pCallBack ) (
|
||||
struct event_handler_args );
|
||||
int ca_create_subscription ( chtype TYPE,
|
||||
unsigned long COUNT, chid CHID,
|
||||
unsigned long MASK, pCallBack USERFUNC, void *USERARG,
|
||||
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
|
||||
int ca_create_subscription ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, unsigned long MASK,
|
||||
caEventCallBackFunc USERFUNC, void *USERARG,
|
||||
evid *PEVID );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
@@ -3064,10 +3049,10 @@ int ca_create_subscription ( chtype TYPE,
|
||||
invoked whenever the process variable undergoes significant state changes. A
|
||||
significant change can be a change in the process variable's value, alarm
|
||||
status, or alarm severity. In the process control function block database the
|
||||
deadband field determines the magnitude of a significant change for for the
|
||||
deadband field determines the magnitude of a significant change for the
|
||||
process variable's value. Each call to this function consumes resources in the
|
||||
client library and potentially a CA server until one of ca_clear_channel or
|
||||
ca_clear_event is called.</p>
|
||||
ca_clear_subscription is called.</p>
|
||||
|
||||
<p>Subscriptions may be installed or canceled against both connected and
|
||||
disconnected channels. The specified USERFUNC is called once immediately after
|
||||
@@ -3075,7 +3060,7 @@ the subscription is installed with the process variable's current state if the
|
||||
process variable is connected. Otherwise, the specified USERFUNC is called
|
||||
immediately after establishing a connection (or reconnection) with the process
|
||||
variable. The specified USERFUNC is called immediately with the process
|
||||
variable's current state from within ca_add_event() if the client and the
|
||||
variable's current state from within ca_create_subscription() if the client and the
|
||||
process variable share the same address space.</p>
|
||||
|
||||
<p>If a subscription is installed on a channel in a disconnected state then the
|
||||
@@ -3132,8 +3117,8 @@ indicating the current state of the channel.</p>
|
||||
<dl>
|
||||
<dt><code>PEVID</code></dt>
|
||||
<dd>This is a pointer to user supplied event id which is overwritten if
|
||||
successful. This event id can later be used to clear a specific
|
||||
event. This option may may be omitted by passing a nil pointer.</dd>
|
||||
successful. This event id can later be used to clear a specific event.
|
||||
This option may be omitted by passing a nill pointer.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>MASK</code></dt>
|
||||
@@ -3181,7 +3166,7 @@ int ca_clear_subscription ( evid EVID );</pre>
|
||||
|
||||
<p>Cancel a subscription.</p>
|
||||
|
||||
<p>All ca_clear_event() requests such as the above are accumulated (buffered)
|
||||
<p>All cancel-subscription requests such as the above are accumulated (buffered)
|
||||
and not forwarded to the server until one of ca_flush_io, ca_pend_io,
|
||||
ca_pend_event, or ca_sg_pend are called. This allows several requests to be
|
||||
efficiently sent together in one message.</p>
|
||||
@@ -3189,7 +3174,7 @@ efficiently sent together in one message.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>EVID</dt>
|
||||
<dd>event id returned by ca_add_event()</dd>
|
||||
<dd>event id returned by ca_create_subscription()</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -3240,9 +3225,9 @@ activities</em>.</p>
|
||||
network delays such as Ethernet collision exponential back off until
|
||||
retransmission delays which can be quite long on overloaded networks.</p>
|
||||
|
||||
<p>Unlike <code><a href="#ca_pend_event">ca_pend_event</a></code>, this routine will
|
||||
not process CA's background activities if none of the selected IO requests are
|
||||
pending.</p>
|
||||
<p>Unlike <code><a href="#ca_pend_event">ca_pend_event</a></code>, this routine
|
||||
will not process CA's background activities if none of the selected IO requests
|
||||
are pending.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
@@ -3305,7 +3290,7 @@ activity is processed for TIMEOUT seconds.</p>
|
||||
background activity is processed.</p>
|
||||
|
||||
<p>The ca_pend_event function will <em>not</em> return before the specified
|
||||
time-out expires and all unfinished channel access labor has been processed,
|
||||
timeout expires and all unfinished channel access labor has been processed,
|
||||
and unlike <code><a href="#ca_pend_io">ca_pend_io</a></code> returning from the
|
||||
function does <em>not </em>indicate anything about the status of pending IO
|
||||
requests.</p>
|
||||
@@ -3417,7 +3402,7 @@ field should not be used.</p>
|
||||
<dl>
|
||||
<dt><code>USERFUNC</code></dt>
|
||||
<dd>Address of user callback function to be executed when an exceptions
|
||||
occur. Passing a nil value causes the default exception handler to be
|
||||
occur. Passing a nill value causes the default exception handler to be
|
||||
reinstalled. The following structure is passed by value to the user's
|
||||
callback function. Currently, the <code>op</code> field can be one of
|
||||
<code>CA_OP_GET, CA_OP_PUT, CA_OP_CREATE_CHANNEL, CA_OP_ADD_EVENT,
|
||||
@@ -3540,7 +3525,7 @@ get the lowest latency response to the arrival of CA messages.</p>
|
||||
<h3><code><a name="ca_replace_printf_handler">ca_replace_printf_handler
|
||||
()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
typedef int caPrintfFunc ( const char *pFromat, va_list args );
|
||||
typedef int caPrintfFunc ( const char *pFormat, va_list args );
|
||||
int ca_replace_printf_handler ( caPrintfFunc *PFUNC );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
@@ -3552,7 +3537,7 @@ default handler uses fprintf to send messages to 'stderr'.</p>
|
||||
<dl>
|
||||
<dt><code>PFUNC</code></dt>
|
||||
<dd>The address of a user supplied call back handler to be invoked when CA
|
||||
prints diagnostic messages. Installing a nil pointer will cause the
|
||||
prints diagnostic messages. Installing a nill pointer will cause the
|
||||
default call back handler to be reinstalled.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -3571,8 +3556,9 @@ SEVCHK ( status, "failed to install my printf handler" );</pre>
|
||||
|
||||
<h3><code><a name="ca_replace">ca_replace_access_rights_event()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
typedef void ( *pCallBack )( struct access_rights_handler_args );
|
||||
int ca_replace_access_rights_event ( chid CHAN, pCallBack PFUNC );</pre>
|
||||
typedef void ( caEventCallBackFunc )(struct access_rights_handler_args);
|
||||
int ca_replace_access_rights_event ( chid CHAN,
|
||||
caEventCallBackFunc PFUNC );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
@@ -3598,7 +3584,7 @@ specified channel.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PFUNC</code></dt>
|
||||
<dd>Address of user supplied call back function. A nil pointer uninstalls
|
||||
<dd>Address of user supplied call back function. A nill pointer uninstalls
|
||||
the current handler. The following arguments are passed <em>by value</em>
|
||||
to the supplied callback handler.
|
||||
<pre>typedef struct ca_access_rights {
|
||||
@@ -3941,12 +3927,12 @@ prints diagnostics to standard out.</p>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>void ca_test_event ();
|
||||
status = ca_add_event ( type, chid, ca_test_event, NULL, NULL );
|
||||
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
|
||||
SEVCHK ( status, .... );</pre>
|
||||
|
||||
<h4>See Also</h4>
|
||||
|
||||
<p><a href="#ca_add_event">ca_add_event</a>()</p>
|
||||
<p><a href="#ca_add_event">ca_create_subscription</a>()</p>
|
||||
|
||||
<h3><code><a name="ca_sg_create">ca_sg_create()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
@@ -4029,7 +4015,7 @@ SEVCHK ( status, Sync group delete failed );</pre>
|
||||
|
||||
<h3><code><a name="ca_sg_block">ca_sg_block()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_sg_block ( CA_SYNC_GID GID, double timeout );</pre>
|
||||
int ca_sg_block ( CA_SYNC_GID GID, double TIMEOUT );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
@@ -4050,13 +4036,16 @@ access background activity while it is waiting.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>GID</dt>
|
||||
<dt><code>GID</code></dt>
|
||||
<dd>Identifier of the synchronous group.</dd>
|
||||
<dt><code>TIMEOUT</code></dt>
|
||||
<dd>The duration to block in this routine in seconds. A timeout of zero
|
||||
seconds blocks forever.</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>CA_SYNC_GID gid;
|
||||
status = ca_sg_block(gid);
|
||||
status = ca_sg_block(gid, 0.0);
|
||||
SEVCHK(status, Sync group block failed);</pre>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -4267,8 +4256,8 @@ reissued.</p>
|
||||
|
||||
<h3><code><a name="ca_client_status">ca_client_status()</a></code></h3>
|
||||
<pre>int ca_client_status ( unsigned level );
|
||||
int ca_context_status ( struct ca_client_context *,
|
||||
unsigned level );</pre>
|
||||
int ca_context_status ( struct ca_client_context *CONTEXT,
|
||||
unsigned LEVEL );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
@@ -4279,7 +4268,7 @@ ca_client_status() prints information about the calling threads CA context.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>CONTEXT</code></dt>
|
||||
<dd>A pointer to the CA context to join with.</dd>
|
||||
<dd>A pointer to the CA context to examine.</dd>
|
||||
<dt><code>LEVEL</code></dt>
|
||||
<dd>The interest level. Increasing level produces increasing detail.</dd>
|
||||
</dl>
|
||||
@@ -4289,7 +4278,7 @@ ca_client_status() prints information about the calling threads CA context.</p>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Returns a pointer to the current thread's CA context. If none then nil is
|
||||
<p>Returns a pointer to the current thread's CA context. If none then nill is
|
||||
returned.</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
@@ -4322,12 +4311,11 @@ preemptively from more than one thread.</p>
|
||||
|
||||
<h4>Returns</h4>
|
||||
|
||||
<p>ECA_ISATTACHED - already attached to a CA context</p>
|
||||
<p>ECA_NORMAL - Normal successful completion</p>
|
||||
|
||||
<p>ECA_NOTTHREADED - the specified context is non-preemptive and therefore does
|
||||
not allow other threads to join</p>
|
||||
<p>ECA_NOTTHREADED - Context is not preemptive so cannot be joined</p>
|
||||
|
||||
<p>ECA_ISATTACHED - the current thread is already attached to a CA context</p>
|
||||
<p>ECA_ISATTACHED - Thread already attached to a CA context</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
|
||||
|
||||
@@ -91,14 +91,19 @@ PROD_LIBS = ca Com
|
||||
# needed when its an object library build
|
||||
PROD_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
|
||||
|
||||
PROD_HOST += caRepeater catime acctst caConnTest casw caEventRate
|
||||
OBJS_IOC += catime acctst caConnTest casw caEventRate acctstRegister
|
||||
PROD_DEFAULT += caRepeater catime acctst caConnTest casw caEventRate
|
||||
PROD_vxWorks = -nil-
|
||||
PROD_RTEMS = -nil-
|
||||
PROD_iOS = -nil-
|
||||
|
||||
OBJS_vxWorks = catime acctst caConnTest casw caEventRate acctstRegister
|
||||
|
||||
caRepeater_SRCS = caRepeater.cpp
|
||||
catime_SRCS = catimeMain.c catime.c
|
||||
acctst_SRCS = acctstMain.c acctst.c
|
||||
catime_SRCS = catimeMain.c catime.c
|
||||
acctst_SRCS = acctstMain.c acctst.c
|
||||
caEventRate_SRCS = caEventRateMain.cpp caEventRate.cpp
|
||||
casw_SRCS = casw.cpp
|
||||
caConnTest_SRCS = caConnTestMain.cpp caConnTest.cpp
|
||||
caConnTest_SRCS = caConnTestMain.cpp caConnTest.cpp
|
||||
|
||||
casw_SYS_LIBS_solaris = socket
|
||||
|
||||
|
||||
0
src/ca/SearchDest.h
Executable file → Normal file
0
src/ca/SearchDest.h
Executable file → Normal file
@@ -376,15 +376,35 @@ int epicsShareAPI ca_create_channel (
|
||||
int epicsShareAPI ca_clear_channel ( chid pChan )
|
||||
{
|
||||
ca_client_context & cac = pChan->getClientCtx ();
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
try {
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
try {
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
}
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
}
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
pChan->destructor ( guard );
|
||||
if ( cac.pCallbackGuard.get() &&
|
||||
cac.createdByThread == epicsThreadGetIdSelf () ) {
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
pChan->destructor ( *cac.pCallbackGuard.get(), guard );
|
||||
cac.oldChannelNotifyFreeList.release ( pChan );
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemtive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user calls this function from an auxiillary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( cac.cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
pChan->destructor ( *cac.pCallbackGuard.get(), guard );
|
||||
cac.oldChannelNotifyFreeList.release ( pChan );
|
||||
}
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
@@ -433,7 +453,7 @@ chid epicsShareAPI ca_evid_to_chid ( evid pMon )
|
||||
}
|
||||
|
||||
// extern "C"
|
||||
int epicsShareAPI ca_pend ( ca_real timeout, int early ) // X aCC 361
|
||||
int epicsShareAPI ca_pend ( ca_real timeout, int early )
|
||||
{
|
||||
if ( early ) {
|
||||
return ca_pend_io ( timeout );
|
||||
@@ -516,7 +536,7 @@ int epicsShareAPI ca_flush_io ()
|
||||
/*
|
||||
* CA_TEST_IO ()
|
||||
*/
|
||||
int epicsShareAPI ca_test_io () // X aCC 361
|
||||
int epicsShareAPI ca_test_io ()
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
@@ -551,7 +571,7 @@ void epicsShareAPI ca_signal ( long ca_status, const char *message )
|
||||
* (if they call this routine again).
|
||||
*/
|
||||
// extern "C"
|
||||
const char * epicsShareAPI ca_message ( long ca_status ) // X aCC 361
|
||||
const char * epicsShareAPI ca_message ( long ca_status )
|
||||
{
|
||||
unsigned msgNo = CA_EXTRACT_MSG_NO ( ca_status );
|
||||
|
||||
|
||||
159
src/ca/acctst.c
159
src/ca/acctst.c
@@ -13,6 +13,7 @@
|
||||
* Authors:
|
||||
* Jeff Hill
|
||||
* Murali Shankar - initial versions of verifyMultithreadSubscr
|
||||
* Michael Abbott - initial versions of multiSubscrDestroyNoLateCallbackTest
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1328,6 +1329,159 @@ void test_sync_groups ( chid chan, unsigned interestLevel )
|
||||
showProgressEnd ( interestLevel );
|
||||
}
|
||||
|
||||
#define multiSubscrDestroyNoLateCallbackEventCount 500
|
||||
|
||||
struct MultiSubscrDestroyNoLateCallbackEventData {
|
||||
evid m_id;
|
||||
size_t m_nCallback;
|
||||
int m_callbackIsOk;
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData * m_pTestData;
|
||||
};
|
||||
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData {
|
||||
const char * m_pChanName;
|
||||
chid m_chan;
|
||||
epicsMutexId m_mutex;
|
||||
epicsEventId m_testDoneEvent;
|
||||
unsigned m_interestLevel;
|
||||
struct MultiSubscrDestroyNoLateCallbackEventData
|
||||
m_eventData [multiSubscrDestroyNoLateCallbackEventCount];
|
||||
};
|
||||
|
||||
static void noLateCallbackDetect ( struct event_handler_args args )
|
||||
{
|
||||
int callbackIsOk;
|
||||
struct MultiSubscrDestroyNoLateCallbackEventData * const pEventData = args.usr;
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pEventData->m_pTestData->m_mutex );
|
||||
callbackIsOk = pEventData->m_callbackIsOk;
|
||||
pEventData->m_nCallback++;
|
||||
epicsMutexUnlock ( pEventData->m_pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
verify ( callbackIsOk );
|
||||
}
|
||||
|
||||
static void multiSubscrDestroyNoLateCallbackThread ( void * pParm )
|
||||
{
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData * const pTestData =
|
||||
( struct MultiSubscrDestroyNoLateCallbackTestData * ) pParm;
|
||||
unsigned i, j;
|
||||
int status;
|
||||
|
||||
status = ca_context_create ( ca_enable_preemptive_callback );
|
||||
verify ( status == ECA_NORMAL );
|
||||
|
||||
status = ca_create_channel ( pTestData->m_pChanName, 0, 0,
|
||||
CA_PRIORITY_DEFAULT, &pTestData->m_chan );
|
||||
status = ca_pend_io ( timeoutToPendIO );
|
||||
SEVCHK ( status, "multiSubscrDestroyLateNoCallbackTest: channel connect failed" );
|
||||
verify ( status == ECA_NORMAL );
|
||||
|
||||
/*
|
||||
* create a set of subscriptions
|
||||
*/
|
||||
for ( i=0; i < 10000; i++ ) {
|
||||
unsigned int priorityOfTestThread;
|
||||
for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
pTestData->m_eventData[j].m_nCallback = 0;
|
||||
pTestData->m_eventData[j].m_callbackIsOk = TRUE;
|
||||
pTestData->m_eventData[j].m_pTestData = pTestData;
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
SEVCHK ( ca_add_event ( DBR_GR_FLOAT, pTestData->m_chan, noLateCallbackDetect,
|
||||
&pTestData->m_eventData[j], &pTestData->m_eventData[j].m_id ) , NULL );
|
||||
}
|
||||
SEVCHK ( ca_flush_io(), NULL );
|
||||
|
||||
/*
|
||||
* raise the priority of the current thread hoping to improve our
|
||||
* likelyhood of detecting a bug
|
||||
*/
|
||||
priorityOfTestThread = epicsThreadGetPrioritySelf ();
|
||||
epicsThreadSetPriority ( epicsThreadGetIdSelf(), epicsThreadPriorityHigh );
|
||||
|
||||
|
||||
/*
|
||||
* wait for the first subscription update to arrive
|
||||
*/
|
||||
{
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
while ( pTestData->m_eventData[0].m_nCallback == 0 ) {
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
epicsThreadSleep ( 50e-6 );
|
||||
lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
}
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
}
|
||||
/*
|
||||
* try to destroy all of the subscriptions at precisely the same time that
|
||||
* their first callbacks are running
|
||||
*/
|
||||
for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
|
||||
epicsMutexLockStatus lockStatus;
|
||||
SEVCHK ( ca_clear_event ( pTestData->m_eventData[j].m_id ) , NULL );
|
||||
lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
pTestData->m_eventData[j].m_callbackIsOk = FALSE;
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
}
|
||||
/*
|
||||
* return to the original priority
|
||||
*/
|
||||
epicsThreadSetPriority ( epicsThreadGetIdSelf(), priorityOfTestThread );
|
||||
|
||||
if ( i % 1000 == 0 ) {
|
||||
showProgress ( pTestData->m_interestLevel );
|
||||
}
|
||||
}
|
||||
|
||||
SEVCHK ( ca_clear_channel ( pTestData->m_chan ), NULL );
|
||||
|
||||
ca_context_destroy ();
|
||||
|
||||
epicsEventSignal ( pTestData->m_testDoneEvent );
|
||||
}
|
||||
|
||||
/*
|
||||
* verify that, in a preemtive callback mode client, a subscription callback never
|
||||
* comes after the subscription is destroyed
|
||||
*/
|
||||
static void multiSubscrDestroyNoLateCallbackTest ( const char *pName, unsigned interestLevel )
|
||||
{
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData * pTestData;
|
||||
|
||||
showProgressBegin ( "multiSubscrDestroyNoLateCallbackTest", interestLevel );
|
||||
|
||||
pTestData = calloc ( 1u, sizeof ( struct MultiSubscrDestroyNoLateCallbackTestData ) );
|
||||
verify ( pTestData );
|
||||
pTestData->m_mutex = epicsMutexMustCreate ();
|
||||
pTestData->m_testDoneEvent = epicsEventMustCreate ( epicsEventEmpty );
|
||||
pTestData->m_pChanName = pName;
|
||||
pTestData->m_interestLevel = interestLevel;
|
||||
epicsThreadMustCreate (
|
||||
"multiSubscrDestroyNoLateCallbackTest",
|
||||
epicsThreadPriorityLow,
|
||||
epicsThreadGetStackSize ( epicsThreadStackMedium ),
|
||||
multiSubscrDestroyNoLateCallbackThread,
|
||||
pTestData );
|
||||
|
||||
/*
|
||||
* wait for test to complete
|
||||
*/
|
||||
epicsEventMustWait ( pTestData->m_testDoneEvent );
|
||||
|
||||
/*
|
||||
* cleanup
|
||||
*/
|
||||
epicsMutexDestroy ( pTestData->m_mutex );
|
||||
epicsEventDestroy ( pTestData->m_testDoneEvent );
|
||||
free ( pTestData );
|
||||
|
||||
showProgressEnd ( interestLevel );
|
||||
}
|
||||
|
||||
/*
|
||||
* multiSubscriptionDeleteTest
|
||||
*
|
||||
@@ -3263,6 +3417,11 @@ int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
|
||||
epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", tmpString );
|
||||
}
|
||||
|
||||
/*
|
||||
* this test creates, and then destroys, a private CA context
|
||||
*/
|
||||
multiSubscrDestroyNoLateCallbackTest ( pName, interestLevel );
|
||||
|
||||
status = ca_context_create ( select );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
|
||||
@@ -332,13 +332,6 @@ void bhe::unregisterIIU (
|
||||
}
|
||||
}
|
||||
|
||||
void * bhe::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void bhe::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -87,7 +87,6 @@ private:
|
||||
const epicsTime & currentTime );
|
||||
bhe ( const bhe & );
|
||||
bhe & operator = ( const bhe & );
|
||||
void * operator new ( size_t size );
|
||||
epicsShareFunc void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
0
src/ca/ca.rc
Executable file → Normal file
0
src/ca/ca.rc
Executable file → Normal file
@@ -106,7 +106,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
|
||||
{
|
||||
osiSockIoctl_t yes = true;
|
||||
int status = socket_ioctl ( this->sock, // X aCC 392
|
||||
int status = socket_ioctl ( this->sock,
|
||||
FIONBIO, & yes);
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -126,7 +126,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
memset ( (char *)&addr, 0 , sizeof ( addr ) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( PORT_ANY ); // X aCC 818
|
||||
addr.ia.sin_port = htons ( PORT_ANY );
|
||||
int status = bind (this->sock, &addr.sa, sizeof (addr) );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -159,9 +159,9 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
this->localPort = htons ( tmpAddr.ia.sin_port );
|
||||
}
|
||||
|
||||
epics_auto_ptr < epicsGuard < epicsMutex > > pCBGuard;
|
||||
epics_auto_ptr < CallbackGuard > pCBGuard;
|
||||
if ( ! enablePreemptiveCallback ) {
|
||||
pCBGuard.reset ( new epicsGuard < epicsMutex > ( this->cbMutex ) );
|
||||
pCBGuard.reset ( new CallbackGuard ( this->cbMutex ) );
|
||||
}
|
||||
|
||||
// multiple steps ensure exception safety
|
||||
@@ -277,7 +277,7 @@ int ca_client_context :: printFormated (
|
||||
}
|
||||
|
||||
int ca_client_context :: varArgsPrintFormated (
|
||||
const char *pformat, va_list args ) const // X aCC 361
|
||||
const char *pformat, va_list args ) const
|
||||
{
|
||||
caPrintfFunc * pFunc;
|
||||
{
|
||||
@@ -751,6 +751,8 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
|
||||
{
|
||||
oldChannelNotify & chan = pMon->channel ();
|
||||
ca_client_context & cac = chan.getClientCtx ();
|
||||
// !!!! the order in which we take the mutex here prevents deadlocks
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
try {
|
||||
// if this stalls out on a live circuit then an exception
|
||||
@@ -761,7 +763,25 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
pMon->cancel ( guard );
|
||||
}
|
||||
if ( cac.pCallbackGuard.get() &&
|
||||
cac.createdByThread == epicsThreadGetIdSelf () ) {
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
pMon->cancel ( *cac.pCallbackGuard.get(), guard );
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemtive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user calls this function from an auxiillary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( cac.cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
pMon->cancel ( cbGuard, guard );
|
||||
}
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -568,7 +568,7 @@ bool cac::findOrCreateVirtCircuit (
|
||||
}
|
||||
|
||||
void cac::transferChanToVirtCircuit (
|
||||
unsigned cid, unsigned sid, // X aCC 431
|
||||
unsigned cid, unsigned sid,
|
||||
ca_uint16_t typeCode, arrayElementCount count,
|
||||
unsigned minorVersionNumber, const osiSockAddr & addr,
|
||||
const epicsTime & currentTime )
|
||||
@@ -711,6 +711,7 @@ netReadNotifyIO & cac::readNotifyRequest (
|
||||
}
|
||||
|
||||
bool cac::destroyIO (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid & idIn, nciu & chan )
|
||||
{
|
||||
@@ -787,7 +788,7 @@ void cac::recycleSubscription (
|
||||
netSubscription & cac::subscriptionRequest (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, privateInterfaceForIO & privChan,
|
||||
unsigned type, // X aCC 361
|
||||
unsigned type,
|
||||
arrayElementCount nElem, unsigned mask,
|
||||
cacStateNotify & notifyIn,
|
||||
bool chanIsInstalled )
|
||||
@@ -1021,7 +1022,7 @@ bool cac::readExcep ( callbackManager &, tcpiiu &,
|
||||
}
|
||||
|
||||
bool cac::writeExcep (
|
||||
callbackManager & mgr, // X aCC 431
|
||||
callbackManager & mgr,
|
||||
tcpiiu &, const caHdrLargeArray & hdr,
|
||||
const char * pCtx, unsigned status )
|
||||
{
|
||||
@@ -1093,7 +1094,7 @@ bool cac::exceptionRespAction ( callbackManager & cbMutexIn, tcpiiu & iiu,
|
||||
}
|
||||
|
||||
bool cac::accessRightsRespAction (
|
||||
callbackManager & mgr, tcpiiu &, // X aCC 431
|
||||
callbackManager & mgr, tcpiiu &,
|
||||
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
@@ -1110,7 +1111,7 @@ bool cac::accessRightsRespAction (
|
||||
}
|
||||
|
||||
bool cac::createChannelRespAction (
|
||||
callbackManager & mgr, tcpiiu & iiu, // X aCC 431
|
||||
callbackManager & mgr, tcpiiu & iiu,
|
||||
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
@@ -1157,7 +1158,7 @@ bool cac::verifyAndDisconnectChan (
|
||||
}
|
||||
|
||||
void cac::disconnectChannel (
|
||||
epicsGuard < epicsMutex > & cbGuard, // X aCC 431
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard, nciu & chan )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
10
src/ca/cac.h
10
src/ca/cac.h
@@ -55,7 +55,7 @@ class netSubscription;
|
||||
// used to control access to cac's recycle routines which
|
||||
// should only be indirectly invoked by CAC when its lock
|
||||
// is applied
|
||||
class cacRecycle { // X aCC 655
|
||||
class cacRecycle {
|
||||
public:
|
||||
virtual void recycleReadNotifyIO (
|
||||
epicsGuard < epicsMutex > &, netReadNotifyIO &io ) = 0;
|
||||
@@ -155,7 +155,8 @@ public:
|
||||
unsigned type, arrayElementCount nElem, unsigned mask,
|
||||
cacStateNotify &, bool channelIsInstalled );
|
||||
bool destroyIO (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & idIn,
|
||||
nciu & chan );
|
||||
void disconnectAllIO (
|
||||
@@ -167,11 +168,6 @@ public:
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid &id, unsigned level ) const;
|
||||
|
||||
// sync group routines
|
||||
CASG * lookupCASG ( epicsGuard < epicsMutex > &, unsigned id );
|
||||
void installCASG ( epicsGuard < epicsMutex > &, CASG & );
|
||||
void uninstallCASG ( epicsGuard < epicsMutex > &, CASG & );
|
||||
|
||||
// exception generation
|
||||
void exception (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
|
||||
@@ -69,7 +69,7 @@ typedef unsigned long arrayElementCount;
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacWriteNotify { // X aCC 655
|
||||
class epicsShareClass cacWriteNotify {
|
||||
public:
|
||||
virtual ~cacWriteNotify () = 0;
|
||||
virtual void completion ( epicsGuard < epicsMutex > & ) = 0;
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacReadNotify { // X aCC 655
|
||||
class epicsShareClass cacReadNotify {
|
||||
public:
|
||||
virtual ~cacReadNotify () = 0;
|
||||
virtual void completion (
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacStateNotify { // X aCC 655
|
||||
class epicsShareClass cacStateNotify {
|
||||
public:
|
||||
virtual ~cacStateNotify () = 0;
|
||||
virtual void current (
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
bool f_operatorConfirmationRequest:1;
|
||||
};
|
||||
|
||||
class epicsShareClass cacChannelNotify { // X aCC 655
|
||||
class epicsShareClass cacChannelNotify {
|
||||
public:
|
||||
virtual ~cacChannelNotify () = 0;
|
||||
virtual void connectNotify ( epicsGuard < epicsMutex > & ) = 0;
|
||||
@@ -152,6 +152,16 @@ public:
|
||||
unsigned type, arrayElementCount count ) = 0;
|
||||
};
|
||||
|
||||
class CallbackGuard :
|
||||
public epicsGuard < epicsMutex > {
|
||||
public:
|
||||
CallbackGuard ( epicsMutex & mutex ) :
|
||||
epicsGuard < epicsMutex > ( mutex ) {}
|
||||
private:
|
||||
CallbackGuard ( const CallbackGuard & );
|
||||
CallbackGuard & operator = ( const CallbackGuard & );
|
||||
};
|
||||
|
||||
//
|
||||
// Notes
|
||||
// 1) This interface assumes that when a channel is deleted then all
|
||||
@@ -174,6 +184,7 @@ public:
|
||||
|
||||
cacChannel ( cacChannelNotify & );
|
||||
virtual void destroy (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
cacChannelNotify & notify () const; // required ?????
|
||||
virtual unsigned getName (
|
||||
@@ -207,7 +218,15 @@ public:
|
||||
epicsGuard < epicsMutex > &, unsigned type,
|
||||
arrayElementCount count, unsigned mask, cacStateNotify &,
|
||||
ioid * = 0 ) = 0;
|
||||
// The primary mutex must be released when calling the user's
|
||||
// callback, and therefore a finite interval exists when we are
|
||||
// moving forward with the intent to call the users callback
|
||||
// but the users IO could be deleted during this interval.
|
||||
// To prevent the user's callback from being called after
|
||||
// destroying his IO we must past a guard for the callback
|
||||
// mutex here.
|
||||
virtual void ioCancel (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & ) = 0;
|
||||
virtual void ioShow (
|
||||
@@ -258,7 +277,7 @@ private:
|
||||
cacChannel & operator = ( const cacChannel & );
|
||||
};
|
||||
|
||||
class epicsShareClass cacContext { // X aCC 655
|
||||
class epicsShareClass cacContext {
|
||||
public:
|
||||
virtual ~cacContext ();
|
||||
virtual cacChannel & createChannel (
|
||||
@@ -277,7 +296,7 @@ public:
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
|
||||
};
|
||||
|
||||
class epicsShareClass cacContextNotify { // X aCC 655
|
||||
class epicsShareClass cacContextNotify {
|
||||
public:
|
||||
virtual ~cacContextNotify () = 0;
|
||||
virtual cacContext & createNetworkContext (
|
||||
@@ -297,7 +316,7 @@ public:
|
||||
// **** Lock Hierarchy ****
|
||||
// callbackControl must be taken before mutualExclusion if both are held at
|
||||
// the same time
|
||||
class epicsShareClass cacService { // X aCC 655
|
||||
class epicsShareClass cacService {
|
||||
public:
|
||||
virtual ~cacService () = 0;
|
||||
virtual cacContext & contextCreate (
|
||||
|
||||
@@ -131,7 +131,7 @@ int main ( int argc, char ** argv )
|
||||
}
|
||||
|
||||
osiSockIoctl_t yes = true;
|
||||
status = socket_ioctl ( sock, FIONBIO, &yes ); // X aCC 392
|
||||
status = socket_ioctl ( sock, FIONBIO, &yes );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
@@ -166,7 +166,7 @@ int main ( int argc, char ** argv )
|
||||
}
|
||||
|
||||
osiSockIoctl_t no = false;
|
||||
status = socket_ioctl ( sock, FIONBIO, &no ); // X aCC 392
|
||||
status = socket_ioctl ( sock, FIONBIO, &no );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
virtual void release ( void * ) = 0;
|
||||
};
|
||||
|
||||
class wireSendAdapter { // X aCC 655
|
||||
class wireSendAdapter {
|
||||
public:
|
||||
virtual unsigned sendBytes ( const void * pBuf,
|
||||
unsigned nBytesInBuf,
|
||||
@@ -65,7 +65,7 @@ struct statusWireIO {
|
||||
swioCircuitState circuitState;
|
||||
};
|
||||
|
||||
class wireRecvAdapter { // X aCC 655
|
||||
class wireRecvAdapter {
|
||||
public:
|
||||
virtual void recvBytes ( void * pBuf,
|
||||
unsigned nBytesInBuf, statusWireIO & ) = 0;
|
||||
@@ -114,7 +114,6 @@ private:
|
||||
unsigned nextWriteIndex;
|
||||
unsigned nextReadIndex;
|
||||
epicsUInt8 buf [ comBufSize ];
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
template < class T >
|
||||
bool push ( const T * ); // disabled
|
||||
|
||||
@@ -155,7 +155,7 @@ epicsUInt32 comQueRecv::multiBufferPopUInt32 ()
|
||||
unsigned byte3 = this->popUInt8();
|
||||
unsigned byte4 = this->popUInt8();
|
||||
tmp = static_cast <epicsUInt32>
|
||||
( ( byte1 << 24u ) | ( byte2 << 16u ) | //X aCC 392
|
||||
( ( byte1 << 24u ) | ( byte2 << 16u ) |
|
||||
( byte3 << 8u ) | byte4 );
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -368,7 +368,7 @@ void comQueSend::insertRequestWithPayLoad (
|
||||
// the above checks verify that the total size
|
||||
// is lest that 0xffffffff
|
||||
size = static_cast < ca_uint32_t >
|
||||
( dbr_size_n ( dataType, nElem ) ); // X aCC 392
|
||||
( dbr_size_n ( dataType, nElem ) );
|
||||
payloadSize = CA_MESSAGE_ALIGN ( size );
|
||||
this->insertRequestHeader ( request, payloadSize,
|
||||
static_cast <ca_uint16_t> ( dataType ),
|
||||
|
||||
@@ -65,7 +65,7 @@ void disconnectGovernorTimer::shutdown (
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus disconnectGovernorTimer::expire (
|
||||
const epicsTime & /* currentTime */ ) // X aCC 361
|
||||
const epicsTime & /* currentTime */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
while ( nciu * pChan = chanList.get () ) {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "caProto.h"
|
||||
#include "netiiu.h"
|
||||
|
||||
class disconnectGovernorNotify { // X aCC 655
|
||||
class disconnectGovernorNotify {
|
||||
public:
|
||||
virtual ~disconnectGovernorNotify () = 0;
|
||||
virtual void govExpireNotify (
|
||||
|
||||
@@ -90,13 +90,6 @@ void getCallback::exception (
|
||||
}
|
||||
}
|
||||
|
||||
void * getCallback::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void getCallback::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -105,13 +105,6 @@ void getCopy::show ( unsigned level ) const
|
||||
}
|
||||
}
|
||||
|
||||
void * getCopy::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void getCopy::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -133,7 +133,7 @@ extern "C" void epicsShareAPI removeDuplicateAddresses
|
||||
|
||||
if ( pNode->addr.sa.sa_family == AF_INET ) {
|
||||
|
||||
pTmpNode = (osiSockAddrNode *) ellFirst (pDestList); // X aCC 749
|
||||
pTmpNode = (osiSockAddrNode *) ellFirst (pDestList);
|
||||
while ( pTmpNode ) {
|
||||
if (pTmpNode->addr.sa.sa_family == AF_INET) {
|
||||
if ( pNode->addr.ia.sin_addr.s_addr == pTmpNode->addr.ia.sin_addr.s_addr &&
|
||||
@@ -149,7 +149,7 @@ extern "C" void epicsShareAPI removeDuplicateAddresses
|
||||
break;
|
||||
}
|
||||
}
|
||||
pTmpNode = (osiSockAddrNode *) ellNext (&pTmpNode->node); // X aCC 749
|
||||
pTmpNode = (osiSockAddrNode *) ellNext (&pTmpNode->node);
|
||||
}
|
||||
if (pNode) {
|
||||
ellAdd (pDestList, &pNode->node);
|
||||
@@ -168,12 +168,12 @@ static void forcePort ( ELLLIST *pList, unsigned short port )
|
||||
{
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
pNode = ( osiSockAddrNode * ) ellFirst ( pList ); // X aCC 749
|
||||
pNode = ( osiSockAddrNode * ) ellFirst ( pList );
|
||||
while ( pNode ) {
|
||||
if ( pNode->addr.sa.sa_family == AF_INET ) {
|
||||
pNode->addr.ia.sin_port = htons ( port );
|
||||
}
|
||||
pNode = ( osiSockAddrNode * ) ellNext ( &pNode->node ); // X aCC 749
|
||||
pNode = ( osiSockAddrNode * ) ellNext ( &pNode->node );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +192,9 @@ extern "C" void epicsShareAPI configureChannelAccessAddressList
|
||||
/*
|
||||
* dont load the list twice
|
||||
*/
|
||||
assert ( ellCount (pList) == 0 ); // X aCC 392
|
||||
assert ( ellCount (pList) == 0 );
|
||||
|
||||
ellInit ( &tmpList ); // X aCC 392
|
||||
ellInit ( &tmpList );
|
||||
|
||||
/*
|
||||
* Check to see if the user has disabled
|
||||
@@ -217,12 +217,12 @@ extern "C" void epicsShareAPI configureChannelAccessAddressList
|
||||
if (yes) {
|
||||
ELLLIST bcastList;
|
||||
osiSockAddr addr;
|
||||
ellInit ( &bcastList ); // X aCC 392
|
||||
ellInit ( &bcastList );
|
||||
addr.ia.sin_family = AF_UNSPEC;
|
||||
osiSockDiscoverBroadcastAddresses ( &bcastList, sock, &addr );
|
||||
forcePort ( &bcastList, port );
|
||||
removeDuplicateAddresses ( &tmpList, &bcastList, 1 );
|
||||
if ( ellCount ( &tmpList ) == 0 ) { // X aCC 392
|
||||
if ( ellCount ( &tmpList ) == 0 ) {
|
||||
osiSockAddrNode *pNewNode;
|
||||
pNewNode = (osiSockAddrNode *) calloc ( 1, sizeof (*pNewNode) );
|
||||
if ( pNewNode ) {
|
||||
@@ -254,11 +254,11 @@ extern "C" void epicsShareAPI printChannelAccessAddressList ( const ELLLIST *pLi
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
::printf ( "Channel Access Address List\n" );
|
||||
pNode = (osiSockAddrNode *) ellFirst ( pList ); // X aCC 749
|
||||
pNode = (osiSockAddrNode *) ellFirst ( pList );
|
||||
while (pNode) {
|
||||
char buf[64];
|
||||
ipAddrToA ( &pNode->addr.ia, buf, sizeof ( buf ) );
|
||||
::printf ( "%s\n", buf );
|
||||
pNode = (osiSockAddrNode *) ellNext ( &pNode->node ); // X aCC 749
|
||||
pNode = (osiSockAddrNode *) ellNext ( &pNode->node );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,13 +73,6 @@ void msgForMultiplyDefinedPV::operator delete ( void *pCadaver,
|
||||
}
|
||||
#endif
|
||||
|
||||
void * msgForMultiplyDefinedPV::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void msgForMultiplyDefinedPV::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
# define epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
class callbackForMultiplyDefinedPV { // X aCC 655
|
||||
class callbackForMultiplyDefinedPV {
|
||||
public:
|
||||
virtual ~callbackForMultiplyDefinedPV () = 0;
|
||||
virtual void pvMultiplyDefinedNotify (
|
||||
@@ -64,7 +64,6 @@ private:
|
||||
void transactionComplete ( const char * pHostName );
|
||||
msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & );
|
||||
msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -76,29 +76,24 @@ nciu::~nciu ()
|
||||
// channels are created by the user, and only destroyed by the user
|
||||
// using this routine
|
||||
void nciu::destroy (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExcusionGuard )
|
||||
{
|
||||
while ( baseNMIU * pNetIO = this->eventq.first () ) {
|
||||
bool success = this->cacCtx.destroyIO ( guard, pNetIO->getId (), *this );
|
||||
bool success = this->cacCtx.destroyIO ( callbackGuard, mutualExcusionGuard,
|
||||
pNetIO->getId (), *this );
|
||||
assert ( success );
|
||||
}
|
||||
|
||||
// if the claim reply has not returned yet then we will issue
|
||||
// the clear channel request to the server when the claim reply
|
||||
// arrives and there is no matching nciu in the client
|
||||
if ( this->channelNode::isInstalledInServer ( guard ) ) {
|
||||
this->getPIIU(guard)->clearChannelRequest (
|
||||
guard, this->sid, this->id );
|
||||
if ( this->channelNode::isInstalledInServer ( mutualExcusionGuard ) ) {
|
||||
this->getPIIU(mutualExcusionGuard)->clearChannelRequest (
|
||||
mutualExcusionGuard, this->sid, this->id );
|
||||
}
|
||||
this->piiu->uninstallChan ( guard, *this );
|
||||
this->cacCtx.destroyChannel ( guard, *this );
|
||||
}
|
||||
|
||||
void * nciu::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
this->piiu->uninstallChan ( mutualExcusionGuard, *this );
|
||||
this->cacCtx.destroyChannel ( mutualExcusionGuard, *this );
|
||||
}
|
||||
|
||||
void nciu::operator delete ( void * )
|
||||
@@ -387,9 +382,12 @@ void nciu::subscribe (
|
||||
}
|
||||
|
||||
void nciu::ioCancel (
|
||||
epicsGuard < epicsMutex > & guard, const ioid & idIn )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & idIn )
|
||||
{
|
||||
this->cacCtx.destroyIO ( guard, idIn, *this );
|
||||
this->cacCtx.destroyIO ( callbackGuard,
|
||||
mutualExclusionGuard, idIn, *this );
|
||||
}
|
||||
|
||||
void nciu::ioShow (
|
||||
|
||||
@@ -121,7 +121,7 @@ private:
|
||||
friend class disconnectGovernorTimer;
|
||||
};
|
||||
|
||||
class privateInterfaceForIO { // X aCC 655
|
||||
class privateInterfaceForIO {
|
||||
public:
|
||||
virtual void ioCompletionNotify (
|
||||
epicsGuard < epicsMutex > &, class baseNMIU & ) = 0;
|
||||
@@ -220,6 +220,7 @@ private:
|
||||
ca_uint16_t typeCode;
|
||||
ca_uint8_t priority;
|
||||
virtual void destroy (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > & );
|
||||
@@ -243,7 +244,15 @@ private:
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
unsigned type, arrayElementCount nElem,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid * );
|
||||
// The primary mutex must be released when calling the user's
|
||||
// callback, and therefore a finite interval exists when we are
|
||||
// moving forward with the intent to call the users callback
|
||||
// but the users IO could be deleted during this interval.
|
||||
// To prevent the user's callback from being called after
|
||||
// destroying his IO we must past a guard for the callback
|
||||
// mutex here.
|
||||
virtual void ioCancel (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & );
|
||||
void ioShow (
|
||||
@@ -270,7 +279,6 @@ private:
|
||||
epicsGuard < epicsMutex > & guard ) const throw ();
|
||||
nciu ( const nciu & );
|
||||
nciu & operator = ( const nciu & );
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
class privateInterfaceForIO;
|
||||
|
||||
class baseNMIU : public tsDLNode < baseNMIU >, // X aCC 655
|
||||
class baseNMIU : public tsDLNode < baseNMIU >,
|
||||
public chronIntIdRes < baseNMIU > {
|
||||
public:
|
||||
virtual void destroy (
|
||||
@@ -106,7 +106,6 @@ private:
|
||||
const unsigned mask;
|
||||
bool subscribed;
|
||||
class netSubscription * isSubscription ();
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class netSubscription, 1024, epicsMutexNOOP > & );
|
||||
@@ -147,7 +146,6 @@ protected:
|
||||
private:
|
||||
cacReadNotify & notify;
|
||||
class privateInterfaceForIO & privateChanForIO;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class netReadNotifyIO, 1024, epicsMutexNOOP > & );
|
||||
@@ -190,7 +188,6 @@ protected:
|
||||
private:
|
||||
cacWriteNotify & notify;
|
||||
privateInterfaceForIO & privateChanForIO;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class netWriteNotifyIO, 1024, epicsMutexNOOP > & );
|
||||
@@ -237,12 +234,12 @@ inline netSubscription * netSubscription::factory (
|
||||
class privateInterfaceForIO & chan, unsigned type, arrayElementCount count,
|
||||
unsigned mask, cacStateNotify ¬ify )
|
||||
{
|
||||
return new ( freeList ) netSubscription ( chan, type, // X aCC 930
|
||||
return new ( freeList ) netSubscription ( chan, type,
|
||||
count, mask, notify );
|
||||
}
|
||||
|
||||
inline arrayElementCount netSubscription::getCount (
|
||||
epicsGuard < epicsMutex > & guard, bool allow_zero ) const // X aCC 361
|
||||
epicsGuard < epicsMutex > & guard, bool allow_zero ) const
|
||||
{
|
||||
//guard.assertIdenticalMutex ( this->mutex );
|
||||
arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard );
|
||||
@@ -268,7 +265,7 @@ inline netReadNotifyIO * netReadNotifyIO::factory (
|
||||
tsFreeList < class netReadNotifyIO, 1024, epicsMutexNOOP > & freeList,
|
||||
privateInterfaceForIO & ioComplNotifIntf, cacReadNotify & notify )
|
||||
{
|
||||
return new ( freeList ) netReadNotifyIO ( ioComplNotifIntf, notify ); // X aCC 930
|
||||
return new ( freeList ) netReadNotifyIO ( ioComplNotifIntf, notify );
|
||||
}
|
||||
|
||||
inline void * netReadNotifyIO::operator new ( size_t size,
|
||||
@@ -289,7 +286,7 @@ inline netWriteNotifyIO * netWriteNotifyIO::factory (
|
||||
tsFreeList < class netWriteNotifyIO, 1024, epicsMutexNOOP > & freeList,
|
||||
privateInterfaceForIO & ioComplNotifyIntf, cacWriteNotify & notify )
|
||||
{
|
||||
return new ( freeList ) netWriteNotifyIO ( ioComplNotifyIntf, notify ); // X aCC 930
|
||||
return new ( freeList ) netWriteNotifyIO ( ioComplNotifyIntf, notify );
|
||||
}
|
||||
|
||||
inline void * netWriteNotifyIO::operator new ( size_t size,
|
||||
|
||||
@@ -119,13 +119,6 @@ void netReadNotifyIO::forceSubscriptionUpdate (
|
||||
{
|
||||
}
|
||||
|
||||
void * netReadNotifyIO::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void netReadNotifyIO::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -170,13 +170,6 @@ void netSubscription::forceSubscriptionUpdate (
|
||||
guard, chan, *this );
|
||||
}
|
||||
|
||||
void * netSubscription::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void netSubscription::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -117,14 +117,6 @@ void netWriteNotifyIO::forceSubscriptionUpdate (
|
||||
{
|
||||
}
|
||||
|
||||
void * netWriteNotifyIO::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error (
|
||||
"why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -35,7 +35,7 @@ union osiSockAddr;
|
||||
class cac;
|
||||
class nciu;
|
||||
|
||||
class netiiu { // X aCC 655
|
||||
class netiiu {
|
||||
public:
|
||||
virtual ~netiiu () = 0;
|
||||
virtual unsigned getHostName (
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
const char * pName, caCh * pConnCallBackIn,
|
||||
void * pPrivateIn, capri priority );
|
||||
void destructor (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & mutexGuard );
|
||||
|
||||
// legacy C API
|
||||
friend unsigned epicsShareAPI ca_get_host_name (
|
||||
@@ -122,6 +123,7 @@ public:
|
||||
unsigned type, arrayElementCount count, const void *pValue,
|
||||
cacWriteNotify &, cacChannel::ioid *pId = 0 );
|
||||
void ioCancel (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & );
|
||||
void ioShow (
|
||||
@@ -162,7 +164,6 @@ private:
|
||||
unsigned type, arrayElementCount count );
|
||||
oldChannelNotify ( const oldChannelNotify & );
|
||||
oldChannelNotify & operator = ( const oldChannelNotify & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -195,7 +196,6 @@ private:
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
getCopy ( const getCopy & );
|
||||
getCopy & operator = ( const getCopy & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -221,7 +221,6 @@ private:
|
||||
const char * pContext, unsigned type, arrayElementCount count );
|
||||
getCallback ( const getCallback & );
|
||||
getCallback & operator = ( const getCallback & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -245,7 +244,6 @@ private:
|
||||
unsigned type, arrayElementCount count );
|
||||
putCallback ( const putCallback & );
|
||||
putCallback & operator = ( const putCallback & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -259,8 +257,16 @@ public:
|
||||
evid * );
|
||||
~oldSubscription ();
|
||||
oldChannelNotify & channel () const;
|
||||
// The primary mutex must be released when calling the user's
|
||||
// callback, and therefore a finite interval exists when we are
|
||||
// moving forward with the intent to call the users callback
|
||||
// but the users IO could be deleted during this interval.
|
||||
// To prevent the user's callback from being called after
|
||||
// destroying his IO we must past a guard for the callback
|
||||
// mutex here.
|
||||
void cancel (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
@@ -278,7 +284,6 @@ private:
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
oldSubscription ( const oldSubscription & );
|
||||
oldSubscription & operator = ( const oldSubscription & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -341,6 +346,8 @@ public:
|
||||
void destroySubscription ( epicsGuard < epicsMutex > &, oldSubscription & );
|
||||
epicsMutex & mutexRef () const;
|
||||
|
||||
template < class T >
|
||||
void whenThereIsAnExceptionDestroySyncGroupIO ( epicsGuard < epicsMutex > &, T & );
|
||||
|
||||
// legacy C API
|
||||
friend int epicsShareAPI ca_create_channel (
|
||||
@@ -368,6 +375,17 @@ public:
|
||||
friend int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeout );
|
||||
friend int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid );
|
||||
friend int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid );
|
||||
friend int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid,
|
||||
chtype type, arrayElementCount count,
|
||||
chid pChan, void *pValue );
|
||||
friend int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid,
|
||||
chtype type, arrayElementCount count,
|
||||
chid pChan, const void *pValue );
|
||||
friend int ca_sync_group_destroy ( CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
ca_client_context & cac, const CA_SYNC_GID gid );
|
||||
friend void sync_group_reset ( ca_client_context & client,
|
||||
CASG & sg );
|
||||
|
||||
// exceptions
|
||||
class noSocket {};
|
||||
@@ -384,7 +402,7 @@ private:
|
||||
epicsEvent ioDone;
|
||||
epicsEvent callbackThreadActivityComplete;
|
||||
epicsThreadId createdByThread;
|
||||
epics_auto_ptr < epicsGuard < epicsMutex > > pCallbackGuard;
|
||||
epics_auto_ptr < CallbackGuard > pCallbackGuard;
|
||||
epics_auto_ptr < cacContext > pServiceContext;
|
||||
caExceptionHandler * ca_exception_func;
|
||||
void * ca_exception_arg;
|
||||
@@ -444,10 +462,11 @@ inline void oldChannelNotify::initiateConnect (
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::ioCancel (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & id )
|
||||
{
|
||||
this->io.ioCancel ( guard, id );
|
||||
this->io.ioCancel ( callbackGuard, mutualExclusionGuard, id );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::ioShow (
|
||||
@@ -492,9 +511,10 @@ inline void oldSubscription::operator delete ( void *pCadaver,
|
||||
#endif
|
||||
|
||||
inline void oldSubscription::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
{
|
||||
this->chan.ioCancel ( guard, this->id );
|
||||
this->chan.ioCancel ( callbackGuard, mutualExclusionGuard, this->id );
|
||||
}
|
||||
|
||||
inline oldChannelNotify & oldSubscription::channel () const
|
||||
@@ -560,5 +580,32 @@ inline unsigned ca_client_context::sequenceNumberOfOutstandingIO (
|
||||
// perhaps on SMP systems THERE should be lock/unlock around this
|
||||
return this->ioSeqNo;
|
||||
}
|
||||
|
||||
template < class T >
|
||||
void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO (
|
||||
epicsGuard < epicsMutex > & guard, T & io )
|
||||
{
|
||||
if ( this->pCallbackGuard.get() &&
|
||||
this->createdByThread == epicsThreadGetIdSelf () ) {
|
||||
io.destroy ( *this->pCallbackGuard.get(), guard );
|
||||
}
|
||||
else {
|
||||
// dont reverse the lock hierarchy
|
||||
epicsGuardRelease < epicsMutex > guardRelease ();
|
||||
{
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemtive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user calls this function from an auxiillary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( this->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
io.destroy ( cbGuard, guard );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ifndef oldAccessh
|
||||
|
||||
@@ -65,14 +65,15 @@ oldChannelNotify::~oldChannelNotify ()
|
||||
}
|
||||
|
||||
void oldChannelNotify::destructor (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & mutexGuard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
|
||||
this->io.destroy ( guard );
|
||||
mutexGuard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
|
||||
this->io.destroy ( cbGuard, mutexGuard );
|
||||
// no need to worry about a connect preempting here because
|
||||
// the io (the nciu) has been destroyed above
|
||||
if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) {
|
||||
this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
|
||||
this->cacCtx.decrementOutstandingIO ( mutexGuard, this->ioSeqNo );
|
||||
}
|
||||
this->~oldChannelNotify ();
|
||||
}
|
||||
@@ -159,13 +160,6 @@ void oldChannelNotify::writeException (
|
||||
__FILE__, __LINE__, *this, type, count, CA_OP_PUT );
|
||||
}
|
||||
|
||||
void * oldChannelNotify::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void oldChannelNotify::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
@@ -638,7 +632,7 @@ arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
|
||||
/*
|
||||
* ca_state ()
|
||||
*/
|
||||
enum channel_state epicsShareAPI ca_state ( chid pChan ) // X aCC 361
|
||||
enum channel_state epicsShareAPI ca_state ( chid pChan )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
if ( pChan->io.connected ( guard ) ) {
|
||||
|
||||
@@ -90,13 +90,6 @@ void putCallback::exception (
|
||||
}
|
||||
}
|
||||
|
||||
void * putCallback::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void putCallback::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -178,7 +178,7 @@ bool repeaterClient::connect ()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool repeaterClient::sendConfirm () // X aCC 361
|
||||
bool repeaterClient::sendConfirm ()
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -204,7 +204,7 @@ bool repeaterClient::sendConfirm () // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
bool repeaterClient::sendMessage ( const void *pBuf, unsigned bufSize ) // X aCC 361
|
||||
bool repeaterClient::sendMessage ( const void *pBuf, unsigned bufSize )
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -245,13 +245,6 @@ repeaterClient::~repeaterClient ()
|
||||
#endif
|
||||
}
|
||||
|
||||
void * repeaterClient::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void repeaterClient::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
@@ -304,7 +297,7 @@ inline bool repeaterClient::identicalPort ( const osiSockAddr &fromIn )
|
||||
return false;
|
||||
}
|
||||
|
||||
bool repeaterClient::verify () // X aCC 361
|
||||
bool repeaterClient::verify ()
|
||||
{
|
||||
SOCKET tmpSock;
|
||||
bool success = makeSocket ( this->port (), false, & tmpSock );
|
||||
|
||||
@@ -64,7 +64,6 @@ private:
|
||||
osiSockAddr from;
|
||||
SOCKET sock;
|
||||
unsigned short port () const;
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ void repeaterSubscribeTimer::shutdown (
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus repeaterSubscribeTimer::
|
||||
expire ( const epicsTime & /* currentTime */ ) // X aCC 361
|
||||
expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
static const unsigned nTriesToMsg = 50;
|
||||
if ( this->attempts > nTriesToMsg && ! this->once ) {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
class epicsMutex;
|
||||
class cacContextNotify;
|
||||
|
||||
class repeaterTimerNotify { // X aCC 655
|
||||
class repeaterTimerNotify {
|
||||
public:
|
||||
virtual ~repeaterTimerNotify () = 0;
|
||||
virtual void repeaterRegistrationMessage (
|
||||
|
||||
@@ -124,7 +124,7 @@ void searchTimer::moveChannels (
|
||||
// searchTimer::expire ()
|
||||
//
|
||||
epicsTimerNotify::expireStatus searchTimer::expire (
|
||||
const epicsTime & currentTime ) // X aCC 361
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "caProto.h"
|
||||
#include "netiiu.h"
|
||||
|
||||
class searchTimerNotify { // X aCC 655
|
||||
class searchTimerNotify {
|
||||
public:
|
||||
virtual ~searchTimerNotify () = 0;
|
||||
virtual void boostChannel (
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
template < class T >
|
||||
class sgAutoPtr {
|
||||
public:
|
||||
sgAutoPtr ( epicsGuard < epicsMutex > &,
|
||||
struct CASG &, tsDLList < syncGroupNotify > & );
|
||||
sgAutoPtr ( epicsGuard < epicsMutex > &, struct CASG & );
|
||||
~sgAutoPtr ();
|
||||
sgAutoPtr < T > & operator = ( T * );
|
||||
T * operator -> ();
|
||||
@@ -38,7 +37,6 @@ public:
|
||||
T * get ();
|
||||
T * release ();
|
||||
private:
|
||||
tsDLList < syncGroupNotify > & list;
|
||||
T * pNotify;
|
||||
struct CASG & sg;
|
||||
epicsGuard < epicsMutex > & guard;
|
||||
@@ -47,9 +45,8 @@ private:
|
||||
|
||||
template < class T >
|
||||
inline sgAutoPtr < T > :: sgAutoPtr (
|
||||
epicsGuard < epicsMutex > & guardIn,
|
||||
struct CASG & sgIn, tsDLList < syncGroupNotify > & listIn ) :
|
||||
list ( listIn ), pNotify ( 0 ), sg ( sgIn ), guard ( guardIn )
|
||||
epicsGuard < epicsMutex > & guardIn, struct CASG & sgIn ) :
|
||||
pNotify ( 0 ), sg ( sgIn ), guard ( guardIn )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -57,8 +54,9 @@ template < class T >
|
||||
inline sgAutoPtr < T > :: ~sgAutoPtr ()
|
||||
{
|
||||
if ( this->pNotify ) {
|
||||
list.remove ( *this->pNotify );
|
||||
pNotify->destroy ( this->guard, this->sg );
|
||||
this->sg.ioPendingList.remove ( *this->pNotify );
|
||||
this->sg.client.
|
||||
whenThereIsAnExceptionDestroySyncGroupIO ( this->guard, *this->pNotify );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +64,12 @@ template < class T >
|
||||
inline sgAutoPtr < T > & sgAutoPtr < T > :: operator = ( T * pNotifyIn )
|
||||
{
|
||||
if ( this->pNotify ) {
|
||||
list.remove ( *this->pNotify );
|
||||
pNotify->destroy ( this->guard, this->sg );
|
||||
this->sg.ioPendingList.remove ( *this->pNotify );
|
||||
this->sg.client.
|
||||
whenThereIsAnExceptionDestroySyncGroupIO ( this->guard, *this->pNotify );
|
||||
}
|
||||
this->pNotify = pNotifyIn;
|
||||
list.add ( *this->pNotify );
|
||||
this->sg.ioPendingList.add ( *this->pNotify );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,29 +46,17 @@
|
||||
|
||||
static const unsigned CASG_MAGIC = 0xFAB4CAFE;
|
||||
|
||||
// used to control access to CASG's recycle routines which
|
||||
// should only be indirectly invoked by CASG when its lock
|
||||
// is applied
|
||||
class casgRecycle { // X aCC 655
|
||||
public:
|
||||
virtual void recycleSyncGroupWriteNotify (
|
||||
epicsGuard < epicsMutex > &, class syncGroupWriteNotify & io ) = 0;
|
||||
virtual void recycleSyncGroupReadNotify (
|
||||
epicsGuard < epicsMutex > &, class syncGroupReadNotify & io ) = 0;
|
||||
protected:
|
||||
virtual ~casgRecycle ();
|
||||
};
|
||||
|
||||
class syncGroupNotify : public tsDLNode < syncGroupNotify > {
|
||||
public:
|
||||
syncGroupNotify ();
|
||||
virtual void destroy (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
casgRecycle & ) = 0;
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
virtual bool ioPending (
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
virtual void cancel (
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual void show (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned level ) const = 0;
|
||||
@@ -78,33 +66,38 @@ protected:
|
||||
syncGroupNotify & operator = ( const syncGroupNotify & );
|
||||
};
|
||||
|
||||
struct CASG;
|
||||
|
||||
class syncGroupReadNotify : public syncGroupNotify, public cacReadNotify {
|
||||
public:
|
||||
typedef void ( CASG :: * PRecycleFunc )
|
||||
( epicsGuard < epicsMutex > &, syncGroupReadNotify & );
|
||||
static syncGroupReadNotify * factory (
|
||||
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > &,
|
||||
struct CASG &, chid, void *pValueIn );
|
||||
CASG &, PRecycleFunc, chid, void *pValueIn );
|
||||
void destroy (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
casgRecycle & );
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool ioPending (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void begin ( epicsGuard < epicsMutex > &,
|
||||
unsigned type, arrayElementCount count );
|
||||
void cancel (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
protected:
|
||||
syncGroupReadNotify ( struct CASG & sgIn, chid, void * pValueIn );
|
||||
syncGroupReadNotify ( CASG & sgIn, PRecycleFunc, chid, void * pValueIn );
|
||||
virtual ~syncGroupReadNotify ();
|
||||
private:
|
||||
chid chan;
|
||||
struct CASG & sg;
|
||||
PRecycleFunc pRecycleFunc;
|
||||
CASG & sg;
|
||||
void * pValue;
|
||||
const unsigned magic;
|
||||
cacChannel::ioid id;
|
||||
bool idIsValid;
|
||||
bool ioComplete;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & );
|
||||
@@ -122,30 +115,33 @@ private:
|
||||
|
||||
class syncGroupWriteNotify : public syncGroupNotify, public cacWriteNotify {
|
||||
public:
|
||||
typedef void ( CASG :: * PRecycleFunc )
|
||||
( epicsGuard < epicsMutex > &, syncGroupWriteNotify & );
|
||||
static syncGroupWriteNotify * factory (
|
||||
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &,
|
||||
struct CASG &, chid );
|
||||
CASG &, PRecycleFunc, chid );
|
||||
void destroy (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
casgRecycle & );
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool ioPending (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void begin ( epicsGuard < epicsMutex > &, unsigned type,
|
||||
arrayElementCount count, const void * pValueIn );
|
||||
void cancel (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
protected:
|
||||
syncGroupWriteNotify ( struct CASG &, chid );
|
||||
syncGroupWriteNotify ( struct CASG &, PRecycleFunc, chid );
|
||||
virtual ~syncGroupWriteNotify (); // allocate only from pool
|
||||
private:
|
||||
chid chan;
|
||||
struct CASG & sg;
|
||||
PRecycleFunc pRecycleFunc;
|
||||
CASG & sg;
|
||||
const unsigned magic;
|
||||
cacChannel::ioid id;
|
||||
bool idIsValid;
|
||||
bool ioComplete;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > & );
|
||||
@@ -163,17 +159,19 @@ struct ca_client_context;
|
||||
|
||||
template < class T > class sgAutoPtr;
|
||||
|
||||
struct CASG : public chronIntIdRes < CASG >, private casgRecycle {
|
||||
struct CASG : public chronIntIdRes < CASG > {
|
||||
public:
|
||||
CASG ( epicsGuard < epicsMutex > &, ca_client_context & cacIn );
|
||||
void destructor (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool ioComplete (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool verify ( epicsGuard < epicsMutex > & ) const;
|
||||
int block ( epicsGuard < epicsMutex > * pcbGuard,
|
||||
epicsGuard < epicsMutex > & guard, double timeout );
|
||||
void reset ( epicsGuard < epicsMutex > & guard );
|
||||
void reset ( CallbackGuard &, epicsGuard < epicsMutex > & );
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
void show ( unsigned level ) const;
|
||||
void get ( epicsGuard < epicsMutex > &, chid pChan,
|
||||
@@ -194,6 +192,7 @@ public:
|
||||
tsFreeList < struct CASG, 128, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < struct CASG, 128, epicsMutexNOOP > & ))
|
||||
|
||||
private:
|
||||
tsDLList < syncGroupNotify > ioPendingList;
|
||||
tsDLList < syncGroupNotify > ioCompletedList;
|
||||
@@ -202,20 +201,21 @@ private:
|
||||
unsigned magic;
|
||||
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > freeListReadOP;
|
||||
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > freeListWriteOP;
|
||||
void recycleSyncGroupWriteNotify (
|
||||
epicsGuard < epicsMutex > &, syncGroupWriteNotify & io );
|
||||
void recycleSyncGroupReadNotify (
|
||||
epicsGuard < epicsMutex > &, syncGroupReadNotify & io );
|
||||
|
||||
void destroyPendingIO (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void destroyCompletedIO (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void recycleReadNotifyIO ( epicsGuard < epicsMutex > &,
|
||||
syncGroupReadNotify & );
|
||||
void recycleWriteNotifyIO ( epicsGuard < epicsMutex > &,
|
||||
syncGroupWriteNotify & );
|
||||
|
||||
CASG ( const CASG & );
|
||||
CASG & operator = ( const CASG & );
|
||||
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
|
||||
~CASG ();
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
#include "oldAccess.h"
|
||||
|
||||
syncGroupReadNotify::syncGroupReadNotify (
|
||||
CASG & sgIn, chid pChan, void * pValueIn ) :
|
||||
chan ( pChan ), sg ( sgIn ), pValue ( pValueIn ),
|
||||
CASG & sgIn, PRecycleFunc pRecycleFuncIn,
|
||||
chid pChan, void * pValueIn ) :
|
||||
chan ( pChan ), pRecycleFunc ( pRecycleFuncIn ),
|
||||
sg ( sgIn ), pValue ( pValueIn ),
|
||||
magic ( CASG_MAGIC ), id ( 0u ),
|
||||
idIsValid ( false ), ioComplete ( false )
|
||||
{
|
||||
@@ -46,27 +48,30 @@ void syncGroupReadNotify::begin (
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExcusionGuard )
|
||||
{
|
||||
if ( this->idIsValid ) {
|
||||
this->chan->ioCancel ( guard, this->id );
|
||||
this->chan->ioCancel ( callbackGuard, mutualExcusionGuard, this->id );
|
||||
this->idIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
syncGroupReadNotify * syncGroupReadNotify::factory (
|
||||
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & freeList,
|
||||
struct CASG & sg, chid chan, void * pValueIn )
|
||||
struct CASG & sg, PRecycleFunc pRecycleFunc, chid chan, void * pValueIn )
|
||||
{
|
||||
return new ( freeList ) // X aCC 930
|
||||
syncGroupReadNotify ( sg, chan, pValueIn );
|
||||
return new ( freeList )
|
||||
syncGroupReadNotify ( sg, pRecycleFunc, chan, pValueIn );
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::destroy (
|
||||
epicsGuard < epicsMutex > & guard, casgRecycle & recycle )
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
CASG & sgRef ( this->sg );
|
||||
this->~syncGroupReadNotify ();
|
||||
recycle.recycleSyncGroupReadNotify ( guard, *this );
|
||||
( sgRef.*pRecycleFunc ) ( guard, *this );
|
||||
}
|
||||
|
||||
syncGroupReadNotify::~syncGroupReadNotify ()
|
||||
@@ -122,13 +127,6 @@ void syncGroupReadNotify::show (
|
||||
}
|
||||
}
|
||||
|
||||
void * syncGroupReadNotify::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
#include "syncGroup.h"
|
||||
#include "oldAccess.h"
|
||||
|
||||
syncGroupWriteNotify::syncGroupWriteNotify ( CASG & sgIn, chid pChan ) :
|
||||
chan ( pChan ), sg ( sgIn ), magic ( CASG_MAGIC ),
|
||||
syncGroupWriteNotify::syncGroupWriteNotify ( CASG & sgIn,
|
||||
PRecycleFunc pRecycleFuncIn, chid pChan ) :
|
||||
chan ( pChan ), pRecycleFunc ( pRecycleFuncIn ),
|
||||
sg ( sgIn ), magic ( CASG_MAGIC ),
|
||||
id ( 0u ), idIsValid ( false ), ioComplete ( false )
|
||||
{
|
||||
}
|
||||
@@ -45,26 +47,29 @@ void syncGroupWriteNotify::begin (
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExcusionGuard )
|
||||
{
|
||||
if ( this->idIsValid ) {
|
||||
this->chan->ioCancel ( guard, this->id );
|
||||
this->chan->ioCancel ( callbackGuard, mutualExcusionGuard, this->id );
|
||||
this->idIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
syncGroupWriteNotify * syncGroupWriteNotify::factory (
|
||||
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &freeList,
|
||||
struct CASG & sg, chid chan )
|
||||
struct CASG & sg, PRecycleFunc pRecycleFunc, chid chan )
|
||||
{
|
||||
return new ( freeList ) syncGroupWriteNotify ( sg, chan );
|
||||
return new ( freeList ) syncGroupWriteNotify ( sg, pRecycleFunc, chan );
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::destroy (
|
||||
epicsGuard < epicsMutex > & guard, casgRecycle & recycle )
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
CASG & sgRef ( this->sg );
|
||||
this->~syncGroupWriteNotify ();
|
||||
recycle.recycleSyncGroupWriteNotify ( guard, *this );
|
||||
( sgRef.*pRecycleFunc ) ( guard, *this );
|
||||
}
|
||||
|
||||
syncGroupWriteNotify::~syncGroupWriteNotify ()
|
||||
@@ -112,13 +117,6 @@ void syncGroupWriteNotify::show (
|
||||
}
|
||||
}
|
||||
|
||||
void * syncGroupWriteNotify::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/*
|
||||
* ca_sg_create()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid ) // X aCC 361
|
||||
extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid )
|
||||
{
|
||||
ca_client_context * pcac;
|
||||
int caStatus;
|
||||
@@ -48,6 +48,22 @@ extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid ) // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
int ca_sync_group_destroy ( CallbackGuard & cbGuard, epicsGuard < epicsMutex > & guard,
|
||||
ca_client_context & cac, const CA_SYNC_GID gid )
|
||||
{
|
||||
int caStatus;
|
||||
CASG * pcasg = cac.lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
pcasg->destructor ( cbGuard, guard );
|
||||
cac.casgFreeList.release ( pcasg );
|
||||
caStatus = ECA_NORMAL;
|
||||
}
|
||||
else {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
}
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* ca_sg_delete()
|
||||
*/
|
||||
@@ -56,19 +72,51 @@ extern "C" int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid )
|
||||
ca_client_context * pcac;
|
||||
int caStatus = fetchClientContext ( & pcac );
|
||||
if ( caStatus == ECA_NORMAL ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
pcasg->destructor ( guard );
|
||||
pcac->casgFreeList.release ( pcasg );
|
||||
if ( pcac->pCallbackGuard.get() &&
|
||||
pcac->createdByThread == epicsThreadGetIdSelf () ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
caStatus = ca_sync_group_destroy ( *pcac->pCallbackGuard.get(),
|
||||
guard, *pcac, gid );
|
||||
}
|
||||
else {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemtive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user calls this function from an auxiillary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( pcac->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
caStatus = ca_sync_group_destroy ( cbGuard, guard, *pcac, gid );
|
||||
}
|
||||
}
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
void sync_group_reset ( ca_client_context & client, CASG & sg )
|
||||
{
|
||||
if ( client.pCallbackGuard.get() &&
|
||||
client.createdByThread == epicsThreadGetIdSelf () ) {
|
||||
epicsGuard < epicsMutex > guard ( client.mutex );
|
||||
sg.reset ( *client.pCallbackGuard.get(), guard );
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemtive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user calls this function from an auxiillary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( client.cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( client.mutex );
|
||||
sg.reset ( cbGuard, guard );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ca_sg_block ()
|
||||
//
|
||||
@@ -84,14 +132,20 @@ extern "C" int epicsShareAPI ca_sg_block (
|
||||
ca_client_context *pcac;
|
||||
int status = fetchClientContext ( &pcac );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
CASG * pcasg;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
status = ECA_BADSYNCGRP;
|
||||
}
|
||||
else {
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
status = pcasg->block (
|
||||
pcac->pCallbackGuard.get (), guard, timeout );
|
||||
}
|
||||
else {
|
||||
status = ECA_BADSYNCGRP;
|
||||
}
|
||||
}
|
||||
if ( pcasg ) {
|
||||
sync_group_reset ( *pcac, *pcasg );
|
||||
}
|
||||
}
|
||||
return status;
|
||||
@@ -105,10 +159,14 @@ extern "C" int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid )
|
||||
ca_client_context *pcac;
|
||||
int caStatus = fetchClientContext (&pcac);
|
||||
if ( caStatus == ECA_NORMAL ) {
|
||||
CASG * pcasg;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
}
|
||||
if ( pcasg ) {
|
||||
pcasg->reset ( guard );
|
||||
sync_group_reset ( *pcac, *pcasg );
|
||||
caStatus = ECA_NORMAL;
|
||||
}
|
||||
else {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
@@ -143,7 +201,7 @@ extern "C" int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid )
|
||||
/*
|
||||
* ca_sg_test
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) // X aCC 361
|
||||
extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid )
|
||||
{
|
||||
ca_client_context * pcac;
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
@@ -151,7 +209,26 @@ extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) // X aCC 361
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
if ( pcasg->ioComplete ( guard ) ) {
|
||||
bool isComplete;
|
||||
if ( pcac->pCallbackGuard.get() &&
|
||||
pcac->createdByThread == epicsThreadGetIdSelf () ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
isComplete = pcasg->ioComplete ( *pcac->pCallbackGuard.get(), guard );
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemtive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user calls this function from an auxiillary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( pcac->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
isComplete = pcasg->ioComplete ( cbGuard, guard );
|
||||
}
|
||||
if ( isComplete ) {
|
||||
caStatus = ECA_IODONE;
|
||||
}
|
||||
else{
|
||||
@@ -172,17 +249,14 @@ extern "C" int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype typ
|
||||
arrayElementCount count, chid pChan, const void *pValue )
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
CASG *pcasg;
|
||||
int caStatus;
|
||||
|
||||
caStatus = fetchClientContext ( &pcac );
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
CASG * const pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
@@ -237,17 +311,14 @@ extern "C" int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid, chtype typ
|
||||
arrayElementCount count, chid pChan, void *pValue )
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
CASG *pcasg;
|
||||
int caStatus;
|
||||
|
||||
caStatus = fetchClientContext ( &pcac );
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
CASG * const pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ tcpRecvWatchdog::~tcpRecvWatchdog ()
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus
|
||||
tcpRecvWatchdog::expire ( const epicsTime & /* currentTime */ ) // X aCC 361
|
||||
tcpRecvWatchdog::expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( this->shuttingDown ) {
|
||||
|
||||
@@ -1135,7 +1135,7 @@ void tcpiiu::show ( unsigned level ) const
|
||||
}
|
||||
}
|
||||
|
||||
bool tcpiiu::setEchoRequestPending ( epicsGuard < epicsMutex > & guard ) // X aCC 361
|
||||
bool tcpiiu::setEchoRequestPending ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1275,12 +1275,9 @@ bool tcpiiu::processIncoming (
|
||||
this->msgHeaderAvailable = false;
|
||||
this->curDataBytes = 0u;
|
||||
}
|
||||
# if defined ( __HP_aCC ) && _HP_aCC <= 033300
|
||||
return false; // to make hpux compiler happy...
|
||||
# endif
|
||||
}
|
||||
|
||||
void tcpiiu::hostNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
void tcpiiu::hostNameSetRequest ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1310,7 +1307,7 @@ void tcpiiu::hostNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 4
|
||||
/*
|
||||
* tcpiiu::userNameSetRequest ()
|
||||
*/
|
||||
void tcpiiu::userNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
void tcpiiu::userNameSetRequest ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1338,7 +1335,7 @@ void tcpiiu::userNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 4
|
||||
}
|
||||
|
||||
void tcpiiu::disableFlowControlRequest (
|
||||
epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1354,7 +1351,7 @@ void tcpiiu::disableFlowControlRequest (
|
||||
}
|
||||
|
||||
void tcpiiu::enableFlowControlRequest (
|
||||
epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1369,7 +1366,7 @@ void tcpiiu::enableFlowControlRequest (
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::versionMessage ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::versionMessage ( epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::priLev & priority )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1389,7 +1386,7 @@ void tcpiiu::versionMessage ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::echoRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
void tcpiiu::echoRequest ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1410,7 +1407,7 @@ void tcpiiu::echoRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::writeRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::writeRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu &chan, unsigned type, arrayElementCount nElem, const void *pValue )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1425,7 +1422,7 @@ void tcpiiu::writeRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
}
|
||||
|
||||
|
||||
void tcpiiu::writeNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::writeNotifyRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu &chan, netWriteNotifyIO &io, unsigned type,
|
||||
arrayElementCount nElem, const void *pValue )
|
||||
{
|
||||
@@ -1444,7 +1441,7 @@ void tcpiiu::writeNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 43
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netReadNotifyIO & io,
|
||||
unsigned dataType, arrayElementCount nElem )
|
||||
{
|
||||
@@ -1477,7 +1474,7 @@ void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
}
|
||||
|
||||
void tcpiiu::createChannelRequest (
|
||||
nciu & chan, epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
nciu & chan, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1525,7 +1522,7 @@ void tcpiiu::createChannelRequest (
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::clearChannelRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::clearChannelRequest ( epicsGuard < epicsMutex > & guard,
|
||||
ca_uint32_t sid, ca_uint32_t cid )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1547,7 +1544,7 @@ void tcpiiu::clearChannelRequest ( epicsGuard < epicsMutex > & guard, // X aCC 4
|
||||
// is to try again the next time that we reconnect
|
||||
//
|
||||
void tcpiiu::subscriptionRequest (
|
||||
epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netSubscription & subscr )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1599,7 +1596,7 @@ void tcpiiu::subscriptionRequest (
|
||||
// is to try again the next time that we reconnect
|
||||
//
|
||||
void tcpiiu::subscriptionUpdateRequest (
|
||||
epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netSubscription & subscr )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1634,7 +1631,7 @@ void tcpiiu::subscriptionUpdateRequest (
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netSubscription & subscr )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -2052,7 +2049,7 @@ bool tcpiiu::bytesArePendingInOS () const
|
||||
return false;
|
||||
#else
|
||||
osiSockIoctl_t bytesPending = 0; /* shut up purifys yapping */
|
||||
int status = socket_ioctl ( this->sock, // X aCC 392
|
||||
int status = socket_ioctl ( this->sock,
|
||||
FIONREAD, & bytesPending );
|
||||
if ( status >= 0 ) {
|
||||
if ( bytesPending > 0 ) {
|
||||
|
||||
@@ -78,6 +78,10 @@ template comBuf :: popStatus comBuf :: pop ( unsigned char & returnVal );
|
||||
template void WireSet ( float const &, unsigned char * );
|
||||
template void WireSet ( int const &, unsigned char * );
|
||||
template void WireSet ( short const &, unsigned char * );
|
||||
template void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO
|
||||
(epicsGuard < epicsMutex > &, syncGroupWriteNotify & );
|
||||
template void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO
|
||||
( epicsGuard < epicsMutex > &, syncGroupReadNotify & );
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -78,7 +78,7 @@ extern "C" void epicsShareAPI ca_dump_dbr (
|
||||
dbr_short_t *pvalue = (dbr_short_t *)pbuffer;
|
||||
for (i = 0; i < count; i++,pvalue++){
|
||||
if(count!=1 && (i%10 == 0)) printf("\n");
|
||||
printf("%d ",* (short *)pvalue); // X aCC 392
|
||||
printf("%d ",* (short *)pvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ extern "C" void epicsShareAPI ca_dump_dbr (
|
||||
dbr_float_t *pvalue = (dbr_float_t *)pbuffer;
|
||||
for (i = 0; i < count; i++,pvalue++){
|
||||
if(count!=1 && (i%10 == 0)) printf("\n");
|
||||
printf("%6.4f ",*(float *)pvalue); // X aCC 392
|
||||
printf("%6.4f ",*(float *)pvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ udpiiu::udpiiu (
|
||||
memset ( (char *)&addr, 0 , sizeof (addr) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( PORT_ANY ); // X aCC 818
|
||||
addr.ia.sin_port = htons ( PORT_ANY );
|
||||
status = bind (this->sock, &addr.sa, sizeof (addr) );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -471,7 +471,7 @@ void epicsShareAPI caRepeaterRegistrationMessage (
|
||||
}
|
||||
|
||||
memset ( (char *) &msg, 0, sizeof (msg) );
|
||||
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = REPEATER_REGISTER; // X aCC 818
|
||||
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = REPEATER_REGISTER;
|
||||
msg.m_available = saddr.ia.sin_addr.s_addr;
|
||||
|
||||
/*
|
||||
|
||||
@@ -335,7 +335,6 @@ private:
|
||||
|
||||
tcpiiu ( const tcpiiu & );
|
||||
tcpiiu & operator = ( const tcpiiu & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -372,7 +371,7 @@ inline bool tcpiiu::ca_v49_ok (
|
||||
}
|
||||
|
||||
inline bool tcpiiu::alive (
|
||||
epicsGuard < epicsMutex > & ) const // X aCC 361
|
||||
epicsGuard < epicsMutex > & ) const
|
||||
{
|
||||
return ( this->state == iiucs_connecting ||
|
||||
this->state == iiucs_connected );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl -w
|
||||
#!/usr/bin/env perl
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# This script is used to extract information about the Perl build
|
||||
# configuration, so the EPICS build system uses the same settings.
|
||||
|
||||
0
src/cas/build/cas.rc
Executable file → Normal file
0
src/cas/build/cas.rc
Executable file → Normal file
@@ -3,9 +3,8 @@
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* $Revision-Id$
|
||||
@@ -15,8 +14,8 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "dbMapper.h" // ait to dbr types
|
||||
#include "gddAppTable.h" // EPICS application type table
|
||||
#include "dbMapper.h" // ait to dbr types
|
||||
#include "gddAppTable.h" // EPICS application type table
|
||||
#include "fdManager.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
@@ -37,67 +36,67 @@ caServer::caServer ()
|
||||
|
||||
caServer::~caServer()
|
||||
{
|
||||
if (this->pCAS) {
|
||||
delete this->pCAS;
|
||||
if (this->pCAS) {
|
||||
delete this->pCAS;
|
||||
this->pCAS = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pvExistReturn caServer::pvExistTest ( const casCtx & ctx,
|
||||
const caNetAddr & /* clientAddress */, const char * pPVAliasName )
|
||||
const caNetAddr & /* clientAddress */, const char * pPVAliasName )
|
||||
{
|
||||
return this->pvExistTest ( ctx, pPVAliasName );
|
||||
}
|
||||
|
||||
pvExistReturn caServer::pvExistTest ( const casCtx &, const char * )
|
||||
{
|
||||
return pverDoesNotExistHere;
|
||||
return pverDoesNotExistHere;
|
||||
}
|
||||
|
||||
pvCreateReturn caServer::createPV ( const casCtx &, const char * )
|
||||
{
|
||||
return S_casApp_pvNotFound;
|
||||
return S_casApp_pvNotFound;
|
||||
}
|
||||
|
||||
pvAttachReturn caServer::pvAttach ( const casCtx &ctx, const char *pAliasName )
|
||||
{
|
||||
// remain backwards compatible (call deprecated routine)
|
||||
return this->createPV ( ctx, pAliasName );
|
||||
// remain backwards compatible (call deprecated routine)
|
||||
return this->createPV ( ctx, pAliasName );
|
||||
}
|
||||
|
||||
casEventMask caServer::registerEvent (const char *pName) // X aCC 361
|
||||
casEventMask caServer::registerEvent (const char *pName)
|
||||
{
|
||||
if (this->pCAS) {
|
||||
return this->pCAS->registerEvent(pName);
|
||||
}
|
||||
else {
|
||||
casEventMask emptyMask;
|
||||
printf("caServer:: no server internals attached\n");
|
||||
return emptyMask;
|
||||
}
|
||||
if (this->pCAS) {
|
||||
return this->pCAS->registerEvent(pName);
|
||||
}
|
||||
else {
|
||||
casEventMask emptyMask;
|
||||
printf("caServer:: no server internals attached\n");
|
||||
return emptyMask;
|
||||
}
|
||||
}
|
||||
|
||||
void caServer::show(unsigned level) const
|
||||
{
|
||||
if (this->pCAS) {
|
||||
this->pCAS->show(level);
|
||||
}
|
||||
else {
|
||||
printf("caServer:: no server internals attached\n");
|
||||
}
|
||||
if (this->pCAS) {
|
||||
this->pCAS->show(level);
|
||||
}
|
||||
else {
|
||||
printf("caServer:: no server internals attached\n");
|
||||
}
|
||||
}
|
||||
|
||||
void caServer::setDebugLevel (unsigned level)
|
||||
{
|
||||
if (pCAS) {
|
||||
this->pCAS->setDebugLevel(level);
|
||||
}
|
||||
else {
|
||||
printf("caServer:: no server internals attached\n");
|
||||
}
|
||||
if (pCAS) {
|
||||
this->pCAS->setDebugLevel(level);
|
||||
}
|
||||
else {
|
||||
printf("caServer:: no server internals attached\n");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned caServer::getDebugLevel () const // X aCC 361
|
||||
unsigned caServer::getDebugLevel () const
|
||||
{
|
||||
if (pCAS) {
|
||||
return this->pCAS->getDebugLevel();
|
||||
@@ -108,7 +107,7 @@ unsigned caServer::getDebugLevel () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
casEventMask caServer::valueEventMask () const // X aCC 361
|
||||
casEventMask caServer::valueEventMask () const
|
||||
{
|
||||
if (pCAS) {
|
||||
return this->pCAS->valueEventMask();
|
||||
@@ -119,7 +118,7 @@ casEventMask caServer::valueEventMask () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
casEventMask caServer::logEventMask () const // X aCC 361
|
||||
casEventMask caServer::logEventMask () const
|
||||
{
|
||||
if (pCAS) {
|
||||
return this->pCAS->logEventMask();
|
||||
@@ -130,7 +129,7 @@ casEventMask caServer::logEventMask () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
casEventMask caServer::alarmEventMask () const // X aCC 361
|
||||
casEventMask caServer::alarmEventMask () const
|
||||
{
|
||||
if ( pCAS ) {
|
||||
return this->pCAS->alarmEventMask ();
|
||||
@@ -141,12 +140,23 @@ casEventMask caServer::alarmEventMask () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
casEventMask caServer::propertyEventMask () const
|
||||
{
|
||||
if (pCAS) {
|
||||
return this->pCAS->propertyEventMask();
|
||||
}
|
||||
else {
|
||||
printf("caServer:: no server internals attached\n");
|
||||
return casEventMask();
|
||||
}
|
||||
}
|
||||
|
||||
class epicsTimer & caServer::createTimer ()
|
||||
{
|
||||
return fileDescriptorManager.createTimer ();
|
||||
}
|
||||
|
||||
unsigned caServer::subscriptionEventsProcessed () const // X aCC 361
|
||||
unsigned caServer::subscriptionEventsProcessed () const
|
||||
{
|
||||
if ( pCAS ) {
|
||||
return this->pCAS->subscriptionEventsProcessed ();
|
||||
@@ -156,7 +166,7 @@ unsigned caServer::subscriptionEventsProcessed () const // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
unsigned caServer::subscriptionEventsPosted () const // X aCC 361
|
||||
unsigned caServer::subscriptionEventsPosted () const
|
||||
{
|
||||
if ( pCAS ) {
|
||||
return this->pCAS->subscriptionEventsPosted ();
|
||||
|
||||
@@ -47,22 +47,23 @@ caServerI::caServerI ( caServer & tool ) :
|
||||
nEventsPosted ( 0u ),
|
||||
ioInProgressCount ( 0u )
|
||||
{
|
||||
assert ( & adapter != NULL );
|
||||
assert ( & adapter != NULL );
|
||||
|
||||
// create predefined event types
|
||||
this->valueEvent = registerEvent ( "value" );
|
||||
this->logEvent = registerEvent ( "log" );
|
||||
this->alarmEvent = registerEvent ( "alarm" );
|
||||
this->logEvent = registerEvent ( "log" );
|
||||
this->alarmEvent = registerEvent ( "alarm" );
|
||||
this->propertyEvent = registerEvent ( "property" );
|
||||
|
||||
this->locateInterfaces ();
|
||||
|
||||
if (this->intfList.count()==0u) {
|
||||
errMessage (S_cas_noInterface,
|
||||
if (this->intfList.count()==0u) {
|
||||
errMessage (S_cas_noInterface,
|
||||
"- CA server internals init unable to continue");
|
||||
throw S_cas_noInterface;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
caServerI::~caServerI()
|
||||
@@ -70,22 +71,22 @@ caServerI::~caServerI()
|
||||
delete & this->beaconAnomalyGov;
|
||||
delete & this->beaconTmr;
|
||||
|
||||
// delete all clients
|
||||
// delete all clients
|
||||
while ( casStrmClient * pClient = this->clientList.get() ) {
|
||||
delete pClient;
|
||||
}
|
||||
delete pClient;
|
||||
}
|
||||
|
||||
casIntfOS *pIF;
|
||||
while ( ( pIF = this->intfList.get() ) ) {
|
||||
delete pIF;
|
||||
}
|
||||
casIntfOS *pIF;
|
||||
while ( ( pIF = this->intfList.get() ) ) {
|
||||
delete pIF;
|
||||
}
|
||||
}
|
||||
|
||||
void caServerI::destroyClient ( casStrmClient & client )
|
||||
{
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
this->clientList.remove ( client );
|
||||
this->clientList.remove ( client );
|
||||
}
|
||||
delete & client;
|
||||
}
|
||||
@@ -143,11 +144,11 @@ caStatus caServerI::attachInterface ( const caNetAddr & addrIn,
|
||||
void caServerI::sendBeacon ( ca_uint32_t beaconNo )
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
tsDLIter < casIntfOS > iter = this->intfList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->sendBeacon ( beaconNo );
|
||||
iter++;
|
||||
}
|
||||
tsDLIter < casIntfOS > iter = this->intfList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
iter->sendBeacon ( beaconNo );
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void caServerI::generateBeaconAnomaly ()
|
||||
@@ -259,11 +260,11 @@ void caServerI::casMonitorDestroy ( casMonitor & cm )
|
||||
}
|
||||
|
||||
//
|
||||
// caServerI::dumpMsg()
|
||||
// caServerI::dumpMsg()
|
||||
//
|
||||
// Debug aid - print the header part of a message.
|
||||
// Debug aid - print the header part of a message.
|
||||
//
|
||||
// dp arg allowed to be null
|
||||
// dp arg allowed to be null
|
||||
//
|
||||
//
|
||||
void caServerI::dumpMsg ( const char * pHostName, const char * pUserName,
|
||||
|
||||
@@ -44,23 +44,24 @@ caStatus convertContainerMemberToAtomic ( class gdd & dd,
|
||||
aitUint32 appType, aitUint32 elemCount );
|
||||
|
||||
class caServerI :
|
||||
public caServerIO,
|
||||
public ioBlockedList,
|
||||
public casEventRegistry {
|
||||
public caServerIO,
|
||||
public ioBlockedList,
|
||||
public casEventRegistry {
|
||||
public:
|
||||
caServerI ( caServer &tool );
|
||||
~caServerI ();
|
||||
bool roomForNewChannel() const;
|
||||
unsigned getDebugLevel() const { return debugLevel; }
|
||||
inline void setDebugLevel ( unsigned debugLevelIn );
|
||||
void show ( unsigned level ) const;
|
||||
caServerI ( caServer &tool );
|
||||
~caServerI ();
|
||||
bool roomForNewChannel() const;
|
||||
unsigned getDebugLevel() const { return debugLevel; }
|
||||
inline void setDebugLevel ( unsigned debugLevelIn );
|
||||
void show ( unsigned level ) const;
|
||||
void destroyMonitor ( casMonitor & );
|
||||
caServer * getAdapter ();
|
||||
caServer * operator -> ();
|
||||
void connectCB ( casIntfOS & );
|
||||
casEventMask valueEventMask () const; // DBE_VALUE registerEvent("value")
|
||||
casEventMask logEventMask () const; // DBE_LOG registerEvent("log")
|
||||
casEventMask alarmEventMask () const; // DBE_ALARM registerEvent("alarm")
|
||||
caServer * getAdapter ();
|
||||
caServer * operator -> ();
|
||||
void connectCB ( casIntfOS & );
|
||||
casEventMask valueEventMask () const; // DBE_VALUE registerEvent("value")
|
||||
casEventMask logEventMask () const; // DBE_LOG registerEvent("log")
|
||||
casEventMask alarmEventMask () const; // DBE_ALARM registerEvent("alarm")
|
||||
casEventMask propertyEventMask () const; // DBE_PROPERTY registerEvent("property")
|
||||
unsigned subscriptionEventsProcessed () const;
|
||||
void incrEventsProcessedCounter ();
|
||||
unsigned subscriptionEventsPosted () const;
|
||||
@@ -82,29 +83,30 @@ public:
|
||||
private:
|
||||
clientBufMemoryManager clientBufMemMgr;
|
||||
tsFreeList < casMonitor, 1024 > casMonitorFreeList;
|
||||
tsDLList < casStrmClient > clientList;
|
||||
tsDLList < casStrmClient > clientList;
|
||||
tsDLList < casIntfOS > intfList;
|
||||
mutable epicsMutex mutex;
|
||||
mutable epicsMutex diagnosticCountersMutex;
|
||||
caServer & adapter;
|
||||
mutable epicsMutex mutex;
|
||||
mutable epicsMutex diagnosticCountersMutex;
|
||||
caServer & adapter;
|
||||
beaconTimer & beaconTmr;
|
||||
beaconAnomalyGovernor & beaconAnomalyGov;
|
||||
unsigned debugLevel;
|
||||
unsigned debugLevel;
|
||||
unsigned nEventsProcessed;
|
||||
unsigned nEventsPosted;
|
||||
unsigned ioInProgressCount;
|
||||
|
||||
casEventMask valueEvent; // DBE_VALUE registerEvent("value")
|
||||
casEventMask logEvent; // DBE_LOG registerEvent("log")
|
||||
casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm")
|
||||
casEventMask logEvent; // DBE_LOG registerEvent("log")
|
||||
casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm")
|
||||
casEventMask propertyEvent; // DBE_PROPERTY registerEvent("property")
|
||||
|
||||
caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr,
|
||||
bool addConfigAddr );
|
||||
caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr,
|
||||
bool addConfigAddr );
|
||||
|
||||
void sendBeacon ( ca_uint32_t beaconNo );
|
||||
|
||||
caServerI ( const caServerI & );
|
||||
caServerI & operator = ( const caServerI & );
|
||||
caServerI ( const caServerI & );
|
||||
caServerI & operator = ( const caServerI & );
|
||||
|
||||
friend class beaconAnomalyGovernor;
|
||||
friend class beaconTimer;
|
||||
@@ -113,17 +115,17 @@ private:
|
||||
|
||||
inline caServer * caServerI::getAdapter()
|
||||
{
|
||||
return & this->adapter;
|
||||
return & this->adapter;
|
||||
}
|
||||
|
||||
inline caServer * caServerI::operator -> ()
|
||||
{
|
||||
return this->getAdapter();
|
||||
return this->getAdapter();
|
||||
}
|
||||
|
||||
inline void caServerI::setDebugLevel(unsigned debugLevelIn)
|
||||
{
|
||||
this->debugLevel = debugLevelIn;
|
||||
this->debugLevel = debugLevelIn;
|
||||
}
|
||||
|
||||
inline casEventMask caServerI::valueEventMask() const
|
||||
@@ -141,6 +143,11 @@ inline casEventMask caServerI::alarmEventMask() const
|
||||
return this->alarmEvent;
|
||||
}
|
||||
|
||||
inline casEventMask caServerI::propertyEventMask() const
|
||||
{
|
||||
return this->propertyEvent;
|
||||
}
|
||||
|
||||
inline bool caServerI :: ioIsPending () const
|
||||
{
|
||||
return ( ioInProgressCount > 0u );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -245,6 +245,7 @@ public:
|
||||
epicsShareFunc casEventMask valueEventMask () const; // DBE_VALUE
|
||||
epicsShareFunc casEventMask logEventMask () const; // DBE_LOG
|
||||
epicsShareFunc casEventMask alarmEventMask () const; // DBE_ALARM
|
||||
epicsShareFunc casEventMask propertyEventMask () const; // DBE_PROPERTY
|
||||
|
||||
epicsShareFunc void setDebugLevel ( unsigned level );
|
||||
epicsShareFunc unsigned getDebugLevel () const;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user