Compare commits

...

33 Commits

Author SHA1 Message Date
6ec0c3b844 rework RHEL cross compilation
Some checks failed
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-16 clang-9 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 pc686 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu (push) Has been cancelled
Base / Win2019 mingw (push) Has been cancelled
Base / Ub-20 gcc-9 C++11, static (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW, static (push) Has been cancelled
Base / Ub-16 gcc-4.8 (push) Has been cancelled
Base / Ub-16 gcc-4.9 (push) Has been cancelled
Base / Ub-20 gcc-8 (push) Has been cancelled
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / Ub-20 gcc-9 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2023-02-10 13:36:31 +01:00
8bad990471 fix the bugfix for gcc-toolset-11 2023-02-02 11:48:21 +01:00
cb4cb6f4d7 build host stuff only for SLx/RHELx 2023-02-02 11:48:21 +01:00
33ecfcb6bc drop support for SL6 and 32 bit Windows 2023-01-18 16:42:22 +01:00
565ccae0b5 fix -g flag usage -- modifying OPT_CFLAGS_YES in CONFIG_SITE.* does not work
Some checks failed
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-16 clang-9 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 pc686 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW, static (push) Has been cancelled
Base / Ub-16 gcc-4.9 (push) Has been cancelled
Base / Ub-20 gcc-8 (push) Has been cancelled
Base / Ub-20 gcc-9 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu (push) Has been cancelled
Base / Win2019 mingw (push) Has been cancelled
Base / Ub-20 gcc-9 C++11, static (push) Has been cancelled
Base / Ub-16 gcc-4.8 (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2022-11-15 14:32:30 +01:00
ddfa24e15d bugfix for long sub function names 2022-11-04 16:08:25 +01:00
6dc7224cea fix problem with fragmented log messages 2022-09-12 17:43:16 +02:00
25a2258663 make NTP driver more robust against strange time stamps 2022-09-12 17:31:25 +02:00
Michael Davidsaver
13bd6bac5f Com: rewrite errlog
Switch to double buffering to allow errlogThread
to unlock while printing.

Conflicts:
	modules/libcom/src/error/errlog.c
2022-08-03 09:18:20 +02:00
39de02f350 fix comments 2022-08-02 17:41:10 +02:00
efd9e7908a allow arrays of strings in CHAR wf and lsi (concatenating) 2022-07-28 12:22:06 +02:00
96fe9306c7 fix JSON errors when reading empty array links 2022-07-27 09:58:09 +02:00
0caa5a045c fix for commit 5e076e6 2022-07-27 09:55:24 +02:00
4ffa5c8c88 fix problem with not working epicsSocketAccept() on moxa42-armv6l
Some checks failed
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-16 clang-9 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 pc686 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu (push) Has been cancelled
Base / Win2019 mingw (push) Has been cancelled
Base / Ub-20 gcc-9 C++11, static (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW, static (push) Has been cancelled
Base / Ub-16 gcc-4.8 (push) Has been cancelled
Base / Ub-16 gcc-4.9 (push) Has been cancelled
Base / Ub-20 gcc-8 (push) Has been cancelled
Base / Ub-20 gcc-9 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2022-06-29 16:03:19 +02:00
5e076e6d30 improve error message 2022-06-29 11:43:56 +02:00
dcb2c5affd fix CA event queuing problem with arrays under high network load 2022-06-28 09:08:57 +02:00
3ac3906fea unify cross windows builds with separate wine dirs per host arch (and thus wine version) 2022-06-21 16:27:33 +02:00
2d597a68b9 enable cross compilation for RHEL7-x86_64 and nilrt7-armv7a on RHEL8 (using mounted SYSROOT at /opt/RHEL7) 2022-06-21 16:27:24 +02:00
1bfe3dec3c use gcc 11 from gcc-toolset for RHEL8 2022-06-10 09:02:20 +02:00
ea0b05c32b use highest supported C++ standard for RHEL8
Some checks failed
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-16 clang-9 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 pc686 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 C++11, static (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW, static (push) Has been cancelled
Base / Ub-20 gcc-9 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu (push) Has been cancelled
Base / Win2019 mingw (push) Has been cancelled
Base / Ub-16 gcc-4.8 (push) Has been cancelled
Base / Ub-16 gcc-4.9 (push) Has been cancelled
Base / Ub-20 gcc-8 (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2022-06-07 11:17:55 +02:00
9c64469f1e re-order cross archs between RHEL7 and RHEL8 hosts 2022-06-07 11:09:03 +02:00
2a4ebdf347 can have only one RTEMS version
Some checks failed
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-16 clang-9 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 pc686 (push) Has been cancelled
Base / Ub-20 gcc-9 C++11, static (push) Has been cancelled
Base / Ub-20 gcc-9 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu (push) Has been cancelled
Base / Win2019 mingw (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW, static (push) Has been cancelled
Base / Ub-16 gcc-4.8 (push) Has been cancelled
Base / Ub-16 gcc-4.9 (push) Has been cancelled
Base / Ub-20 gcc-8 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2022-05-19 09:39:01 +02:00
d5756faef4 restore compatibility with EPICS 3.13 clients 2022-05-19 09:07:31 +02:00
77fb5cf425 use newest C++ standard for yocto 4.0 2022-05-18 16:49:19 +02:00
46141e98d5 add RTEMS 4.9 and 5.1 support 2022-05-05 14:45:08 +02:00
5ac51f86ad disable not needed VxWorks archs 2022-05-05 14:08:36 +02:00
0af4fce080 removed not needed PATH_FILTER 2022-05-05 14:07:14 +02:00
4fb42763a2 moved most cross archs to common linux-x86_64 host arch 2022-05-05 14:06:38 +02:00
211d29c0e1 new yocto 4.0 arch for Zynq 2022-05-05 14:05:19 +02:00
da7bca9c16 some vxWorks 5 hacks 2022-05-05 14:02:31 +02:00
ec346a7b8d update to newer SDK 2022-05-05 14:01:36 +02:00
81d1082bfd no license manager access with this? 2022-05-05 14:01:07 +02:00
3f8cee7d73 fix for debug output formats
Some checks failed
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 pc686 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu (push) Has been cancelled
Base / Ub-20 gcc-9 C++11, static (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
Base / Ub-16 clang-9 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / Win2019 mingw (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW, static (push) Has been cancelled
Base / Ub-16 gcc-4.8 (push) Has been cancelled
Base / Ub-16 gcc-4.9 (push) Has been cancelled
Base / Ub-20 gcc-8 (push) Has been cancelled
Base / Ub-20 gcc-9 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
2021-12-14 16:07:58 +01:00
56 changed files with 634 additions and 719 deletions

View File

@@ -33,7 +33,11 @@ CODE_CFLAGS = $(PROF_CFLAGS_$(PROFILE)) $(GPROF_CFLAGS_$(GPROF))
CODE_CFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
WARN_CFLAGS_YES = -Wall -Werror-implicit-function-declaration
WARN_CFLAGS_NO = -w
OPT_CFLAGS_YES = -O3
# It makes sense to include debugging symbols even in optimized builds
# in case you want to attach gdb to the process or examine a core-dump.
# This does cost disk space, but not memory as debug symbols are not
# loaded into RAM when the binary is loaded.
OPT_CFLAGS_YES = -O3 -g
OPT_CFLAGS_NO = -g
PROF_CXXFLAGS_YES = -p
@@ -42,7 +46,7 @@ CODE_CXXFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
CODE_CXXFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
WARN_CXXFLAGS_YES = -Wall
WARN_CXXFLAGS_NO = -w
OPT_CXXFLAGS_YES = -O3
OPT_CXXFLAGS_YES = -O3 -g
OPT_CXXFLAGS_NO = -g
CODE_LDFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))

View File

@@ -1,2 +1,6 @@
# Include definitions common to linux pentium targets
include $(CONFIG)/os/CONFIG.Common.linux-x86_64
TOOLSET_LOCATION = /opt/rh
#TOOLSET = devtoolset-11
STD_CXXFLAGS = $(if $(TOOLSET),-std=c++17,-std=c++11)

View File

@@ -1,2 +1,18 @@
# Include definitions common to linux pentium targets
include $(CONFIG)/os/CONFIG.Common.linux-x86_64
TOOLSET_LOCATION = /opt/rh
#TOOLSET = gcc-toolset-12
#STD_CXXFLAGS = -std=c++17
# 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)
endif
ifneq (($(TOOLSET)),)
# Perl requests (native) annobin incompatible with the annobin from any TOOLSET
# Disable Perl specific CFLAGS
override Cap5_CFLAGS=
endif

View File

@@ -1 +1,3 @@
include $(CONFIG)/os/CONFIG.Common.linux-clang
STD_CXXFLAGS = -std=c++2a

View File

@@ -32,7 +32,7 @@ OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000
# This check must appear after the above include
ifneq ($(RTEMS_VERSION),5)
ifneq ($(firstword $(subst ., ,$(RTEMS_VERSION))),5)
$(info *** This target is not compatible with the configured RTEMS version.)
$(info *** Build the RTEMS-pc386 (-qemu) target for RTEMS 4.x)
$(error Can't continue)

View File

@@ -0,0 +1,2 @@
RTEMS_VERSION = 4.9
include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386

View File

@@ -0,0 +1,2 @@
RTEMS_VERSION = 5
include $(CONFIG)/os/CONFIG.Common.RTEMS-pc686

View File

@@ -1,7 +0,0 @@
# Include definitions common to linux pentium targets
include $(CONFIG)/os/CONFIG.Common.linux-x86
ARCH_DEP_CFLAGS += -march=i686
# have no full C++11
STD_CXXFLAGS = -std=c++0x

View File

@@ -1,5 +0,0 @@
# Include definitions common to linux pentium targets
include $(CONFIG)/os/CONFIG.Common.linux-x86_64
# have no full C++11
STD_CXXFLAGS = -std=c++0x

View File

@@ -1 +0,0 @@
include $(CONFIG)/os/CONFIG.Common.linux-clang

View File

@@ -1,3 +1,3 @@
include $(CONFIG)/os/CONFIG.Common.vxWorks-ppc32
VXWORKS_VERSION = 6.9
export LD_LIBRARY_PATH=$(WIND_BASE)/lmapi-5.0/$(WIND_HOST_TYPE)/lib
#export LD_LIBRARY_PATH=$(WIND_BASE)/lmapi-5.0/$(WIND_HOST_TYPE)/lib

View File

@@ -1,6 +1,6 @@
include $(CONFIG)/os/CONFIG.Common.vxWorks-ppc604_long
VXWORKS_VERSION = 6.9
export LD_LIBRARY_PATH=$(WIND_BASE)/lmapi-5.0/$(WIND_HOST_TYPE)/lib
#export LD_LIBRARY_PATH=$(WIND_BASE)/lmapi-5.0/$(WIND_HOST_TYPE)/lib
# -fno-implicit-fp causes error: "unable to find a register to spill in class 'FLOAT_REGS'"
ARCH_DEP_CFLAGS = -mcpu=604 -mstrict-align
ARCH_DEP_CFLAGS = -mcpu=604 -mstrict-align

View File

@@ -1,4 +1,4 @@
# DeltaTau PowerPMAC with gcc
# Cross Debian 10 with gcc 8.3
# Include definitions common to all Linux targets
include $(CONFIG)/os/CONFIG.Common.linuxCommon

View File

@@ -14,8 +14,7 @@ GNU_DIR = $(SDKTARGETSYSROOT)/$(SDK_HOST_ARCH)/usr
GNU_BIN = $(GNU_DIR)/bin/$(GNU_ARCH)
GNU_TARGET_INCLUDE_DIR =
GNU_TARGET=powerpc-linux
SYSROOT = $(SDKTARGETSYSROOT)/$(GNU_ARCH)
ARCH_DEP_CPPFLAGS = -m32 -mcpu=440fp -mhard-float
ARCH_DEP_CPPFLAGS += --sysroot=$(SDKTARGETSYSROOT)/$(GNU_ARCH)
ARCH_DEP_LDFLAGS = --sysroot=$(SDKTARGETSYSROOT)/$(GNU_ARCH)
AS=$(GNU_BIN)/$(GNU_TARGET)-as

View File

@@ -10,14 +10,8 @@ SDK_DIR = /opt/fsl-qoriq/2.0
SDK_HOST_ARCH = $(GNU_HOST_ARCH_64)-$(SDK)-$(GNU_HOST_OS)
SDK_TARGET = ppc64e6500-fsl-linux
GNU_TARGET = powerpc64-fsl-linux
SDKTARGETSYSROOT = $(SDK_DIR)/sysroots/$(SDK_TARGET)
SYSROOT = $(SDK_DIR)/sysroots/$(SDK_TARGET)
GNU_DIR = $(SDK_DIR)/sysroots/$(SDK_HOST_ARCH)/usr
GNU_BIN = $(GNU_DIR)/bin/$(GNU_TARGET)
ARCH_DEP_CPPFLAGS = --sysroot=$(SDKTARGETSYSROOT)
ARCH_DEP_CFLAGS = -mcpu=e6500 -m64 -mhard-float
ARCH_DEP_LDFLAGS = --sysroot=$(SDKTARGETSYSROOT)
# warning -O2 and higher are broken!
#OPT_CFLAGS_YES = -O1
#OPT_CXXFLAGS_YES = -O1

View File

@@ -1,4 +1,4 @@
# DeltaTau PowerPMAC with gcc
# DeltaTau PowerPMAC with gcc 8.5
# Include definitions common to all Linux targets
include $(CONFIG)/os/CONFIG.Common.linuxCommon

View File

@@ -17,3 +17,7 @@ ARCH_DEP_CFLAGS += -funwind-tables
# have no full C++11
STD_CXXFLAGS = -std=c++0x
# accept4() exists but does not work
# Give fake __rtems__ macro to posix/osdSock.c because that disables accept4()
osdSock_CFLAGS += -D__rtems__

View File

@@ -10,9 +10,7 @@ GNU_TARGET = arm-linux-gnu
SYSROOT = /opt/LabVIEW-RT-19.5.1/arm/sysroots/armv7a-vfp-neon-nilrt-linux-gnueabi
ARCH_DEP_CPPFLAGS += -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon
ARCH_DEP_CPPFLAGS += --sysroot=$(SYSROOT)
ARCH_DEP_CPPFLAGS += -I$(SYSROOT)/usr/include/c++/4.7.2/arm-nilrt-linux-gnueabi/
ARCH_DEP_CPPFLAGS += -I$(SYSROOT)/usr/include/c++/4.7.2/
ARCH_DEP_LDFLAGS += --sysroot=$(SYSROOT)
ARCH_DEP_CXXFLAGS += -I$(SYSROOT)/usr/include/c++/4.7.2/arm-nilrt-linux-gnueabi/
ARCH_DEP_CXXFLAGS += -I$(SYSROOT)/usr/include/c++/4.7.2/
COMMANDLINE_LIBRARY = READLINE_NCURSES

View File

@@ -6,13 +6,10 @@ include $(CONFIG)/os/CONFIG.Common.linuxCommon
ARCH_CLASS = arm64
SDK = petalinux
SDK_DIR = /opt/petalinux-gfa/2017.2
SDK_DIR = /opt/petalinux-gfa/2018.1
SDK_HOST_ARCH = $(GNU_HOST_ARCH_64)-$(SDK)-$(GNU_HOST_OS)
SDK_TARGET = aarch64-xilinx-linux
GNU_TARGET = $(SDK_TARGET)
SDKTARGETSYSROOT = $(SDK_DIR)/sysroots/$(SDK_TARGET)
SYSROOT = $(SDK_DIR)/sysroots/$(SDK_TARGET)
GNU_DIR = $(SDK_DIR)/sysroots/$(SDK_HOST_ARCH)/usr
GNU_BIN = $(GNU_DIR)/bin/$(GNU_TARGET)
ARCH_DEP_CPPFLAGS = --sysroot=$(SDKTARGETSYSROOT)
ARCH_DEP_LDFLAGS = --sysroot=$(SDKTARGETSYSROOT)

View File

@@ -0,0 +1,19 @@
# XILINX Zynq with Yocto 4.0 toolchain
# Include definitions common to all Linux targets
include $(CONFIG)/os/CONFIG.Common.linuxCommon
ARCH_CLASS = arm64
SDK = pokysdk
SDK_DIR = /opt/yocto40-aarch64
SDK_HOST_ARCH = $(GNU_HOST_ARCH_64)-$(SDK)-$(GNU_HOST_OS)
SDK_TARGET = cortexa53-poky-linux
GNU_TARGET = aarch64-poky-linux
SYSROOT = $(SDK_DIR)/sysroots/$(SDK_TARGET)
GNU_DIR = $(SDK_DIR)/sysroots/$(SDK_HOST_ARCH)/usr
GNU_BIN = $(GNU_DIR)/bin/$(GNU_TARGET)
ARCH_DEP_CPPFLAGS = -mcpu=cortex-a53 -march=armv8-a+crc
STD_CXXFLAGS = -std=c++23

View File

@@ -0,0 +1,6 @@
include $(CONFIG)/os/CONFIG.windows-x64.windows-x64
VALID_BUILDS = Ioc Command
PATH := /opt/wine-msvc-2017/bin/x64:$(PATH)
export WINEPREFIX = $(HOME)/.wine-$(EPICS_HOST_ARCH)

View File

@@ -1,6 +0,0 @@
# "cross compile" for older Linux version (32 bit)
# It was neccessary to install 32 bit compatibility libraries manually
#-------------------------------------------------------
include $(CONFIG)/os/CONFIG.RHEL7-x86_64.SL6-x86_64
TARGET_LDFLAGS = -B /usr/lib/x86_64-redhat-linux6E/lib

View File

@@ -1,16 +0,0 @@
# "cross compile" for older Linux version
# Use older compiler and older libraries
# Used packages:
# compat-gcc-44-c++-4.4.7
# compat-gcc-44-4.4.7
# compat-glibc-headers-2.12
# compat-glibc-2.12
#-------------------------------------------------------
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86
CC = $(GNU_BIN)/$(CMPLR_PREFIX)gcc44
CCC = $(GNU_BIN)/$(CMPLR_PREFIX)g++44
TARGET_CPPFLAGS = -isystem /usr/lib/x86_64-redhat-linux6E/include
TARGET_LDFLAGS = -B /usr/lib/x86_64-redhat-linux6E/lib64
LINK.cpp += --as-needed -lc -lm -lrt -lpthread -lreadline -ltinfo

View File

@@ -1,5 +0,0 @@
include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
PATH_FILTER = $(subst /,/,$(1))
PATH := /opt/wine-msvc-2017/bin/x86:$(PATH)

View File

@@ -1,5 +1 @@
include $(CONFIG)/os/CONFIG.windows-x64.windows-x64
PATH_FILTER = $(subst /,/,$(1))
PATH := /opt/wine-msvc-2017/bin/x64:$(PATH)
include $(CONFIG)/os/CONFIG.Linux.windows-x64

View File

@@ -0,0 +1,23 @@
# Include common linux definitions
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86
# "Cross compile" for RHEL7-x86_64
# Expects RHEL7 RPMs c++ and readline-devel installed
# in $(SYSROOT)
# This can be installed on RHEL7 with:
# yum install --installroot=$(SYSROOT) <packages>
# (Assuming $(SYSROOT) is on a shared network volume.)
# Optionally use a newer TOOLSET (installed on $(SYSROOT)).
SYSROOT = /opt/RHEL7
GNU_DIR = $(SYSROOT)$(TOOLSET_DIR)
# "Cross" TOOLSET progs need to find their libraries
LD_LIBRARY_PATH = $(TOOLSET_DIR:%=$(SYSROOT)%/usr/$$LIB)
# These programs have library problems when using them
# from SYSROOT but without TOOLSET.
# But provinding LD_LIBRARY PATH crashes other progams.
# Our host versions work just fine.
AR = ar -rc
RANLIB = ranlib

View File

@@ -0,0 +1 @@
GNU_BIN=/opt/RHEL7/bin

View File

@@ -1,5 +0,0 @@
include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
PATH_FILTER = $(subst /,/,$(1))
PATH := /opt/wine-msvc-2017/bin/x86:$(PATH)

View File

@@ -1,5 +1 @@
include $(CONFIG)/os/CONFIG.windows-x64.windows-x64
PATH_FILTER = $(subst /,/,$(1))
PATH := /opt/wine-msvc-2017/bin/x64:$(PATH)
include $(CONFIG)/os/CONFIG.Linux.windows-x64

View File

@@ -1,2 +0,0 @@
#CONFIG.$(EPICS_HOST_ARCH).Common is required by build system
#Include definitions common to linux hosts

View File

@@ -1,2 +0,0 @@
# Include common linux definitions
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86

View File

@@ -1,3 +0,0 @@
#CONFIG.$(EPICS_HOST_ARCH).Common is required by build system
#Include definitions common to linux hosts
include $(CONFIG)/os/CONFIG.linux-x86_64.Common

View File

@@ -1,2 +0,0 @@
# Include common linux definitions
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86

View File

@@ -1,2 +0,0 @@
# Include common linux definitions
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86

View File

@@ -24,6 +24,9 @@
#RTEMS_VERSION = 5
#RTEMS_BASE = /usr/local/vw/rtems/rtems-5.1
# PSI:
RTEMS_BASE = /opt/rtems/$(RTEMS_VERSION)
# Cross-compile toolchain in $(RTEMS_TOOLS)/bin
#
RTEMS_TOOLS = $(RTEMS_BASE)

View File

@@ -12,3 +12,12 @@ COMMANDLINE_LIBRARY = READLINE
CODE_CPPFLAGS += -fno-strict-aliasing
USR_CXXFLAGS += $(STD_CXXFLAGS)
STD_CXXFLAGS = -std=c++11
TOOLSET_DIR = $(TOOLSET:%=$(TOOLSET_LOCATION)/%/root)
GNU_DIR = $(TOOLSET_DIR)
TARGET_CPPFLAGS += $(SYSROOT:%=--sysroot=%)
TARGET_LDFLAGS += $(SYSROOT:%=--sysroot=%)
ifeq ($(filter SL% RHEL%,$(T_A)),)
VALID_BUILDS = Ioc Command
endif

View File

@@ -71,6 +71,7 @@ GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
OP_SYS_CFLAGS += -fno-strict-aliasing
OP_SYS_INCLUDE_CPPFLAGS_5 += -include $(VX_DIR)/target/h/vxWorks.h
OP_SYS_INCLUDE_CPPFLAGS_5 += -I$(EPICS_BASE)/include/os/vxWorks/vxWorks5
OP_SYS_INCLUDE_CPPFLAGS_6 += -include $(VX_DIR)/target/h/vxWorks.h
OP_SYS_INCLUDE_CPPFLAGS_7 += -include vxWorks.h
OP_SYS_INCLUDE_CPPFLAGS = $(OP_SYS_INCLUDE_CPPFLAGS_$(VXWORKS_MAJOR_VERSION))
@@ -79,7 +80,7 @@ OP_SYS_LDFLAGS += $(OP_SYS_LDFLAGS_$@)
OP_SYS_LDFLAGS_softIoc = -whole-archive
OP_SYS_LDFLAGS_softIocPVA = -whole-archive
# code flags
# code flags (delete -fno-implicit-templates)
CODE_CXXFLAGS =
# WIND_BASE is where you installed the Wind River software.

View File

@@ -4,25 +4,7 @@ include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common
CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64-clang
CROSS_COMPILER_RUNTEST_ARCHS += RHEL7-x86_64-clang
# Build for old SL6 64 bit
CROSS_COMPILER_TARGET_ARCHS += SL6-x86_64
CROSS_COMPILER_RUNTEST_ARCHS += SL6-x86_64
# Build for old SL6 32 bit
CROSS_COMPILER_TARGET_ARCHS += SL6-x86
CROSS_COMPILER_RUNTEST_ARCHS += SL6-x86
# Cross compilers that don't work on SL6 hosts
# Debian 10
CROSS_COMPILER_TARGET_ARCHS += deb10-x86_64
# Newer DeltaTau PowerPMAC
CROSS_COMPILER_TARGET_ARCHS += gcc8-ppc4xxFP
# NI Linux Real-Time 7.x
# requires RPM gcc-c++-arm-linux-gnu
# Not available on RHEL8
CROSS_COMPILER_TARGET_ARCHS += nilrt7-armv7a
# Windows cross builds using Wine
CROSS_COMPILER_TARGET_ARCHS += win32-x86 windows-x64

View File

@@ -4,18 +4,8 @@ include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common
CROSS_COMPILER_TARGET_ARCHS += RHEL8-x86_64-clang
# Build for old RHEL7 64 bit
#CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64
# Build for old SL6 64 bit
#CROSS_COMPILER_TARGET_ARCHS += SL6-x86_64
# Build for old SL6 32 bit
#CROSS_COMPILER_TARGET_ARCHS += SL6-x86
CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64
# NI Linux Real-Time 7.x
# requires RPM gcc-c++-arm-linux-gnu
# not available yet for RHEL8
#CROSS_COMPILER_TARGET_ARCHS += nilrt7-armv7a
# Windows cross builds using Wine
CROSS_COMPILER_TARGET_ARCHS += win32-x86 windows-x64
CROSS_COMPILER_TARGET_ARCHS += nilrt7-armv7a

View File

@@ -1 +0,0 @@
include $(CONFIG)/os/CONFIG_SITE.linux-x86.Common

View File

@@ -1,7 +0,0 @@
# Build 32 bit version as a cross architecture
#CROSS_COMPILER_TARGET_ARCHS += SL6-x86
# Improved error checking with clang
#CROSS_COMPILER_TARGET_ARCHS += SL6-x86_64-clang
include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common

View File

@@ -18,11 +18,11 @@ LD_LIBRARY_PATH=
CROSS_COMPILER_TARGET_ARCHS += T2-ppc604
# vxWorks 6.7 for MVxxxx boards
CROSS_COMPILER_TARGET_ARCHS += V67-ppc604
#CROSS_COMPILER_TARGET_ARCHS += V67-ppc604
# vxWorks 6.9 for MVxxxx boards
CROSS_COMPILER_TARGET_ARCHS += V69-ppc604
CROSS_COMPILER_TARGET_ARCHS += V69-ppc32
#CROSS_COMPILER_TARGET_ARCHS += V69-ppc32
# NI compact RIO
CROSS_COMPILER_TARGET_ARCHS += V63-ppc603
@@ -45,11 +45,16 @@ CROSS_COMPILER_TARGET_ARCHS += eldk53-ppc4xxFP
# Test other vxWorks versions
#CROSS_COMPILER_TARGET_ARCHS += V66-ppc603
CROSS_COMPILER_TARGET_ARCHS += V66-ppc604
#CROSS_COMPILER_TARGET_ARCHS += V66-ppc604
#CROSS_COMPILER_TARGET_ARCHS += V63-ppc604
CROSS_COMPILER_TARGET_ARCHS += V64-ppc604
#CROSS_COMPILER_TARGET_ARCHS += V64-ppc604
# (No PVA because of old compiler)
CROSS_COMPILER_TARGET_ARCHS += V62-ppc604
#CROSS_COMPILER_TARGET_ARCHS += V62-ppc604
# Raspberry Pi
CROSS_COMPILER_TARGET_ARCHS += raspbian-arm
# RTEMS (Can only have 1 RTEMS major version in 1 EPICS installation
# because they overwrite their header files.)
#CROSS_COMPILER_TARGET_ARCHS += RTEMS49-pc386
CROSS_COMPILER_TARGET_ARCHS += RTEMS51-pc686

View File

@@ -3,13 +3,6 @@
# Site specific definitions for linux-x86 host - linux-x86 target builds
#-------------------------------------------------------
# It makes sense to include debugging symbols even in optimized builds
# in case you want to attach gdb to the process or examine a core-dump.
# This does cost disk space, but not memory as debug symbols are not
# loaded into RAM when the binary is loaded.
OPT_CFLAGS_YES += -g
OPT_CXXFLAGS_YES += -g
# Uncomment the followings lines to build with CLANG instead of GCC.
#
#GNU = NO

View File

@@ -11,8 +11,18 @@ include $(CONFIG)/os/CONFIG_SITE.linux-x86.Common
GNU_HOST_ARCH_64=x86_64
# Windows cross builds using Wine
CROSS_COMPILER_TARGET_ARCHS += windows-x64
# IOxOS IFC1211
CROSS_COMPILER_TARGET_ARCHS += fslqoriq20-e6500_64
# Zynq
CROSS_COMPILER_TARGET_ARCHS += yocto21-aarch64
CROSS_COMPILER_TARGET_ARCHS += yocto40-aarch64
# Debian 10
CROSS_COMPILER_TARGET_ARCHS += deb10-x86_64
# Newer DeltaTau PowerPMAC
CROSS_COMPILER_TARGET_ARCHS += gcc8-ppc4xxFP

View File

@@ -3,13 +3,6 @@
# Site specific definitions for linux-x86_64 host - linux-x86_64 target builds
#-------------------------------------------------------
# It makes sense to include debugging symbols even in optimized builds
# in case you want to attach gdb to the process or examine a core-dump.
# This does cost disk space, but not memory as debug symbols are not
# loaded into RAM when the binary is loaded.
OPT_CFLAGS_YES += -g
OPT_CXXFLAGS_YES += -g
# Uncomment the followings lines to build with CLANG instead of GCC.
#
#GNU = NO

View File

@@ -27,6 +27,7 @@
#include "dbFldTypes.h"
#include "dbLink.h"
#include "link.h"
#include "errlog.h"
/**************************** Convert functions ****************************/
@@ -178,17 +179,23 @@ static long dbConstLoadLS(struct link *plink, char *pbuffer, epicsUInt32 size,
epicsUInt32 *plen)
{
const char *pstr = plink->value.constantStr;
long status;
if (!pstr)
return S_db_badField;
return dbLSConvertJSON(pstr, pbuffer, size, plen);
status = dbLSConvertJSON(pstr, pbuffer, size, plen);
if (status)
errlogPrintf("... while parsing link %s.%s\n",
plink->precord->name, dbLinkFieldName(plink));
return status;
}
static long dbConstLoadArray(struct link *plink, short dbrType, void *pbuffer,
long *pnReq)
{
const char *pstr = plink->value.constantStr;
long status;
if (!pstr)
return S_db_badField;
@@ -197,7 +204,11 @@ static long dbConstLoadArray(struct link *plink, short dbrType, void *pbuffer,
if (dbrType == DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE)
dbrType = DBF_USHORT;
return dbPutConvertJSON(pstr, dbrType, pbuffer, pnReq);
status = dbPutConvertJSON(pstr, dbrType, pbuffer, pnReq);
if (status)
errlogPrintf("... while parsing link %s.%s\n",
plink->precord->name, dbLinkFieldName(plink));
return status;
}
static long dbConstGetNelements(const struct link *plink, long *nelements)

View File

@@ -26,14 +26,16 @@ typedef struct parseContext {
short dbrType;
short dbrSize;
char *pdest;
int elems;
size_t elems;
} parseContext;
static int dbcj_null(void *ctx) {
errlogPrintf("dbConvertJSON: Null objects not supported\n");
return 0; /* Illegal */
}
static int dbcj_boolean(void *ctx, int val) {
errlogPrintf("dbConvertJSON: Boolean not supported\n");
return 0; /* Illegal */
}
@@ -50,10 +52,6 @@ static int dbcj_integer(void *ctx, long long num) {
return 1;
}
static int dblsj_integer(void *ctx, long long num) {
return 0; /* Illegal */
}
static int dbcj_double(void *ctx, double num) {
parseContext *parser = (parseContext *) ctx;
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
@@ -66,19 +64,23 @@ static int dbcj_double(void *ctx, double num) {
return 1;
}
static int dblsj_double(void *ctx, double num) {
return 0; /* Illegal */
}
static int dbcj_string(void *ctx, const unsigned char *val, size_t len) {
parseContext *parser = (parseContext *) ctx;
char *pdest = parser->pdest;
/* Not attempting to handle char-array fields here, they need more
* metadata about the field than we have available at the moment.
*/
if (parser->dbrType == DBF_CHAR || parser->dbrType == DBF_UCHAR) {
/* Treating char array as long string */
if (len > parser->elems)
len = parser->elems;
strncpy(pdest, (const char *) val, len);
parser->elems -= len;
parser->pdest += len;
return 1;
}
if (parser->dbrType != DBF_STRING) {
errlogPrintf("dbConvertJSON: String provided, numeric value(s) expected\n");
errlogPrintf("dbConvertJSON: String \"%.*s\" provided, numeric value expected\n",
(int)len, val);
return 0; /* Illegal */
}
@@ -93,39 +95,11 @@ static int dbcj_string(void *ctx, const unsigned char *val, size_t len) {
return 1;
}
static int dblsj_string(void *ctx, const unsigned char *val, size_t len) {
parseContext *parser = (parseContext *) ctx;
char *pdest = parser->pdest;
if (parser->dbrType != DBF_STRING) {
errlogPrintf("dbConvertJSON: dblsj_string dbrType error\n");
return 0; /* Illegal */
}
if (parser->elems > 0) {
if (len > parser->dbrSize - 1)
len = parser->dbrSize - 1;
strncpy(pdest, (const char *) val, len);
pdest[len] = 0;
parser->pdest = pdest + len;
parser->elems = 0;
}
return 1;
}
static int dbcj_start_map(void *ctx) {
errlogPrintf("dbConvertJSON: Map type not supported\n");
return 0; /* Illegal */
}
static int dbcj_map_key(void *ctx, const unsigned char *key, size_t len) {
return 0; /* Illegal */
}
static int dbcj_end_map(void *ctx) {
return 0; /* Illegal */
}
static int dbcj_start_array(void *ctx) {
parseContext *parser = (parseContext *) ctx;
@@ -135,32 +109,35 @@ static int dbcj_start_array(void *ctx) {
return (parser->depth == 1);
}
static int dbcj_end_array(void *ctx) {
parseContext *parser = (parseContext *) ctx;
parser->depth--;
return (parser->depth == 0);
}
static yajl_callbacks dbcj_callbacks = {
dbcj_null, dbcj_boolean, dbcj_integer, dbcj_double, NULL, dbcj_string,
dbcj_start_map, dbcj_map_key, dbcj_end_map,
dbcj_start_array, dbcj_end_array
dbcj_start_map, NULL, NULL,
dbcj_start_array, NULL
};
long dbPutConvertJSON(const char *json, short dbrType,
void *pdest, long *pnRequest)
{
parseContext context, *parser = &context;
yajl_alloc_funcs dbcj_alloc;
yajl_handle yh;
yajl_status ys;
size_t jlen = strlen(json);
long status;
if(INVALID_DB_REQ(dbrType))
if (INVALID_DB_REQ(dbrType)) {
errlogPrintf("dbConvertJSON: Invalid dbrType %d\n", dbrType);
return S_db_badDbrtype;
}
if (!jlen) {
*pnRequest = 0;
return 0;
}
if (!jlen) {
*pnRequest = 0;
return 0;
}
parser->depth = 0;
parser->dbrType = dbrType;
@@ -168,10 +145,11 @@ long dbPutConvertJSON(const char *json, short dbrType,
parser->pdest = pdest;
parser->elems = *pnRequest;
yajl_set_default_alloc_funcs(&dbcj_alloc);
yh = yajl_alloc(&dbcj_callbacks, &dbcj_alloc, parser);
if (!yh)
yh = yajl_alloc(&dbcj_callbacks, NULL, parser);
if (!yh) {
errlogPrintf("dbConvertJSON: out of memory\n");
return S_db_noMemory;
}
ys = yajl_parse(yh, (const unsigned char *) json, jlen);
if (ys == yajl_status_ok)
@@ -183,36 +161,23 @@ long dbPutConvertJSON(const char *json, short dbrType,
status = 0;
break;
case yajl_status_error: {
unsigned char *err = yajl_get_error(yh, 1,
(const unsigned char *) json, jlen);
fprintf(stderr, "dbConvertJSON: %s\n", err);
yajl_free_error(yh, err);
default: {
unsigned char *err = yajl_get_error(yh, 1,
(const unsigned char *) json, jlen);
errlogPrintf("dbConvertJSON: %s", err);
yajl_free_error(yh, err);
status = S_db_badField;
}
/* fall through */
default:
status = S_db_badField;
}
yajl_free(yh);
return status;
}
static yajl_callbacks dblsj_callbacks = {
dbcj_null, dbcj_boolean, dblsj_integer, dblsj_double, NULL, dblsj_string,
dbcj_start_map, dbcj_map_key, dbcj_end_map,
dbcj_start_array, dbcj_end_array
};
long dbLSConvertJSON(const char *json, char *pdest, epicsUInt32 size,
epicsUInt32 *plen)
{
parseContext context, *parser = &context;
yajl_alloc_funcs dbcj_alloc;
yajl_handle yh;
yajl_status ys;
size_t jlen = strlen(json);
long nRequest = size-1;
long status;
if (!size) {
@@ -220,36 +185,8 @@ long dbLSConvertJSON(const char *json, char *pdest, epicsUInt32 size,
return 0;
}
parser->depth = 0;
parser->dbrType = DBF_STRING;
parser->dbrSize = size;
parser->pdest = pdest;
parser->elems = 1;
yajl_set_default_alloc_funcs(&dbcj_alloc);
yh = yajl_alloc(&dblsj_callbacks, &dbcj_alloc, parser);
if (!yh)
return S_db_noMemory;
ys = yajl_parse(yh, (const unsigned char *) json, jlen);
switch (ys) {
case yajl_status_ok:
*plen = (char *) parser->pdest - pdest + 1;
status = 0;
break;
case yajl_status_error: {
unsigned char *err = yajl_get_error(yh, 1,
(const unsigned char *) json, jlen);
fprintf(stderr, "dbLoadLS_JSON: %s\n", err);
yajl_free_error(yh, err);
}
/* fall through */
default:
status = S_db_badField;
}
yajl_free(yh);
status = dbPutConvertJSON(json, DBF_CHAR, pdest, &nRequest);
pdest[nRequest++] = 0;
*plen = nRequest;
return status;
}

View File

@@ -789,6 +789,18 @@ static void db_queue_event_log (evSubscrip *pevent, db_field_log *pLog)
LOCKEVQUE (ev_que);
/* if we have an event on the queue and both the last
* event on the queue and the current event are empty,
* simply ignore duplicate events.
*/
if (pevent->npend > 0u
&& !dbfl_has_copy(*pevent->pLastLog)
&& !dbfl_has_copy(pLog)) {
db_delete_field_log(pLog);
UNLOCKEVQUE (ev_que);
return;
}
/*
* add to task local event que
*/

View File

@@ -996,8 +996,12 @@ static void printBuffer(
i = 0;
while (len > 0) {
int chunk = (len > MAXLINE - 5) ? MAXLINE - 5 : len;
sprintf(pmsg, "\"%.*s\"", chunk, (char *)pbuffer + i);
strcpy(pmsg, "\"");
while (epicsStrnEscapedFromRawSize((char *)pbuffer + i, chunk) >= MAXLINE - 5)
chunk--;
epicsStrnEscapedFromRaw(pmsg+1, MAXLINE - 5,
(char *)pbuffer + i, chunk);
strcat(pmsg, "\"");
len -= chunk; i += chunk;
if (len > 0)
strcat(pmsg, " +");

View File

@@ -2197,12 +2197,12 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
*/
} else if(dbCanSetLink(plink, &link_info, devsup)!=0) {
errlogPrintf("Error: %s.%s: can't initialize link type %d with \"%s\" (type %d)\n",
prec->name, pflddes->name, plink->type, plink->text, link_info.ltype);
errlogPrintf("Error: %s.%s: can't initialize link type %s with \"%s\" (type %s)\n",
prec->name, pflddes->name, pamaplinkType[plink->type].strvalue, plink->text, pamaplinkType[link_info.ltype].strvalue);
} else if(dbSetLink(plink, &link_info, devsup)) {
errlogPrintf("Error: %s.%s: failed to initialize link type %d with \"%s\" (type %d)\n",
prec->name, pflddes->name, plink->type, plink->text, link_info.ltype);
errlogPrintf("Error: %s.%s: failed to initialize link type %s with \"%s\" (type %s)\n",
prec->name, pflddes->name, pamaplinkType[plink->type].strvalue, plink->text, pamaplinkType[link_info.ltype].strvalue);
}
free(plink->text);
plink->text = NULL;

View File

@@ -280,6 +280,37 @@ static void log_header (
struct channel_in_use *pciu;
char hostName[256];
const char * cmd_str [] = {
"CA_PROTO_VERSION",
"CA_PROTO_EVENT_ADD",
"CA_PROTO_EVENT_CANCEL",
"CA_PROTO_READ",
"CA_PROTO_WRITE",
"CA_PROTO_SNAPSHOT",
"CA_PROTO_SEARCH",
"CA_PROTO_BUILD",
"CA_PROTO_EVENTS_OFF",
"CA_PROTO_EVENTS_ON",
"CA_PROTO_READ_SYNC",
"CA_PROTO_ERROR",
"CA_PROTO_CLEAR_CHANNEL",
"CA_PROTO_RSRV_IS_UP",
"CA_PROTO_NOT_FOUND",
"CA_PROTO_READ_NOTIFY",
"CA_PROTO_READ_BUILD",
"REPEATER_CONFIRM",
"CA_PROTO_CREATE_CHAN",
"CA_PROTO_WRITE_NOTIFY",
"CA_PROTO_CLIENT_NAME",
"CA_PROTO_HOST_NAME",
"CA_PROTO_ACCESS_RIGHTS",
"CA_PROTO_ECHO",
"REPEATER_REGISTER",
"CA_PROTO_SIGNAL",
"CA_PROTO_CREATE_CH_FAIL",
"CA_PROTO_SERVER_DISCONN"
};
ipAddrToDottedIP (&client->addr, hostName, sizeof(hostName));
pciu = MPTOPCIU(mp);
@@ -289,8 +320,10 @@ static void log_header (
hostName, pContext);
}
epicsPrintf ( "CAS: Request from %s => cmmd=%d cid=0x%x type=%d count=%d postsize=%u\n",
hostName, mp->m_cmmd, mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize);
epicsPrintf ( "CAS: %s Request from %s => cmmd=%d (%s) cid=0x%x type=%d count=%d postsize=%u version=%u\n",
client->proto==IPPROTO_TCP ? "TCP" : "UDP",
hostName, mp->m_cmmd, mp->m_cmmd <= CA_PROTO_LAST_CMMD ? cmd_str[mp->m_cmmd] : "invalid",
mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize, client->minor_version_number);
epicsPrintf ( "CAS: Request from %s => available=0x%x \tN=%u paddr=%p\n",
hostName, mp->m_available, mnum, (pciu ? (void *)&pciu->dbch : NULL));
@@ -319,6 +352,18 @@ unsigned lineno
SEND_UNLOCK ( client );
}
/*
* bad_udp_cmd_beacon()
*/
static int bad_udp_cmd_beacon ( caHdrLargeArray *mp,
void *pPayload, struct client *pClient )
{
if (CASDEBUG > 0)
log_header ("got a beacon on the wrong UDP port",
pClient, mp, pPayload, 0);
return RSRV_ERROR;
}
/*
* bad_udp_cmd_action()
*/
@@ -363,6 +408,8 @@ static int tcp_version_action ( caHdrLargeArray *mp, void *pPayload,
client->minor_version_number = mp->m_count;
DLOG(3, ("TCP set version %u\n", client->minor_version_number));
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore version from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
@@ -1213,6 +1260,7 @@ static int claim_ciu_action ( caHdrLargeArray *mp,
struct dbChannel *dbch;
char *pName = (char *) pPayload;
DLOG (3, ("claim_ciu_action: version = %u\n", mp->m_available));
/*
* The available field is used (abused)
* here to communicate the miner version number
@@ -2121,6 +2169,8 @@ static int udp_version_action ( caHdrLargeArray *mp, void *pPayload, struct clie
{
client->minor_version_number = mp->m_count;
DLOG (3, ("UDP set version %u\n", client->minor_version_number));
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore version from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
@@ -2174,6 +2224,9 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client
size_t spaceNeeded;
size_t reasonableMonitorSpace = 10;
DLOG (3, epicsPrintf("UDP search for \"%.*s\" by %s@%s client version %u, m_count = %u\n",
mp->m_postsize, pName, client->pUserName, client->pHostName, client->minor_version_number, mp->m_count));
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore search from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
@@ -2261,6 +2314,9 @@ static int search_reply_tcp (
size_t spaceNeeded;
size_t reasonableMonitorSpace = 10;
DLOG (3, ("TCP search for \"%.*s\" by %s@%s client version %u, m_count = %u\n",
mp->m_postsize, pName, client->pUserName, client->pHostName, client->minor_version_number, mp->m_count));
if (!CA_VSUPPORTED(mp->m_count)) {
DLOG ( 2, ( "CAS: Ignore search from unsupported client %u\n", mp->m_count ) );
return RSRV_ERROR;
@@ -2368,7 +2424,7 @@ static const pProtoStubUDP udpJumpTable[] =
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_beacon,
bad_udp_cmd_action,
bad_udp_cmd_action,
bad_udp_cmd_action,
@@ -2449,6 +2505,7 @@ int camessage ( struct client *client )
pBody = ( void * ) ( mp + 1 );
}
#if 0
/* ignore deprecated clients, but let newer clients identify themselves. */
if (msg.m_cmmd!=CA_PROTO_VERSION && !CA_VSUPPORTED(client->minor_version_number)) {
if (client->proto==IPPROTO_TCP) {
@@ -2470,6 +2527,7 @@ int camessage ( struct client *client )
}
break;
}
#endif
/*
* disconnect clients that dont send 8 byte

View File

@@ -46,6 +46,7 @@ if ($opt_D) { # Output dependencies only
}
$Text::Wrap::columns = 75;
$Text::Wrap::huge = "overflow";
# Eliminate chars not allowed in C symbol names
my $c_bad_ident_chars = '[^0-9A-Za-z_]';

View File

@@ -20,12 +20,12 @@
#include <errno.h>
#define ERRLOG_INIT
#include "adjustment.h"
#include "dbDefs.h"
#include "epicsThread.h"
#include "cantProceed.h"
#include "epicsMutex.h"
#include "epicsEvent.h"
#include "epicsString.h"
#include "epicsInterrupt.h"
#include "errMdef.h"
#include "errSymTbl.h"
@@ -35,8 +35,20 @@
#include "epicsExit.h"
#define BUFFER_SIZE 1280
#define MAX_MESSAGE_SIZE 256
#define MIN_BUFFER_SIZE 1280
#define MIN_MESSAGE_SIZE 256
#define MAX_MESSAGE_SIZE 0x00ffffff
/* errlog buffers contain null terminated strings, each prefixed
* with a 1 byte header containing flags.
*/
/* State of entries in a buffer. */
#define ERL_STATE_MASK 0xc0
#define ERL_STATE_FREE 0x00
#define ERL_STATE_WRITE 0x80
#define ERL_STATE_READY 0x40
/* should this message be echoed to the console? */
#define ERL_LOCALECHO 0x20
/*Declare storage for errVerbose */
int errVerbose = 0;
@@ -44,137 +56,183 @@ int errVerbose = 0;
static void errlogExitHandler(void *);
static void errlogThread(void);
static char *msgbufGetFree(int noConsoleMessage);
static void msgbufSetSize(int size); /* Send 'size' chars plus trailing '\0' */
static char *msgbufGetSend(int *noConsoleMessage);
static void msgbufFreeSend(void);
typedef struct listenerNode{
ELLNODE node;
errlogListener listener;
void *pPrivate;
} listenerNode;
/*each message consists of a msgNode immediately followed by the message */
typedef struct msgNode {
ELLNODE node;
char *message;
int length;
int noConsoleMessage;
} msgNode;
typedef struct {
char *base;
size_t pos;
size_t nchar;
} buffer_t;
static struct {
epicsEventId waitForWork; /*errlogThread waits for this*/
epicsMutexId msgQueueLock;
/* const after errlogInit() */
size_t maxMsgSize;
/* alloc size of both buffer_t::base */
size_t bufSize;
int errlogInitFailed;
epicsMutexId listenerLock;
epicsEventId waitForFlush; /*errlogFlush waits for this*/
epicsEventId flush; /*errlogFlush sets errlogThread does a Try*/
epicsMutexId flushLock;
epicsEventId waitForExit; /*errlogExitHandler waits for this*/
int atExit; /*TRUE when errlogExitHandler is active*/
ELLLIST listenerList;
ELLLIST msgQueue;
msgNode *pnextSend;
int errlogInitFailed;
int buffersize;
int maxMsgSize;
int msgNeeded;
/* notify when log->size!=0 */
epicsEventId waitForWork;
/* signals when worker increments flushSeq */
epicsEventId waitForSeq;
epicsMutexId msgQueueLock;
/* guarded by msgQueueLock */
int atExit;
int sevToLog;
int toConsole;
FILE *console;
int missedMessages;
char *pbuffer;
} pvtData;
/* A loop counter maintained by errlogThread. */
epicsUInt32 flushSeq;
unsigned long nFlushers;
unsigned long nLost;
/*
* vsnprintf with truncation message
/* 'log' and 'print' combine to form a double buffer. */
buffer_t *log;
buffer_t *print;
/* actual storage which 'log' and 'print' point to */
buffer_t bufs[2];
} pvt;
/* Returns an pointer to pvt.maxMsgSize bytes, or NULL if ring buffer is full.
* When !NULL, caller _must_ later msgbufCommit()
*/
static int tvsnPrint(char *str, size_t size, const char *format, va_list ap)
static
char* msgbufAlloc(void)
{
static const char tmsg[] = "<<TRUNCATED>>\n";
int nchar = epicsVsnprintf(str, size, format ? format : "", ap);
char *ret = NULL;
if (nchar >= size) {
if (size > sizeof tmsg)
strcpy(str + size - sizeof tmsg, tmsg);
nchar = size - 1;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlog called from interrupt level\n");
return ret;
}
errlogInit(0);
epicsMutexMustLock(pvt.msgQueueLock); /* matched in msgbufCommit() */
if(pvt.bufSize - pvt.log->pos - pvt.log->nchar >= 1+pvt.maxMsgSize) {
/* there is enough space for the worst cast */
ret = pvt.log->base + pvt.log->pos;
if (pvt.log->nchar) {
/* append to last message */
return ret + 1 + pvt.log->nchar;
}
/* new message */
ret[0] = ERL_STATE_WRITE;
ret++;
}
if(!ret) {
pvt.nLost++;
epicsMutexUnlock(pvt.msgQueueLock);
}
return ret;
}
static
size_t msgbufCommit(size_t nchar, int localEcho)
{
int isOkToBlock = epicsThreadIsOkToBlock();
int wasEmpty = pvt.log->pos==0;
int atExit = pvt.atExit;
char *start = pvt.log->base + pvt.log->pos + pvt.log->nchar;
/* nchar returned by snprintf() is >= maxMsgSize when truncated */
if(nchar >= pvt.maxMsgSize) {
const char *trunc = "<<TRUNCATED>>\n";
nchar = pvt.maxMsgSize - 1u;
strcpy(start + 1u + nchar - strlen(trunc), trunc);
/* assert(strlen(start+1u)==nchar); */
}
start[1u + nchar] = '\0';
if(localEcho && isOkToBlock && atExit) {
/* errlogThread is not running, so we print directly
* and then abandon the buffer.
*/
fprintf(pvt.console, "%s", start);
} else if (start[nchar] != '\n') {
/* incomplete message, prepare to append */
pvt.log->nchar += nchar;
} else {
pvt.log->base[pvt.log->pos] = ERL_STATE_READY | (localEcho ? ERL_LOCALECHO : 0);
pvt.log->pos += 1 + pvt.log->nchar + nchar + 1;
pvt.log->nchar = 0;
}
epicsMutexUnlock(pvt.msgQueueLock); /* matched in msgbufAlloc() */
if(wasEmpty && !atExit && !pvt.log->nchar)
epicsEventMustTrigger(pvt.waitForWork);
if(localEcho && isOkToBlock && !atExit)
errlogFlush();
return nchar;
}
static
void errlogSequence(void)
{
int wakeNext = 0;
size_t seq;
if (pvt.atExit)
return;
epicsMutexMustLock(pvt.msgQueueLock);
pvt.nFlushers++;
seq = pvt.flushSeq;
while(seq == pvt.flushSeq && !pvt.atExit) {
epicsMutexUnlock(pvt.msgQueueLock);
/* force worker to wake and increment seq */
epicsEventMustTrigger(pvt.waitForWork);
epicsEventMustWait(pvt.waitForSeq);
epicsMutexMustLock(pvt.msgQueueLock);
}
pvt.nFlushers--;
wakeNext = pvt.nFlushers!=0u;
epicsMutexUnlock(pvt.msgQueueLock);
if(wakeNext)
epicsEventMustTrigger(pvt.waitForSeq);
}
int errlogPrintf(const char *pFormat, ...)
{
va_list pvar;
char *pbuffer;
int nchar;
int isOkToBlock;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogPrintf called from interrupt level\n");
return 0;
}
errlogInit(0);
isOkToBlock = epicsThreadIsOkToBlock();
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
va_start(pvar, pFormat);
nchar = vfprintf(console, pFormat, pvar);
va_end (pvar);
fflush(console);
}
if (pvtData.atExit)
return nchar;
pbuffer = msgbufGetFree(isOkToBlock);
if (!pbuffer)
return 0;
va_start(pvar, pFormat);
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
va_end(pvar);
msgbufSetSize(nchar);
return nchar;
int ret;
va_list args;
va_start(args, pFormat);
ret = errlogVprintf(pFormat, args);
va_end(args);
return ret;
}
int errlogVprintf(const char *pFormat,va_list pvar)
{
int nchar;
char *pbuffer;
int isOkToBlock;
FILE *console;
int nchar = 0;
char *buf = msgbufAlloc();
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogVprintf called from interrupt level\n");
return 0;
if(buf) {
nchar = epicsVsnprintf(buf, pvt.maxMsgSize, pFormat, pvar);
nchar = msgbufCommit(nchar, pvt.toConsole);
}
errlogInit(0);
if (pvtData.atExit)
return 0;
isOkToBlock = epicsThreadIsOkToBlock();
pbuffer = msgbufGetFree(isOkToBlock);
if (!pbuffer) {
console = pvtData.console ? pvtData.console : stderr;
vfprintf(console, pFormat, pvar);
fflush(console);
return 0;
}
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "%s", pbuffer);
fflush(console);
}
msgbufSetSize(nchar);
return nchar;
}
@@ -188,14 +246,6 @@ int errlogPrintfNoConsole(const char *pFormat, ...)
{
va_list pvar;
int nchar;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogPrintfNoConsole called from interrupt level\n");
return 0;
}
errlogInit(0);
va_start(pvar, pFormat);
nchar = errlogVprintfNoConsole(pFormat, pvar);
va_end(pvar);
@@ -204,25 +254,13 @@ int errlogPrintfNoConsole(const char *pFormat, ...)
int errlogVprintfNoConsole(const char *pFormat, va_list pvar)
{
int nchar;
char *pbuffer;
int nchar = 0;
char *buf = msgbufAlloc();
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogVprintfNoConsole called from interrupt level\n");
return 0;
if(buf) {
nchar = epicsVsnprintf(buf, pvt.maxMsgSize, pFormat, pvar);
nchar = msgbufCommit(nchar, 0);
}
errlogInit(0);
if (pvtData.atExit)
return 0;
pbuffer = msgbufGetFree(1);
if (!pbuffer)
return 0;
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
msgbufSetSize(nchar);
return nchar;
}
@@ -231,29 +269,6 @@ int errlogSevPrintf(errlogSevEnum severity, const char *pFormat, ...)
{
va_list pvar;
int nchar;
int isOkToBlock;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogSevPrintf called from interrupt level\n");
return 0;
}
errlogInit(0);
if (pvtData.sevToLog > severity)
return 0;
isOkToBlock = epicsThreadIsOkToBlock();
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "sevr=%s ", errlogGetSevEnumString(severity));
va_start(pvar, pFormat);
vfprintf(console, pFormat, pvar);
va_end(pvar);
fflush(console);
}
va_start(pvar, pFormat);
nchar = errlogSevVprintf(severity, pFormat, pvar);
va_end(pvar);
@@ -262,35 +277,15 @@ int errlogSevPrintf(errlogSevEnum severity, const char *pFormat, ...)
int errlogSevVprintf(errlogSevEnum severity, const char *pFormat, va_list pvar)
{
char *pnext;
int nchar;
int totalChar = 0;
int isOkToBlock;
int nchar = 0;
char *buf = msgbufAlloc();
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
("errlogSevVprintf called from interrupt level\n");
return 0;
if(buf) {
nchar = sprintf(buf, "sevr=%s ", errlogGetSevEnumString(severity));
if(nchar < pvt.maxMsgSize)
nchar += epicsVsnprintf(buf + nchar, pvt.maxMsgSize - nchar, pFormat, pvar);
nchar = msgbufCommit(nchar, pvt.toConsole);
}
errlogInit(0);
if (pvtData.atExit)
return 0;
isOkToBlock = epicsThreadIsOkToBlock();
pnext = msgbufGetFree(isOkToBlock);
if (!pnext)
return 0;
nchar = sprintf(pnext, "sevr=%s ", errlogGetSevEnumString(severity));
pnext += nchar; totalChar += nchar;
nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pFormat, pvar);
pnext += nchar; totalChar += nchar;
if (pnext[-1] != '\n') {
strcpy(pnext,"\n");
totalChar++;
}
msgbufSetSize(totalChar);
return nchar;
}
@@ -306,13 +301,19 @@ const char * errlogGetSevEnumString(errlogSevEnum severity)
void errlogSetSevToLog(errlogSevEnum severity)
{
errlogInit(0);
pvtData.sevToLog = severity;
epicsMutexMustLock(pvt.msgQueueLock);
pvt.sevToLog = severity;
epicsMutexUnlock(pvt.msgQueueLock);
}
errlogSevEnum errlogGetSevToLog(void)
{
errlogSevEnum ret;
errlogInit(0);
return pvtData.sevToLog;
epicsMutexMustLock(pvt.msgQueueLock);
ret = pvt.sevToLog;
epicsMutexUnlock(pvt.msgQueueLock);
return ret;
}
void errlogAddListener(errlogListener listener, void *pPrivate)
@@ -320,16 +321,16 @@ void errlogAddListener(errlogListener listener, void *pPrivate)
listenerNode *plistenerNode;
errlogInit(0);
if (pvtData.atExit)
if (pvt.atExit)
return;
plistenerNode = callocMustSucceed(1,sizeof(listenerNode),
"errlogAddListener");
epicsMutexMustLock(pvtData.listenerLock);
epicsMutexMustLock(pvt.listenerLock);
plistenerNode->listener = listener;
plistenerNode->pPrivate = pPrivate;
ellAdd(&pvtData.listenerList,&plistenerNode->node);
epicsMutexUnlock(pvtData.listenerLock);
ellAdd(&pvt.listenerList,&plistenerNode->node);
epicsMutexUnlock(pvt.listenerLock);
}
int errlogRemoveListeners(errlogListener listener, void *pPrivate)
@@ -338,46 +339,42 @@ int errlogRemoveListeners(errlogListener listener, void *pPrivate)
int count = 0;
errlogInit(0);
if (!pvtData.atExit)
epicsMutexMustLock(pvtData.listenerLock);
epicsMutexMustLock(pvt.listenerLock);
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
plistenerNode = (listenerNode *)ellFirst(&pvt.listenerList);
while (plistenerNode) {
listenerNode *pnext = (listenerNode *)ellNext(&plistenerNode->node);
if (plistenerNode->listener == listener &&
plistenerNode->pPrivate == pPrivate) {
ellDelete(&pvtData.listenerList, &plistenerNode->node);
ellDelete(&pvt.listenerList, &plistenerNode->node);
free(plistenerNode);
++count;
}
plistenerNode = pnext;
}
if (!pvtData.atExit)
epicsMutexUnlock(pvtData.listenerLock);
if (count == 0) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console,
"errlogRemoveListeners: No listeners found\n");
}
epicsMutexUnlock(pvt.listenerLock);
return count;
}
int eltc(int yesno)
{
errlogInit(0);
errlogFlush();
pvtData.toConsole = yesno;
epicsMutexMustLock(pvt.msgQueueLock);
pvt.toConsole = yesno;
epicsMutexUnlock(pvt.msgQueueLock);
return 0;
}
int errlogSetConsole(FILE *stream)
{
errlogInit(0);
pvtData.console = stream;
epicsMutexMustLock(pvt.msgQueueLock);
pvt.console = stream ? stream : stderr;
epicsMutexUnlock(pvt.msgQueueLock);
/* make sure worker has stopped writing to the previous stream */
errlogSequence();
return 0;
}
@@ -385,115 +382,93 @@ void errPrintf(long status, const char *pFileName, int lineno,
const char *pformat, ...)
{
va_list pvar;
char *pnext;
int nchar;
int totalChar=0;
int isOkToBlock;
char name[256];
int nchar = 0;
char *buf = msgbufAlloc();
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage("errPrintf called from interrupt level\n");
return;
}
errlogInit(0);
isOkToBlock = epicsThreadIsOkToBlock();
if (status == 0)
status = errno;
if (status > 0) {
errSymLookup(status, name, sizeof(name));
}
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
if (pFileName)
fprintf(console, "filename=\"%s\" line number=%d\n",
pFileName, lineno);
if (status > 0)
fprintf(console, "%s ", name);
va_start(pvar, pformat);
vfprintf(console, pformat, pvar);
va_end(pvar);
fputc('\n', console);
fflush(console);
}
if (pvtData.atExit)
return;
pnext = msgbufGetFree(isOkToBlock);
if (!pnext)
return;
if (pFileName) {
nchar = sprintf(pnext,"filename=\"%s\" line number=%d\n",
pFileName, lineno);
pnext += nchar; totalChar += nchar;
}
if (status > 0) {
nchar = sprintf(pnext,"%s ",name);
pnext += nchar; totalChar += nchar;
}
va_start(pvar, pformat);
nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pformat, pvar);
va_end(pvar);
if (nchar>0) {
pnext += nchar;
totalChar += nchar;
if(buf) {
char name[256] = "";
if (status > 0) {
errSymLookup(status, name, sizeof(name));
}
nchar = epicsSnprintf(buf, pvt.maxMsgSize, "%s%sfilename=\"%s\" line number=%d",
name, status ? " " : "", pFileName, lineno);
if(nchar < pvt.maxMsgSize)
nchar += epicsVsnprintf(buf + nchar, pvt.maxMsgSize - nchar, pformat, pvar);
msgbufCommit(nchar, pvt.toConsole);
}
strcpy(pnext, "\n");
totalChar++ ; /*include the \n */
msgbufSetSize(totalChar);
va_end(pvar);
}
static void errlogExitHandler(void *pvt)
/* On *NIX. also RTEM and vxWorks during controlled shutdown.
* On Windows when main() explicitly calls epicsExit(0), like default IOC main().
* Switch to sync. print and join errlogThread.
*
* On Windows otherwise, errlogThread killed by exit(), and this handler is never
* invoked. Use of errlog from OS atexit() handler is undefined.
*/
static void errlogExitHandler(void *raw)
{
pvtData.atExit = 1;
epicsEventSignal(pvtData.waitForWork);
epicsEventMustWait(pvtData.waitForExit);
epicsThreadId tid = raw;
epicsMutexMustLock(pvt.msgQueueLock);
pvt.atExit = 1;
epicsMutexUnlock(pvt.msgQueueLock);
epicsEventSignal(pvt.waitForWork);
epicsThreadMustJoin(tid);
}
struct initArgs {
int bufsize;
int maxMsgSize;
size_t bufsize;
size_t maxMsgSize;
};
static void errlogInitPvt(void *arg)
{
struct initArgs *pconfig = (struct initArgs *) arg;
epicsThreadId tid;
epicsThreadId tid = NULL;
epicsThreadOpts topts = EPICS_THREAD_OPTS_INIT;
pvtData.errlogInitFailed = TRUE;
pvtData.buffersize = pconfig->bufsize;
pvtData.maxMsgSize = pconfig->maxMsgSize;
pvtData.msgNeeded = adjustToWorstCaseAlignment(pvtData.maxMsgSize +
sizeof(msgNode));
ellInit(&pvtData.listenerList);
ellInit(&pvtData.msgQueue);
pvtData.toConsole = TRUE;
pvtData.console = NULL;
pvtData.waitForWork = epicsEventMustCreate(epicsEventEmpty);
pvtData.listenerLock = epicsMutexMustCreate();
pvtData.msgQueueLock = epicsMutexMustCreate();
pvtData.waitForFlush = epicsEventMustCreate(epicsEventEmpty);
pvtData.flush = epicsEventMustCreate(epicsEventEmpty);
pvtData.flushLock = epicsMutexMustCreate();
pvtData.waitForExit = epicsEventMustCreate(epicsEventEmpty);
pvtData.pbuffer = callocMustSucceed(1, pvtData.buffersize,
"errlogInitPvt");
topts.priority = epicsThreadPriorityLow;
topts.stackSize = epicsThreadStackSmall;
topts.joinable = 1;
/* Use of *Must* alloc functions would recurse on failure since
* cantProceed() calls us.
*/
pvt.errlogInitFailed = TRUE;
pvt.bufSize = pconfig->bufsize;
pvt.maxMsgSize = pconfig->maxMsgSize;
ellInit(&pvt.listenerList);
pvt.toConsole = TRUE;
pvt.console = stderr;
pvt.waitForWork = epicsEventCreate(epicsEventEmpty);
pvt.listenerLock = epicsMutexCreate();
pvt.msgQueueLock = epicsMutexCreate();
pvt.waitForSeq = epicsEventCreate(epicsEventEmpty);
pvt.log = &pvt.bufs[0];
pvt.print = &pvt.bufs[1];
pvt.log->base = calloc(1, pvt.bufSize);
pvt.print->base = calloc(1, pvt.bufSize);
errSymBld(); /* Better not to do this lazily... */
tid = epicsThreadCreate("errlog", epicsThreadPriorityLow,
epicsThreadGetStackSize(epicsThreadStackSmall),
(EPICSTHREADFUNC)errlogThread, 0);
if(pvt.waitForWork
&& pvt.listenerLock
&& pvt.msgQueueLock
&& pvt.waitForSeq
&& pvt.log->base
&& pvt.print->base
) {
tid = epicsThreadCreateOpt("errlog", (EPICSTHREADFUNC)errlogThread, 0, &topts);
}
if (tid) {
pvtData.errlogInitFailed = FALSE;
pvt.errlogInitFailed = FALSE;
epicsAtExit(errlogExitHandler, tid);
}
}
@@ -503,19 +478,21 @@ int errlogInit2(int bufsize, int maxMsgSize)
static epicsThreadOnceId errlogOnceFlag = EPICS_THREAD_ONCE_INIT;
struct initArgs config;
if (pvtData.atExit)
if (pvt.atExit)
return 0;
if (bufsize < BUFFER_SIZE)
bufsize = BUFFER_SIZE;
if (bufsize < MIN_BUFFER_SIZE)
bufsize = MIN_BUFFER_SIZE;
config.bufsize = bufsize;
if (maxMsgSize < MAX_MESSAGE_SIZE)
if (maxMsgSize < MIN_MESSAGE_SIZE)
maxMsgSize = MIN_MESSAGE_SIZE;
else if (maxMsgSize > MAX_MESSAGE_SIZE)
maxMsgSize = MAX_MESSAGE_SIZE;
config.maxMsgSize = maxMsgSize;
epicsThreadOnce(&errlogOnceFlag, errlogInitPvt, &config);
if (pvtData.errlogInitFailed) {
if (pvt.errlogInitFailed) {
fprintf(stderr,"errlogInit failed\n");
exit(1);
}
@@ -524,172 +501,88 @@ int errlogInit2(int bufsize, int maxMsgSize)
int errlogInit(int bufsize)
{
return errlogInit2(bufsize, MAX_MESSAGE_SIZE);
return errlogInit2(bufsize, MIN_MESSAGE_SIZE);
}
void errlogFlush(void)
{
int count;
/* wait for both buffers to be handled to know that all currently
* logged message have been seen/sent.
*/
errlogInit(0);
if (pvtData.atExit)
return;
/*If nothing in queue dont wake up errlogThread*/
epicsMutexMustLock(pvtData.msgQueueLock);
count = ellCount(&pvtData.msgQueue);
epicsMutexUnlock(pvtData.msgQueueLock);
if (count <= 0)
return;
/*must let errlogThread empty queue*/
epicsMutexMustLock(pvtData.flushLock);
epicsEventSignal(pvtData.flush);
epicsEventSignal(pvtData.waitForWork);
epicsEventMustWait(pvtData.waitForFlush);
epicsMutexUnlock(pvtData.flushLock);
errlogSequence();
errlogSequence();
}
static void errlogThread(void)
{
listenerNode *plistenerNode;
int noConsoleMessage;
char *pmessage;
epicsMutexMustLock(pvt.msgQueueLock);
while (!pvt.atExit) {
pvt.flushSeq++;
epicsAtExit(errlogExitHandler,0);
while (TRUE) {
epicsEventMustWait(pvtData.waitForWork);
while ((pmessage = msgbufGetSend(&noConsoleMessage))) {
epicsMutexMustLock(pvtData.listenerLock);
if (pvtData.toConsole && !noConsoleMessage) {
FILE *console = pvtData.console ? pvtData.console : stderr;
if(pvt.log->pos==0u) {
int wakeFlusher = pvt.nFlushers!=0;
epicsMutexUnlock(pvt.msgQueueLock);
if(wakeFlusher)
epicsEventMustTrigger(pvt.waitForSeq);
epicsEventMustWait(pvt.waitForWork);
epicsMutexMustLock(pvt.msgQueueLock);
fprintf(console, "%s", pmessage);
} else {
/* snapshot and swap buffers for use while unlocked */
unsigned long nLost = pvt.nLost;
FILE *console = pvt.toConsole ? pvt.console : NULL;
size_t pos = 0u;
buffer_t *print;
{
buffer_t *temp = pvt.log;
pvt.log = pvt.print;
pvt.print = print = temp;
}
pvt.nLost = 0u;
epicsMutexUnlock(pvt.msgQueueLock);
while(pos < print->pos) {
listenerNode *plistenerNode;
const char* base = print->base + pos;
size_t mlen = epicsStrnLen(base+1u, pvt.bufSize - pos);
if((base[0]&ERL_STATE_MASK) != ERL_STATE_READY || mlen>=pvt.bufSize - pos) {
fprintf(stderr, "Logic Error: errlog buffer corruption. %02x, %zu\n",
(unsigned)base[0], mlen);
/* try to reset and recover */
break;
}
if(base[0]&ERL_LOCALECHO && console) {
fprintf(console, "%s", base+1u);
}
epicsMutexMustLock(pvt.listenerLock);
plistenerNode = (listenerNode *)ellFirst(&pvt.listenerList);
while (plistenerNode) {
(*plistenerNode->listener)(plistenerNode->pPrivate, base+1u);
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
}
epicsMutexUnlock(pvt.listenerLock);
pos += 1u + mlen+1u;
}
memset(print->base, 0, pvt.bufSize);
print->pos = 0u;
if(nLost && console)
fprintf(console, "errlog: lost %lu messages\n", nLost);
if(console)
fflush(console);
}
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
while (plistenerNode) {
(*plistenerNode->listener)(plistenerNode->pPrivate, pmessage);
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
}
epicsMutexMustLock(pvt.msgQueueLock);
epicsMutexUnlock(pvtData.listenerLock);
msgbufFreeSend();
}
if (pvtData.atExit)
break;
if (epicsEventTryWait(pvtData.flush) != epicsEventWaitOK)
continue;
epicsThreadSleep(.2); /*just wait an extra .2 seconds*/
epicsEventSignal(pvtData.waitForFlush);
}
epicsEventSignal(pvtData.waitForExit);
}
static msgNode * msgbufGetNode(void)
{
char *pbuffer = pvtData.pbuffer;
char *pnextFree;
msgNode *pnextSend;
if (ellCount(&pvtData.msgQueue) == 0 ) {
pnextFree = pbuffer; /* Reset if empty */
}
else {
msgNode *pfirst = (msgNode *)ellFirst(&pvtData.msgQueue);
msgNode *plast = (msgNode *)ellLast(&pvtData.msgQueue);
char *plimit = pbuffer + pvtData.buffersize;
pnextFree = plast->message + adjustToWorstCaseAlignment(plast->length);
if (pfirst > plast) {
plimit = (char *)pfirst;
}
else if (pnextFree + pvtData.msgNeeded > plimit) {
pnextFree = pbuffer; /* Hit end, wrap to start */
plimit = (char *)pfirst;
}
if (pnextFree + pvtData.msgNeeded > plimit) {
return 0; /* No room */
}
}
pnextSend = (msgNode *)pnextFree;
pnextSend->message = pnextFree + sizeof(msgNode);
pnextSend->length = 0;
return pnextSend;
}
static char * msgbufGetFree(int noConsoleMessage)
{
msgNode *pnextSend;
if (epicsMutexLock(pvtData.msgQueueLock) != epicsMutexLockOK)
return 0;
if ((ellCount(&pvtData.msgQueue) == 0) && pvtData.missedMessages) {
int nchar;
pnextSend = msgbufGetNode();
nchar = sprintf(pnextSend->message,
"errlog: %d messages were discarded\n", pvtData.missedMessages);
pnextSend->length = nchar + 1;
pvtData.missedMessages = 0;
ellAdd(&pvtData.msgQueue, &pnextSend->node);
}
pvtData.pnextSend = pnextSend = msgbufGetNode();
if (pnextSend) {
pnextSend->noConsoleMessage = noConsoleMessage;
pnextSend->length = 0;
return pnextSend->message; /* NB: msgQueueLock is still locked */
}
++pvtData.missedMessages;
epicsMutexUnlock(pvtData.msgQueueLock);
return 0;
}
static void msgbufSetSize(int size)
{
msgNode *pnextSend = pvtData.pnextSend;
pnextSend->length = size+1;
ellAdd(&pvtData.msgQueue, &pnextSend->node);
epicsMutexUnlock(pvtData.msgQueueLock);
epicsEventSignal(pvtData.waitForWork);
}
static char * msgbufGetSend(int *noConsoleMessage)
{
msgNode *pnextSend;
epicsMutexMustLock(pvtData.msgQueueLock);
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
epicsMutexUnlock(pvtData.msgQueueLock);
if (!pnextSend)
return 0;
*noConsoleMessage = pnextSend->noConsoleMessage;
return pnextSend->message;
}
static void msgbufFreeSend(void)
{
msgNode *pnextSend;
epicsMutexMustLock(pvtData.msgQueueLock);
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
if (!pnextSend) {
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "errlog: msgbufFreeSend logic error\n");
epicsThreadSuspendSelf();
}
ellDelete(&pvtData.msgQueue, &pnextSend->node);
epicsMutexUnlock(pvtData.msgQueueLock);
epicsMutexUnlock(pvt.msgQueueLock);
}

View File

@@ -185,6 +185,19 @@ static void NTPTimeSync(void *dummy)
continue;
}
if (ntpDelta > 10 * NTPTimeSyncInterval && NTPTimePvt.synchronized) {
char nowTimeText[32];
char syncTimeText[32];
epicsTimeToStrftime(syncTimeText,sizeof(syncTimeText),"%Y-%m-%d %H:%M:%S.%09f",
&NTPTimePvt.syncTime);
epicsTimeToStrftime(nowTimeText,sizeof(nowTimeText),"%Y-%m-%d %H:%M:%S.%09f",
&timeNow);
errlogPrintf("NTPTimeSync: refuse to jump from %s to future %s (timespec: %li.%09li)\n",
syncTimeText, nowTimeText, timespecNow.tv_sec, timespecNow.tv_nsec);
NTPTimePvt.synchronized = 0;
continue;
}
NTPTimePvt.syncsFailed = 0;
if (!NTPTimePvt.synchronized) {
errlogPrintf("NTPTimeSync: Sync recovered.\n");

View File

@@ -370,7 +370,8 @@ MAIN(epicsErrlogTest)
testDiag("Logged %u messages", pvt.count);
epicsEventMustWait(pvt.done);
testEqInt(pvt.count, N+1);
/* Expect N+1 messages +- 1 depending on impl */
testOk(pvt.count >= N && pvt.count<=N+2, "Logged %u messages, expected %zu", pvt.count, N+1);
/* Clean up */
testOk(1 == errlogRemoveListeners(&logClient, &pvt),