Compare commits
13 Commits
sync_with_
...
PSI-7.0.7.
| Author | SHA1 | Date | |
|---|---|---|---|
| abcada0d85 | |||
| 2c35d60a64 | |||
| af1b77eb0f | |||
| 93947eb027 | |||
| 961671259f | |||
|
|
db2482117d | ||
| a66caa5985 | |||
| 4803aae904 | |||
| 427be18e2e | |||
| fff690a449 | |||
| 428b836500 | |||
| 6c74507b11 | |||
| 122ca4e1d3 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -18,3 +18,5 @@ O.*/
|
||||
.*.swp
|
||||
.DS_Store
|
||||
.iocsh_history
|
||||
RPMS
|
||||
SRPMS
|
||||
|
||||
3
Makefile
3
Makefile
@@ -30,3 +30,6 @@ copysrc:
|
||||
|
||||
tar:
|
||||
tar cfjP epics_base-$(EPICS_VERSION_NUMBER).tar.bz2 $(INSTALL_LOCATION)
|
||||
|
||||
rpm:
|
||||
rpmbuild -bb epics-base.spec
|
||||
|
||||
18
configure/os/CONFIG.Common.RHEL9-x86_64
Normal file
18
configure/os/CONFIG.Common.RHEL9-x86_64
Normal file
@@ -0,0 +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++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)
|
||||
endif
|
||||
|
||||
ifneq (($(TOOLSET)),)
|
||||
# Perl requests (native) annobin incompatible with the annobin from any TOOLSET
|
||||
# Disable Perl specific CFLAGS
|
||||
override Cap5_CFLAGS=
|
||||
endif
|
||||
3
configure/os/CONFIG.Common.RHEL9-x86_64-clang
Normal file
3
configure/os/CONFIG.Common.RHEL9-x86_64-clang
Normal file
@@ -0,0 +1,3 @@
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-clang
|
||||
|
||||
STD_CXXFLAGS = -std=c++2a
|
||||
@@ -1,6 +1,6 @@
|
||||
include $(CONFIG)/os/CONFIG.Common.vxWorks-ppc604_long
|
||||
VXWORKS_VERSION = 5.5.1
|
||||
WIND_BASE = /afs/psi.ch/project/vxworks/Tornado2.2.1
|
||||
WIND_BASE = /opt/VxWorks/Tornado2.2.1
|
||||
|
||||
#there is a problem with our ccppc and optimization
|
||||
# -O0 works, -O and -O1 and higher are buggy
|
||||
|
||||
@@ -12,7 +12,7 @@ SDK_DIR = /opt/xgcc/gcc-8.3.0-deb10
|
||||
GNU_ARCH = x86_64-deb10-linux-gnu
|
||||
SDKTARGETSYSROOT=$(SDK_DIR)/$(GNU_ARCH)/sys-root/
|
||||
GNU_DIR = $(SDK_DIR)
|
||||
GNU_BIN = $(GNU_DIR)/bin/
|
||||
GNU_BIN = $(GNU_DIR)/bin
|
||||
GNU_TARGET_INCLUDE_DIR =
|
||||
GNU_TARGET=x86_64-deb10-linux-gnu
|
||||
|
||||
|
||||
@@ -24,17 +24,23 @@ STATIC_LDFLAGS_NO=
|
||||
STATIC_LDLIBS_YES= -Wl,-Bdynamic
|
||||
|
||||
# Set runtime path for shared libraries if LINKER_USE_RPATH=YES
|
||||
SHRLIBDIR_RPATH_LDFLAGS_YES = $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
|
||||
SHRLIBDIR_RPATH_LDFLAGS_YES = $(subst $(abspath $(LINKER_ORIGIN_ROOT)),$(FINAL_LOCATION),$(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%))
|
||||
SHRLIBDIR_RPATH_LDFLAGS_ORIGIN = $(shell $(MAKERPATH) -O '\$$ORIGIN' -F $(FINAL_DIR) -R $(LINKER_ORIGIN_ROOT) $(SHRLIB_DEPLIB_DIRS))
|
||||
SHRLIBDIR_LDFLAGS += \
|
||||
$(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
|
||||
|
||||
# Set runtime path for products if LINKER_USE_RPATH=YES
|
||||
PRODDIR_RPATH_LDFLAGS_YES = $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
|
||||
PRODDIR_RPATH_LDFLAGS_YES = $(subst $(abspath $(LINKER_ORIGIN_ROOT)),$(FINAL_LOCATION),$(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%))
|
||||
PRODDIR_RPATH_LDFLAGS_ORIGIN = $(shell $(MAKERPATH) -O '\$$ORIGIN' -F $(FINAL_DIR) -R $(LINKER_ORIGIN_ROOT) $(PROD_DEPLIB_DIRS))
|
||||
PRODDIR_LDFLAGS += \
|
||||
$(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
|
||||
|
||||
ifneq ($(LINKER_USE_RPATH:NO=),)
|
||||
ifeq ($(T_A),$(EPICS_HOST_ARCH))
|
||||
LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH:%=%:)$(INSTALL_LIB)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Link libraries controlled by COMMANDLINE_LIBRARY
|
||||
# The newest Linux versions only need readline, older ones need both
|
||||
# readline and ncurses, and the oldest need readline and curses
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Include definitions common to all Linux ARM targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-arm
|
||||
|
||||
GNU_DIR=/afs/psi.ch/project/embeddedlinux/moxa/arm-linux-4.4.2-v4
|
||||
GNU_DIR=/opt/moxa/arm-linux-4.4.2-v4
|
||||
GNU_TARGET=arm
|
||||
ARCH_DEP_LDFLAGS+=-Wl,-rpath-link,$(GNU_DIR)/arm-none-linux-gnueabi/lib
|
||||
ARCH_DEP_LDFLAGS+=-Wl,-rpath-link,$(INSTALL_LIB)
|
||||
|
||||
@@ -7,7 +7,7 @@ COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
ARCH_CLASS = xscale
|
||||
|
||||
GNU_DIR=/afs/psi.ch/project/embeddedlinux/moxa/xscale_be/armv5teb-montavista-linuxeabi
|
||||
GNU_DIR=/opt/moxa/xscale_be/armv5teb-montavista-linuxeabi
|
||||
|
||||
ARCH_DEP_CFLAGS += -funwind-tables
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# National Instruments CompactRIO running LabView RT 19.5.1
|
||||
# requires RPM gcc-c++-arm-linux-gnu
|
||||
|
||||
# Include definitions common to all Linux targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
@@ -8,10 +9,11 @@ ARCH_CLASS = arm
|
||||
GNU_TARGET = arm-linux-gnu
|
||||
|
||||
SYSROOT = /opt/LabVIEW-RT-19.5.1/arm/sysroots/armv7a-vfp-neon-nilrt-linux-gnueabi
|
||||
GNU_BIN = /bin
|
||||
GNU_BIN = /opt/RHEL7/bin
|
||||
LD_LIBRARY_PATH=/usr/$$LIB:/opt/RHEL7/$$LIB
|
||||
|
||||
ARCH_DEP_CPPFLAGS += -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon
|
||||
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/
|
||||
ARCH_DEP_CXXFLAGS += -I=/usr/include/c++/4.7.2/arm-nilrt-linux-gnueabi
|
||||
ARCH_DEP_CXXFLAGS += -I=/usr/include/c++/4.7.2
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE_NCURSES
|
||||
|
||||
@@ -10,13 +10,13 @@ include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
# Due to missing/messed up libs in the toolchain, readline needs copies of
|
||||
# libtinfo.so.5.9 and libreadline.so.6.2 from a Raspbian 7 rootfs
|
||||
# /lib/arm-linux-gnueabihf/ to the toolchain, e.g.
|
||||
# $(SDK_DIR)/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/libc/lib/arm-linux-gnueabihf/
|
||||
# $(SDK_DIR)/$(SDK_TARGET)/arm-linux-gnueabihf/libc/lib/arm-linux-gnueabihf/
|
||||
# and manually created links libtinfo.so.5 and libreadline.so.
|
||||
# For gcc-linaro-arm-linux-gnueabihf-raspbian, an existing incompatible
|
||||
# libtinfo.so.5 is in the way. Remove it.
|
||||
# (Built with glibc 2.16 like installed on Raspbian 9 but toolchain uses glibc 2.13.)
|
||||
# Also copy /usr/include/readline/ directory from some readline 6 installation
|
||||
# to $(SDK_DIR)/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/libc/usr/include/
|
||||
# to $(SDK_DIR)/$(SDK_TARGET)/arm-linux-gnueabihf/libc/usr/include/
|
||||
|
||||
ARCH_CLASS = arm
|
||||
|
||||
@@ -25,10 +25,10 @@ SDK_DIR = /opt/raspberrypi/arm-bcm2708
|
||||
# Available SDK_TARGETs:
|
||||
|
||||
# gcc 4.8.3 for 32 bit hosts with GLIBC 2.3 or higher
|
||||
SDK_TARGET = gcc-linaro-arm-linux-gnueabihf-raspbian
|
||||
# SDK_TARGET = gcc-linaro-arm-linux-gnueabihf-raspbian
|
||||
|
||||
# gcc 4.8.3 for 64 bit hosts with GLIBC 2.14 or higher
|
||||
# SDK_TARGET = gcc-linaro-arm-linux-gnueabihf-raspbian-x64
|
||||
SDK_TARGET = gcc-linaro-arm-linux-gnueabihf-raspbian-x64
|
||||
|
||||
# gcc 4.7.1 for 64 bit hosts with GLIBC 2.8 or higher
|
||||
# SDK_TARGET = arm-linux-gnueabihf
|
||||
|
||||
@@ -2,5 +2,9 @@ include $(CONFIG)/os/CONFIG.windows-x64.windows-x64
|
||||
|
||||
VALID_BUILDS = Ioc Command
|
||||
|
||||
PATH := /opt/wine-msvc-2017/bin/x64:$(PATH)
|
||||
MSVC_VERSION ?= 2019
|
||||
PATH := /opt/gfa-wine/bin:/opt/wine-msvc-$(MSVC_VERSION)/bin/x64:$(PATH)
|
||||
export WINEPREFIX = $(HOME)/.wine-$(EPICS_HOST_ARCH)
|
||||
export WINEDEBUG=fixme-all
|
||||
export WINEDLLOVERRIDES="mscoree,mshtml="
|
||||
export WINE = wine64
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
# MSVC_VERSION 2019 in wine 4 for on RHEL7 would require winetricks
|
||||
MSVC_VERSION = 2017
|
||||
include $(CONFIG)/os/CONFIG.Linux.windows-x64
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
GNU_BIN = /opt/RHEL7/bin
|
||||
3
configure/os/CONFIG.RHEL9-x86_64.Common
Normal file
3
configure/os/CONFIG.RHEL9-x86_64.Common
Normal file
@@ -0,0 +1,3 @@
|
||||
#CONFIG.$(EPICS_HOST_ARCH).Common is required by build system
|
||||
#Include definitions common to linux hosts
|
||||
include $(CONFIG)/os/CONFIG.linux-x86_64.Common
|
||||
18
configure/os/CONFIG.RHEL9-x86_64.RHEL7-x86_64
Normal file
18
configure/os/CONFIG.RHEL9-x86_64.RHEL7-x86_64
Normal file
@@ -0,0 +1,18 @@
|
||||
# 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
|
||||
|
||||
# "Cross" TOOLSET progs need to find their libraries
|
||||
LD_LIBRARY_PATH = $(TOOLSET_DIR:%=$(SYSROOT)%/usr/$$LIB:)/usr/$$LIB:$(SYSROOT)/usr/$$LIB
|
||||
|
||||
# The linker has problems to find indirectly referenced libraries
|
||||
PROD_LDLIBS += $(LDLIBS)
|
||||
23
configure/os/CONFIG.RHEL9-x86_64.RHEL8-x86_64
Normal file
23
configure/os/CONFIG.RHEL9-x86_64.RHEL8-x86_64
Normal file
@@ -0,0 +1,23 @@
|
||||
# Include common linux definitions
|
||||
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86
|
||||
|
||||
# "Cross compile" for RHEL8-x86_64
|
||||
# Expects RHEL8 RPMs gcc-toolset-12-gcc-c++ and readline-devel
|
||||
# to be installed in $(SYSROOT)
|
||||
# These can be installed on RHEL8 with:
|
||||
# yum install --installroot=$(SYSROOT) <packages>
|
||||
# (Assuming $(SYSROOT) is on a shared network volume.)
|
||||
|
||||
SYSROOT = /opt/RHEL8
|
||||
|
||||
# "Cross" TOOLSET progs need to find their libraries.
|
||||
# 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)
|
||||
TARGET_PROD_LDFLAGS += $(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
|
||||
2
configure/os/CONFIG.RHEL9-x86_64.RHEL9-x86_64
Normal file
2
configure/os/CONFIG.RHEL9-x86_64.RHEL9-x86_64
Normal file
@@ -0,0 +1,2 @@
|
||||
# Include common linux definitions
|
||||
include $(CONFIG)/os/CONFIG.linux-x86.linux-x86
|
||||
1
configure/os/CONFIG.RHEL9-x86_64.windows-x64
Normal file
1
configure/os/CONFIG.RHEL9-x86_64.windows-x64
Normal file
@@ -0,0 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.Linux.windows-x64
|
||||
@@ -16,7 +16,7 @@ OPT_WHOLE_PROGRAM = YES
|
||||
|
||||
WINLINK = link
|
||||
|
||||
RCCMD = rc -l 0x409 $(INCLUDES) -fo $@ $<
|
||||
RCCMD = rc -nologo -l 0x409 $(INCLUDES) -fo $@ $<
|
||||
|
||||
ARCMD = lib -nologo -verbose -out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
@@ -87,7 +87,7 @@ CODE_CXXFLAGS =
|
||||
#WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
|
||||
#WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
|
||||
#WIND_BASE = /ade/vxWorks/$(VXWORKS_VERSION)
|
||||
WIND_BASE = /afs/psi.ch/project/vxworks/VxWorks$(VXWORKS_VERSION)
|
||||
WIND_BASE = /opt/VxWorks/VxWorks$(VXWORKS_VERSION)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Modules we cannot build with old compiler
|
||||
|
||||
@@ -3,8 +3,3 @@ include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common
|
||||
# Improved error checking with clang
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64-clang
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += RHEL7-x86_64-clang
|
||||
|
||||
# NI Linux Real-Time 7.x
|
||||
# requires RPM gcc-c++-arm-linux-gnu
|
||||
# Not available on RHEL8
|
||||
CROSS_COMPILER_TARGET_ARCHS += nilrt7-armv7a
|
||||
|
||||
@@ -5,7 +5,3 @@ CROSS_COMPILER_TARGET_ARCHS += RHEL8-x86_64-clang
|
||||
|
||||
# Build for old RHEL7 64 bit
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64
|
||||
|
||||
# NI Linux Real-Time 7.x
|
||||
# requires RPM gcc-c++-arm-linux-gnu
|
||||
CROSS_COMPILER_TARGET_ARCHS += nilrt7-armv7a
|
||||
|
||||
10
configure/os/CONFIG_SITE.RHEL9-x86_64.Common
Normal file
10
configure/os/CONFIG_SITE.RHEL9-x86_64.Common
Normal file
@@ -0,0 +1,10 @@
|
||||
include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common
|
||||
|
||||
# Improved error checking with clang
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL9-x86_64-clang
|
||||
|
||||
# Build for old RHEL8 64 bit
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL8-x86_64
|
||||
|
||||
# Build for old RHEL7 64 bit
|
||||
CROSS_COMPILER_TARGET_ARCHS += RHEL7-x86_64
|
||||
@@ -38,7 +38,7 @@ CROSS_COMPILER_TARGET_ARCHS += eldk52-e500v2
|
||||
|
||||
# DeltaTau PowerPMAC
|
||||
CROSS_COMPILER_TARGET_ARCHS += eldk42-ppc4xxFP
|
||||
#CROSS_COMPILER_TARGET_ARCHS += eldk53-ppc4xxFP
|
||||
CROSS_COMPILER_TARGET_ARCHS += eldk53-ppc4xxFP
|
||||
|
||||
# Test other vxWorks versions
|
||||
#CROSS_COMPILER_TARGET_ARCHS += V66-ppc603
|
||||
@@ -48,9 +48,6 @@ CROSS_COMPILER_TARGET_ARCHS += eldk42-ppc4xxFP
|
||||
# (No PVA because of old compiler)
|
||||
#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
|
||||
|
||||
@@ -25,4 +25,10 @@ CROSS_COMPILER_TARGET_ARCHS += yocto40-aarch64
|
||||
CROSS_COMPILER_TARGET_ARCHS += deb10-x86_64
|
||||
|
||||
# Newer DeltaTau PowerPMAC
|
||||
#CROSS_COMPILER_TARGET_ARCHS += gcc8-ppc4xxFP
|
||||
CROSS_COMPILER_TARGET_ARCHS += gcc8-ppc4xxFP
|
||||
|
||||
# Raspberry Pi
|
||||
CROSS_COMPILER_TARGET_ARCHS += raspbian-arm
|
||||
|
||||
# NI Linux Real-Time 7.x
|
||||
CROSS_COMPILER_TARGET_ARCHS += nilrt7-armv7a
|
||||
|
||||
@@ -22,6 +22,12 @@ should also be read to understand what has changed since earlier releases:
|
||||
|
||||
## Changes made on the 7.0 branch since 7.0.7
|
||||
|
||||
### PROC field changed to ASL0
|
||||
|
||||
The PROC field has been changed from access security level ASL1 to ASL0.
|
||||
This allows users to trigger processing a record without having the rights
|
||||
to reconfigure the records.
|
||||
|
||||
### bi "Raw Soft Channel" use MASK
|
||||
|
||||
If MASK is non-zero, The raw device support will now apply MASK to the
|
||||
|
||||
8
epics-base.sh
Normal file
8
epics-base.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
_OLD_EXTGLOB=$(shopt -p extglob)
|
||||
shopt -s extglob
|
||||
test -n "$EPICS_BASE" || export EPICS_BASE=$(ls -dvr1 /usr/local/epics/base-+([0-9]).+([0-9]).+([0-9])/ | head -n1)
|
||||
test -n "$EPICS_HOST_ARCH" || export EPICS_HOST_ARCH=$(/bin/sed "s%cpe:/o:redhat:enterprise_linux:\([0-9]*\).*%RHEL\1-`/bin/uname -m`%" /etc/system-release-cpe)
|
||||
PATH=${PATH//\/usr\/local\/epics\/base-+([0-9]).+([0-9]).+([0-9])\/bin\/$EPICS_HOST_ARCH}:$(echo $(ls -dvr /usr/local/epics/base-+([0-9]).+([0-9]).+([0-9])/bin/$EPICS_HOST_ARCH) | tr ' ' :)
|
||||
eval $_OLD_EXTGLOB
|
||||
unset _OLD_EXTGLOB
|
||||
|
||||
382
epics-base.spec
Normal file
382
epics-base.spec
Normal file
@@ -0,0 +1,382 @@
|
||||
# Always make sure EpicsVersion.Version-Release matches the git tag!
|
||||
|
||||
%define EpicsVersion 7.0.7
|
||||
|
||||
Name: epics-base-%{EpicsVersion}
|
||||
Summary: EPICS Base %{EpicsVersion}
|
||||
Version: 1
|
||||
Release: 3%{?dist}
|
||||
License: EPICS Open License
|
||||
Group: Development/Languages
|
||||
URL: https://git.psi.ch/epics_base/base-7.0
|
||||
|
||||
%define module_name %{name}
|
||||
%define prog_folder /usr/local/epics/base-%{EpicsVersion}
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
# do not strip libraries
|
||||
%global __strip /bin/true
|
||||
%undefine __brp_strip
|
||||
|
||||
%undefine __brp_mangle_shebangs
|
||||
%undefine __brp_ldconfig
|
||||
%define _binaries_in_noarch_packages_terminate_build 0
|
||||
|
||||
%if %{defined rhel}
|
||||
%global epics_host_arch RHEL%{rhel}-%{_host_cpu}
|
||||
%endif
|
||||
|
||||
%description
|
||||
EPICS is a set of Open Source software tools, libraries and applications
|
||||
developed collaboratively and used worldwide to create distributed soft
|
||||
real-time control systems for scientific instruments such as a particle
|
||||
accelerators, telescopes and other large scientific experiments.
|
||||
This RPM is a binary-only package.
|
||||
|
||||
###########################################
|
||||
|
||||
%package host-devel
|
||||
Requires: make >= 3.80
|
||||
BuildRequires: make >= 3.80
|
||||
|
||||
Summary: Minimal stuff needed to build EPICS host apps
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
# This EPICS installation uses the toolset 12 compiler
|
||||
%if 0%{?rhel} == 7
|
||||
Requires: devtoolset-12-gcc-c++
|
||||
BuildRequires: devtoolset-12-gcc-c++
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} >= 8
|
||||
Requires: gcc-toolset-12-gcc-c++
|
||||
BuildRequires: gcc-toolset-12-gcc-c++
|
||||
%endif
|
||||
|
||||
# The perl stuff we need
|
||||
Requires: perl-interpreter >= 5.10.1
|
||||
BuildRequires: perl-interpreter >= 5.10.1
|
||||
|
||||
%if 0%{?rhel} >= 7
|
||||
Requires: perl-File-Path perl-Getopt-Long perl-Pod-Usage perl-Time-HiRes perl-Data-Dumper perl-Scalar-List-Utils
|
||||
BuildRequires: perl-File-Path perl-Getopt-Long perl-Pod-Usage perl-Time-HiRes perl-Data-Dumper perl-Scalar-List-Utils
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} >= 8
|
||||
Requires: perl-Text-Tabs+Wrap
|
||||
BuildRequires: perl-Text-Tabs+Wrap
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} >= 9
|
||||
Requires: perl-File-Find perl-File-Basename perl-File-Copy perl-FindBin perl-Getopt-Std perl-POSIX
|
||||
BuildRequires: perl-File-Find perl-File-Basename perl-File-Copy perl-FindBin perl-Getopt-Std perl-POSIX
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} == 7
|
||||
# Perl auto-detection is broken
|
||||
# It does not find all EPICS internal packages
|
||||
%global __requires_exclude_from ^%{prog_folder}/bin/.*\\.pl$
|
||||
%endif
|
||||
|
||||
%description host-devel
|
||||
Contains headers etc to build EPICS host applications.
|
||||
|
||||
###########################################
|
||||
|
||||
%package compat
|
||||
Summary: EPICS base %{EpicsVersion} for other RHEL versions
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
AutoReqProv: no
|
||||
|
||||
%description compat
|
||||
Contains EPICS binaries that run on other RHEL versions.
|
||||
|
||||
###########################################
|
||||
|
||||
%package wine
|
||||
Summary: EPICS base %{EpicsVersion} for wine
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: wine
|
||||
BuildRequires: wine
|
||||
|
||||
%description wine
|
||||
Allows to run EPICS in wine.
|
||||
|
||||
###########################################
|
||||
|
||||
%package boot
|
||||
Summary: EPICS base %{EpicsVersion} for boot servers
|
||||
BuildArch: noarch
|
||||
AutoReqProv: no
|
||||
Prefix: /usr/local/epics
|
||||
|
||||
%description boot
|
||||
Contains files needed on NFS server to boot EPICS targets from.
|
||||
This package can be relocated.
|
||||
|
||||
###########################################
|
||||
|
||||
%package devel
|
||||
Summary: EPICS base %{EpicsVersion} for development environments
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: %{name}-host-devel = %{version}-%{release}
|
||||
Requires: %{name}-boot = %{version}-%{release}
|
||||
Requires: gfa-cross-compiler-links
|
||||
BuildArch: noarch
|
||||
AutoReqProv: no
|
||||
|
||||
%description devel
|
||||
All what is needed to develop EPICS for different target architectures.
|
||||
|
||||
###########################################
|
||||
|
||||
%package devel-static
|
||||
Summary: EPICS base %{EpicsVersion} for development environments including static libraries
|
||||
Requires: %{name}-devel = %{version}-%{release}
|
||||
BuildArch: noarch
|
||||
AutoReqProv: no
|
||||
|
||||
%description devel-static
|
||||
Contains the static libraries (*.a) for EPICS development systems.
|
||||
Only needed to build statically linked applications.
|
||||
|
||||
###########################################
|
||||
|
||||
%package src
|
||||
Summary: Sources code of EPICS base %{EpicsVersion}
|
||||
BuildArch: noarch
|
||||
AutoReqProv: no
|
||||
Prefix: /usr/local/epics
|
||||
|
||||
%description src
|
||||
The source code of EPICS base %{EpicsVersion}.
|
||||
May help when debugging
|
||||
|
||||
###########################################
|
||||
|
||||
%package doc
|
||||
Summary: EPICS base %{EpicsVersion} documentation
|
||||
BuildArch: noarch
|
||||
AutoReqProv: no
|
||||
Prefix: /usr/local/epics
|
||||
|
||||
%description doc
|
||||
The documentation of EPICS base %{EpicsVersion}.
|
||||
|
||||
###########################################
|
||||
|
||||
# Our sources are locally in this directory
|
||||
# and here we also build
|
||||
# RPMS and SRPMS will be stored here, too
|
||||
%define _topdir %(pwd)
|
||||
%define _sourcedir %{_topdir}
|
||||
%define _builddir %{_topdir}
|
||||
|
||||
%prep
|
||||
%{__rm} -rf %{buildroot}/usr/lib
|
||||
%{__rm} -f modules/RELEASE.*.local
|
||||
git submodule update --init modules
|
||||
|
||||
%build
|
||||
%if %{defined epics_host_arch}
|
||||
export EPICS_HOST_ARCH=%{epics_host_arch}
|
||||
%endif
|
||||
%{__make} -j $RPM_BUILD_NCPUS INSTALL_LOCATION=%{buildroot}/%{prog_folder} FINAL_LOCATION=%{prog_folder}
|
||||
%{__make} INSTALL_LOCATION=%{buildroot}/%{prog_folder} copysrc
|
||||
|
||||
# remove files we do not need
|
||||
shopt -s extglob
|
||||
%{__rm} -f %{buildroot}/%{prog_folder}/bin/{V,RTEMS}*/{*Harness,softIoc,softIocPVA}
|
||||
%{__rm} -f %{buildroot}/%{prog_folder}/bin/RTEMS*/TEMP.*
|
||||
|
||||
# install the profile script
|
||||
%{__install} epics-base.sh %{buildroot}/%{prog_folder}/bin
|
||||
|
||||
# Do not use install section because build already installed
|
||||
# and install will delete our buildroot!
|
||||
|
||||
%clean
|
||||
%{__make} realclean
|
||||
%{__rm} -f modules/RELEASE.*.local
|
||||
|
||||
# Link caRepeater and profile script to highest installed EPICS version after install and uninstall
|
||||
%post
|
||||
shopt -s extglob
|
||||
|
||||
if [ -e /etc/profile.d/epics-base.sh ]
|
||||
then
|
||||
%{__rm} -f /etc/profile.d/epics-base.sh
|
||||
fi
|
||||
%{__ln_s} "$(/usr/bin/ls -dvr1 /usr/local/epics/base-+([0-9]).+([0-9]).+([0-9])/bin/epics-base.sh | /usr/bin/head -n1)" /etc/profile.d/
|
||||
|
||||
SYSTEMD_DIR=$(pkg-config systemd --variable=systemdsystemunitdir)
|
||||
if [ -n "$SYSTEMD_DIR" ]
|
||||
then
|
||||
systemctl is-enabled caRepeater.service 2>/dev/null && systemctl disable --now caRepeater.service
|
||||
test -e $SYSTEMD_DIR/caRepeater.service && %{__rm} $SYSTEMD_DIR/caRepeater.service
|
||||
%{__ln_s} "$(/usr/bin/ls -dvr1 /usr/local/epics/base-+([0-9]).+([0-9]).+([0-9])/bin/%{epics_host_arch}/caRepeater.service | /usr/bin/head -n1)" $SYSTEMD_DIR/
|
||||
systemctl daemon-reload
|
||||
killall caRepeater 2>/dev/null
|
||||
systemctl enable --now caRepeater.service
|
||||
fi
|
||||
|
||||
%postun
|
||||
shopt -s extglob
|
||||
|
||||
if [ -e /etc/profile.d/epics-base.sh ]
|
||||
then
|
||||
%{__rm} -f /etc/profile.d/epics-base.sh
|
||||
fi
|
||||
%{__ln_s} "$(/usr/bin/ls -dvr1 /usr/local/epics/base-+([0-9]).+([0-9]).+([0-9])/bin/epics-base.sh 2>/dev/null | /usr/bin/head -n1)" /etc/profile.d/ 2>/dev/null
|
||||
|
||||
SYSTEMD_DIR=$(pkg-config systemd --variable=systemdsystemunitdir)
|
||||
if [ -n "$SYSTEMD_DIR" ]
|
||||
then
|
||||
systemctl disable --now caRepeater.service
|
||||
%{__rm} -f $SYSTEMD_DIR/caRepeater.service
|
||||
%{__ln_s} "$(/usr/bin/ls -dvr1 /usr/local/epics/base-+([0-9]).+([0-9]).+([0-9])/bin/%{epics_host_arch}/caRepeater.service 2>/dev/null | /usr/bin/head -n1)" $SYSTEMD_DIR/ 2>/dev/null
|
||||
systemctl daemon-reload
|
||||
if [ -e $SYSTEMD_DIR/caRepeater.service ]
|
||||
then
|
||||
killall caRepeater 2>/dev/null
|
||||
systemctl enable --now caRepeater.service
|
||||
fi
|
||||
fi
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{prog_folder}
|
||||
%dir %{prog_folder}/configure
|
||||
%{prog_folder}/configure/CONFIG_BASE_VERSION
|
||||
|
||||
%dir %{prog_folder}/dbd
|
||||
%{prog_folder}/dbd/softIoc*.dbd
|
||||
|
||||
%dir %{prog_folder}/bin
|
||||
%dir %{prog_folder}/lib
|
||||
%{prog_folder}/db
|
||||
|
||||
%{prog_folder}/bin/epics-base.sh
|
||||
|
||||
# Install host binaries but avoid installing *.pl scripts
|
||||
# and other development tools
|
||||
|
||||
%if %{defined rhel}
|
||||
%dir %{prog_folder}/bin/RHEL%{rhel}*
|
||||
%{prog_folder}/bin/RHEL%{rhel}*/[Scips]*[^.]??
|
||||
%{prog_folder}/bin/RHEL%{rhel}*/p2p
|
||||
%{prog_folder}/bin/RHEL%{rhel}*/msi
|
||||
%dir %{prog_folder}/lib/RHEL%{rhel}*
|
||||
%{prog_folder}/lib/RHEL%{rhel}*/*.so*
|
||||
%endif
|
||||
|
||||
###########################################
|
||||
|
||||
%files compat
|
||||
%if %{?rhel} > 7
|
||||
%{prog_folder}/bin/RHEL7*
|
||||
%dir %{prog_folder}/lib/RHEL7*
|
||||
%{prog_folder}/lib/RHEL7*/*.so*
|
||||
%endif
|
||||
|
||||
%if %{?rhel} > 8
|
||||
%{prog_folder}/bin/RHEL8*
|
||||
%dir %{prog_folder}/lib/RHEL8*
|
||||
%{prog_folder}/lib/RHEL8*/*.so*
|
||||
%endif
|
||||
|
||||
%if %{?rhel} > 9
|
||||
%{prog_folder}/bin/RHEL9*
|
||||
%dir %{prog_folder}/lib/RHEL9*
|
||||
%{prog_folder}/lib/RHEL9*/*.so*
|
||||
%endif
|
||||
|
||||
###########################################
|
||||
|
||||
%files wine
|
||||
%{prog_folder}/bin/win*
|
||||
|
||||
###########################################
|
||||
|
||||
%files boot
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{prog_folder}/configure
|
||||
%{prog_folder}/configure/CONFIG_BASE_VERSION
|
||||
|
||||
%dir %{prog_folder}/dbd
|
||||
%{prog_folder}/dbd/softIoc*.dbd
|
||||
%{prog_folder}/db
|
||||
|
||||
%dir %{prog_folder}/lib
|
||||
# avoid pulling in pkgconfig and perl
|
||||
%dir %{prog_folder}/lib/[a-z]*-*
|
||||
%{prog_folder}/lib/[a-z]*-*/*.so*
|
||||
|
||||
%dir %{prog_folder}/bin
|
||||
# avoid pulling in host files again
|
||||
# but get all cross architectures (mostly lower case)
|
||||
# including all Windows dlls (hence listed twice: here and in wine)
|
||||
%dir %{prog_folder}/bin/[a-z]*
|
||||
%{prog_folder}/bin/[a-z]*/[Scips]*[^.]??
|
||||
%{prog_folder}/bin/[a-z]*/msi*
|
||||
%{prog_folder}/bin/[a-z]*/*.dll
|
||||
|
||||
# vxWorks and RTEMS
|
||||
%dir %{prog_folder}/bin/V*
|
||||
%{prog_folder}/bin/V*/*.munch
|
||||
%{prog_folder}/bin/V*/*.o
|
||||
%dir %{prog_folder}/bin/RTEMS*
|
||||
%{prog_folder}/bin/RTEMS*/*.boot
|
||||
|
||||
###########################################
|
||||
|
||||
%files host-devel
|
||||
%defattr(-,root,root,-)
|
||||
%{prog_folder}/configure
|
||||
%{prog_folder}/cfg
|
||||
%{prog_folder}/include
|
||||
%{prog_folder}/templates
|
||||
%if %{defined rhel}
|
||||
%{prog_folder}/bin/RHEL%{rhel}*/[^Scips]*[^.]??
|
||||
%{prog_folder}/bin/RHEL%{rhel}*/*.??
|
||||
%endif
|
||||
%{prog_folder}/lib/pkgconfig
|
||||
%{prog_folder}/lib/perl
|
||||
%{prog_folder}/lib/win*
|
||||
%{prog_folder}/lib/RTEMS*
|
||||
%{prog_folder}/dbd
|
||||
|
||||
###########################################
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
|
||||
%{prog_folder}/bin/[a-z]*/[^Scips]*[^.]??
|
||||
|
||||
# VxWorks and RTEMS need static libs
|
||||
%{prog_folder}/lib/V*
|
||||
|
||||
###########################################
|
||||
|
||||
%files devel-static
|
||||
%defattr(-,root,root,-)
|
||||
|
||||
# Install bulky static libs for Linux targets only on request
|
||||
%{prog_folder}/lib/RHEL*/*.a
|
||||
%{prog_folder}/lib/[a-z]*/*.a
|
||||
|
||||
###########################################
|
||||
|
||||
%files src
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{prog_folder}
|
||||
%{prog_folder}/modules
|
||||
|
||||
###########################################
|
||||
|
||||
%files doc
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{prog_folder}
|
||||
%docdir %{prog_folder}/html
|
||||
%{prog_folder}/html
|
||||
@@ -240,6 +240,7 @@ The B<SPVT> field is for internal use by the scanning system.
|
||||
}
|
||||
field(PROC,DBF_UCHAR) {
|
||||
prompt("Force Processing")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
interest(3)
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#include "cantProceed.h"
|
||||
#include "epicsExit.h"
|
||||
|
||||
void epicsMutexCleanup(void);
|
||||
|
||||
typedef struct exitNode {
|
||||
ELLNODE node;
|
||||
epicsExitFunc func;
|
||||
@@ -115,8 +113,6 @@ LIBCOM_API void epicsExitCallAtExits(void)
|
||||
epicsExitCallAtExitsPvt ( pep );
|
||||
destroyExitPvt ( pep );
|
||||
}
|
||||
/* Handle specially to avoid circular reference */
|
||||
epicsMutexCleanup();
|
||||
}
|
||||
|
||||
LIBCOM_API void epicsExitCallAtThreadExits(void)
|
||||
|
||||
@@ -26,30 +26,23 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsThread.h"
|
||||
#include "valgrind/valgrind.h"
|
||||
#include "ellLib.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
|
||||
static epicsThreadOnceId epicsMutexOsiOnce = EPICS_THREAD_ONCE_INIT;
|
||||
static ELLLIST mutexList;
|
||||
static ELLLIST freeList;
|
||||
|
||||
struct epicsMutexParm {
|
||||
ELLNODE node;
|
||||
epicsMutexOSD * id;
|
||||
# ifdef LOG_LAST_OWNER
|
||||
epicsThreadId lastOwner;
|
||||
# endif
|
||||
const char *pFileName;
|
||||
int lineno;
|
||||
};
|
||||
|
||||
static epicsMutexOSD * epicsMutexGlobalLock;
|
||||
static ELLLIST mutexList = ELLLIST_INIT;
|
||||
|
||||
/* Specially initialized to bootstrap initialization.
|
||||
* When supported (posix and !rtems) use statically initiallized mutex.
|
||||
* Otherwise, initialize via epicsMutexOsdSetup().
|
||||
*/
|
||||
struct epicsMutexParm epicsMutexGlobalLock = {ELLNODE_INIT, __FILE__, __LINE__};
|
||||
|
||||
// vxWorks 5.4 gcc fails during compile when I use std::exception
|
||||
using namespace std;
|
||||
@@ -76,176 +69,82 @@ const char * epicsMutex::invalidMutex::what () const throw ()
|
||||
return "epicsMutex::invalidMutex()";
|
||||
}
|
||||
|
||||
static void epicsMutexOsiInit(void *) {
|
||||
ellInit(&mutexList);
|
||||
ellInit(&freeList);
|
||||
VALGRIND_CREATE_MEMPOOL(&freeList, 0, 0);
|
||||
epicsMutexGlobalLock = epicsMutexOsdCreate();
|
||||
}
|
||||
|
||||
epicsMutexId epicsStdCall epicsMutexOsiCreate(
|
||||
const char *pFileName,int lineno)
|
||||
{
|
||||
epicsMutexOSD * id;
|
||||
epicsMutexOsdSetup();
|
||||
|
||||
epicsThreadOnce(&epicsMutexOsiOnce, epicsMutexOsiInit, NULL);
|
||||
epicsMutexId ret = (epicsMutexId)calloc(1, sizeof(*ret));
|
||||
if(ret) {
|
||||
ret->pFileName = pFileName;
|
||||
ret->lineno = lineno;
|
||||
|
||||
if(!epicsMutexOsdPrepare(ret)) {
|
||||
epicsMutexMustLock(&epicsMutexGlobalLock);
|
||||
ellAdd(&mutexList, &ret->node);
|
||||
(void)epicsMutexUnlock(&epicsMutexGlobalLock);
|
||||
|
||||
} else {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
id = epicsMutexOsdCreate();
|
||||
if(!id) {
|
||||
return 0;
|
||||
}
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
epicsMutexParm *pmutexNode =
|
||||
reinterpret_cast < epicsMutexParm * > ( ellFirst(&freeList) );
|
||||
if(pmutexNode) {
|
||||
ellDelete(&freeList,&pmutexNode->node);
|
||||
VALGRIND_MEMPOOL_FREE(&freeList, pmutexNode);
|
||||
} else {
|
||||
pmutexNode = static_cast < epicsMutexParm * > ( calloc(1,sizeof(epicsMutexParm)) );
|
||||
}
|
||||
VALGRIND_MEMPOOL_ALLOC(&freeList, pmutexNode, sizeof(epicsMutexParm));
|
||||
pmutexNode->id = id;
|
||||
# ifdef LOG_LAST_OWNER
|
||||
pmutexNode->lastOwner = 0;
|
||||
# endif
|
||||
pmutexNode->pFileName = pFileName;
|
||||
pmutexNode->lineno = lineno;
|
||||
ellAdd(&mutexList,&pmutexNode->node);
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
return(pmutexNode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
epicsMutexId epicsStdCall epicsMutexOsiMustCreate(
|
||||
const char *pFileName,int lineno)
|
||||
{
|
||||
epicsMutexId id = epicsMutexOsiCreate(pFileName,lineno);
|
||||
assert(id);
|
||||
return(id );
|
||||
if(!id) {
|
||||
cantProceed("epicsMutexOsiMustCreate() fails at %s:%d\n",
|
||||
pFileName, lineno);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
ellDelete(&mutexList,&pmutexNode->node);
|
||||
epicsMutexOsdDestroy(pmutexNode->id);
|
||||
VALGRIND_MEMPOOL_FREE(&freeList, pmutexNode);
|
||||
VALGRIND_MEMPOOL_ALLOC(&freeList, &pmutexNode->node, sizeof(pmutexNode->node));
|
||||
ellAdd(&freeList,&pmutexNode->node);
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexOsdUnlock(pmutexNode->id);
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexLock(
|
||||
epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexLockStatus status =
|
||||
epicsMutexOsdLock(pmutexNode->id);
|
||||
# ifdef LOG_LAST_OWNER
|
||||
if ( status == epicsMutexLockOK ) {
|
||||
pmutexNode->lastOwner = epicsThreadGetIdSelf();
|
||||
}
|
||||
# endif
|
||||
return status;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexTryLock(
|
||||
epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexLockStatus status =
|
||||
epicsMutexOsdTryLock(pmutexNode->id);
|
||||
# ifdef LOG_LAST_OWNER
|
||||
if ( status == epicsMutexLockOK ) {
|
||||
pmutexNode->lastOwner = epicsThreadGetIdSelf();
|
||||
}
|
||||
# endif
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Empty the freeList.
|
||||
* Called from epicsExit.c, but not via epicsAtExit()
|
||||
* to avoid the possibility of a circular reference.
|
||||
*/
|
||||
extern "C"
|
||||
void epicsMutexCleanup(void)
|
||||
{
|
||||
ELLNODE *cur;
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
|
||||
while((cur=ellGet(&freeList))!=NULL) {
|
||||
VALGRIND_MEMPOOL_FREE(&freeList, cur);
|
||||
free(cur);
|
||||
if(pmutexNode) {
|
||||
epicsMutexMustLock(&epicsMutexGlobalLock);
|
||||
ellDelete(&mutexList, &pmutexNode->node);
|
||||
(void)epicsMutexUnlock(&epicsMutexGlobalLock);
|
||||
epicsMutexOsdCleanup(pmutexNode);
|
||||
free(pmutexNode);
|
||||
}
|
||||
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexShow(
|
||||
epicsMutexId pmutexNode, unsigned int level)
|
||||
{
|
||||
# ifdef LOG_LAST_OWNER
|
||||
char threadName [255];
|
||||
if ( pmutexNode->lastOwner ) {
|
||||
# error currently not safe to fetch name for stale thread
|
||||
epicsThreadGetName ( pmutexNode->lastOwner,
|
||||
threadName, sizeof ( threadName ) );
|
||||
}
|
||||
else {
|
||||
strcpy ( threadName, "<not used>" );
|
||||
}
|
||||
printf("epicsMutexId %p last owner \"%s\" source %s line %d\n",
|
||||
(void *)pmutexNode, threadName,
|
||||
pmutexNode->pFileName, pmutexNode->lineno);
|
||||
# else
|
||||
printf("epicsMutexId %p source %s line %d\n",
|
||||
(void *)pmutexNode, pmutexNode->pFileName,
|
||||
pmutexNode->lineno);
|
||||
# endif
|
||||
printf("epicsMutexId %p source %s line %d\n",
|
||||
(void *)pmutexNode, pmutexNode->pFileName,
|
||||
pmutexNode->lineno);
|
||||
if ( level > 0 ) {
|
||||
epicsMutexOsdShow(pmutexNode->id,level-1);
|
||||
epicsMutexOsdShow(pmutexNode,level-1);
|
||||
}
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexShowAll(int onlyLocked,unsigned int level)
|
||||
{
|
||||
epicsMutexParm *pmutexNode;
|
||||
epicsMutexOsdSetup();
|
||||
|
||||
if (epicsMutexOsiOnce == EPICS_THREAD_ONCE_INIT)
|
||||
return;
|
||||
|
||||
printf("ellCount(&mutexList) %d ellCount(&freeList) %d\n",
|
||||
ellCount(&mutexList),ellCount(&freeList));
|
||||
printf("ellCount(&mutexList) %d\n", ellCount(&mutexList));
|
||||
epicsMutexOsdShowAll();
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
pmutexNode = reinterpret_cast < epicsMutexParm * > ( ellFirst(&mutexList) );
|
||||
while(pmutexNode) {
|
||||
epicsMutexMustLock(&epicsMutexGlobalLock);
|
||||
for(ELLNODE *cur =ellFirst(&mutexList); cur; cur = ellNext(cur)) {
|
||||
epicsMutexParm *lock = CONTAINER(cur, epicsMutexParm, node);
|
||||
if(onlyLocked) {
|
||||
epicsMutexLockStatus status;
|
||||
status = epicsMutexOsdTryLock(pmutexNode->id);
|
||||
if(status==epicsMutexLockOK) {
|
||||
epicsMutexOsdUnlock(pmutexNode->id);
|
||||
pmutexNode =
|
||||
reinterpret_cast < epicsMutexParm * >
|
||||
( ellNext(&pmutexNode->node) );
|
||||
continue;
|
||||
// cycle through to test state
|
||||
if(epicsMutexTryLock(lock)==epicsMutexLockOK) {
|
||||
epicsMutexUnlock(lock);
|
||||
continue; // was not locked, skip
|
||||
}
|
||||
}
|
||||
epicsMutexShow(pmutexNode, level);
|
||||
pmutexNode =
|
||||
reinterpret_cast < epicsMutexParm * > ( ellNext(&pmutexNode->node) );
|
||||
epicsMutexShow(lock, level);
|
||||
}
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
epicsMutexUnlock(&epicsMutexGlobalLock);
|
||||
}
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<8)
|
||||
|
||||
@@ -247,21 +247,6 @@ LIBCOM_API void epicsStdCall epicsMutexShow(
|
||||
LIBCOM_API void epicsStdCall epicsMutexShowAll(
|
||||
int onlyLocked,unsigned int level);
|
||||
|
||||
/**@privatesection
|
||||
* The following are interfaces to the OS dependent
|
||||
* implementation and should NOT be called directly by
|
||||
* user code.
|
||||
*/
|
||||
struct epicsMutexOSD * epicsMutexOsdCreate(void);
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD *);
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD *);
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD *);
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD *);
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD *,unsigned int level);
|
||||
#ifdef EPICS_PRIVATE_API
|
||||
void epicsMutexOsdShowAll(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
66
modules/libcom/src/osi/epicsMutexImpl.h
Normal file
66
modules/libcom/src/osi/epicsMutexImpl.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* Copyright (c) 2023 Michael Davidsaver
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/* Only include from osdMutex.c */
|
||||
|
||||
#ifndef epicsMutexImpl_H
|
||||
#define epicsMutexImpl_H
|
||||
|
||||
#if defined(vxWorks)
|
||||
# include <vxWorks.h>
|
||||
# include <semLib.h>
|
||||
#elif defined(_WIN32)
|
||||
# define VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#elif defined(__rtems__)
|
||||
# include <rtems.h>
|
||||
# include <rtems/score/cpuopts.h>
|
||||
#else
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "ellLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct epicsMutexParm {
|
||||
/* global list of mutex */
|
||||
ELLNODE node;
|
||||
/* location where mutex was allocated */
|
||||
const char *pFileName;
|
||||
int lineno;
|
||||
#if defined(vxWorks)
|
||||
SEM_ID osd;
|
||||
#elif defined(_WIN32)
|
||||
CRITICAL_SECTION osd;
|
||||
#elif defined(__RTEMS_MAJOR__) && __RTEMS_MAJOR__<5
|
||||
Semaphore_Control *osd;
|
||||
#else
|
||||
pthread_mutex_t osd;
|
||||
#endif
|
||||
};
|
||||
|
||||
void epicsMutexOsdSetup(void);
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *);
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *);
|
||||
void epicsMutexOsdShow(struct epicsMutexParm *,unsigned int level);
|
||||
void epicsMutexOsdShowAll(void);
|
||||
|
||||
extern struct epicsMutexParm epicsMutexGlobalLock;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C
|
||||
#endif
|
||||
|
||||
#endif // epicsMutexImpl_H
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsThread.h"
|
||||
#include "rtemsNamePvt.h"
|
||||
#include "errlog.h"
|
||||
|
||||
/* #define EPICS_RTEMS_SEMAPHORE_STATS */
|
||||
@@ -48,11 +49,9 @@ epicsEventCreate(epicsEventInitialState initialState)
|
||||
rtems_status_code sc;
|
||||
rtems_id sid;
|
||||
rtems_interrupt_level level;
|
||||
static char c1 = 'a';
|
||||
static char c2 = 'a';
|
||||
static char c3 = 'a';
|
||||
static uint32_t name;
|
||||
|
||||
sc = rtems_semaphore_create (rtems_build_name ('B', c3, c2, c1),
|
||||
sc = rtems_semaphore_create (next_rtems_name ('B', &name),
|
||||
initialState,
|
||||
RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE |
|
||||
RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
|
||||
@@ -62,26 +61,6 @@ epicsEventCreate(epicsEventInitialState initialState)
|
||||
errlogPrintf ("Can't create binary semaphore: %s\n", rtems_status_text (sc));
|
||||
return NULL;
|
||||
}
|
||||
rtems_interrupt_disable (level);
|
||||
if (c1 == 'z') {
|
||||
if (c2 == 'z') {
|
||||
if (c3 == 'z') {
|
||||
c3 = 'a';
|
||||
}
|
||||
else {
|
||||
c3++;
|
||||
}
|
||||
c2 = 'a';
|
||||
}
|
||||
else {
|
||||
c2++;
|
||||
}
|
||||
c1 = 'a';
|
||||
}
|
||||
else {
|
||||
c1++;
|
||||
}
|
||||
rtems_interrupt_enable (level);
|
||||
return (epicsEventId)sid;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
@@ -26,97 +27,84 @@
|
||||
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "rtemsNamePvt.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "errlog.h"
|
||||
|
||||
#define RTEMS_FAST_MUTEX
|
||||
/* #define EPICS_RTEMS_SEMAPHORE_STATS */
|
||||
/*
|
||||
* Some performance tuning instrumentation
|
||||
*/
|
||||
#ifdef EPICS_RTEMS_SEMAPHORE_STATS
|
||||
unsigned long semMstat[4];
|
||||
#define SEMSTAT(i) semMstat[i]++;
|
||||
#else
|
||||
#define SEMSTAT(i)
|
||||
#endif
|
||||
uint32_t next_rtems_name(char prefix, uint32_t* counter)
|
||||
{
|
||||
uint32_t next;
|
||||
rtems_interrupt_level level;
|
||||
char a, b, c;
|
||||
|
||||
struct epicsMutexOSD *
|
||||
epicsMutexOsdCreate(void)
|
||||
rtems_interrupt_disable (level);
|
||||
next = *counter;
|
||||
*counter = (next+1)%(26u*26u*26u);
|
||||
rtems_interrupt_enable (level);
|
||||
|
||||
a = 'a' + (next % 26u);
|
||||
next /= 26u;
|
||||
b = 'a' + (next % 26u);
|
||||
next /= 26u;
|
||||
c = 'a' + (next % 26u); // modulo should be redundant, but ... paranoia
|
||||
|
||||
return rtems_build_name(prefix, a, b, c);
|
||||
}
|
||||
|
||||
void epicsMutexOsdSetup(void)
|
||||
{
|
||||
// TODO: use RTEMS_SYSINIT_ITEM() ?
|
||||
if(!epicsMutexGlobalLock.osd) {
|
||||
epicsMutexOsdPrepare(&epicsMutexGlobalLock);
|
||||
}
|
||||
}
|
||||
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *mutex)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id sid;
|
||||
rtems_interrupt_level level;
|
||||
static char c1 = 'a';
|
||||
static char c2 = 'a';
|
||||
static char c3 = 'a';
|
||||
static uint32_t name;
|
||||
|
||||
sc = rtems_semaphore_create (rtems_build_name ('M', c3, c2, c1),
|
||||
sc = rtems_semaphore_create (next_rtems_name ('M', &name),
|
||||
1,
|
||||
RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE|RTEMS_INHERIT_PRIORITY|RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,
|
||||
0,
|
||||
&sid);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
errlogPrintf ("Can't create mutex semaphore: %s\n", rtems_status_text (sc));
|
||||
return NULL;
|
||||
return ENOMEM;
|
||||
}
|
||||
rtems_interrupt_disable (level);
|
||||
if (c1 == 'z') {
|
||||
if (c2 == 'z') {
|
||||
if (c3 == 'z') {
|
||||
c3 = 'a';
|
||||
}
|
||||
else {
|
||||
c3++;
|
||||
}
|
||||
c2 = 'a';
|
||||
}
|
||||
else {
|
||||
c2++;
|
||||
}
|
||||
c1 = 'a';
|
||||
}
|
||||
else {
|
||||
c1++;
|
||||
}
|
||||
rtems_interrupt_enable (level);
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
{
|
||||
Semaphore_Control *the_semaphore;
|
||||
Objects_Locations location;
|
||||
Objects_Locations location;
|
||||
|
||||
the_semaphore = _Semaphore_Get( sid, &location );
|
||||
_Thread_Enable_dispatch();
|
||||
mutex->osd = _Semaphore_Get( sid, &location );
|
||||
_Thread_Enable_dispatch(); /* _Semaphore_Get() disables */
|
||||
|
||||
return (struct epicsMutexOSD *)the_semaphore;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return (struct epicsMutexOSD *)sid;
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * id)
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *mutex)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id sid;
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
sid = the_semaphore->Object.id;
|
||||
#else
|
||||
sid = (rtems_id)id;
|
||||
#endif
|
||||
sc = rtems_semaphore_delete (sid);
|
||||
if (sc == RTEMS_RESOURCE_IN_USE) {
|
||||
rtems_semaphore_release (sid);
|
||||
sc = rtems_semaphore_delete (sid);
|
||||
}
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
errlogPrintf ("Can't destroy semaphore %p (%lx): %s\n", id, (unsigned long)sid, rtems_status_text (sc));
|
||||
errlogPrintf ("Can't destroy semaphore %p (%lx): %s\n",
|
||||
mutex, (unsigned long)sid, rtems_status_text (sc));
|
||||
}
|
||||
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD * id)
|
||||
void epicsMutexUnlock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
_Thread_Disable_dispatch();
|
||||
_CORE_mutex_Surrender (
|
||||
&the_semaphore->Core_control.mutex,
|
||||
@@ -124,18 +112,13 @@ void epicsMutexOsdUnlock(struct epicsMutexOSD * id)
|
||||
NULL
|
||||
);
|
||||
_Thread_Enable_dispatch();
|
||||
#else
|
||||
epicsEventSignal (id);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * id)
|
||||
epicsMutexLockStatus epicsMutexLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
ISR_Level level;
|
||||
SEMSTAT(0)
|
||||
_ISR_Disable( level );
|
||||
_CORE_mutex_Seize(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
@@ -148,19 +131,12 @@ epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * id)
|
||||
return epicsMutexLockOK;
|
||||
else
|
||||
return epicsMutexLockError;
|
||||
#else
|
||||
SEMSTAT(0)
|
||||
return((epicsEventWait (id) == epicsEventWaitOK)
|
||||
?epicsMutexLockOK : epicsMutexLockError);
|
||||
#endif
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
|
||||
epicsMutexLockStatus epicsMutexTryLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
ISR_Level level;
|
||||
SEMSTAT(2)
|
||||
_ISR_Disable( level );
|
||||
_CORE_mutex_Seize(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
@@ -175,25 +151,12 @@ epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
|
||||
return epicsMutexLockTimeout;
|
||||
else
|
||||
return epicsMutexLockError;
|
||||
#else
|
||||
epicsEventWaitStatus status;
|
||||
SEMSTAT(2)
|
||||
status = epicsEventTryWait(id);
|
||||
return((status==epicsEventWaitOK
|
||||
? epicsMutexLockOK
|
||||
: (status==epicsEventWaitTimeout)
|
||||
? epicsMutexLockTimeout
|
||||
: epicsMutexLockError));
|
||||
#endif
|
||||
}
|
||||
|
||||
LIBCOM_API void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
|
||||
LIBCOM_API void epicsMutexOsdShow(struct epicsMutexParm *mutex,unsigned int level)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
id = (struct epicsMutexOSD *)the_semaphore->Object.id;
|
||||
#endif
|
||||
epicsEventShow ((epicsEventId)id,level);
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
epicsEventShow ((epicsEventId)the_semaphore->Object.id,level);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "epicsStdio.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
@@ -59,7 +60,7 @@ struct taskVar {
|
||||
unsigned int threadVariableCapacity;
|
||||
void **threadVariables;
|
||||
};
|
||||
static struct epicsMutexOSD *taskVarMutex;
|
||||
static struct epicsMutexParm taskVarMutex = {ELLNODE_INIT, __FILE__, __LINE__};
|
||||
static struct taskVar *taskVarHead;
|
||||
#define RTEMS_NOTEPAD_TASKVAR 11
|
||||
|
||||
@@ -67,15 +68,7 @@ static struct taskVar *taskVarHead;
|
||||
* Support for `once-only' execution
|
||||
*/
|
||||
static volatile int initialized = 0; /* strictly speaking 'volatile' is not enough here, but it shouldn't hurt */
|
||||
static struct epicsMutexOSD *onceMutex;
|
||||
|
||||
static
|
||||
void epicsMutexOsdMustLock(struct epicsMutexOSD * L)
|
||||
{
|
||||
while(epicsMutexOsdLock(L)!=epicsMutexLockOK) {
|
||||
cantProceed("epicsThreadOnce() mutex error");
|
||||
}
|
||||
}
|
||||
static struct epicsMutexParm onceMutex = {ELLNODE_INIT, __FILE__, __LINE__};
|
||||
|
||||
/*
|
||||
* Just map osi 0 to 99 into RTEMS 199 to 100
|
||||
@@ -161,13 +154,13 @@ epicsThreadGetStackSize (epicsThreadStackSizeClass size)
|
||||
static void
|
||||
taskVarLock (void)
|
||||
{
|
||||
epicsMutexOsdMustLock (taskVarMutex);
|
||||
epicsMutexMustLock (&taskVarMutex);
|
||||
}
|
||||
|
||||
static void
|
||||
taskVarUnlock (void)
|
||||
{
|
||||
epicsMutexOsdUnlock (taskVarMutex);
|
||||
epicsMutexUnlock (&taskVarMutex);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -243,7 +236,7 @@ setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr,
|
||||
v->threadVariables = NULL;
|
||||
v->isRunning = 1;
|
||||
if (joinable) {
|
||||
char c[3];
|
||||
char c[3] = {0,0,0};
|
||||
strncpy(c, v->name, 3);
|
||||
sc = rtems_barrier_create(rtems_build_name('~', c[0], c[1], c[2]),
|
||||
RTEMS_BARRIER_AUTOMATIC_RELEASE | RTEMS_LOCAL,
|
||||
@@ -288,10 +281,8 @@ epicsThreadInit (void)
|
||||
rtems_task_priority old;
|
||||
|
||||
rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);
|
||||
onceMutex = epicsMutexOsdCreate();
|
||||
taskVarMutex = epicsMutexOsdCreate();
|
||||
if (!onceMutex || !taskVarMutex)
|
||||
cantProceed("epicsThreadInit() can't create global mutexes\n");
|
||||
epicsMutexOsdPrepare(&taskVarMutex);
|
||||
epicsMutexOsdPrepare(&onceMutex);
|
||||
rtems_task_ident (RTEMS_SELF, 0, &tid);
|
||||
if(setThreadInfo (tid, "_main_", NULL, NULL, 0) != RTEMS_SUCCESSFUL)
|
||||
cantProceed("epicsThreadInit() unable to setup _main_");
|
||||
@@ -317,7 +308,7 @@ epicsThreadCreateOpt (
|
||||
unsigned int stackSize;
|
||||
rtems_id tid;
|
||||
rtems_status_code sc;
|
||||
char c[4];
|
||||
char c[4] = {0,0,0,0};
|
||||
|
||||
if (!initialized)
|
||||
epicsThreadInit();
|
||||
@@ -612,26 +603,26 @@ void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
|
||||
#define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1
|
||||
|
||||
if (!initialized) epicsThreadInit();
|
||||
epicsMutexOsdMustLock(onceMutex);
|
||||
epicsMutexMustLock(&onceMutex);
|
||||
if (*id != EPICS_THREAD_ONCE_DONE) {
|
||||
if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
|
||||
*id = epicsThreadGetIdSelf(); /* mark active */
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
func(arg);
|
||||
epicsMutexOsdMustLock(onceMutex);
|
||||
epicsMutexMustLock(&onceMutex);
|
||||
*id = EPICS_THREAD_ONCE_DONE; /* mark done */
|
||||
} else if (*id == epicsThreadGetIdSelf()) {
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
cantProceed("Recursive epicsThreadOnce() initialization\n");
|
||||
} else
|
||||
while (*id != EPICS_THREAD_ONCE_DONE) {
|
||||
/* Another thread is in the above func(arg) call. */
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
epicsThreadSleep(epicsThreadSleepQuantum());
|
||||
epicsMutexOsdMustLock(onceMutex);
|
||||
epicsMutexMustLock(&onceMutex);
|
||||
}
|
||||
}
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
20
modules/libcom/src/osi/os/RTEMS-score/rtemsNamePvt.h
Normal file
20
modules/libcom/src/osi/os/RTEMS-score/rtemsNamePvt.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Michael Davidsaver
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef RTEMSNAMEPVT_H
|
||||
#define RTEMSNAMEPVT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Compute rtems_build_name(prefix, A, B, C) where A, B, C are the letters a-z.
|
||||
* eg. "Qaaa"
|
||||
*
|
||||
* 'counter' is incremented atomically during each call.
|
||||
*/
|
||||
uint32_t next_rtems_name(char prefix, uint32_t* counter);
|
||||
|
||||
#endif // RTEMSNAMEPVT_H
|
||||
@@ -20,147 +20,59 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define VC_EXTRALEAN
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
#if _WIN32_WINNT < 0x0501
|
||||
# error Minimum supported is Windows XP
|
||||
#endif
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "libComAPI.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsStdio.h"
|
||||
|
||||
typedef struct epicsMutexOSD {
|
||||
union {
|
||||
HANDLE mutex;
|
||||
CRITICAL_SECTION criticalSection;
|
||||
} os;
|
||||
} epicsMutexOSD;
|
||||
|
||||
static BOOL thisIsNT = FALSE;
|
||||
static LONG weHaveInitialized = 0;
|
||||
|
||||
/*
|
||||
* epicsMutexCreate ()
|
||||
*/
|
||||
epicsMutexOSD * epicsMutexOsdCreate ( void )
|
||||
static epicsThreadOnceId epicsMutexOsdOnce = EPICS_THREAD_ONCE_INIT;
|
||||
static void epicsMutexOsdInit(void* unused)
|
||||
{
|
||||
epicsMutexOSD * pSem;
|
||||
|
||||
if ( ! weHaveInitialized ) {
|
||||
BOOL status;
|
||||
OSVERSIONINFO osInfo;
|
||||
osInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
|
||||
status = GetVersionEx ( & osInfo );
|
||||
thisIsNT = status && ( osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT );
|
||||
weHaveInitialized = 1;
|
||||
}
|
||||
|
||||
pSem = malloc ( sizeof (*pSem) );
|
||||
if ( pSem ) {
|
||||
if ( thisIsNT ) {
|
||||
InitializeCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
pSem->os.mutex = CreateMutex ( NULL, FALSE, NULL );
|
||||
if ( pSem->os.mutex == 0 ) {
|
||||
free ( pSem );
|
||||
pSem = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pSem;
|
||||
(void)unused;
|
||||
InitializeCriticalSection(&epicsMutexGlobalLock.osd);
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdDestroy ()
|
||||
*/
|
||||
void epicsMutexOsdDestroy ( epicsMutexOSD * pSem )
|
||||
void epicsMutexOsdSetup()
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
DeleteCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
CloseHandle ( pSem->os.mutex );
|
||||
}
|
||||
free ( pSem );
|
||||
epicsThreadOnce(&epicsMutexOsdOnce, &epicsMutexOsdInit, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdUnlock ()
|
||||
*/
|
||||
void epicsMutexOsdUnlock ( epicsMutexOSD * pSem )
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *mutex)
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
LeaveCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
BOOL success = ReleaseMutex ( pSem->os.mutex );
|
||||
assert ( success );
|
||||
}
|
||||
InitializeCriticalSection(&mutex->osd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdLock ()
|
||||
*/
|
||||
epicsMutexLockStatus epicsMutexOsdLock ( epicsMutexOSD * pSem )
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *mutex)
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
EnterCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
DWORD status = WaitForSingleObject ( pSem->os.mutex, INFINITE );
|
||||
if ( status != WAIT_OBJECT_0 ) {
|
||||
return epicsMutexLockError;
|
||||
}
|
||||
}
|
||||
DeleteCriticalSection(&mutex->osd);
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexUnlock ( struct epicsMutexParm *mutex )
|
||||
{
|
||||
LeaveCriticalSection ( &mutex->osd );
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexLock ( struct epicsMutexParm *mutex )
|
||||
{
|
||||
EnterCriticalSection ( &mutex->osd );
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdTryLock ()
|
||||
*/
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock ( epicsMutexOSD * pSem )
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexTryLock ( struct epicsMutexParm *mutex )
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
if ( TryEnterCriticalSection ( &pSem->os.criticalSection ) ) {
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
else {
|
||||
return epicsMutexLockTimeout;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DWORD status = WaitForSingleObject ( pSem->os.mutex, 0 );
|
||||
if ( status != WAIT_OBJECT_0 ) {
|
||||
if (status == WAIT_TIMEOUT) {
|
||||
return epicsMutexLockTimeout;
|
||||
}
|
||||
else {
|
||||
return epicsMutexLockError;
|
||||
}
|
||||
}
|
||||
}
|
||||
return epicsMutexLockOK;
|
||||
return TryEnterCriticalSection ( &mutex->osd ) ? epicsMutexLockOK : epicsMutexLockTimeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdShow ()
|
||||
*/
|
||||
void epicsMutexOsdShow ( epicsMutexOSD * pSem, unsigned level )
|
||||
void epicsMutexOsdShow ( struct epicsMutexParm *mutex, unsigned level )
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
printf ("epicsMutex: win32 critical section at %p\n",
|
||||
(void * ) & pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
printf ( "epicsMutex: win32 mutex at %p\n",
|
||||
( void * ) pSem->os.mutex );
|
||||
}
|
||||
(void)level;
|
||||
printf ("epicsMutex: win32 critical section at %p\n",
|
||||
(void * ) & mutex->osd );
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
||||
@@ -24,18 +24,19 @@
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <ctype.h>
|
||||
#include <envDefs.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
#define epicsStdioStdStreams
|
||||
#define epicsStdioStdPrintfEtc
|
||||
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "osdPosixMutexPriv.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsTime.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "envDefs.h"
|
||||
|
||||
#define checkStatus(status,message) \
|
||||
if((status)) { \
|
||||
@@ -128,62 +129,62 @@ static int mutexLock(pthread_mutex_t *id)
|
||||
return status;
|
||||
}
|
||||
|
||||
typedef struct epicsMutexOSD {
|
||||
pthread_mutex_t lock;
|
||||
} epicsMutexOSD;
|
||||
/* used if OS does not support statically allocated mutex */
|
||||
static pthread_once_t epicsMutexOsdOnce = PTHREAD_ONCE_INIT;
|
||||
|
||||
epicsMutexOSD * epicsMutexOsdCreate(void) {
|
||||
epicsMutexOSD *pmutex;
|
||||
int status;
|
||||
|
||||
pmutex = calloc(1, sizeof(*pmutex));
|
||||
if(!pmutex)
|
||||
return NULL;
|
||||
|
||||
status = osdPosixMutexInit(&pmutex->lock, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (!status)
|
||||
return pmutex;
|
||||
|
||||
free(pmutex);
|
||||
return NULL;
|
||||
static void epicsMutexOsdInit(void)
|
||||
{
|
||||
int ret = pthread_mutex_init(&epicsMutexGlobalLock.osd, NULL);
|
||||
if(ret) {
|
||||
/* something has gone wrong early. Not much can be done...*/
|
||||
fprintf(stderr, "osdMutex early init failure %d.\n", ret);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * pmutex)
|
||||
void epicsMutexOsdSetup()
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_destroy(&pmutex->lock);
|
||||
checkStatusQuit(status, "pthread_mutex_destroy", "epicsMutexOsdDestroy");
|
||||
free(pmutex);
|
||||
int ret = pthread_once(&epicsMutexOsdOnce, &epicsMutexOsdInit);
|
||||
if(ret) {
|
||||
/* ditto...*/
|
||||
fprintf(stderr, "osdMutex early once failure %d.\n", ret);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD * pmutex)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_unlock(&pmutex->lock);
|
||||
checkStatusQuit(status, "pthread_mutex_unlock", "epicsMutexOsdUnlock");
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *pmutex) {
|
||||
return osdPosixMutexInit(&pmutex->osd, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * pmutex)
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *pmutex)
|
||||
{
|
||||
int status;
|
||||
int status = pthread_mutex_destroy(&pmutex->osd);
|
||||
checkStatus(status, "pthread_mutex_destroy");
|
||||
}
|
||||
|
||||
status = mutexLock(&pmutex->lock);
|
||||
void epicsMutexUnlock(struct epicsMutexParm * pmutex)
|
||||
{
|
||||
int status = pthread_mutex_unlock(&pmutex->osd);
|
||||
checkStatus(status, "pthread_mutex_unlock epicsMutexOsdUnlock");
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexLock(struct epicsMutexParm * pmutex)
|
||||
{
|
||||
int status = mutexLock(&pmutex->osd);
|
||||
if (status == EINVAL) return epicsMutexLockError;
|
||||
if(status) {
|
||||
errlogMessage("epicsMutex pthread_mutex_lock failed: error epicsMutexOsdLock\n");
|
||||
errlogMessage("epicsMutex pthread_mutex_lock failed: error epicsMutexLock\n");
|
||||
return epicsMutexLockError;
|
||||
}
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
|
||||
epicsMutexLockStatus epicsMutexTryLock(struct epicsMutexParm * pmutex)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!pmutex) return epicsMutexLockError;
|
||||
status = pthread_mutex_trylock(&pmutex->lock);
|
||||
status = pthread_mutex_trylock(&pmutex->osd);
|
||||
if (status == EINVAL) return epicsMutexLockError;
|
||||
if (status == EBUSY) return epicsMutexLockTimeout;
|
||||
if(status) {
|
||||
@@ -193,12 +194,13 @@ epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD * pmutex, unsigned int level)
|
||||
void epicsMutexOsdShow(struct epicsMutexParm * pmutex, unsigned int level)
|
||||
{
|
||||
(void)level;
|
||||
/* GLIBC w/ NTPL is passing the &lock.__data.__lock as the first argument (UADDR)
|
||||
* of the futex() syscall. __lock is at offset 0 of the enclosing structures.
|
||||
*/
|
||||
printf(" pthread_mutex_t* uaddr=%p\n", &pmutex->lock);
|
||||
epicsStdoutPrintf(" pthread_mutex_t* uaddr=%p\n", &pmutex->osd);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void)
|
||||
@@ -207,11 +209,11 @@ void epicsMutexOsdShowAll(void)
|
||||
int proto = -1;
|
||||
int ret = pthread_mutexattr_getprotocol(&globalAttrRecursive, &proto);
|
||||
if(ret) {
|
||||
printf("PI maybe not enabled: %d\n", ret);
|
||||
epicsStdoutPrintf("PI maybe not enabled: %d\n", ret);
|
||||
} else {
|
||||
printf("PI is%s enabled\n", proto==PTHREAD_PRIO_INHERIT ? "" : " not");
|
||||
epicsStdoutPrintf("PI is%s enabled\n", proto==PTHREAD_PRIO_INHERIT ? "" : " not");
|
||||
}
|
||||
#else
|
||||
printf("PI not supported\n");
|
||||
epicsStdoutPrintf("PI not supported\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <semLib.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <objLib.h>
|
||||
#include <sysLib.h>
|
||||
@@ -23,30 +24,47 @@ int sysClkRateGet(void);
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "epicsMutex.h"
|
||||
|
||||
struct epicsMutexOSD * epicsMutexOsdCreate(void)
|
||||
#include "epicsMutexImpl.h"
|
||||
|
||||
void epicsMutexOsdSetup(void)
|
||||
{
|
||||
return((struct epicsMutexOSD *)
|
||||
semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY));
|
||||
if(!epicsMutexGlobalLock.osd) {
|
||||
epicsMutexOsdPrepare(&epicsMutexGlobalLock);
|
||||
}
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * id)
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *mutex)
|
||||
{
|
||||
semDelete((SEM_ID)id);
|
||||
mutex->osd = semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
|
||||
return mutex->osd ? 0 : ENOMEM;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *mutex)
|
||||
{
|
||||
int status;
|
||||
status = semTake((SEM_ID)id,NO_WAIT);
|
||||
semDelete(mutex->osd);
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
return semTake(mutex->osd,WAIT_FOREVER)==OK ? epicsMutexLockOK : epicsMutexLockError;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexTryLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
int status = semTake(mutex->osd,NO_WAIT);
|
||||
if(status==OK) return(epicsMutexLockOK);
|
||||
if(errno==S_objLib_OBJ_UNAVAILABLE) return(epicsMutexLockTimeout);
|
||||
return(epicsMutexLockError);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
|
||||
void epicsMutexUnlock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
semShow((SEM_ID)id,level);
|
||||
semGive(mutex->osd);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexParm *mutex,unsigned int level)
|
||||
{
|
||||
semShow(mutex->osd,level);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
||||
@@ -13,13 +13,3 @@
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <semLib.h>
|
||||
|
||||
/* If the macro is replaced by inline it is necessary to say
|
||||
static __inline__
|
||||
but then a warning message appears everywhere osdMutex.h is included
|
||||
*/
|
||||
|
||||
#define epicsMutexOsdUnlock(ID) semGive((SEM_ID)(ID))
|
||||
|
||||
#define epicsMutexOsdLock(ID) \
|
||||
(semTake((SEM_ID)(ID),WAIT_FOREVER)==OK ? epicsMutexLockOK : epicsMutexLockError)
|
||||
|
||||
Reference in New Issue
Block a user