Compare commits
114 Commits
PSI-7.0.8.
...
PSI-7.0.9.
| Author | SHA1 | Date | |
|---|---|---|---|
| 1804bcef7d | |||
| 990e08c737 | |||
| f501a2810e | |||
| 997746e5e2 | |||
| 09f96d056a | |||
| 84f49ad149 | |||
| db003e8a10 | |||
| 1732c9440a | |||
| ff565267e5 | |||
| acf4c92697 | |||
| 93ba98cdca | |||
| f2a03e906b | |||
|
|
e4ebc01401 | ||
|
|
6ea6ae633b | ||
|
|
9fac52fa58 | ||
|
|
fc5d3c9a5c | ||
| c75ad2673e | |||
| b97a35fec8 | |||
|
|
350570134e | ||
|
|
72f3e75c8d | ||
|
|
90f97a7037 | ||
|
|
fd86f0ff04 | ||
|
|
bcc6cb96ae | ||
|
|
a4bc0db6e6 | ||
|
|
48ebe2c64e | ||
|
|
9f788996dc | ||
|
|
13d6ca598c | ||
| ee1a49045a | |||
|
|
78f263f359 | ||
| 43e75e3901 | |||
| d6481e190f | |||
| 2e77bc8cc1 | |||
| ea7459084e | |||
| ddc49e9f79 | |||
| a3a99e4d14 | |||
| 12144fe267 | |||
| c5315d95b8 | |||
| 74d231b04f | |||
| 23521e0a08 | |||
| 55791ef470 | |||
| 7b2fb669ec | |||
| 312a602952 | |||
|
|
131578124b | ||
|
|
7bd3e7aa2e | ||
|
|
86154953f5 | ||
|
|
07572ab025 | ||
|
|
0733beae50 | ||
|
|
a3d8531008 | ||
|
|
7a6e11cae0 | ||
|
|
7384351181 | ||
|
|
890cbc2c0d | ||
|
|
2612b47c3f | ||
|
|
f4c474eb77 | ||
|
|
1735a821db | ||
| bc27476554 | |||
| 9c1334ae15 | |||
|
|
9481deacb0 | ||
| 8f1a3888c6 | |||
| c9183b5241 | |||
| c3f57ee818 | |||
| 27f4261dfb | |||
| 5eb9997791 | |||
| bfc2f832ec | |||
| f09b235fce | |||
| ece031c88b | |||
| cbbbd67843 | |||
| 57c0295024 | |||
|
|
8f77e941c7 | ||
|
|
c76395abc6 | ||
|
|
1d19ba4cc2 | ||
|
|
144f9756ea | ||
|
|
48eed22f3b | ||
|
|
8ac2c87156 | ||
|
|
0d2ffcd97f | ||
|
|
c8eccfcb8f | ||
|
|
6fb40b02fe | ||
|
|
dad0ee9c89 | ||
|
|
065fe7cab6 | ||
|
|
e4ad4becde | ||
|
|
1cd141c540 | ||
| 72026a27a0 | |||
|
|
9fb820b46e | ||
|
|
721e9cc3a7 | ||
|
|
0186836449 | ||
|
|
b90ab7de13 | ||
|
|
333be085c0 | ||
|
|
169948967f | ||
|
|
5a11954c51 | ||
|
|
9f8a8b9c1f | ||
|
|
d0cf47cd6f | ||
|
|
f4aee8e6b7 | ||
| dac620a708 | |||
| 4ee766b6b1 | |||
| 5143258011 | |||
|
|
ead8b7e82b | ||
|
|
ccbe608c4a | ||
|
|
c68d5a8dc3 | ||
|
|
cfa5ad3195 | ||
|
|
d7a0edf121 | ||
|
|
61fa360461 | ||
|
|
01fc9f83a9 | ||
|
|
ccc730332a | ||
|
|
b948c03675 | ||
|
|
538a3d2f09 | ||
|
|
3724420dc6 | ||
|
|
6b1d30408f | ||
|
|
b615232788 | ||
|
|
763760c58b | ||
|
|
f0d98b9b9a | ||
|
|
60239498a1 | ||
|
|
166157dcbf | ||
|
|
29da5d67e1 | ||
|
|
8e8fb81062 | ||
|
|
448bde1798 |
@@ -52,8 +52,6 @@ environment:
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- CMP: vs2015
|
||||
- CMP: vs2013
|
||||
- CMP: vs2012
|
||||
- CMP: vs2010
|
||||
- CMP: gcc
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
# TODO: static linking w/ readline isn't working. Bypass auto-detect
|
||||
@@ -67,11 +65,6 @@ platform:
|
||||
# Matrix configuration: exclude sets of jobs
|
||||
matrix:
|
||||
exclude:
|
||||
# VS2012 and older installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
CMP: vs2012
|
||||
- platform: x64
|
||||
CMP: vs2010
|
||||
# Exclude more jobs to reduce build time
|
||||
# Skip 32-bit for "middle-aged" compilers
|
||||
- platform: x86
|
||||
|
||||
@@ -59,8 +59,6 @@ environment:
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- CMP: vs2015
|
||||
- CMP: vs2013
|
||||
- CMP: vs2012
|
||||
- CMP: vs2010
|
||||
- CMP: gcc
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
# TODO: static linking w/ readline isn't working. Bypass auto-detect
|
||||
@@ -74,11 +72,6 @@ platform:
|
||||
# Matrix configuration: exclude sets of jobs
|
||||
matrix:
|
||||
exclude:
|
||||
# VS2012 and older installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
CMP: vs2012
|
||||
- platform: x64
|
||||
CMP: vs2010
|
||||
# Exclude more jobs to reduce build time
|
||||
# Skip 32-bit for "middle-aged" compilers
|
||||
- platform: x86
|
||||
|
||||
175
.github/workflows/ci-scripts-build.yml
vendored
175
.github/workflows/ci-scripts-build.yml
vendored
@@ -45,14 +45,15 @@ jobs:
|
||||
CI_CROSS_TARGETS: ${{ matrix.cross }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
TEST: ${{ matrix.test }}
|
||||
CHOCO: llvm
|
||||
strategy:
|
||||
fail-fast: false
|
||||
fail-fast: true
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc-12
|
||||
name: "Ub-22 gcc-12 c++20 Werror"
|
||||
- os: ubuntu-24.04
|
||||
cmp: gcc
|
||||
name: "Ub-24 gcc-13 c++20 Werror"
|
||||
# Turn all warnings into errors,
|
||||
# except for those we could not fix (yet).
|
||||
# Remove respective -Wno-error=... flag once it is fixed.
|
||||
@@ -73,79 +74,79 @@ jobs:
|
||||
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3'
|
||||
CMD_LDFLAGS=-Wl,-z,relro"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "windows-x64-mingw"
|
||||
name: "Ub-20 gcc + MinGW"
|
||||
name: "Ub-22 gcc + MinGW"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
cross: "windows-x64-mingw"
|
||||
name: "Ub-20 gcc + MinGW, static"
|
||||
name: "Ub-22 gcc + MinGW, static"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
name: "Ub-20 gcc C++11, static"
|
||||
name: "Ub-22 gcc C++11, static"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
extra: "CMD_CFLAGS=-funsigned-char CMD_CXXFLAGS=-funsigned-char"
|
||||
name: "Ub-20 gcc unsigned char"
|
||||
name: "Ub-22 gcc unsigned char"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
name: "Ub-20 clang"
|
||||
name: "Ub-22 clang"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
name: "Ub-20 clang C++11"
|
||||
name: "Ub-22 clang C++11"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-pc686-qemu@5"
|
||||
name: "Ub-20 gcc + RT-5.1 pc686"
|
||||
name: "Ub-22 gcc + RT-5.1 pc686"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-beatnik@5"
|
||||
test: NO
|
||||
name: "Ub-20 gcc + RT-5.1 beatnik"
|
||||
name: "Ub-22 gcc + RT-5.1 beatnik"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-xilinx_zynq_a9_qemu@5"
|
||||
test: NO
|
||||
name: "Ub-20 gcc + RT-5.1 xilinx_zynq_a9_qemu"
|
||||
name: "Ub-22 gcc + RT-5.1 xilinx_zynq_a9_qemu"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
cross: "RTEMS-uC5282@5"
|
||||
test: NO
|
||||
name: "Ub-20 gcc + RT-5.1 uC5282"
|
||||
name: "Ub-22 gcc + RT-5.1 uC5282"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
name: "Ub-20 gcc + RT-4.10"
|
||||
name: "Ub-22 gcc + RT-4.10"
|
||||
cross: "RTEMS-pc386-qemu@4.10"
|
||||
test: NO
|
||||
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
name: "Ub-20 gcc + RT-4.9"
|
||||
name: "Ub-22 gcc + RT-4.9"
|
||||
cross: "RTEMS-pc386-qemu@4.9"
|
||||
|
||||
- os: macos-latest
|
||||
@@ -170,10 +171,16 @@ jobs:
|
||||
configuration: debug
|
||||
name: "Win2019 MSC-19, debug"
|
||||
|
||||
- os: windows-2019
|
||||
- os: windows-2022
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
name: "Win2019 mingw"
|
||||
name: "Win2022 mingw"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: clang+vs2019
|
||||
configuration: default
|
||||
name: "Win2019 clang-cl"
|
||||
choco: ["llvm"]
|
||||
|
||||
# Cross builds
|
||||
|
||||
@@ -239,10 +246,15 @@ jobs:
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
#- name: "CentOS-7"
|
||||
# image: centos:7
|
||||
# cmp: gcc
|
||||
# configuration: default
|
||||
- name: "CentOS-8"
|
||||
image: centos:8
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
- name: "Rocky-9"
|
||||
image: rockylinux:9
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
|
||||
- name: "Fedora-33"
|
||||
image: fedora:33
|
||||
@@ -255,47 +267,29 @@ jobs:
|
||||
configuration: default
|
||||
|
||||
steps:
|
||||
- name: "Build newer Git"
|
||||
# actions/checkout@v2 wants git >=2.18
|
||||
# centos:7 has 1.8
|
||||
if: matrix.image=='centos:7'
|
||||
- name: "Fix repo URLs on CentOS-8"
|
||||
# centos:8 is frozen, repos are in the vault
|
||||
if: matrix.image=='centos:8'
|
||||
run: |
|
||||
yum -y install curl make gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
|
||||
curl https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.29.0.tar.gz | tar -xz
|
||||
cd git-*
|
||||
make -j2 prefix=/usr/local all
|
||||
make prefix=/usr/local install
|
||||
cd ..
|
||||
rm -rf git-*
|
||||
type -a git
|
||||
git --version
|
||||
sed -i -e "s|mirrorlist=|#mirrorlist=|" \
|
||||
-e "s|#baseurl=http://mirror|baseurl=http://vault|" \
|
||||
/etc/yum.repos.d/CentOS-Linux-{BaseOS,AppStream,Extras,Plus}.repo
|
||||
- name: "Redhat setup"
|
||||
run: |
|
||||
dnfyum() {
|
||||
dnf -y "$@" || yum -y "$@"
|
||||
return $?
|
||||
}
|
||||
dnfyum install python3 gdb make perl gcc-c++ glibc-devel readline-devel ncurses-devel perl-devel perl-Test-Simple
|
||||
git --version || dnfyum install git
|
||||
# rather than just bite the bullet and link python3 -> python,
|
||||
# people would rather just break all existing scripts...
|
||||
[ -e /usr/bin/python ] || ln -sf python3 /usr/bin/python
|
||||
python --version
|
||||
dnf -y install python3 gdb make perl gcc-c++ glibc-devel readline-devel ncurses-devel perl-devel perl-Test-Simple
|
||||
git --version || dnf -y install git
|
||||
python3 --version
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
if: matrix.image!='centos:7'
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@node16
|
||||
if: matrix.image=='centos:7'
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
run: python3 .ci/cue.py prepare
|
||||
- name: Build main module
|
||||
run: python .ci/cue.py build
|
||||
run: python3 .ci/cue.py build
|
||||
- name: Run main module tests
|
||||
run: python .ci/cue.py -T 20M test
|
||||
run: python3 .ci/cue.py -T 20M test
|
||||
- name: Upload tapfiles Artifact
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -305,4 +299,55 @@ jobs:
|
||||
if-no-files-found: ignore
|
||||
- name: Collect and show test results
|
||||
if: ${{ always() }}
|
||||
run: python .ci/cue.py -T 5M test-results
|
||||
run: python3 .ci/cue.py -T 5M test-results
|
||||
|
||||
build-docker:
|
||||
name: Docker CentOS-7
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CMP: gcc
|
||||
BCFG: default
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Run...
|
||||
run: |
|
||||
env > env.list
|
||||
cat <<EOF > runit.sh
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
cd /io
|
||||
id
|
||||
|
||||
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo
|
||||
sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo
|
||||
sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo
|
||||
yum -y install epel-release
|
||||
yum -y install \
|
||||
curl make gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker \
|
||||
python3 gdb make perl gcc-c++ glibc-devel readline-devel ncurses-devel perl-devel perl-Test-Simple \
|
||||
libevent-devel sudo re2c
|
||||
[ -e /usr/bin/python ] || ln -sf /usr/bin/python3 /usr/bin/python
|
||||
|
||||
# fake out cue.py
|
||||
ln -s /bin/true /usr/bin/apt-get
|
||||
|
||||
# quiet warnings spam from perl
|
||||
export LANG=C
|
||||
|
||||
python --version
|
||||
python .ci/cue.py prepare
|
||||
python .ci/cue.py build
|
||||
python .ci/cue.py -T 15M test
|
||||
python .ci/cue.py test-results
|
||||
EOF
|
||||
chmod +x runit.sh
|
||||
docker run --rm --quiet \
|
||||
--pull=always \
|
||||
--env-file env.list \
|
||||
-v `pwd`:/io \
|
||||
centos:7 \
|
||||
/io/runit.sh
|
||||
|
||||
280
configure/CONFIG.msvcCommon
Normal file
280
configure/CONFIG.msvcCommon
Normal file
@@ -0,0 +1,280 @@
|
||||
# MSVC/clang-cl compiler defaults
|
||||
|
||||
CMPLR_CLASS = msvc
|
||||
|
||||
OPT_WHOLE_PROGRAM = YES
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
WINLINK = link
|
||||
|
||||
RCCMD = $(MSVC_PREFIX)rc$(MSVC_SUFFIX) -nologo -l 0x409 $(INCLUDES) -fo $@ $<
|
||||
|
||||
ARCMD = $(MSVC_PREFIX)lib$(MSVC_SUFFIX) -nologo -verbose -out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
|
||||
|
||||
#
|
||||
# Configure OS vendor C compiler
|
||||
CC = cl
|
||||
|
||||
# OS vendor c preprocessor
|
||||
CPP = $(CC) -nologo -C -E
|
||||
|
||||
# Configure OS vendor C++ compiler
|
||||
#
|
||||
# -EHsc - generate code for exceptions
|
||||
# -GR - generate code for run time type identification
|
||||
#
|
||||
CCC = $(CC) -EHsc -GR
|
||||
|
||||
# Override CONFIG.gnuCommon settings for cross builds.
|
||||
GNU = NO
|
||||
HDEPENDS_METHOD = MKMF
|
||||
|
||||
# Compiler flags for C files (C++ is below)
|
||||
|
||||
#
|
||||
# -W<d> display warnings at level d
|
||||
# -W4 is for maximum (lint type) warnings
|
||||
# -W3 is for production quality warnings
|
||||
# -W2 displays significant warnings
|
||||
# -W1 is the default and shows severe warnings only
|
||||
# -w<d><n> Set warning C<n> to be shown at level <d>
|
||||
WARN_CFLAGS_YES = -W3
|
||||
WARN_CFLAGS_NO = -W1
|
||||
|
||||
#
|
||||
# -Ox maximum optimizations
|
||||
# -GL whole program optimization
|
||||
# -Oy- re-enable creation of frame pointers
|
||||
OPT_CFLAGS_YES_YES = -Ox -GL -Oy-
|
||||
OPT_CFLAGS_YES_NO = -Ox -Oy-
|
||||
OPT_CFLAGS_YES = $(OPT_CFLAGS_YES_$(OPT_WHOLE_PROGRAM))
|
||||
|
||||
#
|
||||
# -Z7 generate C7 compatible debugging information (inside .obj)
|
||||
# -RTCsu enable run-time error checks
|
||||
OPT_CFLAGS_NO = -Z7 -RTCsu
|
||||
|
||||
# specify object file name and location
|
||||
OBJ_CFLAG = -Fo
|
||||
|
||||
#
|
||||
# the following options are required when
|
||||
# vis c++ compiles the code (and includes
|
||||
# the header files)
|
||||
#
|
||||
# -MT static multithreaded C RTL
|
||||
# -MTd static multithreaded C RTL (debug version)
|
||||
# -MD multithreaded C RTL in DLL
|
||||
# -MDd multithreaded C RTL in DLL (debug version)
|
||||
BUILD_DLL_CFLAGS_NO =
|
||||
BUILD_DLL_CFLAGS_YES = -DEPICS_BUILD_DLL
|
||||
BUILD_DLL_CFLAGS = $(BUILD_DLL_CFLAGS_$(SHARED_LIBRARIES))
|
||||
VISC_CFLAGS_DEBUG_NO = d
|
||||
VISC_CFLAGS_DEBUG_YES =
|
||||
VISC_CFLAGS_DEBUG = $(VISC_CFLAGS_DEBUG_$(HOST_OPT))
|
||||
STATIC_CFLAGS_YES= -MT$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS)
|
||||
STATIC_CFLAGS_NO= -MD$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS) -DEPICS_CALL_DLL
|
||||
|
||||
# Other compiler flags, used for CPP, C and C++
|
||||
#
|
||||
# -FC - Show absolute path of source file in diagnostics
|
||||
# -D__STDC__=0 gives us both:
|
||||
# 1) define STDC for code (pretend ANSI conformance)
|
||||
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
|
||||
# because MS uses: if __STDC__ ... disable many nice things
|
||||
#
|
||||
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
|
||||
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
|
||||
|
||||
# Compiler flags for C++ files
|
||||
|
||||
#
|
||||
# -W<n> disable warnings from levels > n
|
||||
# -w<n><m> set warning m to level n
|
||||
# -w44355 "'this' used in the base initializer list"
|
||||
# -w44344 "behavior change: use of explicit template arguments results in ..."
|
||||
# -w44251 "class needs to have dll-interface to be used by clients of ..."
|
||||
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
|
||||
WARN_CXXFLAGS_NO = -W1
|
||||
|
||||
# Silence tr1 namespace deprecation warnings
|
||||
WARN_CXXFLAGS += -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||
|
||||
#
|
||||
# -Ox maximum optimizations
|
||||
# -GL whole program optimization
|
||||
# -Oy- re-enable creation of frame pointers
|
||||
OPT_CXXFLAGS_YES_YES = -Ox -GL -Oy-
|
||||
OPT_CXXFLAGS_YES_NO = -Ox -Oy-
|
||||
OPT_CXXFLAGS_YES = $(OPT_CXXFLAGS_YES_$(OPT_WHOLE_PROGRAM))
|
||||
|
||||
#
|
||||
# -Z7 generate C7 compatible debugging information (inside .obj)
|
||||
# -RTCsu enable run-time error checks
|
||||
OPT_CXXFLAGS_NO = -RTCsu -Z7
|
||||
|
||||
# specify object file name and location
|
||||
OBJ_CXXFLAG = -Fo
|
||||
|
||||
#
|
||||
# the following options are required when
|
||||
# vis c++ compiles the code (and includes
|
||||
# the header files)
|
||||
#
|
||||
# -MT static multithreaded C RTL
|
||||
# -MTd static multithreaded C RTL (debug version)
|
||||
# -MD multithreaded C RTL in DLL
|
||||
# -MDd multithreaded C RTL in DLL (debug version)
|
||||
STATIC_CXXFLAGS_YES= -MT$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS)
|
||||
STATIC_CXXFLAGS_NO= -MD$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS) -DEPICS_CALL_DLL
|
||||
|
||||
STATIC_LDLIBS_YES=ws2_32.lib advapi32.lib user32.lib kernel32.lib winmm.lib dbghelp.lib
|
||||
STATIC_LDLIBS_NO=
|
||||
STATIC_LDFLAGS=
|
||||
RANLIB=
|
||||
|
||||
# add -profile here to run the ms profiler
|
||||
# -LTCG whole program optimization
|
||||
# -incremental:no full linking
|
||||
# -fixed:no generate relocatable code
|
||||
# -version:<major>.<minor> - only 2 components allowed, 0-65535 each
|
||||
# -debug generate debugging info
|
||||
LINK_OPT_FLAGS_WHOLE_YES = -LTCG
|
||||
LINK_OPT_FLAGS_YES = $(LINK_OPT_FLAGS_WHOLE_$(OPT_WHOLE_PROGRAM))
|
||||
LINK_OPT_FLAGS_YES += -incremental:no -opt:ref
|
||||
LINK_OPT_FLAGS_YES += -release $(PROD_VERSION:%=-version:%)
|
||||
LINK_OPT_FLAGS_NO = -debug -incremental:no -fixed:no
|
||||
OPT_LDFLAGS = $(LINK_OPT_FLAGS_$(HOST_OPT))
|
||||
|
||||
LIB_OPT_FLAGS_YES = $(LINK_OPT_FLAGS_WHOLE_$(OPT_WHOLE_PROGRAM))
|
||||
LIB_OPT_LDFLAGS = $(LIB_OPT_FLAGS_$(HOST_OPT))
|
||||
|
||||
ARCH_DEP_CFLAGS=
|
||||
SHRLIB_CFLAGS=
|
||||
|
||||
OS_CLASS=WIN32
|
||||
POSIX=NO
|
||||
|
||||
# ifdef WIN32 looks better that ifeq ($(OS_CLASS),WIN32) ??
|
||||
WIN32=1
|
||||
|
||||
EXE=.exe
|
||||
OBJ=.obj
|
||||
RES=.res
|
||||
|
||||
# MS Visual C++ doesn't recognize *.cc as a C++ source file,
|
||||
# so C++ compiles get the flag -TP
|
||||
COMPILER_CXXFLAGS = -TP
|
||||
|
||||
# Operating system flags
|
||||
OP_SYS_CFLAGS =
|
||||
OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
|
||||
|
||||
# Files and flags needed to link DLLs (used in RULES_BUILD)
|
||||
WIN32_DLLFLAGS = -subsystem:windows -dll $(OPT_LDFLAGS) \
|
||||
$(USR_LDFLAGS) $(CMD_LDFLAGS) $(TARGET_LDFLAGS) $(LIB_LDFLAGS)
|
||||
|
||||
# Specify dll .def file only if it exists
|
||||
DLL_DEF_FLAG = $(addprefix -def:,$(wildcard ../$(addsuffix .def,$*)))
|
||||
|
||||
# A WIN32 dll has three parts:
|
||||
# x.dll: the real dll (SHRLIBNAME)
|
||||
# x.lib: what you link to progs that use the dll (DLLSTUB_LIBNAME)
|
||||
# x.exp: what you need to build the dll (in no variable)
|
||||
LINK.shrlib = $(WINLINK) -nologo $(WIN32_DLLFLAGS) -out:$@ \
|
||||
-implib:$(@:%$(SHRLIB_SUFFIX)=%$(LIB_SUFFIX)) \
|
||||
$(DLL_DEF_FLAG) $(LIBRARY_LD_OBJS) $(LIBRARY_LD_RESS) $(SHRLIB_LDLIBS)
|
||||
|
||||
# Adjust names of libraries to build
|
||||
SHRLIB_SUFFIX_BASE = .dll
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
SHRLIBNAME_YES = $(BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
|
||||
LOADABLE_SHRLIBNAME = $(LOADABLE_BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
|
||||
TESTSHRLIBNAME_YES = $(TESTBUILD_LIBRARY:%=%$(SHRLIB_SUFFIX_BASE))
|
||||
|
||||
# When SHARED_LIBRARIES is YES we are building a DLL shared library.
|
||||
# When SHARED_LIBRARIES is NO we are building an object library
|
||||
DLLSTUB_SUFFIX = .lib
|
||||
DLLSTUB_LIBNAME_YES = $(BUILD_LIBRARY:%=%.lib)
|
||||
DLLSTUB_LIBNAME = $(DLLSTUB_LIBNAME_$(SHARED_LIBRARIES))
|
||||
TESTDLLSTUB_LIBNAME_YES = $(TESTBUILD_LIBRARY:%=%.lib)
|
||||
TESTDLLSTUB_LIBNAME = $(TESTDLLSTUB_LIBNAME_$(SHARED_LIBRARIES))
|
||||
|
||||
LIB_PREFIX=
|
||||
LIB_SUFFIX=.lib
|
||||
LIBNAME_NO = $(BUILD_LIBRARY:%=%.lib)
|
||||
LIBNAME = $(LIBNAME_$(SHARED_LIBRARIES))
|
||||
TESTLIBNAME_NO = $(TESTBUILD_LIBRARY:%=%.lib)
|
||||
TESTLIBNAME = $(TESTLIBNAME_$(SHARED_LIBRARIES))
|
||||
|
||||
# dll install location
|
||||
INSTALL_SHRLIB = $(INSTALL_BIN)
|
||||
|
||||
|
||||
#--------------------------------------------------
|
||||
# Products dependancy definitions
|
||||
|
||||
PROD_DEPLIBS = $(foreach lib, $(PROD_LIBS) $(USR_LIBS), \
|
||||
$(firstword $(wildcard \
|
||||
$(addsuffix /$(DLLSTUB_PREFIX)$(lib)$(DLLSTUB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(SHRLIB_PREFIX)$(lib)*$(SHRLIB_SUFFIX_BASE)*, \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(LIB_PREFIX)$(lib)$(LIB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
) $(addsuffix /$(BUILDLIB_PREFIX)$(lib)$(BUILDLIB_SUFFIX), \
|
||||
$(if $(filter $(lib),$(TESTLIBRARY)),.,$(INSTALL_LIB)))))
|
||||
|
||||
|
||||
PROD_LDLIBS += $($*_DEPLIBS) $(PROD_DEPLIBS)
|
||||
PROD_LDLIBS += $(addsuffix .lib, \
|
||||
$($*_SYS_LIBS) $(PROD_SYS_LIBS) $(USR_SYS_LIBS))
|
||||
|
||||
LDLIBS_STATIC_YES = LDLIBS
|
||||
LDLIBS_SHARED_NO = LDLIBS
|
||||
PROD_LDLIBS += $(STATIC_LDLIBS) \
|
||||
$($(firstword $(LDLIBS_STATIC_$(STATIC_BUILD)) \
|
||||
$(LDLIBS_SHARED_$(SHARED_LIBRARIES))))
|
||||
|
||||
#--------------------------------------------------
|
||||
# Libraries dependancy definitions
|
||||
|
||||
# libs that we need to link the DLL with
|
||||
# (it isnt necessary to rebuild the dll if these change)
|
||||
|
||||
SHRLIB_DEPLIBS = $(foreach lib, $(LIB_LIBS) $(USR_LIBS), \
|
||||
$(firstword $(wildcard \
|
||||
$(addsuffix /$(DLLSTUB_PREFIX)$(lib)$(DLLSTUB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(SHRLIB_PREFIX)$(lib)*$(SHRLIB_SUFFIX_BASE)*, \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(LIB_PREFIX)$(lib)$(LIB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
) $(addsuffix /$(BUILDLIB_PREFIX)$(lib)$(BUILDLIB_SUFFIX), \
|
||||
$(if $(filter $(lib),$(TESTLIBRARY)),.,$(INSTALL_LIB)))))
|
||||
|
||||
|
||||
SHRLIB_LDLIBS += $($*_DLL_DEPLIBS) $($*_DEPLIBS) $(SHRLIB_DEPLIBS)
|
||||
SHRLIB_LDLIBS += $(addsuffix .lib, \
|
||||
$($*_SYS_DLL_LIBS) \
|
||||
$($*_SYS_LIBS) $(LIB_SYS_LIBS) $(USR_SYS_LIBS) )
|
||||
|
||||
#--------------------------------------------------
|
||||
# Linker definition
|
||||
LINK.cpp = $(WINLINK) -nologo $(STATIC_LDFLAGS) $(LDFLAGS) $(PROD_LDFLAGS) \
|
||||
-out:$@ $(PROD_LD_OBJS) $(PROD_LD_RESS) $(PROD_LDLIBS)
|
||||
|
||||
#--------------------------------------------------
|
||||
# UseManifestTool.pl checks MS Visual c++ compiler version number to
|
||||
# decide whether or not to use the Manifest Tool command to embed the
|
||||
# linker created .manifest file into a library or product target.
|
||||
# useManifestTool.pl returns 0(don't use) or 1(use).
|
||||
#
|
||||
MT.exe = $(MSVC_PREFIX)mt$(MSVC_SUFFIX) -nologo -manifest $@.manifest
|
||||
MT_DLL_COMMAND1 = $(MT.exe) "-outputresource:$@;\#2"
|
||||
MT_EXE_COMMAND_YES =
|
||||
MT_EXE_COMMAND_NO = $(MT.exe) "-outputresource:$@;\#1"
|
||||
MT_EXE_COMMAND1 = $(MT_EXE_COMMAND_$(STATIC_BUILD))
|
||||
MT_DLL_COMMAND = $(MT_DLL_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
|
||||
MT_EXE_COMMAND = $(MT_EXE_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
|
||||
@@ -48,11 +48,11 @@ EPICS_VERSION = 7
|
||||
EPICS_REVISION = 0
|
||||
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 8
|
||||
EPICS_MODIFICATION = 9
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included in the official EPICS version number if zero
|
||||
EPICS_PATCH_LEVEL = 2
|
||||
EPICS_PATCH_LEVEL = 1
|
||||
|
||||
# Immediately after an official release the EPICS_PATCH_LEVEL is incremented
|
||||
# and the -DEV suffix is added (similar to the Maven -SNAPSHOT versions)
|
||||
@@ -71,6 +71,3 @@ endif
|
||||
EPICS_SHORT_VERSION=$(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)$(EPICS_PATCH_VSTRING)
|
||||
EPICS_VERSION_NUMBER=$(EPICS_SHORT_VERSION)$(EPICS_DEV_SNAPSHOT)$(EPICS_SITE_VSTRING)
|
||||
EPICS_VERSION_STRING="EPICS Version $(EPICS_VERSION_NUMBER)"
|
||||
|
||||
# Provide this in case anyone is still using the old name
|
||||
COMMIT_DATE="-no-date-"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
EPICS_CA_MAJOR_VERSION = 4
|
||||
EPICS_CA_MINOR_VERSION = 14
|
||||
EPICS_CA_MAINTENANCE_VERSION = 4
|
||||
EPICS_CA_MAINTENANCE_VERSION = 6
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Version number for the database APIs and shared library
|
||||
|
||||
EPICS_DATABASE_MAJOR_VERSION = 3
|
||||
EPICS_DATABASE_MINOR_VERSION = 23
|
||||
EPICS_DATABASE_MINOR_VERSION = 24
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 1
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Version number for the libcom APIs and shared library
|
||||
|
||||
EPICS_LIBCOM_MAJOR_VERSION = 3
|
||||
EPICS_LIBCOM_MINOR_VERSION = 23
|
||||
EPICS_LIBCOM_MINOR_VERSION = 24
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 1
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
@@ -92,3 +92,6 @@ EPICS_IOC_LOG_FILE_NAME=
|
||||
EPICS_IOC_LOG_FILE_COMMAND=
|
||||
EPICS_IOC_LOG_FILE_LIMIT=1000000
|
||||
|
||||
# Set to 'YES' to call abort() rather than suspend the current thread
|
||||
# when an assert() fails
|
||||
EPICS_ABORT_ON_ASSERT=NO
|
||||
|
||||
@@ -9,8 +9,8 @@ STD_CXXFLAGS = -std=c++20
|
||||
|
||||
# Fix bug in gcc-toolset-11 calling the old assembler
|
||||
ifneq ($(filter %-11,$(TOOLSET)),)
|
||||
TARGET_CPPFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
TARGET_LDFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
CPPFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
LDFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
endif
|
||||
|
||||
ifneq (($(TOOLSET)),)
|
||||
|
||||
@@ -9,8 +9,8 @@ STD_CXXFLAGS = -std=c++20
|
||||
|
||||
# Fix bug in gcc-toolset-11 calling the old assembler
|
||||
ifneq ($(filter %-11,$(TOOLSET)),)
|
||||
TARGET_CPPFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
TARGET_LDFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
CPPFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
LDFLAGS += $(TOOLSET_DIR:%=-B$(SYSROOT)%/bin)
|
||||
endif
|
||||
|
||||
ifneq (($(TOOLSET)),)
|
||||
|
||||
18
configure/os/CONFIG.Common.win32-x86-clang
Normal file
18
configure/os/CONFIG.Common.win32-x86-clang
Normal file
@@ -0,0 +1,18 @@
|
||||
# CONFIG.Common.win32-x86-clang
|
||||
#
|
||||
# Definitions for win32-x86-clang target build
|
||||
# Override these definitions in CONFIG_SITE.Common.win32-x86-clang
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to msvc compiler
|
||||
include $(CONFIG)/CONFIG.msvcCommon
|
||||
|
||||
VALID_BUILDS = Ioc Host Command
|
||||
|
||||
# Override CONFIG.msvcCommon settings:
|
||||
MSVC_PREFIX = llvm-
|
||||
CC = clang-cl$(MSVC_SUFFIX) --target=i686-pc-windows-msvc
|
||||
WINLINK = lld-link$(MSVC_SUFFIX)
|
||||
|
||||
# clang-cl does not support /GL option
|
||||
OPT_WHOLE_PROGRAM = NO
|
||||
18
configure/os/CONFIG.Common.windows-x64-clang
Normal file
18
configure/os/CONFIG.Common.windows-x64-clang
Normal file
@@ -0,0 +1,18 @@
|
||||
# CONFIG.Common.windows-x64-clang
|
||||
#
|
||||
# Definitions for windows-x64-clang target builds
|
||||
# Sites may override these definitions in CONFIG_SITE.Common.windows-x64-clang
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to msvc compiler
|
||||
include $(CONFIG)/CONFIG.msvcCommon
|
||||
|
||||
VALID_BUILDS = Ioc Host Command
|
||||
|
||||
# Override CONFIG.msvcCommon settings:
|
||||
MSVC_PREFIX = llvm-
|
||||
CC = clang-cl$(MSVC_SUFFIX) --target=x86_64-pc-windows-msvc
|
||||
WINLINK = lld-link$(MSVC_SUFFIX)
|
||||
|
||||
# clang-cl does not support /GL option
|
||||
OPT_WHOLE_PROGRAM = NO
|
||||
4
configure/os/CONFIG.Linux.win32-x86
Normal file
4
configure/os/CONFIG.Linux.win32-x86
Normal file
@@ -0,0 +1,4 @@
|
||||
include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
|
||||
|
||||
PATH := /opt/wine-msvc-2017/bin/x86:$(PATH)
|
||||
export WINEPREFIX = $(HOME)/.wine32-$(EPICS_HOST_ARCH)
|
||||
@@ -4,7 +4,8 @@ VALID_BUILDS = Ioc Command
|
||||
|
||||
MSVC_VERSION ?= 2019
|
||||
PATH := /opt/gfa-wine/bin:/opt/wine-msvc-$(MSVC_VERSION)/bin/x64:$(PATH)
|
||||
export WINE ?= wine64
|
||||
export WINEPREFIX = $(HOME)/.wine-$(EPICS_HOST_ARCH)
|
||||
export WINEDEBUG=fixme-all
|
||||
export WINEDLLOVERRIDES="mscoree,mshtml="
|
||||
export WINE = wine64
|
||||
export WINEDEBUG := err-all,warn-all,fixme-all$(WINEDEBUG:%=,%)
|
||||
export WINEDLLOVERRIDES := mscoree,mshtml=$(WINEDLLOVERRIDES:%=,%)
|
||||
export WINEPATH := $(WINEPATH:%=%;)$(abspath $(INSTALL_BIN))
|
||||
|
||||
@@ -23,3 +23,6 @@ ARCH_DEP_LDFLAGS+=-Wl,-rpath-link,$(INSTALL_LIB)
|
||||
# Our host versions work just fine.
|
||||
AR = ar -rc
|
||||
RANLIB = ranlib
|
||||
|
||||
# Allow to run cross-tests which expect different lib versions
|
||||
export LD_PRELOAD=$(SYSROOT)/lib64/libreadline.so
|
||||
|
||||
1
configure/os/CONFIG.RHEL8-x86_64.win32-x86-mingw
Normal file
1
configure/os/CONFIG.RHEL8-x86_64.win32-x86-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.linux-x86_64.win32-x86-mingw
|
||||
1
configure/os/CONFIG.RHEL8-x86_64.windows-x64-mingw
Normal file
1
configure/os/CONFIG.RHEL8-x86_64.windows-x64-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.linux-x86_64.windows-x64-mingw
|
||||
@@ -1,3 +1,9 @@
|
||||
#CONFIG.$(EPICS_HOST_ARCH).Common is required by build system
|
||||
#Include definitions common to linux hosts
|
||||
include $(CONFIG)/os/CONFIG.linux-x86_64.Common
|
||||
|
||||
# Windows 32 bit cross builds using mingw
|
||||
# (broken on RHEL8)
|
||||
|
||||
CROSS_COMPILER_TARGET_ARCHS += win32-x86-mingw
|
||||
CROSS_COMPILER_RUNTEST_ARHCS += win32-x86-mingw
|
||||
|
||||
@@ -16,3 +16,6 @@ export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH:%=%:)$(TOOLSET_DIR:%=$(SYSROOT)%/usr
|
||||
|
||||
# The linker has problems to find indirectly referenced libraries
|
||||
PROD_LDLIBS += $(LDLIBS)
|
||||
|
||||
# Allow to run cross-tests which expect different lib versions
|
||||
export LD_PRELOAD=$(SYSROOT)/lib64/libreadline.so
|
||||
|
||||
@@ -14,9 +14,12 @@ SYSROOT = /opt/RHEL8
|
||||
# But linker gets confused with LD_LIBRARY_PATH.
|
||||
# Thus only wrap the compiler.
|
||||
WRAPPER = -wrapper env,LD_LIBRARY_PATH=$(TOOLSET_DIR:%=$(SYSROOT)%/usr/lib64:)/usr/lib64:$(SYSROOT)/usr/lib64
|
||||
TARGET_CPPFLAGS += $(WRAPPER)
|
||||
CPPFLAGS += $(WRAPPER)
|
||||
|
||||
# These programs as cross tools would also need LD_LIBRARY_PATH.
|
||||
# But but our host versions work just fine.
|
||||
AR = ar -rc
|
||||
RANLIB = ranlib
|
||||
|
||||
# Allow to run cross-tests which expect different lib versions
|
||||
export LD_PRELOAD=$(SYSROOT)/lib64/libreadline.so
|
||||
|
||||
1
configure/os/CONFIG.RHEL9-x86_64.win32-x86-mingw
Normal file
1
configure/os/CONFIG.RHEL9-x86_64.win32-x86-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.linux-x86_64.win32-x86-mingw
|
||||
1
configure/os/CONFIG.RHEL9-x86_64.windows-x64-mingw
Normal file
1
configure/os/CONFIG.RHEL9-x86_64.windows-x64-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.linux-x86_64.windows-x64-mingw
|
||||
11
configure/os/CONFIG.darwin-aarch64-debug.Common
Normal file
11
configure/os/CONFIG.darwin-aarch64-debug.Common
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG.darwin-aarch64-debug.Common
|
||||
#
|
||||
# Definitions for darwin-aarch64-debug host builds - darwin-aarch64 target build with debug compiler flags
|
||||
# Sites may override these definitions in CONFIG_SITE.darwin-aarch64-debug.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
include $(CONFIG)/os/CONFIG.darwin-aarch64.Common
|
||||
|
||||
# Removes -O optimization and adds -g compile option
|
||||
HOST_OPT=NO
|
||||
|
||||
14
configure/os/CONFIG.darwin-aarch64.darwin-aarch64-debug
Normal file
14
configure/os/CONFIG.darwin-aarch64.darwin-aarch64-debug
Normal file
@@ -0,0 +1,14 @@
|
||||
# CONFIG.darwin-aarch64.darwin-aarch64-debug
|
||||
#
|
||||
# Definitions for darwin-aarch64 host - darwin-aarch64-debug target build with debug compiler flags
|
||||
# Sites may override these definitions in CONFIG_SITE.darwin-aarch64.darwin-aarch64-debug
|
||||
#-------------------------------------------------------
|
||||
|
||||
-include $(CONFIG)/os/CONFIG.Common.darwin-aarch64
|
||||
-include $(CONFIG)/os/CONFIG.darwin-aarch64.darwin-aarch64
|
||||
-include $(CONFIG)/os/CONFIG_SITE.Common.darwin-aarch64
|
||||
-include $(CONFIG)/os/CONFIG_SITE.darwin-aarch64.darwin-aarch64
|
||||
|
||||
|
||||
BUILD_CLASS=HOST
|
||||
HOST_OPT = NO
|
||||
11
configure/os/CONFIG.darwin-x86-debug.Common
Normal file
11
configure/os/CONFIG.darwin-x86-debug.Common
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG.darwin-x86-debug.Common
|
||||
#
|
||||
# Definitions for darwin-x86-debug host builds - darwin-x86 target build with debug compiler flags
|
||||
# Sites may override these definitions in CONFIG_SITE.darwin-x86-debug.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
include $(CONFIG)/os/CONFIG.darwin-x86.Common
|
||||
|
||||
# Removes -O optimization and adds -g compile option
|
||||
HOST_OPT=NO
|
||||
|
||||
9
configure/os/CONFIG.win32-x86-clang.Common
Normal file
9
configure/os/CONFIG.win32-x86-clang.Common
Normal file
@@ -0,0 +1,9 @@
|
||||
# CONFIG.win32-x86-clang.Common
|
||||
#
|
||||
# Definitions for win32-x86-clang host arch
|
||||
# Override these definitions in CONFIG_SITE.win32-x86-clang.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to win32-x86 hosts
|
||||
include $(CONFIG)/os/CONFIG.win32-x86.Common
|
||||
|
||||
@@ -4,286 +4,7 @@
|
||||
# Override these definitions in CONFIG_SITE.win32-x86.win32-x86
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Win32 valid build types and include directory suffixes
|
||||
# Include common msvc compiler definitions
|
||||
include $(CONFIG)/CONFIG.msvcCommon
|
||||
|
||||
VALID_BUILDS = Host Ioc Command
|
||||
|
||||
CMPLR_CLASS = msvc
|
||||
|
||||
OPT_WHOLE_PROGRAM = YES
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
WINLINK = link
|
||||
|
||||
RCCMD = rc -nologo -l 0x409 $(INCLUDES) -fo $@ $<
|
||||
|
||||
ARCMD = lib -nologo -verbose -out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
|
||||
|
||||
#
|
||||
# Configure OS vendor C compiler
|
||||
CC = cl
|
||||
|
||||
# Override CONFIG.gnuCommon settings for cross builds.
|
||||
GNU = NO
|
||||
HDEPENDS_METHOD = MKMF
|
||||
|
||||
# Compiler flags for C files (C++ is below)
|
||||
|
||||
#
|
||||
# -W<d> display warnings at level d
|
||||
# -W4 is for maximum (lint type) warnings
|
||||
# -W3 is for production quality warnings
|
||||
# -W2 displays significant warnings
|
||||
# -W1 is the default and shows severe warnings only
|
||||
# -w<d><n> Set warning C<n> to be shown at level <d>
|
||||
WARN_CFLAGS_YES = -W3
|
||||
WARN_CFLAGS_NO = -W1
|
||||
|
||||
#
|
||||
# -Ox maximum optimizations
|
||||
# -GL whole program optimization
|
||||
# -Oy- re-enable creation of frame pointers
|
||||
OPT_CFLAGS_YES_YES = -Ox -GL -Oy-
|
||||
OPT_CFLAGS_YES_NO = -Ox -Oy-
|
||||
OPT_CFLAGS_YES = $(OPT_CFLAGS_YES_$(OPT_WHOLE_PROGRAM))
|
||||
|
||||
#
|
||||
# -Z7 generate C7 compatible debugging information (inside .obj)
|
||||
# -RTCsu enable run-time error checks
|
||||
OPT_CFLAGS_NO = -Z7 -RTCsu
|
||||
|
||||
# specify object file name and location
|
||||
OBJ_CFLAG = -Fo
|
||||
|
||||
#
|
||||
# the following options are required when
|
||||
# vis c++ compiles the code (and includes
|
||||
# the header files)
|
||||
#
|
||||
# -MT static multithreaded C RTL
|
||||
# -MTd static multithreaded C RTL (debug version)
|
||||
# -MD multithreaded C RTL in DLL
|
||||
# -MDd multithreaded C RTL in DLL (debug version)
|
||||
BUILD_DLL_CFLAGS_NO =
|
||||
BUILD_DLL_CFLAGS_YES = -DEPICS_BUILD_DLL
|
||||
BUILD_DLL_CFLAGS = $(BUILD_DLL_CFLAGS_$(SHARED_LIBRARIES))
|
||||
VISC_CFLAGS_DEBUG_NO = d
|
||||
VISC_CFLAGS_DEBUG_YES =
|
||||
VISC_CFLAGS_DEBUG = $(VISC_CFLAGS_DEBUG_$(HOST_OPT))
|
||||
STATIC_CFLAGS_YES= -MT$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS)
|
||||
STATIC_CFLAGS_NO= -MD$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS) -DEPICS_CALL_DLL
|
||||
|
||||
# OS vendor c preprocessor
|
||||
CPP = cl -nologo -C -E
|
||||
|
||||
# Configure OS vendor C++ compiler
|
||||
#
|
||||
# -EHsc - generate code for exceptions
|
||||
# -GR - generate code for run time type identification
|
||||
#
|
||||
CCC = cl -EHsc -GR
|
||||
|
||||
# Other compiler flags, used for CPP, C and C++
|
||||
#
|
||||
# -FC - Show absolute path of source file in diagnostics
|
||||
# -D__STDC__=0 gives us both:
|
||||
# 1) define STDC for code (pretend ANSI conformance)
|
||||
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
|
||||
# because MS uses: if __STDC__ ... disable many nice things
|
||||
#
|
||||
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
|
||||
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
|
||||
|
||||
|
||||
# Compiler flags for C++ files
|
||||
|
||||
#
|
||||
# -W<n> disable warnings from levels > n
|
||||
# -w<n><m> set warning m to level n
|
||||
# -w44355 "'this' used in the base initializer list"
|
||||
# -w44344 "behavior change: use of explicit template arguments results in ..."
|
||||
# -w44251 "class needs to have dll-interface to be used by clients of ..."
|
||||
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
|
||||
WARN_CXXFLAGS_NO = -W1
|
||||
|
||||
# Silence tr1 namespace deprecation warnings
|
||||
WARN_CXXFLAGS += -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||
|
||||
#
|
||||
# -Ox maximum optimizations
|
||||
# -GL whole program optimization
|
||||
# -Oy- re-enable creation of frame pointers
|
||||
OPT_CXXFLAGS_YES_YES = -Ox -GL -Oy-
|
||||
OPT_CXXFLAGS_YES_NO = -Ox -Oy-
|
||||
OPT_CXXFLAGS_YES = $(OPT_CXXFLAGS_YES_$(OPT_WHOLE_PROGRAM))
|
||||
|
||||
#
|
||||
# -Z7 generate C7 compatible debugging information (inside .obj)
|
||||
# -RTCsu enable run-time error checks
|
||||
OPT_CXXFLAGS_NO = -RTCsu -Z7
|
||||
|
||||
# specify object file name and location
|
||||
OBJ_CXXFLAG = -Fo
|
||||
|
||||
#
|
||||
# the following options are required when
|
||||
# vis c++ compiles the code (and includes
|
||||
# the header files)
|
||||
#
|
||||
# -MT static multithreaded C RTL
|
||||
# -MTd static multithreaded C RTL (debug version)
|
||||
# -MD multithreaded C RTL in DLL
|
||||
# -MDd multithreaded C RTL in DLL (debug version)
|
||||
STATIC_CXXFLAGS_YES= -MT$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS)
|
||||
STATIC_CXXFLAGS_NO= -MD$(VISC_CFLAGS_DEBUG) $(BUILD_DLL_CFLAGS) -DEPICS_CALL_DLL
|
||||
|
||||
STATIC_LDLIBS_YES=ws2_32.lib advapi32.lib user32.lib kernel32.lib winmm.lib dbghelp.lib
|
||||
STATIC_LDLIBS_NO=
|
||||
STATIC_LDFLAGS=
|
||||
RANLIB=
|
||||
|
||||
# add -profile here to run the ms profiler
|
||||
# -LTCG whole program optimization
|
||||
# -incremental:no full linking
|
||||
# -fixed:no generate relocatable code
|
||||
# -version:<major>.<minor> - only 2 components allowed, 0-65535 each
|
||||
# -debug generate debugging info
|
||||
LINK_OPT_FLAGS_WHOLE_YES = -LTCG
|
||||
LINK_OPT_FLAGS_YES = $(LINK_OPT_FLAGS_WHOLE_$(OPT_WHOLE_PROGRAM))
|
||||
LINK_OPT_FLAGS_YES += -incremental:no -opt:ref
|
||||
LINK_OPT_FLAGS_YES += -release $(PROD_VERSION:%=-version:%)
|
||||
LINK_OPT_FLAGS_NO = -debug -incremental:no -fixed:no
|
||||
OPT_LDFLAGS = $(LINK_OPT_FLAGS_$(HOST_OPT))
|
||||
|
||||
LIB_OPT_FLAGS_YES = $(LINK_OPT_FLAGS_WHOLE_$(OPT_WHOLE_PROGRAM))
|
||||
LIB_OPT_LDFLAGS = $(LIB_OPT_FLAGS_$(HOST_OPT))
|
||||
|
||||
ARCH_DEP_CFLAGS=
|
||||
SHRLIB_CFLAGS=
|
||||
|
||||
OS_CLASS=WIN32
|
||||
POSIX=NO
|
||||
|
||||
# ifdef WIN32 looks better that ifeq ($(OS_CLASS),WIN32) ??
|
||||
WIN32=1
|
||||
|
||||
EXE=.exe
|
||||
OBJ=.obj
|
||||
RES=.res
|
||||
|
||||
# MS Visual C++ doesn't recognize *.cc as a C++ source file,
|
||||
# so C++ compiles get the flag -TP
|
||||
COMPILER_CXXFLAGS = -TP
|
||||
|
||||
# Operating system flags
|
||||
OP_SYS_CFLAGS =
|
||||
OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
|
||||
|
||||
# Files and flags needed to link DLLs (used in RULES_BUILD)
|
||||
WIN32_DLLFLAGS = -subsystem:windows -dll $(OPT_LDFLAGS) \
|
||||
$(USR_LDFLAGS) $(CMD_LDFLAGS) $(TARGET_LDFLAGS) $(LIB_LDFLAGS)
|
||||
|
||||
# Specify dll .def file only if it exists
|
||||
DLL_DEF_FLAG = $(addprefix -def:,$(wildcard ../$(addsuffix .def,$*)))
|
||||
|
||||
# A WIN32 dll has three parts:
|
||||
# x.dll: the real dll (SHRLIBNAME)
|
||||
# x.lib: what you link to progs that use the dll (DLLSTUB_LIBNAME)
|
||||
# x.exp: what you need to build the dll (in no variable)
|
||||
LINK.shrlib = $(WINLINK) -nologo $(WIN32_DLLFLAGS) -out:$@ \
|
||||
-implib:$(@:%$(SHRLIB_SUFFIX)=%$(LIB_SUFFIX)) \
|
||||
$(DLL_DEF_FLAG) $(LIBRARY_LD_OBJS) $(LIBRARY_LD_RESS) $(SHRLIB_LDLIBS)
|
||||
|
||||
# Adjust names of libraries to build
|
||||
SHRLIB_SUFFIX_BASE = .dll
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
SHRLIBNAME_YES = $(BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
|
||||
LOADABLE_SHRLIBNAME = $(LOADABLE_BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
|
||||
TESTSHRLIBNAME_YES = $(TESTBUILD_LIBRARY:%=%$(SHRLIB_SUFFIX_BASE))
|
||||
|
||||
# When SHARED_LIBRARIES is YES we are building a DLL shared library.
|
||||
# When SHARED_LIBRARIES is NO we are building an object library
|
||||
DLLSTUB_SUFFIX = .lib
|
||||
DLLSTUB_LIBNAME_YES = $(BUILD_LIBRARY:%=%.lib)
|
||||
DLLSTUB_LIBNAME = $(DLLSTUB_LIBNAME_$(SHARED_LIBRARIES))
|
||||
TESTDLLSTUB_LIBNAME_YES = $(TESTBUILD_LIBRARY:%=%.lib)
|
||||
TESTDLLSTUB_LIBNAME = $(TESTDLLSTUB_LIBNAME_$(SHARED_LIBRARIES))
|
||||
|
||||
LIB_PREFIX=
|
||||
LIB_SUFFIX=.lib
|
||||
LIBNAME_NO = $(BUILD_LIBRARY:%=%.lib)
|
||||
LIBNAME = $(LIBNAME_$(SHARED_LIBRARIES))
|
||||
TESTLIBNAME_NO = $(TESTBUILD_LIBRARY:%=%.lib)
|
||||
TESTLIBNAME = $(TESTLIBNAME_$(SHARED_LIBRARIES))
|
||||
|
||||
# dll install location
|
||||
INSTALL_SHRLIB = $(INSTALL_BIN)
|
||||
|
||||
|
||||
#--------------------------------------------------
|
||||
# Products dependancy definitions
|
||||
|
||||
PROD_DEPLIBS = $(foreach lib, $(PROD_LIBS) $(USR_LIBS), \
|
||||
$(firstword $(wildcard \
|
||||
$(addsuffix /$(DLLSTUB_PREFIX)$(lib)$(DLLSTUB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(SHRLIB_PREFIX)$(lib)*$(SHRLIB_SUFFIX_BASE)*, \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(LIB_PREFIX)$(lib)$(LIB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
) $(addsuffix /$(BUILDLIB_PREFIX)$(lib)$(BUILDLIB_SUFFIX), \
|
||||
$(if $(filter $(lib),$(TESTLIBRARY)),.,$(INSTALL_LIB)))))
|
||||
|
||||
|
||||
PROD_LDLIBS += $($*_DEPLIBS) $(PROD_DEPLIBS)
|
||||
PROD_LDLIBS += $(addsuffix .lib, \
|
||||
$($*_SYS_LIBS) $(PROD_SYS_LIBS) $(USR_SYS_LIBS))
|
||||
|
||||
LDLIBS_STATIC_YES = LDLIBS
|
||||
LDLIBS_SHARED_NO = LDLIBS
|
||||
PROD_LDLIBS += $(STATIC_LDLIBS) \
|
||||
$($(firstword $(LDLIBS_STATIC_$(STATIC_BUILD)) \
|
||||
$(LDLIBS_SHARED_$(SHARED_LIBRARIES))))
|
||||
|
||||
#--------------------------------------------------
|
||||
# Libraries dependancy definitions
|
||||
|
||||
# libs that we need to link the DLL with
|
||||
# (it isnt necessary to rebuild the dll if these change)
|
||||
|
||||
SHRLIB_DEPLIBS = $(foreach lib, $(LIB_LIBS) $(USR_LIBS), \
|
||||
$(firstword $(wildcard \
|
||||
$(addsuffix /$(DLLSTUB_PREFIX)$(lib)$(DLLSTUB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(SHRLIB_PREFIX)$(lib)*$(SHRLIB_SUFFIX_BASE)*, \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
$(addsuffix /$(LIB_PREFIX)$(lib)$(LIB_SUFFIX), \
|
||||
$($(lib)_DIR) $(SHRLIB_SEARCH_DIRS)) \
|
||||
) $(addsuffix /$(BUILDLIB_PREFIX)$(lib)$(BUILDLIB_SUFFIX), \
|
||||
$(if $(filter $(lib),$(TESTLIBRARY)),.,$(INSTALL_LIB)))))
|
||||
|
||||
|
||||
SHRLIB_LDLIBS += $($*_DLL_DEPLIBS) $($*_DEPLIBS) $(SHRLIB_DEPLIBS)
|
||||
SHRLIB_LDLIBS += $(addsuffix .lib, \
|
||||
$($*_SYS_DLL_LIBS) \
|
||||
$($*_SYS_LIBS) $(LIB_SYS_LIBS) $(USR_SYS_LIBS) )
|
||||
|
||||
#--------------------------------------------------
|
||||
# Linker definition
|
||||
LINK.cpp = $(WINLINK) -nologo $(STATIC_LDFLAGS) $(LDFLAGS) $(PROD_LDFLAGS) \
|
||||
-out:$@ $(PROD_LD_OBJS) $(PROD_LD_RESS) $(PROD_LDLIBS)
|
||||
|
||||
#--------------------------------------------------
|
||||
# UseManifestTool.pl checks MS Visual c++ compiler version number to
|
||||
# decide whether or not to use the Manifest Tool command to embed the
|
||||
# linker created .manifest file into a library or product target.
|
||||
# useManifestTool.pl returns 0(don't use) or 1(use).
|
||||
#
|
||||
MT.exe = mt.exe -nologo -manifest $@.manifest
|
||||
MT_DLL_COMMAND1 = $(MT.exe) "-outputresource:$@;\#2"
|
||||
MT_EXE_COMMAND_YES =
|
||||
MT_EXE_COMMAND_NO = $(MT.exe) "-outputresource:$@;\#1"
|
||||
MT_EXE_COMMAND1 = $(MT_EXE_COMMAND_$(STATIC_BUILD))
|
||||
MT_DLL_COMMAND = $(MT_DLL_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
|
||||
MT_EXE_COMMAND = $(MT_EXE_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
|
||||
|
||||
9
configure/os/CONFIG.windows-x64-clang.Common
Normal file
9
configure/os/CONFIG.windows-x64-clang.Common
Normal file
@@ -0,0 +1,9 @@
|
||||
# CONFIG.windows-x64-clang.Common
|
||||
#
|
||||
# Definitions for windows-x64-clang host arch
|
||||
# Override these definitions in CONFIG_SITE.windows-x64-clang.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to windows-x64 hosts
|
||||
include $(CONFIG)/os/CONFIG.windows-x64.Common
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
# Override these definitions in CONFIG_SITE.windows-x64.windows-x64
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to win32-x86 builds
|
||||
include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
|
||||
-include $(CONFIG)/os/CONFIG_SITE.win32-x86.win32-x86
|
||||
# Include common msvc compiler definitions
|
||||
include $(CONFIG)/CONFIG.msvcCommon
|
||||
|
||||
VALID_BUILDS = Host Ioc Command
|
||||
|
||||
OPT_LDFLAGS += -MACHINE:X64
|
||||
# -MACHINE:X64
|
||||
|
||||
@@ -15,8 +15,8 @@ STD_CXXFLAGS = -std=c++11
|
||||
|
||||
TOOLSET_DIR = $(TOOLSET:%=$(TOOLSET_LOCATION)/%/root)
|
||||
GNU_DIR = $(SYSROOT)$(TOOLSET_DIR)
|
||||
TARGET_CPPFLAGS += $(SYSROOT:%=--sysroot=%)
|
||||
TARGET_LDFLAGS += $(SYSROOT:%=--sysroot=%)
|
||||
CPPFLAGS += $(SYSROOT:%=--sysroot=%)
|
||||
LDFLAGS += $(SYSROOT:%=--sysroot=%)
|
||||
|
||||
# backward compatibility: Keep unversioned libs
|
||||
# in order to prevent dynamic linking problems
|
||||
|
||||
@@ -27,3 +27,6 @@ WIND_BASE = /opt/VxWorks/VxWorks$(VXWORKS_VERSION)
|
||||
|
||||
# For the license counter
|
||||
export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH:%=%:)$(WIND_BASE)/lmapi-5.0/$(WIND_HOST_TYPE)/lib
|
||||
|
||||
softIoc_LDFLAGS += -whole-archive
|
||||
softIocPVA_LDFLAGS += -whole-archive
|
||||
|
||||
@@ -2,6 +2,8 @@ include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common
|
||||
|
||||
# Improved error checking with clang
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL8-x86_64-clang
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += RHEL8-x86_64-clang
|
||||
|
||||
# Build for old RHEL7 64 bit
|
||||
#CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64
|
||||
#CROSS_COMPILER_RUNTEST_ARCHS += RHEL7-x86_64
|
||||
|
||||
1
configure/os/CONFIG_SITE.RHEL8-x86_64.win32-x86-mingw
Normal file
1
configure/os/CONFIG_SITE.RHEL8-x86_64.win32-x86-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.win32-x86-mingw
|
||||
1
configure/os/CONFIG_SITE.RHEL8-x86_64.windows-x64-mingw
Normal file
1
configure/os/CONFIG_SITE.RHEL8-x86_64.windows-x64-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.windows-x64-mingw
|
||||
@@ -2,9 +2,12 @@ include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common
|
||||
|
||||
# Improved error checking with clang
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL9-x86_64-clang
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += RHEL9-x86_64-clang
|
||||
|
||||
# Build for old RHEL8 64 bit
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL8-x86_64
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += RHEL8-x86_64
|
||||
|
||||
# Build for old RHEL7 64 bit
|
||||
# Build for even older RHEL7 64 bit
|
||||
#CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64
|
||||
#CROSS_COMPILER_RUNTEST_ARCHS += RHEL7-x86_64
|
||||
|
||||
1
configure/os/CONFIG_SITE.RHEL9-x86_64.win32-x86-mingw
Normal file
1
configure/os/CONFIG_SITE.RHEL9-x86_64.win32-x86-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.win32-x86-mingw
|
||||
1
configure/os/CONFIG_SITE.RHEL9-x86_64.windows-x64-mingw
Normal file
1
configure/os/CONFIG_SITE.RHEL9-x86_64.windows-x64-mingw
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.windows-x64-mingw
|
||||
@@ -13,6 +13,11 @@ GNU_HOST_ARCH_64=x86_64
|
||||
|
||||
# Windows cross builds using Wine
|
||||
CROSS_COMPILER_TARGET_ARCHS += windows-x64
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += windows-x64
|
||||
|
||||
# Windows cross builds using mingw
|
||||
CROSS_COMPILER_TARGET_ARCHS += windows-x64-mingw
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += windows-x64-mingw
|
||||
|
||||
# IOxOS IFC1211
|
||||
#CROSS_COMPILER_TARGET_ARCHS += fslqoriq20-e6500_64
|
||||
|
||||
@@ -6,3 +6,9 @@
|
||||
# Inherit from the linux-x86 host architecture
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
||||
|
||||
MINGWLIBS ?= /usr/i686-w64-mingw32/sys-root/mingw/bin
|
||||
export WINE ?= wine
|
||||
export WINEPREFIX = $(HOME)/.wine32-$(EPICS_HOST_ARCH)
|
||||
export WINEDEBUG := err-all,warn-all,fixme-all$(WINEDEBUG:%=,%)
|
||||
export WINEDLLOVERRIDES := mscoree,mshtml=$(WINEDLLOVERRIDES:%=,%)
|
||||
export WINEPATH := $(WINEPATH:%=%;)$(MINGWLIBS);$(abspath $(INSTALL_BIN))
|
||||
|
||||
@@ -6,3 +6,9 @@
|
||||
# Inherit from the linux-x86 host architecture
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86.windows-x64-mingw
|
||||
|
||||
MINGWLIBS ?= /usr/x86_64-w64-mingw32/sys-root/mingw/bin
|
||||
export WINE ?= wine64
|
||||
export WINEPREFIX = $(HOME)/.wine-$(EPICS_HOST_ARCH)
|
||||
export WINEDEBUG := err-all,warn-all,fixme-all$(WINEDEBUG:%=,%)
|
||||
export WINEDLLOVERRIDES := mscoree,mshtml=$(WINEDLLOVERRIDES:%=,%)
|
||||
export WINEPATH := $(WINEPATH:%=%;)$(MINGWLIBS);$(abspath $(INSTALL_BIN))
|
||||
|
||||
@@ -64,7 +64,3 @@ COMMANDLINE_LIBRARY ?= EPICS
|
||||
#else
|
||||
COMMANDLINE_LIBRARY ?= $(strip $(if $(wildcard $(if $(GNU_DIR),$(GNU_DIR)/include/readline/readline.h)), READLINE, EPICS))
|
||||
#endif
|
||||
|
||||
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE>2
|
||||
OP_SYS_CPPFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2
|
||||
#endif
|
||||
|
||||
@@ -8,41 +8,163 @@ under the 3.15 release to which they were originally committed.** Thus it is
|
||||
important to read more than just the first section to understand everything that
|
||||
has changed in each release.
|
||||
|
||||
The PVA submodules each have their own individual sets of release notes which
|
||||
should also be read to understand what has changed since earlier releases:
|
||||
The external PVA submodules each have their own individual release notes files.
|
||||
However the entries describing changes included in those submodules since EPICS
|
||||
7.0.5 have now been copied into the appropriate place of this file.
|
||||
|
||||
- [normativeTypes](https://github.com/epics-base/normativeTypesCPP/blob/master/documentation/RELEASE_NOTES.md)
|
||||
- [pvAccess](http://epics-base.github.io/pvAccessCPP/pvarelease_notes.html)
|
||||
- [pvData](http://epics-base.github.io/pvDataCPP/release_notes.html)
|
||||
- [pvDatabase](https://github.com/epics-base/pvDatabaseCPP/blob/master/documentation/RELEASE_NOTES.md)
|
||||
- [pva2pva](https://epics-base.github.io/pva2pva/release_notes.html)
|
||||
- [pvaClient](https://github.com/epics-base/pvaClientCPP/blob/master/documentation/RELEASE_NOTES.md)
|
||||
__This version of EPICS has not been released yet.__
|
||||
|
||||
**This version of EPICS has not been released yet.**
|
||||
## Changes made on the 7.0 branch since 7.0.9
|
||||
|
||||
## Changes made on the 7.0 branch since 7.0.8.1
|
||||
__Add new items below here__
|
||||
|
||||
### DBE_PROPERTY event rate changed
|
||||
### Reduce symbol and macro pollution from epicsAtomic.h on WIN32
|
||||
|
||||
Updating property fields now only post DBE_PROPERTY events if the
|
||||
`epicsAtomic.h` no longer pulls in as many unneeded declarations and macros from
|
||||
`windows.h`. Prior to this change, including `epicsAtomic.h` at the wrong time
|
||||
could result in unexpected compiler errors. Due to the nature of `windows.h`,
|
||||
some unneeded declarations are still pulled in, however the number is greatly reduced.
|
||||
Code that needs these declarations should explicitly include `windows.h` before `epicsAtomic.h`.
|
||||
|
||||
### epicsExport simplifications
|
||||
|
||||
`epicsExportAddress()`, `epicsExportRegistrar()` and `epicsRegisterFunction()`
|
||||
no longer require to be wrapped in `extern "C" { }` in C++ code.
|
||||
|
||||
### New `dbServerStats()` API for iocStats
|
||||
|
||||
A new routine provides the ability to request channel and client counts from
|
||||
named server layers that implement the `stats()` method, or to get a summary
|
||||
of the counts from all registered server layers. A preprocessor macro
|
||||
`HAS_DBSERVER_STATS` macro is defined in the `dbServer.h` header file to
|
||||
simplify code that needs to support older versions of Base as well.
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.9
|
||||
|
||||
### Core documentation published at ReadTheDocs
|
||||
|
||||
The `documentation` directory's `Makefile` can now run various publication scripts including Sphinx and Doxygen to generate formatted documentation that is now being published
|
||||
[at docs.epics-controls.org](https://docs.epics-controls.org/projects/base/en/latest/index.html)
|
||||
and integrated into the main [EPICS Documentation website](https://docs.epics-controls.org/en/latest/index.html).
|
||||
The best place to find out more about these mechanisms is the
|
||||
[Contribution Guide](https://docs.epics-controls.org/en/latest/CONTRIBUTING.html)
|
||||
although it doesn't currently cover the new processes added to epics-base.
|
||||
|
||||
Much of the documentation generated from .dbd.pod files at build time is now
|
||||
also being converted into MarkDown (.md) files and installed into the top-level
|
||||
`doc` directory. Some users might find it quicker to look up information about a
|
||||
record type by opening these files in a text editor intead of opening a browser
|
||||
and loading the HTML versions or finding and opening the files from the EPICS
|
||||
Documentation site.
|
||||
|
||||
### Post monitors from compress record when it's reset
|
||||
|
||||
Writing into a compress record's `RES` field now posts a monitor event instead
|
||||
of only changing `VAL`. Monitor clients will therefore receive an empty array.
|
||||
|
||||
### The AMSG error message propagates through MSS links
|
||||
|
||||
A database link with the MSS attribute will now propagate not only SEVR and
|
||||
STAT, but also AMSG. This field contains additional information that complements
|
||||
STAT. Links with MS or MSI attributes do not propagate STAT, and therefore do
|
||||
not propagate AMSG, either.
|
||||
|
||||
Channel Access links do not propagate AMSG, regardless of the MSS attribute,
|
||||
because the message is not available as Channel metadata.
|
||||
|
||||
### Reloading record aliases
|
||||
|
||||
Aliases can now be defined more than once as long as they still refer to the
|
||||
same record, unless the global variable `dbRecordsOnceOnly` is non-zero.
|
||||
This allows database files to be loaded multiple times, even if they contain
|
||||
alias definitions.
|
||||
|
||||
### `DBE_PROPERTY` event rate changed
|
||||
|
||||
Updating property fields now only posts `DBE_PROPERTY` events if the
|
||||
field actually changed.
|
||||
|
||||
### Changes to msi related to include paths
|
||||
|
||||
There are two changes to `msi` included here.
|
||||
|
||||
`msi` now treats files included by .template or .substutiions files in a more
|
||||
consistent way: for relative paths, it will always look relative to the current
|
||||
working directory if no `-I` flags are passed, and if they are passed then it
|
||||
will search for the _relative_ path from each of those flags. That is, the
|
||||
following will now find the file `bar.template` located at
|
||||
`/some/path/rel/path/bar.template`
|
||||
```
|
||||
$ cat foo.substitutions
|
||||
file rel/path/bar.template {
|
||||
# contents
|
||||
}
|
||||
$ msi -I /some/path foo.substitutions
|
||||
```
|
||||
|
||||
Note that this does provide one change from previous behaviour: when opening a
|
||||
file from the command line, `msi` will not use the `-I`-specified paths to
|
||||
search for the file, but will only work relative to the current working
|
||||
directory, consistent with most commandline utilities.
|
||||
|
||||
### Allow users to delete previously created records from the database
|
||||
|
||||
From this release, record instances and aliases that have already been loaded
|
||||
by an IOC can be removed from the database again before the call to iocInit
|
||||
by loading a second instance of the named records but using `"#"` in place of
|
||||
the record type. Values for the fields are not required or advised, just use
|
||||
an empty record body { }. This is useful when a template defines records that
|
||||
an empty record body `{}`. This is useful when a template defines records that
|
||||
are not wanted in some IOCs, without having to split or duplicate the original
|
||||
template.
|
||||
|
||||
For example this will remove the record named "unwanted":
|
||||
|
||||
```
|
||||
record("#", "unwanted") { }
|
||||
record("#", "unwanted") {}
|
||||
```
|
||||
|
||||
### Only keep readline history for interactive sessions
|
||||
|
||||
Previously, all IOCsh commands were persisited in the libreadline history
|
||||
(when readline support is included).
|
||||
Going forward, only interactive commands are saved.
|
||||
|
||||
### Type change to asTrap serverSpecific data
|
||||
|
||||
Change `void*` to `dbChannel*` in `asTrapWriteBeforeWithData()` and
|
||||
`asTrapWriteMessage::serverSpecific` to reflect the reality since
|
||||
the `dbAddr*` to `dbChannel*` migration.
|
||||
External code wishing to support both before and after 3.15 should
|
||||
already be conditionally casting to/from the appropriate type.
|
||||
|
||||
### Fix issues with `_FORTIFY_SOURCE=3`
|
||||
|
||||
This release fixes the false positives failures whhen building with `_FORTIFY_SOURCE` level 3.
|
||||
The override introduced in 7.0.8.1 has been removed.
|
||||
|
||||
### Other
|
||||
|
||||
- genVersionHeader: work with git submodules and worktrees.
|
||||
- avoid UB with self `pthread_join()`
|
||||
- freebsd: Add support for x86 and amd64 builds
|
||||
- Clear AMSG when SEVR becomes zero.
|
||||
- `seqRecord` fix support for link `DLY0`
|
||||
- Add `ABORT_ON_ASSERT` flag to `CONFIG_SITE_ENV`
|
||||
- rationalize osdMutex
|
||||
|
||||
### Submodule updates
|
||||
|
||||
The pvDatabase module was updated to version 4.7.2:
|
||||
|
||||
* Resolved issue with changed field set in the case where the top level (master)
|
||||
field ("_") is not requested by the client, but the master field callback causes
|
||||
all fields to be marked as updated, rather than only those fields that have
|
||||
actually been modified.
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.8.1
|
||||
|
||||
### Limit to `_FORTIFY_SOURCE=2`
|
||||
@@ -280,6 +402,50 @@ The floating point modulo function `FMOD(NUM,DEN)` has been added to the CALC
|
||||
expression engine and is available to all software using that (calc and calcout
|
||||
record types, access security library and some extensions).
|
||||
|
||||
### Submodule updates
|
||||
|
||||
The pvData module was updated to version 8.0.6:
|
||||
|
||||
- Compatible changes
|
||||
- Actually enable JSON-5 output in PVStructure::Formatter::JSON when available.
|
||||
- Fix unaligned access issues for some ARM/Linux targets.
|
||||
|
||||
The pvAccess module was updated to version 7.1.7:
|
||||
|
||||
- Changes
|
||||
- Registering the PVA server with the IOC now sets the `PVAS_SERVER_PORT`
|
||||
variable in the environment.
|
||||
|
||||
The pva2pva module was updated to version 1.4.1:
|
||||
|
||||
- Bug Fixes
|
||||
- `dbLoadGroup` was fixed
|
||||
- Additions
|
||||
- Support for "meta" member at top of array of structs
|
||||
|
||||
The pvDatabase module was updated to version 4.7.1:
|
||||
|
||||
* Added data distributor plugin which can be used for distributing data between
|
||||
a group of clients. The plugin is triggered by the request string of the
|
||||
form:
|
||||
|
||||
`_[distributor=group:<group id>;set:<set_id>;trigger:<field_name>;updates:<n_updates>;mode:<update_mode>]`
|
||||
|
||||
The plugin parameters are optional and are described bellow:
|
||||
|
||||
- group: this parameter indicates a group that client application belongs to (default value: "default"); groups of clients are completely independent of each other
|
||||
|
||||
- set: this parameter designates a client set that application belongs to within its group (default value: "default")
|
||||
|
||||
- trigger: this is the PV structure field that distinguishes different channel updates (default value: "timeStamp"); for example, for area detector images one could use the "uniqueId" field of the NTND structure
|
||||
|
||||
- updates: this parameter configures how many sequential updates a client (or a set of clients) will receive before the data distributor starts updating the next one (default value: "1")
|
||||
|
||||
- mode: this parameter configures how channel updates are to be distributed between clients in a set:
|
||||
- one: update goes to one client per set
|
||||
- all: update goes to all clients in a set
|
||||
- default is "one" if client set id is not specified, and "all" if set id is specified
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.7
|
||||
@@ -358,10 +524,10 @@ changed to `(p)->dtor`.
|
||||
The order over operations when processing a waveformRecord is adjusted
|
||||
so that updates to NORD is posted with the correct timestamp.
|
||||
|
||||
### Automatic COMMANDLINE_LIBRARY w/ newer compilers
|
||||
### Automatic `COMMANDLINE_LIBRARY` with newer compilers
|
||||
|
||||
When built with a compiler supporting `__has_include<>`, the presence
|
||||
of the `<readline/readline.h>` will be used to automatically determine
|
||||
of a `readline/readline.h` header will be used to automatically determine
|
||||
a default value for `COMMANDLINE_LIBRARY`.
|
||||
|
||||
Mingw builds with readline support now link `-ltermcap` instead of `-lcurses`.
|
||||
@@ -530,6 +696,44 @@ or if unsupported (`$TERM` not set, or Windows < 10).
|
||||
The `dbnd` server side filter now passes through alarm and property
|
||||
change events, even when not exceeding the deadband.
|
||||
|
||||
### Submodule updates
|
||||
|
||||
The pvData module was updated to version 8.0.5:
|
||||
|
||||
- Compatible changes
|
||||
- Internal changes to use the YAJL API for generating JSON and JSON-5 output.
|
||||
|
||||
The pvAccess module was updated to version 7.1.6:
|
||||
|
||||
- Changes to caProvider
|
||||
- Bug fix related to enum values.
|
||||
- More internal changes to improve performance when connecting tens of
|
||||
thousands of CA channels.
|
||||
- Several minor internal improvements.
|
||||
|
||||
The pva2pva module was updated to version 1.4.0:
|
||||
|
||||
- Bug Fixes
|
||||
- Apply ACF when writing to atomic group
|
||||
- Additions
|
||||
- Add new "structure" to @ref qsrv_group_map_types
|
||||
- Changes
|
||||
- Add Access Security hooks for single and group writes.
|
||||
- Enable "Async Soft Channel" for output links
|
||||
- When built against Base 7.0.6.1, set timeStamp.userTag from UTAG field.
|
||||
- Add DTYP="QSRV Set UTag" for longin, which sets UTAG=VAL.
|
||||
|
||||
The pvDatabase module was updated to version 4.7.0:
|
||||
|
||||
* Added support for the whole structure (master field) server side plugins.
|
||||
The whole structure is identified as the `_` string, and a pvRequest string
|
||||
that applies a plugin to it takes the form:
|
||||
|
||||
`field(_[XYZ=A:3;B:uniqueId])`
|
||||
|
||||
where `XYZ` is the name of a specific filter plugin that takes parameters
|
||||
`A` and `B` with values `3` and `uniqueId` respectively.
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.6.1
|
||||
@@ -596,6 +800,15 @@ This was done to simplify the code and may have improved performance slightly fo
|
||||
|
||||
Many of the built-in record types have had improvements to their documentation with additional fields added to the tables, rewrites of descriptions and links to other documents added or fixed.
|
||||
|
||||
### Submodule updates
|
||||
|
||||
The pvAccess module was updated to version 7.1.4:
|
||||
|
||||
- Changes to caProvider
|
||||
- Resolve issues with pv structures that don't have a value field
|
||||
- Add NULL checks for handling unusual structures
|
||||
- Speed up channel creation when using large numbers of channels
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.6
|
||||
@@ -606,7 +819,7 @@ These target architectures have been removed:
|
||||
|
||||
+ darwin-ppc, darwin-ppcx86
|
||||
+ linux-386, linux-486, linux-586, linux-686, linux-athlon (cross-build)
|
||||
+ linux-cris, linux-cris_v10, linux-cris_v32 (cross-build)
|
||||
+ linux-cris, linux-cris\_v10, linux-cris\_v32 (cross-build)
|
||||
+ RTEMS-at91rm9200ek, RTEMS-gen68360, RTEMS-mcp750, RTEMS-mvme167,
|
||||
RTEMS-psim (cross-build)
|
||||
|
||||
@@ -624,9 +837,9 @@ running on RTEMS 5:
|
||||
|
||||
- RTEMS-beagleboneblack
|
||||
- RTEMS-pc686
|
||||
- RTEMS-qoriq_e500 (MVME2500)
|
||||
- RTEMS-xilinx_zynq_a9_qemu
|
||||
- RTEMS-xilinx_zynq_zedboard
|
||||
- RTEMS-qoriq\_e500 (MVME2500)
|
||||
- RTEMS-xilinx\_zynq\_a9\_qemu
|
||||
- RTEMS-xilinx\_zynq\_zedboard
|
||||
|
||||
The EPICS support for RTEMS 4 has always relied on RTEMS-specific
|
||||
kernel APIs which cannot be used on an SMP system, so a new port was
|
||||
@@ -638,7 +851,7 @@ to run `make distclean` if switching a single source tree from one
|
||||
to the other (both header files and dependency files are different
|
||||
between the two and must be cleaned out).
|
||||
|
||||
The configuration variable RTEMS_VERSION in the EPICS config file
|
||||
The configuration variable `RTEMS_VERSION` in the EPICS config file
|
||||
`configure/os/CONFIG_SITE.Common.RTEMS` must be set to the full 3-
|
||||
part version number for RTEMS 4 releases, e.g. `4.9.1`, `4.10.2`
|
||||
but for RTEMS 5.1 and later it must only contain the major version
|
||||
@@ -836,6 +1049,39 @@ Test programs written directly in Perl as a `.plt` script should implement a
|
||||
similar timeout for themselves. The "netget" test in Base does this in a way
|
||||
that works on Windows as well as Unix-like hosts.
|
||||
|
||||
### Submodule updates
|
||||
|
||||
The pvAccess module was updated to version 7.1.4:
|
||||
|
||||
- Changes
|
||||
- Adjust argument parsing with pvput (Jesus Vasquez).
|
||||
|
||||
The pva2pva module was updated to version 1.3.1:
|
||||
|
||||
- Bug Fixes
|
||||
- Correct handling for server side filters.
|
||||
- Changes
|
||||
- Syncing softMain.cpp with epics-base
|
||||
|
||||
The pvDatabase module was updated to version 4.6.0:
|
||||
|
||||
* Access Security is now supported.
|
||||
* <b>special</b> has been revised and extended.
|
||||
* addRecord, removeRecord, processRecord, and traceRecord are replaced by pvdbcr versions.
|
||||
* <b>support</b> is DEPRECATED
|
||||
|
||||
The pvaClient module was updated to version 4.8.0:
|
||||
|
||||
* `PvaClientNTMultiData::getChannelChangeFlags` is a new method. It fixes
|
||||
issue #66.
|
||||
* Fix for issue #68. Both `PvaClientArray` and `PvaClientField` are not longer
|
||||
present. Neither was previously implemented.
|
||||
* Several public methods are now protected. They were never meant to be called
|
||||
by clients.
|
||||
* Issue #70 has been fixed.
|
||||
* Changes was made to increase the performance of `pvaMultiChannel`.
|
||||
* doxygen changes were made.
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.5
|
||||
@@ -873,7 +1119,7 @@ compile device supports as loadable modules.
|
||||
### Priority inversion safe Posix mutexes
|
||||
|
||||
On Posix systems, epicsMutex now support priority inheritance if available.
|
||||
The IOC needs to run with SCHED_FIFO engaged to use these.
|
||||
The IOC needs to run with `SCHED_FIFO` engaged to use these.
|
||||
Support for Posix implementations before POSIX.1-2001 (`_XOPEN_SOURCE < 500`,
|
||||
glibc version < 2.3.3) has been dropped.
|
||||
|
||||
@@ -1006,14 +1252,14 @@ properly handle zero-length arrays. The `caget`, `caput` and `camonitor`
|
||||
client programs are known to work with empty arrays as long as they were
|
||||
built with this or a later version of EPICS.
|
||||
|
||||
#### Change to the db_access.h `dbr_size_n(TYPE, COUNT)` macro
|
||||
#### Change to the db\_access.h `dbr_size_n(TYPE, COUNT)` macro
|
||||
|
||||
When called with COUNT=0 this macro no longer returns the number of bytes
|
||||
required for a scalar (1 element) but for an empty array (0 elements).
|
||||
Make sure code that uses this doesn't call it with COUNT=0 when it really
|
||||
means COUNT=1.
|
||||
|
||||
Note that the db_access.h header file is included by cadef.h so the change
|
||||
Note that the db\_access.h header file is included by cadef.h so the change
|
||||
can impact Channel Access client programs that use this macro.
|
||||
|
||||
#### Channel Access support for zero-length arrays
|
||||
@@ -1123,6 +1369,35 @@ GNUmake added the directive `undefine` in version 3.82 to allow variables to
|
||||
be undefined. Support for this has been added to the EPICS Release file parser,
|
||||
so `undefine` can now be used in configure/RELEASE files to unset variables.
|
||||
|
||||
|
||||
### Submodule updates
|
||||
|
||||
The pvData module was updated to version 8.0.4:
|
||||
|
||||
- Incompatible changes
|
||||
- Remove `ByteBuffer::align()`
|
||||
- Compatible changes
|
||||
- Deprecate `SerializableControl::alignBuffer()` and
|
||||
`DeserializableControl::alignData()`
|
||||
- `shared_vector_convert<>()` fix convert of empty, untyped, array
|
||||
|
||||
The pvAccess module was updated to version 7.1.3:
|
||||
|
||||
- Bug fixes
|
||||
- Increase default TCP timeout to 40 seconds.
|
||||
Applies a 4/3 multiplier on `$EPICS_PVA_CONN_TMO` for compatibility.
|
||||
- CA Provider implementation restructured to simplify, reduce duplication
|
||||
and fix issues #163 and #165.
|
||||
- Changes
|
||||
- Enable building of pvtools to all except vxWorks, RTEMS and iOS.
|
||||
|
||||
The pva2pva module was updated to version 1.3.0:
|
||||
|
||||
- Changes
|
||||
- Add `dbLoadGroup()` iocsh function to read group JSON definitions
|
||||
from a file. Mappings in files must refer to full record names
|
||||
instead of fields. eg. 'recname.VAL' instead of 'VAL'.
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.4.1
|
||||
@@ -1188,7 +1463,7 @@ The following launchpad bugs have fixes included in this release:
|
||||
operators on aarch64
|
||||
- [lp: 1853148](https://bugs.launchpad.net/bugs/1853148), mingw compiler
|
||||
problem with printf/scanf formats
|
||||
- [lp: 1852653](https://bugs.launchpad.net/bugs/1852653), USE_TYPED_DSET
|
||||
- [lp: 1852653](https://bugs.launchpad.net/bugs/1852653), `USE_TYPED_DSET`
|
||||
incompatible with C++
|
||||
- [lp: 1862328](https://bugs.launchpad.net/bugs/1862328), Race condition on
|
||||
IOC start leaves rsrv unresponsive
|
||||
@@ -1198,7 +1473,7 @@ The following launchpad bugs have fixes included in this release:
|
||||
- [lp: 1868680](https://bugs.launchpad.net/bugs/1868680), Access Security file
|
||||
reload (asInit) fails
|
||||
|
||||
### \*_API macros in EPICS headers
|
||||
### `*_API` macros in EPICS headers
|
||||
|
||||
Internally, the Com and ca libraries now express dllimport/export (Windows)
|
||||
and symbol visibility (GCC) using library-specific macros (eg. `LIBCOM_API`)
|
||||
@@ -1432,7 +1707,7 @@ The API functions `epicsGetExecDir()` and `epicsGetExecName()` are also
|
||||
added to `osiFileName.h` to provide runtime access to the directory or
|
||||
filename of the executable with which the process was started.
|
||||
|
||||
### Decouple LINKER_USE_RPATH and STATIC_BUILD
|
||||
### Decouple `LINKER_USE_RPATH` and `STATIC_BUILD`
|
||||
|
||||
Previously, setting `STATIC_BUILD=NO` implied `LINKER_USE_RPATH=NO`.
|
||||
This is no longer the case. Setting `LINKER_USE_RPATH=YES` will
|
||||
@@ -2011,7 +2286,7 @@ number instead, like this:
|
||||
Channel Access does not (and probably never will) directly support 64-bit
|
||||
integer types, so the new field types are presented to the CA server as
|
||||
`DBF_DOUBLE` values. This means that field values larger than 2^52
|
||||
(0x10_0000_0000_0000 = 4503599627370496) cannot be transported over Channel
|
||||
(0x10\_0000\_0000\_0000 = 4503599627370496) cannot be transported over Channel
|
||||
Access without their least significant bits being truncated. The EPICS V4
|
||||
pvAccess network protocol _can_ transport 64-bit data types however, and a
|
||||
future release of the pvaSrv module will connect this ability to the fields of
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Always make sure EpicsVersion.Version-Release matches the git tag!
|
||||
|
||||
%define EpicsVersion 7.0.8
|
||||
%define EpicsVersion 7.0.9
|
||||
|
||||
Name: epics-base-%{EpicsVersion}
|
||||
Summary: EPICS Base %{EpicsVersion}
|
||||
Version: 2
|
||||
Release: 4%{?dist}
|
||||
Version: 1
|
||||
Release: 2%{?dist}
|
||||
License: EPICS Open License
|
||||
Group: Development/Languages
|
||||
URL: https://git.psi.ch/epics_base/base-7.0
|
||||
|
||||
@@ -3396,7 +3396,7 @@ void verifyContextRundownChanStillExist (
|
||||
showProgressEnd ( interestLevel );
|
||||
}
|
||||
|
||||
int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
|
||||
void acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
|
||||
unsigned repetitionCount, enum ca_preemptive_callback_select select )
|
||||
{
|
||||
chid chan;
|
||||
@@ -3549,8 +3549,6 @@ int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
|
||||
printf ( "\nTest Complete\n" );
|
||||
|
||||
epicsExit ( EXIT_SUCCESS );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ extern "C" {
|
||||
enum appendNumberFlag {appendNumber, dontAppendNumber};
|
||||
int catime ( const char *channelName, unsigned channelCount, enum appendNumberFlag appNF );
|
||||
|
||||
int acctst ( const char *pname, unsigned logggingInterestLevel,
|
||||
EPICS_NORETURN
|
||||
void acctst ( const char *pname, unsigned logggingInterestLevel,
|
||||
unsigned channelCount, unsigned repetitionCount,
|
||||
enum ca_preemptive_callback_select select );
|
||||
|
||||
|
||||
@@ -115,10 +115,9 @@ static int dbca_chan_count;
|
||||
* During link modification or IOC shutdown the pca->plink pointer (guarded by caLink.lock)
|
||||
* is used as a flag to indicate that a link is no longer active.
|
||||
*
|
||||
* References to the struct caLink are owned by the dbCaTask, and any scanOnceCallback()
|
||||
* which is in progress.
|
||||
* References to the struct caLink are owned by the dbCaTask.
|
||||
*
|
||||
* The libca and scanOnceCallback callbacks take no action if pca->plink==NULL.
|
||||
* The libca callbacks take no action if pca->plink==NULL.
|
||||
*
|
||||
* dbCaPutLinkCallback causes an additional complication because
|
||||
* when dbCaRemoveLink is called the callback may not have occured.
|
||||
@@ -788,38 +787,6 @@ static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
||||
return status;
|
||||
}
|
||||
|
||||
static void scanComplete(void *raw, dbCommon *prec)
|
||||
{
|
||||
caLink *pca = raw;
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(!pca->plink) {
|
||||
/* IOC shutdown or link re-targeted. Do nothing. */
|
||||
} else if(pca->scanningOnce==0) {
|
||||
errlogPrintf("dbCa.c complete callback w/ scanningOnce==0\n");
|
||||
} else if(--pca->scanningOnce){
|
||||
/* another scan is queued */
|
||||
if(scanOnceCallback(prec, scanComplete, raw)) {
|
||||
errlogPrintf("dbCa.c failed to re-queue scanOnce\n");
|
||||
} else
|
||||
caLinkInc(pca);
|
||||
}
|
||||
epicsMutexUnlock(pca->lock);
|
||||
caLinkDec(pca);
|
||||
}
|
||||
|
||||
/* must be called with pca->lock held */
|
||||
static void scanLinkOnce(dbCommon *prec, caLink *pca) {
|
||||
if(pca->scanningOnce==0) {
|
||||
if(scanOnceCallback(prec, scanComplete, pca)) {
|
||||
errlogPrintf("dbCa.c failed to queue scanOnce\n");
|
||||
} else
|
||||
caLinkInc(pca);
|
||||
}
|
||||
if(pca->scanningOnce<5)
|
||||
pca->scanningOnce++;
|
||||
/* else too many scans queued */
|
||||
}
|
||||
|
||||
static lset dbCa_lset = {
|
||||
0, 1, /* not Constant, Volatile */
|
||||
NULL, dbCaRemoveLink,
|
||||
@@ -856,7 +823,9 @@ static void connectionCallback(struct connection_handler_args arg)
|
||||
if (precord &&
|
||||
((ppv_link->pvlMask & pvlOptCP) ||
|
||||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)))
|
||||
scanLinkOnce(precord, pca);
|
||||
{
|
||||
link_action |= CA_DBPROCESS;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
pca->hasReadAccess = ca_read_access(arg.chid);
|
||||
@@ -988,7 +957,9 @@ static void eventCallback(struct event_handler_args arg)
|
||||
|
||||
if ((ppv_link->pvlMask & pvlOptCP) ||
|
||||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0))
|
||||
scanLinkOnce(precord, pca);
|
||||
{
|
||||
addAction(pca, CA_DBPROCESS);
|
||||
}
|
||||
}
|
||||
done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
@@ -1061,7 +1032,9 @@ static void accessRightsCallback(struct access_rights_handler_args arg)
|
||||
if (precord &&
|
||||
((ppv_link->pvlMask & pvlOptCP) ||
|
||||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)))
|
||||
scanLinkOnce(precord, pca);
|
||||
{
|
||||
addAction(pca, CA_DBPROCESS);
|
||||
}
|
||||
done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
@@ -1273,6 +1246,13 @@ static void dbCaTask(void *arg)
|
||||
printLinks(pca);
|
||||
}
|
||||
}
|
||||
if (link_action & CA_DBPROCESS) {
|
||||
dbCommon *prec;
|
||||
epicsMutexMustLock(pca->lock);
|
||||
prec = pca->plink->precord;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
db_process(prec);
|
||||
}
|
||||
}
|
||||
SEVCHK(ca_flush_io(), "dbCaTask");
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define CA_MONITOR_STRING 0x20
|
||||
#define CA_GET_ATTRIBUTES 0x40
|
||||
#define CA_SYNC 0x1000
|
||||
#define CA_DBPROCESS 0x2000
|
||||
/* write type */
|
||||
#define CA_PUT 0x1
|
||||
#define CA_PUT_CALLBACK 0x2
|
||||
|
||||
@@ -635,9 +635,21 @@ long dbChannelGetField(dbChannel *chan, short dbrType, void *pbuffer,
|
||||
{
|
||||
dbCommon *precord = chan->addr.precord;
|
||||
long status = 0;
|
||||
unsigned char local_fl = 0;
|
||||
|
||||
dbScanLock(precord);
|
||||
if (!pfl && (ellCount(&chan->pre_chain) || ellCount(&chan->post_chain))) {
|
||||
pfl = db_create_read_log(chan);
|
||||
if (pfl) {
|
||||
local_fl = 1;
|
||||
pfl = dbChannelRunPreChain(chan, pfl);
|
||||
pfl = dbChannelRunPostChain(chan, pfl);
|
||||
}
|
||||
}
|
||||
status = dbChannelGet(chan, dbrType, pbuffer, options, nRequest, pfl);
|
||||
if (local_fl) {
|
||||
db_delete_field_log(pfl);
|
||||
}
|
||||
dbScanUnlock(precord);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -511,6 +511,10 @@ DBCORE_API long dbChannelGet(dbChannel *chan, short type,
|
||||
* \param[in,out] nRequest Pointer to the element count.
|
||||
* \param[in] pfl Pointer to a db_field_log or NULL.
|
||||
* \returns 0, or an error status value.
|
||||
*
|
||||
* \since UNRELEASED If pfl is NULL and chan has filters, db_create_read_log() will be called
|
||||
* internally to create a temporary db_field_log which is passed to dbChannelGet()
|
||||
* then deallocated.
|
||||
*/
|
||||
DBCORE_API long dbChannelGetField(dbChannel *chan, short type,
|
||||
void *pbuffer, long *options, long *nRequest, void *pfl);
|
||||
|
||||
@@ -286,7 +286,11 @@ Inf (Infinite) value. UDF defaults to TRUE but can be set in a database file.
|
||||
Record and device support routines which write to the VAL field are generally
|
||||
responsible for setting and clearing UDF.
|
||||
|
||||
=fields STAT, SEVR, AMSG, NSTA, NSEV, NAMSG, ACKS, ACKT, UDF
|
||||
The B<UDFS> field specifies the alarm severity that the record will be set to
|
||||
whenever its value is undefined (i.e., the UDF field is 1). This includes the
|
||||
initial severity of the record being undefined after the IOC boots.
|
||||
|
||||
=fields STAT, SEVR, AMSG, NSTA, NSEV, NAMSG, ACKS, ACKT, UDF, UDFS
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -226,9 +226,10 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
}
|
||||
|
||||
if (!status && precord != dbChannelRecord(chan))
|
||||
recGblInheritSevr(plink->value.pv_link.pvlMask & pvlOptMsMode,
|
||||
recGblInheritSevrMsg(plink->value.pv_link.pvlMask & pvlOptMsMode,
|
||||
plink->precord,
|
||||
dbChannelRecord(chan)->stat, dbChannelRecord(chan)->sevr);
|
||||
dbChannelRecord(chan)->stat, dbChannelRecord(chan)->sevr,
|
||||
dbChannelRecord(chan)->amsg);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -378,8 +379,8 @@ static long dbDbPutValue(struct link *plink, short dbrType,
|
||||
dbCommon *pdest = dbChannelRecord(chan);
|
||||
long status = dbPut(paddr, dbrType, pbuffer, nRequest);
|
||||
|
||||
recGblInheritSevr(ppv_link->pvlMask & pvlOptMsMode, pdest, psrce->nsta,
|
||||
psrce->nsev);
|
||||
recGblInheritSevrMsg(ppv_link->pvlMask & pvlOptMsMode, pdest, psrce->nsta,
|
||||
psrce->nsev, psrce->namsg);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
||||
@@ -75,21 +75,21 @@ static const iocshFuncDef dbbFuncDef = {"dbb",1,dbbArgs,
|
||||
"Set Breakpoint on a record\n"
|
||||
"This command spawns one breakpoint continuation task per lockset,"
|
||||
" in which further record execution is run\n"};
|
||||
static void dbbCallFunc(const iocshArgBuf *args) { dbb(args[0].sval);}
|
||||
static void dbbCallFunc(const iocshArgBuf *args) { iocshSetError(dbb(args[0].sval));}
|
||||
|
||||
/* dbd */
|
||||
static const iocshArg dbdArg0 = { "record name",iocshArgStringRecord};
|
||||
static const iocshArg * const dbdArgs[1] = {&dbdArg0};
|
||||
static const iocshFuncDef dbdFuncDef = {"dbd",1,dbdArgs,
|
||||
"Remove breakpoint from a record.\n"};
|
||||
static void dbdCallFunc(const iocshArgBuf *args) { dbd(args[0].sval);}
|
||||
static void dbdCallFunc(const iocshArgBuf *args) { iocshSetError(dbd(args[0].sval));}
|
||||
|
||||
/* dbc */
|
||||
static const iocshArg dbcArg0 = { "record name",iocshArgStringRecord};
|
||||
static const iocshArg * const dbcArgs[1] = {&dbcArg0};
|
||||
static const iocshFuncDef dbcFuncDef = {"dbc",1,dbcArgs,
|
||||
"Continue processing in a lockset until next breakpoint is found.\n"};
|
||||
static void dbcCallFunc(const iocshArgBuf *args) { dbc(args[0].sval);}
|
||||
static void dbcCallFunc(const iocshArgBuf *args) { iocshSetError(dbc(args[0].sval));}
|
||||
|
||||
/* dbs */
|
||||
static const iocshArg dbsArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -97,12 +97,12 @@ static const iocshArg * const dbsArgs[1] = {&dbsArg0};
|
||||
static const iocshFuncDef dbsFuncDef = {"dbs",1,dbsArgs,
|
||||
"Step through record processing within a lockset.\n"
|
||||
"If called without an argument, automatically steps with the last breakpoint.\n"};
|
||||
static void dbsCallFunc(const iocshArgBuf *args) { dbs(args[0].sval);}
|
||||
static void dbsCallFunc(const iocshArgBuf *args) { iocshSetError(dbs(args[0].sval));}
|
||||
|
||||
/* dbstat */
|
||||
static const iocshFuncDef dbstatFuncDef = {"dbstat",0,0,
|
||||
"Print list of suspended records, and breakpoints set in locksets.\n"};
|
||||
static void dbstatCallFunc(const iocshArgBuf *args) { dbstat();}
|
||||
static void dbstatCallFunc(const iocshArgBuf *args) { iocshSetError(dbstat());}
|
||||
|
||||
/* dbp */
|
||||
static const iocshArg dbpArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -119,7 +119,9 @@ static const iocshFuncDef dbpFuncDef = {
|
||||
" 3 - Fields of minor interest to a System developer.\n"
|
||||
" 4 - Internal record fields.\n"};
|
||||
static void dbpCallFunc(const iocshArgBuf *args)
|
||||
{ dbp(args[0].sval,args[1].ival);}
|
||||
{
|
||||
iocshSetError(dbp(args[0].sval,args[1].ival));
|
||||
}
|
||||
|
||||
/* dbap */
|
||||
static const iocshArg dbapArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -127,7 +129,7 @@ static const iocshArg * const dbapArgs[1] = {&dbapArg0};
|
||||
static const iocshFuncDef dbapFuncDef = {"dbap",1,dbapArgs,
|
||||
"Auto Print.\n"
|
||||
"Toggle automatic printing after processing a record that has a breakpoint.\n"};
|
||||
static void dbapCallFunc(const iocshArgBuf *args) { dbap(args[0].sval);}
|
||||
static void dbapCallFunc(const iocshArgBuf *args) { iocshSetError(dbap(args[0].sval));}
|
||||
|
||||
/* dbsr */
|
||||
static const iocshArg dbsrArg0 = { "interest level",iocshArgInt};
|
||||
@@ -150,7 +152,7 @@ static const iocshFuncDef dbcarFuncDef = {"dbcar",2,dbcarArgs,
|
||||
" 2 - Shows info. for all links.\n"};
|
||||
static void dbcarCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbcar(args[0].sval,args[1].ival);
|
||||
iocshSetError(dbcar(args[0].sval,args[1].ival));
|
||||
}
|
||||
|
||||
/* dbjlr */
|
||||
@@ -162,7 +164,7 @@ static const iocshFuncDef dbjlrFuncDef = {"dbjlr",2,dbjlrArgs,
|
||||
"List all JSON links in a record. If no record is specified, print for all\n"};
|
||||
static void dbjlrCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbjlr(args[0].sval,args[1].ival);
|
||||
iocshSetError(dbjlr(args[0].sval,args[1].ival));
|
||||
}
|
||||
|
||||
/* dbel */
|
||||
@@ -176,7 +178,7 @@ static const iocshFuncDef dbelFuncDef = {"dbel",2,dbelArgs,
|
||||
"Example: dbel aitest 2\n"};
|
||||
static void dbelCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbel(args[0].sval, args[1].ival);
|
||||
iocshSetError(dbel(args[0].sval, args[1].ival));
|
||||
}
|
||||
|
||||
/* dba */
|
||||
@@ -187,7 +189,7 @@ static const iocshFuncDef dbaFuncDef = {"dba",1,dbaArgs,
|
||||
"Print information in the dbAddr structure for a specific field.\n"
|
||||
"If no field is specified, VAL is assumed.\n\n"
|
||||
"Example: dba(\"aitest.HIGH\")\n"};
|
||||
static void dbaCallFunc(const iocshArgBuf *args) { dba(args[0].sval);}
|
||||
static void dbaCallFunc(const iocshArgBuf *args) { iocshSetError(dba(args[0].sval));}
|
||||
|
||||
/* dbl */
|
||||
static const iocshArg dblArg0 = { "record type",iocshArgString};
|
||||
@@ -204,7 +206,7 @@ static const iocshFuncDef dblFuncDef = {"dbl",2,dblArgs,
|
||||
" dbl(\"ai\",\"HIGH LOW VAL PREC\")\n"};
|
||||
static void dblCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbl(args[0].sval,args[1].sval);
|
||||
iocshSetError(dbl(args[0].sval,args[1].sval));
|
||||
}
|
||||
|
||||
/* dbnr */
|
||||
@@ -213,7 +215,7 @@ static const iocshArg * const dbnrArgs[1] = {&dbnrArg0};
|
||||
static const iocshFuncDef dbnrFuncDef = {"dbnr",1,dbnrArgs,
|
||||
"List number of records and aliases by type.\n"
|
||||
"If verbose, list all record types regardless of being instanced\n"};
|
||||
static void dbnrCallFunc(const iocshArgBuf *args) { dbnr(args[0].ival);}
|
||||
static void dbnrCallFunc(const iocshArgBuf *args) { iocshSetError(dbnr(args[0].ival));}
|
||||
|
||||
/* dbli */
|
||||
static const iocshArg dbliArg0 = { "pattern",iocshArgString};
|
||||
@@ -221,7 +223,7 @@ static const iocshArg * const dbliArgs[1] = {&dbliArg0};
|
||||
static const iocshFuncDef dbliFuncDef = {"dbli",1,dbliArgs,
|
||||
"List info() tags with names matching pattern.\n\n"
|
||||
"Example: dbli(\"autosave*\")\n"};
|
||||
static void dbliCallFunc(const iocshArgBuf *args) { dbli(args[0].sval);}
|
||||
static void dbliCallFunc(const iocshArgBuf *args) { iocshSetError(dbli(args[0].sval));}
|
||||
|
||||
/* dbla */
|
||||
static const iocshArg dblaArg0 = { "pattern",iocshArgStringRecord};
|
||||
@@ -229,7 +231,7 @@ static const iocshArg * const dblaArgs[1] = {&dblaArg0};
|
||||
static const iocshFuncDef dblaFuncDef = {"dbla",1,dblaArgs,
|
||||
"List record alias()s by alias name pattern.\n\n"
|
||||
"Example: dbla(\"alia*\")\n"};
|
||||
static void dblaCallFunc(const iocshArgBuf *args) { dbla(args[0].sval);}
|
||||
static void dblaCallFunc(const iocshArgBuf *args) { iocshSetError(dbla(args[0].sval));}
|
||||
|
||||
/* dbgrep */
|
||||
static const iocshArg dbgrepArg0 = { "pattern",iocshArgStringRecord};
|
||||
@@ -240,7 +242,7 @@ static const iocshFuncDef dbgrepFuncDef = {"dbgrep",1,dbgrepArgs,
|
||||
" - \"?\", which matches 0 or one characters.\n"
|
||||
" - \"*\", which matches 0 or more characters.\n\n"
|
||||
"Example: dbgrep(\"*gpibAi*\")\n"};
|
||||
static void dbgrepCallFunc(const iocshArgBuf *args) { dbgrep(args[0].sval);}
|
||||
static void dbgrepCallFunc(const iocshArgBuf *args) { iocshSetError(dbgrep(args[0].sval));}
|
||||
|
||||
/* dbgf */
|
||||
static const iocshArg dbgfArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -250,7 +252,7 @@ static const iocshFuncDef dbgfFuncDef = {"dbgf",1,dbgfArgs,
|
||||
"Print current value of record field.\n"
|
||||
"If no field name is specified, VAL is assumed.\n\n"
|
||||
"Example: dbgf(\"aitest.VAL\")\n"};
|
||||
static void dbgfCallFunc(const iocshArgBuf *args) { dbgf(args[0].sval);}
|
||||
static void dbgfCallFunc(const iocshArgBuf *args) { iocshSetError(dbgf(args[0].sval));}
|
||||
|
||||
/* dbpf */
|
||||
static const iocshArg dbpfArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -261,7 +263,7 @@ static const iocshFuncDef dbpfFuncDef = {"dbpf",2,dbpfArgs,
|
||||
"Change value of record field and read it back with dbgf.\n"
|
||||
"If no field is specified, VAL is assumed\n"};
|
||||
static void dbpfCallFunc(const iocshArgBuf *args)
|
||||
{ dbpf(args[0].sval,args[1].sval);}
|
||||
{ iocshSetError(dbpf(args[0].sval,args[1].sval));}
|
||||
|
||||
/* dbpr */
|
||||
static const iocshArg dbprArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -279,14 +281,14 @@ static const iocshFuncDef dbprFuncDef = {
|
||||
"Example: dbpr aitest 3\n"
|
||||
};
|
||||
static void dbprCallFunc(const iocshArgBuf *args)
|
||||
{ dbpr(args[0].sval,args[1].ival);}
|
||||
{ iocshSetError(dbpr(args[0].sval,args[1].ival));}
|
||||
|
||||
/* dbtr */
|
||||
static const iocshArg dbtrArg0 = { "record name",iocshArgStringRecord};
|
||||
static const iocshArg * const dbtrArgs[1] = {&dbtrArg0};
|
||||
static const iocshFuncDef dbtrFuncDef = {"dbtr",1,dbtrArgs,
|
||||
"Process record and then some fields.\n"};
|
||||
static void dbtrCallFunc(const iocshArgBuf *args) { dbtr(args[0].sval);}
|
||||
static void dbtrCallFunc(const iocshArgBuf *args) { iocshSetError(dbtr(args[0].sval));}
|
||||
|
||||
/* dbtgf */
|
||||
static const iocshArg dbtgfArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -296,7 +298,7 @@ static const iocshFuncDef dbtgfFuncDef = {"dbtgf",1,dbtgfArgs,
|
||||
"Get and print the specified field with all possible DBR_* types\n"
|
||||
"Example: dbtgf aitest\n"
|
||||
"Example: dbtgf aitest.VAL\n"};
|
||||
static void dbtgfCallFunc(const iocshArgBuf *args) { dbtgf(args[0].sval);}
|
||||
static void dbtgfCallFunc(const iocshArgBuf *args) { iocshSetError(dbtgf(args[0].sval));}
|
||||
|
||||
/* dbtpf */
|
||||
static const iocshArg dbtpfArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -308,7 +310,7 @@ static const iocshFuncDef dbtpfFuncDef = {"dbtpf",2,dbtpfArgs,
|
||||
"for all possible DBR_* types\n\n"
|
||||
"Example: dbtpf aitest 5.0\n"};
|
||||
static void dbtpfCallFunc(const iocshArgBuf *args)
|
||||
{ dbtpf(args[0].sval,args[1].sval);}
|
||||
{ iocshSetError(dbtpf(args[0].sval,args[1].sval));}
|
||||
|
||||
/* dbior */
|
||||
static const iocshArg dbiorArg0 = { "driver name",iocshArgString};
|
||||
@@ -317,7 +319,7 @@ static const iocshArg * const dbiorArgs[] = {&dbiorArg0,&dbiorArg1};
|
||||
static const iocshFuncDef dbiorFuncDef = {"dbior",2,dbiorArgs,
|
||||
"Driver Report.\n"};
|
||||
static void dbiorCallFunc(const iocshArgBuf *args)
|
||||
{ dbior(args[0].sval,args[1].ival);}
|
||||
{ iocshSetError(dbior(args[0].sval,args[1].ival));}
|
||||
|
||||
/* dbhcr */
|
||||
static const iocshFuncDef dbhcrFuncDef = {"dbhcr",0,0,
|
||||
@@ -327,7 +329,7 @@ static const iocshFuncDef dbhcrFuncDef = {"dbhcr",0,0,
|
||||
"Use the UNIX sort command:\n"
|
||||
"dbhcr > report\n"
|
||||
"sort report > report.sorted\n"};
|
||||
static void dbhcrCallFunc(const iocshArgBuf *args) { dbhcr();}
|
||||
static void dbhcrCallFunc(const iocshArgBuf *args) { iocshSetError(dbhcr());}
|
||||
|
||||
/* gft */
|
||||
static const iocshArg gftArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -336,7 +338,7 @@ static const iocshFuncDef gftFuncDef = {"gft",1,gftArgs,
|
||||
"Report dbChannel info and value.\n"
|
||||
"Example: gft aitest\n"
|
||||
"Example: gft aitest.VAL\n"};
|
||||
static void gftCallFunc(const iocshArgBuf *args) { gft(args[0].sval);}
|
||||
static void gftCallFunc(const iocshArgBuf *args) { iocshSetError(gft(args[0].sval));}
|
||||
|
||||
/* pft */
|
||||
static const iocshArg pftArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -346,7 +348,7 @@ static const iocshFuncDef pftFuncDef = {"pft",2,pftArgs,
|
||||
"dbChannel put value.\n"
|
||||
"Example: pft aitest 5.0\n"};
|
||||
static void pftCallFunc(const iocshArgBuf *args)
|
||||
{ pft(args[0].sval,args[1].sval);}
|
||||
{ iocshSetError(pft(args[0].sval,args[1].sval));}
|
||||
|
||||
/* dbtpn */
|
||||
static const iocshArg dbtpnArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -359,12 +361,12 @@ static const iocshFuncDef dbtpnFuncDef = {"dbtpn",2,dbtpnArgs,
|
||||
"Example: dbtpn aitest\n"
|
||||
"Example: dbtpn aitest 5.0\n"};
|
||||
static void dbtpnCallFunc(const iocshArgBuf *args)
|
||||
{ dbtpn(args[0].sval,args[1].sval);}
|
||||
{ iocshSetError(dbtpn(args[0].sval,args[1].sval));}
|
||||
|
||||
/* dbNotifyDump */
|
||||
static const iocshFuncDef dbNotifyDumpFuncDef = {"dbNotifyDump",0,0,
|
||||
"Report status of any active async processing with completion notification.\n"};
|
||||
static void dbNotifyDumpCallFunc(const iocshArgBuf *args) { dbNotifyDump();}
|
||||
static void dbNotifyDumpCallFunc(const iocshArgBuf *args) { iocshSetError(dbNotifyDump());}
|
||||
|
||||
/* dbPutAttribute */
|
||||
static const iocshArg dbPutAttrArg0 = { "record type",iocshArgString};
|
||||
@@ -375,7 +377,7 @@ static const iocshArg * const dbPutAttrArgs[] =
|
||||
static const iocshFuncDef dbPutAttrFuncDef = {"dbPutAttribute",3,dbPutAttrArgs,
|
||||
"Set/Create record attribute.\n"};
|
||||
static void dbPutAttrCallFunc(const iocshArgBuf *args)
|
||||
{ dbPutAttribute(args[0].sval,args[1].sval,args[2].sval);}
|
||||
{ iocshSetError(dbPutAttribute(args[0].sval,args[1].sval,args[2].sval));}
|
||||
|
||||
/* tpn */
|
||||
static const iocshArg tpnArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -385,7 +387,7 @@ static const iocshFuncDef tpnFuncDef = {"tpn",2,tpnArgs,
|
||||
"Test Process Notify.\n\n"
|
||||
"Example: tpn aitest 5.0\n"};
|
||||
static void tpnCallFunc(const iocshArgBuf *args)
|
||||
{ tpn(args[0].sval,args[1].sval);}
|
||||
{ iocshSetError(tpn(args[0].sval,args[1].sval));}
|
||||
|
||||
/* dblsr */
|
||||
static const iocshArg dblsrArg0 = { "record name",iocshArgStringRecord};
|
||||
@@ -399,7 +401,7 @@ static const iocshFuncDef dblsrFuncDef = {"dblsr",2,dblsrArgs,
|
||||
" 2 - Show each record and all database links in the lock set.\n\n"
|
||||
"Example: dblsr aitest 2\n"};
|
||||
static void dblsrCallFunc(const iocshArgBuf *args)
|
||||
{ dblsr(args[0].sval,args[1].ival);}
|
||||
{ iocshSetError(dblsr(args[0].sval,args[1].ival));}
|
||||
|
||||
/* dbLockShowLocked */
|
||||
static const iocshArg dbLockShowLockedArg0 = { "interest level",iocshArgInt};
|
||||
@@ -412,7 +414,7 @@ static const iocshFuncDef dbLockShowLockedFuncDef = {
|
||||
"Example: dbLockShowLocked 0\n"
|
||||
};
|
||||
static void dbLockShowLockedCallFunc(const iocshArgBuf *args)
|
||||
{ dbLockShowLocked(args[0].ival);}
|
||||
{ iocshSetError(dbLockShowLocked(args[0].ival));}
|
||||
|
||||
/* scanOnceSetQueueSize */
|
||||
static const iocshArg scanOnceSetQueueSizeArg0 = { "size",iocshArgInt};
|
||||
@@ -423,7 +425,7 @@ static const iocshFuncDef scanOnceSetQueueSizeFuncDef = {"scanOnceSetQueueSize",
|
||||
"Must be called before iocInit().\n"};
|
||||
static void scanOnceSetQueueSizeCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
scanOnceSetQueueSize(args[0].ival);
|
||||
iocshSetError(scanOnceSetQueueSize(args[0].ival));
|
||||
}
|
||||
|
||||
/* scanOnceQueueShow */
|
||||
@@ -444,7 +446,7 @@ static const iocshFuncDef scanpplFuncDef = {"scanppl",1,scanpplArgs,
|
||||
"Print info for records with periodic scan.\n"
|
||||
"If rate == 0.0, all periods are shown.\n"};
|
||||
static void scanpplCallFunc(const iocshArgBuf *args)
|
||||
{ scanppl(args[0].dval);}
|
||||
{ iocshSetError(scanppl(args[0].dval));}
|
||||
|
||||
/* scanpel */
|
||||
static const iocshArg scanpelArg0 = { "event name",iocshArgString};
|
||||
@@ -452,7 +454,7 @@ static const iocshArg * const scanpelArgs[1] = {&scanpelArg0};
|
||||
static const iocshFuncDef scanpelFuncDef = {"scanpel",1,scanpelArgs,
|
||||
"Print info for records with SCAN = \"Event\".\n"};
|
||||
static void scanpelCallFunc(const iocshArgBuf *args)
|
||||
{ scanpel(args[0].sval);}
|
||||
{ iocshSetError(scanpel(args[0].sval));}
|
||||
|
||||
/* postEvent */
|
||||
static const iocshArg postEventArg0 = { "event name",iocshArgString};
|
||||
@@ -468,7 +470,7 @@ static void postEventCallFunc(const iocshArgBuf *args)
|
||||
/* scanpiol */
|
||||
static const iocshFuncDef scanpiolFuncDef = {"scanpiol",0,0,
|
||||
"Print info for records with SCAN = \"I/O Intr\".\n"};
|
||||
static void scanpiolCallFunc(const iocshArgBuf *args) { scanpiol();}
|
||||
static void scanpiolCallFunc(const iocshArgBuf *args) { iocshSetError(scanpiol());}
|
||||
|
||||
/* callbackSetQueueSize */
|
||||
static const iocshArg callbackSetQueueSizeArg0 = { "bufsize",iocshArgInt};
|
||||
@@ -479,7 +481,7 @@ static const iocshFuncDef callbackSetQueueSizeFuncDef = {"callbackSetQueueSize",
|
||||
"Must be called before iocInit().\n"};
|
||||
static void callbackSetQueueSizeCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
callbackSetQueueSize(args[0].ival);
|
||||
iocshSetError(callbackSetQueueSize(args[0].ival));
|
||||
}
|
||||
|
||||
/* callbackQueueShow */
|
||||
@@ -504,7 +506,7 @@ static const iocshFuncDef callbackParallelThreadsFuncDef = {"callbackParallelThr
|
||||
"or one of LOW, MEDIUM, or HIGH.\n"};
|
||||
static void callbackParallelThreadsCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
callbackParallelThreads(args[0].ival, args[1].sval);
|
||||
iocshSetError(callbackParallelThreads(args[0].ival, args[1].sval));
|
||||
}
|
||||
|
||||
/* dbStateCreate */
|
||||
@@ -514,7 +516,8 @@ static const iocshFuncDef dbStateCreateFuncDef = {"dbStateCreate", 1, dbStateCre
|
||||
"Allocate new state name for \"state\" filter.\n"};
|
||||
static void dbStateCreateCallFunc (const iocshArgBuf *args)
|
||||
{
|
||||
dbStateCreate(args[0].sval);
|
||||
if (!dbStateCreate(args[0].sval))
|
||||
iocshSetError(-1);
|
||||
}
|
||||
|
||||
/* dbStateSet */
|
||||
@@ -527,6 +530,8 @@ static void dbStateSetCallFunc (const iocshArgBuf *args)
|
||||
|
||||
if (sid)
|
||||
dbStateSet(sid);
|
||||
else
|
||||
iocshSetError(-1);
|
||||
}
|
||||
|
||||
/* dbStateClear */
|
||||
@@ -539,6 +544,8 @@ static void dbStateClearCallFunc (const iocshArgBuf *args)
|
||||
|
||||
if (sid)
|
||||
dbStateClear(sid);
|
||||
else
|
||||
iocshSetError(-1);
|
||||
}
|
||||
|
||||
/* dbStateShow */
|
||||
@@ -552,6 +559,8 @@ static void dbStateShowCallFunc (const iocshArgBuf *args)
|
||||
|
||||
if (sid)
|
||||
dbStateShow(sid, args[1].ival);
|
||||
else
|
||||
iocshSetError(-1);
|
||||
}
|
||||
|
||||
/* dbStateShowAll */
|
||||
|
||||
@@ -391,6 +391,10 @@ typedef struct lset {
|
||||
#define dbGetSevr(link, sevr) \
|
||||
dbGetAlarm(link, NULL, sevr)
|
||||
|
||||
/** @brief Lookup link field name from pointer.
|
||||
* Returns only field name. aka. value of ``dbFldDes::name``
|
||||
* @since 3.16.2
|
||||
*/
|
||||
DBCORE_API const char * dbLinkFieldName(const struct link *plink);
|
||||
|
||||
DBCORE_API void dbInitLink(struct link *plink, short dbfType);
|
||||
|
||||
@@ -127,6 +127,31 @@ int dbServerClient(char *pBuf, size_t bufSize)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dbServerStats(const char *name, unsigned *channels, unsigned *clients)
|
||||
{
|
||||
dbServer *psrv = (dbServer *)ellFirst(&serverList);
|
||||
if (state != running || !psrv)
|
||||
return -1;
|
||||
|
||||
unsigned tch = 0, tcl = 0, nmatch = 0;
|
||||
for (; psrv; psrv = (dbServer *)ellNext(&psrv->node)) {
|
||||
if (psrv->stats &&
|
||||
(!name || strcmp(name, psrv->name) == 0)) {
|
||||
unsigned lch = 0, lcl = 0;
|
||||
|
||||
psrv->stats(&lch, &lcl);
|
||||
tch += lch;
|
||||
tcl += lcl;
|
||||
nmatch++;
|
||||
if (name)
|
||||
break; /* No duplicate names in serverList */
|
||||
}
|
||||
}
|
||||
if (channels) *channels = tch;
|
||||
if (clients) *clients = tcl;
|
||||
return nmatch;
|
||||
}
|
||||
|
||||
#define STARTSTOP(routine, method, newState) \
|
||||
void routine(void) \
|
||||
{ \
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
* the dbServer interface provides allow the IOC to start, pause and stop
|
||||
* the servers together, and to provide status and debugging information
|
||||
* to the IOC user/developer through a common set of commands.
|
||||
*
|
||||
* @todo No API is provided yet for calling stats() methods.
|
||||
* Nothing in the IOC calls dbStopServers(), not sure where it should go.
|
||||
*/
|
||||
|
||||
#ifndef INC_dbServer_H
|
||||
@@ -59,8 +56,8 @@ typedef struct dbServer {
|
||||
|
||||
/** @brief Get number of channels and clients currently connected.
|
||||
*
|
||||
* @param channels NULL or pointer for returning channel count.
|
||||
* @param clients NULL or pointer for returning client count.
|
||||
* @param channels @c NULL or pointer for returning channel count.
|
||||
* @param clients @c NULL or pointer for returning client count.
|
||||
*/
|
||||
void (* stats) (unsigned *channels, unsigned *clients);
|
||||
|
||||
@@ -145,6 +142,30 @@ DBCORE_API void dbsr(unsigned level);
|
||||
*/
|
||||
DBCORE_API int dbServerClient(char *pBuf, size_t bufSize);
|
||||
|
||||
/** @brief CPP Macro indicating the dbServerStats() routine exists.
|
||||
* @since UNRELEASED
|
||||
*/
|
||||
#define HAS_DBSERVER_STATS
|
||||
|
||||
/** @brief Fetch statistics from server layers.
|
||||
*
|
||||
* This is an API for iocStats and similar to fetch the number of channels
|
||||
* and clients connected to the registered server layers.
|
||||
* If the name given is NULL the statistics returned are the totals from
|
||||
* all registered server layers, otherwise just from the named server.
|
||||
* @param name Server name
|
||||
* @param channels NULL, or where to return the channel count
|
||||
* @param clients NULL or where to return the client count
|
||||
* @returns -1 if the IOC isn't running or no servers are registered, without
|
||||
* writing to the statistics variables. Otherwise it writes to the statistics
|
||||
* variables and returns the number of dbServer::stats() methods called,
|
||||
* 0 if a named server wasn't found or doesn't have a stats() method.
|
||||
*
|
||||
* @since UNRELEASED
|
||||
*/
|
||||
DBCORE_API int dbServerStats(const char *name, unsigned *channels,
|
||||
unsigned *clients);
|
||||
|
||||
/** @brief Initialize all registered servers.
|
||||
*
|
||||
* Calls all dbServer::init() methods.
|
||||
|
||||
@@ -202,7 +202,6 @@ void testdbGetFieldEqual(const char* pv, int dbrType, ...)
|
||||
void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
{
|
||||
dbChannel *chan = dbChannelCreate(pv);
|
||||
db_field_log *pfl = NULL;
|
||||
long nReq = 1;
|
||||
union anybuf pod;
|
||||
long status = S_dbLib_recNotFound;
|
||||
@@ -212,18 +211,7 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(ellCount(&chan->filters)) {
|
||||
pfl = db_create_read_log(chan);
|
||||
if (!pfl) {
|
||||
testFail("can't db_create_read_log w/ %s", pv);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pfl = dbChannelRunPreChain(chan, pfl);
|
||||
pfl = dbChannelRunPostChain(chan, pfl);
|
||||
}
|
||||
|
||||
status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, pfl);
|
||||
status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, NULL);
|
||||
if (status) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status));
|
||||
goto done;
|
||||
@@ -261,7 +249,6 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
}
|
||||
|
||||
done:
|
||||
db_delete_field_log(pfl);
|
||||
if(chan)
|
||||
dbChannelDelete(chan);
|
||||
}
|
||||
@@ -288,7 +275,6 @@ done:
|
||||
void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long cnt, const void *pbufraw)
|
||||
{
|
||||
dbChannel *chan = dbChannelCreate(pv);
|
||||
db_field_log *pfl = NULL;
|
||||
const long vSize = dbValueSize(dbfType);
|
||||
const long nStore = vSize * nRequest;
|
||||
long status = S_dbLib_recNotFound;
|
||||
@@ -300,24 +286,13 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(ellCount(&chan->filters)) {
|
||||
pfl = db_create_read_log(chan);
|
||||
if (!pfl) {
|
||||
testFail("can't db_create_read_log w/ %s", pv);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pfl = dbChannelRunPreChain(chan, pfl);
|
||||
pfl = dbChannelRunPostChain(chan, pfl);
|
||||
}
|
||||
|
||||
gbuf = gstore = malloc(nStore);
|
||||
if(!gbuf && nStore!=0) { /* note that malloc(0) is allowed to return NULL on success */
|
||||
testFail("Allocation failed esize=%ld total=%ld", vSize, nStore);
|
||||
return;
|
||||
}
|
||||
|
||||
status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, pfl);
|
||||
status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, NULL);
|
||||
if (status) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status);
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ int dbChannel_get_count(
|
||||
long options;
|
||||
long i;
|
||||
long zero = 0;
|
||||
unsigned char local_fl = 0;
|
||||
|
||||
/* The order of the DBR* elements in the "newSt" structures below is
|
||||
* very important and must correspond to the order of processing
|
||||
@@ -156,6 +157,16 @@ int dbChannel_get_count(
|
||||
|
||||
dbScanLock(dbChannelRecord(chan));
|
||||
|
||||
/* If filters are involved in a read, create field log and run filters */
|
||||
if (!pfl && (ellCount(&chan->pre_chain) || ellCount(&chan->post_chain))) {
|
||||
pfl = db_create_read_log(chan);
|
||||
if (pfl) {
|
||||
local_fl = 1;
|
||||
pfl = dbChannelRunPreChain(chan, pfl);
|
||||
pfl = dbChannelRunPostChain(chan, pfl);
|
||||
}
|
||||
}
|
||||
|
||||
switch(buffer_type) {
|
||||
case(oldDBR_STRING):
|
||||
status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl);
|
||||
@@ -800,6 +811,8 @@ int dbChannel_get_count(
|
||||
|
||||
dbScanUnlock(dbChannelRecord(chan));
|
||||
|
||||
if (local_fl) db_delete_field_log(pfl);
|
||||
|
||||
if (status) return -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1029,3 +1042,17 @@ int db_put_process(processNotify *ppn, notifyPutType type,
|
||||
ppn->status = notifyError;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void db_process(struct dbCommon *prec)
|
||||
{
|
||||
if (prec->pact) {
|
||||
if (dbAccessDebugPUTF && prec->tpro)
|
||||
printf("%s: dbPutField to Active '%s', setting RPRO=1\n",
|
||||
epicsThreadGetNameSelf(), prec->name);
|
||||
prec->rpro = TRUE;
|
||||
} else {
|
||||
/* indicate that dbPutField called dbProcess */
|
||||
prec->putf = TRUE;
|
||||
(void)dbProcess(prec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ extern "C" {
|
||||
|
||||
#include "dbCoreAPI.h"
|
||||
|
||||
struct dbCommon;
|
||||
|
||||
DBCORE_API extern struct dbBase *pdbbase;
|
||||
DBCORE_API extern volatile int interruptAccept;
|
||||
|
||||
@@ -36,7 +38,9 @@ DBCORE_API int dbChannel_put(struct dbChannel *chan, int src_type,
|
||||
const void *psrc, long no_elements);
|
||||
DBCORE_API int dbChannel_get_count(struct dbChannel *chan,
|
||||
int buffer_type, void *pbuffer, long *nRequest, void *pfl);
|
||||
|
||||
#ifdef EPICS_DBCA_PRIVATE_API
|
||||
DBCORE_API void db_process(struct dbCommon *prec);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -260,8 +260,8 @@ int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr)
|
||||
return recGblSetSevrMsg(precord, new_stat, new_sevr, NULL);
|
||||
}
|
||||
|
||||
void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr)
|
||||
void recGblInheritSevrMsg(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr, const char *msg)
|
||||
{
|
||||
switch (msMode) {
|
||||
case pvlOptNMS:
|
||||
@@ -274,11 +274,17 @@ void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat,
|
||||
recGblSetSevr(precord, LINK_ALARM, sevr);
|
||||
break;
|
||||
case pvlOptMSS:
|
||||
recGblSetSevr(precord, stat, sevr);
|
||||
/* Only MSS inherits msg */
|
||||
recGblSetSevrMsg(precord, stat, sevr, "%s", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr)
|
||||
{
|
||||
recGblInheritSevrMsg(msMode, precord, stat, sevr, NULL);
|
||||
}
|
||||
|
||||
void recGblFwdLink(void *precord)
|
||||
{
|
||||
|
||||
@@ -73,6 +73,8 @@ DBCORE_API int recGblSetSevr(void *precord, epicsEnum16 new_stat,
|
||||
epicsEnum16 new_sevr);
|
||||
DBCORE_API void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr);
|
||||
DBCORE_API void recGblInheritSevrMsg(int msMode, void *precord, epicsEnum16 stat,
|
||||
epicsEnum16 sevr, const char *msg);
|
||||
DBCORE_API int recGblSetSevrMsg(void *precord, epicsEnum16 new_stat,
|
||||
epicsEnum16 new_sevr,
|
||||
EPICS_PRINTF_FMT(const char *msg), ...) EPICS_PRINTF_STYLE(4,5);
|
||||
|
||||
@@ -207,7 +207,7 @@ static const iocshFuncDef dbPvdTableSizeFuncDef = {
|
||||
};
|
||||
static void dbPvdTableSizeCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dbPvdTableSize(args[0].ival);
|
||||
iocshSetError(dbPvdTableSize(args[0].ival));
|
||||
}
|
||||
|
||||
/* dbReportDeviceConfig */
|
||||
|
||||
@@ -14,6 +14,7 @@ SRC_DIRS += $(IOCDIR)/dbtemplate
|
||||
PROD_CMD += msi
|
||||
|
||||
msi_SRCS = msi.cpp
|
||||
msi_SYS_LIBS_WIN32 = shlwapi
|
||||
DOCS += msi.md
|
||||
|
||||
INC += dbLoadTemplate.h
|
||||
|
||||
@@ -41,6 +41,17 @@ static int var_count, sub_count;
|
||||
int dbTemplateMaxVars = 100;
|
||||
epicsExportAddress(int, dbTemplateMaxVars);
|
||||
|
||||
static
|
||||
int msiLoadRecords(const char *fname, const char *subs)
|
||||
{
|
||||
int ret = dbLoadRecords(fname, subs);
|
||||
if(ret) {
|
||||
fprintf(stderr, "dbLoadRecords(\"%s\", %s)\n", fname, subs);
|
||||
yyerror("Error while reading included file");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%start substitution_file
|
||||
@@ -167,7 +178,7 @@ pattern_definition: global_definitions
|
||||
fprintf(stderr, "pattern_definition: pattern_values empty\n");
|
||||
fprintf(stderr, " dbLoadRecords(%s)\n", sub_collect+1);
|
||||
#endif
|
||||
dbLoadRecords(db_file_name, sub_collect+1);
|
||||
if(msiLoadRecords(db_file_name, sub_collect+1)) YYABORT;
|
||||
}
|
||||
| O_BRACE pattern_values C_BRACE
|
||||
{
|
||||
@@ -175,7 +186,7 @@ pattern_definition: global_definitions
|
||||
fprintf(stderr, "pattern_definition:\n");
|
||||
fprintf(stderr, " dbLoadRecords(%s)\n", sub_collect+1);
|
||||
#endif
|
||||
dbLoadRecords(db_file_name, sub_collect+1);
|
||||
if(msiLoadRecords(db_file_name, sub_collect+1)) YYABORT;
|
||||
*sub_locals = '\0';
|
||||
sub_count = 0;
|
||||
}
|
||||
@@ -190,7 +201,7 @@ pattern_definition: global_definitions
|
||||
fprintf(stderr, "pattern_definition:\n");
|
||||
fprintf(stderr, " dbLoadRecords(%s)\n", sub_collect+1);
|
||||
#endif
|
||||
dbLoadRecords(db_file_name, sub_collect+1);
|
||||
if(msiLoadRecords(db_file_name, sub_collect+1)) YYABORT;
|
||||
dbmfFree($1);
|
||||
*sub_locals = '\0';
|
||||
sub_count = 0;
|
||||
@@ -250,7 +261,7 @@ variable_substitution: global_definitions
|
||||
fprintf(stderr, "variable_substitution: variable_definitions empty\n");
|
||||
fprintf(stderr, " dbLoadRecords(%s)\n", sub_collect+1);
|
||||
#endif
|
||||
dbLoadRecords(db_file_name, sub_collect+1);
|
||||
if(msiLoadRecords(db_file_name, sub_collect+1)) YYABORT;
|
||||
}
|
||||
| O_BRACE variable_definitions C_BRACE
|
||||
{
|
||||
@@ -258,7 +269,7 @@ variable_substitution: global_definitions
|
||||
fprintf(stderr, "variable_substitution:\n");
|
||||
fprintf(stderr, " dbLoadRecords(%s)\n", sub_collect+1);
|
||||
#endif
|
||||
dbLoadRecords(db_file_name, sub_collect+1);
|
||||
if(msiLoadRecords(db_file_name, sub_collect+1)) YYABORT;
|
||||
*sub_locals = '\0';
|
||||
}
|
||||
| WORD O_BRACE variable_definitions C_BRACE
|
||||
@@ -272,7 +283,7 @@ variable_substitution: global_definitions
|
||||
fprintf(stderr, "variable_substitution:\n");
|
||||
fprintf(stderr, " dbLoadRecords(%s)\n", sub_collect+1);
|
||||
#endif
|
||||
dbLoadRecords(db_file_name, sub_collect+1);
|
||||
if(msiLoadRecords(db_file_name, sub_collect+1)) YYABORT;
|
||||
dbmfFree($1);
|
||||
*sub_locals = '\0';
|
||||
}
|
||||
@@ -328,6 +339,7 @@ int dbLoadTemplate(const char *sub_file, const char *cmd_collect)
|
||||
{
|
||||
FILE *fp;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
line_num = 1;
|
||||
|
||||
@@ -377,7 +389,7 @@ int dbLoadTemplate(const char *sub_file, const char *cmd_collect)
|
||||
yyrestart(fp);
|
||||
}
|
||||
|
||||
yyparse();
|
||||
err = yyparse();
|
||||
|
||||
for (i = 0; i < var_count; i++) {
|
||||
dbmfFree(vars[i]);
|
||||
@@ -390,5 +402,5 @@ int dbLoadTemplate(const char *sub_file, const char *cmd_collect)
|
||||
dbmfFree(db_file_name);
|
||||
db_file_name = NULL;
|
||||
}
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#include <osiFileName.h>
|
||||
#include <osiUnistd.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <shlwapi.h>
|
||||
#endif
|
||||
|
||||
#define MAX_BUFFER_SIZE 4096
|
||||
#define MAX_DEPS 1024
|
||||
|
||||
@@ -61,7 +65,7 @@ typedef struct inputData inputData;
|
||||
static void inputConstruct(inputData **ppvt);
|
||||
static void inputDestruct(inputData * const pvt);
|
||||
static void inputAddPath(inputData * const pvt, const char * const pval);
|
||||
static void inputBegin(inputData * const pvt, const char * const fileName);
|
||||
static void inputBegin(inputData * const pvt, const char * const fileName, bool fromCmdLine);
|
||||
static char *inputNextLine(inputData * const pvt);
|
||||
static void inputNewIncludeFile(inputData * const pvt, const char * const name);
|
||||
static void inputErrPrint(const inputData * const pvt);
|
||||
@@ -83,7 +87,8 @@ static void addMacroReplacements(MAC_HANDLE * const macPvt,
|
||||
const char * const pval);
|
||||
static void makeSubstitutions(inputData * const inputPvt,
|
||||
MAC_HANDLE * const macPvt,
|
||||
const char * const templateName);
|
||||
const char * const templateName,
|
||||
bool fromCmdLine);
|
||||
|
||||
/*Global variables */
|
||||
static int opt_V = 0;
|
||||
@@ -171,7 +176,7 @@ int main(int argc,char **argv)
|
||||
|
||||
if (substitutionName.empty()) {
|
||||
STEP("Single template+substitutions file");
|
||||
makeSubstitutions(inputPvt, macPvt, templateName);
|
||||
makeSubstitutions(inputPvt, macPvt, templateName, true);
|
||||
}
|
||||
else {
|
||||
subInfo *substitutePvt;
|
||||
@@ -203,7 +208,7 @@ int main(int argc,char **argv)
|
||||
macPushScope(macPvt);
|
||||
|
||||
addMacroReplacements(macPvt, macStr);
|
||||
makeSubstitutions(inputPvt, macPvt, filename);
|
||||
makeSubstitutions(inputPvt, macPvt, filename, false);
|
||||
|
||||
if (localScope)
|
||||
macPopScope(macPvt);
|
||||
@@ -276,14 +281,15 @@ static const char *cmdNames[] = {"include","substitute"};
|
||||
|
||||
static void makeSubstitutions(inputData * const inputPvt,
|
||||
MAC_HANDLE * const macPvt,
|
||||
const char * const templateName)
|
||||
const char * const templateName,
|
||||
bool fromCmdLine)
|
||||
{
|
||||
char *input;
|
||||
static char buffer[MAX_BUFFER_SIZE];
|
||||
int n;
|
||||
|
||||
ENTER;
|
||||
inputBegin(inputPvt, templateName);
|
||||
inputBegin(inputPvt, templateName, fromCmdLine);
|
||||
while ((input = inputNextLine(inputPvt))) {
|
||||
int expand=1;
|
||||
char *p;
|
||||
@@ -378,7 +384,7 @@ struct inputData {
|
||||
inputData() { memset(inputBuffer, 0, sizeof(inputBuffer) * sizeof(inputBuffer[0])); };
|
||||
};
|
||||
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename);
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename, bool fromCmdLine);
|
||||
static void inputCloseFile(inputData *pinputData);
|
||||
static void inputCloseAllFiles(inputData *pinputData);
|
||||
|
||||
@@ -431,11 +437,11 @@ static void inputAddPath(inputData * const pinputData, const char * const path)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputBegin(inputData * const pinputData, const char * const fileName)
|
||||
static void inputBegin(inputData * const pinputData, const char * const fileName, bool fromCmdLine)
|
||||
{
|
||||
ENTER;
|
||||
inputCloseAllFiles(pinputData);
|
||||
inputOpenFile(pinputData, fileName);
|
||||
inputOpenFile(pinputData, fileName, fromCmdLine);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
@@ -462,7 +468,7 @@ static void inputNewIncludeFile(inputData * const pinputData,
|
||||
const char * const name)
|
||||
{
|
||||
ENTER;
|
||||
inputOpenFile(pinputData,name);
|
||||
inputOpenFile(pinputData, name, false);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
@@ -493,7 +499,15 @@ static void inputErrPrint(const inputData *const pinputData)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename)
|
||||
static int isPathRelative(const char * const path) {
|
||||
#ifdef _WIN32
|
||||
return path && PathIsRelativeA(path);
|
||||
#else
|
||||
return path && path[0] != '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename, bool fromCmdLine)
|
||||
{
|
||||
std::list<std::string>& pathList = pinputData->pathList;
|
||||
std::list<std::string>::iterator pathIt = pathList.end();
|
||||
@@ -505,7 +519,7 @@ static void inputOpenFile(inputData *pinputData, const char * const filename)
|
||||
STEP("Using stdin");
|
||||
fp = stdin;
|
||||
}
|
||||
else if (pathList.empty() || strchr(filename, '/')){
|
||||
else if (fromCmdLine || pathList.empty() || !isPathRelative(filename)){
|
||||
STEPS("Opening ", filename);
|
||||
fp = fopen(filename, "r");
|
||||
}
|
||||
|
||||
@@ -60,6 +60,18 @@ Switches have the following meanings:
|
||||
2. . (the current directory)
|
||||
3. .. (the parent of the current directory)
|
||||
|
||||
Note that relative path searching is handled as
|
||||
|
||||
$ cat foo.substitutions
|
||||
file rel/path/bar.template {
|
||||
# contents
|
||||
}
|
||||
$ msi -I . -I /some/path foo.substitutions
|
||||
|
||||
which will try to find `bar.template` at the path `./rel/path/` followed by
|
||||
`/some/path/rel/path`.
|
||||
|
||||
|
||||
- **-M _substitutions_**
|
||||
|
||||
This parameter specifies macro values for the template instance.
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
#include "iocsh.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
IOCSH_STATIC_FUNC void dlload(const char* name)
|
||||
IOCSH_STATIC_FUNC int dlload(const char* name)
|
||||
{
|
||||
if (!epicsLoadLibrary(name)) {
|
||||
printf("epicsLoadLibrary failed: %s\n", epicsLoadError());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const iocshArg dlloadArg0 = { "path/library.so", iocshArgStringPath};
|
||||
@@ -28,7 +30,7 @@ static const iocshFuncDef dlloadFuncDef = {
|
||||
};
|
||||
static void dlloadCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
dlload(args[0].sval);
|
||||
iocshSetError(dlload(args[0].sval));
|
||||
}
|
||||
|
||||
static void dlloadRegistar(void) {
|
||||
|
||||
@@ -22,6 +22,9 @@ enum iocStateEnum {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Query present IOC run state
|
||||
* @since 3.15.8
|
||||
*/
|
||||
DBCORE_API enum iocStateEnum getIocState(void);
|
||||
DBCORE_API int iocInit(void);
|
||||
DBCORE_API int iocBuild(void);
|
||||
|
||||
@@ -540,7 +540,6 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
|
||||
const int readAccess = asCheckGet ( pciu->asClientPVT );
|
||||
int status;
|
||||
int autosize;
|
||||
int local_fl = 0;
|
||||
long item_count;
|
||||
ca_uint32_t payload_size;
|
||||
dbAddr *paddr=&dbch->addr;
|
||||
@@ -582,21 +581,9 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
|
||||
return;
|
||||
}
|
||||
|
||||
/* If filters are involved in a read, create field log and run filters */
|
||||
if (!pfl && (ellCount(&dbch->pre_chain) || ellCount(&dbch->post_chain))) {
|
||||
pfl = db_create_read_log(dbch);
|
||||
if (pfl) {
|
||||
local_fl = 1;
|
||||
pfl = dbChannelRunPreChain(dbch, pfl);
|
||||
pfl = dbChannelRunPostChain(dbch, pfl);
|
||||
}
|
||||
}
|
||||
|
||||
status = dbChannel_get_count ( dbch, pevext->msg.m_dataType,
|
||||
pPayload, &item_count, pfl);
|
||||
|
||||
if (local_fl) db_delete_field_log(pfl);
|
||||
|
||||
if ( status < 0 ) {
|
||||
/* Clients recv the status of the operation directly to the
|
||||
* event/put/get callback. (from CA_V41())
|
||||
@@ -663,7 +650,6 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p
|
||||
ca_uint32_t payloadSize;
|
||||
void *pPayload;
|
||||
int status;
|
||||
int local_fl = 0;
|
||||
db_field_log *pfl = NULL;
|
||||
|
||||
if ( ! pciu ) {
|
||||
@@ -702,21 +688,9 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
/* If filters are involved in a read, create field log and run filters */
|
||||
if (ellCount(&pciu->dbch->pre_chain) || ellCount(&pciu->dbch->post_chain)) {
|
||||
pfl = db_create_read_log(pciu->dbch);
|
||||
if (pfl) {
|
||||
local_fl = 1;
|
||||
pfl = dbChannelRunPreChain(pciu->dbch, pfl);
|
||||
pfl = dbChannelRunPostChain(pciu->dbch, pfl);
|
||||
}
|
||||
}
|
||||
|
||||
status = dbChannel_get ( pciu->dbch, mp->m_dataType,
|
||||
pPayload, mp->m_count, pfl );
|
||||
|
||||
if (local_fl) db_delete_field_log(pfl);
|
||||
|
||||
if ( status < 0 ) {
|
||||
send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( pciu->dbch ) );
|
||||
SEND_UNLOCK ( pClient );
|
||||
|
||||
@@ -163,9 +163,11 @@ void camsgtask ( void *pParm )
|
||||
|
||||
int casClientInitiatingCurrentThread ( char * pBuf, size_t bufSize )
|
||||
{
|
||||
struct client * pClient = ( struct client * )
|
||||
epicsThreadPrivateGet ( rsrvCurrentClient );
|
||||
struct client * pClient;
|
||||
if ( ! rsrvCurrentClient )
|
||||
return RSRV_ERROR; /* not yet initialized, or disabled via dbServer */
|
||||
|
||||
pClient = ( struct client * ) epicsThreadPrivateGet ( rsrvCurrentClient );
|
||||
if ( ! pClient )
|
||||
return RSRV_ERROR;
|
||||
|
||||
|
||||
@@ -1536,6 +1536,13 @@ struct client *create_tcp_client (SOCKET sock , const osiSockAddr *peerAddr)
|
||||
|
||||
void casStatsFetch ( unsigned *pChanCount, unsigned *pCircuitCount )
|
||||
{
|
||||
if(!clientQlock) { /* not yet initialized, or disabled via dbServer */
|
||||
if(pChanCount)
|
||||
*pChanCount = 0;
|
||||
if(pCircuitCount)
|
||||
*pCircuitCount = 0;
|
||||
return;
|
||||
}
|
||||
LOCK_CLIENTQ;
|
||||
{
|
||||
int circuitCount = ellCount ( &clientQ );
|
||||
|
||||
@@ -33,7 +33,7 @@ These fields control where the record will read data from when it is processed:
|
||||
The DTYP field selects which device support layer should be responsible for
|
||||
providing input data to the record.
|
||||
The ai device support layers provided by EPICS Base are documented in the
|
||||
L<Device Support|devSoft> section.
|
||||
L<Device Support Interface> section.
|
||||
External support modules may provide additional device support for this record
|
||||
type.
|
||||
If not set explicitly, the DTYP value defaults to the first device support that
|
||||
|
||||
@@ -384,6 +384,7 @@ static long special(DBADDR *paddr, int after)
|
||||
|
||||
if (special_type == SPC_RESET) {
|
||||
reset(prec);
|
||||
monitor(prec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,8 +208,8 @@ TESTSPEC_RTEMS = dbTestHarness.boot; epicsRunDbTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD_RTEMS = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
|
||||
TESTPROD += $(TESTPROD_HOST)
|
||||
TESTSCRIPTS += $(TESTS:%=%.t)
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -130,9 +130,11 @@ static void check(short dbr_type) {
|
||||
off = Offset; req = 10; \
|
||||
memset(buf, 0, sizeof(buf)); \
|
||||
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
|
||||
dbScanLock(dbChannelRecord(pch)); \
|
||||
pfl = db_create_read_log(pch); \
|
||||
testOk(pfl && pfl->type == dbfl_type_ref, "Valid pfl, type = ref"); \
|
||||
testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
|
||||
testOk(!dbChannelGet(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
|
||||
dbScanUnlock(dbChannelRecord(pch)); \
|
||||
testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
|
||||
if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
|
||||
for (i=0; i<Size; i++) \
|
||||
@@ -174,6 +176,7 @@ static void check(short dbr_type) {
|
||||
off = Offset; req = 15; \
|
||||
memset(buf, 0, sizeof(buf)); \
|
||||
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
|
||||
dbScanLock(dbChannelRecord(pch)); \
|
||||
pfl = db_create_read_log(pch); \
|
||||
pfl->type = dbfl_type_ref; \
|
||||
pfl->field_type = DBF_CHAR; \
|
||||
@@ -181,7 +184,8 @@ static void check(short dbr_type) {
|
||||
pfl->no_elements = 26; \
|
||||
pfl->dtor = freeArray; \
|
||||
pfl->u.r.field = epicsStrDup("abcdefghijklmnopqrsstuvwxyz"); \
|
||||
testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
|
||||
testOk(!dbChannelGet(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
|
||||
dbScanUnlock(dbChannelRecord(pch)); \
|
||||
testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
|
||||
if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
|
||||
for (i=0; i<Size; i++) \
|
||||
|
||||
@@ -40,6 +40,8 @@ void oneReport(unsigned level)
|
||||
void oneStats(unsigned *channels, unsigned *clients)
|
||||
{
|
||||
oneState = STATS_CALLED;
|
||||
if (channels) *channels = 2;
|
||||
if (clients) *clients = 1;
|
||||
}
|
||||
|
||||
int oneClient(char *pbuf, size_t len)
|
||||
@@ -128,8 +130,9 @@ MAIN(dbServerTest)
|
||||
char name[16];
|
||||
char *theName = "The One";
|
||||
int status;
|
||||
unsigned ch=0, cl=0;
|
||||
|
||||
testPlan(25);
|
||||
testPlan(35);
|
||||
|
||||
/* Prove that we handle substring names properly */
|
||||
epicsEnvSet("EPICS_IOC_IGNORE_SERVERS", "none ones");
|
||||
@@ -151,6 +154,9 @@ MAIN(dbServerTest)
|
||||
testDiag("Registering dbServer 'disabled'");
|
||||
testOk(dbRegisterServer(&disabled) == 0, "Registration accepted");
|
||||
|
||||
testOk(dbServerStats("one", &ch, &cl) == -1 && oneState == NOTHING_CALLED,
|
||||
"dbServerStats returns error before IOC running");
|
||||
|
||||
testDiag("Changing server state");
|
||||
dbInitServers();
|
||||
testOk(oneState == INIT_CALLED, "dbInitServers");
|
||||
@@ -163,8 +169,26 @@ MAIN(dbServerTest)
|
||||
|
||||
testDiag("Checking server methods called");
|
||||
dbsr(0);
|
||||
testOk(oneState == REPORT_CALLED, "dbsr called report()");
|
||||
testOk(oneState == REPORT_CALLED, "dbsr called one::report()");
|
||||
|
||||
testDiag("Checking stats functionality");
|
||||
testOk(dbServerStats("none", &ch, &cl) == 0, "Stats: unknown name ignored");
|
||||
testOk(dbServerStats("one", &ch, &cl) == 1 && oneState == STATS_CALLED,
|
||||
"dbServerStats('one') called one::stats()");
|
||||
testOk(ch == 2 && cl == 1, "Stats: ch==%d, cl==%d (expected 2, 1)", ch, cl);
|
||||
|
||||
testOk(dbServerStats("no-routines", &ch, &cl) == 0,
|
||||
"dbServerStats('no-routines') layer not counted");
|
||||
testOk(ch == 0 && cl == 0, "Stats: ch==%d, cl==%d (expected 0, 0)", ch, cl);
|
||||
|
||||
ch = 10; cl = 10; oneState = NOTHING_CALLED;
|
||||
testOk(dbServerStats(NULL, NULL, &cl) == 1 && oneState == STATS_CALLED,
|
||||
"dbServerStats(NULL, &cl) called one::stats()");
|
||||
testOk(dbServerStats(NULL, &ch, NULL) == 1 && oneState == STATS_CALLED,
|
||||
"dbServerStats(NULL, &ch) called one::stats()");
|
||||
testOk(ch == 2 && cl == 1, "Stats: ch==%d, cl==%d (expected 2, 1)", ch, cl);
|
||||
|
||||
testDiag("Checking client identification");
|
||||
oneSim = NULL;
|
||||
name[0] = 0;
|
||||
status = dbServerClient(name, sizeof(name));
|
||||
@@ -188,6 +212,9 @@ MAIN(dbServerTest)
|
||||
status = dbServerClient(name, sizeof(name));
|
||||
testOk(oneState != CLIENT_CALLED_KNOWN, "No call to client() when paused");
|
||||
|
||||
testOk(dbServerStats("one", &ch, &cl) == -1 && oneState != STATS_CALLED,
|
||||
"No call to stats() when paused");
|
||||
|
||||
dbStopServers();
|
||||
testOk(oneState == STOP_CALLED, "dbStopServers");
|
||||
testOk(dbUnregisterServer(&toolate) != 0, "No unreg' if not reg'ed");
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use strict;
|
||||
use Test;
|
||||
|
||||
BEGIN {plan tests => 12}
|
||||
BEGIN {plan tests => 14}
|
||||
|
||||
# Check include/substitute command model
|
||||
ok(msi('-I .. ../t1-template.txt'), slurp('../t1-result.txt'));
|
||||
@@ -56,6 +56,12 @@ my %envs = (TEST_NO => 12, PREFIX => 't');
|
||||
ok(msi('-I. -I.. -S ../t12-substitute.txt'), slurp('../t12-result.txt'));
|
||||
delete @ENV{ keys %envs }; # Not really needed
|
||||
|
||||
# Substitution file, relative path includes
|
||||
ok(msi('-I @TOP@/modules -S ../t13-substitute.txt'), slurp('../t13-result.txt'));
|
||||
|
||||
# Template file, relative path includes
|
||||
ok(msi('-I @TOP@/modules ../t14-template.txt'), slurp('../t14-result.txt'));
|
||||
|
||||
# Test support routines
|
||||
|
||||
sub slurp {
|
||||
|
||||
2
modules/database/test/ioc/dbtemplate/t13-result.txt
Normal file
2
modules/database/test/ioc/dbtemplate/t13-result.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=foo
|
||||
3
modules/database/test/ioc/dbtemplate/t13-substitute.txt
Normal file
3
modules/database/test/ioc/dbtemplate/t13-substitute.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
file database/test/ioc/dbtemplate/t13-template.txt {
|
||||
{ a=foo }
|
||||
}
|
||||
2
modules/database/test/ioc/dbtemplate/t13-template.txt
Normal file
2
modules/database/test/ioc/dbtemplate/t13-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
1
modules/database/test/ioc/dbtemplate/t14-include.txt
Normal file
1
modules/database/test/ioc/dbtemplate/t14-include.txt
Normal file
@@ -0,0 +1 @@
|
||||
I'm a file!
|
||||
5
modules/database/test/ioc/dbtemplate/t14-result.txt
Normal file
5
modules/database/test/ioc/dbtemplate/t14-result.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
This is t14-template.txt
|
||||
|
||||
I'm a file!
|
||||
|
||||
End of t14-template.txt
|
||||
5
modules/database/test/ioc/dbtemplate/t14-template.txt
Normal file
5
modules/database/test/ioc/dbtemplate/t14-template.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
This is t14-template.txt
|
||||
|
||||
include "database/test/ioc/dbtemplate/t14-include.txt"
|
||||
|
||||
End of t14-template.txt
|
||||
@@ -81,8 +81,8 @@ TESTSPEC_RTEMS = filterTestHarness.boot; epicsRunFilterTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD_RTEMS = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
|
||||
TESTPROD += $(TESTPROD_HOST)
|
||||
TESTSCRIPTS += $(TESTS:%=%.t)
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -57,8 +57,8 @@ TESTSPEC_RTEMS = linkTestHarness.boot; epicsRunLinkTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
|
||||
TESTPROD += $(TESTPROD_HOST)
|
||||
TESTSCRIPTS += $(TESTS:%=%.t)
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -221,6 +221,34 @@ testHarness_SRCS += linkFilterTest.c
|
||||
TESTFILES += ../linkFilterTest.db
|
||||
TESTS += linkFilterTest
|
||||
|
||||
TARGETS += $(COMMON_DIR)/epicsExportTestIoc.dbd
|
||||
DBDDEPENDS_FILES += epicsExportTestIoc.dbd$(DEP)
|
||||
epicsExportTestIoc_DBD += base.dbd
|
||||
epicsExportTestIoc_DBD += epicsExportTest.dbd
|
||||
TESTFILES += $(COMMON_DIR)/epicsExportTestIoc.dbd ../epicsExportTest.db
|
||||
|
||||
TESTLIBRARY += epicsExportTestLib
|
||||
epicsExportTestLib_SRCS += epicsExportTest.c
|
||||
epicsExportTestLib_LIBS += dbCore Com
|
||||
|
||||
TESTPROD_HOST += epicsExportTest
|
||||
TESTS += epicsExportTest
|
||||
TARGETS += epicsExportTest$(OBJ)
|
||||
epicsExportTest_SRCS += epicsExportTestMain.c
|
||||
epicsExportTest_SRCS += epicsExportTestIoc_registerRecordDeviceDriver.cpp
|
||||
epicsExportTest_LIBS = epicsExportTestLib
|
||||
|
||||
TESTLIBRARY += epicsExportTestxxLib
|
||||
epicsExportTestxxLib_SRCS += epicsExportTestxx.cpp
|
||||
epicsExportTestxxLib_LIBS += dbCore Com
|
||||
|
||||
TESTPROD_HOST += epicsExportTestxx
|
||||
TESTS += epicsExportTestxx
|
||||
TARGETS += epicsExportTestxx$(OBJ)
|
||||
epicsExportTestxx_SRCS += epicsExportTestMain.c
|
||||
epicsExportTestxx_SRCS += epicsExportTestIoc_registerRecordDeviceDriver.cpp
|
||||
epicsExportTestxx_LIBS = epicsExportTestxxLib
|
||||
|
||||
# These are compile-time tests, no need to link or run
|
||||
TARGETS += dbHeaderTest$(OBJ)
|
||||
TARGET_SRCS += dbHeaderTest.cpp
|
||||
@@ -251,8 +279,8 @@ TESTSPEC_RTEMS = recordTestHarness.boot; epicsRunRecordTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD_RTEMS = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
|
||||
TESTPROD += $(TESTPROD_HOST)
|
||||
TESTSCRIPTS += $(TESTS:%=%.t)
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
146
modules/database/test/std/rec/epicsExportTest.c
Normal file
146
modules/database/test/std/rec/epicsExportTest.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2025 Dirk Zimoch
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/* Compile and link test for epicsExport.h
|
||||
*
|
||||
* Test if macros eppicsExportAddr, epicsExportRegistrar and epicsRegisterFunction
|
||||
* expand to valid C and C++ code, in the latter case regardless if
|
||||
* wrapped with extern "C" {} or not.
|
||||
* Also test that those macros have the intended effect in both cases.
|
||||
*
|
||||
* This file is compiled directly as C
|
||||
* and included from epicsExportTestxx.cpp as C++
|
||||
*/
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <dbUnitTest.h>
|
||||
#include <testMain.h>
|
||||
#include <dbAccess.h>
|
||||
#include <longinRecord.h>
|
||||
#include <aSubRecord.h>
|
||||
#include <iocsh.h>
|
||||
#include <registryFunction.h>
|
||||
#include <epicsExport.h>
|
||||
|
||||
int i1, i2;
|
||||
volatile int v1=10, v2=20;
|
||||
const int c1=100, c2=200;
|
||||
|
||||
static long myReadLongin(struct dbCommon* prec)
|
||||
{
|
||||
struct longinRecord* pli =
|
||||
#ifdef __cplusplus
|
||||
reinterpret_cast<struct longinRecord*>(prec);
|
||||
#else
|
||||
(struct longinRecord*)prec;
|
||||
#endif
|
||||
pli->val=5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Also test cast from user-specific const mydset to dset */
|
||||
const struct mydset {
|
||||
long number;
|
||||
long (*report)(int);
|
||||
long (*init)(int);
|
||||
long (*init_record)(struct dbCommon*);
|
||||
long (*get_ioint_info)(int, struct dbCommon*, IOSCANPVT*);
|
||||
long (*process)(struct dbCommon*);
|
||||
long (*something_else)(struct dbCommon*);
|
||||
} dset1 = {
|
||||
6,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
myReadLongin,
|
||||
NULL
|
||||
}, dset2 = {
|
||||
6,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
myReadLongin,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void registrar1() {
|
||||
i1++;
|
||||
testPass("registrar1 executed");
|
||||
}
|
||||
|
||||
static void registrar2() {
|
||||
i2++;
|
||||
testPass("registrar2 executed");
|
||||
}
|
||||
|
||||
/* Also test cast from int(*)() to REGISTRAR */
|
||||
static int registrar3() {
|
||||
i1++;
|
||||
testPass("registrar3 executed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int registrar4() {
|
||||
i2++;
|
||||
testPass("registrar4 executed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test both, native (potentially C++) and extern "C" functions */
|
||||
static long aSubInit1(aSubRecord* prec) {
|
||||
*(epicsInt32*)prec->a = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long aSubProc1(aSubRecord* prec) {
|
||||
*(epicsInt32*)prec->b = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
static long aSubInit2(aSubRecord* prec) {
|
||||
*(epicsInt32*)prec->a = 3;
|
||||
return 0;
|
||||
}
|
||||
static long aSubProc2(aSubRecord* prec) {
|
||||
*(epicsInt32*)prec->b = 4;
|
||||
return 0;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Test without wrapping */
|
||||
epicsExportAddress(int, i1);
|
||||
epicsExportAddress(int, v1);
|
||||
epicsExportAddress(int, c1);
|
||||
epicsExportAddress(dset, dset1);
|
||||
epicsExportRegistrar(registrar1);
|
||||
epicsExportRegistrar(registrar3);
|
||||
epicsRegisterFunction(aSubInit1);
|
||||
epicsRegisterFunction(aSubProc1);
|
||||
|
||||
/* In C++ test wrapped in extern "C" {} */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
epicsExportAddress(int, i2);
|
||||
epicsExportAddress(int, v2);
|
||||
epicsExportAddress(int, c2);
|
||||
epicsExportAddress(dset, dset2);
|
||||
epicsExportRegistrar(registrar2);
|
||||
epicsExportRegistrar(registrar4);
|
||||
epicsRegisterFunction(aSubInit2);
|
||||
epicsRegisterFunction(aSubProc2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
24
modules/database/test/std/rec/epicsExportTest.db
Normal file
24
modules/database/test/std/rec/epicsExportTest.db
Normal file
@@ -0,0 +1,24 @@
|
||||
record(longin, "li1") {
|
||||
field(DTYP, "dset1")
|
||||
field(VAL, "-1")
|
||||
}
|
||||
record(longin, "li2") {
|
||||
field(DTYP, "dset2")
|
||||
field(VAL, "-2")
|
||||
}
|
||||
record(aSub, "asub1") {
|
||||
field(FTA, "LONG")
|
||||
field(FTB, "LONG")
|
||||
field(INPA, "-1")
|
||||
field(INPB, "-2")
|
||||
field(INAM, "aSubInit1")
|
||||
field(SNAM, "aSubProc1")
|
||||
}
|
||||
record(aSub, "asub2") {
|
||||
field(FTA, "LONG")
|
||||
field(FTB, "LONG")
|
||||
field(INPA, "-3")
|
||||
field(INPB, "-4")
|
||||
field(INAM, "aSubInit2")
|
||||
field(SNAM, "aSubProc2")
|
||||
}
|
||||
16
modules/database/test/std/rec/epicsExportTest.dbd
Normal file
16
modules/database/test/std/rec/epicsExportTest.dbd
Normal file
@@ -0,0 +1,16 @@
|
||||
variable(i1,int)
|
||||
variable(i2,int)
|
||||
variable(v1,int)
|
||||
variable(v2,int)
|
||||
variable(c1,int)
|
||||
variable(c2,int)
|
||||
device(longin, CONSTANT, dset1, "dset1")
|
||||
device(longin, CONSTANT, dset2, "dset2")
|
||||
registrar(registrar1)
|
||||
registrar(registrar2)
|
||||
registrar(registrar3)
|
||||
registrar(registrar4)
|
||||
function(aSubInit1)
|
||||
function(aSubProc1)
|
||||
function(aSubInit2)
|
||||
function(aSubProc2)
|
||||
95
modules/database/test/std/rec/epicsExportTestMain.c
Normal file
95
modules/database/test/std/rec/epicsExportTestMain.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2025 Dirk Zimoch
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/* Compile and link test for epicsExport.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <dbUnitTest.h>
|
||||
#include <testMain.h>
|
||||
#include <dbAccess.h>
|
||||
#include <iocsh.h>
|
||||
#include <epicsExport.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int epicsExportTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
static int* testVarEquals(const char* name, int expected)
|
||||
{
|
||||
const iocshVarDef *var;
|
||||
int *p;
|
||||
|
||||
var = iocshFindVariable(name);
|
||||
if (!var) {
|
||||
testFail("Cannot access variable %s", name);
|
||||
return NULL;
|
||||
}
|
||||
if (var->type != iocshArgInt) {
|
||||
testFail("Variable %s has wrong type", name);
|
||||
return NULL;
|
||||
}
|
||||
p = (int*)(var->pval);
|
||||
testOk(*p == expected, "Variable %s == %d", name, expected);
|
||||
return p;
|
||||
}
|
||||
|
||||
MAIN(epicsExportTest)
|
||||
{
|
||||
int *p1, *p2;
|
||||
|
||||
testPlan(31);
|
||||
testdbPrepare();
|
||||
testdbReadDatabase("epicsExportTestIoc.dbd", 0, 0);
|
||||
testOk(epicsExportTestIoc_registerRecordDeviceDriver(pdbbase)==0, "registerRecordDeviceDriver");
|
||||
|
||||
testDiag("Testing if dsets and functions are found");
|
||||
testdbReadDatabase("epicsExportTest.db", 0, 0);
|
||||
testIocInitOk();
|
||||
|
||||
testDiag("Testing if dsets work correctly");
|
||||
testdbGetFieldEqual("li1", DBF_LONG, -1);
|
||||
testdbGetFieldEqual("li2", DBF_LONG, -2);
|
||||
testdbPutFieldOk("li1.PROC", DBF_LONG, 1);
|
||||
testdbPutFieldOk("li2.PROC", DBF_LONG, 1);
|
||||
testdbGetFieldEqual("li1", DBF_LONG, 5);
|
||||
testdbGetFieldEqual("li2", DBF_LONG, 5);
|
||||
|
||||
testDiag("Testing if functions work correctly");
|
||||
testdbGetFieldEqual("asub1.A", DBF_LONG, 1);
|
||||
testdbGetFieldEqual("asub1.B", DBF_LONG, -2);
|
||||
testdbGetFieldEqual("asub2.A", DBF_LONG, 3);
|
||||
testdbGetFieldEqual("asub2.B", DBF_LONG, -4);
|
||||
testdbPutFieldOk("asub1.PROC", DBF_LONG, 1);
|
||||
testdbPutFieldOk("asub2.PROC", DBF_LONG, 1);
|
||||
testdbGetFieldEqual("asub1.A", DBF_LONG, 1);
|
||||
testdbGetFieldEqual("asub1.B", DBF_LONG, 2);
|
||||
testdbGetFieldEqual("asub2.A", DBF_LONG, 3);
|
||||
testdbGetFieldEqual("asub2.B", DBF_LONG, 4);
|
||||
|
||||
testDiag("Testing if variable access works");
|
||||
p1 = testVarEquals("i1", 2);
|
||||
p2 = testVarEquals("i2", 2);
|
||||
testVarEquals("v1", 10);
|
||||
testVarEquals("v2", 20);
|
||||
testVarEquals("c1", 100);
|
||||
testVarEquals("c2", 200);
|
||||
|
||||
if (p1 && p2) {
|
||||
testDiag("Testing if variables are accessible from iocsh");
|
||||
testOk(iocshCmd("var i1,4") == 0, "Setting i1 = 4 in iocsh");
|
||||
testOk(iocshCmd("var i2,5") == 0, "Setting i2 = 5 in iocsh");
|
||||
testOk(*p1==4, "Variable i1 == 4");
|
||||
testOk(*p2==5, "Variable i2 == 5");
|
||||
}
|
||||
|
||||
testIocShutdownOk();
|
||||
testdbCleanup();
|
||||
return testDone();
|
||||
}
|
||||
2
modules/database/test/std/rec/epicsExportTestxx.cpp
Normal file
2
modules/database/test/std/rec/epicsExportTestxx.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
// just compile as c++
|
||||
#include "epicsExportTest.c"
|
||||
@@ -510,6 +510,7 @@ static void rtshellCallFunc(const iocshArgBuf *args)
|
||||
|
||||
if (!cmd) {
|
||||
fprintf(stderr, "ERR: No such command\n");
|
||||
iocshSetError(-1);
|
||||
|
||||
} else {
|
||||
fflush(stdout);
|
||||
@@ -517,6 +518,7 @@ static void rtshellCallFunc(const iocshArgBuf *args)
|
||||
ret = (*cmd->command)(args[1].aval.ac,args[1].aval.av);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
iocshSetError(ret);
|
||||
if(ret)
|
||||
fprintf(stderr, "ERR: %d\n",ret);
|
||||
}
|
||||
@@ -611,18 +613,27 @@ static void nfsMountCallFunc(const iocshArgBuf *args)
|
||||
}
|
||||
*cp = '/';
|
||||
}
|
||||
nfsMount(args[0].sval, args[1].sval, args[2].sval);
|
||||
iocshSetError(nfsMount(args[0].sval, args[1].sval, args[2].sval));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void zoneset(const char *zone)
|
||||
int zoneset(const char *zone)
|
||||
{
|
||||
if(zone)
|
||||
setenv("TZ", zone, 1);
|
||||
else
|
||||
unsetenv("TZ");
|
||||
int ret;
|
||||
if(zone) {
|
||||
if ((ret = setenv("TZ", zone, 1)) < 0)
|
||||
return ret;
|
||||
}
|
||||
#if defined( __NEWLIB_MINOR__ ) /* Added in newlib 2.2.0 */
|
||||
else if ((ret = unsetenv("TZ")) < 0)
|
||||
return ret;
|
||||
#else
|
||||
else
|
||||
unsetenv("TZ");
|
||||
#endif
|
||||
tzset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const iocshArg zonesetArg0 = {"zone string", iocshArgString};
|
||||
@@ -634,7 +645,7 @@ static const iocshFuncDef zonesetFuncDef = {"zoneset",1,zonesetArgs
|
||||
};
|
||||
static void zonesetCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
zoneset(args[0].sval);
|
||||
iocshSetError(zoneset(args[0].sval));
|
||||
}
|
||||
|
||||
#ifndef RTEMS_LEGACY_STACK
|
||||
@@ -667,6 +678,7 @@ static void setlogmaskCallFunc(const iocshArgBuf *args)
|
||||
return;
|
||||
}
|
||||
printf("Error: unknown log level.\n");
|
||||
iocshSetError(-1);
|
||||
}
|
||||
}
|
||||
static const iocshArg setlogmaskArg0 = {"level name", iocshArgString};
|
||||
|
||||
@@ -483,18 +483,27 @@ static void nfsMountCallFunc(const iocshArgBuf *args)
|
||||
}
|
||||
*cp = '/';
|
||||
}
|
||||
nfsMount(args[0].sval, args[1].sval, args[2].sval);
|
||||
iocshSetError(nfsMount(args[0].sval, args[1].sval, args[2].sval));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void zoneset(const char *zone)
|
||||
int zoneset(const char *zone)
|
||||
{
|
||||
if(zone)
|
||||
setenv("TZ", zone, 1);
|
||||
else
|
||||
unsetenv("TZ");
|
||||
int ret;
|
||||
if(zone) {
|
||||
if ((ret = setenv("TZ", zone, 1)) < 0)
|
||||
return ret;
|
||||
}
|
||||
#if defined( __NEWLIB_MINOR__ ) /* Added in newlib 2.2.0 */
|
||||
else if ((ret = unsetenv("TZ")) < 0)
|
||||
return ret;
|
||||
#else
|
||||
else
|
||||
unsetenv("TZ");
|
||||
#endif
|
||||
tzset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const iocshArg zonesetArg0 = {"zone string", iocshArgString};
|
||||
@@ -502,7 +511,7 @@ static const iocshArg * const zonesetArgs[1] = {&zonesetArg0};
|
||||
static const iocshFuncDef zonesetFuncDef = {"zoneset",1,zonesetArgs};
|
||||
static void zonesetCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
zoneset(args[0].sval);
|
||||
iocshSetError(zoneset(args[0].sval));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -311,13 +311,13 @@ inline bool tsSLIterConst<T>::valid () const
|
||||
template < class T >
|
||||
inline bool tsSLIterConst<T>::operator == ( const tsSLIterConst<T> &rhs ) const
|
||||
{
|
||||
return this->pEntry == rhs.pConstEntry;
|
||||
return this->pEntry == rhs.pEntry;
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline bool tsSLIterConst<T>::operator != (const tsSLIterConst<T> &rhs) const
|
||||
{
|
||||
return this->pEntry != rhs.pConstEntry;
|
||||
return this->pEntry != rhs.pEntry;
|
||||
}
|
||||
|
||||
template < class T >
|
||||
|
||||
1
modules/libcom/src/env/envDefs.h
vendored
1
modules/libcom/src/env/envDefs.h
vendored
@@ -77,6 +77,7 @@ LIBCOM_API extern const ENV_PARAM IOCSH_PS1;
|
||||
LIBCOM_API extern const ENV_PARAM IOCSH_HISTSIZE;
|
||||
LIBCOM_API extern const ENV_PARAM IOCSH_HISTEDIT_DISABLE;
|
||||
LIBCOM_API extern const ENV_PARAM EPICS_MUTEX_USE_PRIORITY_INHERITANCE;
|
||||
LIBCOM_API extern const ENV_PARAM EPICS_ABORT_ON_ASSERT;
|
||||
LIBCOM_API extern const ENV_PARAM *env_param_list[];
|
||||
|
||||
struct in_addr;
|
||||
|
||||
@@ -19,39 +19,117 @@
|
||||
// 1) This library is not thread safe
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define instantiateRecourceLib
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsThread.h"
|
||||
#include "fdManager.h"
|
||||
#include "locationException.h"
|
||||
|
||||
using std :: max;
|
||||
#if !defined(FDMGR_USE_POLL) && !defined(FDMGR_USE_SELECT)
|
||||
#if defined(__linux__) || defined(darwin) || _WIN32_WINNT >= 0x600 || (defined(__rtems__) && !defined(RTEMS_LEGACY_STACK))
|
||||
#define FDMGR_USE_POLL
|
||||
#else
|
||||
#define FDMGR_USE_SELECT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FDMGR_USE_POLL
|
||||
#include <vector>
|
||||
#if !defined(_WIN32)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
static const short PollEvents[] = { // must match fdRegType
|
||||
POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR,
|
||||
POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR,
|
||||
POLLPRI };
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define poll WSAPoll
|
||||
// Filter out PollEvents that Windows does not accept in events (only returns in revents)
|
||||
#define WIN_POLLEVENT_FILTER(ev) static_cast<short>((ev) & (POLLIN | POLLOUT))
|
||||
#else
|
||||
// Linux, MacOS and RTEMS don't care
|
||||
#define WIN_POLLEVENT_FILTER(ev) (ev)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
struct fdManagerPrivate {
|
||||
tsDLList<fdReg> regList;
|
||||
tsDLList<fdReg> activeList;
|
||||
resTable<fdReg, fdRegId> fdTbl;
|
||||
const double sleepQuantum;
|
||||
epics::auto_ptr<epicsTimerQueuePassive> pTimerQueue;
|
||||
bool processInProg;
|
||||
|
||||
#ifdef FDMGR_USE_POLL
|
||||
std::vector<struct pollfd> pollfds;
|
||||
#endif
|
||||
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
fd_set fdSets[fdrNEnums];
|
||||
SOCKET maxFD;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Set to fdreg when in call back
|
||||
// and nill otherwise
|
||||
//
|
||||
volatile fdReg* pCBReg;
|
||||
fdManager& owner;
|
||||
|
||||
explicit fdManagerPrivate(fdManager& owner);
|
||||
void lazyInitTimerQueue();
|
||||
};
|
||||
|
||||
fdManagerPrivate::fdManagerPrivate(fdManager& owner) :
|
||||
sleepQuantum(epicsThreadSleepQuantum()),
|
||||
processInProg(false),
|
||||
pCBReg(NULL), owner(owner)
|
||||
{}
|
||||
|
||||
inline void fdManagerPrivate::lazyInitTimerQueue()
|
||||
{
|
||||
if (!pTimerQueue.get()) {
|
||||
pTimerQueue.reset(&epicsTimerQueuePassive::create(owner));
|
||||
}
|
||||
}
|
||||
|
||||
epicsTimer& fdManager::createTimer()
|
||||
{
|
||||
priv->lazyInitTimerQueue();
|
||||
return priv->pTimerQueue->createTimer();
|
||||
}
|
||||
|
||||
fdManager fileDescriptorManager;
|
||||
|
||||
const unsigned mSecPerSec = 1000u;
|
||||
const unsigned uSecPerSec = 1000u * mSecPerSec;
|
||||
static const unsigned mSecPerSec = 1000u;
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
static const unsigned uSecPerSec = 1000u * mSecPerSec;
|
||||
#endif
|
||||
|
||||
//
|
||||
// fdManager::fdManager()
|
||||
//
|
||||
// hopefully its a reasonable guess that select() and epicsThreadSleep()
|
||||
// hopefully its a reasonable guess that poll()/select() and epicsThreadSleep()
|
||||
// will have the same sleep quantum
|
||||
//
|
||||
LIBCOM_API fdManager::fdManager () :
|
||||
sleepQuantum ( epicsThreadSleepQuantum () ),
|
||||
fdSetsPtr ( new fd_set [fdrNEnums] ),
|
||||
pTimerQueue ( 0 ), maxFD ( 0 ), processInProg ( false ),
|
||||
pCBReg ( 0 )
|
||||
LIBCOM_API fdManager::fdManager() :
|
||||
priv(new fdManagerPrivate(*this))
|
||||
{
|
||||
int status = osiSockAttach ();
|
||||
assert (status);
|
||||
int status = osiSockAttach();
|
||||
assert(status);
|
||||
|
||||
for ( size_t i = 0u; i < fdrNEnums; i++ ) {
|
||||
FD_ZERO ( &fdSetsPtr[i] );
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
priv->maxFD = 0;
|
||||
for (size_t i = 0u; i < fdrNEnums; i++) {
|
||||
FD_ZERO(&priv->fdSets[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
@@ -59,82 +137,138 @@ LIBCOM_API fdManager::fdManager () :
|
||||
//
|
||||
LIBCOM_API fdManager::~fdManager()
|
||||
{
|
||||
fdReg *pReg;
|
||||
fdReg* pReg;
|
||||
|
||||
while ( (pReg = this->regList.get()) ) {
|
||||
while ((pReg = priv->regList.get())) {
|
||||
pReg->state = fdReg::limbo;
|
||||
pReg->destroy();
|
||||
}
|
||||
while ( (pReg = this->activeList.get()) ) {
|
||||
while ((pReg = priv->activeList.get())) {
|
||||
pReg->state = fdReg::limbo;
|
||||
pReg->destroy();
|
||||
}
|
||||
delete this->pTimerQueue;
|
||||
delete [] this->fdSetsPtr;
|
||||
osiSockRelease();
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::process()
|
||||
//
|
||||
LIBCOM_API void fdManager::process (double delay)
|
||||
LIBCOM_API void fdManager::process(double delay)
|
||||
{
|
||||
this->lazyInitTimerQueue ();
|
||||
priv->lazyInitTimerQueue();
|
||||
|
||||
//
|
||||
// no recursion
|
||||
//
|
||||
if (this->processInProg) {
|
||||
if (priv->processInProg)
|
||||
return;
|
||||
}
|
||||
this->processInProg = true;
|
||||
priv->processInProg = true;
|
||||
|
||||
//
|
||||
// One shot at expired timers prior to going into
|
||||
// select. This allows zero delay timers to arm
|
||||
// poll/select. This allows zero delay timers to arm
|
||||
// fd writes. We will never process the timer queue
|
||||
// more than once here so that fd activity get serviced
|
||||
// in a reasonable length of time.
|
||||
//
|
||||
double minDelay = this->pTimerQueue->process(epicsTime::getCurrent());
|
||||
double minDelay = priv->pTimerQueue->process(epicsTime::getCurrent());
|
||||
|
||||
if ( minDelay >= delay ) {
|
||||
if (minDelay >= delay) {
|
||||
minDelay = delay;
|
||||
}
|
||||
|
||||
bool ioPending = false;
|
||||
tsDLIter < fdReg > iter = this->regList.firstIter ();
|
||||
while ( iter.valid () ) {
|
||||
FD_SET(iter->getFD(), &this->fdSetsPtr[iter->getType()]);
|
||||
ioPending = true;
|
||||
#ifdef FDMGR_USE_POLL
|
||||
priv->pollfds.clear();
|
||||
#endif
|
||||
|
||||
int ioPending = 0;
|
||||
tsDLIter<fdReg> iter = priv->regList.firstIter();
|
||||
while (iter.valid()) {
|
||||
++ioPending;
|
||||
|
||||
#ifdef FDMGR_USE_POLL
|
||||
#if __cplusplus >= 201100L
|
||||
priv->pollfds.emplace_back(pollfd{
|
||||
.fd = iter->getFD(),
|
||||
.events = WIN_POLLEVENT_FILTER(PollEvents[iter->getType()])
|
||||
});
|
||||
#else
|
||||
struct pollfd pollfd;
|
||||
pollfd.fd = iter->getFD();
|
||||
pollfd.events = WIN_POLLEVENT_FILTER(PollEvents[iter->getType()]);
|
||||
pollfd.revents = 0;
|
||||
priv->pollfds.push_back(pollfd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
FD_SET(iter->getFD(), &priv->fdSets[iter->getType()]);
|
||||
#endif
|
||||
++iter;
|
||||
}
|
||||
|
||||
if ( ioPending ) {
|
||||
if (ioPending) {
|
||||
#ifdef FDMGR_USE_POLL
|
||||
if (minDelay * mSecPerSec > INT_MAX)
|
||||
minDelay = INT_MAX / mSecPerSec;
|
||||
|
||||
int status = poll(&priv->pollfds[0], // ancient C++ has no vector.data()
|
||||
ioPending, static_cast<int>(minDelay * mSecPerSec));
|
||||
int i = 0;
|
||||
#endif
|
||||
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
struct timeval tv;
|
||||
tv.tv_sec = static_cast<time_t> ( minDelay );
|
||||
tv.tv_usec = static_cast<long> ( (minDelay-tv.tv_sec) * uSecPerSec );
|
||||
tv.tv_sec = static_cast<time_t>(minDelay);
|
||||
tv.tv_usec = static_cast<long>((minDelay-tv.tv_sec) * uSecPerSec);
|
||||
|
||||
fd_set * pReadSet = & this->fdSetsPtr[fdrRead];
|
||||
fd_set * pWriteSet = & this->fdSetsPtr[fdrWrite];
|
||||
fd_set * pExceptSet = & this->fdSetsPtr[fdrException];
|
||||
int status = select (this->maxFD, pReadSet, pWriteSet, pExceptSet, &tv);
|
||||
int status = select(priv->maxFD,
|
||||
&priv->fdSets[fdrRead],
|
||||
&priv->fdSets[fdrWrite],
|
||||
&priv->fdSets[fdrException], &tv);
|
||||
#endif
|
||||
|
||||
this->pTimerQueue->process(epicsTime::getCurrent());
|
||||
priv->pTimerQueue->process(epicsTime::getCurrent());
|
||||
|
||||
if ( status > 0 ) {
|
||||
if (status > 0) {
|
||||
|
||||
//
|
||||
// Look for activity
|
||||
//
|
||||
iter=this->regList.firstIter ();
|
||||
while ( iter.valid () && status > 0 ) {
|
||||
tsDLIter < fdReg > tmp = iter;
|
||||
iter = priv->regList.firstIter();
|
||||
while (iter.valid() && status > 0) {
|
||||
tsDLIter<fdReg> tmp = iter;
|
||||
tmp++;
|
||||
if (FD_ISSET(iter->getFD(), &this->fdSetsPtr[iter->getType()])) {
|
||||
FD_CLR(iter->getFD(), &this->fdSetsPtr[iter->getType()]);
|
||||
this->regList.remove(*iter);
|
||||
this->activeList.add(*iter);
|
||||
|
||||
#ifdef FDMGR_USE_POLL
|
||||
// In a single threaded application, nothing should have
|
||||
// changed the order of regList and pollfds by now.
|
||||
// But just in case...
|
||||
int isave = i;
|
||||
while (priv->pollfds[i].fd != iter->getFD() ||
|
||||
priv->pollfds[i].events != WIN_POLLEVENT_FILTER(PollEvents[iter->getType()]))
|
||||
{
|
||||
errlogPrintf("fdManager: skipping (removed?) pollfd %d (expected %d)\n", priv->pollfds[i].fd, iter->getFD());
|
||||
i++; // skip pollfd of removed items
|
||||
if (i >= ioPending) { // skip unknown (inserted?) items
|
||||
errlogPrintf("fdManager: skipping (inserted?) item %d\n", iter->getFD());
|
||||
iter = tmp;
|
||||
tmp++;
|
||||
if (!iter.valid()) break;
|
||||
i = isave;
|
||||
}
|
||||
}
|
||||
if (i >= ioPending) break; // any unhandled item stays in regList for next time
|
||||
|
||||
if (priv->pollfds[i++].revents & PollEvents[iter->getType()]) {
|
||||
#endif
|
||||
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
if (FD_ISSET(iter->getFD(), &priv->fdSets[iter->getType()])) {
|
||||
FD_CLR(iter->getFD(), &priv->fdSets[iter->getType()]);
|
||||
#endif
|
||||
priv->regList.remove(*iter);
|
||||
priv->activeList.add(*iter);
|
||||
iter->state = fdReg::active;
|
||||
status--;
|
||||
}
|
||||
@@ -145,8 +279,8 @@ LIBCOM_API void fdManager::process (double delay)
|
||||
// I am careful to prevent problems if they access the
|
||||
// above list while in a "callBack()" routine
|
||||
//
|
||||
fdReg * pReg;
|
||||
while ( (pReg = this->activeList.get()) ) {
|
||||
fdReg* pReg;
|
||||
while ((pReg = priv->activeList.get())) {
|
||||
pReg->state = fdReg::limbo;
|
||||
|
||||
//
|
||||
@@ -154,45 +288,53 @@ LIBCOM_API void fdManager::process (double delay)
|
||||
// can detect if it was deleted
|
||||
// during the call back
|
||||
//
|
||||
this->pCBReg = pReg;
|
||||
priv->pCBReg = pReg;
|
||||
pReg->callBack();
|
||||
if (this->pCBReg != NULL) {
|
||||
if (priv->pCBReg != NULL) {
|
||||
//
|
||||
// check only after we see that it is non-null so
|
||||
// that we don't trigger bounds-checker dangling pointer
|
||||
// error
|
||||
//
|
||||
assert (this->pCBReg==pReg);
|
||||
this->pCBReg = 0;
|
||||
assert(priv->pCBReg == pReg);
|
||||
priv->pCBReg = NULL;
|
||||
if (pReg->onceOnly) {
|
||||
pReg->destroy();
|
||||
}
|
||||
else {
|
||||
this->regList.add(*pReg);
|
||||
priv->regList.add(*pReg);
|
||||
pReg->state = fdReg::pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( status < 0 ) {
|
||||
else if (status < 0) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
// don't depend on flags being properly set if
|
||||
// an error is returned from select
|
||||
for ( size_t i = 0u; i < fdrNEnums; i++ ) {
|
||||
FD_ZERO ( &fdSetsPtr[i] );
|
||||
for (size_t i = 0u; i < fdrNEnums; i++) {
|
||||
FD_ZERO(&priv->fdSets[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// print a message if its an unexpected error
|
||||
// print a message if it's an unexpected error
|
||||
//
|
||||
if ( errnoCpy != SOCK_EINTR ) {
|
||||
if (errnoCpy != SOCK_EINTR) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf ( stderr,
|
||||
"fdManager: select failed because \"%s\"\n",
|
||||
sockErrBuf );
|
||||
epicsSocketConvertErrnoToString(
|
||||
sockErrBuf, sizeof(sockErrBuf));
|
||||
errlogPrintf("fdManager: "
|
||||
#ifdef FDMGR_USE_POLL
|
||||
"poll()"
|
||||
#endif
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
"select()"
|
||||
#endif
|
||||
" failed because \"%s\"\n",
|
||||
sockErrBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,9 +345,9 @@ LIBCOM_API void fdManager::process (double delay)
|
||||
* of select()
|
||||
*/
|
||||
epicsThreadSleep(minDelay);
|
||||
this->pTimerQueue->process(epicsTime::getCurrent());
|
||||
priv->pTimerQueue->process(epicsTime::getCurrent());
|
||||
}
|
||||
this->processInProg = false;
|
||||
priv->processInProg = false;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -222,7 +364,7 @@ void fdReg::destroy()
|
||||
//
|
||||
fdReg::~fdReg()
|
||||
{
|
||||
this->manager.removeReg(*this);
|
||||
manager.removeReg(*this);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -230,57 +372,62 @@ fdReg::~fdReg()
|
||||
//
|
||||
void fdReg::show(unsigned level) const
|
||||
{
|
||||
printf ("fdReg at %p\n", (void *) this);
|
||||
if (level>1u) {
|
||||
printf ("\tstate = %d, onceOnly = %d\n",
|
||||
this->state, this->onceOnly);
|
||||
printf("fdReg at %p\n", this);
|
||||
if (level > 1u) {
|
||||
printf("\tstate = %d, onceOnly = %d\n",
|
||||
state, onceOnly);
|
||||
}
|
||||
this->fdRegId::show(level);
|
||||
fdRegId::show(level);
|
||||
}
|
||||
|
||||
//
|
||||
// fdRegId::show()
|
||||
//
|
||||
void fdRegId::show ( unsigned level ) const
|
||||
void fdRegId::show(unsigned level) const
|
||||
{
|
||||
printf ( "fdRegId at %p\n",
|
||||
static_cast <const void *> ( this ) );
|
||||
if ( level > 1u ) {
|
||||
printf ( "\tfd = %d, type = %d\n",
|
||||
int(this->fd), this->type );
|
||||
printf("fdRegId at %p\n", this);
|
||||
if (level > 1u) {
|
||||
printf("\tfd = %"
|
||||
#if defined(_WIN32)
|
||||
"I"
|
||||
#endif
|
||||
"d, type = %d\n",
|
||||
fd, type);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::installReg ()
|
||||
// fdManager::installReg()
|
||||
//
|
||||
void fdManager::installReg (fdReg ®)
|
||||
void fdManager::installReg(fdReg ®)
|
||||
{
|
||||
this->maxFD = max ( this->maxFD, reg.getFD()+1 );
|
||||
// Most applications will find that its important to push here to
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
priv->maxFD = std::max(priv->maxFD, reg.getFD()+1);
|
||||
#endif
|
||||
// Most applications will find that it's important to push here to
|
||||
// the front of the list so that transient writes get executed
|
||||
// first allowing incoming read protocol to find that outgoing
|
||||
// buffer space is newly available.
|
||||
this->regList.push ( reg );
|
||||
priv->regList.push(reg);
|
||||
reg.state = fdReg::pending;
|
||||
|
||||
int status = this->fdTbl.add ( reg );
|
||||
if ( status != 0 ) {
|
||||
throwWithLocation ( fdInterestSubscriptionAlreadyExits () );
|
||||
int status = priv->fdTbl.add(reg);
|
||||
if (status != 0) {
|
||||
throwWithLocation(fdInterestSubscriptionAlreadyExits());
|
||||
}
|
||||
// errlogPrintf("fdManager::adding fd %d\n", reg.getFD());
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::removeReg ()
|
||||
// fdManager::removeReg()
|
||||
//
|
||||
void fdManager::removeReg (fdReg ®In)
|
||||
void fdManager::removeReg(fdReg ®In)
|
||||
{
|
||||
fdReg *pItemFound;
|
||||
fdReg* pItemFound;
|
||||
|
||||
pItemFound = this->fdTbl.remove (regIn);
|
||||
if (pItemFound!=®In) {
|
||||
fprintf(stderr,
|
||||
"fdManager::removeReg() bad fd registration object\n");
|
||||
pItemFound = priv->fdTbl.remove(regIn);
|
||||
if (pItemFound != ®In) {
|
||||
errlogPrintf("fdManager::removeReg() bad fd registration object\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -288,16 +435,16 @@ void fdManager::removeReg (fdReg ®In)
|
||||
// signal fdManager that the fdReg was deleted
|
||||
// during the call back
|
||||
//
|
||||
if (this->pCBReg == ®In) {
|
||||
this->pCBReg = 0;
|
||||
if (priv->pCBReg == ®In) {
|
||||
priv->pCBReg = NULL;
|
||||
}
|
||||
|
||||
switch (regIn.state) {
|
||||
case fdReg::active:
|
||||
this->activeList.remove (regIn);
|
||||
priv->activeList.remove(regIn);
|
||||
break;
|
||||
case fdReg::pending:
|
||||
this->regList.remove (regIn);
|
||||
priv->regList.remove(regIn);
|
||||
break;
|
||||
case fdReg::limbo:
|
||||
break;
|
||||
@@ -309,49 +456,55 @@ void fdManager::removeReg (fdReg ®In)
|
||||
}
|
||||
regIn.state = fdReg::limbo;
|
||||
|
||||
FD_CLR(regIn.getFD(), &this->fdSetsPtr[regIn.getType()]);
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
FD_CLR(regIn.getFD(), &priv->fdSets[regIn.getType()]);
|
||||
#endif
|
||||
|
||||
// errlogPrintf("fdManager::removing fd %d\n", regIn.getFD());
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::reschedule ()
|
||||
// fdManager::reschedule()
|
||||
// NOOP - this only runs single threaded, and therefore they can only
|
||||
// add a new timer from places that will always end up in a reschedule
|
||||
//
|
||||
void fdManager::reschedule ()
|
||||
void fdManager::reschedule()
|
||||
{
|
||||
}
|
||||
|
||||
double fdManager::quantum ()
|
||||
double fdManager::quantum()
|
||||
{
|
||||
return this->sleepQuantum;
|
||||
return priv->sleepQuantum;
|
||||
}
|
||||
|
||||
//
|
||||
// lookUpFD()
|
||||
//
|
||||
LIBCOM_API fdReg *fdManager::lookUpFD (const SOCKET fd, const fdRegType type)
|
||||
LIBCOM_API fdReg* fdManager::lookUpFD(const SOCKET fd, const fdRegType type)
|
||||
{
|
||||
if (fd<0) {
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
fdRegId id (fd,type);
|
||||
return this->fdTbl.lookup(id);
|
||||
fdRegId id(fd,type);
|
||||
return priv->fdTbl.lookup(id);
|
||||
}
|
||||
|
||||
//
|
||||
// fdReg::fdReg()
|
||||
//
|
||||
fdReg::fdReg (const SOCKET fdIn, const fdRegType typIn,
|
||||
fdReg::fdReg(const SOCKET fdIn, const fdRegType typIn,
|
||||
const bool onceOnlyIn, fdManager &managerIn) :
|
||||
fdRegId (fdIn,typIn), state (limbo),
|
||||
onceOnly (onceOnlyIn), manager (managerIn)
|
||||
fdRegId(fdIn,typIn), state(limbo),
|
||||
onceOnly(onceOnlyIn), manager(managerIn)
|
||||
{
|
||||
#ifdef FDMGR_USE_SELECT
|
||||
if (!FD_IN_FDSET(fdIn)) {
|
||||
fprintf (stderr, "%s: fd > FD_SETSIZE ignored\n",
|
||||
errlogPrintf("%s: fd > FD_SETSIZE ignored\n",
|
||||
__FILE__);
|
||||
return;
|
||||
}
|
||||
this->manager.installReg (*this);
|
||||
#endif
|
||||
manager.installReg(*this);
|
||||
}
|
||||
|
||||
template class resTable<fdReg, fdRegId>;
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
#ifndef fdManagerH_included
|
||||
#define fdManagerH_included
|
||||
|
||||
#include <memory>
|
||||
namespace epics {
|
||||
#if __cplusplus>=201103L
|
||||
template<typename T>
|
||||
using auto_ptr = std::unique_ptr<T>;
|
||||
#else
|
||||
using std::auto_ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "libComAPI.h" // reset share lib defines
|
||||
#include "tsDLList.h"
|
||||
#include "resourceLib.h"
|
||||
@@ -37,27 +47,27 @@ class LIBCOM_API fdRegId
|
||||
{
|
||||
public:
|
||||
|
||||
fdRegId (const SOCKET fdIn, const fdRegType typeIn) :
|
||||
fdRegId(const SOCKET fdIn, const fdRegType typeIn) :
|
||||
fd(fdIn), type(typeIn) {}
|
||||
|
||||
SOCKET getFD () const
|
||||
SOCKET getFD() const
|
||||
{
|
||||
return this->fd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
fdRegType getType () const
|
||||
fdRegType getType() const
|
||||
{
|
||||
return this->type;
|
||||
return type;
|
||||
}
|
||||
|
||||
bool operator == (const fdRegId &idIn) const
|
||||
bool operator == (const fdRegId& idIn) const
|
||||
{
|
||||
return this->fd == idIn.fd && this->type==idIn.type;
|
||||
return fd == idIn.fd && type == idIn.type;
|
||||
}
|
||||
|
||||
resTableIndex hash () const;
|
||||
resTableIndex hash() const;
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
virtual void show(unsigned level) const;
|
||||
|
||||
virtual ~fdRegId() {}
|
||||
private:
|
||||
@@ -70,43 +80,31 @@ private:
|
||||
//
|
||||
// file descriptor manager
|
||||
//
|
||||
class fdManager : public epicsTimerQueueNotify {
|
||||
class LIBCOM_API fdManager : public epicsTimerQueueNotify {
|
||||
public:
|
||||
//
|
||||
// exceptions
|
||||
//
|
||||
class fdInterestSubscriptionAlreadyExits {};
|
||||
|
||||
LIBCOM_API fdManager ();
|
||||
LIBCOM_API virtual ~fdManager ();
|
||||
LIBCOM_API void process ( double delay ); // delay parameter is in seconds
|
||||
fdManager();
|
||||
virtual ~fdManager();
|
||||
void process(double delay); // delay parameter is in seconds
|
||||
|
||||
// returns NULL if the fd is unknown
|
||||
LIBCOM_API class fdReg *lookUpFD (const SOCKET fd, const fdRegType type);
|
||||
class fdReg* lookUpFD(const SOCKET fd, const fdRegType type);
|
||||
|
||||
epicsTimer & createTimer ();
|
||||
epicsTimer& createTimer();
|
||||
|
||||
private:
|
||||
tsDLList < fdReg > regList;
|
||||
tsDLList < fdReg > activeList;
|
||||
resTable < fdReg, fdRegId > fdTbl;
|
||||
const double sleepQuantum;
|
||||
fd_set * fdSetsPtr;
|
||||
epicsTimerQueuePassive * pTimerQueue;
|
||||
SOCKET maxFD;
|
||||
bool processInProg;
|
||||
//
|
||||
// Set to fdreg when in call back
|
||||
// and nill otherwise
|
||||
//
|
||||
fdReg * pCBReg;
|
||||
void reschedule ();
|
||||
double quantum ();
|
||||
void installReg (fdReg ®);
|
||||
void removeReg (fdReg ®);
|
||||
void lazyInitTimerQueue ();
|
||||
fdManager ( const fdManager & );
|
||||
fdManager & operator = ( const fdManager & );
|
||||
epics::auto_ptr <struct fdManagerPrivate> priv;
|
||||
|
||||
void reschedule();
|
||||
double quantum();
|
||||
void installReg(fdReg& reg);
|
||||
void removeReg(fdReg& reg);
|
||||
fdManager(const fdManager&);
|
||||
fdManager& operator = (const fdManager&);
|
||||
friend class fdReg;
|
||||
};
|
||||
|
||||
@@ -126,11 +124,11 @@ class LIBCOM_API fdReg :
|
||||
|
||||
public:
|
||||
|
||||
fdReg (const SOCKET fdIn, const fdRegType type,
|
||||
const bool onceOnly=false, fdManager &manager = fileDescriptorManager);
|
||||
virtual ~fdReg ();
|
||||
fdReg(const SOCKET fdIn, const fdRegType type,
|
||||
const bool onceOnly=false, fdManager& manager = fileDescriptorManager);
|
||||
virtual ~fdReg();
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
virtual void show(unsigned level) const;
|
||||
|
||||
//
|
||||
// Called by the file descriptor manager:
|
||||
@@ -141,7 +139,7 @@ public:
|
||||
//
|
||||
// fdReg::destroy() does a "delete this"
|
||||
//
|
||||
virtual void destroy ();
|
||||
virtual void destroy();
|
||||
|
||||
private:
|
||||
enum state {active, pending, limbo};
|
||||
@@ -153,32 +151,32 @@ private:
|
||||
// lifetime of a fdReg object if the constructor
|
||||
// specified "onceOnly"
|
||||
//
|
||||
virtual void callBack ()=0;
|
||||
virtual void callBack() = 0;
|
||||
|
||||
unsigned char state; // state enums go here
|
||||
unsigned char onceOnly;
|
||||
fdManager &manager;
|
||||
fdManager& manager;
|
||||
|
||||
fdReg ( const fdReg & );
|
||||
fdReg & operator = ( const fdReg & );
|
||||
fdReg(const fdReg&);
|
||||
fdReg& operator = (const fdReg&);
|
||||
};
|
||||
|
||||
//
|
||||
// fdRegId::hash()
|
||||
//
|
||||
inline resTableIndex fdRegId::hash () const
|
||||
inline resTableIndex fdRegId::hash() const
|
||||
{
|
||||
const unsigned fdManagerHashTableMinIndexBits = 8;
|
||||
const unsigned fdManagerHashTableMaxIndexBits = sizeof(SOCKET)*CHAR_BIT;
|
||||
const unsigned fdManagerHashTableMaxIndexBits = sizeof(SOCKET) * CHAR_BIT;
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = integerHash ( fdManagerHashTableMinIndexBits,
|
||||
fdManagerHashTableMaxIndexBits, this->fd );
|
||||
hashid = integerHash(fdManagerHashTableMinIndexBits,
|
||||
fdManagerHashTableMaxIndexBits, fd);
|
||||
|
||||
//
|
||||
// also evenly distribute based on the type of fdRegType
|
||||
//
|
||||
hashid ^= this->type;
|
||||
hashid ^= type;
|
||||
|
||||
//
|
||||
// the result here is always masked to the
|
||||
@@ -187,18 +185,5 @@ inline resTableIndex fdRegId::hash () const
|
||||
return hashid;
|
||||
}
|
||||
|
||||
inline void fdManager::lazyInitTimerQueue ()
|
||||
{
|
||||
if ( ! this->pTimerQueue ) {
|
||||
this->pTimerQueue = & epicsTimerQueuePassive::create ( *this );
|
||||
}
|
||||
}
|
||||
|
||||
inline epicsTimer & fdManager::createTimer ()
|
||||
{
|
||||
this->lazyInitTimerQueue ();
|
||||
return this->pTimerQueue->createTimer ();
|
||||
}
|
||||
|
||||
#endif // fdManagerH_included
|
||||
|
||||
|
||||
@@ -696,16 +696,16 @@ extern void dataend (void);
|
||||
extern void flexerror (char[]) NORETURN;
|
||||
|
||||
/* report a fatal error message and terminate */
|
||||
extern void flexfatal (char[]);
|
||||
extern void flexfatal (char[]) NORETURN;
|
||||
|
||||
/* return current time */
|
||||
extern char *flex_gettime();
|
||||
|
||||
/* report an error message formatted with one integer argument */
|
||||
extern void lerrif (char[], int);
|
||||
extern void lerrif (char[], int) NORETURN;
|
||||
|
||||
/* report an error message formatted with one string argument */
|
||||
extern void lerrsf (char[], char[]);
|
||||
extern void lerrsf (char[], char[]) NORETURN;
|
||||
|
||||
/* spit out a "# line" statement */
|
||||
extern void line_directive_out (FILE*);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ellLib.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
|
||||
#include "initHooks.h"
|
||||
|
||||
@@ -52,19 +53,26 @@ static void initHookInit(void)
|
||||
int initHookRegister(initHookFunction func)
|
||||
{
|
||||
initHookLink *newHook;
|
||||
ELLNODE *cur;
|
||||
|
||||
if (!func) return 0;
|
||||
|
||||
initHookInit();
|
||||
|
||||
newHook = (initHookLink *)malloc(sizeof(initHookLink));
|
||||
if (!newHook) {
|
||||
printf("Cannot malloc a new initHookLink\n");
|
||||
return -1;
|
||||
epicsMutexMustLock(listLock);
|
||||
|
||||
for(cur = ellFirst(&functionList); cur; cur = ellNext(cur)) {
|
||||
const initHookLink *fn = CONTAINER(cur, initHookLink, node);
|
||||
if(fn->func==func) {
|
||||
/* silently ignore duplicate */
|
||||
epicsMutexUnlock(listLock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
newHook = (initHookLink *)mallocMustSucceed(sizeof(initHookLink), "initHookRegister");
|
||||
newHook->func = func;
|
||||
|
||||
epicsMutexMustLock(listLock);
|
||||
ellAdd(&functionList, &newHook->node);
|
||||
epicsMutexUnlock(listLock);
|
||||
return 0;
|
||||
|
||||
@@ -163,7 +163,11 @@ typedef void (*initHookFunction)(initHookState state);
|
||||
*
|
||||
* Registers \p func for initHook notifications
|
||||
* \param func Pointer to application's notification function.
|
||||
* \return 0 if Ok, -1 on error (memory allocation failure).
|
||||
* \return Always zero. (before UNRELEASED could return -1 on allocation failure)
|
||||
*
|
||||
* \since UNRELEASED initHookRegister is idempotent.
|
||||
* Previously, repeated registrations would result
|
||||
* in duplicate calls to the hook function.
|
||||
*/
|
||||
LIBCOM_API int initHookRegister(initHookFunction func);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user