Compare commits

...

59 Commits

Author SHA1 Message Date
Janet B. Anderson
919850d693 R3.14.9 2007-02-05 16:31:45 +00:00
Andrew Johnson
894cab79e4 Revised and improved NPTL error description. 2007-02-05 16:04:43 +00:00
Andrew Johnson
b38dd45b03 Revert to -CVS after -RC1 tag applied. 2007-01-26 20:37:25 +00:00
Andrew Johnson
d468d7f462 R3.14.9-RC1 2007-01-26 20:29:41 +00:00
Andrew Johnson
8dfea0ce50 Added description of the NPTL Abort issue. 2007-01-26 19:03:56 +00:00
Andrew Johnson
cda58de74a Win32 doesn't support line buffering, so fflush after every printf. 2007-01-25 21:21:05 +00:00
Andrew Johnson
2d031c46a2 Fixed bad example code. 2007-01-24 22:05:16 +00:00
Janet B. Anderson
5e4b2d03ad More changes for osf-alpha from Kazuro Furukawa. 2007-01-22 15:25:47 +00:00
Jeff Hill
db067c9780 1) replaced elimateExcessiveSendBacklog with
requestMessageBytesPending and flush
2) Removed callback control guards from this interface
2007-01-11 22:07:47 +00:00
Jeff Hill
3ec09adf20 added code to catch bugs where a guard is used when it is released 2007-01-11 22:04:44 +00:00
Jeff Hill
57e9e59714 fixed a bug where the callback control gaurd was used from a different thread
than the one that created it
2007-01-11 22:02:47 +00:00
Jeff Hill
cde78f0b70 fixed a bug where the callback control gaurd was used from a different thread
than the one that created it
2007-01-11 21:45:58 +00:00
Jeff Hill
6ed4f091b2 1) replaced elimateExcessiveSendBacklog with
requestMessageBytesPending and flush
2) Removed callback control guards from this interface
2007-01-11 21:43:40 +00:00
Jeff Hill
bb625c7f25 flushBlockThreshold no longer takes a message size argument 2007-01-11 21:38:59 +00:00
Jeff Hill
47f5203faa improved doc on preemptive callback mode 2007-01-11 21:37:43 +00:00
Jeff Hill
287743f140 1) replaced elimateExcessiveSendBacklog with
requestMessageBytesPending and flush
2) Removed callback control guards from this interface
2007-01-11 21:33:31 +00:00
Janet B. Anderson
a841a79194 Added changes from Kazuro FURUKAWA (modified for R3.14.9). 2007-01-09 19:02:15 +00:00
Andrew Johnson
9e2c64ecfd Make vxDevWriteProbe() actually do a write - Mantis #280. 2007-01-09 00:21:43 +00:00
Jeff Hill
6fb7d5255b made comnsistent with workaround for T202 issue 2007-01-09 00:00:12 +00:00
Jeff Hill
00fc1ce769 workaround for T202 issue 2007-01-08 23:59:56 +00:00
W. Eric Norum
852afdc4d8 Create properly-formatted POSIX TZ environment variable from EPICS_TIMEZONE. 2007-01-08 15:11:31 +00:00
Andrew Johnson
ae06349563 Make fracFormatFind static.
Removed 'const' from epicsTime::strftime pointer args to match prototype,
needed by Sun C++ complier which doesn't find the symbol otherwise.
2007-01-02 19:37:57 +00:00
Andrew Johnson
a710bff122 Fixed testPlan, added test for %% in strtfime format strings. 2007-01-02 19:30:04 +00:00
Jeff Hill
fe2b0e599d fix dll exports 2006-12-22 21:56:46 +00:00
Jeff Hill
255751f420 export shared lib symbols 2006-12-22 21:36:13 +00:00
Jeff Hill
7787f5906d use temporaries 2006-12-22 21:32:10 +00:00
Jeff Hill
de34f5de03 removed workaround for problems in visual C++ 8.0 2006-12-22 19:43:59 +00:00
Jeff Hill
40bb69f5fd workaround for problems in visual C++ 8.0 2006-12-22 19:43:04 +00:00
Jeff Hill
6ce83fc9e4 fixed throw specification 2006-12-22 19:35:37 +00:00
Jeff Hill
e0b4715c98 fixed mantis 279 - epicsTimeToStrftime problem with %06f format 2006-12-22 18:57:53 +00:00
Jeff Hill
e989af9b01 fix for dec c++ compiler detected issue 2006-12-21 22:15:42 +00:00
Andrew Johnson
3c1b10dfce Clear out old issues. 2006-12-21 20:09:13 +00:00
Andrew Johnson
27342322ec Cygwin make issue. 2006-12-21 19:39:03 +00:00
Andrew Johnson
3d3ad47e47 Added test using timeout = DBL_MAX. 2006-12-21 17:11:33 +00:00
Andrew Johnson
f2154fec35 Fix for Mantis #254. 2006-12-21 16:47:56 +00:00
Andrew Johnson
6bed83c70e OSF-Alpha. 2006-12-21 15:52:04 +00:00
Andrew Johnson
4f2cb790e5 Additional instances needed for 3.14.9-pre2 to load. 2006-12-21 15:44:41 +00:00
Andrew Johnson
15f3358e39 Prevent vxWorks 5.4 builds of altivec targets. 2006-12-20 23:28:12 +00:00
Andrew Johnson
285f1e03ba Wind River don't support osf-alpha as a vxWorks host architecture. 2006-12-20 23:25:56 +00:00
Janet B. Anderson
03e9ce2855 Moved ca to immediately follow libCom. 2006-12-20 21:21:44 +00:00
Janet B. Anderson
c5563644db Removed code that makes each depend file a target. 2006-12-20 15:25:36 +00:00
Janet B. Anderson
75aa6bbf97 Deleted unused definition. 2006-12-19 22:34:28 +00:00
Janet B. Anderson
8b8b61b797 Removed obsolete comment. 2006-12-19 22:24:59 +00:00
Janet B. Anderson
8540fdd813 Added gcc version requirement. 2006-12-19 21:46:26 +00:00
Janet B. Anderson
23c1596d22 Applied patches for recognizing external dependencies from B. Franksen. 2006-12-19 19:43:02 +00:00
Janet B. Anderson
9e292ca085 Applied patches for recognizing external dependencies from B. Franksen.
Print one file dependancy per line.
2006-12-19 19:34:42 +00:00
Janet B. Anderson
410eca1633 Removing os/alpha directory and adding osf directory and files. 2006-12-19 17:14:08 +00:00
Janet B. Anderson
44d742e147 Initail version from Kazuro Furukawa. 2006-12-19 17:08:02 +00:00
Janet B. Anderson
abe127c6f9 Initial version from Kazuro Furukawa. 2006-12-19 17:08:01 +00:00
Janet B. Anderson
beacc52519 Changes for osf-alpha from Kazuro Furukawa. 2006-12-19 17:03:02 +00:00
Janet B. Anderson
5a9e8d156e Initial version from Kazuro Furukawa. 2006-12-19 17:02:01 +00:00
Janet B. Anderson
239cd857a8 Added osf-alpha files from Kazuro FURUKAWA (modified for R3.14.9). 2006-12-19 16:57:05 +00:00
Janet B. Anderson
dea42bdf66 Initial version. 2006-12-19 16:50:54 +00:00
Andrew Johnson
196f107432 Breakpoint initialization and cleanup. 2006-12-19 16:29:38 +00:00
Andrew Johnson
2a7c2e9d26 Breakpoint initialization and cleanup. 2006-12-19 16:20:47 +00:00
Andrew Johnson
556724f050 Fixed warning. 2006-12-12 21:04:19 +00:00
Andrew Johnson
0f0ff1eec0 Fix for when size=1. 2006-12-12 20:44:53 +00:00
Andrew Johnson
b937142ff3 Fixes for vxWorks: permit multiple runs, don't use assert(). 2006-12-12 19:58:52 +00:00
Andrew Johnson
a6527232cf Revert to -CVS 2006-12-11 22:32:14 +00:00
73 changed files with 1010 additions and 649 deletions

