Compare commits

...

14 Commits

Author SHA1 Message Date
e2bb42d8d3 obsolete caRepeater rpm
Some checks failed
Check EditorConfig / editorconfig (push) Failing after 2s
Base / Cross linux-aarch64 (push) Failing after 1s
Base / Cross linux-arm gnueabi (push) Failing after 2s
Base / Cross linux-arm gnueabihf (push) Failing after 1s
Base / CentOS-7 (push) Failing after 2s
Base / Fedora-33 (push) Failing after 1s
Base / Fedora-latest (push) Failing after 2s
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-4.9 (push) Has been cancelled
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-20 clang-10 (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 + 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 (push) Has been cancelled
Base / Ub-20 gcc-9 unsigned char (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-22 gcc-12 c++20 Werror (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2023-12-10 13:47:17 +01:00
abcada0d85 add rpm specfile and profile script
Some checks failed
Check EditorConfig / editorconfig (push) Failing after 1s
Base / Cross linux-aarch64 (push) Failing after 2s
Base / Cross linux-arm gnueabi (push) Failing after 1s
Base / Cross linux-arm gnueabihf (push) Failing after 2s
Base / CentOS-7 (push) Failing after 1s
Base / Fedora-33 (push) Failing after 2s
Base / Fedora-latest (push) Failing after 1s
Base / Ub-20 clang-10 C++11 (push) Has been cancelled
Base / MacOS clang-12 (push) Has been cancelled
Base / Ub-20 clang-10 (push) Has been cancelled
Base / Ub-20 gcc-9 + RT-5.1 beatnik (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 pc686 (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 + RT-5.1 uC5282 (push) Has been cancelled
Base / Ub-20 gcc-9 + MinGW (push) Has been cancelled
Base / Ub-20 gcc-9 unsigned char (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-22 gcc-12 c++20 Werror (push) Has been cancelled
Base / Win2019 MSC-19 (push) Has been cancelled
Base / Win2019 MSC-19, debug (push) Has been cancelled
Base / Win2019 MSC-19, static (push) Has been cancelled
2023-12-08 15:32:20 +01:00
2c35d60a64 silent wine errors 2023-12-08 11:38:38 +01:00
af1b77eb0f fix rpath when FINAL_LOCATION is set 2023-12-07 16:07:02 +01:00
93947eb027 prevents using make -j2 2023-12-06 14:24:56 +01:00
961671259f Add support for RHEL9 2023-12-04 16:00:24 +01:00
Michael Davidsaver
db2482117d rationalize osdMutex
Avoids split allocation.
Eliminates special case free-list.

win32: eliminate pre-XP
rtems-score: eliminate non-fast
2023-12-04 11:04:51 +01:00
a66caa5985 move cross compilers away from AFS 2023-12-04 10:08:47 +01:00
4803aae904 re-enable alternative PowerPMAC archs 2023-12-01 16:52:41 +01:00
427be18e2e upgrade cross windows build to use mvsc 2019 on Linux archs that support it 2023-12-01 16:52:41 +01:00
fff690a449 skip Microsoft noise in rc 2023-12-01 16:52:41 +01:00
428b836500 switch to 64 bit raspbian cross compiler 2023-12-01 16:52:41 +01:00
6c74507b11 all our current host OS can build nilrt7-armv7a 2023-12-01 16:52:40 +01:00
122ca4e1d3 change PROC to ASL0 2023-12-01 16:51:49 +01:00
43 changed files with 831 additions and 522 deletions

2
.gitignore vendored
View File

@@ -18,3 +18,5 @@ O.*/
.*.swp
.DS_Store
.iocsh_history
RPMS
SRPMS

View File

@@ -30,3 +30,6 @@ copysrc:
tar:
tar cfjP epics_base-$(EPICS_VERSION_NUMBER).tar.bz2 $(INSTALL_LOCATION)
rpm:
rpmbuild -bb epics-base.spec

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

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

View 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

View File

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

View File

@@ -0,0 +1 @@
include $(CONFIG)/os/CONFIG.Linux.windows-x64

View File

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

View File

@@ -1,2 +0,0 @@
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

385
epics-base.spec Normal file
View File

@@ -0,0 +1,385 @@
# 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: 4%{?dist}
License: EPICS Open License
Group: Development/Languages
URL: https://git.psi.ch/epics_base/base-7.0
Obsoletes: caRepeater
%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
%{__mkdir_p} RPMS
%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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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