Compare commits
60 Commits
R3.14.12.1
...
R3.14.12.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db0c9d7d82 | ||
|
|
b791a3692b | ||
|
|
0e41c03ff2 | ||
|
|
b5ec6e2448 | ||
|
|
d077c8b0ff | ||
|
|
b48979f5a5 | ||
|
|
967ce8eb84 | ||
|
|
b27e22d75e | ||
|
|
6ef52b5d03 | ||
|
|
652235ef13 | ||
|
|
5b46eebe1a | ||
|
|
a252218e69 | ||
|
|
fae5bbcf86 | ||
|
|
a0c1c0fb15 | ||
|
|
bb14c6594b | ||
|
|
0dfbd460e1 | ||
|
|
b36b07db9e | ||
|
|
ee95f0c4b7 | ||
|
|
d72b4a3c1e | ||
|
|
21b4acfa86 | ||
|
|
96cad82a2a | ||
|
|
d088d4b664 | ||
|
|
6cb9a3f7c1 | ||
|
|
6c4164d953 | ||
|
|
3a101aa697 | ||
|
|
46ea687c6d | ||
|
|
75aa05d30f | ||
|
|
3cfa011760 | ||
|
|
83e5247ed4 | ||
|
|
f203e9a48b | ||
|
|
14e7111e72 | ||
|
|
2b65025d93 | ||
|
|
2b4edba8f3 | ||
|
|
35b72b60fb | ||
|
|
d286a81ef0 | ||
|
|
bc4a7854ec | ||
|
|
f59825a462 | ||
|
|
7783f0044b | ||
|
|
1b9ca756cc | ||
|
|
f9f8d1150c | ||
|
|
e71785edf6 | ||
|
|
a367e4be95 | ||
|
|
a80bd1a630 | ||
|
|
515712c0e7 | ||
|
|
2fb7df8548 | ||
|
|
4448a5501a | ||
|
|
dafb7d5d4c | ||
|
|
5343b836b8 | ||
|
|
d0423738d1 | ||
|
|
3bf5b21f57 | ||
|
|
8d15407e2f | ||
|
|
7560fb1bb1 | ||
|
|
445b5e473b | ||
|
|
f18b435cf6 | ||
|
|
5649e15842 | ||
|
|
43f58c990a | ||
|
|
0dfc92f48d | ||
|
|
f1a646240b | ||
|
|
ce0114418f | ||
|
|
342920b1db |
9
LICENSE
9
LICENSE
@@ -1,11 +1,14 @@
|
||||
Copyright (c) 1991-2007 UChicago Argonne LLC and The Regents of the
|
||||
University of California. All rights reserved.
|
||||
Copyright (c) 1991-2011 UChicago Argonne LLC.
|
||||
Copyright (c) 1991-2006 The Regents of the University of California.
|
||||
Copyright (c) 2006-2011. Los Alamos National Security, LLC. Some of this
|
||||
material was produced under U.S. Government contract DE-AC52-06NA25396
|
||||
for Los Alamos National Laboratory (LANL), which is operated by Los Alamos
|
||||
National Security, LLC for the U.S. Department of Energy.
|
||||
|
||||
EPICS BASE is distributed subject to the following license conditions:
|
||||
|
||||
SOFTWARE LICENSE AGREEMENT
|
||||
Software: EPICS BASE
|
||||
Versions: 3.13.7 and higher
|
||||
|
||||
1. The "Software", below, refers to EPICS BASE (in either source code, or
|
||||
binary form and accompanying documentation). Each licensee is
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
@@ -34,6 +34,7 @@
|
||||
# LIBSRCS source files for building libraries (deprecated)
|
||||
# PROD_OBJS object files for building prods
|
||||
# LIB_OBJS object files for building libraries
|
||||
# USR_OBJS object files for building libraries and prods
|
||||
# USR_LIBS libs needed by PROD and TESTPROD and LIBRARY
|
||||
# PROD_LIBS libs needed by PROD and TESTPROD
|
||||
# LIB_LIBS libs needed by shared LIBRARY
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
@@ -19,30 +19,30 @@
|
||||
|
||||
BASE_3_14=YES
|
||||
|
||||
# EPICS_VERSION must be a number >0 and <256
|
||||
# EPICS_VERSION must be a number >0 and <256
|
||||
EPICS_VERSION = 3
|
||||
|
||||
# EPICS_REVISION must be a number >=0 and <256
|
||||
# EPICS_REVISION must be a number >=0 and <256
|
||||
EPICS_REVISION = 14
|
||||
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 12
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included if zero
|
||||
EPICS_PATCH_LEVEL = 1
|
||||
EPICS_PATCH_LEVEL = 2
|
||||
|
||||
# This will end in -DEV between official releases
|
||||
#EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#PICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre2
|
||||
#EPICS_DEV_SNAPSHOT=-pre2-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc1
|
||||
EPICS_DEV_SNAPSHOT=-rc1
|
||||
#EPICS_DEV_SNAPSHOT=-rc1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc2
|
||||
#EPICS_DEV_SNAPSHOT=-rc2-DEV
|
||||
EPICS_DEV_SNAPSHOT=
|
||||
#EPICS_DEV_SNAPSHOT=
|
||||
|
||||
# No changes should be needed below here
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
#*************************************************************************
|
||||
#
|
||||
@@ -82,7 +81,8 @@ COMMON_DIR = ../O.Common
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Make echo output - suppress echoing if make's '-s' flag is set
|
||||
ECHO := $(if $(findstring s,$(MAKEFLAGS)),\#,@echo)
|
||||
COMMENT = \#
|
||||
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(COMMENT),echo)
|
||||
|
||||
#-------------------------------------------------------
|
||||
ifdef T_A
|
||||
@@ -335,7 +335,7 @@ HDEPENDS_CFLAGS = $(HDEPENDS_CFLAGS_$(HDEPENDS))
|
||||
#--------------------------------------------------
|
||||
# depends definition
|
||||
|
||||
TARGET_SRCS = $(foreach name, $(TESTPROD) $(PROD) $(LIBRARY), $($(name)_SRCS))
|
||||
TARGET_SRCS = $(foreach name, $(TESTPROD) $(PROD) $(LIBRARY) $(LOADABLE_LIBRARY), $($(name)_SRCS))
|
||||
SRC_FILES = $(LIB_SRCS) $(LIBSRCS) $(SRCS) $(USR_SRCS) $(PROD_SRCS) $(TARGET_SRCS)
|
||||
HDEPENDS_FILES_YES = $(addsuffix $(DEP),$(notdir $(basename $(SRC_FILES))))
|
||||
HDEPENDS_FILES = $(if $(filter NO,$(HDEPENDS)),,$(HDEPENDS_FILES_YES))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
#*************************************************************************
|
||||
#RULES.Db
|
||||
@@ -23,8 +22,8 @@ vpath %.acs $(USR_VPATH) $(GENERIC_SRC_DIRS) $(COMMON_DIR)
|
||||
##################################################### dbdflags
|
||||
|
||||
# dbExpand
|
||||
INSTALL_DBDFLAGS += -I $(INSTALL_LOCATION)/dbd
|
||||
INSTALL_DBFLAGS += -I $(INSTALL_LOCATION)/db
|
||||
INSTALL_DBDFLAGS += -I $(INSTALL_DBD)
|
||||
INSTALL_DBFLAGS += -I $(INSTALL_DB)
|
||||
DBDFLAGS = $(USR_DBDFLAGS) -I . -I .. $(INSTALL_DBDFLAGS) $(RELEASE_DBDFLAGS)
|
||||
DBFLAGS = $($*_DBFLAGS) $(USR_DBFLAGS) -I. -I.. $(INSTALL_DBFLAGS) $(RELEASE_DBFLAGS)
|
||||
|
||||
@@ -48,7 +47,7 @@ DBFLAGS = $($*_DBFLAGS) $(USR_DBFLAGS) -I. -I.. $(INSTALL_DBFLAGS) $(RELEASE_DBF
|
||||
# Following line added for backward compatibilty
|
||||
DBD += $(DBDNAME)
|
||||
|
||||
DBDINC_NAME = $(patsubst %.h,%,$(patsubst %.db,%,$(DBDINC)))
|
||||
DBDINC_NAME = $(patsubst %.h,%,$(patsubst %.dbd,%,$(DBDINC)))
|
||||
DBD += $(addsuffix .dbd,$(DBDINC_NAME))
|
||||
INC += $(addsuffix .h,$(DBDINC_NAME))
|
||||
|
||||
@@ -122,7 +121,7 @@ MAKEDBDEPENDS = $(PERL) $(TOOLS)/makeDbDepends.pl
|
||||
|
||||
ifndef T_A
|
||||
|
||||
ECHO := $(if $(findstring s,$(MAKEFLAGS)),\#,@echo)
|
||||
ECHO := $(if $(findstring s,$(MAKEFLAGS)),$(COMMENT),@echo)
|
||||
COMMON_DIR = .
|
||||
INSTALL_DBDS =
|
||||
INSTALL_DBS =
|
||||
@@ -224,58 +223,65 @@ $(INSTALL_DB)/%.template: %.template
|
||||
$(COMMON_DIR)/%Record.h: $(COMMON_DIR)/%Record.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
$(ECHO) "$<:../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $@
|
||||
$(DBTORECORDTYPEH) $(DBDFLAGS) $< $@
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTORECORDTYPEH) $(DBDFLAGS) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%Record.h: %Record.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
$(ECHO) "$<:../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $@
|
||||
$(DBTORECORDTYPEH) $(DBDFLAGS) $< $@
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTORECORDTYPEH) $(DBDFLAGS) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/menu%.h: $(COMMON_DIR)/menu%.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
$(ECHO) "$<:../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $@
|
||||
$(DBTOMENUH) $(DBDFLAGS) $< $@
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTOMENUH) $(DBDFLAGS) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/menu%.h: menu%.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
$(ECHO) "$<:../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $@
|
||||
$(DBTOMENUH) $(DBDFLAGS) $< $@
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTOMENUH) $(DBDFLAGS) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
.PRECIOUS: $(COMMON_DIR)/%.h
|
||||
|
||||
##################################################### DBD files
|
||||
|
||||
$(COMMON_DIR)/bpt%.dbd: bpt%.data
|
||||
@$(RM) $@
|
||||
$(MAKEBPT) $< $@
|
||||
$(MAKEBPT) $< $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%.dbd: $(COMMON_DIR)/%Include.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
$(ECHO) "$<:../Makefile" >> $(notdir $@)$(DEP)
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
$(ECHO) "Expanding dbd"
|
||||
@$(RM) $@
|
||||
@$(DBEXPAND) $(DBDFLAGS) -o $@ $<
|
||||
@$(RM) $(notdir $@)
|
||||
@$(DBEXPAND) $(DBDFLAGS) -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%.dbd: %Include.dbd
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
@$(DBDDEPENDS_CMD)
|
||||
$(ECHO) "$<:../Makefile" >> $(notdir $@)$(DEP)
|
||||
echo "$< : ../Makefile" >> $(notdir $@)$(DEP)
|
||||
$(ECHO) "Expanding dbd"
|
||||
@$(RM) $@
|
||||
$(DBEXPAND) $(DBDFLAGS) -o $@ $<
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBEXPAND) $(DBDFLAGS) -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%Include.dbd:
|
||||
@$(RM) $@
|
||||
$(PERL) $(TOOLS)/makeIncludeDbd.pl $($*_DBD) $@
|
||||
@$(RM) $(notdir $@)
|
||||
$(PERL) $(TOOLS)/makeIncludeDbd.pl $($*_DBD) $(notdir $@)
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(INSTALL_DBD)/%: $(COMMON_DIR)/%
|
||||
$(ECHO) "Installing created dbd file $@"
|
||||
@@ -303,8 +309,8 @@ $(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf
|
||||
|
||||
$(COMMON_DIR)/%.db$(RAW): %.substitutions
|
||||
@$(RM) $(notdir $@)$(DEP)
|
||||
$(MAKEDBDEPENDS) $@ $< $(TEMPLATE_FILENAME) >> $(notdir $@)$(DEP)
|
||||
$(ECHO) "$@:$(TEMPLATE_FILENAME)" >> $(notdir $@)$(DEP)
|
||||
@$(MAKEDBDEPENDS) $@ $< $(TEMPLATE_FILENAME) >> $(notdir $@)$(DEP)
|
||||
echo "$@ : $(TEMPLATE_FILENAME)" >> $(notdir $@)$(DEP)
|
||||
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
|
||||
@$(RM) $@ $*.tmp
|
||||
$(MSI) $(DBFLAGS) -S$< $(TEMPLATE_FILENAME) > $*.tmp
|
||||
|
||||
@@ -205,11 +205,6 @@ $(OBJLIBNAME):%$(OBJ):
|
||||
@$(RM) $@
|
||||
$(COMPILE.cpp) $(call PATH_FILTER,$<) $(COMPILE_FILTER.cpp)
|
||||
|
||||
%$(OBJ): %.C
|
||||
@$(HDEPENDS_CMD)
|
||||
@$(RM) $@
|
||||
$(COMPILE.cpp) $(call PATH_FILTER,$<) $(COMPILE_FILTER.cpp)
|
||||
|
||||
# WIN95/NT resource compiler
|
||||
%$(RES): %.rc
|
||||
@$(RM) $@
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
#*************************************************************************
|
||||
#
|
||||
@@ -13,73 +12,73 @@
|
||||
|
||||
include $(CONFIG)/RULES_DIRS
|
||||
|
||||
distclean: realclean cvsclean realuninstall
|
||||
|
||||
CVSCLEAN=$(firstword $(wildcard $(TOOLS)/cvsclean.pl $(TOP)/src/tools/cvsclean.pl))
|
||||
cvsclean:
|
||||
$(PERL) $(CVSCLEAN)
|
||||
|
||||
realuninstall: uninstallDirs
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
|
||||
UNINSTALL_DIRS += $(INSTALL_DBD) $(INSTALL_INCLUDE) $(INSTALL_DOC)\
|
||||
$(INSTALL_HTML) $(INSTALL_JAVA) $(INSTALL_TEMPLATES) \
|
||||
$(INSTALL_DB)
|
||||
UNINSTALL_DIRS += $(DIRECTORY_TARGETS)
|
||||
uninstallDirs:
|
||||
$(RMDIR) $(UNINSTALL_DIRS)
|
||||
|
||||
uninstall: archuninstall uninstallDirs
|
||||
|
||||
archuninstall: $(addprefix uninstall$(DIVIDER),$(BUILD_ARCHS))
|
||||
@$(MAKE) -f Makefile cleandirs
|
||||
|
||||
uninstallArchTargets = $(foreach arch,$(BUILD_ARCHS), uninstall$(DIVIDER)$(arch))
|
||||
archPart = $(word 2, $(subst $(DIVIDER), ,$@))
|
||||
|
||||
$(uninstallArchTargets): uninstallDirs
|
||||
@$(RMDIR) $(INSTALL_LOCATION_BIN)/$(archPart) $(INSTALL_LOCATION_LIB)/$(archPart)
|
||||
uninstall$(DIVIDER)%:
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)/$(archPart)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)/$(archPart)
|
||||
|
||||
cleandirs:
|
||||
ifeq ($(wildcard $(INSTALL_LOCATION_BIN)/*),)
|
||||
@$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
endif
|
||||
ifeq ($(wildcard $(INSTALL_LOCATION_LIB)/*),)
|
||||
@$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
endif
|
||||
@echo
|
||||
# The echo above stops a "nothing to be done for cleandirs" message
|
||||
|
||||
distclean: realclean realuninstall
|
||||
|
||||
CVSCLEAN=$(firstword $(wildcard $(TOOLS)/cvsclean.pl $(TOP)/src/tools/cvsclean.pl))
|
||||
|
||||
cvsclean:
|
||||
@$(PERL) $(CVSCLEAN)
|
||||
|
||||
realuninstall:
|
||||
@$(RMDIR) $(INSTALL_LOCATION_BIN) $(INSTALL_LOCATION_LIB)
|
||||
@$(RMDIR) $(UNINSTALL_DIRS)
|
||||
|
||||
uninstall: $(addprefix uninstall$(DIVIDER),$(BUILD_ARCHS))
|
||||
@$(MAKE) -f Makefile cleandirs
|
||||
|
||||
uninstallDirs:
|
||||
@$(RMDIR) $(UNINSTALL_DIRS)
|
||||
|
||||
help:
|
||||
@echo "Usage: gnumake [options] [target] ..."
|
||||
@echo "Targets supported by all Makefiles:"
|
||||
@echo " install - Builds and installs all targets (default rule)"
|
||||
@echo " all - Same as install"
|
||||
@echo " buildInstall - Same as install"
|
||||
@echo " all - Same as install (default rule)"
|
||||
@echo " inc - Installs header files"
|
||||
@echo " build - Builds and installs all targets"
|
||||
@echo " install - Builds and installs all targets"
|
||||
@echo " buildInstall - Same as install (deprecated)"
|
||||
@echo " clean - Removes the O.<arch> dirs created by running make"
|
||||
@echo " In O.<arch> dir, clean removes build created files"
|
||||
@echo " realclean - Removes ALL O.<arch> dirs"
|
||||
@echo " Cannot be used within an O.<arch> dir"
|
||||
@echo " rebuild - Same as clean install"
|
||||
@echo " inc - Installs header files"
|
||||
@echo " build - Builds all targets"
|
||||
@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 " build.<arch> - Builds <arch> only."
|
||||
@echo " uninstall.<arch> - Remove bin & lib directories for <arch> only."
|
||||
@echo "Targets supported by top level Makefile:"
|
||||
@echo " uninstall - Cleans directories created by the install."
|
||||
@echo " archuninstall - Remove bin & lib directories created by this hostarch."
|
||||
@echo " uninstall - Remove install directories created by this hostarch."
|
||||
@echo " realuninstall - Removes ALL install dirs"
|
||||
@echo " distclean - Same as realclean realuninstall."
|
||||
@echo " distclean - Same as realclean cvsclean realuninstall."
|
||||
@echo " cvsclean - Removes cvs .#* files in all dirs of directory tree"
|
||||
@echo " help - Prints this list of valid make targets "
|
||||
@echo "Indiv. object targets are supported by O.<arch> level Makefile .e.g"
|
||||
@echo " xxxRecord.o"
|
||||
|
||||
.PHONY : $(uninstallArchTargets)
|
||||
.PHONY : uninstall help cleandirs distclean uninstallDirs realuninstall
|
||||
.PHONY : cvsclean
|
||||
.PHONY: cleandirs distclean cvsclean realuninstall archuninstall uninstallDirs
|
||||
.PHONY: uninstall help
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ export TOOL_FAMILY = GNU
|
||||
|
||||
#--------------------------------------------------
|
||||
# Operating system flags
|
||||
OP_SYS_CPPFLAGS += -DvxWorks
|
||||
OP_SYS_CPPFLAGS += -DvxWorks=vxWorks
|
||||
OP_SYS_CFLAGS += -fno-builtin
|
||||
|
||||
# Fix for vxWorks 5 headers that use macros defined in vxWorks.h but
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
#-------------------------------------------------------
|
||||
|
||||
CP = $(PERL) -MExtUtils::Command -e cp
|
||||
MV = $(PERL) -MExtUtils::Command -e mv
|
||||
MV = $(PERL) -MExtUtils::Command -e mv
|
||||
RM = $(PERL) -MExtUtils::Command -e rm_f
|
||||
MKDIR = $(PERL) -MExtUtils::Command -e mkpath
|
||||
RMDIR = $(PERL) -MExtUtils::Command -e rm_rf
|
||||
COMMENT = $(PERL) -e ''
|
||||
|
||||
WIND_HOST_TYPE = x86-win32
|
||||
OSITHREAD_USE_DEFAULT_STACK = NO
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
include $(CONFIG)/os/CONFIG.UnixCommon.Common
|
||||
|
||||
CP = $(PERL) -MExtUtils::Command -e cp
|
||||
MV = $(PERL) -MExtUtils::Command -e mv
|
||||
MV = $(PERL) -MExtUtils::Command -e mv
|
||||
RM = $(PERL) -MExtUtils::Command -e rm_f
|
||||
MKDIR = $(PERL) -MExtUtils::Command -e mkpath
|
||||
RMDIR = $(PERL) -MExtUtils::Command -e rm_rf
|
||||
COMMENT = $(PERL) -e ''
|
||||
|
||||
WIND_HOST_TYPE = x86-win32
|
||||
OSITHREAD_USE_DEFAULT_STACK = NO
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
#-------------------------------------------------------
|
||||
|
||||
CP = $(PERL) -MExtUtils::Command -e cp
|
||||
MV = $(PERL) -MExtUtils::Command -e mv
|
||||
MV = $(PERL) -MExtUtils::Command -e mv
|
||||
RM = $(PERL) -MExtUtils::Command -e rm_f
|
||||
MKDIR = $(PERL) -MExtUtils::Command -e mkpath
|
||||
RMDIR = $(PERL) -MExtUtils::Command -e rm_rf
|
||||
COMMENT = $(PERL) -e ''
|
||||
|
||||
WIND_HOST_TYPE = x86-win32
|
||||
OSITHREAD_USE_DEFAULT_STACK = NO
|
||||
|
||||
@@ -31,7 +31,9 @@ BAFCMD = bscmake /nologo /o $@
|
||||
# Configure OS vendor C compiler
|
||||
CC = cl
|
||||
|
||||
# Override CONFIG.gnuCommon for cross builds.
|
||||
GNU = NO
|
||||
HDEPENDS_METHOD = CMD
|
||||
|
||||
#
|
||||
# /W<N> use warning level N
|
||||
|
||||
@@ -13,3 +13,11 @@
|
||||
ARCH_CLASS = i386
|
||||
#ARCH_CLASS = x86_64
|
||||
#ARCH_CLASS = i386 x86_64
|
||||
|
||||
#
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#CC = clang
|
||||
#CCC = clang++
|
||||
#GNU_LDLIBS_YES =
|
||||
|
||||
|
||||
@@ -3,14 +3,156 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
|
||||
<title>EPICS Base R3.14.12.1 Release Notes</title>
|
||||
<title>EPICS Base R3.14.12.2-rc1 Release Notes</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1 align="center">EPICS Base Release 3.14.12.1</h1>
|
||||
<h1 align="center">EPICS Base Release 3.14.12.2-rc1</h1>
|
||||
|
||||
<h2 align="center">Changes between 3.14.12.1 and 3.14.12.2-rc1</h2>
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h4>Added <tt>-b</tt> option to dbExpand</h4>
|
||||
|
||||
<p>This turns off monotonic checking of breakpoint tables.</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>697509
|
||||
<a href="https://launchpad.net/bugs/697509">
|
||||
Thread synchronization issue in libCom/osi/os/WIN32/osdTime.cpp</a></li>
|
||||
<li>697516
|
||||
<a href="https://launchpad.net/bugs/697516">
|
||||
Crash occurs in Com.dll if filetime is before the EPICS epoch </a></li>
|
||||
<li>697517
|
||||
<a href="https://launchpad.net/bugs/697517">
|
||||
WIN32 osdtime should handle the system time change properly</a></li>
|
||||
<li>697519
|
||||
<a href="https://launchpad.net/bugs/697519">
|
||||
The incorrect way to compute the roll-over in WIN32 osdTime.cpp</a></li>
|
||||
<li>736273
|
||||
<a href="https://launchpad.net/bugs/736273">
|
||||
nonstandard c++ mutable ref in cac</a></li>
|
||||
<li>786979
|
||||
<a href="https://launchpad.net/bugs/786979">
|
||||
incorrect ref counting for timer queues</a></li>
|
||||
<li>794749
|
||||
<a href="https://launchpad.net/bugs/794749">
|
||||
3.14.12 caget without -c always requests maximum element count</a></li>
|
||||
<li>816678
|
||||
<a href="https://launchpad.net/bugs/816678">
|
||||
g++ generic thunk generation fails virtual varargs</a></li>
|
||||
<li>831648
|
||||
<a href="https://launchpad.net/bugs/831648">
|
||||
RTEMS dynamically loaded app fails to execute osdTimeRegister</a></li>
|
||||
<li>835138
|
||||
<a href="https://launchpad.net/bugs/835138">
|
||||
Incorrect calculation oss priorities for posix threads</a></li>
|
||||
<li>861214
|
||||
<a href="https://launchpad.net/bugs/861214">
|
||||
epicsThreadOnce crashes in static object destructor on win32</a></li>
|
||||
<li>861627
|
||||
<a href="https://launchpad.net/bugs/861627">
|
||||
RULES.db has incorrect dbExpand flags</a></li>
|
||||
<li>878372
|
||||
<a href="https://launchpad.net/bugs/878372">
|
||||
in-memory channel, ca client subscribe isnt thread safe</a></li>
|
||||
<li>878387
|
||||
<a href="https://launchpad.net/bugs/878387">
|
||||
In memory channel clear fails from put callback function</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>Added database sanity checks to iocInit</h4>
|
||||
|
||||
<p>Two menus may legitimately be modified by users; some checks have been added
|
||||
that run at iocInit and make sure the choices haven't been changed too much for
|
||||
the IOC to function properly:</p>
|
||||
|
||||
<ul>
|
||||
<li><tt>menuConvert</tt> is checked to flag problems with IOCs converted from
|
||||
3.13.x, where the SLOPE choice didn't exist.</p>
|
||||
<li><tt>menuScan</tt> is checked to ensure the three initial choices are still
|
||||
present and that there is at least one periodic scan rate.</li>
|
||||
</ul>
|
||||
|
||||
<h4>Fix various catools issues</h4>
|
||||
|
||||
<p>Array handling in the caget and camonitor programs has been debugged, fixing
|
||||
<a href="https://bugs.launchpad.net/bugs/794749">launchpad bug 794749</a> along
|
||||
with a few other related issues dating back to the addition of variable length
|
||||
array support.</p>
|
||||
|
||||
<h4>Another race condition in errlog cleaned up</h4>
|
||||
|
||||
<p>If it was still busy when the IOC was closed down, the errlog thread could
|
||||
have preempted the exit handler and freed the various internal pvtData mutex and
|
||||
event objects too soon.</p>
|
||||
|
||||
<h4>Top-level make target changes</h4>
|
||||
|
||||
<p>Several make targets have been changed. Note that these can only be used from
|
||||
an application's <top> directory.</p>
|
||||
|
||||
<dl>
|
||||
<dt><code>make uninstall.<arch></code></dt>
|
||||
<dd>Deletes the bin/<arch> and lib/<arch> directories for
|
||||
<arch> only. Note that <arch> does not have to be an
|
||||
architecture that this host is configured to build, it works for any
|
||||
arch.</dd>
|
||||
|
||||
<dt><code>make archuninstall</code></dt>
|
||||
<dd>Deletes the bin/<arch> and lib/<arch> directories for all
|
||||
architectures that this host is configured to build. Should not affect files
|
||||
used for multiple architectures, or for host or target architectures that
|
||||
this host is not configured to build.</dd>
|
||||
|
||||
<dt><code>make uninstall</code></dt>
|
||||
<dd>Does archuninstall and also deletes the other install directories include,
|
||||
db, dbd, doc, html, templates and java. This will affect subsequent builds
|
||||
for other architectures, but it doesn't delete their bin/<arch> or
|
||||
lib/<arch> contents.</dd>
|
||||
|
||||
<dt><code>make realuninstall</code></dt>
|
||||
<dd>Deletes all install directories for all architectures.</dd>
|
||||
|
||||
<dt><code>make distclean</code></dt>
|
||||
<dd>Does realclean realuninstall as before, and also now does a cvsclean,
|
||||
which removes file remnants from CVS operations named <code>.#*</code> and
|
||||
editor backups named <code>*~</code> throughout the source tree.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<h4>Compress record type</h4>
|
||||
|
||||
<p>This record now posts monitors on its NUSE field whenever its value changes.
|
||||
A new field OUSE was added to support this.</p>
|
||||
|
||||
<h4>Remove C++ build rule for <code>.C</code> files</h4>
|
||||
|
||||
<p>An early convention on Unix systems was to name C++ files with an upper-case
|
||||
extention, <code>.C</code>. This does not work on Windows or MacOS where the
|
||||
filesystems are case-insensitive, and the C++ build rule was causing problems so
|
||||
has been eliminated. Any remaining C++ source files that are still using this
|
||||
convention will have to be renamed, preferably to <code>.cpp</code></p>
|
||||
|
||||
<h4>Support <code>make -s</code> on Windows</h4>
|
||||
|
||||
<p>The flag to silence build output did not work on some Windows architecture
|
||||
combinations. This has now been fixed.</p>
|
||||
|
||||
<h4>iocLogServer now supports logrotate</h4>
|
||||
|
||||
<p>The feature in the iocLogServer that closed and reopened the logfile used to
|
||||
ignore the SIGHUP signal when the log filename did not change. This has now been
|
||||
changed so these logfiles can be used with the standard Linux logrotate
|
||||
package.</p>
|
||||
|
||||
|
||||
<h2 align="center">Changes between 3.14.12 and 3.14.12.1</h2>
|
||||
|
||||
<p>This release only contains changes that fix bugs or add build configuration
|
||||
|
||||
@@ -12,15 +12,14 @@ include $(TOP)/configure/CONFIG
|
||||
|
||||
INC += epicsRtemsInitHooks.h
|
||||
|
||||
SRCS += rtems_init.c
|
||||
SRCS += rtems_config.c
|
||||
SRCS += rtems_netconfig.c
|
||||
SRCS += rtems_util.c
|
||||
SRCS += setBootConfigFromNVRAM.c
|
||||
SRCS += epicsRtemsInitHookPre.c
|
||||
SRCS += epicsRtemsInitHookPost.c
|
||||
rtemsCom_SRCS += rtems_init.c
|
||||
rtemsCom_SRCS += rtems_config.c
|
||||
rtemsCom_SRCS += rtems_netconfig.c
|
||||
rtemsCom_SRCS += rtems_util.c
|
||||
rtemsCom_SRCS += setBootConfigFromNVRAM.c
|
||||
rtemsCom_SRCS += epicsRtemsInitHookPre.c
|
||||
rtemsCom_SRCS += epicsRtemsInitHookPost.c
|
||||
|
||||
LIBRARY_RTEMS = rtemsCom
|
||||
LIBRARY_SRCS = $(SRCS) $(BUILD_ARCHS)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -22,7 +22,8 @@ DBD += bptTypeKdegF.dbd
|
||||
|
||||
PROD_LIBS = Com
|
||||
PROD_HOST += makeBpt
|
||||
makeBpt_SRCS=makeBpt
|
||||
|
||||
makeBpt_SRCS = makeBpt
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ $Date$</span></small></p>
|
||||
|
||||
<h3>Why Reconfigure Channel Access</h3>
|
||||
|
||||
<p>Typically reasons to reconfigure EPICS Channel Access:</p>
|
||||
<p>Typical reasons to reconfigure EPICS Channel Access:</p>
|
||||
<ul>
|
||||
<li>Two independent control systems must share a network without fear of
|
||||
interaction</li>
|
||||
@@ -4359,7 +4359,7 @@ that use ca_context_destroy).</p>
|
||||
<p><a href="#ca_context_destroy">ca_context_destroy</a>()</p>
|
||||
|
||||
<h3><code><a name="ca_dump_dbr">ca_dump_dbr()</a></code></h3>
|
||||
<pre>void ca_dump_dbr (chtype TYPE, unsigned COUNT, const void * PDBR);</pre>
|
||||
<code><pre>void ca_dump_dbr (chtype TYPE, unsigned COUNT, const void * PDBR);</pre></code>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ PROD_LIBS = ca Com
|
||||
PROD_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
|
||||
|
||||
PROD_HOST += caRepeater catime acctst caConnTest casw caEventRate
|
||||
OBJS_IOC_vxWorks += catime acctst caConnTest casw caEventRate
|
||||
OBJS_IOC += catime acctst caConnTest casw caEventRate acctstRegister
|
||||
caRepeater_SRCS = caRepeater.cpp
|
||||
catime_SRCS = catimeMain.c catime.c
|
||||
acctst_SRCS = acctstMain.c acctst.c
|
||||
|
||||
257
src/ca/acctst.c
257
src/ca/acctst.c
@@ -10,6 +10,10 @@
|
||||
|
||||
/*
|
||||
* CA regression test
|
||||
* Authors:
|
||||
* Jeff Hill
|
||||
* Murali Shankar - initial versions of verifyMultithreadSubscr
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -26,6 +30,8 @@
|
||||
*/
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsTime.h"
|
||||
#include "dbDefs.h"
|
||||
#include "envDefs.h"
|
||||
@@ -2719,6 +2725,186 @@ void fdRegCB ( void * parg, int fd, int opened )
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char m_chanName[100u];
|
||||
struct ca_client_context * m_pCtx;
|
||||
chid m_chan;
|
||||
epicsMutexId m_mutex;
|
||||
epicsEventId m_testCompleteEvent;
|
||||
epicsEventId m_threadExitEvent;
|
||||
size_t m_nUpdatesReceived;
|
||||
size_t m_nUpdatesRequired;
|
||||
int m_testInitiated;
|
||||
int m_testComplete;
|
||||
unsigned m_interestLevel;
|
||||
} MultiThreadSubscrTest;
|
||||
|
||||
static void testMultithreadSubscrSubscrCallback
|
||||
( struct event_handler_args eha )
|
||||
{
|
||||
const epicsEventId firstUpdateEvent = ( epicsEventId ) eha.usr;
|
||||
epicsEventSignal ( firstUpdateEvent );
|
||||
}
|
||||
|
||||
static void testMultithreadSubscrCreateSubscr ( void * pParm )
|
||||
{
|
||||
static unsigned nElem = 0;
|
||||
int testComplete = FALSE;
|
||||
evid id;
|
||||
epicsEventId firstUpdateEvent;
|
||||
epicsEventWaitStatus eventWaitStatus;
|
||||
MultiThreadSubscrTest * const pMultiThreadSubscrTest =
|
||||
( MultiThreadSubscrTest * ) pParm;
|
||||
|
||||
/* this is required for the ca_flush below to work correctly */
|
||||
int status = ca_attach_context ( pMultiThreadSubscrTest->m_pCtx );
|
||||
verify ( status == ECA_NORMAL );
|
||||
firstUpdateEvent = epicsEventMustCreate ( epicsEventEmpty );
|
||||
verify ( firstUpdateEvent );
|
||||
status = ca_create_subscription (
|
||||
DBR_TIME_LONG,
|
||||
nElem,
|
||||
pMultiThreadSubscrTest->m_chan,
|
||||
DBE_VALUE,
|
||||
testMultithreadSubscrSubscrCallback,
|
||||
firstUpdateEvent,
|
||||
& id );
|
||||
verify ( status == ECA_NORMAL );
|
||||
status = ca_flush_io ();
|
||||
verify ( status == ECA_NORMAL );
|
||||
/* wait for first update */
|
||||
eventWaitStatus = epicsEventWaitWithTimeout (
|
||||
firstUpdateEvent, 60.0 * 10 );
|
||||
verify ( eventWaitStatus == epicsEventWaitOK );
|
||||
epicsEventDestroy ( firstUpdateEvent );
|
||||
status = ca_clear_subscription ( id );
|
||||
verify ( status == ECA_NORMAL );
|
||||
epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
|
||||
pMultiThreadSubscrTest->m_nUpdatesReceived++;
|
||||
testComplete = ( pMultiThreadSubscrTest->m_nUpdatesReceived ==
|
||||
pMultiThreadSubscrTest->m_nUpdatesRequired );
|
||||
pMultiThreadSubscrTest->m_testComplete = testComplete;
|
||||
epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
|
||||
if ( testComplete ) {
|
||||
epicsEventSignal ( pMultiThreadSubscrTest->m_testCompleteEvent );
|
||||
}
|
||||
}
|
||||
|
||||
void testMultithreadSubscrConnHandler ( struct connection_handler_args args )
|
||||
{
|
||||
MultiThreadSubscrTest * const pMultiThreadSubscrTest =
|
||||
( MultiThreadSubscrTest * ) ca_puser ( args.chid );
|
||||
epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
|
||||
if ( !pMultiThreadSubscrTest->m_testInitiated &&
|
||||
args.op == CA_OP_CONN_UP ) {
|
||||
int i;
|
||||
pMultiThreadSubscrTest->m_testInitiated = TRUE;
|
||||
for ( i = 0; i < pMultiThreadSubscrTest->m_nUpdatesRequired; i++ ) {
|
||||
char threadname[64];
|
||||
epicsThreadId threadId;
|
||||
sprintf(threadname, "testSubscr%06u", i);
|
||||
threadId = epicsThreadCreate ( threadname,
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
testMultithreadSubscrCreateSubscr,
|
||||
pMultiThreadSubscrTest );
|
||||
verify ( threadId );
|
||||
}
|
||||
}
|
||||
epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
|
||||
}
|
||||
|
||||
void testMultithreadSubscr ( void * pParm )
|
||||
{
|
||||
MultiThreadSubscrTest * const pMultiThreadSubscrTest =
|
||||
( MultiThreadSubscrTest * ) pParm;
|
||||
int status;
|
||||
unsigned i;
|
||||
|
||||
status = ca_context_create ( ca_enable_preemptive_callback );
|
||||
verify ( status == ECA_NORMAL );
|
||||
pMultiThreadSubscrTest->m_pCtx = ca_current_context ();
|
||||
verify ( pMultiThreadSubscrTest->m_pCtx );
|
||||
status = ca_create_channel (
|
||||
pMultiThreadSubscrTest->m_chanName,
|
||||
testMultithreadSubscrConnHandler,
|
||||
pMultiThreadSubscrTest,
|
||||
CA_PRIORITY_MIN,
|
||||
& pMultiThreadSubscrTest->m_chan );
|
||||
verify ( status == ECA_NORMAL );
|
||||
|
||||
showProgressBegin ( "verifyMultithreadSubscr",
|
||||
pMultiThreadSubscrTest->m_interestLevel );
|
||||
i = 0;
|
||||
while ( TRUE ) {
|
||||
int success = FALSE;
|
||||
epicsEventWaitStatus eventWaitStatus;
|
||||
epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
|
||||
success = pMultiThreadSubscrTest->m_testComplete;
|
||||
epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
|
||||
if ( success ) {
|
||||
break;
|
||||
}
|
||||
eventWaitStatus = epicsEventWaitWithTimeout (
|
||||
pMultiThreadSubscrTest->m_testCompleteEvent, 0.1 );
|
||||
verify ( eventWaitStatus == epicsEventWaitOK ||
|
||||
eventWaitStatus == epicsEventWaitTimeout );
|
||||
if ( i++ % 100 == 0u )
|
||||
showProgress ( pMultiThreadSubscrTest->m_interestLevel );
|
||||
verify ( i < 1000 );
|
||||
}
|
||||
showProgressEnd ( pMultiThreadSubscrTest->m_interestLevel );
|
||||
|
||||
status = ca_clear_channel ( pMultiThreadSubscrTest->m_chan );
|
||||
verify ( status == ECA_NORMAL );
|
||||
ca_context_destroy ();
|
||||
epicsEventSignal ( pMultiThreadSubscrTest->m_threadExitEvent );
|
||||
}
|
||||
|
||||
/*
|
||||
* test installation of subscriptions similar to usage paterns
|
||||
* employed by modern versions of the sequencer
|
||||
*/
|
||||
void verifyMultithreadSubscr ( const char * pName, unsigned interestLevel )
|
||||
{
|
||||
static unsigned nSubscr = 3000;
|
||||
epicsThreadId threadId;
|
||||
MultiThreadSubscrTest * const pMultiThreadSubscrTest =
|
||||
(MultiThreadSubscrTest*) calloc ( 1,
|
||||
sizeof ( MultiThreadSubscrTest ) );
|
||||
verify ( pMultiThreadSubscrTest);
|
||||
pMultiThreadSubscrTest->m_mutex = epicsMutexMustCreate ();
|
||||
verify ( pMultiThreadSubscrTest->m_mutex );
|
||||
pMultiThreadSubscrTest->m_testCompleteEvent =
|
||||
epicsEventMustCreate ( epicsEventEmpty );
|
||||
verify ( pMultiThreadSubscrTest->m_testCompleteEvent );
|
||||
pMultiThreadSubscrTest->m_threadExitEvent =
|
||||
epicsEventMustCreate ( epicsEventEmpty );
|
||||
verify ( pMultiThreadSubscrTest->m_threadExitEvent );
|
||||
strncpy ( pMultiThreadSubscrTest->m_chanName, pName,
|
||||
sizeof ( pMultiThreadSubscrTest->m_chanName ) );
|
||||
pMultiThreadSubscrTest->m_chanName
|
||||
[ sizeof ( pMultiThreadSubscrTest->m_chanName ) - 1u ] = '\0';
|
||||
pMultiThreadSubscrTest->m_nUpdatesRequired = nSubscr;
|
||||
pMultiThreadSubscrTest->m_interestLevel = interestLevel;
|
||||
threadId = epicsThreadCreate (
|
||||
"testMultithreadSubscr",
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
testMultithreadSubscr, pMultiThreadSubscrTest );
|
||||
verify ( threadId );
|
||||
{
|
||||
epicsEventWaitStatus eventWaitStatus;
|
||||
eventWaitStatus = epicsEventWaitWithTimeout (
|
||||
pMultiThreadSubscrTest->m_threadExitEvent, 1000.0 );
|
||||
verify ( eventWaitStatus == epicsEventWaitOK );
|
||||
}
|
||||
epicsEventDestroy ( pMultiThreadSubscrTest->m_testCompleteEvent );
|
||||
epicsEventDestroy ( pMultiThreadSubscrTest->m_threadExitEvent );
|
||||
epicsMutexDestroy ( pMultiThreadSubscrTest->m_mutex );
|
||||
free ( pMultiThreadSubscrTest );
|
||||
}
|
||||
|
||||
void fdManagerVerify ( const char * pName, unsigned interestLevel )
|
||||
{
|
||||
int status;
|
||||
@@ -2965,17 +3151,22 @@ void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
|
||||
SEVCHK ( status, "context create failed" );
|
||||
|
||||
status = ca_create_channel ( pName, 0, 0, 0, & chan );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
status = ca_pend_io( timeoutToPendIO );
|
||||
SEVCHK ( status, "channel connect failed" );
|
||||
|
||||
status = ca_put ( DBR_DOUBLE, chan, & stim );
|
||||
SEVCHK ( status, "channel put failed" );
|
||||
|
||||
status = ca_clear_channel ( chan );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
/*
|
||||
* currently in-memory channels cant be used with this test
|
||||
* !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
|
||||
*/
|
||||
if ( status != ECA_UNAVAILINSERV ) {
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
status = ca_pend_io( timeoutToPendIO );
|
||||
SEVCHK ( status, "channel connect failed" );
|
||||
|
||||
status = ca_put ( DBR_DOUBLE, chan, & stim );
|
||||
SEVCHK ( status, "channel put failed" );
|
||||
|
||||
status = ca_clear_channel ( chan );
|
||||
SEVCHK ( status, NULL );
|
||||
}
|
||||
ca_context_destroy ();
|
||||
}
|
||||
|
||||
@@ -2985,24 +3176,28 @@ void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
|
||||
dbr_double_t resp;
|
||||
status = ca_context_create ( ca_disable_preemptive_callback );
|
||||
SEVCHK ( status, "context create failed" );
|
||||
|
||||
|
||||
status = ca_create_channel ( pName, 0, 0, 0, & chan );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
status = ca_pend_io( timeoutToPendIO );
|
||||
SEVCHK ( status, "channel connect failed" );
|
||||
|
||||
status = ca_get ( DBR_DOUBLE, chan, & resp );
|
||||
SEVCHK ( status, "channel get failed" );
|
||||
|
||||
status = ca_pend_io ( timeoutToPendIO );
|
||||
SEVCHK ( status, "get, pend io failed" );
|
||||
|
||||
verify ( stim == resp );
|
||||
|
||||
status = ca_clear_channel ( chan );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
/*
|
||||
* currently in-memory channels cant be used with this test
|
||||
* !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
|
||||
*/
|
||||
if ( status != ECA_UNAVAILINSERV ) {
|
||||
status = ca_pend_io( timeoutToPendIO );
|
||||
SEVCHK ( status, "channel connect failed" );
|
||||
|
||||
status = ca_get ( DBR_DOUBLE, chan, & resp );
|
||||
SEVCHK ( status, "channel get failed" );
|
||||
|
||||
status = ca_pend_io ( timeoutToPendIO );
|
||||
SEVCHK ( status, "get, pend io failed" );
|
||||
|
||||
verify ( stim == resp );
|
||||
|
||||
status = ca_clear_channel ( chan );
|
||||
SEVCHK ( status, NULL );
|
||||
}
|
||||
ca_context_destroy ();
|
||||
}
|
||||
|
||||
@@ -3028,6 +3223,13 @@ void verifyContextRundownChanStillExist (
|
||||
|
||||
for ( i = 0; i < NELEMENTS ( chan ); i++ ) {
|
||||
status = ca_create_channel ( pName, 0, 0, 0, & chan[i] );
|
||||
/*
|
||||
* currently in-memory channels cant be used with this test
|
||||
* !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
|
||||
*/
|
||||
if ( status == ECA_UNAVAILINSERV ) {
|
||||
break;
|
||||
}
|
||||
SEVCHK ( status, NULL );
|
||||
}
|
||||
|
||||
@@ -3123,6 +3325,7 @@ int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
|
||||
verifyHighThroughputReadCallback ( chan, interestLevel );
|
||||
verifyHighThroughputWriteCallback ( chan, interestLevel );
|
||||
verifyBadString ( chan, interestLevel );
|
||||
verifyMultithreadSubscr ( pName, interestLevel );
|
||||
if ( select != ca_enable_preemptive_callback ) {
|
||||
fdManagerVerify ( pName, interestLevel );
|
||||
}
|
||||
|
||||
69
src/ca/acctstRegister.cpp
Normal file
69
src/ca/acctstRegister.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* CA client library diagnostics IOC shell registration
|
||||
* Authors:
|
||||
* Jeff Hill
|
||||
*/
|
||||
|
||||
#include <iocsh.h>
|
||||
#include "caDiagnostics.h"
|
||||
|
||||
/* Information needed by iocsh */
|
||||
static const iocshArg acctstArg0 = { "channel name", iocshArgString };
|
||||
static const iocshArg acctstArg1 = { "interest level", iocshArgInt };
|
||||
static const iocshArg acctstArg2 = { "channel count", iocshArgInt };
|
||||
static const iocshArg acctstArg3 = { "repetition count", iocshArgInt };
|
||||
static const iocshArg acctstArg4 = { "preemptive callback select", iocshArgInt };
|
||||
|
||||
static const iocshArg *acctstArgs[] =
|
||||
{
|
||||
&acctstArg0,
|
||||
&acctstArg1,
|
||||
&acctstArg2,
|
||||
&acctstArg3,
|
||||
&acctstArg4
|
||||
};
|
||||
static const iocshFuncDef acctstFuncDef = {"acctst", 5, acctstArgs};
|
||||
|
||||
|
||||
/* Wrapper called by iocsh, selects the argument types that print needs */
|
||||
static void acctstCallFunc(const iocshArgBuf *args) {
|
||||
if ( args[1].ival < 0 ) {
|
||||
printf ( "negative interest level not allowed\n" );
|
||||
return;
|
||||
}
|
||||
if ( args[2].ival < 0 ) {
|
||||
printf ( "negative channel count not allowed\n" );
|
||||
return;
|
||||
}
|
||||
if ( args[3].ival < 0 ) {
|
||||
printf ( "negative repetition count not allowed\n" );
|
||||
return;
|
||||
}
|
||||
acctst (
|
||||
args[0].sval, /* channel name */
|
||||
( unsigned ) args[1].ival, /* interest level */
|
||||
( unsigned ) args[2].ival, /* channel count */
|
||||
( unsigned ) args[3].ival, /* repetition count */
|
||||
( ca_preemptive_callback_select ) args[4].ival ); /* preemptive callback select */
|
||||
}
|
||||
|
||||
struct AutoInit {
|
||||
AutoInit ();
|
||||
};
|
||||
|
||||
AutoInit :: AutoInit ()
|
||||
{
|
||||
iocshRegister ( &acctstFuncDef, acctstCallFunc );
|
||||
}
|
||||
|
||||
AutoInit autoInit;
|
||||
|
||||
@@ -266,8 +266,8 @@ private:
|
||||
// **** lock hierarchy ****
|
||||
// 1) callback lock must always be acquired before
|
||||
// the primary mutex if both locks are needed
|
||||
mutable epicsMutex & mutex;
|
||||
mutable epicsMutex & cbMutex;
|
||||
epicsMutex & mutex;
|
||||
epicsMutex & cbMutex;
|
||||
epicsEvent iiuUninstall;
|
||||
ipAddrToAsciiEngine & ipToAEngine;
|
||||
epicsTimerQueueActive & timerQueue;
|
||||
|
||||
@@ -185,7 +185,8 @@ epicsShareFunc enum channel_state epicsShareAPI ca_state (chid chan);
|
||||
epicsShareFunc int epicsShareAPI ca_task_initialize (void);
|
||||
enum ca_preemptive_callback_select
|
||||
{ ca_disable_preemptive_callback, ca_enable_preemptive_callback };
|
||||
epicsShareFunc int epicsShareAPI ca_context_create (enum ca_preemptive_callback_select select);
|
||||
epicsShareFunc int epicsShareAPI
|
||||
ca_context_create (enum ca_preemptive_callback_select select);
|
||||
epicsShareFunc void epicsShareAPI ca_detach_context ();
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
@@ -81,8 +81,9 @@ udpiiu::udpiiu (
|
||||
cac::lowestPriorityLevelAbove (
|
||||
cac::lowestPriorityLevelAbove (
|
||||
cac.getInitializingThreadsPriority () ) ) ),
|
||||
m_repeaterTimerNotify ( *this ),
|
||||
repeaterSubscribeTmr (
|
||||
*this, timerQueue, cbMutexIn, ctxNotifyIn ),
|
||||
m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ),
|
||||
govTmr ( *this, timerQueue, cacMutexIn ),
|
||||
maxPeriod ( maxSearchPeriodDefault ),
|
||||
rtteMean ( minRoundTripEstimate ),
|
||||
@@ -397,14 +398,14 @@ void udpRecvThread::run ()
|
||||
}
|
||||
|
||||
/*
|
||||
* udpiiu::repeaterRegistrationMessage ()
|
||||
* udpiiu::M_repeaterTimerNotify::repeaterRegistrationMessage ()
|
||||
*
|
||||
* register with the repeater
|
||||
*/
|
||||
void udpiiu::repeaterRegistrationMessage ( unsigned attemptNumber )
|
||||
void udpiiu :: M_repeaterTimerNotify :: repeaterRegistrationMessage ( unsigned attemptNumber )
|
||||
{
|
||||
epicsGuard < epicsMutex > cbGuard ( this->cacMutex );
|
||||
caRepeaterRegistrationMessage ( this->sock, this->repeaterPort, attemptNumber );
|
||||
epicsGuard < epicsMutex > cbGuard ( m_udpiiu.cacMutex );
|
||||
caRepeaterRegistrationMessage ( m_udpiiu.sock, m_udpiiu.repeaterPort, attemptNumber );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1233,16 +1234,16 @@ void udpiiu::govExpireNotify (
|
||||
this->ppSearchTmr[0]->installChannel ( guard, chan );
|
||||
}
|
||||
|
||||
int udpiiu :: printFormated (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
const char * pformat, ... )
|
||||
int udpiiu :: M_repeaterTimerNotify :: printFormated (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
const char * pformat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
int status;
|
||||
|
||||
va_start ( theArgs, pformat );
|
||||
|
||||
status = this->cacRef.varArgsPrintFormated ( cbGuard, pformat, theArgs );
|
||||
status = m_udpiiu.cacRef.varArgsPrintFormated ( cbGuard, pformat, theArgs );
|
||||
|
||||
va_end ( theArgs );
|
||||
|
||||
|
||||
@@ -88,8 +88,7 @@ static const double beaconAnomalySearchPeriod = 5.0; // seconds
|
||||
class udpiiu :
|
||||
private netiiu,
|
||||
private searchTimerNotify,
|
||||
private disconnectGovernorNotify,
|
||||
private repeaterTimerNotify {
|
||||
private disconnectGovernorNotify {
|
||||
public:
|
||||
udpiiu (
|
||||
epicsGuard < epicsMutex > & cacGuard,
|
||||
@@ -139,9 +138,24 @@ private:
|
||||
private:
|
||||
udpiiu & _udpiiu;
|
||||
};
|
||||
class M_repeaterTimerNotify :
|
||||
public repeaterTimerNotify {
|
||||
public:
|
||||
M_repeaterTimerNotify ( udpiiu & iiu ) :
|
||||
m_udpiiu ( iiu ) {}
|
||||
// repeaterTimerNotify
|
||||
void repeaterRegistrationMessage (
|
||||
unsigned attemptNumber );
|
||||
int printFormated (
|
||||
epicsGuard < epicsMutex > & callbackControl,
|
||||
const char * pformat, ... );
|
||||
private:
|
||||
udpiiu & m_udpiiu;
|
||||
};
|
||||
char xmitBuf [MAX_UDP_SEND];
|
||||
char recvBuf [MAX_UDP_RECV];
|
||||
udpRecvThread recvThread;
|
||||
M_repeaterTimerNotify m_repeaterTimerNotify;
|
||||
repeaterSubscribeTimer repeaterSubscribeTmr;
|
||||
disconnectGovernorTimer govTmr;
|
||||
tsDLList < SearchDest > _searchDestList;
|
||||
@@ -149,8 +163,8 @@ private:
|
||||
double rtteMean;
|
||||
double rtteMeanDev;
|
||||
cac & cacRef;
|
||||
mutable epicsMutex & cbMutex;
|
||||
mutable epicsMutex & cacMutex;
|
||||
epicsMutex & cbMutex;
|
||||
epicsMutex & cacMutex;
|
||||
epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array > ppSearchTmr;
|
||||
unsigned nBytesInXmitBuf;
|
||||
unsigned nTimers;
|
||||
@@ -278,14 +292,6 @@ private:
|
||||
void govExpireNotify (
|
||||
epicsGuard < epicsMutex > &, nciu & );
|
||||
|
||||
// repeaterTimerNotify
|
||||
void repeaterRegistrationMessage (
|
||||
unsigned attemptNumber );
|
||||
|
||||
int printFormated (
|
||||
epicsGuard < epicsMutex > & callbackControl,
|
||||
const char * pformat, ... );
|
||||
|
||||
udpiiu ( const udpiiu & );
|
||||
udpiiu & operator = ( const udpiiu & );
|
||||
|
||||
@@ -294,6 +300,7 @@ private:
|
||||
// These are needed for the vxWorks 5.5 compiler:
|
||||
friend class udpiiu::SearchDestUDP;
|
||||
friend class udpiiu::SearchRespCallback;
|
||||
friend class udpiiu::M_repeaterTimerNotify;
|
||||
};
|
||||
|
||||
#endif // udpiiuh
|
||||
|
||||
@@ -33,6 +33,12 @@ ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),)
|
||||
PERL_SCRIPTS += camonitor.pl
|
||||
|
||||
PERL_MODULES += CA.pm
|
||||
|
||||
ifeq ($(findstring Host,$(VALID_BUILDS)),Host)
|
||||
# Can only create docs in Host build
|
||||
HTMLS_DIR = .
|
||||
HTMLS = CA.html
|
||||
endif
|
||||
endif
|
||||
|
||||
Cap5_SRCS = Cap5.xs
|
||||
@@ -40,12 +46,6 @@ Cap5_LIBS = ca Com
|
||||
Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE
|
||||
Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags)
|
||||
|
||||
ifeq ($(findstring Host,$(VALID_BUILDS)),Host)
|
||||
# Can only create docs in Host build
|
||||
HTMLS_DIR = .
|
||||
HTMLS = CA.html
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
ifdef T_A
|
||||
|
||||
@@ -23,8 +23,8 @@ PROD_LIBS := cas ca gdd Com
|
||||
#
|
||||
PROD_SYS_LIBS_WIN32 := ws2_32 advapi32 user32
|
||||
|
||||
SRCS += main.cc
|
||||
SRCS += directoryServer.cc
|
||||
caDirServ_SRCS += main.cc
|
||||
caDirServ_SRCS += directoryServer.cc
|
||||
|
||||
PROD_HOST = caDirServ
|
||||
|
||||
|
||||
@@ -126,7 +126,6 @@ static void event_handler (evargs args)
|
||||
ppv->dbrType = args.type;
|
||||
ppv->value = calloc(1, dbr_size_n(args.type, args.count));
|
||||
memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count));
|
||||
ppv->onceConnected = 1;
|
||||
ppv->nElems = args.count;
|
||||
nRead++;
|
||||
}
|
||||
@@ -159,12 +158,13 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
int n, result;
|
||||
|
||||
for (n = 0; n < nPvs; n++) {
|
||||
unsigned long nElems;
|
||||
|
||||
/* Set up pvs structure */
|
||||
/* -------------------- */
|
||||
|
||||
/* Get natural type and array count */
|
||||
pvs[n].nElems = ca_element_count(pvs[n].chid);
|
||||
nElems = ca_element_count(pvs[n].chid);
|
||||
pvs[n].dbfType = ca_field_type(pvs[n].chid);
|
||||
pvs[n].dbrType = dbrType;
|
||||
|
||||
@@ -183,10 +183,6 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
pvs[n].dbrType = DBR_TIME_STRING;
|
||||
}
|
||||
}
|
||||
/* Adjust array count */
|
||||
if (reqElems > pvs[n].nElems)
|
||||
reqElems = pvs[n].nElems;
|
||||
pvs[n].reqElems = reqElems;
|
||||
|
||||
/* Issue CA request */
|
||||
/* ---------------- */
|
||||
@@ -196,17 +192,20 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
nConn++;
|
||||
pvs[n].onceConnected = 1;
|
||||
if (request == callback)
|
||||
{ /* Event handler will allocate value */
|
||||
{
|
||||
/* Event handler will allocate value and set nElems */
|
||||
pvs[n].reqElems = reqElems > nElems ? nElems : reqElems;
|
||||
result = ca_array_get_callback(pvs[n].dbrType,
|
||||
pvs[n].reqElems,
|
||||
pvs[n].chid,
|
||||
event_handler,
|
||||
(void*)&pvs[n]);
|
||||
} else {
|
||||
/* Allocate value structure */
|
||||
/* We allocate value structure and set nElems */
|
||||
pvs[n].nElems = reqElems && reqElems < nElems ? reqElems : nElems;
|
||||
pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems));
|
||||
if(!pvs[n].value) {
|
||||
fprintf(stderr,"Allocation failed\n");
|
||||
if (!pvs[n].value) {
|
||||
fprintf(stderr,"Memory allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
result = ca_array_get(pvs[n].dbrType,
|
||||
@@ -252,9 +251,6 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
/* -------------- */
|
||||
|
||||
for (n = 0; n < nPvs; n++) {
|
||||
/* Truncate the data printed to what was requested. */
|
||||
if (pvs[n].reqElems != 0 && pvs[n].nElems > pvs[n].reqElems)
|
||||
pvs[n].nElems = pvs[n].reqElems;
|
||||
|
||||
switch (format) {
|
||||
case plain: /* Emulate old caget behaviour */
|
||||
@@ -377,7 +373,7 @@ static void complainIfNotPlainAndSet (OutputT *current, const OutputT requested)
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int n = 0;
|
||||
int n;
|
||||
int result; /* CA result */
|
||||
OutputT format = plain; /* User specified format */
|
||||
RequestT request = get; /* User specified request type */
|
||||
@@ -389,7 +385,7 @@ int main (int argc, char *argv[])
|
||||
int digits = 0; /* getopt() no. of float digits */
|
||||
|
||||
int nPvs; /* Number of PVs */
|
||||
pv* pvs = 0; /* Array of PV structures */
|
||||
pv* pvs; /* Array of PV structures */
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
|
||||
@@ -529,7 +525,7 @@ int main (int argc, char *argv[])
|
||||
result = ca_context_create(ca_disable_preemptive_callback);
|
||||
if (result != ECA_NORMAL) {
|
||||
fprintf(stderr, "CA error %s occurred while trying "
|
||||
"to start channel access '%s'.\n", ca_message(result), pvs[n].name);
|
||||
"to start channel access.\n", ca_message(result));
|
||||
return 1;
|
||||
}
|
||||
/* Allocate PV structure array */
|
||||
|
||||
@@ -127,13 +127,13 @@ int cainfo (pv *pvs, int nPvs)
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int n = 0;
|
||||
int n;
|
||||
int result; /* CA result */
|
||||
|
||||
int opt; /* getopt() current option */
|
||||
|
||||
int nPvs; /* Number of PVs */
|
||||
pv* pvs = 0; /* Array of PV structures */
|
||||
pv* pvs; /* Array of PV structures */
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
|
||||
@@ -195,7 +195,7 @@ int main (int argc, char *argv[])
|
||||
result = ca_context_create(ca_disable_preemptive_callback);
|
||||
if (result != ECA_NORMAL) {
|
||||
fprintf(stderr, "CA error %s occurred while trying "
|
||||
"to start channel access '%s'.\n", ca_message(result), pvs[n].name);
|
||||
"to start channel access.\n", ca_message(result));
|
||||
return 1;
|
||||
}
|
||||
/* Allocate PV structure array */
|
||||
|
||||
@@ -42,45 +42,49 @@ static int nConn = 0; /* Number of connected
|
||||
|
||||
void usage (void)
|
||||
{
|
||||
fprintf (stderr, "\nUsage: camonitor [options] <PV name> ...\n\n"
|
||||
" -h: Help: Print this message\n"
|
||||
fprintf (stderr, "\nUsage: camonitor [options] <PV name> ...\n"
|
||||
"\n"
|
||||
" -h: Help; Print this message\n"
|
||||
"Channel Access options:\n"
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
|
||||
" -m <mask>: Specify CA event mask to use, with <mask> being any combination of\n"
|
||||
" 'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property). Default: va\n"
|
||||
" -p <prio>: CA priority (0-%u, default 0=lowest)\n"
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
|
||||
" -m <msk>: Specify CA event mask to use. <msk> is any combination of\n"
|
||||
" 'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property).\n"
|
||||
" Default event mask is 'va'\n"
|
||||
" -p <pri>: CA priority (0-%u, default 0=lowest)\n"
|
||||
"Timestamps:\n"
|
||||
" Default: Print absolute timestamps (as reported by CA server)\n"
|
||||
" -t <key>: Specify timestamp source(s) and type, with <key> containing\n"
|
||||
" 's' = CA server (remote) timestamps\n"
|
||||
" 'c' = CA client (local) timestamps (shown in '()'s)\n"
|
||||
" 'n' = no timestamps\n"
|
||||
" 'r' = relative timestamps (time elapsed since start of program)\n"
|
||||
" 'i' = incremental timestamps (time elapsed since last update)\n"
|
||||
" 'I' = incremental timestamps (time elapsed since last update, by channel)\n"
|
||||
" Default: Print absolute timestamps (as reported by CA server)\n"
|
||||
" -t <key>: Specify timestamp source(s) and type, with <key> containing\n"
|
||||
" 's' = CA server (remote) timestamps\n"
|
||||
" 'c' = CA client (local) timestamps (shown in '()'s)\n"
|
||||
" 'n' = no timestamps\n"
|
||||
" 'r' = relative timestamps (time elapsed since start of program)\n"
|
||||
" 'i' = incremental timestamps (time elapsed since last update)\n"
|
||||
" 'I' = incremental timestamps (time since last update, by channel)\n"
|
||||
" 'r', 'i' or 'I' require 's' or 'c' to select the time source\n"
|
||||
"Enum format:\n"
|
||||
" -n: Print DBF_ENUM values as number (default are enum string values)\n"
|
||||
"Arrays: Value format: print number of requested values, then list of values\n"
|
||||
" Default: Print all values\n"
|
||||
" -# <count>: Print first <count> elements of an array\n"
|
||||
" -S: Print array of char as a string (long string)\n"
|
||||
"Floating point type format:\n"
|
||||
" Default: Use %%g format\n"
|
||||
" -e <nr>: Use %%e format, with a precision of <nr> digits\n"
|
||||
" -f <nr>: Use %%f format, with a precision of <nr> digits\n"
|
||||
" -g <nr>: Use %%g format, with a precision of <nr> digits\n"
|
||||
" -s: Get value as string (honors server-side precision)\n"
|
||||
" -lx: Round to long integer and print as hex number\n"
|
||||
" -lo: Round to long integer and print as octal number\n"
|
||||
" -lb: Round to long integer and print as binary number\n"
|
||||
" -n: Print DBF_ENUM values as number (default is enum string)\n"
|
||||
"Array values: Print number of elements, then list of values\n"
|
||||
" Default: Request and print all elements (dynamic arrays supported)\n"
|
||||
" -# <num>: Request and print up to <num> elements\n"
|
||||
" -S: Print arrays of char as a string (long string)\n"
|
||||
"Floating point format:\n"
|
||||
" Default: Use %%g format\n"
|
||||
" -e <num>: Use %%e format, with a precision of <num> digits\n"
|
||||
" -f <num>: Use %%f format, with a precision of <num> digits\n"
|
||||
" -g <num>: Use %%g format, with a precision of <num> digits\n"
|
||||
" -s: Get value as string (honors server-side precision)\n"
|
||||
" -lx: Round to long integer and print as hex number\n"
|
||||
" -lo: Round to long integer and print as octal number\n"
|
||||
" -lb: Round to long integer and print as binary number\n"
|
||||
"Integer number format:\n"
|
||||
" Default: Print as decimal number\n"
|
||||
" -0x: Print as hex number\n"
|
||||
" -0o: Print as octal number\n"
|
||||
" -0b: Print as binary number\n"
|
||||
" Default: Print as decimal number\n"
|
||||
" -0x: Print as hex number\n"
|
||||
" -0o: Print as octal number\n"
|
||||
" -0b: Print as binary number\n"
|
||||
"Alternate output field separator:\n"
|
||||
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
|
||||
"\nExample: camonitor -f8 my_channel another_channel\n"
|
||||
" -F <ofs>: Use <ofs> to separate fields in output\n"
|
||||
"\n"
|
||||
"Example: camonitor -f8 my_channel another_channel\n"
|
||||
" (doubles are printed as %%f with precision of 8)\n\n"
|
||||
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
|
||||
}
|
||||
@@ -92,7 +96,7 @@ void usage (void)
|
||||
* Function: event_handler
|
||||
*
|
||||
* Description: CA event_handler for request type callback
|
||||
* Allocates the dbr structure and copies the data
|
||||
* Prints the event data
|
||||
*
|
||||
* Arg(s) In: args - event handler args (see CA manual)
|
||||
*
|
||||
@@ -107,10 +111,12 @@ static void event_handler (evargs args)
|
||||
{
|
||||
pv->dbrType = args.type;
|
||||
pv->nElems = args.count;
|
||||
memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));
|
||||
pv->value = (void *) args.dbr; /* casting away const */
|
||||
|
||||
print_time_val_sts(pv, reqElems);
|
||||
fflush(stdout);
|
||||
|
||||
pv->value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,51 +135,39 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
{
|
||||
pv *ppv = ( pv * ) ca_puser ( args.chid );
|
||||
if ( args.op == CA_OP_CONN_UP ) {
|
||||
nConn++;
|
||||
if (!ppv->onceConnected) {
|
||||
ppv->onceConnected = 1;
|
||||
/* Set up pv structure */
|
||||
/* ------------------- */
|
||||
|
||||
/* Get natural type and array count */
|
||||
ppv->nElems = ca_element_count(ppv->chid);
|
||||
ppv->dbfType = ca_field_type(ppv->chid);
|
||||
ppv->dbfType = ca_field_type(ppv->chid);
|
||||
ppv->dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */
|
||||
if (dbr_type_is_ENUM(ppv->dbrType)) /* Enums honour -n option */
|
||||
{
|
||||
if (enumAsNr) ppv->dbrType = DBR_TIME_INT;
|
||||
else ppv->dbrType = DBR_TIME_STRING;
|
||||
}
|
||||
else if (floatAsString &&
|
||||
(dbr_type_is_FLOAT(ppv->dbrType) || dbr_type_is_DOUBLE(ppv->dbrType)))
|
||||
{
|
||||
ppv->dbrType = DBR_TIME_STRING;
|
||||
}
|
||||
/* Set request count */
|
||||
ppv->nElems = ca_element_count(ppv->chid);
|
||||
ppv->reqElems = reqElems > ppv->nElems ? ppv->nElems : reqElems;
|
||||
|
||||
/* Set up value structures */
|
||||
ppv->dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */
|
||||
if (dbr_type_is_ENUM(ppv->dbrType)) /* Enums honour -n option */
|
||||
{
|
||||
if (enumAsNr) ppv->dbrType = DBR_TIME_INT;
|
||||
else ppv->dbrType = DBR_TIME_STRING;
|
||||
}
|
||||
|
||||
else if (floatAsString &&
|
||||
(dbr_type_is_FLOAT(ppv->dbrType) || dbr_type_is_DOUBLE(ppv->dbrType)))
|
||||
{
|
||||
ppv->dbrType = DBR_TIME_STRING;
|
||||
}
|
||||
/* Adjust array count */
|
||||
if (reqElems > ppv->nElems)
|
||||
reqElems = ppv->nElems;
|
||||
ppv->reqElems = reqElems;
|
||||
|
||||
ppv->onceConnected = 1;
|
||||
nConn++;
|
||||
/* Issue CA request */
|
||||
/* ---------------- */
|
||||
/* install monitor once with first connect */
|
||||
if ( ! ppv->value ) {
|
||||
/* Allocate value structure */
|
||||
ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->nElems));
|
||||
if ( ppv->value ) {
|
||||
ppv->status = ca_create_subscription(ppv->dbrType,
|
||||
/* install monitor once with first connect */
|
||||
ppv->status = ca_create_subscription(ppv->dbrType,
|
||||
ppv->reqElems,
|
||||
ppv->chid,
|
||||
eventMask,
|
||||
event_handler,
|
||||
(void*)ppv,
|
||||
NULL);
|
||||
if ( ppv->status != ECA_NORMAL ) {
|
||||
free ( ppv->value );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( args.op == CA_OP_CONN_DOWN ) {
|
||||
@@ -203,7 +197,7 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int returncode = 0;
|
||||
int n = 0;
|
||||
int n;
|
||||
int result; /* CA result */
|
||||
IntFormatT outType; /* Output type */
|
||||
|
||||
@@ -211,7 +205,7 @@ int main (int argc, char *argv[])
|
||||
int digits = 0; /* getopt() no. of float digits */
|
||||
|
||||
int nPvs; /* Number of PVs */
|
||||
pv* pvs = 0; /* Array of PV structures */
|
||||
pv* pvs; /* Array of PV structures */
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
|
||||
@@ -356,7 +350,7 @@ int main (int argc, char *argv[])
|
||||
result = ca_context_create(ca_disable_preemptive_callback);
|
||||
if (result != ECA_NORMAL) {
|
||||
fprintf(stderr, "CA error %s occurred while trying "
|
||||
"to start channel access '%s'.\n", ca_message(result), pvs[n].name);
|
||||
"to start channel access.\n", ca_message(result));
|
||||
return 1;
|
||||
}
|
||||
/* Allocate PV structure array */
|
||||
|
||||
@@ -251,7 +251,6 @@ int caget (pv *pvs, int nPvs, OutputT format,
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
int result; /* CA result */
|
||||
OutputT format = plain; /* User specified format */
|
||||
@@ -273,7 +272,7 @@ int main (int argc, char *argv[])
|
||||
struct dbr_gr_enum bufGrEnum;
|
||||
|
||||
int nPvs; /* Number of PVs */
|
||||
pv* pvs = 0; /* Array of PV structures */
|
||||
pv* pvs; /* Array of PV structures */
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
|
||||
@@ -372,7 +371,7 @@ int main (int argc, char *argv[])
|
||||
result = ca_context_create(ca_enable_preemptive_callback);
|
||||
if (result != ECA_NORMAL) {
|
||||
fprintf(stderr, "CA error %s occurred while trying "
|
||||
"to start channel access '%s'.\n", ca_message(result), pvs[n].name);
|
||||
"to start channel access.\n", ca_message(result));
|
||||
return 1;
|
||||
}
|
||||
/* Allocate PV structure array */
|
||||
|
||||
@@ -196,8 +196,8 @@ private:
|
||||
dbContextReadNotifyCache readNotifyCache;
|
||||
dbEventCtx ctx;
|
||||
unsigned long stateNotifyCacheSize;
|
||||
mutable epicsMutex & mutex;
|
||||
mutable epicsMutex & cbMutex;
|
||||
epicsMutex & mutex;
|
||||
epicsMutex & cbMutex;
|
||||
cacContextNotify & notify;
|
||||
epics_auto_ptr < cacContext > pNetContext;
|
||||
char * pStateNotifyCache;
|
||||
|
||||
194
src/db/dbEvent.c
194
src/db/dbEvent.c
@@ -203,35 +203,44 @@ int epicsShareAPI dbel ( const char *pname, unsigned level )
|
||||
}
|
||||
|
||||
if ( level > 1 ) {
|
||||
unsigned nEntriesFree = ringSpace ( pevent->ev_que );
|
||||
unsigned nEntriesFree;
|
||||
const void * taskId;
|
||||
LOCKEVQUE(pevent->ev_que);
|
||||
nEntriesFree = ringSpace ( pevent->ev_que );
|
||||
taskId = ( void * ) pevent->ev_que->evUser->taskid;
|
||||
UNLOCKEVQUE(pevent->ev_que);
|
||||
if ( nEntriesFree == 0u ) {
|
||||
printf ( ", thread=%p, queue full",
|
||||
(void *) pevent->ev_que->evUser->taskid );
|
||||
(void *) taskId );
|
||||
}
|
||||
else if ( nEntriesFree == EVENTQUESIZE ) {
|
||||
printf ( ", thread=%p, queue empty",
|
||||
(void *) pevent->ev_que->evUser->taskid );
|
||||
(void *) taskId );
|
||||
}
|
||||
else {
|
||||
printf ( ", thread=%p, unused entries=%u",
|
||||
(void *) pevent->ev_que->evUser->taskid, nEntriesFree );
|
||||
(void *) taskId, nEntriesFree );
|
||||
}
|
||||
}
|
||||
|
||||
if ( level > 2 ) {
|
||||
unsigned nDuplicates;
|
||||
unsigned nCanceled;
|
||||
if ( pevent->nreplace ) {
|
||||
printf (", discarded by replacement=%ld", pevent->nreplace);
|
||||
}
|
||||
if ( ! pevent->valque ) {
|
||||
printf (", queueing disabled" );
|
||||
}
|
||||
if ( pevent->ev_que->nDuplicates ) {
|
||||
printf (", duplicate count =%u\n",
|
||||
pevent->ev_que->nDuplicates );
|
||||
LOCKEVQUE(pevent->ev_que);
|
||||
nDuplicates = pevent->ev_que->nDuplicates;
|
||||
nCanceled = pevent->ev_que->nCanceled;
|
||||
UNLOCKEVQUE(pevent->ev_que);
|
||||
if ( nDuplicates ) {
|
||||
printf (", duplicate count =%u\n", nDuplicates );
|
||||
}
|
||||
if ( pevent->ev_que->nCanceled ) {
|
||||
printf (", canceled count =%u\n",
|
||||
pevent->ev_que->nCanceled );
|
||||
if ( nCanceled ) {
|
||||
printf (", canceled count =%u\n", nCanceled );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +273,7 @@ int epicsShareAPI dbel ( const char *pname, unsigned level )
|
||||
*/
|
||||
dbEventCtx epicsShareAPI db_init_events (void)
|
||||
{
|
||||
struct event_user *evUser;
|
||||
struct event_user * evUser;
|
||||
|
||||
if (!dbevEventUserFreeList) {
|
||||
freeListInitPvt(&dbevEventUserFreeList,
|
||||
@@ -326,7 +335,7 @@ dbEventCtx epicsShareAPI db_init_events (void)
|
||||
*/
|
||||
void epicsShareAPI db_close_events (dbEventCtx ctx)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
/*
|
||||
* Exit not forced on event blocks for now - this is left to channel
|
||||
@@ -336,13 +345,32 @@ void epicsShareAPI db_close_events (dbEventCtx ctx)
|
||||
* NOTE: not deleting events before calling this routine could be
|
||||
* hazardous to the system's health.
|
||||
*/
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->pendexit = TRUE;
|
||||
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
/* notify the waiting task */
|
||||
epicsEventSignal(evUser->ppendsem);
|
||||
}
|
||||
|
||||
/*
|
||||
* create_ev_que()
|
||||
*/
|
||||
static struct event_que * create_ev_que ( struct event_user * const evUser )
|
||||
{
|
||||
struct event_que * const ev_que = (struct event_que *)
|
||||
freeListCalloc ( dbevEventQueueFreeList );
|
||||
if ( ! ev_que ) {
|
||||
return NULL;
|
||||
}
|
||||
ev_que->writelock = epicsMutexCreate();
|
||||
if ( ! ev_que->writelock ) {
|
||||
freeListFree ( dbevEventQueueFreeList, ev_que );
|
||||
return NULL;
|
||||
}
|
||||
ev_que->evUser = evUser;
|
||||
return ev_que;
|
||||
}
|
||||
|
||||
/*
|
||||
* DB_ADD_EVENT()
|
||||
*/
|
||||
@@ -350,13 +378,9 @@ dbEventSubscription epicsShareAPI db_add_event (
|
||||
dbEventCtx ctx, struct dbAddr *paddr,
|
||||
EVENTFUNC *user_sub, void *user_arg, unsigned select)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct dbCommon *precord;
|
||||
struct event_que *ev_que;
|
||||
struct event_que *tmp_que;
|
||||
struct evSubscrip *pevent;
|
||||
|
||||
precord = paddr->precord;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
struct event_que * ev_que;
|
||||
struct evSubscrip * pevent;
|
||||
|
||||
/*
|
||||
* Don't add events which will not be triggered
|
||||
@@ -365,38 +389,42 @@ dbEventSubscription epicsShareAPI db_add_event (
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pevent = freeListCalloc (dbevEventBlockFreeList);
|
||||
if (!pevent) {
|
||||
pevent = freeListCalloc ( dbevEventBlockFreeList );
|
||||
if ( ! pevent ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find an event que block with enough quota */
|
||||
/* otherwise add a new one to the list */
|
||||
ev_que = &evUser->firstque;
|
||||
while (TRUE) {
|
||||
if (ev_que->quota + ev_que->nCanceled < EVENTQUESIZE - EVENTENTRIES) {
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
ev_que = & evUser->firstque;
|
||||
while ( TRUE ) {
|
||||
int success = 0;
|
||||
LOCKEVQUE ( ev_que );
|
||||
success = ( ev_que->quota + ev_que->nCanceled <
|
||||
EVENTQUESIZE - EVENTENTRIES );
|
||||
if ( success ) {
|
||||
ev_que->quota += EVENTENTRIES;
|
||||
}
|
||||
UNLOCKEVQUE ( ev_que );
|
||||
if ( success ) {
|
||||
break;
|
||||
}
|
||||
if (!ev_que->nextque) {
|
||||
tmp_que = (struct event_que *)
|
||||
freeListCalloc(dbevEventQueueFreeList);
|
||||
if (!tmp_que) {
|
||||
freeListFree (dbevEventBlockFreeList, pevent);
|
||||
return NULL;
|
||||
if ( ! ev_que->nextque ) {
|
||||
ev_que->nextque = create_ev_que ( evUser );
|
||||
if ( ! ev_que->nextque ) {
|
||||
ev_que = NULL;
|
||||
break;
|
||||
}
|
||||
tmp_que->evUser = evUser;
|
||||
tmp_que->writelock = epicsMutexCreate();
|
||||
if (!tmp_que->writelock) {
|
||||
freeListFree (dbevEventBlockFreeList, pevent);
|
||||
freeListFree (dbevEventQueueFreeList, tmp_que);
|
||||
return NULL;
|
||||
}
|
||||
ev_que->nextque = tmp_que;
|
||||
ev_que = tmp_que;
|
||||
break;
|
||||
}
|
||||
ev_que = ev_que->nextque;
|
||||
}
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
|
||||
if ( ! ev_que ) {
|
||||
freeListFree ( dbevEventBlockFreeList, pevent );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pevent->npend = 0ul;
|
||||
pevent->nreplace = 0ul;
|
||||
@@ -409,10 +437,6 @@ dbEventSubscription epicsShareAPI db_add_event (
|
||||
pevent->enabled = FALSE;
|
||||
pevent->ev_que = ev_que;
|
||||
|
||||
LOCKEVQUE(ev_que);
|
||||
ev_que->quota += EVENTENTRIES;
|
||||
UNLOCKEVQUE(ev_que);
|
||||
|
||||
/*
|
||||
* Simple types values queued up for reliable interprocess
|
||||
* communication (for other types they get whatever happens to be
|
||||
@@ -434,10 +458,9 @@ dbEventSubscription epicsShareAPI db_add_event (
|
||||
*/
|
||||
void epicsShareAPI db_event_enable (dbEventSubscription es)
|
||||
{
|
||||
struct evSubscrip *pevent = (struct evSubscrip *) es;
|
||||
struct dbCommon *precord;
|
||||
|
||||
precord = (struct dbCommon *) pevent->paddr->precord;
|
||||
struct evSubscrip * const pevent = (struct evSubscrip *) es;
|
||||
struct dbCommon * const precord =
|
||||
(struct dbCommon *) pevent->paddr->precord;
|
||||
|
||||
LOCKREC(precord);
|
||||
if ( ! pevent->enabled ) {
|
||||
@@ -452,10 +475,9 @@ void epicsShareAPI db_event_enable (dbEventSubscription es)
|
||||
*/
|
||||
void epicsShareAPI db_event_disable (dbEventSubscription es)
|
||||
{
|
||||
struct evSubscrip *pevent = (struct evSubscrip *) es;
|
||||
struct dbCommon *precord;
|
||||
|
||||
precord = (struct dbCommon *) pevent->paddr->precord;
|
||||
struct evSubscrip * const pevent = (struct evSubscrip *) es;
|
||||
struct dbCommon * const precord =
|
||||
(struct dbCommon *) pevent->paddr->precord;
|
||||
|
||||
LOCKREC(precord);
|
||||
if ( pevent->enabled ) {
|
||||
@@ -472,7 +494,7 @@ void epicsShareAPI db_event_disable (dbEventSubscription es)
|
||||
static void event_remove ( struct event_que *ev_que,
|
||||
unsigned short index, struct evSubscrip *placeHolder )
|
||||
{
|
||||
struct evSubscrip *pEvent = ev_que->evque[index];
|
||||
struct evSubscrip * const pEvent = ev_que->evque[index];
|
||||
|
||||
ev_que->evque[index] = placeHolder;
|
||||
if ( pEvent->npend == 1u ) {
|
||||
@@ -495,12 +517,9 @@ static void event_remove ( struct event_que *ev_que,
|
||||
*/
|
||||
void epicsShareAPI db_cancel_event (dbEventSubscription es)
|
||||
{
|
||||
struct evSubscrip * pevent = ( struct evSubscrip * ) es;
|
||||
struct dbCommon * precord;
|
||||
struct evSubscrip * const pevent = ( struct evSubscrip * ) es;
|
||||
unsigned short getix;
|
||||
|
||||
precord = ( struct dbCommon * ) pevent->paddr->precord;
|
||||
|
||||
db_event_disable ( es );
|
||||
|
||||
/*
|
||||
@@ -564,12 +583,12 @@ void epicsShareAPI db_cancel_event (dbEventSubscription es)
|
||||
*/
|
||||
void epicsShareAPI db_flush_extra_labor_event (dbEventCtx ctx)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
while ( evUser->extraLaborBusy ) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
epicsThreadSleep(1.0);
|
||||
epicsThreadSleep(0.1);
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
}
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
@@ -585,7 +604,7 @@ void epicsShareAPI db_flush_extra_labor_event (dbEventCtx ctx)
|
||||
int epicsShareAPI db_add_extra_labor_event (
|
||||
dbEventCtx ctx, EXTRALABORFUNC *func, void *arg)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->extralabor_sub = func;
|
||||
@@ -600,7 +619,7 @@ int epicsShareAPI db_add_extra_labor_event (
|
||||
*/
|
||||
int epicsShareAPI db_post_extra_labor (dbEventCtx ctx)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
int doit;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
@@ -627,12 +646,10 @@ int epicsShareAPI db_post_extra_labor (dbEventCtx ctx)
|
||||
*/
|
||||
static void db_post_single_event_private (struct evSubscrip *event)
|
||||
{
|
||||
struct event_que *ev_que;
|
||||
db_field_log *pLog;
|
||||
int firstEventFlag;
|
||||
unsigned rngSpace;
|
||||
|
||||
ev_que = event->ev_que;
|
||||
struct event_que * const ev_que = event->ev_que;
|
||||
db_field_log * pLog;
|
||||
int firstEventFlag;
|
||||
unsigned rngSpace;
|
||||
|
||||
/*
|
||||
* evUser ring buffer must be locked for the multiple
|
||||
@@ -747,10 +764,10 @@ void *pField,
|
||||
unsigned int caEventMask
|
||||
)
|
||||
{
|
||||
struct dbCommon *pdbc = (struct dbCommon *)pRecord;
|
||||
struct evSubscrip *event;
|
||||
struct dbCommon * const pdbc = (struct dbCommon *)pRecord;
|
||||
struct evSubscrip * event;
|
||||
|
||||
if (pdbc->mlis.count == 0) return DB_EVENT_OK; /* no monitors set */
|
||||
if (pdbc->mlis.count == 0) return DB_EVENT_OK; /* no monitors set */
|
||||
|
||||
LOCKREC(pdbc);
|
||||
|
||||
@@ -762,8 +779,7 @@ unsigned int caEventMask
|
||||
* changed or pval==NULL and waiting on alarms and alarms changed
|
||||
*/
|
||||
if ( (event->paddr->pfield == (void *)pField || pField==NULL) &&
|
||||
(caEventMask & event->select)) {
|
||||
|
||||
(caEventMask & event->select) ) {
|
||||
db_post_single_event_private (event);
|
||||
}
|
||||
}
|
||||
@@ -778,8 +794,8 @@ unsigned int caEventMask
|
||||
*/
|
||||
void epicsShareAPI db_post_single_event (dbEventSubscription es)
|
||||
{
|
||||
struct evSubscrip *event = (struct evSubscrip *) es;
|
||||
struct dbCommon *precord = event->paddr->precord;
|
||||
struct evSubscrip * const event = (struct evSubscrip *) es;
|
||||
struct dbCommon * const precord = event->paddr->precord;
|
||||
|
||||
dbScanLock (precord);
|
||||
db_post_single_event_private (event);
|
||||
@@ -898,8 +914,8 @@ static int event_read ( struct event_que *ev_que )
|
||||
*/
|
||||
static void event_task (void *pParm)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) pParm;
|
||||
struct event_que *ev_que;
|
||||
struct event_user * const evUser = (struct event_user *) pParm;
|
||||
struct event_que * ev_que;
|
||||
|
||||
/* init hook */
|
||||
if (evUser->init_func) {
|
||||
@@ -934,12 +950,14 @@ static void event_task (void *pParm)
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
}
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
|
||||
for ( ev_que = &evUser->firstque; ev_que;
|
||||
ev_que = ev_que->nextque ) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
event_read (ev_que);
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
}
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
|
||||
} while( ! evUser->pendexit );
|
||||
|
||||
@@ -975,7 +993,7 @@ int epicsShareAPI db_start_events (
|
||||
dbEventCtx ctx,const char *taskname, void (*init_func)(void *),
|
||||
void *init_func_arg, unsigned osiPriority )
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
|
||||
@@ -995,7 +1013,8 @@ int epicsShareAPI db_start_events (
|
||||
taskname = EVENT_PEND_NAME;
|
||||
}
|
||||
evUser->taskid = epicsThreadCreate (
|
||||
taskname, osiPriority, epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
taskname, osiPriority,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
event_task, (void *)evUser);
|
||||
if (!evUser->taskid) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
@@ -1008,9 +1027,10 @@ int epicsShareAPI db_start_events (
|
||||
/*
|
||||
* db_event_change_priority()
|
||||
*/
|
||||
void epicsShareAPI db_event_change_priority ( dbEventCtx ctx, unsigned epicsPriority )
|
||||
void epicsShareAPI db_event_change_priority ( dbEventCtx ctx,
|
||||
unsigned epicsPriority )
|
||||
{
|
||||
struct event_user * evUser = ( struct event_user * ) ctx;
|
||||
struct event_user * const evUser = ( struct event_user * ) ctx;
|
||||
epicsThreadSetPriority ( evUser->taskid, epicsPriority );
|
||||
}
|
||||
|
||||
@@ -1019,9 +1039,11 @@ void epicsShareAPI db_event_change_priority ( dbEventCtx ctx, unsigned epicsPrio
|
||||
*/
|
||||
void epicsShareAPI db_event_flow_ctrl_mode_on (dbEventCtx ctx)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->flowCtrlMode = TRUE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
/*
|
||||
* notify the event handler task
|
||||
*/
|
||||
@@ -1036,9 +1058,11 @@ void epicsShareAPI db_event_flow_ctrl_mode_on (dbEventCtx ctx)
|
||||
*/
|
||||
void epicsShareAPI db_event_flow_ctrl_mode_off (dbEventCtx ctx)
|
||||
{
|
||||
struct event_user *evUser = (struct event_user *) ctx;
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->flowCtrlMode = FALSE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
/*
|
||||
* notify the event handler task
|
||||
*/
|
||||
|
||||
@@ -74,7 +74,7 @@ void dbPutNotifyBlocker::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->pn.paddr ) {
|
||||
if ( this->pNotify ) {
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
dbNotifyCancel ( &this->pn );
|
||||
}
|
||||
@@ -100,26 +100,31 @@ void dbPutNotifyBlocker::expandValueBuf (
|
||||
|
||||
extern "C" void putNotifyCompletion ( putNotify *ppn )
|
||||
{
|
||||
dbPutNotifyBlocker * pBlocker = static_cast < dbPutNotifyBlocker * > ( ppn->usrPvt );
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pBlocker->mutex );
|
||||
if ( pBlocker->pNotify ) {
|
||||
if ( pBlocker->pn.status != putNotifyOK) {
|
||||
pBlocker->pNotify->exception (
|
||||
guard, ECA_PUTFAIL, "put notify unsuccessful",
|
||||
static_cast <unsigned> (pBlocker->pn.dbrType),
|
||||
static_cast <unsigned> (pBlocker->pn.nRequest) );
|
||||
}
|
||||
else {
|
||||
pBlocker->pNotify->completion ( guard );
|
||||
}
|
||||
dbPutNotifyBlocker * const pBlocker =
|
||||
static_cast < dbPutNotifyBlocker * > ( ppn->usrPvt );
|
||||
epicsGuard < epicsMutex > guard ( pBlocker->mutex );
|
||||
cacWriteNotify * const pNtfy = pBlocker->pNotify;
|
||||
if ( pNtfy ) {
|
||||
pBlocker->pNotify = 0;
|
||||
// Its necessary to signal the initiators now before we call
|
||||
// the user callback. This is less efficent, and potentially
|
||||
// causes more thread context switching, but its probably
|
||||
// unavoidable because its possible that the use callback
|
||||
// might destroy this object.
|
||||
pBlocker->block.signal ();
|
||||
if ( pBlocker->pn.status != putNotifyOK ) {
|
||||
pNtfy->exception (
|
||||
guard, ECA_PUTFAIL, "put notify unsuccessful",
|
||||
static_cast < unsigned > (pBlocker->pn.dbrType),
|
||||
static_cast < unsigned > (pBlocker->pn.nRequest) );
|
||||
}
|
||||
else {
|
||||
errlogPrintf ( "put notify completion with nill pNotify?\n" );
|
||||
pNtfy->completion ( guard );
|
||||
}
|
||||
pBlocker->pNotify = 0;
|
||||
}
|
||||
pBlocker->block.signal ();
|
||||
else {
|
||||
errlogPrintf ( "put notify completion with nill pNotify?\n" );
|
||||
}
|
||||
}
|
||||
|
||||
void dbPutNotifyBlocker::initiatePutNotify (
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2011 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.
|
||||
\*************************************************************************/
|
||||
/* dbExpand.c */
|
||||
/* Author: Marty Kraimer Date: 30NOV95 */
|
||||
/* Author: Marty Kraimer Date: 30NOV95 */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
@@ -25,24 +24,25 @@
|
||||
#include "osiFileName.h"
|
||||
|
||||
DBBASE *pdbbase = NULL;
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage:\n\tdbExpand -Ipath -ooutfile "
|
||||
"-S macro=value file1.dbd file2.dbd ...\n");
|
||||
fprintf(stderr, "Usage:\n\tdbExpand -b -Ipath -ooutfile "
|
||||
"-S macro=value file1.dbd file2.dbd ...\n");
|
||||
fprintf(stderr,"Specifying any path will replace the default of '.'\n");
|
||||
fprintf(stderr,"The -b option enables relaxed breakpoint table checking\n");
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
char *path = NULL;
|
||||
char *sub = NULL;
|
||||
int pathLength = 0;
|
||||
int subLength = 0;
|
||||
char *path = NULL;
|
||||
char *sub = NULL;
|
||||
int pathLength = 0;
|
||||
int subLength = 0;
|
||||
char *outFilename = NULL;
|
||||
FILE *outFP = stdout;
|
||||
long status;
|
||||
long returnStatus = 0;
|
||||
long status;
|
||||
long returnStatus = 0;
|
||||
static char *pathSep = OSI_PATH_LIST_SEPARATOR;
|
||||
static char *subSep = ",";
|
||||
|
||||
@@ -53,8 +53,8 @@ int main(int argc,char **argv)
|
||||
while ((argc > 1) && (**argv == '-')) {
|
||||
char optLtr = (*argv)[1];
|
||||
char *optArg;
|
||||
|
||||
if (strlen(*argv) > 2) {
|
||||
|
||||
if (strlen(*argv) > 2 || optLtr == 'b') {
|
||||
optArg = *argv+2;
|
||||
++argv;
|
||||
--argc;
|
||||
@@ -63,36 +63,40 @@ int main(int argc,char **argv)
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
|
||||
|
||||
switch (optLtr) {
|
||||
case 'o':
|
||||
outFilename = optArg;
|
||||
break;
|
||||
|
||||
|
||||
case 'I':
|
||||
dbCatString(&path, &pathLength, optArg, pathSep);
|
||||
break;
|
||||
|
||||
|
||||
case 'S':
|
||||
dbCatString(&sub, &subLength, optArg, subSep);
|
||||
break;
|
||||
|
||||
|
||||
case 'b':
|
||||
dbBptNotMonotonic = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "dbExpand: Unknown option '-%c'\n", optLtr);
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (argc < 1) {
|
||||
fprintf(stderr, "dbExpand: No input file specified\n");
|
||||
fprintf(stderr, "dbExpand: No input file specified\n");
|
||||
usage();
|
||||
exit(1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
for (; argc>0; --argc, ++argv) {
|
||||
status = dbReadDatabase(&pdbbase,*argv,path,sub);
|
||||
if (status) returnStatus = status;
|
||||
status = dbReadDatabase(&pdbbase,*argv,path,sub);
|
||||
if (status) returnStatus = status;
|
||||
}
|
||||
if (returnStatus) {
|
||||
errlogFlush();
|
||||
@@ -106,7 +110,7 @@ int main(int argc,char **argv)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dbWriteMenuFP(pdbbase,outFP,0);
|
||||
dbWriteRecordTypeFP(pdbbase,outFP,0);
|
||||
dbWriteDeviceFP(pdbbase,outFP);
|
||||
@@ -116,7 +120,7 @@ int main(int argc,char **argv)
|
||||
dbWriteVariableFP(pdbbase,outFP);
|
||||
dbWriteBreaktableFP(pdbbase,outFP);
|
||||
dbWriteRecordFP(pdbbase,outFP,0,0);
|
||||
|
||||
|
||||
free((void *)path);
|
||||
free((void *)sub);
|
||||
return 0;
|
||||
|
||||
@@ -74,6 +74,8 @@ epicsShareFunc DBENTRY * epicsShareAPI dbCopyEntry(DBENTRY *pdbentry);
|
||||
epicsShareFunc void epicsShareAPI dbCopyEntryContents(DBENTRY *pfrom,
|
||||
DBENTRY *pto);
|
||||
|
||||
epicsShareExtern int dbBptNotMonotonic;
|
||||
|
||||
epicsShareFunc long epicsShareAPI dbReadDatabase(DBBASE **ppdbbase,
|
||||
const char *filename, const char *path, const char *substitutions);
|
||||
epicsShareFunc long epicsShareAPI dbReadDatabaseFP(DBBASE **ppdbbase,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
@@ -19,7 +19,7 @@ SRC_DIRS += $(TOP)/src/makeBaseApp/top/caServerApp
|
||||
#
|
||||
# Added ws2_32 winmm user32 for the non-dll build
|
||||
#
|
||||
SYS_PROD_LIBS_WIN32 += ws2_32 advapi32 user32
|
||||
PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
|
||||
|
||||
|
||||
PROD_HOST = excas
|
||||
|
||||
@@ -222,8 +222,6 @@ SRCS += epicsTempFile.cpp
|
||||
SRCS += epicsStdio.c
|
||||
SRCS += osdStdio.c
|
||||
|
||||
osdEnv_CFLAGS_WIN32= -U__STDC__
|
||||
|
||||
SRCS += osdThread.c
|
||||
SRCS += osdMutex.c
|
||||
SRCS += osdEvent.c
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
void * pInstance () const;
|
||||
private:
|
||||
void * _pInstance;
|
||||
size_t _refCount;
|
||||
std :: size_t _refCount;
|
||||
SingletonUntyped ( const SingletonUntyped & );
|
||||
SingletonUntyped & operator = ( const SingletonUntyped & );
|
||||
};
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
/*Declare storage for errVerbose */
|
||||
epicsShareDef int errVerbose = 0;
|
||||
|
||||
static void errlogCleanup(void);
|
||||
static void exitHandler(void *);
|
||||
static void errlogThread(void);
|
||||
|
||||
@@ -391,8 +390,15 @@ static void exitHandler(void *pvt)
|
||||
pvtData.atExit = 1;
|
||||
epicsEventSignal(pvtData.waitForWork);
|
||||
epicsEventMustWait(pvtData.waitForExit);
|
||||
|
||||
free(pvtData.pbuffer);
|
||||
epicsMutexDestroy(pvtData.flushLock);
|
||||
epicsEventDestroy(pvtData.flush);
|
||||
epicsEventDestroy(pvtData.waitForFlush);
|
||||
epicsMutexDestroy(pvtData.listenerLock);
|
||||
epicsMutexDestroy(pvtData.msgQueueLock);
|
||||
epicsEventDestroy(pvtData.waitForWork);
|
||||
epicsEventDestroy(pvtData.waitForExit);
|
||||
return;
|
||||
}
|
||||
|
||||
struct initArgs {
|
||||
@@ -432,18 +438,6 @@ static void errlogInitPvt(void *arg)
|
||||
pvtData.errlogInitFailed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void errlogCleanup(void)
|
||||
{
|
||||
free(pvtData.pbuffer);
|
||||
epicsMutexDestroy(pvtData.flushLock);
|
||||
epicsEventDestroy(pvtData.flush);
|
||||
epicsEventDestroy(pvtData.waitForFlush);
|
||||
epicsMutexDestroy(pvtData.listenerLock);
|
||||
epicsMutexDestroy(pvtData.msgQueueLock);
|
||||
epicsEventDestroy(pvtData.waitForWork);
|
||||
/*Note that exitHandler must destroy waitForExit*/
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI errlogInit2(int bufsize, int maxMsgSize)
|
||||
{
|
||||
@@ -514,7 +508,6 @@ static void errlogThread(void)
|
||||
epicsThreadSleep(.2); /*just wait an extra .2 seconds*/
|
||||
epicsEventSignal(pvtData.waitForFlush);
|
||||
}
|
||||
errlogCleanup();
|
||||
epicsEventSignal(pvtData.waitForExit);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
/*
|
||||
* Deprecation marker
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#if defined( __GNUC__ ) && (__GNUC__ > 2)
|
||||
# define EPICS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
# define EPICS_DEPRECATED
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
@@ -13,10 +12,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -24,8 +19,6 @@ extern "C" {
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
/*#include <sys/filio.h>
|
||||
#include <sys/sockio.h>*/
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -34,10 +27,6 @@ extern "C" {
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
@@ -26,10 +25,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -37,8 +32,6 @@ extern "C" {
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
/*#include <sys/filio.h>
|
||||
#include <sys/sockio.h>*/
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -47,10 +40,6 @@ extern "C" {
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
@@ -14,10 +13,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -32,6 +27,10 @@ extern "C" {
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <rtems/rtems_bsdnet_internal.h>
|
||||
#include "epicsTime.h"
|
||||
#include "osdTime.h"
|
||||
#include "osiNTPTime.h"
|
||||
@@ -117,17 +118,21 @@ double rtemsTicksPerSecond_double, rtemsTicksPerTwoSeconds_double;
|
||||
* explicitly calls osdTimeRegister() at the appropriate time.
|
||||
* However if we are loaded dynamically we *do* register our
|
||||
* standard time providers at static constructor time; in this
|
||||
* case the tick rate will have been set already.
|
||||
* case the network is available already.
|
||||
*/
|
||||
static int staticTimeRegister(void)
|
||||
{
|
||||
if (rtemsTicksPerSecond != 0)
|
||||
osdTimeRegister();
|
||||
|
||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtemsTicksPerSecond);
|
||||
rtemsTicksPerSecond_double = rtemsTicksPerSecond;
|
||||
rtemsTicksPerTwoSeconds_double = rtemsTicksPerSecond_double * 2.0;
|
||||
|
||||
/* If networking is already up at the time static constructors
|
||||
* are executed then we are probably run-time loaded and it's
|
||||
* OK to osdTimeRegister() at this point.
|
||||
*/
|
||||
if (rtems_bsdnet_ticks_per_second != 0)
|
||||
osdTimeRegister();
|
||||
|
||||
return 1;
|
||||
}
|
||||
static int done = staticTimeRegister();
|
||||
|
||||
@@ -3,15 +3,12 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
@@ -25,9 +22,6 @@ extern "C" {
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SOCKERRNO WSAGetLastError()
|
||||
|
||||
@@ -79,3 +73,4 @@ typedef int osiSocklen_t;
|
||||
|
||||
epicsShareFunc unsigned epicsShareAPI wsaMajorVersion ();
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
@@ -272,10 +272,6 @@ static void threadCleanupWIN32 ( void )
|
||||
ellFirst ( & pGbl->threadList ) ) ) {
|
||||
epicsParmCleanupWIN32 ( pParm );
|
||||
}
|
||||
|
||||
TlsFree ( pGbl->tlsIndexThreadLibraryEPICS );
|
||||
|
||||
DeleteCriticalSection ( & pGbl->mutex );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -60,6 +60,7 @@ static int osdTimeGetCurrent ( epicsTimeStamp *pDest );
|
||||
// for mingw
|
||||
#if !defined ( MAXLONGLONG )
|
||||
#define MAXLONGLONG LL_CONSTANT(0x7fffffffffffffff)
|
||||
#define MINLONGLONG LL_CONSTANT(~0x7fffffffffffffff)
|
||||
#endif
|
||||
|
||||
static const LONGLONG epicsEpochInFileTime = LL_CONSTANT(0x01b41e2a18d64000);
|
||||
@@ -81,7 +82,7 @@ private:
|
||||
epicsTimerQueueActive * pTimerQueue;
|
||||
epicsTimer * pTimer;
|
||||
bool perfCtrPresent;
|
||||
|
||||
static const int pllDelay; /* integer seconds */
|
||||
epicsTimerNotify::expireStatus expire ( const epicsTime & );
|
||||
};
|
||||
|
||||
@@ -91,6 +92,8 @@ static const LONGLONG EPICS_TIME_TICKS_PER_SEC = 1000000000;
|
||||
static const LONGLONG ET_TICKS_PER_FT_TICK =
|
||||
EPICS_TIME_TICKS_PER_SEC / FILE_TIME_TICKS_PER_SEC;
|
||||
|
||||
const int currentTime :: pllDelay = 5;
|
||||
|
||||
//
|
||||
// Start and register time provider
|
||||
//
|
||||
@@ -302,8 +305,8 @@ currentTime::currentTime () :
|
||||
}
|
||||
else {
|
||||
errlogPrintf (
|
||||
"win32 osdTime.cpp detected questionable "
|
||||
"system date prior to EPICS epoch\n" );
|
||||
"win32 osdTime.cpp init detected questionable "
|
||||
"system date prior to EPICS epoch, epics time will not advance\n" );
|
||||
this->epicsTimeLast = 0;
|
||||
}
|
||||
|
||||
@@ -346,7 +349,7 @@ void currentTime::getCurrentTime ( epicsTimeStamp & dest )
|
||||
// counter resolution will more than likely improve over time.
|
||||
//
|
||||
offset = ( MAXLONGLONG - this->lastPerfCounter )
|
||||
+ ( curPerfCounter.QuadPart + MAXLONGLONG );
|
||||
+ ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
|
||||
}
|
||||
if ( offset < MAXLONGLONG / EPICS_TIME_TICKS_PER_SEC ) {
|
||||
offset *= EPICS_TIME_TICKS_PER_SEC;
|
||||
@@ -392,6 +395,8 @@ void currentTime::getCurrentTime ( epicsTimeStamp & dest )
|
||||
//
|
||||
epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
{
|
||||
EnterCriticalSection ( & this->mutex );
|
||||
|
||||
// avoid interruptions by briefly becoming a time critical thread
|
||||
LARGE_INTEGER curFileTime;
|
||||
LARGE_INTEGER curPerfCounter;
|
||||
@@ -407,8 +412,6 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
curFileTime.HighPart = ft.dwHighDateTime;
|
||||
}
|
||||
|
||||
EnterCriticalSection ( & this->mutex );
|
||||
|
||||
LONGLONG perfCounterDiff;
|
||||
if ( curPerfCounter.QuadPart >= this->lastPerfCounterPLL ) {
|
||||
perfCounterDiff = curPerfCounter.QuadPart - this->lastPerfCounterPLL;
|
||||
@@ -424,7 +427,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
// counter resolution will more than likely improve over time.
|
||||
//
|
||||
perfCounterDiff = ( MAXLONGLONG - this->lastPerfCounterPLL )
|
||||
+ ( curPerfCounter.QuadPart + MAXLONGLONG );
|
||||
+ ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
|
||||
}
|
||||
this->lastPerfCounterPLL = curPerfCounter.QuadPart;
|
||||
|
||||
@@ -432,10 +435,10 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
this->lastFileTimePLL = curFileTime.QuadPart;
|
||||
|
||||
// discard glitches
|
||||
if ( fileTimeDiff == 0 ) {
|
||||
if ( fileTimeDiff <= 0 ) {
|
||||
LeaveCriticalSection( & this->mutex );
|
||||
debugPrintf ( ( "currentTime: file time difference in PLL was zero\n" ) );
|
||||
return expireStatus ( restart, 1.0 /* sec */ );
|
||||
debugPrintf ( ( "currentTime: file time difference in PLL was less than zero\n" ) );
|
||||
return expireStatus ( restart, pllDelay /* sec */ );
|
||||
}
|
||||
|
||||
LONGLONG freq = ( FILE_TIME_TICKS_PER_SEC * perfCounterDiff ) / fileTimeDiff;
|
||||
@@ -449,7 +452,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
static_cast < int > ( -bound ),
|
||||
static_cast < int > ( delta ),
|
||||
static_cast < int > ( bound ) ) );
|
||||
return expireStatus ( restart, 1.0 /* sec */ );
|
||||
return expireStatus ( restart, pllDelay /* sec */ );
|
||||
}
|
||||
|
||||
// update feedback loop estimating the performance counter's frequency
|
||||
@@ -473,7 +476,21 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
//
|
||||
perfCounterDiffSinceLastFetch =
|
||||
( MAXLONGLONG - this->lastPerfCounter )
|
||||
+ ( curPerfCounter.QuadPart + MAXLONGLONG );
|
||||
+ ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
|
||||
}
|
||||
|
||||
// discard performance counter delay measurement glitches
|
||||
{
|
||||
const LONGLONG expectedDly = this->perfCounterFreq * pllDelay;
|
||||
const LONGLONG bnd = expectedDly / 4;
|
||||
if ( perfCounterDiffSinceLastFetch <= 0 ||
|
||||
perfCounterDiffSinceLastFetch >= expectedDly + bnd ) {
|
||||
LeaveCriticalSection( & this->mutex );
|
||||
debugPrintf ( ( "perf ctr measured delay out of bounds m=%d max=%d\n",
|
||||
static_cast < int > ( perfCounterDiffSinceLastFetch ),
|
||||
static_cast < int > ( expectedDly + bnd ) ) );
|
||||
return expireStatus ( restart, pllDelay /* sec */ );
|
||||
}
|
||||
}
|
||||
|
||||
// Update the current estimated time.
|
||||
@@ -482,9 +499,32 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
/ this->perfCounterFreq;
|
||||
this->lastPerfCounter = curPerfCounter.QuadPart;
|
||||
|
||||
LONGLONG epicsTimeFromCurrentFileTime =
|
||||
( curFileTime.QuadPart - epicsEpochInFileTime ) *
|
||||
ET_TICKS_PER_FT_TICK;
|
||||
LONGLONG epicsTimeFromCurrentFileTime;
|
||||
|
||||
{
|
||||
static bool firstMessageWasSent = false;
|
||||
if ( curFileTime.QuadPart >= epicsEpochInFileTime ) {
|
||||
epicsTimeFromCurrentFileTime =
|
||||
( curFileTime.QuadPart - epicsEpochInFileTime ) *
|
||||
ET_TICKS_PER_FT_TICK;
|
||||
firstMessageWasSent = false;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* if the system time jumps to before the EPICS epoch
|
||||
* then latch to the EPICS epoch printing only one
|
||||
* warning message the first time that the issue is
|
||||
* detected
|
||||
*/
|
||||
if ( ! firstMessageWasSent ) {
|
||||
errlogPrintf (
|
||||
"win32 osdTime.cpp time PLL update detected questionable "
|
||||
"system date prior to EPICS epoch, epics time will not advance\n" );
|
||||
firstMessageWasSent = true;
|
||||
}
|
||||
epicsTimeFromCurrentFileTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
delta = epicsTimeFromCurrentFileTime - this->epicsTimeLast;
|
||||
if ( delta > EPICS_TIME_TICKS_PER_SEC || delta < -EPICS_TIME_TICKS_PER_SEC ) {
|
||||
@@ -537,7 +577,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
|
||||
|
||||
LeaveCriticalSection ( & this->mutex );
|
||||
|
||||
return expireStatus ( restart, 1.0 /* sec */ );
|
||||
return expireStatus ( restart, pllDelay /* sec */ );
|
||||
}
|
||||
|
||||
void currentTime::startPLL ()
|
||||
@@ -546,7 +586,7 @@ void currentTime::startPLL ()
|
||||
if ( this->perfCtrPresent && ! this->pTimerQueue ) {
|
||||
this->pTimerQueue = & epicsTimerQueueActive::allocate ( true );
|
||||
this->pTimer = & this->pTimerQueue->createTimer ();
|
||||
this->pTimer->start ( *this, 1.0 );
|
||||
this->pTimer->start ( *this, pllDelay );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
@@ -15,10 +14,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -31,10 +26,7 @@ extern "C" {
|
||||
#include <netdb.h>
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -29,10 +25,6 @@ extern "C" {
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef IPPORT_USERRESERVED
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
#endif
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -24,8 +20,6 @@ extern "C" {
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
/*#include <sys/filio.h>
|
||||
#include <sys/sockio.h>*/
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -34,10 +28,6 @@ extern "C" {
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
|
||||
@@ -75,6 +75,13 @@ typedef struct epicsThreadOSD {
|
||||
char *name;
|
||||
} epicsThreadOSD;
|
||||
|
||||
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
typedef struct {
|
||||
int min_pri, max_pri;
|
||||
int policy;
|
||||
} priAvailable;
|
||||
#endif
|
||||
|
||||
static pthread_key_t getpthreadInfo;
|
||||
static pthread_mutex_t onceLock;
|
||||
static pthread_mutex_t listLock;
|
||||
@@ -201,6 +208,101 @@ static void free_threadInfo(epicsThreadOSD *pthreadInfo)
|
||||
free(pthreadInfo);
|
||||
}
|
||||
|
||||
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
|
||||
/*
|
||||
* The actually available range priority range (at least under linux)
|
||||
* may be restricted by resource limitations (but that is ignored
|
||||
* by sched_get_priority_max()). See bug #835138 which is fixed by
|
||||
* this code.
|
||||
*/
|
||||
|
||||
static int try_pri(int pri, int policy)
|
||||
{
|
||||
struct sched_param schedp;
|
||||
|
||||
schedp.sched_priority = pri;
|
||||
return pthread_setschedparam(pthread_self(), policy, &schedp);
|
||||
}
|
||||
|
||||
static void*
|
||||
find_pri_range(void *arg)
|
||||
{
|
||||
priAvailable *prm = arg;
|
||||
int min = sched_get_priority_min(prm->policy);
|
||||
int max = sched_get_priority_max(prm->policy);
|
||||
int low, try;
|
||||
|
||||
if ( -1 == min || -1 == max ) {
|
||||
/* something is very wrong; maintain old behavior
|
||||
* (warning message if sched_get_priority_xxx() fails
|
||||
* and use default policy's sched_priority [even if
|
||||
* that is likely to cause epicsThreadCreate to fail
|
||||
* because that priority is not suitable for SCHED_FIFO]).
|
||||
*/
|
||||
prm->min_pri = prm->max_pri = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ( try_pri(min, prm->policy) ) {
|
||||
/* cannot create thread at minimum priority;
|
||||
* probably no permission to use SCHED_FIFO
|
||||
* at all. However, we still must return
|
||||
* a priority range accepted by the SCHED_FIFO
|
||||
* policy. Otherwise, epicsThreadCreate() cannot
|
||||
* detect the unsufficient permission (EPERM)
|
||||
* and fall back to a non-RT thread (because
|
||||
* pthread_attr_setschedparam would fail with
|
||||
* EINVAL due to the bad priority).
|
||||
*/
|
||||
prm->min_pri = prm->max_pri = min;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Binary search through available priorities.
|
||||
* The actually available range may be restricted
|
||||
* by resource limitations (but that is ignored
|
||||
* by sched_get_priority_max() [linux]).
|
||||
*/
|
||||
low = min;
|
||||
|
||||
while ( low < max ) {
|
||||
try = (max+low)/2;
|
||||
if ( try_pri(try, prm->policy) ) {
|
||||
max = try;
|
||||
} else {
|
||||
low = try + 1;
|
||||
}
|
||||
}
|
||||
|
||||
prm->min_pri = min;
|
||||
prm->max_pri = try_pri(max, prm->policy) ? max-1 : max;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void findPriorityRange(commonAttr *a_p)
|
||||
{
|
||||
priAvailable arg;
|
||||
pthread_t id;
|
||||
void *dummy;
|
||||
int status;
|
||||
|
||||
arg.policy = a_p->schedPolicy;
|
||||
|
||||
status = pthread_create(&id, 0, find_pri_range, &arg);
|
||||
checkStatusQuit(status, "pthread_create","epicsThreadInit");
|
||||
|
||||
status = pthread_join(id, &dummy);
|
||||
checkStatusQuit(status, "pthread_join","epicsThreadInit");
|
||||
|
||||
a_p->minPriority = arg.min_pri;
|
||||
a_p->maxPriority = arg.max_pri;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void once(void)
|
||||
{
|
||||
epicsThreadOSD *pthreadInfo;
|
||||
@@ -230,13 +332,14 @@ static void once(void)
|
||||
status = pthread_attr_getschedparam(
|
||||
&pcommonAttr->attr,&pcommonAttr->schedParam);
|
||||
checkStatusOnce(status,"pthread_attr_getschedparam");
|
||||
pcommonAttr->maxPriority = sched_get_priority_max(pcommonAttr->schedPolicy);
|
||||
|
||||
findPriorityRange(pcommonAttr);
|
||||
|
||||
if(pcommonAttr->maxPriority == -1) {
|
||||
pcommonAttr->maxPriority = pcommonAttr->schedParam.sched_priority;
|
||||
fprintf(stderr,"sched_get_priority_max failed set to %d\n",
|
||||
pcommonAttr->maxPriority);
|
||||
}
|
||||
pcommonAttr->minPriority = sched_get_priority_min(pcommonAttr->schedPolicy);
|
||||
if(pcommonAttr->minPriority == -1) {
|
||||
pcommonAttr->minPriority = pcommonAttr->schedParam.sched_priority;
|
||||
fprintf(stderr,"sched_get_priority_min failed set to %d\n",
|
||||
@@ -422,7 +525,7 @@ static epicsThreadOSD *createImplicit(void)
|
||||
int status;
|
||||
|
||||
tid = pthread_self();
|
||||
sprintf(name, "non-EPICS_%d", (int)tid);
|
||||
sprintf(name, "non-EPICS_%ld", (long)tid);
|
||||
pthreadInfo = create_threadInfo(name);
|
||||
pthreadInfo->tid = tid;
|
||||
pthreadInfo->osiPriority = 0;
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
@@ -15,10 +14,6 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -35,10 +30,7 @@ extern "C" {
|
||||
#include <netdb.h>
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKERRNO errno
|
||||
|
||||
@@ -50,9 +50,9 @@ static myISR *isrFetch(unsigned vectorNumber);
|
||||
|
||||
/*
|
||||
* this routine needs to be in the symbol table
|
||||
* for this code to work correctly
|
||||
* (i.e. not static) for this code to work correctly
|
||||
*/
|
||||
static void unsolicitedHandlerEPICS(int vectorNumber);
|
||||
void unsolicitedHandlerEPICS(int vectorNumber);
|
||||
|
||||
/*
|
||||
* this is in veclist.c
|
||||
@@ -412,8 +412,10 @@ static int vxDevInterruptInUseVME (unsigned vectorNumber)
|
||||
* interrupt and an interrupt arrives on the
|
||||
* disconnected vector
|
||||
*
|
||||
* This routine needs to be in the symbol table
|
||||
* (i.e. not static) for this code to work correctly
|
||||
*/
|
||||
static void unsolicitedHandlerEPICS(int vectorNumber)
|
||||
void unsolicitedHandlerEPICS(int vectorNumber)
|
||||
{
|
||||
/*
|
||||
* call logMsg() and not errMessage()
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
@@ -14,12 +13,10 @@
|
||||
#ifndef osdSockH
|
||||
#define osdSockH
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This is needed for vxWorks 6.8 to prevent an obnoxious compiler warning */
|
||||
#ifndef _VSB_CONFIG_FILE
|
||||
#define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@@ -36,6 +33,11 @@ extern "C" {
|
||||
#include <ioLib.h>
|
||||
#include <hostLib.h>
|
||||
#include <selectLib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*This following is not defined in any vxWorks header files*/
|
||||
int sysClkRateGet(void);
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ MAIN(epicsErrlogTest)
|
||||
pvt.expect = "Testing";
|
||||
pvt.checkLen = strlen(pvt.expect);
|
||||
|
||||
errlogPrintfNoConsole(pvt.expect);
|
||||
errlogPrintfNoConsole("%s", pvt.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 1);
|
||||
@@ -153,7 +153,7 @@ MAIN(epicsErrlogTest)
|
||||
pvt2.expect = pvt.expect = "Testing2";
|
||||
pvt2.checkLen = pvt.checkLen = strlen(pvt.expect);
|
||||
|
||||
errlogPrintfNoConsole(pvt.expect);
|
||||
errlogPrintfNoConsole("%s", pvt.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
@@ -165,7 +165,7 @@ MAIN(epicsErrlogTest)
|
||||
pvt2.expect = "Testing3";
|
||||
pvt2.checkLen = strlen(pvt2.expect);
|
||||
|
||||
errlogPrintfNoConsole(pvt2.expect);
|
||||
errlogPrintfNoConsole("%s", pvt2.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
@@ -188,7 +188,7 @@ MAIN(epicsErrlogTest)
|
||||
pvt.expect = truncmsg;
|
||||
pvt.checkLen = 255;
|
||||
|
||||
errlogPrintfNoConsole(longmsg);
|
||||
errlogPrintfNoConsole("%s", longmsg);
|
||||
errlogFlush();
|
||||
|
||||
testOk1(pvt.count == 3);
|
||||
@@ -201,7 +201,7 @@ MAIN(epicsErrlogTest)
|
||||
*/
|
||||
pvt.jam = 1;
|
||||
|
||||
errlogPrintfNoConsole(longmsg);
|
||||
errlogPrintfNoConsole("%s", longmsg);
|
||||
epicsThreadSleep(0.1);
|
||||
|
||||
testOk1(pvt.count == 3);
|
||||
@@ -227,7 +227,7 @@ MAIN(epicsErrlogTest)
|
||||
pvt.jam = 1;
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
errlogPrintfNoConsole(msg);
|
||||
errlogPrintfNoConsole("%s", msg);
|
||||
}
|
||||
|
||||
epicsEventSignal(pvt.jammer);
|
||||
@@ -258,7 +258,7 @@ MAIN(epicsErrlogTest)
|
||||
testDiag("Filling with %d messages of size %d", (int) N, (int) mlen);
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
errlogPrintfNoConsole(msg);
|
||||
errlogPrintfNoConsole("%s", msg);
|
||||
}
|
||||
epicsThreadSleep(0.1); /* should really be a second Event */
|
||||
|
||||
@@ -273,10 +273,10 @@ MAIN(epicsErrlogTest)
|
||||
testOk1(pvt.count == 2);
|
||||
|
||||
/* The buffer has space for 1 more message: sizeof(msgNode) + 256 bytes */
|
||||
errlogPrintfNoConsole(msg); /* Use up that space */
|
||||
errlogPrintfNoConsole("%s", msg); /* Use up that space */
|
||||
|
||||
testDiag("Overflow the buffer");
|
||||
errlogPrintfNoConsole(msg);
|
||||
errlogPrintfNoConsole("%s", msg);
|
||||
|
||||
testOk1(pvt.count == 2);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ static void check(const char *str, const char *expect)
|
||||
testDiag("Got \"%s\", expected \"%s\".\n", got, expect);
|
||||
pass = 0;
|
||||
}
|
||||
testOk(pass, str);
|
||||
testOk(pass, "%s", str);
|
||||
}
|
||||
|
||||
MAIN(macEnvExpandTest)
|
||||
|
||||
@@ -58,20 +58,21 @@ epicsTimerQueueActiveForC & timerQueueActiveMgr ::
|
||||
void timerQueueActiveMgr ::
|
||||
release ( epicsTimerQueueActiveForC & queue )
|
||||
{
|
||||
timerQueueActiveMgrPrivate * pPriv = & queue;
|
||||
{
|
||||
epicsGuard < epicsMutex > locker ( this->mutex );
|
||||
assert ( queue.timerQueueActiveMgrPrivate::referenceCount > 0u );
|
||||
queue.timerQueueActiveMgrPrivate::referenceCount--;
|
||||
if ( queue.timerQueueActiveMgrPrivate::referenceCount == 0u ) {
|
||||
if ( queue.sharingOK () ) {
|
||||
this->sharedQueueList.remove ( queue );
|
||||
}
|
||||
if ( queue.timerQueueActiveMgrPrivate::referenceCount > 0u ) {
|
||||
return;
|
||||
}
|
||||
else if ( queue.sharingOK () ) {
|
||||
this->sharedQueueList.remove ( queue );
|
||||
}
|
||||
}
|
||||
// delete only after we release the guard in case the embedded
|
||||
// reference is the last one and this object is destroyed
|
||||
// as a side effect
|
||||
timerQueueActiveMgrPrivate * pPriv = & queue;
|
||||
delete pPriv;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,15 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
|
||||
# Authors: Ralph Lange, Marty Kraimer, Andrew Johnson and Janet Anderson
|
||||
# $Revision-Id$
|
||||
|
||||
use FindBin qw($Bin);
|
||||
use lib ("$Bin/../../lib/perl", $Bin);
|
||||
|
||||
use Cwd;
|
||||
use Getopt::Std;
|
||||
use File::Find;
|
||||
use File::Path;
|
||||
use File::Path 'mkpath';
|
||||
use EPICS::Path;
|
||||
use EPICS::Release;
|
||||
|
||||
$app_top = cwd();
|
||||
|
||||
@@ -17,10 +22,8 @@ $app_top = cwd();
|
||||
$bad_ident_chars = '[^0-9A-Za-z_]';
|
||||
|
||||
&GetUser; # Ensure we know who's in charge
|
||||
&readRelease("configure/RELEASE", \%release, \@apps) if (-r "configure/RELEASE");
|
||||
&readRelease("configure/RELEASE.$ENV{EPICS_HOST_ARCH}", \%release, \@apps)
|
||||
if (-r "configure/RELEASE.$ENV{EPICS_HOST_ARCH}");
|
||||
&expandRelease(\%release, \@apps);
|
||||
&readReleaseFiles("configure/RELEASE", \%release, \@apps);
|
||||
&expandRelease(\%release);
|
||||
&get_commandline_opts; # Check command-line options
|
||||
|
||||
#
|
||||
@@ -297,57 +300,6 @@ sub get_commandline_opts { #no args
|
||||
. "EPICS-Base: $epics_base\n\n" if $opt_d;
|
||||
}
|
||||
|
||||
#
|
||||
# Parse a configure/RELEASE file.
|
||||
#
|
||||
# NB: This subroutine also appears in base/configure/tools/convertRelease.pl
|
||||
# If you make changes here, they will be needed there as well.
|
||||
#
|
||||
sub readRelease {
|
||||
my ($file, $Rmacros, $Rapps) = @_;
|
||||
# $Rmacros is a reference to a hash, $Rapps a ref to an array
|
||||
my ($pre, $var, $post, $macro, $path);
|
||||
local *IN;
|
||||
open(IN, $file) or die "Can't open $file: $!\n";
|
||||
while (<IN>) {
|
||||
chomp;
|
||||
s/\r$//; # Shouldn't need this, but sometimes...
|
||||
s/\s*#.*$//; # Remove trailing comments
|
||||
next if /^\s*$/; # Skip blank lines
|
||||
|
||||
# Expand all already-defined macros in the line:
|
||||
while (($pre,$var,$post) = /(.*)\$\((\w+)\)(.*)/) {
|
||||
last unless (exists $Rmacros->{$var});
|
||||
$_ = $pre . $Rmacros->{$var} . $post;
|
||||
}
|
||||
|
||||
# Handle "<macro> = <path>"
|
||||
($macro, $path) = /^\s*(\w+)\s*=\s*(.*)/;
|
||||
if ($macro ne "") {
|
||||
$Rmacros->{$macro} = $path;
|
||||
push @$Rapps, $macro;
|
||||
next;
|
||||
}
|
||||
# Handle "include <path>" syntax
|
||||
($path) = /^\s*include\s+(.*)/;
|
||||
&readRelease($path, $Rmacros, $Rapps) if (-r $path);
|
||||
}
|
||||
close IN;
|
||||
}
|
||||
|
||||
sub expandRelease {
|
||||
my ($Rmacros, $Rapps) = @_;
|
||||
# $Rmacros is a reference to a hash, $Rapps a ref to an array
|
||||
|
||||
# Expand any (possibly nested) macros that were defined after use
|
||||
while (($macro, $path) = each %$Rmacros) {
|
||||
while (($pre,$var,$post) = $path =~ /(.*)\$\((\w+)\)(.*)/) {
|
||||
$path = $pre . $Rmacros->{$var} . $post;
|
||||
$Rmacros->{$macro} = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# List application types
|
||||
#
|
||||
@@ -480,29 +432,3 @@ sub GetUser {
|
||||
}
|
||||
die "No user name" unless $user;
|
||||
}
|
||||
|
||||
# Path rewriting rules for various OSs
|
||||
# These functions are duplicated in configure/convertRelease.pl
|
||||
sub UnixPath {
|
||||
my ($newpath) = @_;
|
||||
if ($^O eq 'cygwin') {
|
||||
$newpath =~ s{\\}{/}go;
|
||||
$newpath =~ s{^([a-zA-Z]):/}{/cygdrive/$1/};
|
||||
} elsif ($^O eq 'MSWin32') {
|
||||
$newpath =~ s{\\}{/}go;
|
||||
} elsif ($^O eq 'sunos') {
|
||||
$newpath =~ s{^/tmp_mnt/}{/};
|
||||
}
|
||||
return $newpath;
|
||||
}
|
||||
|
||||
sub LocalPath {
|
||||
my ($newpath) = @_;
|
||||
if ($^O eq "cygwin") {
|
||||
$newpath =~ s{^/cygdrive/([a-zA-Z])/}{$1:/};
|
||||
} elsif ($^O eq "darwin") {
|
||||
# These rules are likely to be site-specific
|
||||
$newpath =~ s{^/private/var/auto\.home/}{/home/}; # APS
|
||||
}
|
||||
return $newpath;
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@ PROD_LIBS += $(EPICS_BASE_HOST_LIBS)
|
||||
#
|
||||
# Added ws2_32 winmm user32 for the non-dll build
|
||||
#
|
||||
SYS_PROD_LIBS_WIN32 += ws2_32 advapi32 user32
|
||||
PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
|
||||
|
||||
SRCS += main.cc
|
||||
SRCS += exServer.cc
|
||||
SRCS += exPV.cc
|
||||
SRCS += exVectorPV.cc
|
||||
SRCS += exScalarPV.cc
|
||||
SRCS += exAsyncPV.cc
|
||||
SRCS += exChannel.cc
|
||||
casexample_SRCS += main.cc
|
||||
casexample_SRCS += exServer.cc
|
||||
casexample_SRCS += exPV.cc
|
||||
casexample_SRCS += exVectorPV.cc
|
||||
casexample_SRCS += exScalarPV.cc
|
||||
casexample_SRCS += exAsyncPV.cc
|
||||
casexample_SRCS += exChannel.cc
|
||||
|
||||
PROD_HOST = casexample
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "dbLock.h"
|
||||
#include "devSup.h"
|
||||
#include "drvSup.h"
|
||||
#include "menuConvert.h"
|
||||
#include "menuPini.h"
|
||||
#include "registryRecordType.h"
|
||||
#include "registryDeviceSupport.h"
|
||||
@@ -68,6 +69,7 @@ static enum {
|
||||
} iocState = iocVirgin;
|
||||
|
||||
/* define forward references*/
|
||||
static int checkDatabase(dbBase *pdbbase);
|
||||
static void initDrvSup(void);
|
||||
static void initRecSup(void);
|
||||
static void initDevSup(void);
|
||||
@@ -98,8 +100,8 @@ int iocBuild(void)
|
||||
}
|
||||
|
||||
errlogPrintf("Starting iocInit\n");
|
||||
if (!pdbbase) {
|
||||
errlogPrintf("iocBuild: Aborting, no database loaded!\n");
|
||||
if (checkDatabase(pdbbase)) {
|
||||
errlogPrintf("iocBuild: Aborting, bad database definition (DBD)!\n");
|
||||
return -1;
|
||||
}
|
||||
epicsSignalInstallSigHupIgnore();
|
||||
@@ -203,6 +205,83 @@ int iocPause(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Database sanity checks
|
||||
*
|
||||
* This is not an attempt to sanity-check the whole .dbd file, only
|
||||
* two menus normally get modified by users: menuConvert and menuScan.
|
||||
*
|
||||
* The menuConvert checks were added to flag problems with IOCs
|
||||
* converted from 3.13.x, where the SLOPE choice didn't exist.
|
||||
*
|
||||
* The menuScan checks make sure the user didn't fiddle too much
|
||||
* when creating new periodic scan choices.
|
||||
*/
|
||||
|
||||
static int checkDatabase(dbBase *pdbbase)
|
||||
{
|
||||
const dbMenu *pMenu;
|
||||
|
||||
if (!pdbbase) {
|
||||
errlogPrintf("checkDatabase: No database definitions loaded.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pMenu = dbFindMenu(pdbbase, "menuConvert");
|
||||
if (!pMenu) {
|
||||
errlogPrintf("checkDatabase: menuConvert not defined.\n");
|
||||
return -1;
|
||||
}
|
||||
if (pMenu->nChoice <= menuConvertLINEAR) {
|
||||
errlogPrintf("checkDatabase: menuConvert has too few choices.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuConvertNO_CONVERSION],
|
||||
"menuConvertNO_CONVERSION")) {
|
||||
errlogPrintf("checkDatabase: menuConvertNO_CONVERSION doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuConvertSLOPE], "menuConvertSLOPE")) {
|
||||
errlogPrintf("checkDatabase: menuConvertSLOPE doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuConvertLINEAR], "menuConvertLINEAR")) {
|
||||
errlogPrintf("checkDatabase: menuConvertLINEAR doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pMenu = dbFindMenu(pdbbase, "menuScan");
|
||||
if (!pMenu) {
|
||||
errlogPrintf("checkDatabase: menuScan not defined.\n");
|
||||
return -1;
|
||||
}
|
||||
if (pMenu->nChoice <= menuScanI_O_Intr) {
|
||||
errlogPrintf("checkDatabase: menuScan has too few choices.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuScanPassive],
|
||||
"menuScanPassive")) {
|
||||
errlogPrintf("checkDatabase: menuScanPassive doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuScanEvent],
|
||||
"menuScanEvent")) {
|
||||
errlogPrintf("checkDatabase: menuScanEvent doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuScanI_O_Intr],
|
||||
"menuScanI_O_Intr")) {
|
||||
errlogPrintf("checkDatabase: menuScanI_O_Intr doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (pMenu->nChoice <= SCAN_1ST_PERIODIC) {
|
||||
errlogPrintf("checkDatabase: menuScan has no periodic choices.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void initDrvSup(void) /* Locate all driver support entry tables */
|
||||
{
|
||||
@@ -506,6 +585,7 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
devSup *pdevSup;
|
||||
struct dsxt *pdsxt;
|
||||
int j;
|
||||
int locked = 0;
|
||||
|
||||
for (j = 0; j < pdbRecordType->no_links; j++) {
|
||||
dbFldDes *pdbFldDes =
|
||||
@@ -513,7 +593,12 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
DBLINK *plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
|
||||
|
||||
if (plink->type == CA_LINK) {
|
||||
if (!locked) {
|
||||
dbScanLock(precord);
|
||||
locked = 1;
|
||||
}
|
||||
dbCaRemoveLink(plink);
|
||||
plink->type = CONSTANT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,8 +606,16 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
(pdevSup = dbDSETtoDevSup(pdbRecordType, precord->dset)) &&
|
||||
(pdsxt = pdevSup->pdsxt) &&
|
||||
pdsxt->del_record) {
|
||||
if (!locked) {
|
||||
dbScanLock(precord);
|
||||
locked = 1;
|
||||
}
|
||||
pdsxt->del_record(precord);
|
||||
}
|
||||
if (locked) {
|
||||
precord->pact = TRUE;
|
||||
dbScanUnlock(precord);
|
||||
}
|
||||
}
|
||||
|
||||
static void exitDatabase(void *dummy)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
#*************************************************************************
|
||||
TOP=../..
|
||||
|
||||
@@ -92,12 +92,14 @@ static void reset(compressRecord *prec)
|
||||
|
||||
static void monitor(compressRecord *prec)
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
unsigned short alarm_mask = recGblResetAlarms(prec);
|
||||
unsigned short monitor_mask = alarm_mask | DBE_LOG | DBE_VALUE;
|
||||
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
monitor_mask |= (DBE_LOG|DBE_VALUE);
|
||||
if(monitor_mask) db_post_events(prec,prec->bptr,monitor_mask);
|
||||
return;
|
||||
if (alarm_mask || prec->nuse != prec->ouse) {
|
||||
db_post_events(prec, &prec->nuse, monitor_mask);
|
||||
prec->ouse = prec->nuse;
|
||||
}
|
||||
db_post_events(prec, prec->bptr, monitor_mask);
|
||||
}
|
||||
|
||||
static void put_value(compressRecord *prec,double *psource, epicsInt32 n)
|
||||
|
||||
@@ -95,6 +95,10 @@ recordtype(compress) {
|
||||
prompt("Number Used")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OUSE,DBF_ULONG) {
|
||||
prompt("Old Number Used")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(BPTR,DBF_NOACCESS) {
|
||||
prompt("Buffer Pointer")
|
||||
special(SPC_NOMOD)
|
||||
|
||||
@@ -64,7 +64,6 @@ put into a file. It converts paths from the Unix form that Perl understands to
|
||||
any necessary external representation, and also removes automounter prefixes to
|
||||
put the path into its canonical form.
|
||||
|
||||
On cygwin we convert cygdrive paths to their equivalent Windows drive specs.
|
||||
Before Leopard, the Mac OS X automounter inserted a verbose prefix, and in case
|
||||
anyone is still using SunOS it adds its own prefix as well.
|
||||
|
||||
@@ -72,9 +71,7 @@ anyone is still using SunOS it adds its own prefix as well.
|
||||
|
||||
sub LocalPath {
|
||||
my ($newpath) = @_;
|
||||
if ($^O eq 'cygwin') {
|
||||
$newpath =~ s{^/cygdrive/([a-zA-Z])/}{$1:/};
|
||||
} elsif ($^O eq 'darwin') {
|
||||
if ($^O eq 'darwin') {
|
||||
# Darwin automounter
|
||||
$newpath =~ s{^/private/var/auto\.}{/};
|
||||
} elsif ($^O eq 'sunos') {
|
||||
|
||||
@@ -19,7 +19,7 @@ use strict;
|
||||
use FindBin qw($Bin);
|
||||
use lib ("$Bin/../../lib/perl", $Bin);
|
||||
|
||||
use Cwd qw(cwd abs_path);
|
||||
use Cwd qw(cwd);
|
||||
use Getopt::Std;
|
||||
use EPICS::Path;
|
||||
use EPICS::Release;
|
||||
@@ -215,7 +215,7 @@ sub checkRelease {
|
||||
|
||||
while (my ($parent, $ppath) = each %check) {
|
||||
if (exists $macros{$parent} &&
|
||||
abs_path($macros{$parent}) ne abs_path($ppath)) {
|
||||
AbsPath($macros{$parent}) ne AbsPath($ppath)) {
|
||||
print "\n" unless ($status);
|
||||
print "Definition of $parent conflicts with $app support.\n";
|
||||
print "In this application a RELEASE file defines\n";
|
||||
|
||||
@@ -29,7 +29,7 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
|
||||
my $path = AbsPath(shift);
|
||||
|
||||
# Escape shell special characters unless on Windows, which doesn't allow them.
|
||||
$path =~ s/([!"\$&'\(\)*,:;<=>?\[\\\]^`{|}])/\\\1/g unless $^O eq 'MSWin32';
|
||||
$path =~ s/([!"\$&'\(\)*,:;<=>?\[\\\]^`{|}])/\\$1/g unless $^O eq 'MSWin32';
|
||||
|
||||
print "$path\n";
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#!/usr/bin/perl
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
#*************************************************************************
|
||||
#
|
||||
@@ -62,18 +61,13 @@ foreach $source ( @files )
|
||||
$basename=$source;
|
||||
$basename=~s'.*[/\\]'';
|
||||
$target = "$install_dir/$basename";
|
||||
$temp = "$target.$$";
|
||||
|
||||
# The Win32 filesystem seems to be 'slow',
|
||||
# i.e. $target may look like 'up to date'
|
||||
# unless you wait an hour.
|
||||
# -> skip this test on WIN32 ?
|
||||
#if (-f $target and $^O ne "MSWin32")
|
||||
if (-f $target)
|
||||
{
|
||||
if (-M $target < -M $source and
|
||||
if (-M $target < -M $source and
|
||||
-C $target < -C $source)
|
||||
{
|
||||
print "$target is up to date\n";
|
||||
next;
|
||||
}
|
||||
else
|
||||
@@ -84,8 +78,9 @@ foreach $source ( @files )
|
||||
}
|
||||
}
|
||||
|
||||
# print "Installing $source into $install_dir\n";
|
||||
copy ($source, $target) or die "Copy failed";
|
||||
# Using copy + rename fixes problems with parallel builds:
|
||||
copy ($source, $temp) or die "Copy failed: $!\n";
|
||||
rename ($temp, $target) or die "Rename failed: $!\n";
|
||||
|
||||
# chmod 0555 <read-only> DOES work on WIN32, but:
|
||||
# Another chmod 0777 to make it write- and deletable
|
||||
|
||||
@@ -3,31 +3,22 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
|
||||
|
||||
# Called from within RULES.Db in the Db directories.
|
||||
# Searches .substitutions and .template files (from the command line) for
|
||||
# "file xxx {" entries to create a DEPENDS file
|
||||
# and
|
||||
# 'include "xxx"' entries to create a DEPENDS file
|
||||
# file ["']xxx["'] {
|
||||
# and
|
||||
# include "xxx"
|
||||
# entries to include in the DEPENDS file
|
||||
|
||||
use strict;
|
||||
|
||||
$target = $ARGV[0];
|
||||
shift @ARGV;
|
||||
my $target = shift @ARGV;
|
||||
my %depends;
|
||||
|
||||
|
||||
foreach $file (@ARGV) {
|
||||
open(IN, "<$file") or die "Cannot open $file: $!";
|
||||
@infile = <IN>;
|
||||
close IN or die "Cannot close $file: $!";
|
||||
|
||||
@depends = grep { s/^\s*file\s*(.*)\s*\{.*$/\1/ } @infile;
|
||||
chomp @depends;
|
||||
|
||||
if (@depends) {
|
||||
print "$target: @depends\n";
|
||||
}
|
||||
|
||||
@depends2 = grep { s/^\s*include\s*\"\s*(.*)\s*\".*$/\1/ } @infile;
|
||||
chomp @depends2;
|
||||
|
||||
if (@depends2) {
|
||||
print "$target: @depends2\n";
|
||||
}
|
||||
while (my $line = <>) {
|
||||
$depends{$2}++ if $line =~ m/^\s*file\s*(["']?)(.*)\1/;
|
||||
$depends{$1}++ if $line =~ m/^\s*include\s+"(.*)"/;
|
||||
}
|
||||
|
||||
if (%depends) {
|
||||
my @depends = keys %depends;
|
||||
print "$target: @depends\n";
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2011 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.
|
||||
\*************************************************************************/
|
||||
/* iocLogServer.c */
|
||||
/* base/src/util $Revision-Id$ */
|
||||
/* $Revision-Id$ */
|
||||
|
||||
/*
|
||||
* archive logMsg() from several IOC's to a common rotating file
|
||||
* archive logMsg() from several IOC's to a common rotating file
|
||||
*
|
||||
*
|
||||
* Author: Jeffrey O. Hill
|
||||
@@ -903,40 +902,35 @@ static void serviceSighupRequest(void *pParam)
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's changed, open the new file.
|
||||
* Try (re)opening the file.
|
||||
*/
|
||||
if (strcmp(ioc_log_file_name, pserver->outfile) == 0) {
|
||||
status = openLogFile(pserver);
|
||||
if(status<0){
|
||||
fprintf(stderr,
|
||||
"iocLogServer: log file name unchanged; not re-opened\n");
|
||||
}
|
||||
else {
|
||||
"File access problems to `%s' because `%s'\n",
|
||||
ioc_log_file_name,
|
||||
strerror(errno));
|
||||
/* Revert to old filename */
|
||||
strcpy(ioc_log_file_name, pserver->outfile);
|
||||
status = openLogFile(pserver);
|
||||
if(status<0){
|
||||
fprintf(stderr,
|
||||
"File access problems to `%s' because `%s'\n",
|
||||
"File access problems to `%s' because `%s'\n",
|
||||
ioc_log_file_name,
|
||||
strerror(errno));
|
||||
strcpy(ioc_log_file_name, pserver->outfile);
|
||||
status = openLogFile(pserver);
|
||||
if(status<0){
|
||||
fprintf(stderr,
|
||||
"File access problems to `%s' because `%s'\n",
|
||||
ioc_log_file_name,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"iocLogServer: re-opened old log file %s\n",
|
||||
ioc_log_file_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"iocLogServer: opened new log file %s\n",
|
||||
"iocLogServer: re-opened old log file %s\n",
|
||||
ioc_log_file_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"iocLogServer: opened new log file %s\n",
|
||||
ioc_log_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#!/bin/sh
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
#*************************************************************************
|
||||
#
|
||||
@@ -37,9 +36,9 @@ case $sysname in
|
||||
Darwin )
|
||||
os=darwin
|
||||
cpu=`uname -m`
|
||||
case "$cpu" in
|
||||
case $cpu in
|
||||
"Power Macintosh") cpu=ppc ;;
|
||||
"i386") cpu=x86 ;;
|
||||
i386 | x86_64 ) cpu=x86 ;;
|
||||
esac
|
||||
echo ${os}-${cpu}${suffix}
|
||||
;;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
|
||||
if $running_under_some_shell; # EpicsHostArch.pl
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 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.
|
||||
@@ -34,6 +34,7 @@ sub GetEpicsHostArch { # no args
|
||||
my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname();
|
||||
if ($cpu =~ m/Power Macintosh/) { return "darwin-ppc"; }
|
||||
elsif ($cpu =~ m/i386/) { return "darwin-x86"; }
|
||||
elsif ($cpu =~ m/x86_64/) { return "darwin-x86"; }
|
||||
else { return "unsupported"; }
|
||||
} else { return "unsupported"; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user