View 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++
#==========================

View File

@@ -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

View File

@@ -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 ""

View File

@@ -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

View 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

View 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

View File

@@ -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))

View 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

View 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)

View 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

View 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

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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

View 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>

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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() );

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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 );
}
}
}

View File

@@ -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 (

View File

@@ -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 );

View File

@@ -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 (

View File

@@ -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

View File

@@ -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

View File

@@ -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 (

View File

@@ -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 &notify, ioid * );
virtual void ioCancel (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & );
void ioShow (

View File

@@ -129,8 +129,13 @@ void netiiu::flushRequest (
{
}
void netiiu::eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > *,
unsigned netiiu::requestMessageBytesPending (
epicsGuard < epicsMutex > & )
{
return 0u;
}
void netiiu::flush (
epicsGuard < epicsMutex > & )
{
}

View File

@@ -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 &,

View File

@@ -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 (

View File

@@ -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 &,

View File

@@ -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

View File

@@ -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)

View File

@@ -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 );

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
/*

View File

@@ -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 ) {

View File

@@ -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

View File

@@ -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 (

View File

@@ -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 &,

View File

@@ -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 (

View File

@@ -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);
}
}

View File

@@ -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:

View File

@@ -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);
}
/*

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -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 &notify, ioid * );
void ioCancel (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & );
void ioShow (

View File

@@ -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);

View File

@@ -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 () {}

View File

@@ -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"

View File

@@ -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;

View File

@@ -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"

View File

@@ -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;
}
//

View File

@@ -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 <>

View File

@@ -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 > (

View 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 */

View File

@@ -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*/

View File

@@ -18,4 +18,4 @@
#include "unixFileName.h"
#endif /* osiFileNameH */
#endif /* osiFileNameH */

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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"

View File

@@ -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,

View File

@@ -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

View File

@@ -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 ();

View File

@@ -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
}
}

View File

@@ -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();

View File

@@ -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}
;;

View File

@@ -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"; }