Subject: |
[Merge] lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base |
From: |
Jeff Hill <[email protected]> |
To: |
[email protected] |
Date: |
Wed, 31 Aug 2011 22:29:27 -0000 |
Jeff Hill has proposed merging lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base.
Requested reviews:
EPICS Core Developers (epics-core)
For more details, see:
https://code.launchpad.net/~johill-lanl/epics-base/epicsThreadOnce-atomics-based/+merge/73605
o added new epicsAtomics based, and OS independent, implementation of epicsThreadOnce in epicsThreadOnce.cpp
o changed type of epicsThreadOnceId from epicsThreadId to void *
o fixed once flag isnt initialized with EPICSTHREAD_ONCE_INIT in ipAddrToAsciiAsynchronous.cpp
o removed OS dependent implementations of epicsThreadOnce from {posix, RTEMS, vxWorks, win32}
--
https://code.launchpad.net/~johill-lanl/epics-base/epicsThreadOnce-atomics-based/+merge/73605
Your team EPICS Core Developers is requested to review the proposed merge of lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:epics-base.
=== modified file 'configure/CONFIG.gnuCommon'
--- configure/CONFIG.gnuCommon 2009-11-25 17:15:47 +0000
+++ configure/CONFIG.gnuCommon 2011-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +0000
@@ -9,6 +9,7 @@
TOP = ../..
include $(TOP)/configure/CONFIG
+<<<<<<< TREE
SRC = $(TOP)/src
LIBCOM = $(SRC)/libCom
@@ -38,6 +39,288 @@
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 += epicsThreadOnce.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 */
=== modified file 'src/libCom/misc/ipAddrToAsciiAsynchronous.cpp'
--- src/libCom/misc/ipAddrToAsciiAsynchronous.cpp 2008-10-21 20:26:48 +0000
+++ src/libCom/misc/ipAddrToAsciiAsynchronous.cpp 2011-08-31 22:29:24 +0000
@@ -127,7 +127,7 @@
ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;
bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;
-static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0;
+static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
// the users are not required to supply a show routine
// for there transaction callback class
=== 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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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 */
+
+
=== modified file 'src/libCom/osi/epicsThread.h'
--- src/libCom/osi/epicsThread.h 2010-04-26 20:38:11 +0000
+++ src/libCom/osi/epicsThread.h 2011-08-31 22:29:24 +0000
@@ -51,7 +51,7 @@
/* (epicsThreadId)0 is guaranteed to be an invalid thread id */
typedef struct epicsThreadOSD *epicsThreadId;
-typedef epicsThreadId epicsThreadOnceId;
+typedef void * epicsThreadOnceId;
#define EPICS_THREAD_ONCE_INIT 0
epicsShareFunc void epicsShareAPI epicsThreadOnce(
=== added file 'src/libCom/osi/epicsThreadOnce.cpp'
--- src/libCom/osi/epicsThreadOnce.cpp 1970-01-01 00:00:00 +0000
+++ src/libCom/osi/epicsThreadOnce.cpp 2011-08-31 22:29:24 +0000
@@ -0,0 +1,129 @@
+
+/*************************************************************************\
+* Copyright (c) 2011 LANS LLC, as Operator of
+* Los Alamos National Laboratory.
+* Copyright (c) 2011 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]
+ * Original Authors (before converting to operating system independent code):
+ * Jeff Hill, Andrew Johnson, Marty Kraimer, Eric Norum
+ */
+
+#include <cstdlib>
+
+#define epicsExportSharedSymbols
+#include "errlog.h"
+#include "cantProceed.h"
+#include "epicsThread.h"
+#include "epicsAtomic.h"
+#include "epicsAssert.h"
+
+namespace {
+
+struct ThreadID {
+public:
+ ThreadID ();
+ ThreadID ( epicsThreadId id );
+ bool operator == ( const ThreadID & ) const;
+private:
+ epicsThreadId m_threadId;
+ ThreadID ( const ThreadID & ); // disabled
+ ThreadID & operator = ( const ThreadID & ); // disabled
+};
+
+inline ThreadID :: ThreadID ( epicsThreadId id ) :
+ m_threadId ( id )
+{
+}
+
+inline ThreadID :: ThreadID () : m_threadId ( 0 )
+{
+}
+
+inline bool ThreadID :: operator == ( const ThreadID & ctrl ) const
+{
+ return ctrl.m_threadId == m_threadId;
+}
+
+static ThreadID done;
+
+} // end of namespace annonymous
+
+using namespace epics;
+using namespace atomic;
+
+/*
+ * epicsThreadOnceOnly ()
+ */
+static void epicsShareAPI epicsThreadOnceOnly ( epicsThreadOnceId * pId,
+ void ( * pFunc )( void * ),
+ void * pArg )
+{
+ static const epicsThreadOnceId idStartup = EPICS_THREAD_ONCE_INIT;
+ ThreadID self ( epicsThreadGetIdSelf () );
+ epicsThreadOnceId pCurrent = compareAndSwap ( *pId, idStartup, & self );
+ if ( pCurrent != & done ) {
+ if ( pCurrent == idStartup ) {
+ ( *pFunc ) ( pArg );
+ set ( *pId, & done );
+ }
+ else {
+ {
+ ThreadID & initID =
+ * reinterpret_cast < ThreadID * > ( pCurrent );
+ if ( initID == self ) {
+ cantProceed( "epicsThreadOnce() once was called "
+ "recursively from the user's once fuction\n" );
+ }
+ }
+ static const std :: size_t spinDownInit = 1000u;
+ static const std :: size_t spinCount = 10u;
+ STATIC_ASSERT ( spinDownInit > spinCount );
+ static const std :: size_t spinThresh = spinDownInit - spinCount;
+ std :: size_t spinDown = spinDownInit;
+ do {
+ if ( spinDown <= spinThresh ) {
+ epicsThreadSleep ( epicsThreadSleepQuantum () );
+ }
+ if ( spinDown > 0u ) {
+ spinDown--;
+ }
+ else {
+ errlogPrintf ( "epicsThreadOnce: waiting for another "
+ "thread to finish calling the once function\n" );
+ spinDown = spinThresh;
+ }
+ pCurrent = get ( *pId );
+ } while ( pCurrent != & done );
+ }
+ }
+}
+
+//
+// we implement this as a separate function so that it is easy to see
+// that the performance impact of the primary (most commonly used) path
+// and that options for inlining this function are available (based on
+// source code organization)
+//
+// performance might be slightly better if this were implemented as an inline
+// function, but that would pull epicsAtomic.h into epicsThread.h, and on
+// windows this includes (the lean and mean version of) windows.h, so perhaps
+// its best to make this an out-of-line function as that type of instantiation
+// will probably have only a small negative impact on performance
+//
+extern "C" void epicsShareAPI epicsThreadOnce ( epicsThreadOnceId * pId,
+ void ( * pFunc )( void * ),
+ void * pArg )
+{
+ const epicsThreadOnceId pCurrent = get ( *pId );
+ if ( pCurrent != & done ) {
+ epicsThreadOnceOnly ( pId, pFunc, pArg );
+ }
+}
=== modified file 'src/libCom/osi/os/RTEMS/osdThread.c'
--- src/libCom/osi/os/RTEMS/osdThread.c 2010-10-05 19:27:37 +0000
+++ src/libCom/osi/os/RTEMS/osdThread.c 2011-08-31 22:29:24 +0000
@@ -60,7 +60,6 @@
* Support for `once-only' execution
*/
static int initialized = 0;
-static epicsMutexId onceMutex;
/*
* Just map osi 0 to 99 into RTEMS 199 to 100
@@ -231,7 +230,6 @@
rtems_task_priority old;
rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);
- onceMutex = epicsMutexMustCreate();
taskVarMutex = epicsMutexMustCreate ();
rtems_task_ident (RTEMS_SELF, 0, &tid);
setThreadInfo (tid, "_main_", NULL, NULL);
@@ -471,36 +469,6 @@
}
/*
- * Ensure func() is run only once.
- */
-void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
-{
- #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1
-
- if (!initialized) epicsThreadInit();
- epicsMutexMustLock(onceMutex);
- if (*id != EPICS_THREAD_ONCE_DONE) {
- if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
- *id = epicsThreadGetIdSelf(); /* mark active */
- epicsMutexUnlock(onceMutex);
- func(arg);
- epicsMutexMustLock(onceMutex);
- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
- } else if (*id == epicsThreadGetIdSelf()) {
- epicsMutexUnlock(onceMutex);
- cantProceed("Recursive epicsThreadOnce() initialization\n");
- } else
- while (*id != EPICS_THREAD_ONCE_DONE) {
- /* Another thread is in the above func(arg) call. */
- epicsMutexUnlock(onceMutex);
- epicsThreadSleep(epicsThreadSleepQuantum());
- epicsMutexMustLock(onceMutex);
- }
- }
- epicsMutexUnlock(onceMutex);
-}
-
-/*
* Thread private storage implementation based on the vxWorks
* implementation by Andrew Johnson APS/ASD.
*/
=== 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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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 */
+
=== modified file 'src/libCom/osi/os/WIN32/osdThread.c'
--- src/libCom/osi/os/WIN32/osdThread.c 2011-02-11 22:33:58 +0000
+++ src/libCom/osi/os/WIN32/osdThread.c 2011-08-31 22:29:24 +0000
@@ -1008,41 +1008,6 @@
}
/*
- * epicsThreadOnce ()
- */
-epicsShareFunc void epicsShareAPI epicsThreadOnce (
- epicsThreadOnceId *id, void (*func)(void *), void *arg )
-{
- static struct epicsThreadOSD threadOnceComplete;
- #define EPICS_THREAD_ONCE_DONE & threadOnceComplete
- win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
-
- assert ( pGbl );
-
- EnterCriticalSection ( & pGbl->mutex );
-
- if ( *id != EPICS_THREAD_ONCE_DONE ) {
- if ( *id == EPICS_THREAD_ONCE_INIT ) { /* first call */
- *id = epicsThreadGetIdSelf(); /* mark active */
- LeaveCriticalSection ( & pGbl->mutex );
- func ( arg );
- EnterCriticalSection ( & pGbl->mutex );
- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
- } else if ( *id == epicsThreadGetIdSelf() ) {
- LeaveCriticalSection ( & pGbl->mutex );
- cantProceed( "Recursive epicsThreadOnce() initialization\n" );
- } else
- while ( *id != EPICS_THREAD_ONCE_DONE ) {
- /* Another thread is in the above func(arg) call. */
- LeaveCriticalSection ( & pGbl->mutex );
- epicsThreadSleep ( epicsThreadSleepQuantum() );
- EnterCriticalSection ( & pGbl->mutex );
- }
- }
- LeaveCriticalSection ( & pGbl->mutex );
-}
-
-/*
* epicsThreadPrivateCreate ()
*/
epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate ()
=== 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-08-31 22:29:24 +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-08-31 22:29:24 +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 */
+
=== modified file 'src/libCom/osi/os/posix/osdThread.c'
--- src/libCom/osi/os/posix/osdThread.c 2010-05-14 22:26:54 +0000
+++ src/libCom/osi/os/posix/osdThread.c 2011-08-31 22:29:24 +0000
@@ -76,7 +76,6 @@
} epicsThreadOSD;
static pthread_key_t getpthreadInfo;
-static pthread_mutex_t onceLock;
static pthread_mutex_t listLock;
static ELLLIST pthreadList = ELLLIST_INIT;
static commonAttr *pcommonAttr = 0;
@@ -207,8 +206,6 @@
int status;
pthread_key_create(&getpthreadInfo,0);
- status = pthread_mutex_init(&onceLock,0);
- checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
status = pthread_mutex_init(&listLock,0);
checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
pcommonAttr = calloc(1,sizeof(commonAttr));
@@ -321,47 +318,6 @@
#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
}
-epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
-{
- static struct epicsThreadOSD threadOnceComplete;
- #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
- int status;
-
- epicsThreadInit();
- status = mutexLock(&onceLock);
- if(status) {
- fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
- strerror(status));
- exit(-1);
- }
-
- if (*id != EPICS_THREAD_ONCE_DONE) {
- if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
- *id = epicsThreadGetIdSelf(); /* mark active */
- status = pthread_mutex_unlock(&onceLock);
- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
- func(arg);
- status = mutexLock(&onceLock);
- checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
- } else if (*id == epicsThreadGetIdSelf()) {
- status = pthread_mutex_unlock(&onceLock);
- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
- cantProceed("Recursive epicsThreadOnce() initialization\n");
- } else
- while (*id != EPICS_THREAD_ONCE_DONE) {
- /* Another thread is in the above func(arg) call. */
- status = pthread_mutex_unlock(&onceLock);
- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
- epicsThreadSleep(epicsThreadSleepQuantum());
- status = mutexLock(&onceLock);
- checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
- }
- }
- status = pthread_mutex_unlock(&onceLock);
- checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
-}
-
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm)
=== 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-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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/osi/os/vxWorks/osdThread.c'
--- src/libCom/osi/os/vxWorks/osdThread.c 2010-08-11 15:45:17 +0000
+++ src/libCom/osi/os/vxWorks/osdThread.c 2011-08-31 22:29:24 +0000
@@ -53,7 +53,6 @@
static void **papTSD = 0;
static int nepicsThreadPrivate = 0;
-static SEM_ID epicsThreadOnceMutex = 0;
/* Just map osi 0 to 99 into vx 100 to 199 */
/* remember that for vxWorks lower number means higher priority */
@@ -83,19 +82,6 @@
}
}
-static void epicsThreadInit(void)
-{
- static int lock = 0;
-
- while(!vxTas(&lock)) taskDelay(1);
- if(epicsThreadOnceMutex==0) {
- epicsThreadOnceMutex = semMCreate(
- SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
- assert(epicsThreadOnceMutex);
- }
- lock = 0;
-}
-
unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
{
@@ -112,43 +98,6 @@
return stackSizeTable[stackSizeClass];
}
-struct epicsThreadOSD {};
- /* Strictly speaking this should be a WIND_TCB, but we only need it to
- * be able to create an epicsThreadId that is guaranteed never to be
- * the same as any current TID, and since TIDs are pointers this works.
- */
-
-void epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
-{
- static struct epicsThreadOSD threadOnceComplete;
- #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
- int result;
-
- epicsThreadInit();
- result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
- assert(result == OK);
- if (*id != EPICS_THREAD_ONCE_DONE) {
- if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
- *id = epicsThreadGetIdSelf(); /* mark active */
- semGive(epicsThreadOnceMutex);
- func(arg);
- result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
- assert(result == OK);
- *id = EPICS_THREAD_ONCE_DONE; /* mark done */
- } else if (*id == epicsThreadGetIdSelf()) {
- semGive(epicsThreadOnceMutex);
- cantProceed("Recursive epicsThreadOnce() initialization\n");
- } else
- while (*id != EPICS_THREAD_ONCE_DONE) {
- /* Another thread is in the above func(arg) call. */
- semGive(epicsThreadOnceMutex);
- epicsThreadSleep(epicsThreadSleepQuantum());
- result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
- assert(result == OK);
- }
- }
- semGive(epicsThreadOnceMutex);
-}
static void createFunction(EPICSTHREADFUNC func, void *parm)
{
@@ -173,7 +122,6 @@
EPICSTHREADFUNC funptr,void *parm)
{
int tid;
- if(epicsThreadOnceMutex==0) epicsThreadInit();
if(stackSize<100) {
errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize);
return(0);
@@ -343,7 +291,6 @@
static int lock = 0;
epicsThreadPrivateId id;
- epicsThreadInit();
/*lock is necessary because ++nepicsThreadPrivate may not be indivisible*/
while(!vxTas(&lock)) taskDelay(1);
id = (epicsThreadPrivateId)++nepicsThreadPrivate;
=== modified file 'src/libCom/test/Makefile'
--- src/libCom/test/Makefile 2011-08-30 23:09:11 +0000
+++ src/libCom/test/Makefile 2011-08-31 22:29:24 +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-08-31 22:29:24 +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-08-31 22:29:24 +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 ();
+}
- Navigate by Date:
- Prev:
Re: [Merge] lp:~epics-core/epics-base/epicsR3.15-atomics into lp:epics-base Jeff Hill
- Next:
[Merge] lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based 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:
[Merge] lp:~mshankar/epics-base/softioclogging into lp:epics-base noreply
- Next:
[Merge] lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based 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
|