Compare commits
59 Commits
R3.14.9-pr
...
R3.14.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
919850d693 | ||
|
|
894cab79e4 | ||
|
|
b38dd45b03 | ||
|
|
d468d7f462 | ||
|
|
8dfea0ce50 | ||
|
|
cda58de74a | ||
|
|
2d031c46a2 | ||
|
|
5e4b2d03ad | ||
|
|
db067c9780 | ||
|
|
3ec09adf20 | ||
|
|
57e9e59714 | ||
|
|
cde78f0b70 | ||
|
|
6ed4f091b2 | ||
|
|
bb625c7f25 | ||
|
|
47f5203faa | ||
|
|
287743f140 | ||
|
|
a841a79194 | ||
|
|
9e2c64ecfd | ||
|
|
6fb7d5255b | ||
|
|
00fc1ce769 | ||
|
|
852afdc4d8 | ||
|
|
ae06349563 | ||
|
|
a710bff122 | ||
|
|
fe2b0e599d | ||
|
|
255751f420 | ||
|
|
7787f5906d | ||
|
|
de34f5de03 | ||
|
|
40bb69f5fd | ||
|
|
6ce83fc9e4 | ||
|
|
e0b4715c98 | ||
|
|
e989af9b01 | ||
|
|
3c1b10dfce | ||
|
|
27342322ec | ||
|
|
3d3ad47e47 | ||
|
|
f2154fec35 | ||
|
|
6bed83c70e | ||
|
|
4f2cb790e5 | ||
|
|
15f3358e39 | ||
|
|
285f1e03ba | ||
|
|
03e9ce2855 | ||
|
|
c5563644db | ||
|
|
75aa6bbf97 | ||
|
|
8b8b61b797 | ||
|
|
8540fdd813 | ||
|
|
23c1596d22 | ||
|
|
9e292ca085 | ||
|
|
410eca1633 | ||
|
|
44d742e147 | ||
|
|
abe127c6f9 | ||
|
|
beacc52519 | ||
|
|
5a9e8d156e | ||
|
|
239cd857a8 | ||
|
|
dea42bdf66 | ||
|
|
196f107432 | ||
|
|
2a7c2e9d26 | ||
|
|
556724f050 | ||
|
|
0f0ff1eec0 | ||
|
|
b937142ff3 | ||
|
|
a6527232cf |
20
config/CONFIG.Host.osf-alpha-gnu
Normal file
20
config/CONFIG.Host.osf-alpha-gnu
Normal file
@@ -0,0 +1,20 @@
|
||||
#*************************************************************************
|
||||
# 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 Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
# $Id$
|
||||
|
||||
# osf-alpha is the new name for alpha
|
||||
-include $(EPICS_BASE)/config/CONFIG.Host.alpha
|
||||
|
||||
#==========================
|
||||
# These are overrides of ANSI and CPLUSPLUS values in CONFIG_SITE
|
||||
ANSI=GCC
|
||||
CPLUSPLUS=G++
|
||||
#==========================
|
||||
|
||||
@@ -29,8 +29,8 @@ EPICS_MODIFICATION = 9
|
||||
EPICS_PATCH_LEVEL = 0
|
||||
|
||||
# This will be -CVS or empty at an official release point
|
||||
EPICS_CVS_SNAPSHOT=-pre2
|
||||
#EPICS_CVS_SNAPSHOT=
|
||||
#EPICS_CVS_SNAPSHOT=-CVS
|
||||
EPICS_CVS_SNAPSHOT=
|
||||
|
||||
# No changes should be needed below here
|
||||
|
||||
|
||||
@@ -312,8 +312,7 @@ PREPROCESS.cpp = $(CPP) $(CPPFLAGS) $(INCLUDES) $< > $@
|
||||
# Depends command
|
||||
|
||||
HDEPENDS_FLAGS =
|
||||
# Use only dependancies from current top tree
|
||||
HDEPENDS_INCLUDES = $(filter .%,$(subst -I,,$(INCLUDES)))
|
||||
HDEPENDS_INCLUDES = $(subst -I,,$(INCLUDES))
|
||||
HDEPENDSFLAGS = -m $*$(DEP) $(HDEPENDS_INCLUDES) $@ $<
|
||||
HDEPENDS_CMD_YES = -$(MKMF) $(HDEPENDS_FLAGS) $(HDEPENDSFLAGS)
|
||||
HDEPENDS_CMD_NO = echo ""
|
||||
|
||||
@@ -78,7 +78,7 @@ COMMON_DBDINC += $(addprefix $(COMMON_DIR),$(HINC))
|
||||
DBDDEPENDS_FILES += $(addsuffix $(DEP),$(COMMON_DBDS) \
|
||||
$(COMMON_DBDINC) $(COMMON_DBS))
|
||||
|
||||
DBDDEPENDS_FLAGS = $(filter .%,$(subst -I,,$(filter-out -S%,$(DBDFLAGS))))
|
||||
DBDDEPENDS_FLAGS = $(subst -I,,$(filter-out -S%,$(DBDFLAGS)))
|
||||
DBDDEPENDS_CMD = -$(MKMF) -m $@$(DEP) $(DBDDEPENDS_FLAGS) $@ $<
|
||||
|
||||
MAKEDBDEPENDS = $(PERL) $(TOOLS)/makeDbDepends.pl
|
||||
|
||||
40
configure/os/CONFIG.Common.osf-alpha
Normal file
40
configure/os/CONFIG.Common.osf-alpha
Normal file
@@ -0,0 +1,40 @@
|
||||
# CONFIG.Common.osf-alpha
|
||||
#
|
||||
# $Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for osf-alpha target archs
|
||||
# Sites may override these definitions in CONFIG_SITE.Common.osf-alpha
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include definitions common to all Unix targets
|
||||
include $(CONFIG)/os/CONFIG.Common.UnixCommon
|
||||
|
||||
OS_CLASS = osf
|
||||
ARCH_CLASS = alpha
|
||||
|
||||
CODE_CPPFLAGS =
|
||||
|
||||
POSIX_CPPFLAGS += -pthread -ieee
|
||||
POSIX_LDFLAGS += -pthread -ieee
|
||||
|
||||
OP_SYS_CPPFLAGS += -D_OSF_SOURCE
|
||||
OP_SYS_LDLIBS += -lrt
|
||||
# Unknown reason why USR_SYS_LIBS += m is needed
|
||||
USR_SYS_LIBS += m
|
||||
|
||||
space:=$(empty) $(empty)
|
||||
colon := :
|
||||
|
||||
# Set runtime path for shared libraries
|
||||
SHRLIBDIR_LDFLAGS += $(SHRLIB_DEPLIB_DIRS:%=-rpath %)
|
||||
|
||||
# Set runtime path for products
|
||||
PRODDIR_LDFLAGS += $(PROD_DEPLIB_DIRS:%=-rpath %)
|
||||
|
||||
ifdef CROSS
|
||||
GNU_TARGET=alpha-osf
|
||||
CMPLR_SUFFIX=
|
||||
CMPLR_PREFIX=$(addsuffix -,$(GNU_TARGET))
|
||||
endif
|
||||
|
||||
38
configure/os/CONFIG.Common.osf-alpha-gnu
Normal file
38
configure/os/CONFIG.Common.osf-alpha-gnu
Normal file
@@ -0,0 +1,38 @@
|
||||
# CONFIG.Common.osf-alpha-gnu
|
||||
#
|
||||
# $Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for osf-alpha target archs
|
||||
# Sites may override these definitions in CONFIG_SITE.Common.osf-alpha-gnu
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include definitions common to all Unix targets
|
||||
include $(CONFIG)/os/CONFIG.Common.UnixCommon
|
||||
|
||||
OS_CLASS = osf
|
||||
ARCH_CLASS = alpha
|
||||
|
||||
CODE_CPPFLAGS =
|
||||
|
||||
POSIX_CPPFLAGS += -D_REENTRANT
|
||||
POSIX_LDLIBS += -lpthread -lexc
|
||||
|
||||
OP_SYS_CPPFLAGS += -D_OSF_SOURCE
|
||||
OP_SYS_LDLIBS += -lrt
|
||||
|
||||
space:=$(empty) $(empty)
|
||||
colon := :
|
||||
|
||||
# Set runtime path for shared libraries
|
||||
SHRLIBDIR_LDFLAGS += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
|
||||
|
||||
# Set runtime path for products
|
||||
PRODDIR_LDFLAGS += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
|
||||
|
||||
ifdef CROSS
|
||||
GNU_TARGET=alpha-osf
|
||||
CMPLR_SUFFIX=
|
||||
CMPLR_PREFIX=$(addsuffix -,$(GNU_TARGET))
|
||||
endif
|
||||
|
||||
@@ -11,11 +11,12 @@ include $(CONFIG)/os/CONFIG.Common.vxWorks-ppc604_long
|
||||
|
||||
defval = $(if $(strip $(1),),$(1),$(2))
|
||||
|
||||
# Tell compiler to include altivec support
|
||||
ALTIVEC_CFLAG_5 = -fvec
|
||||
|
||||
# From 6.1 the altivec compiler option changed
|
||||
# Tell compiler to include altivec support; not available in 5.4
|
||||
ALTIVEC_CFLAG_5.4 = THIS_VERSION_OF_VXWORKS DOES_NOT_SUPPORT_ALTIVEC
|
||||
ALTIVEC_CFLAG_5.5 = -fvec
|
||||
ALTIVEC_CFLAG_6.0 = -fvec
|
||||
ALTIVEC_CFLAG_6 = $(call defval,$(ALTIVEC_CFLAG_$(VXWORKS_VERSION)),-maltivec)
|
||||
|
||||
ARCH_DEP_CFLAGS += $(ALTIVEC_CFLAG_$(VXWORKS_MAJOR_VERSION))
|
||||
# From 6.1 onwards the compiler option changed
|
||||
ALTIVEC_CFLAG = -maltivec
|
||||
|
||||
ARCH_DEP_CFLAGS += $(call defval,$(ALTIVEC_CFLAG_$(VXWORKS_VERSION)),$(ALTIVEC_CFLAG))
|
||||
|
||||
12
configure/os/CONFIG.osf-alpha-gnu.Common
Normal file
12
configure/os/CONFIG.osf-alpha-gnu.Common
Normal file
@@ -0,0 +1,12 @@
|
||||
# CONFIG.osf-alpha-gnu.Common
|
||||
#
|
||||
# $Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for osf-alpha host archs
|
||||
# Sites may override these definitions in CONFIG_SITE.osf-alpha-gnu.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to unix hosts
|
||||
include $(CONFIG)/os/CONFIG.UnixCommon.Common
|
||||
|
||||
45
configure/os/CONFIG.osf-alpha-gnu.osf-alpha-gnu
Normal file
45
configure/os/CONFIG.osf-alpha-gnu.osf-alpha-gnu
Normal file
@@ -0,0 +1,45 @@
|
||||
# CONFIG.osf-alpha-gnu.osf-alpha-gnu
|
||||
#
|
||||
# $Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for osf-alpha host archs
|
||||
# Sites may override these definitions in CONFIG_SITE.osf-alpha-gnu.osf-alpha-gnu
|
||||
#-------------------------------------------------------
|
||||
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CPP = $(CC) -E
|
||||
RANLIB =
|
||||
AR = ar -r
|
||||
LD = -r
|
||||
|
||||
# Configure OS vendor C compiler
|
||||
CONFORM_CFLAGS_ANSI =
|
||||
CONFORM_CFLAGS_STRICT =
|
||||
CONFORM_CFLAGS_TRAD =
|
||||
CODE_CFLAGS =
|
||||
WARN_CFLAGS_YES =
|
||||
WARN_CFLAGS_NO = -w
|
||||
OPT_CFLAGS_YES = -O
|
||||
OPT_CFLAGS_NO = -g
|
||||
|
||||
# Configure OS vendor C++ compiler
|
||||
CONFORM_CXXFLAGS_NORMAL =
|
||||
CONFORM_CXXFLAGS_STRICT =
|
||||
PROF_CXXFLAGS_YES = +p
|
||||
PROF_CXXFLAGS_NO =
|
||||
CODE_CXXFLAGS =
|
||||
WARN_CXXFLAGS_YES =
|
||||
WARN_CXXFLAGS_NO =
|
||||
OPT_CXXFLAGS_YES = -O
|
||||
OPT_CXXFLAGS_NO = -g
|
||||
|
||||
STATIC_LDFLAGS_YES= -Bstatic
|
||||
STATIC_LDFLAGS_NO=
|
||||
STATIC_LDLIBS_YES= -Bdynamic
|
||||
STATIC_LDLIBS_NO=
|
||||
|
||||
SHRLIB_LDFLAGS = -shared
|
||||
LOADABLE_SHRLIB_LDFLAGS = $(SHRLIB_LDFLAGS)
|
||||
|
||||
12
configure/os/CONFIG.osf-alpha.Common
Normal file
12
configure/os/CONFIG.osf-alpha.Common
Normal file
@@ -0,0 +1,12 @@
|
||||
# CONFIG.osf-alpha.Common
|
||||
#
|
||||
# $Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for osf-alpha host archs
|
||||
# Sites may override these definitions in CONFIG_SITE.osf-alpha.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to unix hosts
|
||||
include $(CONFIG)/os/CONFIG.UnixCommon.Common
|
||||
|
||||
49
configure/os/CONFIG.osf-alpha.osf-alpha
Normal file
49
configure/os/CONFIG.osf-alpha.osf-alpha
Normal file
@@ -0,0 +1,49 @@
|
||||
# CONFIG.osf-alpha.osf-alpha
|
||||
#
|
||||
# $Id$
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for osf-alpha host archs
|
||||
# Sites may override these definitions in CONFIG_SITE.osf-alpha.osf-alpha
|
||||
#-------------------------------------------------------
|
||||
|
||||
CC = cc
|
||||
CCC = cxx
|
||||
CPP = $(CC) -E
|
||||
RANLIB =
|
||||
AR = ar -r
|
||||
LD = -r
|
||||
|
||||
# Configure OS vendor C compiler
|
||||
CONFORM_CFLAGS_ANSI = -std
|
||||
CONFORM_CFLAGS_STRICT = -std1
|
||||
CONFORM_CFLAGS_TRAD = -std0
|
||||
CODE_CFLAGS =
|
||||
WARN_CFLAGS_YES =
|
||||
WARN_CFLAGS_NO = -w
|
||||
OPT_CFLAGS_YES = -O
|
||||
OPT_CFLAGS_NO = -g
|
||||
|
||||
# Configure OS vendor C++ compiler
|
||||
CONFORM_CXXFLAGS_NORMAL =
|
||||
CONFORM_CXXFLAGS_STRICT = -std gnu
|
||||
PROF_CXXFLAGS_YES = +p
|
||||
PROF_CXXFLAGS_NO =
|
||||
CODE_CXXFLAGS =
|
||||
WARN_CXXFLAGS_YES =
|
||||
WARN_CXXFLAGS_NO =
|
||||
OPT_CXXFLAGS_YES = -O
|
||||
OPT_CXXFLAGS_NO = -g
|
||||
|
||||
STATIC_LDFLAGS_YES= -Bstatic
|
||||
STATIC_LDFLAGS_NO=
|
||||
STATIC_LDLIBS_YES= -Bdynamic
|
||||
STATIC_LDLIBS_NO=
|
||||
|
||||
SHRLIB_LDFLAGS = -shared
|
||||
LOADABLE_SHRLIB_LDFLAGS = $(SHRLIB_LDFLAGS)
|
||||
|
||||
############# ???????????
|
||||
#####ACC_SFLAGS_YES= -non_shared
|
||||
#####ACC_SFLAGS_NO= -call_shared
|
||||
|
||||
@@ -25,13 +25,9 @@
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
use Getopt::Std;
|
||||
use Text::Wrap;
|
||||
|
||||
$Text::Wrap::columns = 76;
|
||||
|
||||
my $version = 'mkmf.pl,v 1.5 2002/03/25 21:33:24 jba Exp $ ';
|
||||
my $endline = $/;
|
||||
my %delim_match = ( q/'/ => q/'/, q/"/ => q/"/);
|
||||
my %output;
|
||||
my @includes;
|
||||
|
||||
@@ -75,7 +71,7 @@ print "\n ALL DONE \n\n" if $debug;
|
||||
sub printList{
|
||||
my $depFile = shift;
|
||||
my $objFile = shift;
|
||||
my $line;
|
||||
my $file;
|
||||
|
||||
unlink($depFile) or die "Can't delete $depFile: $!\n" if -f $depFile;
|
||||
|
||||
@@ -85,20 +81,10 @@ sub printList{
|
||||
|
||||
print "# DO NOT EDIT: This file created by $version\n\n";
|
||||
|
||||
local $: = " \t\n"; # remove hyphen from word boundary defaults
|
||||
|
||||
$line = "$objFile : @includes";
|
||||
$fmtline = wrap ("", " ", $line);
|
||||
$fmtline =~ s/\n/ \\\n/mg;
|
||||
print $fmtline;
|
||||
|
||||
print "\n\n";
|
||||
print "#Depend files must be targets to avoid 'No rule to make target ...' errors\n";
|
||||
|
||||
#$line = "@includes";
|
||||
foreach $file (@includes) {
|
||||
print "$file :\n";
|
||||
print "$objFile : $file\n";
|
||||
}
|
||||
print "\n\n";
|
||||
|
||||
select($old_handle) ; # in this case, STDOUT
|
||||
}
|
||||
@@ -139,10 +125,10 @@ sub findNextIncName {
|
||||
my $dir;
|
||||
|
||||
local $/ = $endline;
|
||||
return 0 if !($line =~ m/^[ ]*\#?[ ]*include/);
|
||||
return 0 if !($line =~ /^[\#?\s]*include\s*(['""'<])([\w\.\/]*)$delim_match{\1}/ix);
|
||||
return 0 if !$2;
|
||||
$incname = $2;
|
||||
return 0 if not $line =~ /^\s*#?\s*include\s*(<.*?>|".*?")/;
|
||||
$incname = substr $1, 1, length($1)-2;
|
||||
print "DEBUG: $incname\n" if $debug;
|
||||
|
||||
|
||||
return $incname if -f $incname;
|
||||
return 0 if ( $incname =~ /^\// || $incname =~ /^\\/ );
|
||||
@@ -155,4 +141,3 @@ sub findNextIncName {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,28 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center">EPICS Base R3.14.8: Known Problems</h1>
|
||||
<h1 style="text-align: center">EPICS Base R3.14.9: Known Problems</h1>
|
||||
|
||||
<ul>
|
||||
<li>The new architectures <tt>linux-x86_64</tt> and <tt>solaris-sparc64</tt>
|
||||
are known to not work yet; do not attempt do use them, although if you need
|
||||
either one an offer to help find the problems would be welcomed.</li>
|
||||
<li>It is not possible to build a statically linked version of base on
|
||||
HP-UX. If you need this and manage to work out how, please tell us!</li>
|
||||
<li>We have had problems with the linux-x86 target running on the Linux
|
||||
2.6.10 kernel, but these disappeared with later kernel versions.</li>
|
||||
<li>It is not possible to build this version of base on HP-UX due to C++
|
||||
issues which appear to be bugs in the HP-UX compiler.</li>
|
||||
|
||||
<li>When shutting down an IOC on a recent version of GNU/Linux (one that
|
||||
includes the NPTL threading library) various messages may appear, such as:
|
||||
|
||||
<blockquote>
|
||||
<pre>FATAL: exception not rethrown</pre></blockquote>
|
||||
|
||||
<blockquote>
|
||||
<pre>epicsThread: Unknown C++ exception in thread "CAC-UDP" at ...</pre>
|
||||
<pre>terminate called after throwing an instance of ''</pre>
|
||||
</blockquote>
|
||||
|
||||
These errors are caused by the implementation of the pthread_cancel()
|
||||
mechanism in NPTL, which uses the C++ exception mechanism without providing
|
||||
any means to distinguish the cancel exception to regular C++ exception
|
||||
handlers. It is possible that they might also occur when a CA client
|
||||
application exits (or closes its connection to the CA library).</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -152,6 +152,8 @@ Software requirements</h3>
|
||||
<blockquote><b>GNU make</b>
|
||||
<br>You must use GNU make, gnumake, for any EPICS builds. Set your
|
||||
path so that a gnumake version 3.78.1 or later is available.
|
||||
<p><b>gcc</b>
|
||||
<br>You must have gcc version 3.4.2 or later.
|
||||
<p><b>Perl</b>
|
||||
<br>You must have perl version 5.0 or later installed. The configure files
|
||||
do not specify the perl full pathname. You need the perl executable
|
||||
|
||||
78
documentation/README.tru64unix
Normal file
78
documentation/README.tru64unix
Normal file
@@ -0,0 +1,78 @@
|
||||
Compiling EPICS and Building IOC Applications on Tru64Unix/Alpha
|
||||
(former Digital-Unix, and even former OSF1)
|
||||
for architectures "osf-alpha" and "osf-alpha-gnu"
|
||||
|
||||
======================================================================
|
||||
|
||||
Tools needed
|
||||
------------
|
||||
|
||||
For C/C++ Compiler, you need one of these compiler set.
|
||||
|
||||
- DEC/Compaq/HP's ANSI C/C++ compilers for "osf-alpha"
|
||||
I used
|
||||
cc -V
|
||||
Compaq C V6.5-303 (dtk) on Compaq Tru64 UNIX V5.1B (Rev. 2650)
|
||||
Compiler Driver V6.5-302 (dtk) cc Driver
|
||||
cxx -V
|
||||
Compaq C++ V6.5-042 for Compaq Tru64 UNIX V5.1B (Rev. 2650)
|
||||
Compiler Driver V6.5-042 (cxx) cxx Driver
|
||||
|
||||
- GNU gcc/g++ compiler for "osf-alpha-gnu"
|
||||
I used
|
||||
gcc --version
|
||||
gcc (GCC) 3.4.3
|
||||
|
||||
Environment
|
||||
-----------
|
||||
|
||||
Before compiling, please set the environment variable EPICS_HOST_ARCH
|
||||
dependent on your compiler.
|
||||
|
||||
for cc/cxx
|
||||
setenv EPICS_HOST_ARCH osf-alpha
|
||||
(setenv EPICS_HOST_ARCH `startup/EpicsHostArch.pl`)
|
||||
export EPICS_HOST_ARCH=osf-alpha
|
||||
|
||||
for gcc/g++
|
||||
setenv EPICS_HOST_ARCH osf-alpha-gnu
|
||||
(setenv EPICS_HOST_ARCH `startup/EpicsHostArch.pl gnu`)
|
||||
export EPICS_HOST_ARCH=osf-alpha-gnu
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Should be quite straightforward. Edit (if necessary) the CONFIG_SITE
|
||||
files and "make". (Be sure that GNU make is in your path or call it
|
||||
explicitly as the standard make on Tru64Unix is _not_ GNU.)
|
||||
|
||||
For example (with csh):
|
||||
setenv EPICS_HOST_ARCH `startup/EpicsHostArch.pl`
|
||||
make |& tee ../make-base-osf.log
|
||||
make runtests | & tee ../test-base-osf.log
|
||||
setenv EPICS_HOST_ARCH `startup/EpicsHostArch.pl gnu`
|
||||
make |& tee ../make-base-osfgnu.log
|
||||
|
||||
Minor errors are detected in and timer. They should be investigated
|
||||
later.
|
||||
|
||||
Some internals
|
||||
-----------------------
|
||||
|
||||
__alpha is used to distinguish this architecture from others.
|
||||
__DECCXX is used to distinguish DEC/Compaq/HP C++ compiler from GNU's.
|
||||
There are several ways to specify compiler options for pthread.
|
||||
Please consult the pthread(3) manual page.
|
||||
src/libCom/osi/os/osf is used for osi definitions,
|
||||
src/libCom/osi/os/alpha is not used.
|
||||
About 230 warning messages with cc/cxx, and 4 with gcc. Sometimes
|
||||
errors from cxx are intuitive.
|
||||
I just started to use IOC application for a gateway purpose. There
|
||||
can be architecture-dependent problems, that I didn't find yet.
|
||||
|
||||
Only several lines in configure and src files were modified from
|
||||
base-3.14.4/5/6/7/8/8.2/9pre. Thanks the core team for keeping
|
||||
the alpha-osf dependent part in the distribution.
|
||||
|
||||
<URL:http://www-linac.kek.jp/jk/osf/>
|
||||
Kazuro Furukawa <kazuro.furukawa at kek.jp>
|
||||
@@ -13,9 +13,20 @@
|
||||
|
||||
<!-- Insert new items below here ... -->
|
||||
|
||||
<h4>Cygwin Builds</h4>
|
||||
|
||||
<p>The cygwin make version 3.81-1 does not handle MS-DOS path names and thus
|
||||
does not work for EPICS builds with RELEASE file definitions. From the
|
||||
discussion on the cygwin mailing list it looks like this will be fixed in make
|
||||
version 3.82. In the meantime make version 3.80 or a fixed make can be
|
||||
downloaded from
|
||||
<a href="https://projects.coin-or.org/BuildTools/wiki/current-issues">this
|
||||
website</a>.
|
||||
|
||||
<h4>New Architectures</h4>
|
||||
|
||||
<p>The following target architectures have been added to this release:</p>
|
||||
<p>The following target architectures have been added to this release, although
|
||||
the core developers lack the ability to test all of them:</p>
|
||||
|
||||
<ul>
|
||||
<li>darwin-ppcx86</li>
|
||||
@@ -24,6 +35,8 @@
|
||||
<li>freebsd-x86_64</li>
|
||||
<li>interix-x86</li>
|
||||
<li>linux-arm</li>
|
||||
<li>osf-alpha</li>
|
||||
<li>osf-alpha-gnu</li>
|
||||
<li>vxWorks-mpc8540</li>
|
||||
<li>vxWorks-ppc604_altivec</li>
|
||||
</ul>
|
||||
@@ -226,8 +239,6 @@ before reading values from NVRAM and
|
||||
epicsRtemsInitPostSetBootConfigFromNVRAM just afterwards. See
|
||||
epicsRtemsInitHooks.h for prototypes and global variables.</p>
|
||||
|
||||
<h4>libCom</h4>
|
||||
|
||||
<h4>e_flex</h4>
|
||||
|
||||
<p><tt>e_flex</tt> has been modified to accept DOS line endings as well as Unix
|
||||
|
||||
@@ -14,10 +14,10 @@ TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
DIRS += libCom
|
||||
DIRS += ca
|
||||
DIRS += RTEMS
|
||||
DIRS += libCom/test
|
||||
DIRS += toolsComm
|
||||
DIRS += ca
|
||||
DIRS += dbStatic
|
||||
DIRS += registry
|
||||
DIRS += bpt
|
||||
|
||||
@@ -525,9 +525,9 @@ Init (rtems_task_argument ignored)
|
||||
else {
|
||||
char posixTzBuf[40];
|
||||
char *p = posixTzBuf;
|
||||
p += sprintf(p, "%cST %d:%d", tz[0], minWest/60, minWest%60);
|
||||
p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60);
|
||||
if (toDst != fromDst)
|
||||
p += sprintf(p, " %cDT", tz[0]);
|
||||
p += sprintf(p, "%cDT", tz[0]);
|
||||
epicsEnvSet("TZ", posixTzBuf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,13 +40,12 @@ CASG::~CASG ()
|
||||
}
|
||||
|
||||
void CASG::destructor (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
|
||||
if ( this->verify ( guard ) ) {
|
||||
this->reset ( cbGuard, guard );
|
||||
this->reset ( guard );
|
||||
this->client.uninstallCASG ( guard, *this );
|
||||
this->magic = 0;
|
||||
}
|
||||
@@ -65,7 +64,7 @@ bool CASG::verify ( epicsGuard < epicsMutex > & ) const
|
||||
* CASG::block ()
|
||||
*/
|
||||
int CASG::block (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > * pcbGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
double timeout )
|
||||
{
|
||||
@@ -110,9 +109,15 @@ int CASG::block (
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
if ( pcbGuard ) {
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > uncbGuard ( *pcbGuard );
|
||||
this->sem.wait ( remaining );
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
epicsGuardRelease < epicsMutex > uncbGuard ( cbGuard );
|
||||
this->sem.wait ( remaining );
|
||||
}
|
||||
|
||||
@@ -124,18 +129,17 @@ int CASG::block (
|
||||
delay = cur_time - beg_time;
|
||||
}
|
||||
|
||||
this->reset ( cbGuard, guard );
|
||||
this->reset ( guard );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void CASG::reset (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
this->destroyCompletedIO ( guard );
|
||||
this->destroyPendingIO ( cbGuard, guard );
|
||||
this->destroyPendingIO ( guard );
|
||||
}
|
||||
|
||||
// lock must be applied
|
||||
@@ -150,13 +154,11 @@ void CASG::destroyCompletedIO (
|
||||
}
|
||||
|
||||
void CASG::destroyPendingIO (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
syncGroupNotify * pNotify;
|
||||
while ( ( pNotify = this->ioPendingList.first () ) ) {
|
||||
pNotify->cancel ( cbGuard, guard );
|
||||
while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
|
||||
pNotify->cancel ( guard );
|
||||
// cancel must release the guard while
|
||||
// canceling put callbacks so we
|
||||
// must double check list membership
|
||||
@@ -201,7 +203,6 @@ void CASG::show (
|
||||
}
|
||||
|
||||
bool CASG::ioComplete (
|
||||
epicsGuard < epicsMutex > & /* cbGuard */,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
|
||||
@@ -2303,15 +2303,30 @@ callbacks will be called preemptively from more than one thread.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>SELECT</code></dt>
|
||||
<dd>Specifies if preemptive callback is allowed. If it is allowed your
|
||||
callbacks might be called when the thread that calls this routine is
|
||||
not executing in the CA client library. Programmers who are unfamiliar
|
||||
with mutual exclusion locking in a multi-threaded environment should
|
||||
specify <code>ca_disable_preemptive_callback</code>. If
|
||||
ca_enable_preemptive_callback is specified then CA client background
|
||||
activities, such as connection management, will proceed even if the
|
||||
thread that calls this routine is not executing in the CA client
|
||||
library.</dd>
|
||||
<dd>This argument specifies if preemptive invocation of callback
|
||||
functions is allowed. If so your callback functions might be called
|
||||
when the thread that calls this routine is not executing in the CA
|
||||
client library. There are two implications to consider. </dd>
|
||||
<dd><p>First, if preemptive callback mode is enabled the developer must
|
||||
provide mutual exclusion protection for his data structures. In this
|
||||
mode it's possible for two threads to touch the application's data
|
||||
structures at once: this might be the initializing thread (the thread
|
||||
that called ca_context_create) and also a private thread created by the
|
||||
CA client library for the purpose of receiving network messages and
|
||||
calling callbacks. It might be prudent for developers who are
|
||||
unfamiliar with mutual exclusion locking in a multi-threaded
|
||||
environment to specify <code>ca_disable_preemptive_callback</code>. </p>
|
||||
<p>Second, if preemptive callback mode is enabled the application is no
|
||||
longer burdened with the necessity of periodically polling the CA
|
||||
client library in order that it might take care of its background
|
||||
activities. If <code>ca_enable_preemptive_callback</code> is specified
|
||||
then CA client background activities, such as connection management,
|
||||
will proceed even if the thread that calls this routine is not
|
||||
executing in the CA client library. Furthermore, in preemptive callback
|
||||
mode callbacks might be called with less latency because the library is
|
||||
not required to wait until the initializing thread (the thread that
|
||||
called ca_context_create) is executing within the CA client library.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Returns</h4>
|
||||
|
||||
@@ -364,16 +364,15 @@ int epicsShareAPI ca_create_channel (
|
||||
int epicsShareAPI ca_clear_channel ( chid pChan )
|
||||
{
|
||||
ca_client_context & cac = pChan->getClientCtx ();
|
||||
epicsGuard < epicsMutex > * pCBGuard = cac.pCallbackGuard.get();
|
||||
if ( pCBGuard ) {
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
cac.destroyChannel ( *pCBGuard, guard, *pChan );
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
try {
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
}
|
||||
else {
|
||||
epicsGuard < epicsMutex > cbGuard ( cac.cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
cac.destroyChannel ( cbGuard, guard, *pChan );
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
pChan->destructor ( guard );
|
||||
cac.oldChannelNotifyFreeList.release ( pChan );
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ epicsShareDef epicsThreadPrivateId caClientCallbackThreadId;
|
||||
|
||||
static epicsThreadOnceId cacOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
const unsigned ca_client_context :: flushBlockThreshold = 0x58000;
|
||||
|
||||
extern "C" void cacExitHandler ( void *)
|
||||
{
|
||||
epicsThreadPrivateDelete ( caClientCallbackThreadId );
|
||||
@@ -65,6 +67,7 @@ cacService * ca_client_context::pDefaultService = 0;
|
||||
epicsMutex * ca_client_context::pDefaultServiceInstallMutex;
|
||||
|
||||
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
createdByThread ( epicsThreadGetIdSelf () ),
|
||||
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
|
||||
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
|
||||
pndRecvCnt ( 0u ), ioSeqNo ( 0u ), callbackThreadsPending ( 0u ),
|
||||
@@ -189,22 +192,6 @@ ca_client_context::~ca_client_context ()
|
||||
}
|
||||
}
|
||||
|
||||
void ca_client_context::destroyChannel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
oldChannelNotify & chan )
|
||||
{
|
||||
try {
|
||||
chan.eliminateExcessiveSendBacklog (
|
||||
&cbGuard, guard );
|
||||
}
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
chan.destructor ( cbGuard, guard );
|
||||
this->oldChannelNotifyFreeList.release ( & chan );
|
||||
}
|
||||
|
||||
void ca_client_context::destroyGetCopy (
|
||||
epicsGuard < epicsMutex > & guard, getCopy & gc )
|
||||
{
|
||||
@@ -663,7 +650,7 @@ void ca_client_context::callbackProcessingCompleteNotify ()
|
||||
|
||||
cacChannel & ca_client_context::createChannel (
|
||||
epicsGuard < epicsMutex > & guard, const char * pChannelName,
|
||||
oldChannelNotify & chan, cacChannel::priLev pri )
|
||||
cacChannelNotify & chan, cacChannel::priLev pri )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
return this->pServiceContext->createChannel (
|
||||
@@ -753,32 +740,41 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
|
||||
{
|
||||
oldChannelNotify & chan = pMon->channel ();
|
||||
ca_client_context & cac = chan.getClientCtx ();
|
||||
epicsGuard < epicsMutex > * pCBGuard = cac.pCallbackGuard.get();
|
||||
if ( pCBGuard ) {
|
||||
cac.clearSubscriptionPrivate ( *pCBGuard, *pMon );
|
||||
}
|
||||
else {
|
||||
epicsGuard < epicsMutex > cbGuard ( cac.cbMutex );
|
||||
cac.clearSubscriptionPrivate ( cbGuard, *pMon );
|
||||
}
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
void ca_client_context::clearSubscriptionPrivate (
|
||||
epicsGuard < epicsMutex > & cbGuard, oldSubscription & subscr )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
oldChannelNotify & chan = subscr.channel ();
|
||||
epicsGuard < epicsMutex > guard ( cac.mutex );
|
||||
try {
|
||||
// if this stalls out on a live circuit then an exception
|
||||
// can be forthcoming which we must ignore as the clear
|
||||
// request must always be successful
|
||||
chan.eliminateExcessiveSendBacklog (
|
||||
& cbGuard, guard );
|
||||
chan.eliminateExcessiveSendBacklog ( guard );
|
||||
}
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
subscr.cancel ( cbGuard, guard );
|
||||
pMon->cancel ( guard );
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
void ca_client_context :: eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > & guard, cacChannel & chan )
|
||||
{
|
||||
if ( chan.requestMessageBytesPending ( guard ) >
|
||||
ca_client_context :: flushBlockThreshold ) {
|
||||
if ( this->pCallbackGuard.get() &&
|
||||
this->createdByThread == epicsThreadGetIdSelf () ) {
|
||||
// we need to be very careful about lock hierarchy
|
||||
// inversion in this situation
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > cbunguard (
|
||||
* this->pCallbackGuard.get() );
|
||||
{
|
||||
epicsGuard < epicsMutex > nestedGuard ( this->mutex );
|
||||
chan.flush ( nestedGuard );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
chan.flush ( guard );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,15 +497,15 @@ void cac::transferChanToVirtCircuit (
|
||||
if ( ! sockAddrAreIdentical ( &addr, &chanAddr ) ) {
|
||||
char acc[64];
|
||||
pChan->getPIIU(guard)->getHostName ( guard, acc, sizeof ( acc ) );
|
||||
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
|
||||
msgForMultiplyDefinedPV ( this->ipToAEngine,
|
||||
*this, pChan->pName ( guard ), acc );
|
||||
// It is possible for the ioInitiate call below to
|
||||
// call the callback directly if queue quota is exceeded.
|
||||
// This callback takes the callback lock and therefore we
|
||||
// must release the primary mutex here to avoid a lock
|
||||
// hierarchy inversion.
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
|
||||
msgForMultiplyDefinedPV ( this->ipToAEngine,
|
||||
*this, pChan->pName ( guard ), acc );
|
||||
pMsg->ioInitiate ( addr );
|
||||
}
|
||||
return;
|
||||
@@ -566,19 +566,16 @@ void cac::transferChanToVirtCircuit (
|
||||
}
|
||||
|
||||
void cac::destroyChannel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
cbGuard.assertIdenticalMutex ( this->cbMutex );
|
||||
|
||||
// uninstall channel so that recv threads
|
||||
// will not start a new callback for this channel's IO.
|
||||
if ( this->chanTable.remove ( chan ) != & chan ) {
|
||||
throw std::logic_error ( "Invalid channel identifier" );
|
||||
}
|
||||
|
||||
chan.~nciu ();
|
||||
this->channelFreeList.release ( & chan );
|
||||
}
|
||||
@@ -642,12 +639,10 @@ netReadNotifyIO & cac::readNotifyRequest (
|
||||
return *pIO.release();
|
||||
}
|
||||
|
||||
baseNMIU * cac::destroyIO (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
bool cac::destroyIO (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid & idIn, nciu & chan )
|
||||
{
|
||||
cbGuard.assertIdenticalMutex ( this->cbMutex );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
baseNMIU * pIO = this->ioTable.remove ( idIn );
|
||||
@@ -660,8 +655,9 @@ baseNMIU * cac::destroyIO (
|
||||
// this uninstalls from the list and destroys the IO
|
||||
pIO->exception ( guard, *this,
|
||||
ECA_CHANDESTROY, chan.pName ( guard ) );
|
||||
return true;
|
||||
}
|
||||
return pIO;
|
||||
return false;
|
||||
}
|
||||
|
||||
void cac::ioShow (
|
||||
|
||||
@@ -135,9 +135,7 @@ public:
|
||||
epicsGuard < epicsMutex > & guard, const char * pChannelName,
|
||||
cacChannelNotify &, cacChannel::priLev );
|
||||
void destroyChannel (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
nciu & );
|
||||
epicsGuard < epicsMutex > &, nciu & );
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > &, nciu &, netiiu * & );
|
||||
nciu * lookupChannel (
|
||||
@@ -156,8 +154,7 @@ public:
|
||||
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
|
||||
unsigned type, arrayElementCount nElem, unsigned mask,
|
||||
cacStateNotify &, bool channelIsInstalled );
|
||||
baseNMIU * destroyIO (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
bool destroyIO (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid & idIn,
|
||||
nciu & chan );
|
||||
|
||||
@@ -137,7 +137,6 @@ public:
|
||||
virtual void connectNotify ( epicsGuard < epicsMutex > & ) = 0;
|
||||
virtual void disconnectNotify ( epicsGuard < epicsMutex > & ) = 0;
|
||||
virtual void serviceShutdownNotify (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual void accessRightsNotify (
|
||||
epicsGuard < epicsMutex > &, const caAccessRights & ) = 0;
|
||||
@@ -175,7 +174,6 @@ public:
|
||||
|
||||
cacChannel ( cacChannelNotify & );
|
||||
virtual void destroy (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
cacChannelNotify & notify () const; // required ?????
|
||||
virtual unsigned getName (
|
||||
@@ -189,8 +187,9 @@ public:
|
||||
unsigned level ) const = 0;
|
||||
virtual void initiateConnect (
|
||||
epicsGuard < epicsMutex > & ) = 0;
|
||||
virtual void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
virtual unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual void flush (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual ioStatus read (
|
||||
epicsGuard < epicsMutex > &,
|
||||
@@ -209,7 +208,6 @@ public:
|
||||
arrayElementCount count, unsigned mask, cacStateNotify &,
|
||||
ioid * = 0 ) = 0;
|
||||
virtual void ioCancel (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & ) = 0;
|
||||
virtual void ioShow (
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
void clear ();
|
||||
unsigned occupiedBytes () const;
|
||||
bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const;
|
||||
bool flushBlockThreshold ( unsigned nBytesThisMsg ) const;
|
||||
bool flushBlockThreshold () const;
|
||||
void pushUInt16 ( const ca_uint16_t value );
|
||||
void pushUInt32 ( const ca_uint32_t value );
|
||||
void pushFloat32 ( const ca_float32_t value );
|
||||
@@ -215,9 +215,9 @@ inline unsigned comQueSend::occupiedBytes () const
|
||||
return this->nBytesPending;
|
||||
}
|
||||
|
||||
inline bool comQueSend::flushBlockThreshold ( unsigned nBytesThisMsg ) const
|
||||
inline bool comQueSend::flushBlockThreshold () const
|
||||
{
|
||||
return ( this->nBytesPending + nBytesThisMsg > 16 * comBuf::capacityBytes () );
|
||||
return ( this->nBytesPending > 16 * comBuf::capacityBytes () );
|
||||
}
|
||||
|
||||
inline bool comQueSend::flushEarlyThreshold ( unsigned nBytesThisMsg ) const
|
||||
|
||||
@@ -64,25 +64,28 @@ void getCopy::completion (
|
||||
unsigned size = dbr_size_n ( typeIn, countIn );
|
||||
memcpy ( this->pValue, pDataIn, size );
|
||||
this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
|
||||
this->cacCtx.destroyGetCopy ( guard, *this );
|
||||
}
|
||||
else {
|
||||
this->exception ( guard, ECA_INTERNAL,
|
||||
"bad data type match in get copy back response",
|
||||
typeIn, countIn);
|
||||
}
|
||||
this->cacCtx.destroyGetCopy ( guard, *this );
|
||||
}
|
||||
|
||||
void getCopy::exception (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
int status, const char *pContext, unsigned /* typeIn */, arrayElementCount /* countIn */ )
|
||||
{
|
||||
oldChannelNotify & chanTmp ( this->chan );
|
||||
unsigned typeTmp ( this->type );
|
||||
arrayElementCount countTmp ( this->count );
|
||||
this->cacCtx.destroyGetCopy ( guard, *this );
|
||||
if ( status != ECA_CHANDESTROY ) {
|
||||
this->cacCtx.exception ( guard, status, pContext,
|
||||
__FILE__, __LINE__, this->chan, this->type,
|
||||
this->count, CA_OP_GET );
|
||||
__FILE__, __LINE__, chanTmp, typeTmp,
|
||||
countTmp, CA_OP_GET );
|
||||
}
|
||||
this->cacCtx.destroyGetCopy ( guard, *this );
|
||||
}
|
||||
|
||||
void getCopy::show ( unsigned level ) const
|
||||
|
||||
@@ -76,27 +76,22 @@ nciu::~nciu ()
|
||||
// channels are created by the user, and only destroyed by the user
|
||||
// using this routine
|
||||
void nciu::destroy (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
while ( baseNMIU * pNetIO = this->eventq.first () ) {
|
||||
assert ( this->cacCtx.destroyIO (
|
||||
callbackControlGuard, mutualExclusionGuard,
|
||||
pNetIO->getId (), *this ) );
|
||||
guard, pNetIO->getId (), *this ) );
|
||||
}
|
||||
|
||||
|
||||
// if the claim reply has not returned yet then we will issue
|
||||
// the clear channel request to the server when the claim reply
|
||||
// arrives and there is no matching nciu in the client
|
||||
if ( this->channelNode::isInstalledInServer ( mutualExclusionGuard ) ) {
|
||||
this->getPIIU(mutualExclusionGuard)->clearChannelRequest (
|
||||
mutualExclusionGuard, this->sid, this->id );
|
||||
if ( this->channelNode::isInstalledInServer ( guard ) ) {
|
||||
this->getPIIU(guard)->clearChannelRequest (
|
||||
guard, this->sid, this->id );
|
||||
}
|
||||
|
||||
this->piiu->uninstallChan ( mutualExclusionGuard, *this );
|
||||
|
||||
this->cacCtx.destroyChannel (
|
||||
callbackControlGuard, mutualExclusionGuard, *this );
|
||||
this->piiu->uninstallChan ( guard, *this );
|
||||
this->cacCtx.destroyChannel ( guard, *this );
|
||||
}
|
||||
|
||||
void * nciu::operator new ( size_t ) // X aCC 361
|
||||
@@ -268,12 +263,16 @@ unsigned nciu::nameLen (
|
||||
return this->nameLength;
|
||||
}
|
||||
|
||||
void nciu::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
unsigned nciu::requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->piiu->eliminateExcessiveSendBacklog (
|
||||
pCallbackGuard, mutualExclusionGuard );
|
||||
return piiu->requestMessageBytesPending ( guard );
|
||||
}
|
||||
|
||||
void nciu::flush (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
piiu->flush ( guard );
|
||||
}
|
||||
|
||||
cacChannel::ioStatus nciu::read (
|
||||
@@ -391,10 +390,9 @@ void nciu::subscribe (
|
||||
}
|
||||
|
||||
void nciu::ioCancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard, const ioid & idIn )
|
||||
{
|
||||
this->cacCtx.destroyIO ( cbGuard, guard, idIn, *this );
|
||||
this->cacCtx.destroyIO ( guard, idIn, *this );
|
||||
}
|
||||
|
||||
void nciu::ioShow (
|
||||
@@ -577,7 +575,7 @@ void nciu::serviceShutdownNotify (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
{
|
||||
this->setServerAddressUnknown ( noopIIU, mutualExclusionGuard );
|
||||
this->notify().serviceShutdownNotify ( callbackControlGuard, mutualExclusionGuard );
|
||||
this->notify().serviceShutdownNotify ( mutualExclusionGuard );
|
||||
}
|
||||
|
||||
void channelNode::setRespPendingState (
|
||||
|
||||
@@ -217,12 +217,12 @@ private:
|
||||
ca_uint16_t typeCode;
|
||||
ca_uint8_t priority;
|
||||
virtual void destroy (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
ioStatus read (
|
||||
epicsGuard < epicsMutex > &,
|
||||
@@ -241,7 +241,6 @@ private:
|
||||
unsigned type, arrayElementCount nElem,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid * );
|
||||
virtual void ioCancel (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & );
|
||||
void ioShow (
|
||||
|
||||
@@ -129,8 +129,13 @@ void netiiu::flushRequest (
|
||||
{
|
||||
}
|
||||
|
||||
void netiiu::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > *,
|
||||
unsigned netiiu::requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & )
|
||||
{
|
||||
return 0u;
|
||||
}
|
||||
|
||||
void netiiu::flush (
|
||||
epicsGuard < epicsMutex > & )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,8 +47,9 @@ public:
|
||||
epicsGuard < epicsMutex > & ) const = 0;
|
||||
virtual bool ca_v42_ok (
|
||||
epicsGuard < epicsMutex > & ) const = 0;
|
||||
virtual void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
virtual unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual void flush (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual void writeRequest (
|
||||
epicsGuard < epicsMutex > &, nciu &,
|
||||
|
||||
@@ -116,11 +116,16 @@ void noopiiu::flushRequest (
|
||||
netiiu::flushRequest ( guard );
|
||||
}
|
||||
|
||||
void noopiiu::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCBGuard,
|
||||
unsigned noopiiu::requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
netiiu::eliminateExcessiveSendBacklog ( pCBGuard, guard );
|
||||
return netiiu::requestMessageBytesPending ( guard );
|
||||
}
|
||||
|
||||
void noopiiu::flush (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
netiiu::flush ( guard );
|
||||
}
|
||||
|
||||
void noopiiu::requestRecvProcessPostponedFlush (
|
||||
|
||||
@@ -39,8 +39,9 @@ public:
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
bool ca_v42_ok (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void writeRequest (
|
||||
epicsGuard < epicsMutex > &, nciu &,
|
||||
|
||||
@@ -46,14 +46,13 @@
|
||||
#include "cadef.h"
|
||||
#include "syncGroup.h"
|
||||
|
||||
struct oldChannelNotify : public cacChannelNotify {
|
||||
struct oldChannelNotify : private cacChannelNotify {
|
||||
public:
|
||||
oldChannelNotify (
|
||||
epicsGuard < epicsMutex > &, struct ca_client_context &,
|
||||
const char * pName, caCh * pConnCallBackIn,
|
||||
void * pPrivateIn, capri priority );
|
||||
void destructor (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
|
||||
// legacy C API
|
||||
@@ -114,9 +113,6 @@ public:
|
||||
unsigned level ) const;
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void read (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, arrayElementCount count,
|
||||
@@ -126,13 +122,15 @@ public:
|
||||
unsigned type, arrayElementCount count, const void *pValue,
|
||||
cacWriteNotify &, cacChannel::ioid *pId = 0 );
|
||||
void ioCancel (
|
||||
epicsGuard < epicsMutex > & callbackControl,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & );
|
||||
void ioShow (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid &, unsigned level ) const;
|
||||
ca_client_context & getClientCtx ();
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > & );
|
||||
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void * ,
|
||||
@@ -151,7 +149,6 @@ private:
|
||||
void connectNotify ( epicsGuard < epicsMutex > & );
|
||||
void disconnectNotify ( epicsGuard < epicsMutex > & );
|
||||
void serviceShutdownNotify (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void accessRightsNotify (
|
||||
epicsGuard < epicsMutex > &, const caAccessRights & );
|
||||
@@ -263,7 +260,6 @@ public:
|
||||
~oldSubscription ();
|
||||
oldChannelNotify & channel () const;
|
||||
void cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & );
|
||||
@@ -301,10 +297,10 @@ public:
|
||||
void replaceErrLogHandler ( caPrintfFunc * ca_printf_func );
|
||||
cacChannel & createChannel (
|
||||
epicsGuard < epicsMutex > &, const char * pChannelName,
|
||||
oldChannelNotify &, cacChannel::priLev pri );
|
||||
cacChannelNotify &, cacChannel::priLev pri );
|
||||
void flush ( epicsGuard < epicsMutex > & );
|
||||
void eliminateExcessiveSendBacklog (
|
||||
oldChannelNotify & chan, epicsGuard < epicsMutex > & guard );
|
||||
epicsGuard < epicsMutex > &, cacChannel & );
|
||||
int pendIO ( const double & timeout );
|
||||
int pendEvent ( const double & timeout );
|
||||
bool ioComplete () const;
|
||||
@@ -339,14 +335,14 @@ public:
|
||||
void vSignal ( int ca_status, const char * pfilenm,
|
||||
int lineno, const char *pFormat, va_list args );
|
||||
bool preemptiveCallbakIsEnabled () const;
|
||||
void destroyChannel ( epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard, oldChannelNotify & chan );
|
||||
void destroyGetCopy ( epicsGuard < epicsMutex > &, getCopy & );
|
||||
void destroyGetCallback ( epicsGuard < epicsMutex > &, getCallback & );
|
||||
void destroyPutCallback ( epicsGuard < epicsMutex > &, putCallback & );
|
||||
void destroySubscription ( epicsGuard < epicsMutex > &, oldSubscription & );
|
||||
epicsMutex & mutexRef () const;
|
||||
|
||||
|
||||
// legacy C API
|
||||
friend int epicsShareAPI ca_create_channel (
|
||||
const char * name_str, caCh * conn_func, void * puser,
|
||||
capri priority, chid * chanptr );
|
||||
@@ -365,8 +361,6 @@ public:
|
||||
chtype type, arrayElementCount count, chid pChan,
|
||||
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
|
||||
evid *monixptr );
|
||||
|
||||
// legacy C API
|
||||
friend int epicsShareAPI ca_flush_io ();
|
||||
friend int epicsShareAPI ca_clear_subscription ( evid pMon );
|
||||
friend int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid );
|
||||
@@ -389,6 +383,7 @@ private:
|
||||
mutable epicsMutex cbMutex;
|
||||
epicsEvent ioDone;
|
||||
epicsEvent callbackThreadActivityComplete;
|
||||
epicsThreadId createdByThread;
|
||||
epics_auto_ptr < epicsGuard < epicsMutex > > pCallbackGuard;
|
||||
epics_auto_ptr < cacContext > pServiceContext;
|
||||
caExceptionHandler * ca_exception_func;
|
||||
@@ -409,8 +404,6 @@ private:
|
||||
void callbackProcessingCompleteNotify ();
|
||||
cacContext & createNetworkContext (
|
||||
epicsMutex & mutualExclusion, epicsMutex & callbackControl );
|
||||
void clearSubscriptionPrivate (
|
||||
epicsGuard < epicsMutex > & cbGuard, oldSubscription & subscr );
|
||||
|
||||
ca_client_context ( const ca_client_context & );
|
||||
ca_client_context & operator = ( const ca_client_context & );
|
||||
@@ -419,6 +412,7 @@ private:
|
||||
friend void cacExitHandler ( void *);
|
||||
static cacService * pDefaultService;
|
||||
static epicsMutex * pDefaultServiceInstallMutex;
|
||||
static const unsigned flushBlockThreshold;
|
||||
};
|
||||
|
||||
int fetchClientContext ( ca_client_context * * ppcac );
|
||||
@@ -448,20 +442,11 @@ inline void oldChannelNotify::initiateConnect (
|
||||
this->io.initiateConnect ( guard );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
{
|
||||
this->io.eliminateExcessiveSendBacklog (
|
||||
pCallbackGuard, mutualExclusionGuard );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::ioCancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid & id )
|
||||
{
|
||||
this->io.ioCancel ( cbGuard, guard, id );
|
||||
this->io.ioCancel ( guard, id );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::ioShow (
|
||||
@@ -471,6 +456,12 @@ inline void oldChannelNotify::ioShow (
|
||||
this->io.ioShow ( guard, id, level );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->cacCtx.eliminateExcessiveSendBacklog ( guard, this->io );
|
||||
}
|
||||
|
||||
inline void * oldChannelNotify::operator new ( size_t size,
|
||||
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & freeList )
|
||||
{
|
||||
@@ -500,10 +491,9 @@ inline void oldSubscription::operator delete ( void *pCadaver,
|
||||
#endif
|
||||
|
||||
inline void oldSubscription::cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->chan.ioCancel ( cbGuard, guard, this->id );
|
||||
this->chan.ioCancel ( guard, this->id );
|
||||
}
|
||||
|
||||
inline oldChannelNotify & oldSubscription::channel () const
|
||||
@@ -569,12 +559,5 @@ inline unsigned ca_client_context::sequenceNumberOfOutstandingIO (
|
||||
// perhaps on SMP systems THERE should be lock/unlock around this
|
||||
return this->ioSeqNo;
|
||||
}
|
||||
|
||||
inline void ca_client_context::eliminateExcessiveSendBacklog (
|
||||
oldChannelNotify & chan, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
chan.eliminateExcessiveSendBacklog (
|
||||
this->pCallbackGuard.get(), guard );
|
||||
}
|
||||
|
||||
#endif // ifndef oldAccessh
|
||||
|
||||
@@ -65,11 +65,10 @@ oldChannelNotify::~oldChannelNotify ()
|
||||
}
|
||||
|
||||
void oldChannelNotify::destructor (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
|
||||
this->io.destroy ( cbGuard, guard );
|
||||
this->io.destroy ( guard );
|
||||
// no need to worry about a connect preempting here because
|
||||
// the io (the nciu) has been destroyed above
|
||||
if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) {
|
||||
@@ -119,13 +118,9 @@ void oldChannelNotify::disconnectNotify (
|
||||
}
|
||||
|
||||
void oldChannelNotify::serviceShutdownNotify (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
this->cacCtx.destroyChannel (
|
||||
callbackControlGuard,
|
||||
mutualExclusionGuard,
|
||||
*this );
|
||||
this->disconnectNotify ( guard );
|
||||
}
|
||||
|
||||
void oldChannelNotify::accessRightsNotify (
|
||||
@@ -287,8 +282,7 @@ int epicsShareAPI ca_array_get ( chtype type,
|
||||
}
|
||||
unsigned tmpType = static_cast < unsigned > ( type );
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
pChan->eliminateExcessiveSendBacklog (
|
||||
pChan->getClientCtx().pCallbackGuard.get(), guard );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
autoPtrFreeList < getCopy, 0x400, epicsMutexNOOP > pNotify
|
||||
( pChan->getClientCtx().getCopyFreeList,
|
||||
new ( pChan->getClientCtx().getCopyFreeList )
|
||||
@@ -355,8 +349,7 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
|
||||
unsigned tmpType = static_cast < unsigned > ( type );
|
||||
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
pChan->eliminateExcessiveSendBacklog (
|
||||
pChan->getClientCtx().pCallbackGuard.get(), guard );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
autoPtrFreeList < getCallback, 0x400, epicsMutexNOOP > pNotify
|
||||
( pChan->getClientCtx().getCallbackFreeList,
|
||||
new ( pChan->getClientCtx().getCallbackFreeList )
|
||||
@@ -427,8 +420,7 @@ int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
pChan->eliminateExcessiveSendBacklog (
|
||||
pChan->getClientCtx().pCallbackGuard.get(), guard );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
unsigned tmpType = static_cast < unsigned > ( type );
|
||||
autoPtrFreeList < putCallback, 0x400, epicsMutexNOOP > pNotify
|
||||
( pChan->getClientCtx().putCallbackFreeList,
|
||||
@@ -491,8 +483,7 @@ int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
|
||||
int caStatus;
|
||||
try {
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
pChan->eliminateExcessiveSendBacklog (
|
||||
pChan->getClientCtx().pCallbackGuard.get(), guard );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
pChan->io.write ( guard, tmpType, count, pValue );
|
||||
caStatus = ECA_NORMAL;
|
||||
}
|
||||
@@ -569,8 +560,7 @@ int epicsShareAPI ca_create_subscription (
|
||||
// can be forthcoming which we must ignore (this is a
|
||||
// special case preserving legacy ca_create_subscription
|
||||
// behavior)
|
||||
pChan->eliminateExcessiveSendBacklog (
|
||||
pChan->getClientCtx().pCallbackGuard.get(), guard );
|
||||
pChan->eliminateExcessiveSendBacklog ( guard );
|
||||
}
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored (its ok to subscribe when not connected)
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
virtual bool ioPending (
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
virtual void cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
virtual void show (
|
||||
epicsGuard < epicsMutex > &,
|
||||
@@ -92,7 +91,6 @@ public:
|
||||
void begin ( epicsGuard < epicsMutex > &,
|
||||
unsigned type, arrayElementCount count );
|
||||
void cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
protected:
|
||||
@@ -135,7 +133,6 @@ public:
|
||||
void begin ( epicsGuard < epicsMutex > &, unsigned type,
|
||||
arrayElementCount count, const void * pValueIn );
|
||||
void cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
protected:
|
||||
@@ -170,16 +167,13 @@ struct CASG : public chronIntIdRes < CASG >, private casgRecycle {
|
||||
public:
|
||||
CASG ( epicsGuard < epicsMutex > &, ca_client_context & cacIn );
|
||||
void destructor (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool ioComplete (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool verify ( epicsGuard < epicsMutex > & ) const;
|
||||
int block ( epicsGuard < epicsMutex > & cbGuard,
|
||||
int block ( epicsGuard < epicsMutex > * pcbGuard,
|
||||
epicsGuard < epicsMutex > & guard, double timeout );
|
||||
void reset ( epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void reset ( epicsGuard < epicsMutex > & guard );
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
void show ( unsigned level ) const;
|
||||
void get ( epicsGuard < epicsMutex > &, chid pChan,
|
||||
@@ -214,7 +208,6 @@ private:
|
||||
epicsGuard < epicsMutex > &, syncGroupReadNotify & io );
|
||||
|
||||
void destroyPendingIO (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void destroyCompletedIO (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
|
||||
@@ -38,8 +38,7 @@ void syncGroupReadNotify::begin (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
this->chan->getClientCtx().
|
||||
eliminateExcessiveSendBacklog ( *this->chan, guard );
|
||||
this->chan->eliminateExcessiveSendBacklog ( guard );
|
||||
this->ioComplete = false;
|
||||
boolFlagManager mgr ( this->idIsValid );
|
||||
this->chan->read ( guard, type, count, *this, &this->id );
|
||||
@@ -47,11 +46,10 @@ void syncGroupReadNotify::begin (
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
if ( this->idIsValid ) {
|
||||
this->chan->ioCancel ( cbGuard, guard, this->id );
|
||||
this->chan->ioCancel ( guard, this->id );
|
||||
this->idIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ void syncGroupWriteNotify::begin (
|
||||
epicsGuard < epicsMutex > & guard, unsigned type,
|
||||
arrayElementCount count, const void * pValueIn )
|
||||
{
|
||||
this->chan->getClientCtx().eliminateExcessiveSendBacklog (
|
||||
*this->chan, guard );
|
||||
this->chan->eliminateExcessiveSendBacklog ( guard );
|
||||
this->ioComplete = false;
|
||||
boolFlagManager mgr ( this->idIsValid );
|
||||
this->chan->write ( guard, type, count,
|
||||
@@ -46,11 +45,10 @@ void syncGroupWriteNotify::begin (
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::cancel (
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
if ( this->idIsValid ) {
|
||||
this->chan->ioCancel ( cbGuard, guard, this->id );
|
||||
this->chan->ioCancel ( guard, this->id );
|
||||
this->idIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,75 +55,45 @@ extern "C" int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid )
|
||||
{
|
||||
ca_client_context * pcac;
|
||||
int caStatus = fetchClientContext ( & pcac );
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
if ( pcac->pCallbackGuard.get() ) {
|
||||
if ( caStatus == ECA_NORMAL ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
return ECA_BADSYNCGRP;
|
||||
if ( pcasg ) {
|
||||
pcasg->destructor ( guard );
|
||||
pcac->casgFreeList.release ( pcasg );
|
||||
}
|
||||
|
||||
pcasg->destructor ( *pcac->pCallbackGuard, guard );
|
||||
pcac->casgFreeList.release ( pcasg );
|
||||
}
|
||||
else {
|
||||
epicsGuard < epicsMutex > cbGuard ( pcac->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
return ECA_BADSYNCGRP;
|
||||
else {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
pcasg->destructor ( cbGuard, guard );
|
||||
pcac->casgFreeList.release ( pcasg );
|
||||
}
|
||||
|
||||
return ECA_NORMAL;
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* ca_sg_block ()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeout )
|
||||
//
|
||||
// ca_sg_block ()
|
||||
//
|
||||
// !!!! This routine is only visible in the old interface - or in a new ST interface.
|
||||
// !!!! In the old interface we restrict thread attach so that calls from threads
|
||||
// !!!! other than the initializing thread are not allowed if preemptive callback
|
||||
// !!!! is disabled. This prevents the preemptive callback lock from being released
|
||||
// !!!! by other threads than the one that locked it.
|
||||
//
|
||||
extern "C" int epicsShareAPI ca_sg_block (
|
||||
const CA_SYNC_GID gid, ca_real timeout )
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
CASG *pcasg;
|
||||
int status;
|
||||
|
||||
status = fetchClientContext ( &pcac );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if ( pcac->pCallbackGuard.get() ) {
|
||||
int status = fetchClientContext ( &pcac );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
status = ECA_BADSYNCGRP;
|
||||
}
|
||||
else {
|
||||
status = pcasg->block ( *pcac->pCallbackGuard, guard, timeout );
|
||||
status = pcasg->block (
|
||||
pcac->pCallbackGuard.get (), guard, timeout );
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsGuard < epicsMutex > cbGuard ( pcac->cbMutex);
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
status = ECA_BADSYNCGRP;
|
||||
}
|
||||
else {
|
||||
status = pcasg->block ( cbGuard, guard, timeout );
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -133,40 +103,17 @@ extern "C" int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeou
|
||||
extern "C" int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid )
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
CASG *pcasg;
|
||||
int caStatus;
|
||||
|
||||
caStatus = fetchClientContext (&pcac);
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
if ( pcac->pCallbackGuard.get() ) {
|
||||
int caStatus = fetchClientContext (&pcac);
|
||||
if ( caStatus == ECA_NORMAL ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
pcasg->reset ( guard );
|
||||
}
|
||||
else {
|
||||
caStatus = ECA_NORMAL;
|
||||
pcasg->reset ( *pcac->pCallbackGuard, guard );
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsGuard < epicsMutex > cbGuard ( pcac->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
}
|
||||
else {
|
||||
caStatus = ECA_NORMAL;
|
||||
pcasg->reset ( cbGuard, guard );
|
||||
}
|
||||
}
|
||||
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
@@ -198,44 +145,24 @@ extern "C" int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid )
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) // X aCC 361
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
CASG *pcasg;
|
||||
int caStatus;
|
||||
|
||||
caStatus = fetchClientContext ( &pcac );
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
if ( pcac->pCallbackGuard.get() ) {
|
||||
ca_client_context * pcac;
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
if ( caStatus == ECA_NORMAL ) {
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
return ECA_BADSYNCGRP;
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
if ( pcasg->ioComplete ( guard ) ) {
|
||||
caStatus = ECA_IODONE;
|
||||
}
|
||||
else{
|
||||
caStatus = ECA_IOINPROGRESS;
|
||||
}
|
||||
}
|
||||
if ( pcasg->ioComplete ( *pcac->pCallbackGuard, guard ) ) {
|
||||
return ECA_IODONE;
|
||||
}
|
||||
else{
|
||||
return ECA_IOINPROGRESS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsGuard < epicsMutex > cbGuard ( pcac->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
|
||||
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
if ( pcasg->ioComplete ( cbGuard, guard ) ) {
|
||||
return ECA_IODONE;
|
||||
}
|
||||
else{
|
||||
return ECA_IOINPROGRESS;
|
||||
else {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
}
|
||||
}
|
||||
return caStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -133,7 +133,7 @@ void tcpSendThread::run ()
|
||||
laborPending = true;
|
||||
}
|
||||
|
||||
if ( this->iiu.sendQue.flushBlockThreshold ( 0u ) ) {
|
||||
if ( this->iiu.sendQue.flushBlockThreshold () ) {
|
||||
laborPending = true;
|
||||
break;
|
||||
}
|
||||
@@ -145,7 +145,7 @@ void tcpSendThread::run ()
|
||||
this->iiu.connectedList.add ( *pChan );
|
||||
pChan->channelNode::listMember =
|
||||
channelNode::cs_connected;
|
||||
if ( this->iiu.sendQue.flushBlockThreshold ( 0u ) ) {
|
||||
if ( this->iiu.sendQue.flushBlockThreshold () ) {
|
||||
laborPending = true;
|
||||
break;
|
||||
}
|
||||
@@ -157,18 +157,18 @@ void tcpSendThread::run ()
|
||||
this->iiu.connectedList.add ( *pChan );
|
||||
pChan->channelNode::listMember =
|
||||
channelNode::cs_connected;
|
||||
if ( this->iiu.sendQue.flushBlockThreshold ( 0u ) ) {
|
||||
if ( this->iiu.sendQue.flushBlockThreshold () ) {
|
||||
laborPending = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! this->iiu.flush ( guard ) ) {
|
||||
if ( ! this->iiu.sendThreadFlush ( guard ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( this->iiu.state == tcpiiu::iiucs_clean_shutdown ) {
|
||||
this->iiu.flush ( guard );
|
||||
this->iiu.sendThreadFlush ( guard );
|
||||
// this should cause the server to disconnect from
|
||||
// the client
|
||||
int status = ::shutdown ( this->iiu.sock, SHUT_WR );
|
||||
@@ -1623,7 +1623,7 @@ void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard, // X
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
bool tcpiiu::flush ( epicsGuard < epicsMutex > & guard )
|
||||
bool tcpiiu::sendThreadFlush ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1667,58 +1667,53 @@ bool tcpiiu::flush ( epicsGuard < epicsMutex > & guard )
|
||||
return true;
|
||||
}
|
||||
|
||||
void tcpiiu::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
void tcpiiu :: flush ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
mutualExclusionGuard.assertIdenticalMutex ( this->mutex );
|
||||
this->flushRequest ( guard );
|
||||
// the process thread is not permitted to flush as this
|
||||
// can result in a push / pull deadlock on the TCP pipe.
|
||||
// Instead, the process thread scheduals the flush with the
|
||||
// send thread which runs at a higher priority than the
|
||||
// receive thread. The same applies to the UDP thread for
|
||||
// locking hierarchy reasons.
|
||||
if ( ! epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
|
||||
// enable / disable of call back preemption must occur here
|
||||
// because the tcpiiu might disconnect while waiting and its
|
||||
// pointer to this cac might become invalid
|
||||
assert ( this->blockingForFlush < UINT_MAX );
|
||||
this->blockingForFlush++;
|
||||
while ( this->sendQue.flushBlockThreshold() ) {
|
||||
|
||||
if ( this->sendQue.flushBlockThreshold ( 0u ) ) {
|
||||
this->flushRequest ( mutualExclusionGuard );
|
||||
// the process thread is not permitted to flush as this
|
||||
// can result in a push / pull deadlock on the TCP pipe.
|
||||
// Instead, the process thread scheduals the flush with the
|
||||
// send thread which runs at a higher priority than the
|
||||
// receive thread. The same applies to the UDP thread for
|
||||
// locking hierarchy reasons.
|
||||
if ( ! epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
|
||||
// enable / disable of call back preemption must occur here
|
||||
// because the tcpiiu might disconnect while waiting and its
|
||||
// pointer to this cac might become invalid
|
||||
assert ( this->blockingForFlush < UINT_MAX );
|
||||
this->blockingForFlush++;
|
||||
while ( this->sendQue.flushBlockThreshold(0u) ) {
|
||||
|
||||
bool userRequestsCanBeAccepted =
|
||||
this->state == iiucs_connected ||
|
||||
( ! this->ca_v42_ok ( mutualExclusionGuard ) &&
|
||||
this->state == iiucs_connecting );
|
||||
// fail the users request if we have a disconnected
|
||||
// or unresponsive circuit
|
||||
if ( ! userRequestsCanBeAccepted ||
|
||||
this->unresponsiveCircuit ) {
|
||||
this->decrementBlockingForFlushCount ( mutualExclusionGuard );
|
||||
throw cacChannel::notConnected ();
|
||||
}
|
||||
|
||||
epicsGuardRelease < epicsMutex > autoRelease (
|
||||
mutualExclusionGuard );
|
||||
if ( pCallbackGuard ) {
|
||||
epicsGuardRelease < epicsMutex >
|
||||
autoReleaseCB ( *pCallbackGuard );
|
||||
this->flushBlockEvent.wait ( 30.0 );
|
||||
}
|
||||
else {
|
||||
this->flushBlockEvent.wait ( 30.0 );
|
||||
}
|
||||
bool userRequestsCanBeAccepted =
|
||||
this->state == iiucs_connected ||
|
||||
( ! this->ca_v42_ok ( guard ) &&
|
||||
this->state == iiucs_connecting );
|
||||
// fail the users request if we have a disconnected
|
||||
// or unresponsive circuit
|
||||
if ( ! userRequestsCanBeAccepted ||
|
||||
this->unresponsiveCircuit ) {
|
||||
this->decrementBlockingForFlushCount ( guard );
|
||||
throw cacChannel::notConnected ();
|
||||
}
|
||||
this->decrementBlockingForFlushCount ( mutualExclusionGuard );
|
||||
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
this->flushBlockEvent.wait ( 30.0 );
|
||||
}
|
||||
this->decrementBlockingForFlushCount ( guard );
|
||||
}
|
||||
else if ( ! this->earlyFlush && this->sendQue.flushEarlyThreshold(0u) ) {
|
||||
}
|
||||
|
||||
unsigned tcpiiu::requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
#if 0
|
||||
if ( ! this->earlyFlush && this->sendQue.flushEarlyThreshold(0u) ) {
|
||||
this->earlyFlush = true;
|
||||
this->sendThreadFlushEvent.signal ();
|
||||
}
|
||||
#endif
|
||||
return sendQue.occupiedBytes ();
|
||||
}
|
||||
|
||||
void tcpiiu::decrementBlockingForFlushCount (
|
||||
@@ -1968,7 +1963,6 @@ int tcpiiu::printf (
|
||||
return status;
|
||||
}
|
||||
|
||||
// this is called virtually
|
||||
void tcpiiu::flushRequest ( epicsGuard < epicsMutex > & )
|
||||
{
|
||||
if ( this->sendQue.occupiedBytes () > 0 ) {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "msgForMultiplyDefinedPV.h"
|
||||
#include "repeaterClient.h"
|
||||
#include "hostNameCache.h"
|
||||
#include "comBuf.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning ( push )
|
||||
@@ -68,6 +69,13 @@ template class tsFreeList < putCallback, 1024, epicsMutexNOOP >;
|
||||
template class tsFreeList < repeaterClient, 0x20 >;
|
||||
template class epicsSingleton < localHostName >;
|
||||
template class epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array >;
|
||||
template unsigned comBuf :: push ( const double * pValue, unsigned nElem );
|
||||
template unsigned comBuf :: push ( const float * pValue, unsigned nElem );
|
||||
template unsigned comBuf :: push ( const int * pValue, unsigned nElem );
|
||||
template unsigned comBuf :: push ( const short * pValue, unsigned nElem );
|
||||
template comBuf :: popStatus comBuf :: pop ( unsigned int & returnVal );
|
||||
template comBuf :: popStatus comBuf :: pop ( unsigned short & returnVal );
|
||||
template comBuf :: popStatus comBuf :: pop ( unsigned char & returnVal );
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -1223,11 +1223,16 @@ void udpiiu::flushRequest (
|
||||
netiiu::flushRequest ( guard );
|
||||
}
|
||||
|
||||
void udpiiu::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCBGuard,
|
||||
unsigned udpiiu::requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
netiiu::eliminateExcessiveSendBacklog ( pCBGuard, guard );
|
||||
return netiiu::requestMessageBytesPending ( guard );
|
||||
}
|
||||
|
||||
void udpiiu::flush (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
netiiu::flush ( guard );
|
||||
}
|
||||
|
||||
void udpiiu::requestRecvProcessPostponedFlush (
|
||||
|
||||
@@ -189,8 +189,9 @@ private:
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
bool ca_v42_ok (
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void writeRequest (
|
||||
epicsGuard < epicsMutex > &, nciu &,
|
||||
|
||||
@@ -124,9 +124,11 @@ public:
|
||||
|
||||
void flushRequest (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
|
||||
void show ( unsigned level ) const;
|
||||
bool setEchoRequestPending (
|
||||
epicsGuard < epicsMutex > & );
|
||||
@@ -294,8 +296,8 @@ private:
|
||||
nciu & chan, netSubscription & subscr );
|
||||
void flushIfRecvProcessRequested (
|
||||
epicsGuard < epicsMutex > & );
|
||||
bool flush (
|
||||
epicsGuard < epicsMutex > & ); // only to be called by the send thread
|
||||
bool sendThreadFlush (
|
||||
epicsGuard < epicsMutex > & );
|
||||
|
||||
// netiiu stubs
|
||||
void uninstallChanDueToSuccessfulSearchResponse (
|
||||
|
||||
@@ -91,6 +91,7 @@ void event_handler (evargs args)
|
||||
memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));
|
||||
|
||||
print_time_val_sts(pv, pv->reqElems);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -535,7 +535,7 @@ long epicsShareAPI dbProcess(dbCommon *precord)
|
||||
*/
|
||||
|
||||
/* see if there are any stopped records or breakpoints */
|
||||
if (lset_stack_not_empty) {
|
||||
if (lset_stack_count != 0) {
|
||||
/*
|
||||
* Check to see if the record should be processed
|
||||
* and activate breakpoint accordingly. If this
|
||||
@@ -624,7 +624,7 @@ long epicsShareAPI dbProcess(dbCommon *precord)
|
||||
/* process record */
|
||||
status = (*prset->process)(precord);
|
||||
/* Print record's fields if PRINT_MASK set in breakpoint field */
|
||||
if (lset_stack_not_empty) {
|
||||
if (lset_stack_count != 0) {
|
||||
dbPrint(precord);
|
||||
}
|
||||
all_done:
|
||||
|
||||
@@ -141,7 +141,7 @@ static long FIND_CONT_NODE(
|
||||
* normal record execution, i.e. when there aren't
|
||||
* any breakpoints set.
|
||||
*/
|
||||
long lset_stack_not_empty = 0;
|
||||
long lset_stack_count = 0;
|
||||
|
||||
/*
|
||||
* Stack--in which each entry represents a different
|
||||
@@ -154,7 +154,7 @@ long lset_stack_not_empty = 0;
|
||||
* operating with this stack.
|
||||
*/
|
||||
static ELLLIST lset_stack;
|
||||
static epicsMutexId bkpt_stack_sem;
|
||||
static epicsMutexId bkpt_stack_sem = 0;
|
||||
|
||||
/*
|
||||
* Stores the last lockset continued or stepped from.
|
||||
@@ -250,6 +250,18 @@ static long FIND_CONT_NODE(
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialise the breakpoint stack
|
||||
*/
|
||||
void epicsShareAPI dbBkptInit(void)
|
||||
{
|
||||
if (! bkpt_stack_sem) {
|
||||
bkpt_stack_sem = epicsMutexMustCreate();
|
||||
ellInit(&lset_stack);
|
||||
lset_stack_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add breakpoint to a lock set
|
||||
* 1. Convert name to address and check breakpoint mask.
|
||||
@@ -290,17 +302,6 @@ long epicsShareAPI dbb(const char *record_name)
|
||||
* Add lock set to the stack of lock sets that
|
||||
* contain breakpoints and/or stopped records.
|
||||
*/
|
||||
if (! lset_stack_not_empty) {
|
||||
/* initialize list and semaphore */
|
||||
bkpt_stack_sem = epicsMutexCreate();
|
||||
if (bkpt_stack_sem == 0) {
|
||||
printf(" BKPT> epicsMutexCreate failed\n");
|
||||
dbScanUnlock(precord);
|
||||
return(1);
|
||||
}
|
||||
ellInit(&lset_stack);
|
||||
lset_stack_not_empty = 1;
|
||||
}
|
||||
|
||||
epicsMutexMustLock(bkpt_stack_sem);
|
||||
|
||||
@@ -335,7 +336,9 @@ long epicsShareAPI dbb(const char *record_name)
|
||||
pnode->taskid = 0;
|
||||
pnode->step = 0;
|
||||
pnode->l_num = dbLockGetLockId(precord);
|
||||
|
||||
ellAdd(&lset_stack, (ELLNODE *)pnode);
|
||||
++lset_stack_count;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -604,11 +607,11 @@ static void dbBkptCont(dbCommon *precord)
|
||||
|
||||
/* Reset precord. (Since no records are at a breakpoint) */
|
||||
pnode->precord = NULL;
|
||||
}
|
||||
while (ellCount(&pnode->bp_list) != 0);
|
||||
} while (ellCount(&pnode->bp_list) != 0);
|
||||
|
||||
/* remove node from lockset stack */
|
||||
ellDelete(&lset_stack, (ELLNODE *)pnode);
|
||||
--lset_stack_count;
|
||||
|
||||
{
|
||||
/*
|
||||
@@ -634,15 +637,7 @@ static void dbBkptCont(dbCommon *precord)
|
||||
/* free list node */
|
||||
free(pnode);
|
||||
|
||||
/* if last node on stack ... */
|
||||
if (ellCount(&lset_stack) == 0) {
|
||||
/* Unset flag, delete stack semaphore */
|
||||
lset_stack_not_empty = 0;
|
||||
epicsMutexDestroy(bkpt_stack_sem);
|
||||
}
|
||||
|
||||
if (lset_stack_not_empty)
|
||||
epicsMutexUnlock(bkpt_stack_sem);
|
||||
epicsMutexUnlock(bkpt_stack_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -82,6 +82,7 @@ struct LS_LIST {
|
||||
|
||||
#define MAX_EP_COUNT 99999
|
||||
|
||||
epicsShareFunc void epicsShareAPI dbBkptInit(void);
|
||||
epicsShareFunc long epicsShareAPI dbb(const char *recordname);
|
||||
epicsShareFunc long epicsShareAPI dbd(const char *recordname);
|
||||
epicsShareFunc long epicsShareAPI dbc(const char *recordname);
|
||||
@@ -90,11 +91,11 @@ epicsShareFunc long epicsShareAPI dbstat(void);
|
||||
epicsShareFunc long epicsShareAPI dbp(
|
||||
const char *record_name, int interest_level);
|
||||
epicsShareFunc long epicsShareAPI dbap(const char *record_name);
|
||||
epicsShareFunc int epicsShareAPI dbBkpt(dbCommon *precord);
|
||||
epicsShareFunc void epicsShareAPI dbPrint(dbCommon *precord);
|
||||
epicsShareFunc int epicsShareAPI dbBkpt(struct dbCommon *precord);
|
||||
epicsShareFunc void epicsShareAPI dbPrint(struct dbCommon *precord);
|
||||
epicsShareFunc long epicsShareAPI dbprc(char *record_name);
|
||||
|
||||
extern long lset_stack_not_empty;
|
||||
extern long lset_stack_count;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -69,11 +69,10 @@ void dbChannelIO::destructor ( epicsGuard < epicsMutex > & guard )
|
||||
}
|
||||
|
||||
void dbChannelIO::destroy (
|
||||
epicsGuard < epicsMutex > & /* callbackControlGuard */,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
mutualExclusionGuard.assertIdenticalMutex ( this->mutex );
|
||||
this->serviceIO.destroyChannel ( mutualExclusionGuard, *this );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->serviceIO.destroyChannel ( guard, *this );
|
||||
// dont access this pointer after above call because
|
||||
// object nolonger exists
|
||||
}
|
||||
@@ -133,7 +132,6 @@ void dbChannelIO::subscribe (
|
||||
}
|
||||
|
||||
void dbChannelIO::ioCancel (
|
||||
epicsGuard < epicsMutex > & /* callbackControlGuard */,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & id )
|
||||
{
|
||||
@@ -232,9 +230,14 @@ void dbChannelIO::operator delete ( void * )
|
||||
__FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
void dbChannelIO::eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * /* pCallbackGuard */,
|
||||
epicsGuard < epicsMutex > & /* mutualExclusionGuard */ )
|
||||
void dbChannelIO::flush (
|
||||
epicsGuard < epicsMutex > & )
|
||||
{
|
||||
}
|
||||
|
||||
unsigned dbChannelIO::requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & )
|
||||
{
|
||||
return 0u;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ public:
|
||||
void destructor (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void destroy (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void callReadNotify (
|
||||
epicsGuard < epicsMutex > &,
|
||||
@@ -80,9 +79,10 @@ private:
|
||||
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void eliminateExcessiveSendBacklog (
|
||||
epicsGuard < epicsMutex > * pCallbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & );
|
||||
ioStatus read (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
@@ -100,7 +100,6 @@ private:
|
||||
unsigned type, unsigned long count,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid * );
|
||||
void ioCancel (
|
||||
epicsGuard < epicsMutex > & callbackControlGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & );
|
||||
void ioShow (
|
||||
|
||||
@@ -908,7 +908,7 @@ static void exitCallFunc(const iocshArgBuf *)
|
||||
|
||||
static void localRegister (void)
|
||||
{
|
||||
iocshRegister(&commentFuncDef,helpCallFunc);
|
||||
iocshRegister(&commentFuncDef,commentCallFunc);
|
||||
iocshRegister(&exitFuncDef,exitCallFunc);
|
||||
iocshRegister(&helpFuncDef,helpCallFunc);
|
||||
iocshRegister(&iocshCmdFuncDef,iocshCmdCallFunc);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#define epicsGuardh
|
||||
|
||||
#ifndef assert // allow use of epicsAssert.h
|
||||
# include <assert.h>
|
||||
# include <cassert>
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -25,29 +25,32 @@
|
||||
template < class T > class epicsGuardRelease;
|
||||
|
||||
// Automatically applies and releases the mutex.
|
||||
// This is for use in situations where C++ exceptions are possible.
|
||||
// This class is also useful in situations where
|
||||
// C++ exceptions are possible.
|
||||
template < class T >
|
||||
class epicsGuard {
|
||||
public:
|
||||
epicsGuard ( const epicsGuard & );
|
||||
epicsGuard ( T & );
|
||||
void assertIdenticalMutex ( const T & ) const;
|
||||
~epicsGuard ();
|
||||
private:
|
||||
T & targetMutex;
|
||||
T * _pTargetMutex;
|
||||
epicsGuard ( const epicsGuard & );
|
||||
epicsGuard & operator = ( const epicsGuard & );
|
||||
friend class epicsGuardRelease < T >;
|
||||
};
|
||||
|
||||
// Automatically releases and reapplies the mutex.
|
||||
// This is for use in situations where C++ exceptions are possible.
|
||||
// This class is also useful in situations where
|
||||
// C++ exceptions are possible.
|
||||
template < class T >
|
||||
class epicsGuardRelease {
|
||||
public:
|
||||
epicsGuardRelease ( epicsGuard < T > & );
|
||||
~epicsGuardRelease ();
|
||||
private:
|
||||
epicsGuard < T > & guard;
|
||||
epicsGuard < T > & _guard;
|
||||
T * _pTargetMutex;
|
||||
epicsGuardRelease ( const epicsGuardRelease & );
|
||||
epicsGuardRelease & operator = ( const epicsGuardRelease & );
|
||||
};
|
||||
@@ -63,43 +66,45 @@ public:
|
||||
|
||||
template < class T >
|
||||
inline epicsGuard < T > :: epicsGuard ( T & mutexIn ) :
|
||||
targetMutex ( mutexIn )
|
||||
_pTargetMutex ( & mutexIn )
|
||||
{
|
||||
this->targetMutex.lock ();
|
||||
}
|
||||
|
||||
template < class T >
|
||||
epicsGuard < T > :: epicsGuard ( const epicsGuard & guardIn ) :
|
||||
targetMutex ( guardIn.targetMutex )
|
||||
{
|
||||
this->targetMutex.lock ();
|
||||
_pTargetMutex->lock ();
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline epicsGuard < T > :: ~epicsGuard ()
|
||||
{
|
||||
this->targetMutex.unlock ();
|
||||
_pTargetMutex->unlock ();
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline void epicsGuard < T > :: assertIdenticalMutex (
|
||||
const T & mutexToVerify ) const
|
||||
{
|
||||
assert ( & this->targetMutex == & mutexToVerify );
|
||||
assert ( _pTargetMutex == & mutexToVerify );
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline epicsGuardRelease < T > ::
|
||||
epicsGuardRelease ( epicsGuard<T> & guardIn ) :
|
||||
guard ( guardIn )
|
||||
_guard ( guardIn ),
|
||||
_pTargetMutex ( guardIn._pTargetMutex )
|
||||
{
|
||||
this->guard.targetMutex.unlock ();
|
||||
// Setting the guard's _pTargetMutex to nill will
|
||||
// allow assertIdenticalMutex to catch situations
|
||||
// where a guard is being used and it has been
|
||||
// released, and also situations where ~epicsGuard ()
|
||||
// runs and an epicsGuardRelease is still referencing
|
||||
// the guard will be detected.
|
||||
_guard._pTargetMutex = 0;
|
||||
_pTargetMutex->unlock ();
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline epicsGuardRelease < T > :: ~epicsGuardRelease ()
|
||||
{
|
||||
this->guard.targetMutex.lock ();
|
||||
_pTargetMutex->lock ();
|
||||
_guard._pTargetMutex = _pTargetMutex;
|
||||
}
|
||||
|
||||
inline void epicsMutexNOOP::lock () {}
|
||||
|
||||
2
src/libCom/env/envSubr.c
vendored
2
src/libCom/env/envSubr.c
vendored
@@ -37,11 +37,11 @@
|
||||
*-***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <epicsStdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsStdlib.h"
|
||||
#include "epicsStdioRedirect.h"
|
||||
#include "errMdef.h"
|
||||
#include "envDefs.h"
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsThread.h"
|
||||
#include "epicsMutex.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsUnitTest.h"
|
||||
|
||||
static epicsMutexId testLock = 0;
|
||||
|
||||
@@ -25,6 +25,7 @@ static const char sccsID[] = "@(#) $Id$";
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbDefs.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "errlog.h"
|
||||
|
||||
@@ -48,6 +48,7 @@ static const unsigned uSecPerSec = 1000u * mSecPerSec;
|
||||
static const unsigned nSecPerSec = 1000u * uSecPerSec;
|
||||
static const unsigned nSecPerUSec = 1000u;
|
||||
static const unsigned secPerMin = 60u;
|
||||
static const unsigned nSecFracDigits = 9u;
|
||||
|
||||
static const unsigned tmStructEpochYear = 1900;
|
||||
|
||||
@@ -442,108 +443,185 @@ epicsTime::operator epicsTimeStamp () const
|
||||
return ts;
|
||||
}
|
||||
|
||||
// return pointer to trailing "%0<n>f" (<n> is a number) in a format string,
|
||||
// NULL if none; also return <n> and a pointer to the "f"
|
||||
static char *fracFormat (const char *pFormat, unsigned long *width)
|
||||
// Break up a format string into "<strftime prefix>%0<nnn>f<postfix>"
|
||||
// (where <nnn> in an unsigned integer)
|
||||
// Result:
|
||||
// A) Copies a prefix which is valid for ANSI strftime into the supplied
|
||||
// buffer setting the buffer to an empty string if no prefix is present.
|
||||
// B) Indicates whether a valid "%0<n>f]" is present or not and if so
|
||||
// specifying its nnnn
|
||||
// C) returning a pointer to the postfix (which might be passed again
|
||||
// to fracFormatFind.
|
||||
static const char * fracFormatFind (
|
||||
const char * const pFormat,
|
||||
char * const pPrefixBuf,
|
||||
const size_t prefixBufLen,
|
||||
bool & fracFmtFound,
|
||||
unsigned long & fracFmtWidth )
|
||||
{
|
||||
// initialize returned field width
|
||||
*width = 0;
|
||||
|
||||
// point at char past format string
|
||||
const char *ptr = pFormat + strlen (pFormat);
|
||||
|
||||
// allow trailing ws
|
||||
while (isspace (*(--ptr)));
|
||||
|
||||
// if (last) char not 'f', no match
|
||||
if (*ptr != 'f') return NULL;
|
||||
|
||||
// look for %f
|
||||
if ( *(ptr-1) == '%' ) {
|
||||
*width = 9;
|
||||
return (char *) (ptr-1);
|
||||
assert ( prefixBufLen > 1 );
|
||||
unsigned long width = ULONG_MAX;
|
||||
bool fracFound = false;
|
||||
const char * pAfter = pFormat;
|
||||
const char * pFmt = pFormat;
|
||||
while ( *pFmt != '\0' ) {
|
||||
if ( *pFmt == '%' ) {
|
||||
if ( pFmt[1] == '%' ) {
|
||||
pFmt++;
|
||||
}
|
||||
else if ( pFmt[1] == 'f' ) {
|
||||
fracFound = true;
|
||||
pAfter = & pFmt[2];
|
||||
break;
|
||||
}
|
||||
else {
|
||||
errno = 0;
|
||||
char * pAfterTmp;
|
||||
unsigned long result = strtoul ( pFmt + 1, & pAfterTmp, 10 );
|
||||
if ( errno == 0 && *pAfterTmp == 'f' && result > 0 ) {
|
||||
width = result;
|
||||
fracFound = true;
|
||||
pAfter = pAfterTmp + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pFmt++;
|
||||
pAfter = pFmt;
|
||||
}
|
||||
size_t len = pFmt - pFormat;
|
||||
if ( len < prefixBufLen ) {
|
||||
strncpy ( pPrefixBuf, pFormat, len );
|
||||
pPrefixBuf [ len ] = '\0';
|
||||
if ( fracFound ) {
|
||||
fracFmtFound = true;
|
||||
fracFmtWidth = width;
|
||||
}
|
||||
else {
|
||||
fracFmtFound = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
strncpy ( pPrefixBuf, "<invalid format>", prefixBufLen - 1 );
|
||||
pPrefixBuf [ prefixBufLen - 1 ] = '\0';
|
||||
fracFmtFound = false;
|
||||
pAfter = "";
|
||||
}
|
||||
|
||||
// skip digits, extracting <n> (must start with 0)
|
||||
while (isdigit (*(--ptr))); // NB, empty loop body
|
||||
if (*ptr != '%') {
|
||||
return NULL;
|
||||
}
|
||||
++ptr; // points to first digit, if any
|
||||
if (sscanf (ptr, "%lu", width) != 1) return NULL;
|
||||
|
||||
// if (prev) char not '%', no match
|
||||
if (*(--ptr) != '%') return NULL;
|
||||
|
||||
// return pointer to '%'
|
||||
return (char *) ptr;
|
||||
return pAfter;
|
||||
}
|
||||
|
||||
//
|
||||
// size_t epicsTime::strftime (char *pBuff, size_t bufLength, const char *pFormat)
|
||||
// size_t epicsTime::strftime ()
|
||||
//
|
||||
size_t epicsTime::strftime ( char *pBuff, size_t bufLength, const char *pFormat ) const
|
||||
size_t epicsTime::strftime (
|
||||
char * pBuff, size_t bufLength, const char * pFormat ) const
|
||||
{
|
||||
if ( bufLength == 0u ) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
// dont report EPOCH date if its an uninitialized time stamp
|
||||
// presume that EPOCH date is an uninitialized time stamp
|
||||
if ( this->secPastEpoch == 0 && this->nSec == 0u ) {
|
||||
strncpy ( pBuff, "<undefined>", bufLength );
|
||||
pBuff[bufLength-1] = '\0';
|
||||
return strlen ( pBuff );
|
||||
}
|
||||
|
||||
// copy format (needs to be writable)
|
||||
char format[256];
|
||||
strncpy ( format, pFormat, sizeof ( format ) );
|
||||
if ( format [sizeof(format)-1] != '\0' ) {
|
||||
strncpy ( pBuff, "<invalid format>", bufLength );
|
||||
pBuff[bufLength-1] = '\0';
|
||||
return strlen ( pBuff );
|
||||
}
|
||||
|
||||
// look for "%0<n>f" at the end (used for fractional second formatting)
|
||||
unsigned long fracWid;
|
||||
char *fracPtr = fracFormat (format, &fracWid);
|
||||
|
||||
// if found, hide from strftime
|
||||
if (fracPtr != NULL) *fracPtr = '\0';
|
||||
|
||||
// format all but fractional seconds
|
||||
local_tm_nano_sec tmns = *this;
|
||||
size_t numChar = ::strftime (pBuff, bufLength, format, &tmns.ansi_tm);
|
||||
if (numChar == 0 || fracPtr == NULL) return numChar;
|
||||
|
||||
// check there are enough chars for the fractional seconds
|
||||
if (numChar + fracWid < bufLength)
|
||||
{
|
||||
char * p = pBuff + numChar;
|
||||
size_t len = bufLength - numChar;
|
||||
if ( tmns.nSec < nSecPerSec ) {
|
||||
// divisors for fraction (see below)
|
||||
const int div[9+1] = {(int)1e9,(int)1e8,(int)1e7,(int)1e6,(int)1e5,
|
||||
(int)1e4,(int)1e3,(int)1e2,(int)1e1,(int)1e0};
|
||||
|
||||
// round and convert nanosecs to integer of correct range
|
||||
int ndp = fracWid <= 9 ? fracWid : 9;
|
||||
int frac = ((tmns.nSec + div[ndp]/2) % ((int)1e9)) / div[ndp];
|
||||
|
||||
// restore fractional format and format fraction
|
||||
*fracPtr = '%';
|
||||
*(format + strlen (format) - 1) = 'u';
|
||||
epicsSnprintf ( p, len, fracPtr, frac );
|
||||
p[len-1] = '\0';
|
||||
char * pBufCur = pBuff;
|
||||
const char * pFmt = pFormat;
|
||||
size_t bufLenLeft = bufLength;
|
||||
while ( *pFmt != '\0' && bufLenLeft > 1 ) {
|
||||
// look for "%0<n>f" at the end (used for fractional second formatting)
|
||||
char strftimePrefixBuf [256];
|
||||
bool fracFmtFound;
|
||||
unsigned long fracWid;
|
||||
pFmt = fracFormatFind (
|
||||
pFmt,
|
||||
strftimePrefixBuf, sizeof ( strftimePrefixBuf ),
|
||||
fracFmtFound, fracWid );
|
||||
|
||||
// nothing more in the string, then quit
|
||||
if ( ! ( strftimePrefixBuf[0] != '\0' || fracFmtFound ) ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
strncpy ( p, "OVF", len );
|
||||
p[len-1] = '\0';
|
||||
return strlen ( pBuff );
|
||||
// all but fractional seconds use strftime formatting
|
||||
if ( strftimePrefixBuf[0] != '\0' ) {
|
||||
local_tm_nano_sec tmns = *this;
|
||||
size_t strftimeNumChar = :: strftime (
|
||||
pBufCur, bufLenLeft, strftimePrefixBuf, & tmns.ansi_tm );
|
||||
pBufCur [ strftimeNumChar ] = '\0';
|
||||
pBufCur += strftimeNumChar;
|
||||
bufLenLeft -= strftimeNumChar;
|
||||
}
|
||||
|
||||
// fractional seconds formating
|
||||
if ( fracFmtFound && bufLenLeft > 1 ) {
|
||||
if ( fracWid > nSecFracDigits ) {
|
||||
fracWid = nSecFracDigits;
|
||||
}
|
||||
// verify that there are enough chars left for the fractional seconds
|
||||
if ( fracWid < bufLenLeft )
|
||||
{
|
||||
local_tm_nano_sec tmns = *this;
|
||||
if ( tmns.nSec < nSecPerSec ) {
|
||||
// divisors for fraction (see below)
|
||||
static const unsigned long div[] = {
|
||||
static_cast < unsigned long > ( 1e9 ),
|
||||
static_cast < unsigned long > ( 1e8 ),
|
||||
static_cast < unsigned long > ( 1e7 ),
|
||||
static_cast < unsigned long > ( 1e6 ),
|
||||
static_cast < unsigned long > ( 1e5 ),
|
||||
static_cast < unsigned long > ( 1e4 ),
|
||||
static_cast < unsigned long > ( 1e3 ),
|
||||
static_cast < unsigned long > ( 1e2 ),
|
||||
static_cast < unsigned long > ( 1e1 ),
|
||||
static_cast < unsigned long > ( 1e0 )
|
||||
};
|
||||
// round and convert nanosecs to integer of correct range
|
||||
unsigned long frac = tmns.nSec + div[fracWid] / 2;
|
||||
frac %= static_cast < unsigned long > ( 1e9 );
|
||||
frac /= div[fracWid];
|
||||
char fracFormat[32];
|
||||
sprintf ( fracFormat, "%%0%uu", fracWid );
|
||||
int status = epicsSnprintf ( pBufCur, bufLenLeft, fracFormat, frac );
|
||||
if ( status > 0 ) {
|
||||
unsigned long nChar = static_cast < unsigned long > ( status );
|
||||
if ( nChar >= bufLenLeft ) {
|
||||
nChar = bufLenLeft - 1;
|
||||
}
|
||||
pBufCur[nChar] = '\0';
|
||||
pBufCur += nChar;
|
||||
bufLenLeft -= nChar;
|
||||
}
|
||||
}
|
||||
else {
|
||||
static const char pOVF [] = "OVF";
|
||||
size_t tmpLen = sizeof ( pOVF ) - 1;
|
||||
if ( tmpLen >= bufLenLeft ) {
|
||||
tmpLen = bufLenLeft - 1;
|
||||
}
|
||||
strncpy ( pBufCur, pOVF, tmpLen );
|
||||
pBufCur[tmpLen] = '\0';
|
||||
pBufCur += tmpLen;
|
||||
bufLenLeft -= tmpLen;
|
||||
}
|
||||
}
|
||||
else {
|
||||
static const char pDoesntFit [] = "************";
|
||||
size_t tmpLen = sizeof ( pDoesntFit ) - 1;
|
||||
if ( tmpLen >= bufLenLeft ) {
|
||||
tmpLen = bufLenLeft - 1;
|
||||
}
|
||||
strncpy ( pBufCur, pDoesntFit, tmpLen );
|
||||
pBufCur[tmpLen] = '\0';
|
||||
pBufCur += tmpLen;
|
||||
bufLenLeft -= tmpLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return numChar + fracWid;
|
||||
return pBufCur - pBuff;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -44,7 +44,7 @@ inline void WireGet < epicsFloat64 > (
|
||||
inline void WireGet (
|
||||
const epicsUInt8 * pWireSrc, epicsOldString & dst )
|
||||
{
|
||||
memcpy ( & dst, pWireSrc, sizeof ( dst ) );
|
||||
memcpy ( dst, pWireSrc, sizeof ( dst ) );
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -68,7 +68,7 @@ inline void WireSet < epicsFloat64 > (
|
||||
inline void WireSet (
|
||||
const epicsOldString & src, epicsUInt8 * pWireDst )
|
||||
{
|
||||
memcpy ( pWireDst, & src, sizeof ( src ) );
|
||||
memcpy ( pWireDst, src, sizeof ( src ) );
|
||||
}
|
||||
|
||||
template <>
|
||||
|
||||
@@ -118,11 +118,20 @@ inline void WireGet < epicsFloat64 > (
|
||||
dst = tmp._f;
|
||||
}
|
||||
|
||||
#if defined ( __GNUC__ ) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 0 )
|
||||
template <>
|
||||
inline void WireGet < epicsOldString > (
|
||||
const epicsUInt8 * pWireSrc, epicsOldString & dst )
|
||||
{
|
||||
memcpy ( dst, pWireSrc, sizeof ( dst ) );
|
||||
}
|
||||
#else
|
||||
inline void WireGet (
|
||||
const epicsUInt8 * pWireSrc, epicsOldString & dst )
|
||||
{
|
||||
memcpy ( & dst, pWireSrc, sizeof ( dst ) );
|
||||
memcpy ( dst, pWireSrc, sizeof ( dst ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline void WireSet < epicsFloat64 > (
|
||||
@@ -147,11 +156,20 @@ inline void WireSet < epicsFloat64 > (
|
||||
# endif
|
||||
}
|
||||
|
||||
#if defined ( __GNUC__ ) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 0 )
|
||||
template <>
|
||||
inline void WireSet < epicsOldString > (
|
||||
const epicsOldString & src, epicsUInt8 * pWireDst )
|
||||
{
|
||||
memcpy ( pWireDst, src, sizeof ( src ) );
|
||||
}
|
||||
#else
|
||||
inline void WireSet (
|
||||
const epicsOldString & src, epicsUInt8 * pWireDst )
|
||||
{
|
||||
memcpy ( pWireDst, & src, sizeof ( src ) );
|
||||
memcpy ( pWireDst, src, sizeof ( src ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline void AlignedWireGet < epicsUInt16 > (
|
||||
|
||||
18
src/libCom/osi/os/hpux/epicsMath.h
Normal file
18
src/libCom/osi/os/hpux/epicsMath.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*************************************************************************\
|
||||
* 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 Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef epicsMathh
|
||||
#define epicsMathh
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define finite(D) (isfinite(D) != 0)
|
||||
|
||||
#endif /* epicsMathh */
|
||||
@@ -69,9 +69,5 @@ typedef int osiSocklen_t;
|
||||
|
||||
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE (0xffffffff)
|
||||
#endif
|
||||
|
||||
#endif /*osdSockH*/
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
|
||||
#include "unixFileName.h"
|
||||
|
||||
#endif /* osiFileNameH */
|
||||
#endif /* osiFileNameH */
|
||||
@@ -285,9 +285,6 @@ static long vxDevReadProbe (unsigned wordSize, volatile const void *ptr, void *p
|
||||
{
|
||||
long status;
|
||||
|
||||
/*
|
||||
* this global variable exists in the nivxi library
|
||||
*/
|
||||
status = vxMemProbe ((char *)ptr, VX_READ, wordSize, (char *) pValue);
|
||||
if (status!=OK) {
|
||||
return S_dev_noDevice;
|
||||
@@ -304,10 +301,7 @@ static long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *
|
||||
{
|
||||
long status;
|
||||
|
||||
/*
|
||||
* this global variable exists in the nivxi library
|
||||
*/
|
||||
status = vxMemProbe ((char *)ptr, VX_READ, wordSize, (char *) pValue);
|
||||
status = vxMemProbe ((char *)ptr, VX_WRITE, wordSize, (char *) pValue);
|
||||
if (status!=OK) {
|
||||
return S_dev_noDevice;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <time.h>
|
||||
#include <objLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* The following not defined in an vxWorks header */
|
||||
int sysClkRateGet(void);
|
||||
|
||||
@@ -42,14 +44,17 @@ void epicsEventDestroy(epicsEventId id)
|
||||
epicsEventWaitStatus epicsEventWaitWithTimeout(
|
||||
epicsEventId id, double timeOut)
|
||||
{
|
||||
int rate = sysClkRateGet();
|
||||
int status;
|
||||
int ticks;
|
||||
|
||||
if(timeOut<=0.0) {
|
||||
if (timeOut <= 0.0) {
|
||||
ticks = 0;
|
||||
} else if (timeOut >= (double) INT_MAX / rate) {
|
||||
ticks = WAIT_FOREVER;
|
||||
} else {
|
||||
ticks = timeOut*sysClkRateGet();
|
||||
if(ticks<=0) ticks = 1;
|
||||
ticks = timeOut * rate;
|
||||
if (ticks<=0) ticks = 1;
|
||||
}
|
||||
status = semTake((SEM_ID)id,ticks);
|
||||
if(status==OK) return(epicsEventWaitOK);
|
||||
|
||||
@@ -24,13 +24,14 @@ static STATUS outRoutine(char *buffer, int nchars, int outarg) {
|
||||
int free = poutStr->free;
|
||||
int len;
|
||||
|
||||
if(free<=1) { /*let fioFormatV continue to count length*/
|
||||
if (free < 1) { /*let fioFormatV continue to count length*/
|
||||
return OK;
|
||||
} else if (free > 1) {
|
||||
len = min(free-1, nchars);
|
||||
strncpy(poutStr->str, buffer, len);
|
||||
poutStr->str += len;
|
||||
poutStr->free -= len;
|
||||
}
|
||||
len = min(free-1, nchars);
|
||||
strncpy(poutStr->str, buffer, len);
|
||||
poutStr->str += len;
|
||||
poutStr->free -= len;
|
||||
/*make sure final string is null terminated*/
|
||||
*poutStr->str = 0;
|
||||
return OK;
|
||||
|
||||
@@ -244,10 +244,10 @@ inline void AlignedWireGet ( const T & src, T & dst )
|
||||
// copy through union here
|
||||
// a) prevents over-aggresive optimization under strict aliasing rules
|
||||
// b) doesnt preclude extra copy operation being optimized away
|
||||
WireAlias < T > tmp;
|
||||
tmp._o = src;
|
||||
AlignedWireGet ( tmp._u, tmp._u );
|
||||
dst = tmp._o;
|
||||
WireAlias < T > srcu, dstu;
|
||||
srcu._o = src;
|
||||
AlignedWireGet ( srcu._u, dstu._u );
|
||||
dst = dstu._o;
|
||||
}
|
||||
|
||||
template < class T >
|
||||
@@ -256,10 +256,10 @@ inline void AlignedWireSet ( const T & src, T & dst )
|
||||
// copy through union here
|
||||
// a) prevents over-aggresive optimization under strict aliasing rules
|
||||
// b) doesnt preclude extra copy operation being optimized away
|
||||
WireAlias < T > tmp;
|
||||
tmp._o = src;
|
||||
AlignedWireSet ( tmp._u, tmp._u );
|
||||
dst = tmp._o;
|
||||
WireAlias < T > srcu, dstu;
|
||||
srcu._o = src;
|
||||
AlignedWireSet ( srcu._u, dstu._u );
|
||||
dst = dstu._o;
|
||||
}
|
||||
|
||||
#include "osdWireFormat.h"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "epicsThread.h"
|
||||
#include "epicsEvent.h"
|
||||
@@ -143,7 +144,7 @@ MAIN(epicsEventTest)
|
||||
epicsEventId event;
|
||||
int status;
|
||||
|
||||
testPlan(9);
|
||||
testPlan(10);
|
||||
|
||||
event = epicsEventMustCreate(epicsEventEmpty);
|
||||
|
||||
@@ -160,6 +161,11 @@ MAIN(epicsEventTest)
|
||||
testOk(status == 0,
|
||||
"epicsEventWaitWithTimeout(event, 2.0) = %d", status);
|
||||
|
||||
epicsEventSignal(event);
|
||||
status = epicsEventWaitWithTimeout(event,DBL_MAX);
|
||||
testOk(status == 0,
|
||||
"epicsEventWaitWithTimeout(event, DBL_MAX) = %d", status);
|
||||
|
||||
epicsEventSignal(event);
|
||||
status = epicsEventTryWait(event);
|
||||
testOk(status == 0,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Authors: Jeff HIll and Marty Kraimer
|
||||
* Authors: Jeff Hill, Marty Kraimer and Andrew Johnson
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
@@ -46,7 +46,7 @@ MAIN(epicsTimeTest)
|
||||
const int nTimes = 10;
|
||||
const double precisionEPICS = 1.0 / nSecPerSec;
|
||||
|
||||
testPlan(7 + nTimes * 18);
|
||||
testPlan(10 + nTimes * 18);
|
||||
|
||||
const epicsTime begin = epicsTime::getCurrent();
|
||||
{
|
||||
@@ -95,6 +95,19 @@ MAIN(epicsTimeTest)
|
||||
pFormat = "%S.%05f";
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "00.09877") == 0, "'%s' => '%s'", pFormat, buf);
|
||||
|
||||
pFormat = "%S.%05f %S.%05f";
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "00.09877 00.09877") == 0, "'%s' => '%s'", pFormat, buf);
|
||||
|
||||
char smbuf[5];
|
||||
pFormat = "%S.%05f";
|
||||
et.strftime(smbuf, sizeof(smbuf), pFormat);
|
||||
testOk(strcmp(smbuf, "00.*") == 0, "'%s' => '%s'", pFormat, smbuf);
|
||||
|
||||
pFormat = "%%S.%%05f";
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "%S.%05f") == 0, "'%s' => '%s'", pFormat, buf);
|
||||
}
|
||||
|
||||
{ // invalidFormatTest
|
||||
|
||||
@@ -106,6 +106,7 @@ void testAccuracy ()
|
||||
static const unsigned nTimers = 25u;
|
||||
delayVerify *pTimers[nTimers];
|
||||
unsigned i;
|
||||
unsigned timerCount = 0;
|
||||
|
||||
testDiag ( "Testing timer accuracy" );
|
||||
|
||||
@@ -114,8 +115,9 @@ void testAccuracy ()
|
||||
|
||||
for ( i = 0u; i < nTimers; i++ ) {
|
||||
pTimers[i] = new delayVerify ( i * 0.1 + delayVerifyOffset, queue );
|
||||
assert ( pTimers[i] );
|
||||
timerCount += pTimers[i] ? 1 : 0;
|
||||
}
|
||||
testOk1 ( timerCount == nTimers );
|
||||
|
||||
expireCount = nTimers;
|
||||
for ( i = 0u; i < nTimers; i++ ) {
|
||||
@@ -142,7 +144,7 @@ public:
|
||||
cancelVerify ( epicsTimerQueue & );
|
||||
void start ( const epicsTime &expireTime );
|
||||
void cancel ();
|
||||
static unsigned cancellCount;
|
||||
static unsigned cancelCount;
|
||||
static unsigned expireCount;
|
||||
protected:
|
||||
virtual ~cancelVerify ();
|
||||
@@ -152,6 +154,9 @@ private:
|
||||
static epicsSingleton < tsFreeList < class cancelVerify, 0x20 > > pFreeList;
|
||||
};
|
||||
|
||||
unsigned cancelVerify::cancelCount;
|
||||
unsigned cancelVerify::expireCount;
|
||||
|
||||
cancelVerify::cancelVerify ( epicsTimerQueue &queueIn ) :
|
||||
timer ( queueIn.createTimer () )
|
||||
{
|
||||
@@ -170,7 +175,7 @@ inline void cancelVerify::start ( const epicsTime &expireTime )
|
||||
inline void cancelVerify::cancel ()
|
||||
{
|
||||
this->timer.cancel ();
|
||||
++cancelVerify::cancellCount;
|
||||
++cancelVerify::cancelCount;
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus cancelVerify::expire ( const epicsTime & )
|
||||
@@ -183,9 +188,6 @@ epicsTimerNotify::expireStatus cancelVerify::expire ( const epicsTime & )
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
unsigned cancelVerify::cancellCount = 0;
|
||||
unsigned cancelVerify::expireCount = 0;
|
||||
|
||||
//
|
||||
// verify that expire() won't be called after the timer is cancelled
|
||||
//
|
||||
@@ -194,6 +196,10 @@ void testCancel ()
|
||||
static const unsigned nTimers = 25u;
|
||||
cancelVerify *pTimers[nTimers];
|
||||
unsigned i;
|
||||
unsigned timerCount = 0;
|
||||
|
||||
cancelVerify::cancelCount = 0;
|
||||
cancelVerify::expireCount = 0;
|
||||
|
||||
testDiag ( "Testing timer cancellation" );
|
||||
|
||||
@@ -202,10 +208,13 @@ void testCancel ()
|
||||
|
||||
for ( i = 0u; i < nTimers; i++ ) {
|
||||
pTimers[i] = new cancelVerify ( queue );
|
||||
assert ( pTimers[i] );
|
||||
timerCount += pTimers[i] ? 1 : 0;
|
||||
}
|
||||
assert ( cancelVerify::expireCount == 0 );
|
||||
assert ( cancelVerify::cancellCount == 0 );
|
||||
testOk1 ( timerCount == nTimers );
|
||||
if ( ! testOk1 ( cancelVerify::expireCount == 0 ) )
|
||||
testDiag ( "expireCount = %u", cancelVerify::expireCount );
|
||||
if ( ! testOk1 ( cancelVerify::cancelCount == 0 ) )
|
||||
testDiag ( "cancelCount = %u", cancelVerify::cancelCount );
|
||||
|
||||
testDiag ( "starting %d timers", nTimers );
|
||||
epicsTime exp = epicsTime::getCurrent () + 4.0;
|
||||
@@ -213,19 +222,19 @@ void testCancel ()
|
||||
pTimers[i]->start ( exp );
|
||||
}
|
||||
testOk1 ( cancelVerify::expireCount == 0 );
|
||||
testOk1 ( cancelVerify::cancellCount == 0 );
|
||||
testOk1 ( cancelVerify::cancelCount == 0 );
|
||||
|
||||
testDiag ( "cancelling timers" );
|
||||
for ( i = 0u; i < nTimers; i++ ) {
|
||||
pTimers[i]->cancel ();
|
||||
}
|
||||
testOk1 ( cancelVerify::expireCount == 0 );
|
||||
testOk1 ( cancelVerify::cancellCount == nTimers );
|
||||
testOk1 ( cancelVerify::cancelCount == nTimers );
|
||||
|
||||
testDiag ( "waiting until after timers should have expired" );
|
||||
epicsThreadSleep ( 5.0 );
|
||||
testOk1 ( cancelVerify::expireCount == 0 );
|
||||
testOk1 ( cancelVerify::cancellCount == nTimers );
|
||||
testOk1 ( cancelVerify::cancelCount == nTimers );
|
||||
|
||||
epicsThreadSleep ( 1.0 );
|
||||
queue.release ();
|
||||
@@ -245,6 +254,8 @@ private:
|
||||
static epicsSingleton < tsFreeList < class expireDestroVerify, 0x20 > > pFreeList;
|
||||
};
|
||||
|
||||
unsigned expireDestroVerify::destroyCount;
|
||||
|
||||
expireDestroVerify::expireDestroVerify ( epicsTimerQueue & queueIn ) :
|
||||
timer ( queueIn.createTimer () )
|
||||
{
|
||||
@@ -267,8 +278,6 @@ epicsTimerNotify::expireStatus expireDestroVerify::expire ( const epicsTime & )
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
unsigned expireDestroVerify::destroyCount = 0;
|
||||
|
||||
//
|
||||
// verify that a timer can be destroyed in expire
|
||||
//
|
||||
@@ -277,6 +286,8 @@ void testExpireDestroy ()
|
||||
static const unsigned nTimers = 25u;
|
||||
expireDestroVerify *pTimers[nTimers];
|
||||
unsigned i;
|
||||
unsigned timerCount = 0;
|
||||
expireDestroVerify::destroyCount = 0;
|
||||
|
||||
testDiag ( "Testing timer destruction in expire()" );
|
||||
|
||||
@@ -285,9 +296,10 @@ void testExpireDestroy ()
|
||||
|
||||
for ( i = 0u; i < nTimers; i++ ) {
|
||||
pTimers[i] = new expireDestroVerify ( queue );
|
||||
assert ( pTimers[i] );
|
||||
timerCount += pTimers[i] ? 1 : 0;
|
||||
}
|
||||
assert ( expireDestroVerify::destroyCount == 0 );
|
||||
testOk1 ( timerCount == nTimers );
|
||||
testOk1 ( expireDestroVerify::destroyCount == 0 );
|
||||
|
||||
testDiag ( "starting %d timers", nTimers );
|
||||
epicsTime cur = epicsTime::getCurrent ();
|
||||
@@ -368,6 +380,7 @@ void testPeriodic ()
|
||||
static const unsigned nTimers = 25u;
|
||||
periodicVerify *pTimers[nTimers];
|
||||
unsigned i;
|
||||
unsigned timerCount = 0;
|
||||
|
||||
testDiag ( "Testing periodic timers" );
|
||||
|
||||
@@ -376,8 +389,9 @@ void testPeriodic ()
|
||||
|
||||
for ( i = 0u; i < nTimers; i++ ) {
|
||||
pTimers[i] = new periodicVerify ( queue );
|
||||
assert ( pTimers[i] );
|
||||
timerCount += pTimers[i] ? 1 : 0;
|
||||
}
|
||||
testOk1 ( timerCount == nTimers );
|
||||
|
||||
testDiag ( "starting %d timers", nTimers );
|
||||
epicsTime cur = epicsTime::getCurrent ();
|
||||
@@ -400,7 +414,7 @@ void testPeriodic ()
|
||||
|
||||
MAIN(epicsTimerTest)
|
||||
{
|
||||
testPlan(33);
|
||||
testPlan(40);
|
||||
testAccuracy ();
|
||||
testCancel ();
|
||||
testExpireDestroy ();
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
program sncExample
|
||||
double v;
|
||||
assign v to "{user}:xxxExample";
|
||||
assign v to "{user}:aiExample";
|
||||
monitor v;
|
||||
|
||||
ss ss1
|
||||
{
|
||||
state low
|
||||
{
|
||||
when(v>5.0)
|
||||
{
|
||||
printf("changing to high\n");
|
||||
} state high
|
||||
when(delay(.1))
|
||||
{
|
||||
} state low
|
||||
}
|
||||
state high
|
||||
{
|
||||
when(v<=5.0)
|
||||
{
|
||||
printf("changing to low\n");
|
||||
} state low
|
||||
when(delay(.1))
|
||||
{
|
||||
} state high
|
||||
}
|
||||
ss ss1 {
|
||||
state init {
|
||||
when (delay(10)) {
|
||||
printf("sncExample: Startup delay over\n");
|
||||
} state low
|
||||
}
|
||||
state low {
|
||||
when (v > 5.0) {
|
||||
printf("sncExample: Changing to high\n");
|
||||
} state high
|
||||
}
|
||||
state high {
|
||||
when (v <= 5.0) {
|
||||
printf("sncExample: Changing to low\n");
|
||||
} state low
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2006 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.
|
||||
\*************************************************************************/
|
||||
/* iocInit.c ioc initialization */
|
||||
/* base/src/db $Id$ */
|
||||
/* $Id$ */
|
||||
/* Author: Marty Kraimer Date: 06-01-91 */
|
||||
|
||||
|
||||
@@ -27,6 +26,7 @@
|
||||
#include "dbBase.h"
|
||||
#include "caeventmask.h"
|
||||
#include "dbAddr.h"
|
||||
#include "dbBkpt.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "link.h"
|
||||
#include "dbLock.h"
|
||||
@@ -125,6 +125,7 @@ int epicsShareAPI iocInit()
|
||||
interruptAccept=TRUE; initHooks(initHookAfterInterruptAccept);
|
||||
epicsThreadSleep(1.0);
|
||||
|
||||
dbBkptInit();
|
||||
|
||||
/* Start up CA server */
|
||||
rsrv_init();
|
||||
|
||||
@@ -46,9 +46,9 @@ case $sysname in
|
||||
HP-UX )
|
||||
os=hpux
|
||||
cpu=`uname -m`
|
||||
case $cpu in 9000/[34678]??)
|
||||
cpu=m68k
|
||||
;;
|
||||
case $cpu in
|
||||
9000/[346]??) cpu=m68k ;;
|
||||
9000/[78]??) cpu=parisc ;;
|
||||
esac
|
||||
echo ${os}-${cpu}${suffix}
|
||||
;;
|
||||
|
||||
@@ -33,6 +33,8 @@ sub GetEpicsHostArch { # no args
|
||||
} elsif ($arch =~ m/MSWin32-x86/) { return "win32-x86";
|
||||
} elsif ($arch =~ m/cygwin/) { return "cygwin-x86";
|
||||
} elsif ($arch =~ m/PA-RISC1.1/) { return "hpux-parisc";
|
||||
} elsif ($arch =~ m/PA-RISC2.0/) { return "hpux-parisc";
|
||||
} elsif ($arch =~ m/alpha-dec_osf/) { return "osf-alpha";
|
||||
} elsif ($arch =~ m/darwin/) {
|
||||
my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname();
|
||||
if ($cpu =~ m/Power Macintosh/) { return "darwin-ppc"; }
|
||||
|
||||
Reference in New Issue
Block a user