Subject: |
[Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base |
From: |
Jeff Hill <[email protected]> |
To: |
[email protected] |
Date: |
Thu, 01 Sep 2011 00:23:30 -0000 |
Jeff Hill has proposed merging lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base with lp:~epics-core/epics-base/3.15-buildCompilerSpecific as a prerequisite.
Requested reviews:
EPICS Core Developers (epics-core)
For more details, see:
https://code.launchpad.net/~epics-core/epics-base/epicsR3.15-atomics/+merge/73613
This is my atomic set/get/incr/decr/add/sub/compare-and-swap library implemented currently for types size_t, int, and void * (no incr/decr/add/sub for void *).
I resubmitted the merge proposal so I could add a prerequisite branch.
I need to start merging other things for which this is a prerequisite.
The basic strategy is to look for a compiler intrinsic first, then an os specific primitive, and finally to fall back (on posix) to a global mutex.
I have tested this on (see epicsAtomicTest and epicsAtomicPerform in the libCom test directory):
windows32/msvc
windows32/gcc
windows64/msvc
cygwin32/gcc
vxWorks6.2/gcc
vxWorks6.8/gcc (but possibly issues with the test or test harness system - see the comments in the log)
linux32/gcc
I am having troubles building for solaris here due to old perl compatibility issues and also it maybe doesn't help that much because we don't have Solaris 5.10 (we are phasing out Solaris) and I wouldn't be able to test the os primitives (only the global lock version which has already been tested on Linux).
I suspect that RTEMS may just work because the same gcc compiler intrinsics will be used as linux.
--
https://code.launchpad.net/~epics-core/epics-base/epicsR3.15-atomics/+merge/73613
Your team EPICS Core Developers is requested to review the proposed merge of lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base.
=== modified file 'configure/CONFIG.gnuCommon'
--- configure/CONFIG.gnuCommon 2009-11-25 17:15:47 +0000
+++ configure/CONFIG.gnuCommon 2011-09-01 00:23:27 +0000
@@ -12,6 +12,8 @@
GNU = YES
+CMPLR_CLASS = gcc
+
GNU_BIN = $(GNU_DIR)/bin
GNU_LIB = $(GNU_DIR)/lib
=== modified file 'configure/CONFIG_COMMON'
--- configure/CONFIG_COMMON 2011-08-17 21:36:38 +0000
+++ configure/CONFIG_COMMON 2011-09-01 00:23:27 +0000
@@ -133,11 +133,14 @@
GENERIC_SRC_DIRS = .. $(SRC_DIRS)
OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
$(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default ))
-ALL_SRC_DIRS = $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
+CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
+ $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default ))
+ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
#--------------------------------------------------
# compile line include directories
INSTALL_INCLUDES += \
+ -I$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) \
-I$(INSTALL_INCLUDE)/os/$(OS_CLASS) \
-I$(INSTALL_INCLUDE)
SRC_INCLUDES = -I$(COMMON_DIR) $(addprefix -I, $(wildcard $(ALL_SRC_DIRS)))
@@ -379,25 +382,36 @@
#
# auto determine the directory paths that things are installed to
# RULES:
-# 1) found in any one of several os 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 paths
# => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS)
-# 2) not foundin (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
# build rules work on vpath
#
# These rules guarantee that the users include from
-# no more than two directories
+# no more than three directories
#
INSTALL_INC += $(foreach inc, $(INC), \
$(firstword \
+ $(CMPLR_INSTALL_INC) \
$(OS_INSTALL_INC) \
$(GENERIC_INSTALL_INC) \
$(GENERATED_INSTALL_INC) ) )
INSTALL_INC += $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INC_$(OS_CLASS)) )
#
+# Rule 0
+#
+CMPLR_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/, $(INSTALL_INC_jjj) )
+INSTALL_INC_jjj = $(foreach dir, $(CMPLR_SRC_DIRS), $(INSTALL_INC_iii) )
+INSTALL_INC_iii = $(subst $(dir)/, , $(INSTALL_INC_hhh) )
+INSTALL_INC_hhh = $(wildcard $(addsuffix /$(inc), $(dir)) )
+
+#
# Rule 1
#
OS_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INSTALL_INC_ggg) )
=== modified file 'configure/RULES_BUILD'
--- configure/RULES_BUILD 2010-12-20 15:48:12 +0000
+++ configure/RULES_BUILD 2011-09-01 00:23:27 +0000
@@ -408,7 +408,11 @@
@$(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)/% : %
+ $(ECHO) "Installing compiler dependent include file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
$(INSTALL_DOC)/%: %
=== modified file 'configure/os/CONFIG.solarisCommon.solarisCommon'
--- configure/os/CONFIG.solarisCommon.solarisCommon 2010-10-05 19:27:37 +0000
+++ configure/os/CONFIG.solarisCommon.solarisCommon 2011-09-01 00:23:27 +0000
@@ -7,6 +7,8 @@
# Sites may override these definitions in CONFIG_SITE.solaris-sparc.solaris-sparc
#-------------------------------------------------------
+CMPLR_CLASS = solStudio
+
SPARCWORKS = /opt/SUNWspro
GNU = NO
=== modified file 'configure/os/CONFIG.win32-x86.win32-x86'
--- configure/os/CONFIG.win32-x86.win32-x86 2011-08-17 21:36:38 +0000
+++ configure/os/CONFIG.win32-x86.win32-x86 2011-09-01 00:23:27 +0000
@@ -11,6 +11,8 @@
VALID_BUILDS = Host Ioc
+CMPLR_CLASS = msvc
+
# convert UNIX path to native path
PATH_FILTER = $(subst /,\\,$(1))
@@ -122,7 +124,7 @@
# /D_CRTDBG_MAP_ALLOC
# /RTCsu catch bugs occurring only in optimized code
# /DEPICS_FREELIST_DEBUG good for detecting mem mrg bugs
-OPT_CXXFLAGS_NO = /RTCsu /Zi
+OPT_CXXFLAGS_NO = /RTCsu /Zi
# specify object file name and location
OBJ_CXXFLAG = /Fo
=== modified file 'src/libCom/Makefile'
--- src/libCom/Makefile 2011-08-23 22:28:20 +0000
+++ src/libCom/Makefile 2011-09-01 00:23:27 +0000
@@ -9,6 +9,7 @@
TOP = ../..
include $(TOP)/configure/CONFIG
+<<<<<<< TREE
SRC = $(TOP)/src
LIBCOM = $(SRC)/libCom
@@ -38,6 +39,287 @@
include $(LIBCOM)/yacc/Makefile
# Library to build:
+=======
+LIBCOM = $(TOP)/src/libCom
+
+# Command-line input support
+epicsReadline_CFLAGS += -DEPICS_COMMANDLINE_LIBRARY=EPICS_COMMANDLINE_LIBRARY_$(COMMANDLINE_LIBRARY)
+epicsReadline_INCLUDES += $(INCLUDES_$(COMMANDLINE_LIBRARY))
+
+#POSIX thread priority scheduling flag
+THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
+osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
+
+#epicsVersion is created by this Makefile
+INC += epicsVersion.h
+
+SRC_DIRS += $(LIBCOM)/bucketLib
+INC += bucketLib.h
+SRCS += bucketLib.c
+
+SRC_DIRS += $(LIBCOM)/ring
+#following needed for locating epicsRingPointer.h and epicsRingBytes.h
+INC += epicsRingPointer.h
+INC += epicsRingBytes.h
+SRCS += epicsRingPointer.cpp
+SRCS += epicsRingBytes.c
+
+SRC_DIRS += $(LIBCOM)/calc
+INC += postfix.h
+SRCS += postfix.c
+SRCS += calcPerform.c
+
+SRC_DIRS += $(LIBCOM)/cvtFast
+INC += cvtFast.h
+SRCS += cvtFast.c
+
+# From cppStd
+SRC_DIRS += $(LIBCOM)/cppStd
+INC += epicsAlgorithm.h
+INC += epicsExcept.h
+INC += epicsMemory.h
+
+# From cxxTemplates
+SRC_DIRS += $(LIBCOM)/cxxTemplates
+INC += resourceLib.h
+INC += tsDLList.h
+INC += tsSLList.h
+INC += tsMinMax.h
+INC += tsBTree.h
+INC += tsFreeList.h
+INC += epicsSingleton.h
+INC += epicsGuard.h
+INC += epicsOnce.h
+SRCS += resourceLib.cpp
+SRCS += epicsOnce.cpp
+SRCS += epicsSingletonMutex.cpp
+
+SRC_DIRS += $(LIBCOM)/dbmf
+INC += dbmf.h
+SRCS += dbmf.c
+
+SRC_DIRS += $(LIBCOM)/ellLib
+INC += ellLib.h
+SRCS += ellLib.c
+
+SRC_DIRS += $(LIBCOM)/env
+INC += envDefs.h
+SRCS += envSubr.c
+SRCS += envData.c
+
+SRC_DIRS += $(LIBCOM)/error
+INC += epicsPrint.h
+INC += errMdef.h
+INC += errSymTbl.h
+INC += errlog.h
+INC += error.h
+SRCS += errlog.c
+SRCS += errSymLib.c
+SRCS += errSymTbl.c
+
+SRC_DIRS += $(LIBCOM)/fdmgr
+INC += fdManager.h
+INC += fdmgr.h
+SRCS += fdmgr.cpp
+SRCS += fdManager.cpp
+
+SRC_DIRS += $(LIBCOM)/freeList
+INC += freeList.h
+SRCS += freeListLib.c
+HTMLS += freeList/freeList.html
+
+SRC_DIRS += $(LIBCOM)/gpHash
+INC += gpHash.h
+SRCS += gpHashLib.c
+HTMLS += gpHash/gpHash.html
+
+SRC_DIRS += $(LIBCOM)/iocsh
+INC += iocsh.h
+INC += registry.h
+INC += libComRegister.h
+SRCS += iocsh.cpp
+SRCS += registry.c
+SRCS += libComRegister.c
+
+SRC_DIRS += $(LIBCOM)/logClient
+INC += iocLog.h
+INC += logClient.h
+SRCS += iocLog.c
+SRCS += logClient.c
+
+SRC_DIRS += $(LIBCOM)/macLib
+INC += macLib.h
+SRCS += macCore.c
+SRCS += macEnv.c
+SRCS += macUtil.c
+
+SRC_DIRS += $(LIBCOM)/misc
+INC += adjustment.h
+INC += cantProceed.h
+INC += dbDefs.h
+INC += epicsConvert.h
+INC += epicsExit.h
+INC += epicsStdlib.h
+INC += epicsString.h
+INC += epicsTypes.h
+INC += shareLib.h
+INC += epicsExport.h
+INC += unixFileName.h
+INC += locationException.h
+INC += ipAddrToAsciiAsynchronous.h
+INC += epicsUnitTest.h
+INC += testMain.h
+SRCS += aToIPAddr.c
+SRCS += adjustment.c
+SRCS += cantProceed.c
+SRCS += epicsConvert.c
+SRCS += epicsExit.c
+SRCS += epicsStdlib.c
+SRCS += epicsString.c
+SRCS += truncateFile.c
+SRCS += ipAddrToAsciiAsynchronous.cpp
+SRCS += epicsUnitTest.c
+
+# From osi
+SRC_DIRS += $(LIBCOM)/osi
+INC += osiFileName.h
+INC += osiSock.h
+INC += osdSock.h
+INC += epicsInterrupt.h
+INC += osdInterrupt.h
+
+INC += epicsMutex.h
+INC += osdMutex.h
+INC += epicsEvent.h
+INC += osdEvent.h
+INC += epicsMath.h
+INC += osdMessageQueue.h
+INC += osdStrtod.h
+
+INC += epicsAssert.h
+INC += epicsFindSymbol.h
+INC += osiPoolStatus.h
+INC += osdPoolStatus.h
+INC += osdThread.h
+
+INC += epicsThread.h
+INC += epicsTime.h
+INC += epicsGeneralTime.h
+INC += osdTime.h
+INC += generalTimeSup.h
+INC += osiClockTime.h
+INC += epicsSignal.h
+INC += osiProcess.h
+INC += osiUnistd.h
+INC += osiWireFormat.h
+INC += osdWireFormat.h
+INC += osdWireConfig.h
+INC += epicsAtomic.h
+INC += epicsAtomicCD.h
+INC += epicsAtomicOSD.h
+INC += epicsAtomicDefault.h
+INC += epicsEndian.h
+INC += epicsReadline.h
+INC += epicsMessageQueue.h
+INC += epicsStdio.h
+INC += epicsStdioRedirect.h
+INC += epicsGetopt.h
+
+INC += devLib.h
+INC += devLibVME.h
+INC += devLibVMEImpl.h
+INC += osdVME.h
+INC += compilerDependencies.h
+INC += compilerSpecific.h
+
+SRCS += epicsThread.cpp
+SRCS += epicsMutex.cpp
+SRCS += epicsEvent.cpp
+SRCS += epicsTime.cpp
+SRCS += epicsMessageQueue.cpp
+SRCS += epicsMath.cpp
+SRCS += epicsAtomicOSD.cpp
+
+SRCS += epicsGeneralTime.c
+SRCS += osiClockTime.c
+
+SRCS += osdSock.c
+SRCS += osdSockAddrReuse.cpp
+SRCS += osiSock.c
+SRCS += systemCallIntMech.cpp
+SRCS += epicsSocketConvertErrnoToString.cpp
+SRCS += osdAssert.c
+SRCS += osdFindSymbol.c
+SRCS += osdInterrupt.c
+SRCS += osdPoolStatus.c
+SRCS += osdSignal.cpp
+SRCS += osdEnv.c
+SRCS += epicsReadline.c
+SRCS += epicsTempFile.cpp
+SRCS += epicsStdio.c
+SRCS += osdStdio.c
+
+osdEnv_CFLAGS_WIN32= -U__STDC__
+
+SRCS += osdThread.c
+SRCS += osdMutex.c
+SRCS += osdEvent.c
+SRCS += osdTime.cpp
+SRCS += osdProcess.c
+SRCS += osdNetIntf.c
+SRCS += osdMessageQueue.c
+
+SRCS += devLibVME.c
+SRCS += devLibVMEOSD.c
+
+SRC_DIRS += $(LIBCOM)/taskwd
+INC += taskwd.h
+SRCS += taskwd.c
+
+SRC_DIRS += $(LIBCOM)/timer
+INC += epicsTimer.h
+SRCS += epicsTimer.cpp
+SRCS += timer.cpp
+SRCS += timerQueue.cpp
+SRCS += timerQueueActive.cpp
+SRCS += timerQueueActiveMgr.cpp
+SRCS += timerQueuePassive.cpp
+
+#tsDefs contains R3.13 compatibility tsStamp code
+SRC_DIRS += $(LIBCOM)/tsDefs
+INC += tsDefs.h
+SRCS += tsDefs.c
+
+# Time providers, in osi
+SRCS_vxWorks += osiNTPTime.c
+SRCS_RTEMS += osiNTPTime.c
+
+# These files are in osi/os/vxWorks
+# Special reboot hook
+SRCS_vxWorks += atReboot.cpp
+# For old vxWorks applications
+INC_vxWorks += camacLib.h
+INC_vxWorks += epicsDynLink.h
+INC_vxWorks += module_types.h
+INC_vxWorks += task_params.h
+SRCS_vxWorks += epicsDynLink.c
+SRCS_vxWorks += veclist.c
+SRCS_vxWorks += logMsgToErrlog.cpp
+
+#This forces the vxWorks compatibility stuff to be loaded
+OBJS_vxWorks = vxComLibrary
+
+# These files are in osi/os/WIN32
+INC_WIN32 += epicsAtomicMS.h
+SRCS_WIN32 += epicsGetopt.c
+SRCS_WIN32 += setThreadName.cpp
+#SRCS_WIN32 += dllmain.cpp
+SRCS_WIN32 += forceBadAllocException.cpp
+
+# Library to build:
+# lib$(LIBRARY).a or ..dll/..exp/..lib
+#
+>>>>>>> MERGE-SOURCE
LIBRARY=Com
Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
=== removed file 'src/libCom/misc/compilerDependencies.h'
--- src/libCom/misc/compilerDependencies.h 2011-06-20 18:52:32 +0000
+++ src/libCom/misc/compilerDependencies.h 1970-01-01 00:00:00 +0000
@@ -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
- * [email protected]
- */
-
-#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
- */
-#if defined( __GNUC__ ) && (__GNUC__ > 2)
-# define EPICS_DEPRECATED __attribute__((deprecated))
-#else
-# define EPICS_DEPRECATED
-#endif
-
-#endif /* ifndef compilerDependencies_h */
=== added directory 'src/libCom/osi/compiler'
=== added directory 'src/libCom/osi/compiler/borland'
=== added file 'src/libCom/osi/compiler/borland/compilerSpecific.h'
--- src/libCom/osi/compiler/borland/compilerSpecific.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/borland/compilerSpecific.h 2011-09-01 00:23:27 +0000
@@ -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
+ * [email protected]
+ */
+
+#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 */
=== added directory 'src/libCom/osi/compiler/clang'
=== added file 'src/libCom/osi/compiler/clang/compilerSpecific.h'
--- src/libCom/osi/compiler/clang/compilerSpecific.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/clang/compilerSpecific.h 2011-09-01 00:23:27 +0000
@@ -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
+ * [email protected]
+ */
+
+#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 */
=== added file 'src/libCom/osi/compiler/clang/epicsAtomicCD.h'
--- src/libCom/osi/compiler/clang/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/clang/epicsAtomicCD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,27 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#if defined ( __cplusplus )
+# define EPICS_ATOMIC_INLINE inline
+#else
+# define EPICS_ATOMIC_INLINE __inline__
+#endif
+
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */
=== added directory 'src/libCom/osi/compiler/default'
=== added file 'src/libCom/osi/compiler/default/compilerSpecific.h'
--- src/libCom/osi/compiler/default/compilerSpecific.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/default/compilerSpecific.h 2011-09-01 00:23:27 +0000
@@ -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
+ * [email protected]
+ */
+
+#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 */
=== added file 'src/libCom/osi/compiler/default/epicsAtomicCD.h'
--- src/libCom/osi/compiler/default/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/default/epicsAtomicCD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,25 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus )
+# define EPICS_ATOMIC_INLINE inline
+#endif
+
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */
=== added directory 'src/libCom/osi/compiler/gcc'
=== added file 'src/libCom/osi/compiler/gcc/compilerSpecific.h'
--- src/libCom/osi/compiler/gcc/compilerSpecific.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/gcc/compilerSpecific.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,62 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#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
+ */
+#if (__GNUC__ > 2)
+# define EPICS_DEPRECATED __attribute__((deprecated))
+#else
+# define EPICS_DEPRECATED
+#endif
+
+#endif /* ifndef compilerSpecific_h */
=== added file 'src/libCom/osi/compiler/gcc/epicsAtomicCD.h'
--- src/libCom/osi/compiler/gcc/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/gcc/epicsAtomicCD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,172 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#ifndef __GNUC__
+# error this header is only for use with the gnu compiler
+#endif
+
+#define EPICS_ATOMIC_INLINE __inline__
+
+#define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
+#define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
+
+#define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
+ GCC_ATOMIC_CONCAT ( \
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
+ __SIZEOF_INT__ )
+
+#define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
+ GCC_ATOMIC_CONCAT ( \
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
+ __SIZEOF_SIZE_T__ )
+
+#define GCC_ATOMIC_INTRINSICS_MIN_X86 \
+ ( defined ( __i486 ) || defined ( __pentium ) || \
+ defined ( __pentiumpro ) || defined ( __MMX__ ) )
+
+#define GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER \
+ ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 )
+
+#define GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER \
+ ( GCC_ATOMIC_INTRINSICS_MIN_X86 && \
+ GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * We are optimistic that __sync_synchronize is implemented
+ * in all version four gcc invarient of target. The gnu doc
+ * seems to say that when not supported by architecture a call
+ * to an external function is generated but in practice
+ * this isnt the case for some of the atomic intrinsics, and
+ * so there is an undefined symbol. So far we have not seen
+ * that with __sync_synchronize, but we can only guess based
+ * on experimental evidence.
+ *
+ * For example we know that when generating object code for
+ * 386 most of the atomic instrinsics are not present and
+ * we see undefined symbols with mingw, but we dont have
+ * troubles with __sync_synchronize.
+ */
+#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
+{
+ __sync_synchronize ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
+{
+ __sync_synchronize ();
+}
+#endif
+
+#endif /* if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER */
+
+#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
+ || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
+
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+ return __sync_add_and_fetch ( pTarget, 1 );
+}
+
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+ return __sync_sub_and_fetch ( pTarget, 1 );
+}
+
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+ return __sync_add_and_fetch ( pTarget, delta );
+}
+
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
+ int oldVal, int newVal )
+{
+ return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
+}
+
+#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T */
+
+#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
+ || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
+
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+ return __sync_add_and_fetch ( pTarget, 1u );
+}
+
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+ return __sync_sub_and_fetch ( pTarget, 1u );
+}
+
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+ return __sync_add_and_fetch ( pTarget, delta );
+}
+
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+ return __sync_sub_and_fetch ( pTarget, delta );
+}
+
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
+ size_t oldVal, size_t newVal )
+{
+ return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
+}
+
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
+ EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+ return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
+}
+
+#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T */
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+/*
+ * if currently unavailable as gcc intrinsics we
+ * will try for an os specific inline solution
+ */
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */
=== added directory 'src/libCom/osi/compiler/msvc'
=== added file 'src/libCom/osi/compiler/msvc/compilerSpecific.h'
--- src/libCom/osi/compiler/msvc/compilerSpecific.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/msvc/compilerSpecific.h 2011-09-01 00:23:27 +0000
@@ -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
+ * [email protected]
+ */
+
+#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 */
=== added file 'src/libCom/osi/compiler/msvc/epicsAtomicCD.h'
--- src/libCom/osi/compiler/msvc/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/msvc/epicsAtomicCD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,124 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#include "epicsAssert.h"
+
+#ifndef _MSC_VER
+# error this header file is only for use with with the Microsoft Compiler
+#endif
+
+#ifdef _MSC_EXTENSIONS
+
+#include <intrin.h>
+
+#if _MSC_VER >= 1200
+# define EPICS_ATOMIC_INLINE __forceinline
+#else
+# define EPICS_ATOMIC_INLINE __inline
+#endif
+
+#if defined ( _M_IX86 )
+# pragma warning( push )
+# pragma warning( disable : 4793 )
+ EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
+ {
+ long fence;
+ __asm { xchg fence, eax }
+ }
+# pragma warning( pop )
+#elif defined ( _M_X64 )
+# define MS_ATOMIC_64
+# pragma intrinsic ( __faststorefence )
+ EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
+ {
+ __faststorefence ();
+ }
+#elif defined ( _M_IA64 )
+# define MS_ATOMIC_64
+# pragma intrinsic ( __mf )
+ EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
+ {
+ __mf ();
+ }
+#else
+# error unexpected target architecture, msvc version of epicsAtomicCD.h
+#endif
+
+/*
+ * The windows doc appears to recommend defining InterlockedExchange
+ * to be _InterlockedExchange to cause it to be an intrinsic, but that
+ * creates issues when later, in a windows os specific header, we include
+ * windows.h. Therefore, we except some code duplication between the msvc
+ * csAtomic.h and win32 osdAtomic.h to avoid problems, and to keep the
+ * os specific windows.h header file out of the msvc cdAtomic.h
+ */
+#define MS_LONG long
+#define MS_InterlockedExchange _InterlockedExchange
+#define MS_InterlockedCompareExchange _InterlockedCompareExchange
+#define MS_InterlockedIncrement _InterlockedIncrement
+#define MS_InterlockedDecrement _InterlockedDecrement
+#define MS_InterlockedExchange _InterlockedExchange
+#define MS_InterlockedExchangeAdd _InterlockedExchangeAdd
+#if defined ( MS_ATOMIC_64 )
+# define MS_LONGLONG long long
+# define MS_InterlockedIncrement64 _InterlockedIncrement64
+# define MS_InterlockedDecrement64 _InterlockedDecrement64
+# define MS_InterlockedExchange64 _InterlockedExchange64
+# define MS_InterlockedExchangeAdd64 _InterlockedExchangeAdd64
+# define MS_InterlockedCompareExchange64 _InterlockedCompareExchange64
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
+{
+ epicsAtomicMemoryBarrier ();
+}
+
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
+{
+ epicsAtomicMemoryBarrier ();
+}
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#include "epicsAtomicMS.h"
+#include "epicsAtomicDefault.h"
+
+#else /* ifdef _MSC_EXTENSIONS */
+
+#if defined ( __cplusplus )
+# define EPICS_ATOMIC_INLINE inline
+#endif
+
+/*
+ * if unavailable as an intrinsic we will try
+ * for os specific solution
+ */
+#include "epicsAtomicOSD.h"
+
+#endif /* ifdef _MSC_EXTENSIONS */
+
+#endif /* epicsAtomicCD_h */
+
=== added directory 'src/libCom/osi/compiler/solStudio'
=== added file 'src/libCom/osi/compiler/solStudio/epicsAtomicCD.h'
--- src/libCom/osi/compiler/solStudio/epicsAtomicCD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compiler/solStudio/epicsAtomicCD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,27 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicCD_h
+#define epicsAtomicCD_h
+
+#if defined ( __cplusplus )
+# define EPICS_ATOMIC_INLINE inline
+#else
+# define EPICS_ATOMIC_INLINE __inline
+#endif
+
+#include "epicsAtomicOSD.h"
+
+#endif /* epicsAtomicCD_h */
=== added file 'src/libCom/osi/compilerDependencies.h'
--- src/libCom/osi/compilerDependencies.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/compilerDependencies.h 2011-09-01 00:23:27 +0000
@@ -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
+ * [email protected]
+ */
+
+#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 */
=== added file 'src/libCom/osi/epicsAtomic.h'
--- src/libCom/osi/epicsAtomic.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/epicsAtomic.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,237 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomic_h
+#define epicsAtomic_h
+
+#include <stdlib.h> /* define size_t */
+
+#include "shareLib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void * EpicsAtomicPtrT;
+
+/* load target into cache */
+epicsShareFunc void epicsAtomicReadMemoryBarrier ();
+
+/* push cache version of target into target */
+epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, add one to target, flush cache
+ * to target, allow other smp processors to access the target,
+ * return new value of target as modified by this operation
+ */
+epicsShareFunc size_t epicsAtomicIncrSizeT ( size_t * pTarget );
+epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget );
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, subtract one from target, flush cache
+ * to target, allow out other smp processors to access the target,
+ * return new value of target as modified by this operation
+ */
+epicsShareFunc size_t epicsAtomicDecrSizeT ( size_t * pTarget );
+epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget );
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, add/sub delta to/from target, flush cache
+ * to target, allow other smp processors to access the target,
+ * return new value of target as modified by this operation
+ */
+epicsShareFunc size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta );
+epicsShareFunc size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta );
+epicsShareFunc int epicsAtomicAddIntT ( int * pTarget, int delta );
+
+/*
+ * set cache version of target, flush cache to target
+ */
+epicsShareFunc void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue );
+epicsShareFunc void epicsAtomicSetIntT ( int * pTarget, int newValue );
+epicsShareFunc void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue );
+
+/*
+ * fetch target into cache, return new value of target
+ */
+epicsShareFunc size_t epicsAtomicGetSizeT ( const size_t * pTarget );
+epicsShareFunc int epicsAtomicGetIntT ( const int * pTarget );
+epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget );
+
+/*
+ * lock out other smp processors from accessing the target,
+ * load target into cache, if target is equal to oldVal set target
+ * to newVal, flush cache to target, allow other smp processors
+ * to access the target, return the original value stored in the
+ * target
+ */
+epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
+ size_t oldVal, size_t newVal );
+epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget,
+ int oldVal, int newVal );
+epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
+ EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldVal,
+ EpicsAtomicPtrT newVal );
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+/*
+ * options for inline compiler instrinsic or os specific
+ * implementations of the above function prototypes
+ *
+ * its importnat for certaiin compiler to define the
+ * inline functions before they get used in the c++
+ * code below
+ */
+#include "epicsAtomicCD.h"
+
+#ifdef __cplusplus
+
+namespace epics {
+namespace atomic {
+
+/*
+ * overloaded c++ interface
+ */
+epicsShareFunc size_t increment ( size_t & v );
+epicsShareFunc int increment ( int & v );
+epicsShareFunc size_t decrement ( size_t & v );
+epicsShareFunc int decrement ( int & v );
+epicsShareFunc size_t add ( size_t & v, size_t delta );
+epicsShareFunc int add ( int & v, int delta );
+epicsShareFunc size_t subtract ( size_t & v, size_t delta );
+epicsShareFunc int subtract ( int & v, int delta );
+epicsShareFunc void set ( size_t & v , size_t newValue );
+epicsShareFunc void set ( int & v, int newValue );
+epicsShareFunc void set ( EpicsAtomicPtrT & v,
+ EpicsAtomicPtrT newValue );
+epicsShareFunc size_t get ( const size_t & v );
+epicsShareFunc int get ( const int & v );
+epicsShareFunc EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v );
+epicsShareFunc size_t compareAndSwap ( size_t & v, size_t oldVal,
+ size_t newVal );
+epicsShareFunc int compareAndSwap ( int & v, int oldVal, int newVal );
+epicsShareFunc EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
+ EpicsAtomicPtrT oldVal,
+ EpicsAtomicPtrT newVal );
+
+/************* incr ***************/
+inline size_t increment ( size_t & v )
+{
+ return epicsAtomicIncrSizeT ( & v );
+}
+
+inline int increment ( int & v )
+{
+ return epicsAtomicIncrIntT ( & v );
+}
+
+/************* decr ***************/
+inline size_t decrement ( size_t & v )
+{
+ return epicsAtomicDecrSizeT ( & v );
+}
+
+inline int decrement ( int & v )
+{
+ return epicsAtomicDecrIntT ( & v );
+}
+
+/************* add ***************/
+inline size_t add ( size_t & v, size_t delta )
+{
+ return epicsAtomicAddSizeT ( & v, delta );
+}
+
+inline int add ( int & v, int delta )
+{
+ return epicsAtomicAddIntT ( & v, delta );
+}
+
+/************* sub ***************/
+inline size_t subtract ( size_t & v, size_t delta )
+{
+ return epicsAtomicSubSizeT ( & v, delta );
+}
+
+inline int subtract ( int & v, int delta )
+{
+ return epicsAtomicAddIntT ( & v, -delta );
+}
+
+/************* set ***************/
+inline void set ( size_t & v , size_t newValue )
+{
+ epicsAtomicSetSizeT ( & v, newValue );
+}
+
+inline void set ( int & v, int newValue )
+{
+ epicsAtomicSetIntT ( & v, newValue );
+}
+
+inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue )
+{
+ epicsAtomicSetPtrT ( & v, newValue );
+}
+
+/************* get ***************/
+inline size_t get ( const size_t & v )
+{
+ return epicsAtomicGetSizeT ( & v );
+}
+
+inline int get ( const int & v )
+{
+ return epicsAtomicGetIntT ( & v );
+}
+
+inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v )
+{
+ return epicsAtomicGetPtrT ( & v );
+}
+
+/************* cas ***************/
+inline size_t compareAndSwap ( size_t & v,
+ size_t oldVal, size_t newVal )
+{
+ return epicsAtomicCmpAndSwapSizeT ( & v, oldVal, newVal );
+}
+
+inline int compareAndSwap ( int & v, int oldVal, int newVal )
+{
+ return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal );
+}
+
+inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
+ EpicsAtomicPtrT oldVal,
+ EpicsAtomicPtrT newVal )
+{
+ return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal );
+}
+
+} /* end of namespace atomic */
+} /* end of namespace epics */
+
+#endif /* ifdef __cplusplus */
+
+#endif /* epicsAtomic_h */
=== added file 'src/libCom/osi/epicsAtomicDefault.h'
--- src/libCom/osi/epicsAtomicDefault.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/epicsAtomicDefault.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,235 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicDefault_h
+#define epicsAtomicDefault_h
+
+/*
+ * EPICS_ATOMIC_INLINE might be defined, but empty for an out-of-line
+ * instantiation
+ */
+#ifdef EPICS_ATOMIC_INLINE
+
+#ifdef __cpluplus
+extern "C" {
+#endif
+
+/*
+ * struct EpicsAtomicLockKey;
+ * epicsShareFunc void epicsAtomicReadMemoryBarrier ();
+ * epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
+ * epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
+ * epicsShareFunc void epicsAtomicUnock ( struct EpicsAtomicLockKey * );
+ */
+
+/*
+ * incr
+ */
+#ifndef EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const int result = ++(*pTarget);
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const size_t result = ++(*pTarget);
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+/*
+ * decr
+ */
+#ifndef EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const int result = --(*pTarget);
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const size_t result = --(*pTarget);
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+/*
+ * add/sub
+ */
+#ifndef EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const int result = *pTarget += delta;
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const size_t result = *pTarget += delta;
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const size_t result = *pTarget -= delta;
+ epicsAtomicUnlock ( & key );
+ return result;
+}
+#endif
+
+/*
+ * set
+ */
+#ifndef EPICS_ATOMIC_SET_INTT
+EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newVal )
+{
+ *pTarget = newVal;
+ epicsAtomicWriteMemoryBarrier ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SET_SIZET
+EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal )
+{
+ *pTarget = newVal;
+ epicsAtomicWriteMemoryBarrier ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SET_PTRT
+EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT newVal )
+{
+ *pTarget = newVal;
+ epicsAtomicWriteMemoryBarrier ();
+}
+#endif
+
+/*
+ * get
+ */
+#ifndef EPICS_ATOMIC_GET_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget )
+{
+ epicsAtomicReadMemoryBarrier ();
+ return *pTarget;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_GET_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget )
+{
+ epicsAtomicReadMemoryBarrier ();
+ return *pTarget;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_GET_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT
+ epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget )
+{
+ epicsAtomicReadMemoryBarrier ();
+ return *pTarget;
+}
+#endif
+
+/*
+ * cmp and swap
+ */
+#ifndef EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldval, int newval )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const int cur = *pTarget;
+ if ( cur == oldval ) {
+ *pTarget = newval;
+ }
+ epicsAtomicUnlock ( & key );
+ return cur;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
+ size_t oldval, size_t newval )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const size_t cur = *pTarget;
+ if ( cur == oldval ) {
+ *pTarget = newval;
+ }
+ epicsAtomicUnlock ( & key );
+ return cur;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
+ EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval )
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ const EpicsAtomicPtrT cur = *pTarget;
+ if ( cur == oldval ) {
+ *pTarget = newval;
+ }
+ epicsAtomicUnlock ( & key );
+ return cur;
+}
+#endif
+
+#ifdef __cpluplus
+} /* end of extern "C" */
+#endif
+
+#endif /* EPICS_ATOMIC_INLINE */
+
+#endif /* epicsAtomicDefault_h */
+
+
=== added file 'src/libCom/osi/os/WIN32/epicsAtomicMS.h'
--- src/libCom/osi/os/WIN32/epicsAtomicMS.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/WIN32/epicsAtomicMS.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,222 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicMS_h
+#define epicsAtomicMS_h
+
+#include "epicsAssert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_INCR_INTT
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+ MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
+ return MS_InterlockedIncrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_INTT
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ return MS_InterlockedDecrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_INTT
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ /* we dont use InterlockedAdd because only latest windows is supported */
+ return delta + ( int ) MS_InterlockedExchangeAdd ( pTarg,
+ ( MS_LONG ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_INTT
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
+ int oldVal, int newVal )
+{
+ STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ return (int) MS_InterlockedCompareExchange ( pTarg,
+ (MS_LONG) newVal, (MS_LONG) oldVal );
+}
+#endif
+
+#if ! defined ( MS_ATOMIC_64 )
+
+/*
+ * necessary for next three functions
+ *
+ * looking at the MS documentation it appears that they will
+ * keep type long the same size as an int on 64 bit builds
+ */
+STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( size_t ) );
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+ MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
+ return MS_InterlockedIncrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ return MS_InterlockedDecrement ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
+ size_t delta )
+{
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ /* we dont use InterlockedAdd because only latest windows is supported */
+ return delta + ( size_t ) MS_InterlockedExchangeAdd ( pTarg,
+ ( MS_LONG ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ MS_LONG ldelta = (MS_LONG) delta;
+ /* we dont use InterlockedAdd because only latest windows is supported */
+ return ( ( size_t ) MS_InterlockedExchangeAdd ( pTarg, -ldelta ) ) - delta;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT (
+ size_t * pTarget,
+ size_t oldVal, size_t newVal )
+{
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ return (size_t) MS_InterlockedCompareExchange ( pTarg,
+ (MS_LONG) newVal, (MS_LONG) oldVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
+ EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+ MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
+ return (EpicsAtomicPtrT) MS_InterlockedCompareExchange ( pTarg,
+ (MS_LONG) newVal, (MS_LONG) oldVal );
+}
+#endif
+
+#else /* ! MS_ATOMIC_64 */
+
+/*
+ * necessary for next three functions
+ */
+STATIC_ASSERT ( sizeof ( MS_LONGLONG ) == sizeof ( size_t ) );
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) pTarget;
+ return ( size_t ) MS_InterlockedIncrement64 ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+ return ( size_t ) MS_InterlockedDecrement64 ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+ /* we dont use InterlockedAdd64 because only latest windows is supported */
+ return delta + ( size_t ) MS_InterlockedExchangeAdd64 ( pTarg,
+ ( MS_LONGLONG ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+ MS_LONGLONG ldelta = (MS_LONGLONG) delta;
+ /* we dont use InterlockedAdd64 because only latest windows is supported */
+ return (( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, -ldelta )) - delta;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
+ size_t oldVal, size_t newVal )
+{
+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+ return (size_t) MS_InterlockedCompareExchange64 ( pTarg,
+ (MS_LONGLONG) newVal,
+ (MS_LONGLONG) oldVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
+ EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+ MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
+ return (EpicsAtomicPtrT) MS_InterlockedCompareExchange64 ( pTarg,
+ (MS_LONGLONG) newVal, (MS_LONGLONG) oldVal );
+}
+#endif
+
+#endif /* ! MS_ATOMIC_64 */
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* ifdef epicsAtomicMS_h */
+
=== added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp'
--- src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp 2011-09-01 00:23:27 +0000
@@ -0,0 +1,22 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#define epicsExportSharedSymbols
+#include "epicsAtomic.h"
+
+// if the compiler is unable to inline then instantiate out-of-line
+#ifndef EPICS_ATOMIC_INLINE
+#define EPICS_ATOMIC_INLINE
+#include "epicsAtomic.h"
+#endif
+
=== added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.h'
--- src/libCom/osi/os/WIN32/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/WIN32/epicsAtomicOSD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,49 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+#define VC_EXTRALEAN
+#define STRICT
+#include "windows.h"
+
+#if defined ( _WIN64 )
+# define MS_ATOMIC_64
+#endif
+
+#define MS_LONG LONG
+#define MS_InterlockedExchange InterlockedExchange
+#define MS_InterlockedCompareExchange InterlockedCompareExchange
+#define MS_InterlockedIncrement InterlockedIncrement
+#define MS_InterlockedDecrement InterlockedDecrement
+#define MS_InterlockedExchange InterlockedExchange
+#define MS_InterlockedExchangeAdd InterlockedExchangeAdd
+#if defined ( MS_ATOMIC_64 )
+# define MS_LONGLONG LONGLONG
+# define MS_InterlockedIncrement64 InterlockedIncrement64
+# define MS_InterlockedDecrement64 InterlockedDecrement64
+# define MS_InterlockedExchange64 InterlockedExchange64
+# define MS_InterlockedExchangeAdd64 InterlockedExchangeAdd64
+# define MS_InterlockedCompareExchange InterlockedCompareExchange64
+#endif
+
+#ifdef EPICS_ATOMIC_INLINE
+# include "epicsAtomicMS.h"
+# include "epicsAtomicDefault.h"
+#endif
+
+#endif /* epicsAtomicOSD_h */
+
=== added file 'src/libCom/osi/os/posix/epicsAtomicOSD.cpp'
--- src/libCom/osi/os/posix/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/posix/epicsAtomicOSD.cpp 2011-09-01 00:23:27 +0000
@@ -0,0 +1,108 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#define epicsExportSharedSymbols
+#include "epicsAtomic.h"
+
+// if the compiler is unable to inline then instantiate out-of-line
+#ifndef EPICS_ATOMIC_INLINE
+#define EPICS_ATOMIC_INLINE
+#include "epicsAtomic.h"
+#endif
+
+/* Authors: Jeffrey O. Hill */
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#define epicsExportSharedSymbols
+#include "epicsAssert.h"
+
+// if the compiler is unable to inline then instantiate out-of-line
+#ifndef EPICS_ATOMIC_INLINE
+#define EPICS_ATOMIC_INLINE
+#include "epicsAtomic.h"
+#endif
+
+#ifndef EPICS_ATOMIC_LOCK
+
+/*
+ * Slow, but probably correct on all systems.
+ * Useful only if something more efficent isnt
+ * provided based on knowledge of the compiler
+ * or OS
+ *
+ * A statically initialized pthread mutex doesnt
+ * need to be destroyed
+ *
+ * !!!!!
+ * !!!!! WARNING
+ * !!!!!
+ * !!!!! Do not use this implementation on systems where
+ * !!!!! code runs at interrupt context. If so, then
+ * !!!!! an implementation must be provided that is based
+ * !!!!! on a compiler intrinsic or an interrpt lock and or
+ * !!!!! a spin lock primitive
+ * !!!!!
+ */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void epicsAtomicLock ( EpicsAtomicLockKey * )
+{
+ unsigned countDown = 1000u;
+ int status;
+ while ( true ) {
+ status = pthread_mutex_lock ( & mutex );
+ if ( status == 0 ) return;
+ assert ( status == EINTR );
+ static const useconds_t retryDelayUSec = 100000;
+ usleep ( retryDelayUSec );
+ countDown--;
+ assert ( countDown );
+ }
+}
+
+void epicsAtomicUnlock ( EpicsAtomicLockKey * )
+{
+ const int status = pthread_mutex_unlock ( & mutex );
+ assert ( status == 0 );
+}
+
+#endif // ifndef EPICS_ATOMIC_LOCK
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+// Slow, but probably correct on all systems.
+// Useful only if something more efficent isnt
+// provided based on knowledge of the compiler
+// or OS
+void epicsAtomicReadMemoryBarrier ()
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ epicsAtomicUnlock ( & key );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+// Slow, but probably correct on all systems.
+// Useful only if something more efficent isnt
+// provided based on knowledge of the compiler
+// or OS
+void epicsAtomicWriteMemoryBarrier ()
+{
+ EpicsAtomicLockKey key;
+ epicsAtomicLock ( & key );
+ epicsAtomicUnlock ( & key );
+}
+#endif
+
=== added file 'src/libCom/osi/os/posix/epicsAtomicOSD.h'
--- src/libCom/osi/os/posix/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/posix/epicsAtomicOSD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,32 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+struct EpicsAtomicLockKey {};
+epicsShareFunc void epicsAtomicReadMemoryBarrier ();
+epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
+epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
+epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * );
+
+#ifdef EPICS_ATOMIC_INLINE
+
+#include "epicsAtomicDefault.h"
+
+#endif /* ifdef EPICS_ATOMIC_INLINE */
+
+#endif /* epicsAtomicOSD_h */
+
=== added file 'src/libCom/osi/os/solaris/epicsAtomicOSD.h'
--- src/libCom/osi/os/solaris/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/solaris/epicsAtomicOSD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,166 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+#if defined ( EPICS_ATOMIC_INLINE )
+
+/*
+ * atomic.h exists only in Solaris 10 or higher
+ */
+#if defined ( __SunOS_5_10 )
+
+#include <atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE int epicsAtomicReadMemoryBarrier ()
+{
+ membar_consumer ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE int epicsAtomicWriteMemoryBarrier ()
+{
+ membar_producer ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_INTT
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
+ int oldVal, int newVal )
+{
+ STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) );
+ return ( int ) atomic_cas_uint ( pTarget, ( unsigned ) oldVal,
+ ( unsigned ) newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapSizeT (
+ size_t * pTarget,
+ size_t oldVal, size_t newVal )
+{
+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+ void ** ppPtr = (void **) pTarget;
+ return ( size_t ) atomic_cas_ptr ( ppPtr, ( void * )oldVal, ( void * )newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
+ EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldVal,
+ EpicsAtomicPtrT newVal )
+{
+ return atomic_cas_ptr ( pTarget, oldVal, newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_INCR_INTT
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+ STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
+ unsigned * const pTarg = ( unsigned * ) ( pTarget );
+ return ( int ) atomic_inc_uint_nv ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+ void ** const ppTarg = ( void ** ) ( pTarget );
+ return ( size_t ) atomic_inc_ptr_nv ( ppTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_INTT
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+ STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
+ unsigned * const pTarg = ( unsigned * ) ( pTarget );
+ return ( int ) atomic_dec_uint_nv ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+ void ** const pTarg = ( void ** ) ( pTarget );
+ return ( size_t ) atomic_dec_ptr_nv ( pTarg );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_INTT
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+ STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
+ unsigned * const pTarg = ( unsigned * ) ( pTarget );
+ return ( int ) atomic_add_int_nv ( pTarg, delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
+ size_t delta )
+{
+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+ void ** const pTarg = ( void ** ) ( pTarget );
+ return ( size_t ) atomic_add_ptr_nv ( pTarg, ( ssize_t ) delta );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget,
+ size_t delta )
+{
+ STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
+ void ** const pTarg = ( void ** ) ( pTarget );
+ ssize_t = sdelta = ( ssize_t ) delta;
+ return ( size_t ) atomic_add_ptr_nv ( pTarg, -sdelta );
+}
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* ifdef __SunOS_5_10 */
+
+#include "epicsAtomicDefault.h"
+
+#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
+
+#endif /* epicsAtomicOSD_h */
+
=== added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp'
--- src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp 2011-09-01 00:23:27 +0000
@@ -0,0 +1,22 @@
+
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#define epicsExportSharedSymbols
+#include "epicsAtomic.h"
+
+// if the compiler is unable to inline then instantiate out-of-line
+#ifndef EPICS_ATOMIC_INLINE
+#define EPICS_ATOMIC_INLINE
+#include "epicsAtomic.h"
+#endif
+
=== added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.h'
--- src/libCom/osi/os/vxWorks/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.h 2011-09-01 00:23:27 +0000
@@ -0,0 +1,255 @@
+/*************************************************************************\
+* 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
+ * [email protected]
+ */
+
+#ifndef epicsAtomicOSD_h
+#define epicsAtomicOSD_h
+
+#if defined ( EPICS_ATOMIC_INLINE )
+
+#include "vxWorks.h" /* obtain the version of vxWorks */
+#include "epicsAssert.h"
+
+/*
+ * With vxWorks 6.6 and later we need to use vxAtomicLib
+ * to implement this functionality correctly on SMP systems
+ */
+#if _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606
+
+#include <limits.h>
+#include <vxAtomicLib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
+{
+ VX_MEM_BARRIER_R ();
+}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
+{
+ VX_MEM_BARRIER_W ();
+}
+#endif
+
+/*
+ * we make the probably correct guess that if ULONG_MAX
+ * is the same as UINT_MAX then sizeof ( atomic_t )
+ * will be the same as sizeof ( size_t )
+ *
+ * if ULONG_MAX != UINT_MAX then its 64 bit vxWorks and
+ * WRS doesnt not supply at this time the atomic interface
+ * for 8 byte integers that is needed - so that architecture
+ * receives the lock synchronized version
+ */
+#if ULONG_MAX == UINT_MAX
+
+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( size_t ) );
+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( EpicsAtomicPtrT ) );
+
+
+#ifndef EPICS_ATOMIC_INCR_SIZET
+#define EPICS_ATOMIC_INCR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicInc ( pTarg );
+ return 1 + ( size_t ) ( oldVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_SIZET
+#define EPICS_ATOMIC_DECR_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicDec ( pTarg );
+ return ( ( size_t ) oldVal ) - 1u;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_SIZET
+#define EPICS_ATOMIC_ADD_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
+{
+ /*
+ * vxAtomicLib doc indicates that vxAtomicAdd is
+ * implemented using signed arithmetic, but it
+ * does not change the end result because twos
+ * complement addition is used in either case
+ */
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
+ return delta + ( size_t ) oldVal;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_SUB_SIZET
+#define EPICS_ATOMIC_SUB_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
+{
+ /*
+ * vxAtomicLib doc indicates that vxAtomicSub is
+ * implemented using signed arithmetic, but it
+ * does not change the end result because twos
+ * complement subtraction is used in either case
+ */
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicSub ( pTarg, (atomic_t) delta );
+ return ( ( size_t ) oldVal ) - delta;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_SIZET
+#define EPICS_ATOMIC_CAS_SIZET
+EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
+ size_t oldVal, size_t newVal )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ return ( size_t ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_PTRT
+#define EPICS_ATOMIC_CAS_PTRT
+EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget,
+ EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ return (EpicsAtomicPtrT) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
+}
+#endif
+
+#else /* ULONG_MAX == UINT_MAX */
+
+/*
+ * if its 64 bit SMP vxWorks and the compiler doesnt
+ * have an intrinsic then maybe there isnt any way to
+ * implement these without using a global lock because
+ * size_t is maybe bigger than atomic_t
+ *
+ * I dont yet have access to vxWorks manuals for
+ * 64 bit systems so this is still undecided, but is
+ * defaulting now to a global lock
+ */
+
+#endif /* ULONG_MAX == UINT_MAX */
+
+STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( int ) );
+
+#ifndef EPICS_ATOMIC_INCR_INTT
+#define EPICS_ATOMIC_INCR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicInc ( pTarg );
+ return 1 + ( int ) oldVal;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_DECR_INTT
+#define EPICS_ATOMIC_DECR_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicDec ( pTarg );
+ return ( ( int ) oldVal ) - 1;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_ADD_INTT
+#define EPICS_ATOMIC_ADD_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
+ return delta + ( int ) oldVal;
+}
+#endif
+
+#ifndef EPICS_ATOMIC_CAS_INTT
+#define EPICS_ATOMIC_CAS_INTT
+EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
+ int oldVal, int newVal )
+{
+ atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
+ return ( int ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
+}
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#else /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
+
+#include "vxLib.h"
+#include "intLib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef EPICS_ATOMIC_LOCK
+#define EPICS_ATOMIC_LOCK
+
+typedef struct EpicsAtomicLockKey { int m_key; } EpicsAtomicLockKey;
+
+EPICS_ATOMIC_INLINE void epicsAtomicLock ( EpicsAtomicLockKey * pKey )
+{
+ pKey->m_key = intLock ();
+}
+
+EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey )
+{
+ intUnlock ( pKey->m_key );
+}
+#endif
+
+#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
+#define EPICS_ATOMIC_READ_MEMORY_BARRIER
+/*
+ * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
+ * (we are not protecting against multiple access to memory mapped IO)
+ */
+EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {}
+#endif
+
+#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
+/*
+ * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
+ * (we are not protecting against multiple access to memory mapped IO)
+ */
+EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () {}
+#endif
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
+
+#include "epicsAtomicDefault.h"
+
+#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
+
+#endif /* epicsAtomicOSD_h */
+
=== modified file 'src/libCom/test/Makefile'
--- src/libCom/test/Makefile 2011-08-30 23:09:11 +0000
+++ src/libCom/test/Makefile 2011-09-01 00:23:27 +0000
@@ -108,6 +108,11 @@
testHarness_SRCS += epicsMutexTest.cpp
TESTS += epicsMutexTest
+TESTPROD_HOST += epicsAtomicTest
+epicsAtomicTest_SRCS += epicsAtomicTest.c
+testHarness_SRCS += epicsAtomicTest.c
+TESTS += epicsAtomicTest
+
TESTPROD_HOST += epicsExceptionTest
epicsExceptionTest_SRCS += epicsExceptionTest.cpp
testHarness_SRCS += epicsExceptionTest.cpp
@@ -178,6 +183,10 @@
fdmgrTest_LIBS += ca
# FIXME: program never exits.
+TESTPROD_HOST += epicsAtomicPerform
+epicsAtomicPerform_SRCS += epicsAtomicPerform.cpp
+testHarness_SRCS += epicsAtomicPerform.cpp
+
TESTPROD_HOST += cvtFastPerform
cvtFastPerform_SRCS += cvtFastPerform.cpp
testHarness_SRCS += cvtFastPerform.cpp
=== added file 'src/libCom/test/epicsAtomicPerform.cpp'
--- src/libCom/test/epicsAtomicPerform.cpp 1970-01-01 00:00:00 +0000
+++ src/libCom/test/epicsAtomicPerform.cpp 2011-09-01 00:23:27 +0000
@@ -0,0 +1,506 @@
+
+#include <cstdlib>
+#include <cstdio>
+#include <cassert>
+#include <typeinfo>
+
+#include "epicsInterrupt.h"
+#include "epicsAtomic.h"
+#include "epicsTime.h"
+#include "epicsUnitTest.h"
+#include "testMain.h"
+
+using std :: size_t;
+using namespace epics;
+using namespace atomic;
+
+class RefCtr {
+public:
+ RefCtr ();
+ ~RefCtr ();
+ void reference ();
+ void unreference ();
+private:
+ size_t m_cnt;
+};
+
+class Ownership {
+public:
+ Ownership ();
+ Ownership ( RefCtr & refCtr );
+ Ownership ( const Ownership & );
+ ~Ownership ();
+ Ownership & operator = ( const Ownership & );
+private:
+ RefCtr * _pRefCtr;
+ static RefCtr m_noOwnership;
+};
+
+inline RefCtr :: RefCtr ()
+{
+ epicsAtomicSetSizeT ( & m_cnt, 0 );
+}
+
+inline RefCtr :: ~RefCtr ()
+{
+ unsigned cnt = epicsAtomicGetSizeT ( & m_cnt );
+ assert ( cnt == 0u );
+}
+
+inline void RefCtr :: reference ()
+{
+ epicsAtomicIncrSizeT ( & m_cnt );
+}
+
+inline void RefCtr :: unreference ()
+{
+ epicsAtomicDecrSizeT ( & m_cnt );
+}
+
+RefCtr Ownership :: m_noOwnership;
+
+inline Ownership :: Ownership () :
+ _pRefCtr ( & m_noOwnership )
+{
+ m_noOwnership.reference ();
+}
+
+inline Ownership :: Ownership ( RefCtr & refCtr ) :
+ _pRefCtr ( & refCtr )
+{
+ refCtr.reference ();
+}
+
+inline Ownership :: Ownership ( const Ownership & ownership ) :
+ _pRefCtr ( ownership._pRefCtr )
+{
+ _pRefCtr->reference ();
+}
+
+inline Ownership :: ~Ownership ()
+{
+ _pRefCtr->unreference ();
+}
+
+inline Ownership & Ownership ::
+ operator = ( const Ownership & ownership )
+{
+ RefCtr * const pOldRefCtr = _pRefCtr;
+ _pRefCtr = ownership._pRefCtr;
+ _pRefCtr->reference ();
+ pOldRefCtr->unreference ();
+ return *this;
+}
+
+inline Ownership retOwnership ( const Ownership & ownership )
+{
+ return Ownership ( ownership );
+}
+
+inline Ownership recurRetOwner10 ( const Ownership & ownershipIn )
+{
+ Ownership ownership =
+ retOwnership (
+ retOwnership (
+ retOwnership (
+ retOwnership (
+ retOwnership ( ownershipIn ) ) ) ) );
+ return retOwnership (
+ retOwnership (
+ retOwnership (
+ retOwnership (
+ retOwnership ( ownership ) ) ) ) );
+}
+
+inline Ownership recurRetOwner100 ( const Ownership & ownershipIn )
+{
+ Ownership ownership =
+ recurRetOwner10 (
+ recurRetOwner10 (
+ recurRetOwner10 (
+ recurRetOwner10 (
+ recurRetOwner10 ( ownershipIn ) ) ) ) );
+ return recurRetOwner10 (
+ recurRetOwner10 (
+ recurRetOwner10 (
+ recurRetOwner10 (
+ recurRetOwner10 ( ownership ) ) ) ) );
+}
+
+inline Ownership recurRetOwner1000 ( const Ownership & ownershipIn )
+{
+ Ownership ownership =
+ recurRetOwner100 (
+ recurRetOwner100 (
+ recurRetOwner100 (
+ recurRetOwner100 (
+ recurRetOwner100 ( ownershipIn ) ) ) ) );
+ return recurRetOwner100 (
+ recurRetOwner100 (
+ recurRetOwner100 (
+ recurRetOwner100 (
+ recurRetOwner100 ( ownership ) ) ) ) );
+}
+
+inline void passRefOwnership ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+ ownershipOut = ownershipIn;
+}
+
+inline void passRefOwnership10 ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+ Ownership ownershipTmp0;
+ passRefOwnership ( ownershipIn, ownershipTmp0 );
+ Ownership ownershipTmp1;
+ passRefOwnership ( ownershipTmp0, ownershipTmp1 );
+ Ownership ownershipTmp2;
+ passRefOwnership ( ownershipTmp1, ownershipTmp2 );
+ Ownership ownershipTmp3;
+ passRefOwnership ( ownershipTmp2, ownershipTmp3 );
+ Ownership ownershipTmp4;
+ passRefOwnership ( ownershipTmp3, ownershipTmp4 );
+ Ownership ownershipTmp5;
+ passRefOwnership ( ownershipTmp4, ownershipTmp5 );
+ Ownership ownershipTmp6;
+ passRefOwnership ( ownershipTmp5, ownershipTmp6 );
+ Ownership ownershipTmp7;
+ passRefOwnership ( ownershipTmp6, ownershipTmp7 );
+ Ownership ownershipTmp8;
+ passRefOwnership ( ownershipTmp7, ownershipTmp8 );
+ passRefOwnership ( ownershipTmp8, ownershipOut );
+}
+
+inline void passRefOwnership100 ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+ Ownership ownershipTmp0;
+ passRefOwnership10 ( ownershipIn, ownershipTmp0 );
+ Ownership ownershipTmp1;
+ passRefOwnership10 ( ownershipTmp0, ownershipTmp1 );
+ Ownership ownershipTmp2;
+ passRefOwnership10 ( ownershipTmp1, ownershipTmp2 );
+ Ownership ownershipTmp3;
+ passRefOwnership10 ( ownershipTmp2, ownershipTmp3 );
+ Ownership ownershipTmp4;
+ passRefOwnership10 ( ownershipTmp3, ownershipTmp4 );
+ Ownership ownershipTmp5;
+ passRefOwnership10 ( ownershipTmp4, ownershipTmp5 );
+ Ownership ownershipTmp6;
+ passRefOwnership10 ( ownershipTmp5, ownershipTmp6 );
+ Ownership ownershipTmp7;
+ passRefOwnership10 ( ownershipTmp6, ownershipTmp7 );
+ Ownership ownershipTmp8;
+ passRefOwnership10 ( ownershipTmp7, ownershipTmp8 );
+ passRefOwnership10 ( ownershipTmp8, ownershipOut );
+}
+
+inline void passRefOwnership1000 ( const Ownership & ownershipIn, Ownership & ownershipOut )
+{
+ Ownership ownershipTmp0;
+ passRefOwnership100 ( ownershipIn, ownershipTmp0 );
+ Ownership ownershipTmp1;
+ passRefOwnership100 ( ownershipTmp0, ownershipTmp1 );
+ Ownership ownershipTmp2;
+ passRefOwnership100 ( ownershipTmp1, ownershipTmp2 );
+ Ownership ownershipTmp3;
+ passRefOwnership100 ( ownershipTmp2, ownershipTmp3 );
+ Ownership ownershipTmp4;
+ passRefOwnership100 ( ownershipTmp3, ownershipTmp4 );
+ Ownership ownershipTmp5;
+ passRefOwnership100 ( ownershipTmp4, ownershipTmp5 );
+ Ownership ownershipTmp6;
+ passRefOwnership100 ( ownershipTmp5, ownershipTmp6 );
+ Ownership ownershipTmp7;
+ passRefOwnership100 ( ownershipTmp6, ownershipTmp7 );
+ Ownership ownershipTmp8;
+ passRefOwnership100 ( ownershipTmp7, ownershipTmp8 );
+ passRefOwnership100 ( ownershipTmp8, ownershipOut );
+}
+
+time_t extTime = 0;
+
+template < class T >
+class OrdinaryIncr {
+public:
+ OrdinaryIncr () : m_target ( 0 ) {}
+ void run ();
+ void diagnostic ( double delay );
+private:
+ T m_target;
+};
+
+// tests the time it takes to perform a call to an external
+// function and also increment an integer word. The
+// epicsInterruptIsInterruptContext function is an
+// out-of-line function implemented in a sharable library
+// so hopefully it wont be optimized away.
+template < class T >
+inline void OrdinaryIncr < T > :: run ()
+{
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+ m_target += epicsInterruptIsInterruptContext ();
+}
+
+template < class T >
+void OrdinaryIncr < T > :: diagnostic ( double delay )
+{
+ delay /= 10.0;
+ delay *= 1e6;
+ const char * const pName = typeid ( T ) . name ();
+ testDiag ( "raw incr of \"%s\" and a NOOP function call takes %f microseconds",
+ pName, delay );
+}
+
+template < class T >
+class AtomicIncr {
+public:
+ AtomicIncr () : m_target ( 0 ) {}
+ void run ();
+ void diagnostic ( double delay );
+private:
+ T m_target;
+};
+
+template < class T >
+inline void AtomicIncr < T > :: run ()
+{
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+ increment ( m_target );
+}
+
+template < class T >
+void AtomicIncr < T > :: diagnostic ( double delay )
+{
+ delay /= 10.0;
+ delay *= 1e6;
+ const char * const pName = typeid ( T ) . name ();
+ testDiag ( "epicsAtomicIncr \"%s\" takes %f microseconds",
+ pName, delay );
+}
+
+template < class T > T trueValue ();
+template < class T > T falseValue ();
+
+// int
+template <>
+inline int trueValue < int > () { return 1; }
+
+template <>
+inline int falseValue < int > () { return 0; }
+
+// size_t
+template <>
+inline size_t trueValue < size_t > () { return 1u; }
+
+template <>
+inline size_t falseValue < size_t > () { return 0u; }
+
+// EpicsAtomicPtrT
+template <>
+inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > ()
+{ static char c; return & c; }
+
+template <>
+inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > ()
+{ return 0u; }
+
+template < class T >
+class AtomicCmpAndSwap {
+public:
+ AtomicCmpAndSwap () : m_target ( 0 ) {}
+ void run ();
+ void diagnostic ( double delay );
+private:
+ T m_target;
+};
+
+template < class T >
+inline void AtomicCmpAndSwap < T > :: run ()
+{
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+ compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
+}
+
+template < class T >
+void AtomicCmpAndSwap < T > :: diagnostic ( double delay )
+{
+ delay /= 10.0;
+ delay *= 1e6;
+ const char * const pName = typeid ( T ) . name ();
+ testDiag ( "epicsAtomicCmpAndSwap of \"%s\" takes %f microseconds",
+ pName, delay );
+}
+
+template < class T >
+class AtomicSet {
+public:
+ AtomicSet () : m_target ( 0 ) {}
+ void run ();
+ void diagnostic ( double delay );
+private:
+ T m_target;
+};
+
+template < class T >
+inline void AtomicSet < T > :: run ()
+{
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+ set ( m_target, 0 );
+}
+
+template < class T >
+void AtomicSet < T > :: diagnostic ( double delay )
+{
+ delay /= 10.0;
+ delay *= 1e6;
+ const char * const pName = typeid ( T ) . name ();
+ testDiag ( "epicsAtomicSet of \"%s\" takes %f microseconds",
+ pName, delay );
+}
+
+static const unsigned N = 10000;
+
+void recursiveOwnershipRetPerformance ()
+{
+ RefCtr refCtr;
+ epicsTime begin = epicsTime::getCurrent ();
+ for ( size_t i = 0; i < N; i++ ) {
+ Ownership ownership ( refCtr );
+ recurRetOwner1000 ( ownership );
+ }
+ double delay = epicsTime::getCurrent () - begin;
+ delay /= N * 1000u; // convert to delay per call
+ delay *= 1e6; // convert to micro seconds
+ testDiag ( "retOwnership() takes %f microseconds", delay );
+}
+
+void ownershipPassRefPerformance ()
+{
+ RefCtr refCtr;
+ epicsTime begin = epicsTime::getCurrent ();
+ for ( size_t i = 0; i < N; i++ ) {
+ Ownership ownershipSrc ( refCtr );
+ Ownership ownershipDest;
+ passRefOwnership1000 ( ownershipSrc, ownershipDest );
+ }
+ double delay = epicsTime::getCurrent () - begin;
+ delay /= N * 1000u; // convert to delay per call
+ delay *= 1e6; // convert to micro seconds
+ testDiag ( "passRefOwnership() takes %f microseconds", delay );
+}
+
+template < class T >
+class Ten
+{
+public:
+ void run ();
+ void diagnostic ( double delay );
+ typedef Ten < Ten < T > > Hundred;
+ typedef Ten < Hundred > Thousand;
+private:
+ T m_target;
+};
+
+template < class T >
+inline void Ten < T > :: run ()
+{
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+ m_target.run ();
+}
+
+template < class T >
+void Ten < T > :: diagnostic ( double delay )
+{
+ m_target.diagnostic ( delay / 10.0 );
+}
+
+template < class T >
+void measurePerformance ()
+{
+ epicsTime begin = epicsTime::getCurrent ();
+ T target;
+ for ( size_t i = 0; i < N; i++ ) {
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ target.run ();
+ }
+ double delay = epicsTime::getCurrent () - begin;
+ delay /= ( N * 10u ); // convert to delay per call
+ target.diagnostic ( delay );
+}
+
+template < class T >
+void measure ()
+{
+ measurePerformance < typename Ten < T > :: Hundred > ();
+}
+
+MAIN ( epicsAtomicPerform )
+{
+ testPlan ( 0 );
+ //
+ // The tests running here are measuring fast
+ // functions so they tend to be impacted
+ // by where the cache lines are wrt to the
+ // virtual pages perhap
+ //
+ measure < AtomicSet < int > > ();
+ measure < AtomicSet < size_t > > ();
+ measure < AtomicSet < void * > > ();
+ measure < OrdinaryIncr < int > > ();
+ measure < OrdinaryIncr < size_t > > ();
+ measure < AtomicIncr < int > > ();
+ measure < AtomicIncr < size_t > > ();
+ measure < AtomicCmpAndSwap < int > > ();
+ measure < AtomicCmpAndSwap < size_t > > ();
+ measure < AtomicCmpAndSwap < void * > > ();
+ recursiveOwnershipRetPerformance ();
+ ownershipPassRefPerformance ();
+ return testDone();
+}
=== added file 'src/libCom/test/epicsAtomicTest.cpp'
--- src/libCom/test/epicsAtomicTest.cpp 1970-01-01 00:00:00 +0000
+++ src/libCom/test/epicsAtomicTest.cpp 2011-09-01 00:23:27 +0000
@@ -0,0 +1,238 @@
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "epicsAtomic.h"
+#include "epicsTime.h"
+#include "epicsThread.h"
+#include "epicsUnitTest.h"
+#include "testMain.h"
+
+using namespace epics;
+using namespace atomic;
+
+template < class T >
+struct TestDataIncrDecr {
+ T m_testValue;
+ size_t m_testIterations;
+};
+
+template < class T >
+struct TestDataAddSub {
+ T m_testValue;
+ size_t m_testIterations;
+ static const T delta = 17;
+};
+
+template < class T >
+static void incr ( void *arg )
+{
+ TestDataIncrDecr < T > * const pTestData =
+ reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
+ increment ( pTestData->m_testValue );
+ increment ( pTestData->m_testIterations );
+}
+
+template < class T >
+static void decr ( void *arg )
+{
+ TestDataIncrDecr < T > * const pTestData =
+ reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
+ decrement ( pTestData->m_testValue );
+ increment ( pTestData->m_testIterations );
+}
+
+
+template < class T >
+static void add ( void *arg )
+{
+ TestDataAddSub < T > * const pTestData =
+ reinterpret_cast < TestDataAddSub < T > * > ( arg );
+ add ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
+ increment ( pTestData->m_testIterations );
+}
+
+template < class T >
+static void sub ( void *arg )
+{
+ TestDataAddSub < T > * const pTestData =
+ reinterpret_cast < TestDataAddSub < T > * > ( arg );
+ subtract ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
+ increment ( pTestData->m_testIterations );
+}
+
+template < class T >
+struct TestDataCAS {
+ T m_testValue;
+ size_t m_testIterationsSet;
+ size_t m_testIterationsNotSet;
+};
+
+int isModulo ( size_t N, size_t n )
+{
+ return ( n % N ) == 0u;
+}
+
+template < class T >
+static T trueValue ();
+template < class T >
+static T falseValue ();
+
+// int
+template <>
+inline int trueValue < int > () { return 1; }
+
+template <>
+inline int falseValue < int > () { return 0; }
+
+// size_t
+template <>
+inline size_t trueValue < size_t > () { return 1u; }
+
+template <>
+inline size_t falseValue < size_t > () { return 0u; }
+
+// EpicsAtomicPtrT
+template <>
+inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > ()
+{ static char c; return & c; }
+
+template <>
+inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > ()
+{ return 0u; }
+
+template < class T >
+static void cas ( void *arg )
+{
+ TestDataCAS < T > * const pTestData =
+ reinterpret_cast < TestDataCAS < T > * > ( arg );
+ /*
+ * intentionally waste cpu and maximize
+ * contention for the shared data
+ */
+ increment ( pTestData->m_testIterationsNotSet );
+ while ( ! compareAndSwap ( pTestData->m_testValue,
+ falseValue < T > (),
+ trueValue < T > () ) ) {
+ }
+ decrement ( pTestData->m_testIterationsNotSet );
+ set ( pTestData->m_testValue, falseValue < T > () );
+ increment ( pTestData->m_testIterationsSet );
+}
+
+template < class T >
+void testIncrDecr ()
+{
+ static const size_t N = 100;
+ static const T NT = static_cast < T > ( N );
+
+ const unsigned int stackSize =
+ epicsThreadGetStackSize ( epicsThreadStackSmall );
+
+ TestDataIncrDecr < T > testData = { 0, N };
+ set ( testData.m_testValue, NT );
+ testOk ( get ( testData.m_testValue ) == NT,
+ "set/get %u", testData.m_testValue );
+ set ( testData.m_testIterations, 0u );
+ testOk ( get ( testData.m_testIterations ) == 0u,
+ "set/get %u", testData.m_testIterations );
+ for ( size_t i = 0u; i < N; i++ ) {
+ epicsThreadCreate ( "incr",
+ 50, stackSize, incr < T >, & testData );
+ epicsThreadCreate ( "decr",
+ 50, stackSize, decr < T >, & testData );
+ }
+ while ( testData.m_testIterations < 2 * N ) {
+ epicsThreadSleep ( 0.01 );
+ }
+ testOk ( get ( testData.m_testIterations ) == 2 * N,
+ "incr/decr iterations %u",
+ testData.m_testIterations );
+ testOk ( get ( testData.m_testValue ) == NT,
+ "incr/decr final value %u",
+ testData.m_testValue );
+}
+
+template < class T >
+void testAddSub ()
+{
+ static const size_t N = 100;
+ static const T NDT = TestDataAddSub < T > :: delta *
+ static_cast < T > ( N );
+
+ const unsigned int stackSize =
+ epicsThreadGetStackSize ( epicsThreadStackSmall );
+
+ TestDataIncrDecr < T > testData = { 0, N };
+ set ( testData.m_testValue, NDT );
+ testOk ( get ( testData.m_testValue ) == NDT,
+ "set/get %u", testData.m_testValue );
+ set ( testData.m_testIterations, 0u );
+ testOk ( get ( testData.m_testIterations ) == 0u,
+ "set/get %u", testData.m_testIterations );
+ for ( size_t i = 0u; i < N; i++ ) {
+ epicsThreadCreate ( "add",
+ 50, stackSize, add < T >, & testData );
+ epicsThreadCreate ( "sub",
+ 50, stackSize, sub < T >, & testData );
+ }
+ while ( testData.m_testIterations < 2 * N ) {
+ epicsThreadSleep ( 0.01 );
+ }
+ testOk ( get ( testData.m_testIterations ) == 2 * N,
+ "add/sub iterations %u",
+ testData.m_testIterations );
+ testOk ( get ( testData.m_testValue ) == NDT,
+ "add/sub final value %u",
+ testData.m_testValue );
+}
+
+template < class T >
+void testCAS ()
+{
+ static const size_t N = 10;
+
+ const unsigned int stackSize =
+ epicsThreadGetStackSize ( epicsThreadStackSmall );
+
+ TestDataCAS < T > testData = { 0, N, N };
+ set ( testData.m_testIterationsSet, 0 );
+ testOk ( get ( testData.m_testIterationsSet ) == 0u,
+ "set/get %u", testData.m_testIterationsSet );
+ set ( testData.m_testIterationsNotSet, 0 );
+ testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
+ "set/get %u", testData.m_testIterationsNotSet );
+ set ( testData.m_testValue, trueValue < T > () );
+ testOk ( get ( testData.m_testValue ) == trueValue < T > (),
+ "set/get a true value" );
+ for ( size_t i = 0u; i < N; i++ ) {
+ epicsThreadCreate ( "tns",
+ 50, stackSize, cas < T >, & testData );
+ }
+ set ( testData.m_testValue, falseValue < T > () );
+ while ( testData.m_testIterationsSet < N ) {
+ epicsThreadSleep ( 0.01 );
+ }
+ testOk ( get ( testData.m_testIterationsSet ) == N,
+ "test and set iterations %u",
+ testData.m_testIterationsSet );
+ testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
+ "test and set not-set tracking = %u",
+ testData.m_testIterationsNotSet );
+}
+
+MAIN ( epicsAtomicTest )
+{
+
+ testPlan ( 31 );
+
+ testIncrDecr < int > ();
+ testIncrDecr < size_t > ();
+ testAddSub < int > ();
+ testAddSub < size_t > ();
+ testCAS < int > ();
+ testCAS < size_t > ();
+ testCAS < EpicsAtomicPtrT > ();
+
+ return testDone ();
+}
- Replies:
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Andrew Johnson
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Andrew Johnson
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Andrew Johnson
- [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Andrew Johnson
- Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Andrew Johnson
- Navigate by Date:
- Prev:
Re: [Merge] lp:~epics-core/epics-base/3.15-buildCompilerSpecific into lp:epics-base Jeff Hill
- Next:
Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
<2011>
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Next:
Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
<2011>
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|