From 4d8045ab5abff06821ef3f2bbb8c5709617a566d Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Fri, 19 Aug 2011 13:48:03 -0600 Subject: [PATCH] o merged in changes from the "compiler specific build" branch o changed implementation of default mutex locked version to be POSIX specific so we can use a static pthread mutex which is more efficent --- configure/CONFIG_COMMON | 6 +- configure/RULES_BUILD | 2 +- .../os/CONFIG_SITE.cygwin-x86.cygwin-x86 | 3 +- ...FIG_SITE.win32-x86-cygwin.win32-x86-cygwin | 1 - ...ONFIG_SITE.win32-x86-mingw.win32-x86-mingw | 1 + src/libCom/Makefile | 8 +- src/libCom/misc/compilerDependencies.h | 104 ------------ .../osi/compiler/borland/compilerSpecific.h | 55 ++++++ .../osi/compiler/clang/compilerSpecific.h | 59 +++++++ .../osi/compiler/default/compilerSpecific.h | 45 +++++ .../osi/compiler/gcc/compilerSpecific.h | 59 +++++++ src/libCom/osi/compiler/gcc/epicsAtomicCD.h | 7 +- .../osi/compiler/msvc/compilerSpecific.h | 57 +++++++ src/libCom/osi/compiler/msvc/epicsAtomicCD.h | 2 + src/libCom/osi/compilerDependencies.h | 47 ++++++ src/libCom/osi/epicsAtomic.h | 19 --- src/libCom/osi/epicsAtomicGuard.h | 54 ++++++ src/libCom/osi/epicsAtomicLocked.cpp | 158 ------------------ src/libCom/osi/epicsAtomicLocked.h | 108 +++++++----- src/libCom/osi/os/WIN32/epicsAtomicOSD.h | 2 + src/libCom/osi/os/default/epicsAtomicOSD.cpp | 26 +++ src/libCom/osi/os/default/epicsAtomicOSD.h | 2 - src/libCom/osi/os/posix/epicsAtomicOSD.cpp | 71 ++++++++ src/libCom/osi/os/solaris/epicsAtomicOSD.h | 6 +- src/libCom/osi/os/vxWorks/epicsAtomicOSD.h | 2 + 25 files changed, 558 insertions(+), 346 deletions(-) delete mode 100644 src/libCom/misc/compilerDependencies.h create mode 100644 src/libCom/osi/compiler/borland/compilerSpecific.h create mode 100644 src/libCom/osi/compiler/clang/compilerSpecific.h create mode 100644 src/libCom/osi/compiler/default/compilerSpecific.h create mode 100644 src/libCom/osi/compiler/gcc/compilerSpecific.h create mode 100644 src/libCom/osi/compiler/msvc/compilerSpecific.h create mode 100644 src/libCom/osi/compilerDependencies.h create mode 100644 src/libCom/osi/epicsAtomicGuard.h delete mode 100644 src/libCom/osi/epicsAtomicLocked.cpp create mode 100644 src/libCom/osi/os/default/epicsAtomicOSD.cpp create mode 100644 src/libCom/osi/os/posix/epicsAtomicOSD.cpp diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index fe0353542..72d9d4e9f 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -382,11 +382,11 @@ INSTALL_PERMISSIONS = 444 # # auto determine the directory paths that things are installed to # RULES: -# 0) found in any one of several compiler specific area +# 0) found in any one of several compiler specific paths # => install to $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) -# 1) not found in (0) and found in any one of several os specific area +# 1) not found in (0) and found in any one of several OS specific paths # => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS) -# 2) not found in (1) and found in generic area +# 2) not found in (1) and found in generic paths # => install to $(INSTALL_INCLUDE) # 3) not found in (1) or (2) then may be (not yet) computer generated # => install into $(INSTALL_INCLUDE)/os/$(OS_CLASS) and let diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 54ddd9ac4..b861e00e6 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -415,7 +415,7 @@ $(INSTALL_INCLUDE)/% : % @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) $(INSTALL_INCLUDE)/os/$(OS_CLASS)/% : % - $(ECHO) "Installing os dependent include file $@" + $(ECHO) "Installing OS dependent include file $@" @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/% : % diff --git a/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 b/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 index dee6a86f0..97e3cb1f3 100644 --- a/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 +++ b/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 @@ -7,4 +7,5 @@ #------------------------------------------------------- # GNU_DIR used when COMMANDLINE_LIBRARY is READLINE -#GNU_DIR=C:/cygwin \ No newline at end of file +#GNU_DIR=C:/cygwin + diff --git a/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin b/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin index b28b04f64..139597f9c 100644 --- a/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin +++ b/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin @@ -1,3 +1,2 @@ - diff --git a/configure/os/CONFIG_SITE.win32-x86-mingw.win32-x86-mingw b/configure/os/CONFIG_SITE.win32-x86-mingw.win32-x86-mingw index 771a4ba87..259d1e0c8 100644 --- a/configure/os/CONFIG_SITE.win32-x86-mingw.win32-x86-mingw +++ b/configure/os/CONFIG_SITE.win32-x86-mingw.win32-x86-mingw @@ -14,3 +14,4 @@ #AR = $(CMPLR_PREFIX)ar -rc #LD = $(CMPLR_PREFIX)ld -r #RANLIB = $(CMPLR_PREFIX)ranlib + diff --git a/src/libCom/Makefile b/src/libCom/Makefile index 02efe9348..8ba24f31c 100644 --- a/src/libCom/Makefile +++ b/src/libCom/Makefile @@ -136,7 +136,6 @@ INC += epicsExport.h INC += unixFileName.h INC += locationException.h INC += ipAddrToAsciiAsynchronous.h -INC += compilerDependencies.h INC += epicsUnitTest.h INC += testMain.h SRCS += aToIPAddr.c @@ -185,9 +184,8 @@ INC += osiWireFormat.h INC += osdWireFormat.h INC += osdWireConfig.h INC += epicsAtomic.h -INC += epicsAtomicLocked.h -INC += epicsAtomicOSD.h INC += epicsAtomicCD.h +INC += epicsAtomicOSD.h INC += epicsEndian.h INC += epicsReadline.h INC += epicsMessageQueue.h @@ -199,6 +197,8 @@ INC += devLib.h INC += devLibVME.h INC += devLibVMEImpl.h INC += osdVME.h +INC += compilerDependencies.h +INC += compilerSpecific.h SRCS += epicsThread.cpp SRCS += epicsMutex.cpp @@ -206,7 +206,6 @@ SRCS += epicsEvent.cpp SRCS += epicsTime.cpp SRCS += epicsMessageQueue.cpp SRCS += epicsMath.cpp -SRCS += epicsAtomicLocked.cpp SRCS += epicsAtomicOSD.cpp SRCS += epicsGeneralTime.c @@ -228,7 +227,6 @@ SRCS += epicsTempFile.cpp SRCS += epicsStdio.c SRCS += osdStdio.c - osdEnv_CFLAGS_WIN32= -U__STDC__ SRCS += osdThread.c diff --git a/src/libCom/misc/compilerDependencies.h b/src/libCom/misc/compilerDependencies.h deleted file mode 100644 index 4d451469e..000000000 --- a/src/libCom/misc/compilerDependencies.h +++ /dev/null @@ -1,104 +0,0 @@ - -/*************************************************************************\ -* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* - * Author: - * Jeffrey O. Hill - * johill@lanl.gov - */ - -#ifndef compilerDependencies_h -#define compilerDependencies_h - -/* - * This is an attempt to move all tests identifying what features a - * compiler supports into one file. - * - * Since this is a compiler, and not os dependent, issue then ifdefs - * are used. The ifdefs allow us to make the default assumption that - * standards incompliance issues will be fixed by future compiler - * releases. - */ - -#ifdef __cplusplus - -/* - * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete - * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification - */ - -#if defined ( _MSC_VER ) -# if _MSC_VER >= 1200 /* visual studio 6.0 or later */ -# define CXX_PLACEMENT_DELETE -# endif -# if _MSC_VER > 1300 /* some release after visual studio 7 we hope */ -# define CXX_THROW_SPECIFICATION -# endif -#elif defined ( __HP_aCC ) -# if _HP_aCC > 33300 -# define CXX_PLACEMENT_DELETE -# endif -# define CXX_THROW_SPECIFICATION -#elif defined ( __BORLANDC__ ) -# if __BORLANDC__ >= 0x600 -# define CXX_PLACEMENT_DELETE -# endif -# define CXX_THROW_SPECIFICATION -#elif defined ( __GNUC__ ) -# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 ) -# define CXX_THROW_SPECIFICATION -# endif -# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 ) -# define CXX_PLACEMENT_DELETE -# endif -#else -# define CXX_PLACEMENT_DELETE -# define CXX_THROW_SPECIFICATION -#endif - -/* - * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error )) - */ -#if defined ( CXX_THROW_SPECIFICATION ) -# define epicsThrows(X) throw X -#else -# define epicsThrows(X) -#endif - -/* - * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & )) - */ -#if defined ( CXX_PLACEMENT_DELETE ) -# define epicsPlacementDeleteOperator(X) void operator delete X; -#else -# define epicsPlacementDeleteOperator(X) -#endif - -#endif /* __cplusplus */ - -/* - * Enable format-string checking if possible - */ -#ifdef __GNUC__ -# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a))) -#else -# define EPICS_PRINTF_STYLE(f,a) -#endif - -/* - * Deprecation marker - */ -#ifdef __GNUC__ -# define EPICS_DEPRECATED __attribute__((deprecated)) -#else -# define EPICS_DEPRECATED -#endif - -#endif /* ifndef compilerDependencies_h */ diff --git a/src/libCom/osi/compiler/borland/compilerSpecific.h b/src/libCom/osi/compiler/borland/compilerSpecific.h new file mode 100644 index 000000000..9a86e1aae --- /dev/null +++ b/src/libCom/osi/compiler/borland/compilerSpecific.h @@ -0,0 +1,55 @@ + +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerSpecific_h +#define compilerSpecific_h + +#ifndef __BORLANDC__ +# error compiler/borland/compilerSpecific.h is only for use with the Borland compiler +#endif + +#ifdef __cplusplus + +/* + * in general we dont like ifdefs but they do allow us to check the + * compiler version and make the optimistic assumption that + * standards incompliance issues will be fixed by future compiler + * releases + */ + +/* + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification + */ +#if __BORLANDC__ >= 0x600 +# define CXX_PLACEMENT_DELETE +#endif + +#define CXX_THROW_SPECIFICATION + +#endif /* __cplusplus */ + +/* + * Enable format-string checking if possible + */ +#define EPICS_PRINTF_STYLE(f,a) + +/* + * Deprecation marker + */ +#define EPICS_DEPRECATED + +#endif /* ifndef compilerSpecific_h */ diff --git a/src/libCom/osi/compiler/clang/compilerSpecific.h b/src/libCom/osi/compiler/clang/compilerSpecific.h new file mode 100644 index 000000000..881c30f42 --- /dev/null +++ b/src/libCom/osi/compiler/clang/compilerSpecific.h @@ -0,0 +1,59 @@ + +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerSpecific_h +#define compilerSpecific_h + +#ifndef __clang__ +# error compiler/clang/compilerSpecific.h is only for use with the clang compiler +#endif + +/* + * WARNING: the current state of this file is only based on reading clang manuals + * and has not actually been tested with the compiler + */ +#pragma warning compiler/clang/compilerSpecific.h is based on reading the manual, but hasnt been tested with the clang compiler + +#ifdef __cplusplus + +/* + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification + */ +#define CXX_PLACEMENT_DELETE +#define CXX_THROW_SPECIFICATION + +#endif /* __cplusplus */ + +/* + * Enable format-string checking if possible + */ +#if __has_attribute(format) +# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a))) +#else +# define EPICS_PRINTF_STYLE +#endif + +/* + * Deprecation marker if possible + */ +#if __has_attribute(deprecated) +# define EPICS_DEPRECATED __attribute__((deprecated)) +#else +# define EPICS_DEPRECATED +#endif + +#endif /* ifndef compilerSpecific_h */ diff --git a/src/libCom/osi/compiler/default/compilerSpecific.h b/src/libCom/osi/compiler/default/compilerSpecific.h new file mode 100644 index 000000000..da2a21acc --- /dev/null +++ b/src/libCom/osi/compiler/default/compilerSpecific.h @@ -0,0 +1,45 @@ + +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerSpecific_h +#define compilerSpecific_h + +#ifdef __cplusplus + +/* + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification + * + * (our default guess is that the compiler implements the C++ 97 standard) + */ +#define CXX_THROW_SPECIFICATION +#define CXX_PLACEMENT_DELETE + +#endif /* __cplusplus */ + +/* + * Enable format-string checking if possible + * (our default guess is that the compiler doesnt implement non-standard extensions) + */ +#define EPICS_PRINTF_STYLE(f,a) + +/* + * Deprecation marker + * (our default guess is that the compiler doesnt implement non-standard extensions) + */ +#define EPICS_DEPRECATED + +#endif /* ifndef compilerSpecific_h */ diff --git a/src/libCom/osi/compiler/gcc/compilerSpecific.h b/src/libCom/osi/compiler/gcc/compilerSpecific.h new file mode 100644 index 000000000..f30b696b5 --- /dev/null +++ b/src/libCom/osi/compiler/gcc/compilerSpecific.h @@ -0,0 +1,59 @@ + +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerSpecific_h +#define compilerSpecific_h + +#ifndef __GNUC__ +# error compiler/gcc/compilerSpecific.h is only for use with the gnu compiler +#endif + +#ifdef __cplusplus + +/* + * in general we dont like ifdefs but they do allow us to check the + * compiler version and make the optimistic assumption that + * standards incompliance issues will be fixed by future compiler + * releases + */ + +/* + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification + */ + +#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 ) +# define CXX_THROW_SPECIFICATION +#endif + +#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 ) +# define CXX_PLACEMENT_DELETE +#endif + +#endif /* __cplusplus */ + +/* + * Enable format-string checking if possible + */ +#define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a))) + +/* + * Deprecation marker if possible + */ + +#define EPICS_DEPRECATED __attribute__((deprecated)) + +#endif /* ifndef compilerSpecific_h */ diff --git a/src/libCom/osi/compiler/gcc/epicsAtomicCD.h b/src/libCom/osi/compiler/gcc/epicsAtomicCD.h index 8b06bd7bb..7e961386a 100644 --- a/src/libCom/osi/compiler/gcc/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/gcc/epicsAtomicCD.h @@ -50,6 +50,8 @@ && GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T ) \ || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER +#define OSD_ATOMIC_INLINE_DEFINITION + #ifdef __cplusplus extern "C" { #endif @@ -120,11 +122,6 @@ OSD_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * #endif #else /* if GCC_ATOMIC_INTRINSICS_AVAIL */ - -# if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER && __i386 - /* 386 hardware is probably rare today even in embedded systems */ -# warning "this code will run much faster if specifying i486 or better" -# endif /* * not available as gcc intrinsics so we diff --git a/src/libCom/osi/compiler/msvc/compilerSpecific.h b/src/libCom/osi/compiler/msvc/compilerSpecific.h new file mode 100644 index 000000000..64ebf915f --- /dev/null +++ b/src/libCom/osi/compiler/msvc/compilerSpecific.h @@ -0,0 +1,57 @@ + +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerSpecific_h +#define compilerSpecific_h + +#ifndef _MSC_VER +# error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler +#endif + +#ifdef __cplusplus + +/* + * in general we dont like ifdefs but they do allow us to check the + * compiler version and make the optimistic assumption that + * standards incompliance issues will be fixed by future compiler + * releases + */ + +/* + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification + */ +#if _MSC_VER >= 1200 /* visual studio 6.0 or later */ +# define CXX_PLACEMENT_DELETE +#endif + +#if _MSC_VER > 1300 /* some release after visual studio 7 we hope */ +# define CXX_THROW_SPECIFICATION +#endif + +#endif /* __cplusplus */ + +/* + * Enable format-string checking if possible + */ +#define EPICS_PRINTF_STYLE(f,a) + +/* + * Deprecation marker + */ +#define EPICS_DEPRECATED + +#endif /* ifndef compilerSpecific_h */ diff --git a/src/libCom/osi/compiler/msvc/epicsAtomicCD.h b/src/libCom/osi/compiler/msvc/epicsAtomicCD.h index 4923664e7..fa3ba8a81 100644 --- a/src/libCom/osi/compiler/msvc/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/msvc/epicsAtomicCD.h @@ -66,6 +66,8 @@ # error unexpected target architecture, msvc version of epicsAtomicCD.h #endif +#define OSD_ATOMIC_INLINE_DEFINITION + /* * The windows doc appears to recommend defining InterlockedExchange * to be _InterlockedExchange to cause it to be an intrinsic, but that diff --git a/src/libCom/osi/compilerDependencies.h b/src/libCom/osi/compilerDependencies.h new file mode 100644 index 000000000..7f2acc699 --- /dev/null +++ b/src/libCom/osi/compilerDependencies.h @@ -0,0 +1,47 @@ + +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerDependencies_h +#define compilerDependencies_h + +#include "compilerSpecific.h" + +#ifdef __cplusplus + +/* + * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error )) + * + * Note: now a widely accepted concensus (ref Meyers and C++ faq) is that + * one should avoid using throw specifications in C++ code + */ +#if defined ( CXX_THROW_SPECIFICATION ) +# define epicsThrows(X) throw X +#else +# define epicsThrows(X) +#endif + +/* + * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & )) + */ +#if defined ( CXX_PLACEMENT_DELETE ) +# define epicsPlacementDeleteOperator(X) void operator delete X; +#else +# define epicsPlacementDeleteOperator(X) +#endif + +#endif /* __cplusplus */ + +#endif /* ifndef compilerDependencies_h */ diff --git a/src/libCom/osi/epicsAtomic.h b/src/libCom/osi/epicsAtomic.h index 586cb15c2..1a28622bf 100644 --- a/src/libCom/osi/epicsAtomic.h +++ b/src/libCom/osi/epicsAtomic.h @@ -81,25 +81,6 @@ epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTa EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ); -/* - * the following are, never inline and always synchronized by a global - * mutual exclusion lock, implementations of the epicsAtomicXxxx interface - * which may used to implement the epicsAtomicXxxx functions when - * more efficent primitives aren't available - */ -epicsShareFunc size_t epicsLockedIncrSizeT ( size_t * pTarget ); -epicsShareFunc size_t epicsLockedDecrSizeT ( size_t * pTarget ); -epicsShareFunc void epicsLockedSetSizeT ( size_t * pTarget, size_t newVal ); -epicsShareFunc void epicsLockedSetUIntT ( unsigned * pTarget, unsigned newVal ); -epicsShareFunc void epicsLockedSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newVal ); -epicsShareFunc size_t epicsLockedGetSizeT ( const size_t * pTarget ); -epicsShareFunc unsigned epicsLockedGetUIntT ( const unsigned * pTarget ); -epicsShareFunc EpicsAtomicPtrT epicsLockedGetPtrT ( const EpicsAtomicPtrT * pTarget ); -epicsShareFunc unsigned epicsLockedCmpAndSwapUIntT ( unsigned * pTarget, - unsigned oldval, unsigned newval ); -epicsShareFunc EpicsAtomicPtrT epicsLockedCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, - EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ); - #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/src/libCom/osi/epicsAtomicGuard.h b/src/libCom/osi/epicsAtomicGuard.h new file mode 100644 index 000000000..7e5cf5334 --- /dev/null +++ b/src/libCom/osi/epicsAtomicGuard.h @@ -0,0 +1,54 @@ + +/*************************************************************************\ +* Copyright (c) 2011 LANS LLC, as Operator of +* Los Alamos National Laboratory. +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef epicsAtomicGuard_h +#define epicsAtomicGuard_h + +// +// This header file is intended only for use with the epicsAtomicLocked +// header file. The intent is that an OS specific implementation of +// epicsAtomicOSD.cpp might first include this file, next implement +// AtomicGuard depending on os specific capabilities, and finally include +// the epicsAtomicLocked header file to define the various epicsAtomicXxxx +// functions. +// +// The AtomicGuard class is defined in a seperate header file +// from the epicsAtomicLocked header for two reasons. +// o First, it must be possible to have an inline definition of the +// AtomicGuard member functions, and that isnt possible if the +// epicsAtomicXxxx function definitions in the epicsAtomicLocked +// header file have already been seen by the translation unit. +// o Second, we need to enforce a uniform interface for all definitions +// of the the AtomicGuard constructor and destructor member functions +// requiring that no exception are thrown. This is because the +// epicsAtomicXxxx functions in the epicsAtomicLocked header file are +// directly callable by C code. +// +// The epicsAtomicXxxx functions in the epicsAtomicLocked do not pass +// any parameters to the AtomicGuard constructor, and therefore the lock +// used by AtomicGuard is restricted to be a global lock for the entire +// multithreaded executable. Therefore, AtomicGuard will typically +// reference some translation unit scope limited global variable in +// the anonymous namespace for implementation of the locking primitive. +// + +namespace { + struct AtomicGuard { + AtomicGuard () throw (); + ~AtomicGuard () throw (); + }; +} // end of anonymous namespace + +#endif // ifndef epicsAtomicGuard_h \ No newline at end of file diff --git a/src/libCom/osi/epicsAtomicLocked.cpp b/src/libCom/osi/epicsAtomicLocked.cpp deleted file mode 100644 index 42cbb33bd..000000000 --- a/src/libCom/osi/epicsAtomicLocked.cpp +++ /dev/null @@ -1,158 +0,0 @@ - -/*************************************************************************\ -* Copyright (c) 2011 LANS LLC, as Operator of -* Los Alamos National Laboratory. -* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne -* National Laboratory. -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* - * Author Jeffrey O. Hill - * johill@lanl.gov - * - * Provide a global mutex version of the atomic functions for when - * we dont have more efficent OS primitives or compiler intriniscs - * to use instead. - * - * We implement these mutex-based primitives upon the libCom private - * interface epicsMutexOsdXxxx because, in libCom, it is convenient - * to make this a standalone primitive upon which we can implement - * epicsMutex. - */ - -#define epicsExportSharedSymbols -#include "epicsAtomic.h" -#include "epicsThread.h" -#include "epicsMutex.h" - -namespace { - -class AtomicGuard { -public: - AtomicGuard (); - ~AtomicGuard (); -private: - static epicsMutexOSD * m_pMutex; - static epicsThreadOnceId m_onceFlag; - static void m_once ( void * ); -}; - -// -// c++ 0x specifies the behavior for concurrent -// access to block scope statics but some compiler -// writers, lacking clear guidance in the earlier -// c++ standards, curiously implement thread unsafe -// block static variables despite ensuring for -// proper multithreaded behavior for many other -// parst of the compiler infrastructure such as -// runtime support for exception handling -// -// since this is potentially used by the implementation -// of staticInstance we cant use it here and must use -// epicsThreadOnce despite its perfomance pentalty -// -// using epicsThreadOnce here (at this time) increases -// the overhead of AtomicGuard by as much as 100% -// -epicsMutexOSD * AtomicGuard :: m_pMutex = 0; -epicsThreadOnceId AtomicGuard :: m_onceFlag = EPICS_THREAD_ONCE_INIT; - -void AtomicGuard :: m_once ( void * ) -{ - m_pMutex = epicsMutexOsdCreate (); -} - -inline AtomicGuard :: AtomicGuard () -{ - - epicsThreadOnce ( & m_onceFlag, m_once, 0 ); - const int status = epicsMutexOsdLock ( m_pMutex ); - assert ( status == epicsMutexLockOK ); -} - -inline AtomicGuard :: ~AtomicGuard () -{ - epicsMutexOsdUnlock ( m_pMutex ); -} - -} // end of anonymous namespace - -extern "C" { - -size_t epicsLockedIncrSizeT ( size_t * pTarget ) -{ - AtomicGuard atomicGuard; - return ++(*pTarget); -} - -size_t epicsLockedDecrSizeT ( size_t * pTarget ) -{ - AtomicGuard atomicGuard; - return --(*pTarget); -} - -void epicsLockedSetSizeT ( size_t * pTarget, size_t newVal ) -{ - AtomicGuard atomicGuard; - *pTarget = newVal; -} - -void epicsLockedSetUIntT ( unsigned * pTarget, unsigned newVal ) -{ - AtomicGuard atomicGuard; - *pTarget = newVal; -} - -void epicsLockedSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newVal ) -{ - AtomicGuard atomicGuard; - *pTarget = newVal; -} - -unsigned epicsLockedGetUIntT ( const unsigned * pTarget ) -{ - AtomicGuard atomicGuard; - return *pTarget; -} - -size_t epicsLockedGetSizeT ( const size_t * pTarget ) -{ - AtomicGuard atomicGuard; - return *pTarget; -} - -EpicsAtomicPtrT epicsLockedGetPtrT ( const EpicsAtomicPtrT * pTarget ) -{ - AtomicGuard atomicGuard; - return *pTarget; -} - -unsigned epicsLockedCmpAndSwapUIntT ( unsigned * pTarget, - unsigned oldval, unsigned newval ) -{ - AtomicGuard atomicGuard; - const unsigned cur = *pTarget; - if ( cur == oldval ) { - *pTarget = newval; - } - return cur; -} - -EpicsAtomicPtrT epicsLockedCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, - EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval ) -{ - AtomicGuard atomicGuard; - const EpicsAtomicPtrT cur = *pTarget; - if ( cur == oldval ) { - *pTarget = newval; - } - return cur; -} - -} // end of extern "C" - - - - diff --git a/src/libCom/osi/epicsAtomicLocked.h b/src/libCom/osi/epicsAtomicLocked.h index 298dcc3dc..5f325e614 100644 --- a/src/libCom/osi/epicsAtomicLocked.h +++ b/src/libCom/osi/epicsAtomicLocked.h @@ -12,86 +12,108 @@ * Author Jeffrey O. Hill * johill@lanl.gov */ + +// +// The epicsAtomicXxxxx functions herein are implemented with C++ but directly +// callable by C code, and therefore they must not be instantiated inline. +// Therefore, this isnt a traditional header file because it has function +// definitions that are not inline, and must therefore be included by only +// one module in the executable - typically this is the epicsAtomicOSD +// c++ source file. These out-of-line function definitions are placed in a +// header file so that there is potential code reuse when instantiating for +// a specific OS. An alternative option would have been to place these +// function definitions in a OS type conditionally compiled source file +// but this wasnt done because I suspect that selecting the posix version +// would require a proliferation of "SRCS_XXXX += xxx.cpp" in the libCom +// Makefile for every variety of Unix (a maintenance headache when new +// varieties of UNIX are configured). +// +// Aee also the comments in epicsAtomicGuard header. +// #ifndef epicsAtomicLocked_h #define epicsAtomicLocked_h -#if defined ( OSD_ATOMIC_INLINE ) +#ifndef __cplusplus +# error epicsAtomicLocked.h is intended only for use only by C++ code +#endif + +#include "epicsAtomic.h" // always cross check the function prototypes +#include "epicsAtomicGuard.h" -#ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ -OSD_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) +size_t epicsAtomicIncrSizeT ( size_t * pTarget ) { - return epicsLockedIncrSizeT ( pTarget ); + AtomicGuard atomicGuard; + return ++(*pTarget); } -OSD_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) +size_t epicsAtomicDecrSizeT ( size_t * pTarget ) { - return epicsLockedDecrSizeT ( pTarget ); + AtomicGuard atomicGuard; + return --(*pTarget); } -OSD_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal ) +void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal ) { - epicsLockedSetSizeT ( pTarget, newVal ); + AtomicGuard atomicGuard; + *pTarget = newVal; } -OSD_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget ) +void epicsAtomicSetUIntT ( unsigned * pTarget, unsigned newVal ) { - return epicsLockedGetSizeT ( pTarget ); + AtomicGuard atomicGuard; + *pTarget = newVal; } -OSD_ATOMIC_INLINE unsigned epicsAtomicGetUIntT ( const unsigned * pTarget ) +void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newVal ) { - return epicsLockedGetUIntT ( pTarget ); + AtomicGuard atomicGuard; + *pTarget = newVal; } -OSD_ATOMIC_INLINE void epicsAtomicSetUIntT ( unsigned * pTarget, unsigned newVal ) +unsigned epicsAtomicGetUIntT ( const unsigned * pTarget ) { - epicsLockedSetUIntT ( pTarget, newVal ); + AtomicGuard atomicGuard; + return *pTarget; } -OSD_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newVal ) +size_t epicsAtomicGetSizeT ( const size_t * pTarget ) { - epicsLockedSetPtrT ( pTarget, newVal ); + AtomicGuard atomicGuard; + return *pTarget; } -OSD_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget ) +EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget ) { - return epicsLockedGetPtrT ( pTarget ); + AtomicGuard atomicGuard; + return *pTarget; } -OSD_ATOMIC_INLINE unsigned epicsAtomicCmpAndSwapUIntT ( unsigned * pTarget, - unsigned oldVal, unsigned newVal ) +unsigned epicsAtomicCmpAndSwapUIntT ( unsigned * pTarget, + unsigned oldval, unsigned newval ) { - return epicsLockedCmpAndSwapUIntT ( pTarget, oldVal, newVal ); + AtomicGuard atomicGuard; + const unsigned cur = *pTarget; + if ( cur == oldval ) { + *pTarget = newval; + } + return cur; } -OSD_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, - EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ) +EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, + EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval ) { - return epicsLockedCmpAndSwapPtrT ( pTarget, oldVal, newVal ); + AtomicGuard atomicGuard; + const EpicsAtomicPtrT cur = *pTarget; + if ( cur == oldval ) { + *pTarget = newval; + } + return cur; } -#ifdef __cplusplus -} /* end of extern "C" */ -#endif /* __cplusplus */ - -#else /* if defined ( OSD_ATOMIC_INLINE ) */ - -# define epicsAtomicIncrSizeT epicsLockedIncrSizeT -# define epicsAtomicDecrSizeT epicsLockedDecrSizeT -# define epicsAtomicSetSizeT epicsLockedSetSizeT -# define epicsAtomicSetUIntT epicsLockedSetUIntT -# define epicsAtomicSetPtrT epicsLockedSetPtrT -# define epicsAtomicGetSizeT epicsLockedGetSizeT -# define epicsAtomicGetUIntT epicsLockedGetUIntT -# define epicsAtomicGetPtrT epicsLockedGetPtrT -# define epicsAtomicCmpAndSwapUIntT epicsLockedCmpAndSwapUIntT -# define epicsAtomicCmpAndSwapPtrT epicsLockedCmpAndSwapPtrT - -#endif /* if defined ( OSD_ATOMIC_INLINE ) */ +} // end of extern "C" #endif /* epicsAtomicLocked_h */ diff --git a/src/libCom/osi/os/WIN32/epicsAtomicOSD.h b/src/libCom/osi/os/WIN32/epicsAtomicOSD.h index 3b3ab6942..bcf48facd 100644 --- a/src/libCom/osi/os/WIN32/epicsAtomicOSD.h +++ b/src/libCom/osi/os/WIN32/epicsAtomicOSD.h @@ -30,6 +30,8 @@ extern "C" { #endif /* __cplusplus */ +#define OSD_ATOMIC_INLINE_DEFINITION + /* * mingw doesnt currently provide MemoryBarrier * (this is mostly for testing purposes as the gnu diff --git a/src/libCom/osi/os/default/epicsAtomicOSD.cpp b/src/libCom/osi/os/default/epicsAtomicOSD.cpp new file mode 100644 index 000000000..ecb1ad7c9 --- /dev/null +++ b/src/libCom/osi/os/default/epicsAtomicOSD.cpp @@ -0,0 +1,26 @@ + +/*************************************************************************\ +* Copyright (c) 2011 LANS LLC, as Operator of +* Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author Jeffrey O. Hill + * johill@lanl.gov + */ + +#define epicsExportSharedSymbols +#include "epicsAtomic.h" + +// +// We need a default epicsAtopmicOSD.cpp which is empty for use when +// a compiler or inline OS specific implementation is provided. See +// "osi/os/posix/epicsAtomicOSD.cpp" for an example OS specific generic +// out-of-line implementation based on a mutex lock. +// +#if ! defined ( OSD_ATOMIC_INLINE_DEFINITION ) +# error the epicsAtomicXxxxx functions definitions are misssing +#endif + diff --git a/src/libCom/osi/os/default/epicsAtomicOSD.h b/src/libCom/osi/os/default/epicsAtomicOSD.h index 0b250495b..bf09ae083 100644 --- a/src/libCom/osi/os/default/epicsAtomicOSD.h +++ b/src/libCom/osi/os/default/epicsAtomicOSD.h @@ -16,6 +16,4 @@ #ifndef epicsAtomicOSD_h #define epicsAtomicOSD_h -#include "epicsAtomicLocked.h" - #endif /* epicsAtomicOSD_h */ diff --git a/src/libCom/osi/os/posix/epicsAtomicOSD.cpp b/src/libCom/osi/os/posix/epicsAtomicOSD.cpp new file mode 100644 index 000000000..e6cf40d22 --- /dev/null +++ b/src/libCom/osi/os/posix/epicsAtomicOSD.cpp @@ -0,0 +1,71 @@ + +/*************************************************************************\ +* Copyright (c) 2011 LANS LLC, as Operator of +* Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Author Jeffrey O. Hill + * johill@lanl.gov + * + * Provide a global mutex version of AtomicGuard on POSIX + * systems for when we dont have more efficent compiler or + * OS primitives intriniscs to use instead. + * + * We implement this mutex-based AtomicGuard primitive directly + * upon the standalone POSIX pthread library so that the epicsAtomic + * library can be used to implement other primitives such + * epicsThreadOnce. + * + * We use a static initialized pthread mutex to minimize code + * size, and are also optimistic that this can be more efficent + * than pthread_once. + */ + +#include + +#define epicsExportSharedSymbols +#include "epicsAtomic.h" + +// If we have an inline implementation then implement +// nothing that conflicts here +#if ! defined ( OSD_ATOMIC_INLINE_DEFINITION ) + +// get the interface for class AtomicGuard +#include "epicsAtomicGuard.h" + +namespace { + +// a statically initialized mutex doesnt need to be destroyed +static pthread_mutex_t AtomicGuard :: mutex = PTHREAD_MUTEX_INITIALIZER; + +inline AtomicGuard :: AtomicGuard () throw () +{ + unsigned countDown = 1000u; + while ( true ) { + status = pthread_mutex_lock ( & mutex ); + if ( status != EINTR ) break; + static const useconds_t retryDelayUSec = 100000; + usleep ( retryDelayUSec ); + countDown--; + assert ( countDown ); + } + assert ( status == 0 ); +} + +inline AtomicGuard :: ~AtomicGuard () throw () +{ + const int status = pthread_mutex_unlock ( & mutex ); + assert ( status == 0 ); +} + +} // end of namespace anonymous + +// Define the epicsAtomicXxxx functions out-of-line using this +// implementation of AtomicGuard. Note that this isnt a traditional +// c++ header file. +#include "epicsAtomicLocked.h" + +#endif // if ! defined ( #define OSD_ATOMIC_INLINE_DEFINITION ) diff --git a/src/libCom/osi/os/solaris/epicsAtomicOSD.h b/src/libCom/osi/os/solaris/epicsAtomicOSD.h index 542997ccf..48c95824a 100644 --- a/src/libCom/osi/os/solaris/epicsAtomicOSD.h +++ b/src/libCom/osi/os/solaris/epicsAtomicOSD.h @@ -29,6 +29,8 @@ #define __STDC_LIMIT_MACROS /* define SIZE_MAX for c++ */ #include +#define OSD_ATOMIC_INLINE_DEFINITION + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -97,10 +99,6 @@ OSD_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * p } /* end of extern "C" */ #endif /* __cplusplus */ -#else /* ifdef __SunOS_5_10 */ - -#include "epicsAtomicLocked.h" - #endif /* ifdef __SunOS_5_10 */ #endif /* if defined ( OSD_ATOMIC_INLINE ) */ diff --git a/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h b/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h index e71f6d9b6..b46c66436 100644 --- a/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h +++ b/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h @@ -28,6 +28,8 @@ #include #include + +#define OSD_ATOMIC_INLINE_DEFINITION #ifdef __cplusplus extern "C" {