Merge lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:~epics-core/epics-base/3.15

Proposed by Jeff Hill
Status: Superseded
Proposed branch: lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based
Merge into: lp:~epics-core/epics-base/3.15
Diff against target: 3899 lines (+3245/-276) (has conflicts)
38 files modified
configure/CONFIG.gnuCommon (+2/-0)
configure/CONFIG_COMMON (+18/-4)
configure/RULES_BUILD (+5/-1)
configure/os/CONFIG.solarisCommon.solarisCommon (+2/-0)
configure/os/CONFIG.win32-x86.win32-x86 (+3/-1)
src/libCom/Makefile (+283/-0)
src/libCom/misc/compilerDependencies.h (+0/-104)
src/libCom/misc/ipAddrToAsciiAsynchronous.cpp (+1/-1)
src/libCom/osi/compiler/borland/compilerSpecific.h (+55/-0)
src/libCom/osi/compiler/clang/compilerSpecific.h (+59/-0)
src/libCom/osi/compiler/clang/epicsAtomicCD.h (+27/-0)
src/libCom/osi/compiler/default/compilerSpecific.h (+45/-0)
src/libCom/osi/compiler/default/epicsAtomicCD.h (+25/-0)
src/libCom/osi/compiler/gcc/compilerSpecific.h (+62/-0)
src/libCom/osi/compiler/gcc/epicsAtomicCD.h (+172/-0)
src/libCom/osi/compiler/msvc/compilerSpecific.h (+57/-0)
src/libCom/osi/compiler/msvc/epicsAtomicCD.h (+124/-0)
src/libCom/osi/compiler/solStudio/epicsAtomicCD.h (+27/-0)
src/libCom/osi/compilerDependencies.h (+47/-0)
src/libCom/osi/epicsAtomic.h (+237/-0)
src/libCom/osi/epicsAtomicDefault.h (+235/-0)
src/libCom/osi/epicsThread.h (+1/-1)
src/libCom/osi/epicsThreadOnce.cpp (+129/-0)
src/libCom/osi/os/RTEMS/osdThread.c (+0/-32)
src/libCom/osi/os/WIN32/epicsAtomicMS.h (+222/-0)
src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp (+22/-0)
src/libCom/osi/os/WIN32/epicsAtomicOSD.h (+49/-0)
src/libCom/osi/os/WIN32/osdThread.c (+0/-35)
src/libCom/osi/os/posix/epicsAtomicOSD.cpp (+108/-0)
src/libCom/osi/os/posix/epicsAtomicOSD.h (+32/-0)
src/libCom/osi/os/posix/osdThread.c (+0/-44)
src/libCom/osi/os/solaris/epicsAtomicOSD.h (+166/-0)
src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp (+22/-0)
src/libCom/osi/os/vxWorks/epicsAtomicOSD.h (+255/-0)
src/libCom/osi/os/vxWorks/osdThread.c (+0/-53)
src/libCom/test/Makefile (+9/-0)
src/libCom/test/epicsAtomicPerform.cpp (+506/-0)
src/libCom/test/epicsAtomicTest.cpp (+238/-0)
Text conflict in src/libCom/Makefile
To merge this branch: bzr merge lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based
Reviewer Review Type Date Requested Status
EPICS Core Developers Pending
Review via email: mp+73605@code.launchpad.net

This proposal has been superseded by a proposal from 2011-08-31.

Description of the change

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}

To post a comment you must log in.
12261. By Jeff Hill

fixed spelling in comment

Unmerged revisions

12261. By Jeff Hill

fixed spelling in comment

12260. By Jeff Hill

o moved epicsThreadOnce impl details to anonymous namespace
o fixed recursion sanity test is too agressive
o added some comments

12259. By Jeff Hill

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}

12258. By Jeff Hill <email address hidden>

fixed names on redefinition protection macros for vxWorks

12257. By Jeff Hill

fixed epics atomic read memory barrier name - old versions of vxWorks

12256. By Jeff Hill

fixed word missing from vxWorks specific read and write memory barrier functions

12255. By Jeff Hill <email address hidden>

fixed vxWorks name for epicsAtomicTest

12254. By Jeff Hill <email address hidden>

fixed wrong return type old vxWorks epicsAtomicUnlock

12253. By Jeff Hill

fixed test count

12252. By Jeff Hill

fixed vxWorks jumbled ifdef

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== 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 @@
1212
13GNU = YES13GNU = YES
1414
15CMPLR_CLASS = gcc
16
15GNU_BIN = $(GNU_DIR)/bin17GNU_BIN = $(GNU_DIR)/bin
16GNU_LIB = $(GNU_DIR)/lib18GNU_LIB = $(GNU_DIR)/lib
1719
1820
=== 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 @@
133GENERIC_SRC_DIRS = .. $(SRC_DIRS)133GENERIC_SRC_DIRS = .. $(SRC_DIRS)
134OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \134OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
135 $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default ))135 $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default ))
136ALL_SRC_DIRS = $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)136CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
137 $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default ))
138ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
137139
138#--------------------------------------------------140#--------------------------------------------------
139# compile line include directories141# compile line include directories
140INSTALL_INCLUDES += \142INSTALL_INCLUDES += \
143 -I$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) \
141 -I$(INSTALL_INCLUDE)/os/$(OS_CLASS) \144 -I$(INSTALL_INCLUDE)/os/$(OS_CLASS) \
142 -I$(INSTALL_INCLUDE)145 -I$(INSTALL_INCLUDE)
143SRC_INCLUDES = -I$(COMMON_DIR) $(addprefix -I, $(wildcard $(ALL_SRC_DIRS)))146SRC_INCLUDES = -I$(COMMON_DIR) $(addprefix -I, $(wildcard $(ALL_SRC_DIRS)))
@@ -379,25 +382,36 @@
379#382#
380# auto determine the directory paths that things are installed to383# auto determine the directory paths that things are installed to
381# RULES:384# RULES:
382# 1) found in any one of several os specific area385# 0) found in any one of several compiler specific paths
386# => install to $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)
387# 1) not found in (0) and found in any one of several OS specific paths
383# => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS)388# => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS)
384# 2) not foundin (1) and found in generic area389# 2) not found in (1) and found in generic paths
385# => install to $(INSTALL_INCLUDE)390# => install to $(INSTALL_INCLUDE)
386# 3) not found in (1) or (2) then may be (not yet) computer generated391# 3) not found in (1) or (2) then may be (not yet) computer generated
387# => install into $(INSTALL_INCLUDE)/os/$(OS_CLASS) and let392# => install into $(INSTALL_INCLUDE)/os/$(OS_CLASS) and let
388# build rules work on vpath393# build rules work on vpath
389#394#
390# These rules guarantee that the users include from395# These rules guarantee that the users include from
391# no more than two directories396# no more than three directories
392#397#
393INSTALL_INC += $(foreach inc, $(INC), \398INSTALL_INC += $(foreach inc, $(INC), \
394 $(firstword \399 $(firstword \
400 $(CMPLR_INSTALL_INC) \
395 $(OS_INSTALL_INC) \401 $(OS_INSTALL_INC) \
396 $(GENERIC_INSTALL_INC) \402 $(GENERIC_INSTALL_INC) \
397 $(GENERATED_INSTALL_INC) ) )403 $(GENERATED_INSTALL_INC) ) )
398INSTALL_INC += $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INC_$(OS_CLASS)) )404INSTALL_INC += $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INC_$(OS_CLASS)) )
399405
400#406#
407# Rule 0
408#
409CMPLR_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/, $(INSTALL_INC_jjj) )
410INSTALL_INC_jjj = $(foreach dir, $(CMPLR_SRC_DIRS), $(INSTALL_INC_iii) )
411INSTALL_INC_iii = $(subst $(dir)/, , $(INSTALL_INC_hhh) )
412INSTALL_INC_hhh = $(wildcard $(addsuffix /$(inc), $(dir)) )
413
414#
401# Rule 1415# Rule 1
402#416#
403OS_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INSTALL_INC_ggg) )417OS_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INSTALL_INC_ggg) )
404418
=== 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 @@
408 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)408 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
409409
410$(INSTALL_INCLUDE)/os/$(OS_CLASS)/% : %410$(INSTALL_INCLUDE)/os/$(OS_CLASS)/% : %
411 $(ECHO) "Installing os dependent include file $@"411 $(ECHO) "Installing OS dependent include file $@"
412 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
413
414$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/% : %
415 $(ECHO) "Installing compiler dependent include file $@"
412 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)416 @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
413417
414$(INSTALL_DOC)/%: %418$(INSTALL_DOC)/%: %
415419
=== 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 @@
7# Sites may override these definitions in CONFIG_SITE.solaris-sparc.solaris-sparc7# Sites may override these definitions in CONFIG_SITE.solaris-sparc.solaris-sparc
8#-------------------------------------------------------8#-------------------------------------------------------
99
10CMPLR_CLASS = solStudio
11
10SPARCWORKS = /opt/SUNWspro12SPARCWORKS = /opt/SUNWspro
11GNU = NO13GNU = NO
1214
1315
=== 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 @@
1111
12VALID_BUILDS = Host Ioc12VALID_BUILDS = Host Ioc
1313
14CMPLR_CLASS = msvc
15
14# convert UNIX path to native path16# convert UNIX path to native path
15PATH_FILTER = $(subst /,\\,$(1))17PATH_FILTER = $(subst /,\\,$(1))
1618
@@ -122,7 +124,7 @@
122# /D_CRTDBG_MAP_ALLOC124# /D_CRTDBG_MAP_ALLOC
123# /RTCsu catch bugs occurring only in optimized code125# /RTCsu catch bugs occurring only in optimized code
124# /DEPICS_FREELIST_DEBUG good for detecting mem mrg bugs126# /DEPICS_FREELIST_DEBUG good for detecting mem mrg bugs
125OPT_CXXFLAGS_NO = /RTCsu /Zi 127OPT_CXXFLAGS_NO = /RTCsu /Zi
126128
127# specify object file name and location129# specify object file name and location
128OBJ_CXXFLAG = /Fo130OBJ_CXXFLAG = /Fo
129131
=== 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 @@
9TOP = ../..9TOP = ../..
10include $(TOP)/configure/CONFIG10include $(TOP)/configure/CONFIG
1111
12<<<<<<< TREE
12SRC = $(TOP)/src13SRC = $(TOP)/src
13LIBCOM = $(SRC)/libCom14LIBCOM = $(SRC)/libCom
1415
@@ -38,6 +39,288 @@
38include $(LIBCOM)/yacc/Makefile39include $(LIBCOM)/yacc/Makefile
3940
40# Library to build:41# Library to build:
42=======
43LIBCOM = $(TOP)/src/libCom
44
45# Command-line input support
46epicsReadline_CFLAGS += -DEPICS_COMMANDLINE_LIBRARY=EPICS_COMMANDLINE_LIBRARY_$(COMMANDLINE_LIBRARY)
47epicsReadline_INCLUDES += $(INCLUDES_$(COMMANDLINE_LIBRARY))
48
49#POSIX thread priority scheduling flag
50THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
51osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
52
53#epicsVersion is created by this Makefile
54INC += epicsVersion.h
55
56SRC_DIRS += $(LIBCOM)/bucketLib
57INC += bucketLib.h
58SRCS += bucketLib.c
59
60SRC_DIRS += $(LIBCOM)/ring
61#following needed for locating epicsRingPointer.h and epicsRingBytes.h
62INC += epicsRingPointer.h
63INC += epicsRingBytes.h
64SRCS += epicsRingPointer.cpp
65SRCS += epicsRingBytes.c
66
67SRC_DIRS += $(LIBCOM)/calc
68INC += postfix.h
69SRCS += postfix.c
70SRCS += calcPerform.c
71
72SRC_DIRS += $(LIBCOM)/cvtFast
73INC += cvtFast.h
74SRCS += cvtFast.c
75
76# From cppStd
77SRC_DIRS += $(LIBCOM)/cppStd
78INC += epicsAlgorithm.h
79INC += epicsExcept.h
80INC += epicsMemory.h
81
82# From cxxTemplates
83SRC_DIRS += $(LIBCOM)/cxxTemplates
84INC += resourceLib.h
85INC += tsDLList.h
86INC += tsSLList.h
87INC += tsMinMax.h
88INC += tsBTree.h
89INC += tsFreeList.h
90INC += epicsSingleton.h
91INC += epicsGuard.h
92INC += epicsOnce.h
93SRCS += resourceLib.cpp
94SRCS += epicsOnce.cpp
95SRCS += epicsSingletonMutex.cpp
96
97SRC_DIRS += $(LIBCOM)/dbmf
98INC += dbmf.h
99SRCS += dbmf.c
100
101SRC_DIRS += $(LIBCOM)/ellLib
102INC += ellLib.h
103SRCS += ellLib.c
104
105SRC_DIRS += $(LIBCOM)/env
106INC += envDefs.h
107SRCS += envSubr.c
108SRCS += envData.c
109
110SRC_DIRS += $(LIBCOM)/error
111INC += epicsPrint.h
112INC += errMdef.h
113INC += errSymTbl.h
114INC += errlog.h
115INC += error.h
116SRCS += errlog.c
117SRCS += errSymLib.c
118SRCS += errSymTbl.c
119
120SRC_DIRS += $(LIBCOM)/fdmgr
121INC += fdManager.h
122INC += fdmgr.h
123SRCS += fdmgr.cpp
124SRCS += fdManager.cpp
125
126SRC_DIRS += $(LIBCOM)/freeList
127INC += freeList.h
128SRCS += freeListLib.c
129HTMLS += freeList/freeList.html
130
131SRC_DIRS += $(LIBCOM)/gpHash
132INC += gpHash.h
133SRCS += gpHashLib.c
134HTMLS += gpHash/gpHash.html
135
136SRC_DIRS += $(LIBCOM)/iocsh
137INC += iocsh.h
138INC += registry.h
139INC += libComRegister.h
140SRCS += iocsh.cpp
141SRCS += registry.c
142SRCS += libComRegister.c
143
144SRC_DIRS += $(LIBCOM)/logClient
145INC += iocLog.h
146INC += logClient.h
147SRCS += iocLog.c
148SRCS += logClient.c
149
150SRC_DIRS += $(LIBCOM)/macLib
151INC += macLib.h
152SRCS += macCore.c
153SRCS += macEnv.c
154SRCS += macUtil.c
155
156SRC_DIRS += $(LIBCOM)/misc
157INC += adjustment.h
158INC += cantProceed.h
159INC += dbDefs.h
160INC += epicsConvert.h
161INC += epicsExit.h
162INC += epicsStdlib.h
163INC += epicsString.h
164INC += epicsTypes.h
165INC += shareLib.h
166INC += epicsExport.h
167INC += unixFileName.h
168INC += locationException.h
169INC += ipAddrToAsciiAsynchronous.h
170INC += epicsUnitTest.h
171INC += testMain.h
172SRCS += aToIPAddr.c
173SRCS += adjustment.c
174SRCS += cantProceed.c
175SRCS += epicsConvert.c
176SRCS += epicsExit.c
177SRCS += epicsStdlib.c
178SRCS += epicsString.c
179SRCS += truncateFile.c
180SRCS += ipAddrToAsciiAsynchronous.cpp
181SRCS += epicsUnitTest.c
182
183# From osi
184SRC_DIRS += $(LIBCOM)/osi
185INC += osiFileName.h
186INC += osiSock.h
187INC += osdSock.h
188INC += epicsInterrupt.h
189INC += osdInterrupt.h
190
191INC += epicsMutex.h
192INC += osdMutex.h
193INC += epicsEvent.h
194INC += osdEvent.h
195INC += epicsMath.h
196INC += osdMessageQueue.h
197INC += osdStrtod.h
198
199INC += epicsAssert.h
200INC += epicsFindSymbol.h
201INC += osiPoolStatus.h
202INC += osdPoolStatus.h
203INC += osdThread.h
204
205INC += epicsThread.h
206INC += epicsTime.h
207INC += epicsGeneralTime.h
208INC += osdTime.h
209INC += generalTimeSup.h
210INC += osiClockTime.h
211INC += epicsSignal.h
212INC += osiProcess.h
213INC += osiUnistd.h
214INC += osiWireFormat.h
215INC += osdWireFormat.h
216INC += osdWireConfig.h
217INC += epicsAtomic.h
218INC += epicsAtomicCD.h
219INC += epicsAtomicOSD.h
220INC += epicsAtomicDefault.h
221INC += epicsEndian.h
222INC += epicsReadline.h
223INC += epicsMessageQueue.h
224INC += epicsStdio.h
225INC += epicsStdioRedirect.h
226INC += epicsGetopt.h
227
228INC += devLib.h
229INC += devLibVME.h
230INC += devLibVMEImpl.h
231INC += osdVME.h
232INC += compilerDependencies.h
233INC += compilerSpecific.h
234
235SRCS += epicsThread.cpp
236SRCS += epicsMutex.cpp
237SRCS += epicsEvent.cpp
238SRCS += epicsTime.cpp
239SRCS += epicsMessageQueue.cpp
240SRCS += epicsMath.cpp
241SRCS += epicsAtomicOSD.cpp
242
243SRCS += epicsGeneralTime.c
244SRCS += osiClockTime.c
245
246SRCS += osdSock.c
247SRCS += osdSockAddrReuse.cpp
248SRCS += osiSock.c
249SRCS += systemCallIntMech.cpp
250SRCS += epicsSocketConvertErrnoToString.cpp
251SRCS += osdAssert.c
252SRCS += osdFindSymbol.c
253SRCS += osdInterrupt.c
254SRCS += osdPoolStatus.c
255SRCS += osdSignal.cpp
256SRCS += osdEnv.c
257SRCS += epicsReadline.c
258SRCS += epicsTempFile.cpp
259SRCS += epicsThreadOnce.cpp
260SRCS += epicsStdio.c
261SRCS += osdStdio.c
262
263osdEnv_CFLAGS_WIN32= -U__STDC__
264
265SRCS += osdThread.c
266SRCS += osdMutex.c
267SRCS += osdEvent.c
268SRCS += osdTime.cpp
269SRCS += osdProcess.c
270SRCS += osdNetIntf.c
271SRCS += osdMessageQueue.c
272
273SRCS += devLibVME.c
274SRCS += devLibVMEOSD.c
275
276SRC_DIRS += $(LIBCOM)/taskwd
277INC += taskwd.h
278SRCS += taskwd.c
279
280SRC_DIRS += $(LIBCOM)/timer
281INC += epicsTimer.h
282SRCS += epicsTimer.cpp
283SRCS += timer.cpp
284SRCS += timerQueue.cpp
285SRCS += timerQueueActive.cpp
286SRCS += timerQueueActiveMgr.cpp
287SRCS += timerQueuePassive.cpp
288
289#tsDefs contains R3.13 compatibility tsStamp code
290SRC_DIRS += $(LIBCOM)/tsDefs
291INC += tsDefs.h
292SRCS += tsDefs.c
293
294# Time providers, in osi
295SRCS_vxWorks += osiNTPTime.c
296SRCS_RTEMS += osiNTPTime.c
297
298# These files are in osi/os/vxWorks
299# Special reboot hook
300SRCS_vxWorks += atReboot.cpp
301# For old vxWorks applications
302INC_vxWorks += camacLib.h
303INC_vxWorks += epicsDynLink.h
304INC_vxWorks += module_types.h
305INC_vxWorks += task_params.h
306SRCS_vxWorks += epicsDynLink.c
307SRCS_vxWorks += veclist.c
308SRCS_vxWorks += logMsgToErrlog.cpp
309
310#This forces the vxWorks compatibility stuff to be loaded
311OBJS_vxWorks = vxComLibrary
312
313# These files are in osi/os/WIN32
314INC_WIN32 += epicsAtomicMS.h
315SRCS_WIN32 += epicsGetopt.c
316SRCS_WIN32 += setThreadName.cpp
317#SRCS_WIN32 += dllmain.cpp
318SRCS_WIN32 += forceBadAllocException.cpp
319
320# Library to build:
321# lib$(LIBRARY).a or ..dll/..exp/..lib
322#
323>>>>>>> MERGE-SOURCE
41LIBRARY=Com324LIBRARY=Com
42325
43Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32326Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
44327
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerDependencies_h
18#define compilerDependencies_h
19
20/*
21 * This is an attempt to move all tests identifying what features a
22 * compiler supports into one file.
23 *
24 * Since this is a compiler, and not os dependent, issue then ifdefs
25 * are used. The ifdefs allow us to make the default assumption that
26 * standards incompliance issues will be fixed by future compiler
27 * releases.
28 */
29
30#ifdef __cplusplus
31
32/*
33 * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
34 * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
35 */
36
37#if defined ( _MSC_VER )
38# if _MSC_VER >= 1200 /* visual studio 6.0 or later */
39# define CXX_PLACEMENT_DELETE
40# endif
41# if _MSC_VER > 1300 /* some release after visual studio 7 we hope */
42# define CXX_THROW_SPECIFICATION
43# endif
44#elif defined ( __HP_aCC )
45# if _HP_aCC > 33300
46# define CXX_PLACEMENT_DELETE
47# endif
48# define CXX_THROW_SPECIFICATION
49#elif defined ( __BORLANDC__ )
50# if __BORLANDC__ >= 0x600
51# define CXX_PLACEMENT_DELETE
52# endif
53# define CXX_THROW_SPECIFICATION
54#elif defined ( __GNUC__ )
55# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 )
56# define CXX_THROW_SPECIFICATION
57# endif
58# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
59# define CXX_PLACEMENT_DELETE
60# endif
61#else
62# define CXX_PLACEMENT_DELETE
63# define CXX_THROW_SPECIFICATION
64#endif
65
66/*
67 * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error ))
68 */
69#if defined ( CXX_THROW_SPECIFICATION )
70# define epicsThrows(X) throw X
71#else
72# define epicsThrows(X)
73#endif
74
75/*
76 * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & ))
77 */
78#if defined ( CXX_PLACEMENT_DELETE )
79# define epicsPlacementDeleteOperator(X) void operator delete X;
80#else
81# define epicsPlacementDeleteOperator(X)
82#endif
83
84#endif /* __cplusplus */
85
86/*
87 * Enable format-string checking if possible
88 */
89#ifdef __GNUC__
90# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
91#else
92# define EPICS_PRINTF_STYLE(f,a)
93#endif
94
95/*
96 * Deprecation marker
97 */
98#if defined( __GNUC__ ) && (__GNUC__ > 2)
99# define EPICS_DEPRECATED __attribute__((deprecated))
100#else
101# define EPICS_DEPRECATED
102#endif
103
104#endif /* ifndef compilerDependencies_h */
1050
=== 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 @@
127ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;127ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
128unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;128unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;
129bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;129bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;
130static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0;130static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
131131
132// the users are not required to supply a show routine132// the users are not required to supply a show routine
133// for there transaction callback class133// for there transaction callback class
134134
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerSpecific_h
18#define compilerSpecific_h
19
20#ifndef __BORLANDC__
21# error compiler/borland/compilerSpecific.h is only for use with the Borland compiler
22#endif
23
24#ifdef __cplusplus
25
26/*
27 * in general we dont like ifdefs but they do allow us to check the
28 * compiler version and make the optimistic assumption that
29 * standards incompliance issues will be fixed by future compiler
30 * releases
31 */
32
33/*
34 * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
35 * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
36 */
37#if __BORLANDC__ >= 0x600
38# define CXX_PLACEMENT_DELETE
39#endif
40
41#define CXX_THROW_SPECIFICATION
42
43#endif /* __cplusplus */
44
45/*
46 * Enable format-string checking if possible
47 */
48#define EPICS_PRINTF_STYLE(f,a)
49
50/*
51 * Deprecation marker
52 */
53#define EPICS_DEPRECATED
54
55#endif /* ifndef compilerSpecific_h */
056
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerSpecific_h
18#define compilerSpecific_h
19
20#ifndef __clang__
21# error compiler/clang/compilerSpecific.h is only for use with the clang compiler
22#endif
23
24/*
25 * WARNING: the current state of this file is only based on reading clang manuals
26 * and has not actually been tested with the compiler
27 */
28#pragma warning compiler/clang/compilerSpecific.h is based on reading the manual, but hasnt been tested with the clang compiler
29
30#ifdef __cplusplus
31
32/*
33 * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
34 * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
35 */
36#define CXX_PLACEMENT_DELETE
37#define CXX_THROW_SPECIFICATION
38
39#endif /* __cplusplus */
40
41/*
42 * Enable format-string checking if possible
43 */
44#if __has_attribute(format)
45# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
46#else
47# define EPICS_PRINTF_STYLE
48#endif
49
50/*
51 * Deprecation marker if possible
52 */
53#if __has_attribute(deprecated)
54# define EPICS_DEPRECATED __attribute__((deprecated))
55#else
56# define EPICS_DEPRECATED
57#endif
58
59#endif /* ifndef compilerSpecific_h */
060
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicCD_h
17#define epicsAtomicCD_h
18
19#if defined ( __cplusplus )
20# define EPICS_ATOMIC_INLINE inline
21#else
22# define EPICS_ATOMIC_INLINE __inline__
23#endif
24
25#include "epicsAtomicOSD.h"
26
27#endif /* epicsAtomicCD_h */
028
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerSpecific_h
18#define compilerSpecific_h
19
20#ifdef __cplusplus
21
22/*
23 * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
24 * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
25 *
26 * (our default guess is that the compiler implements the C++ 97 standard)
27 */
28#define CXX_THROW_SPECIFICATION
29#define CXX_PLACEMENT_DELETE
30
31#endif /* __cplusplus */
32
33/*
34 * Enable format-string checking if possible
35 * (our default guess is that the compiler doesnt implement non-standard extensions)
36 */
37#define EPICS_PRINTF_STYLE(f,a)
38
39/*
40 * Deprecation marker
41 * (our default guess is that the compiler doesnt implement non-standard extensions)
42 */
43#define EPICS_DEPRECATED
44
45#endif /* ifndef compilerSpecific_h */
046
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicCD_h
17#define epicsAtomicCD_h
18
19#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus )
20# define EPICS_ATOMIC_INLINE inline
21#endif
22
23#include "epicsAtomicOSD.h"
24
25#endif /* epicsAtomicCD_h */
026
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerSpecific_h
18#define compilerSpecific_h
19
20#ifndef __GNUC__
21# error compiler/gcc/compilerSpecific.h is only for use with the gnu compiler
22#endif
23
24#ifdef __cplusplus
25
26/*
27 * in general we dont like ifdefs but they do allow us to check the
28 * compiler version and make the optimistic assumption that
29 * standards incompliance issues will be fixed by future compiler
30 * releases
31 */
32
33/*
34 * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
35 * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
36 */
37
38#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 )
39# define CXX_THROW_SPECIFICATION
40#endif
41
42#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 )
43# define CXX_PLACEMENT_DELETE
44#endif
45
46#endif /* __cplusplus */
47
48/*
49 * Enable format-string checking if possible
50 */
51#define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a)))
52
53/*
54 * Deprecation marker if possible
55 */
56#if (__GNUC__ > 2)
57# define EPICS_DEPRECATED __attribute__((deprecated))
58#else
59# define EPICS_DEPRECATED
60#endif
61
62#endif /* ifndef compilerSpecific_h */
063
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicCD_h
17#define epicsAtomicCD_h
18
19#ifndef __GNUC__
20# error this header is only for use with the gnu compiler
21#endif
22
23#define EPICS_ATOMIC_INLINE __inline__
24
25#define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
26#define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
27
28#define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
29 GCC_ATOMIC_CONCAT ( \
30 __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
31 __SIZEOF_INT__ )
32
33#define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
34 GCC_ATOMIC_CONCAT ( \
35 __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
36 __SIZEOF_SIZE_T__ )
37
38#define GCC_ATOMIC_INTRINSICS_MIN_X86 \
39 ( defined ( __i486 ) || defined ( __pentium ) || \
40 defined ( __pentiumpro ) || defined ( __MMX__ ) )
41
42#define GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER \
43 ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 )
44
45#define GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER \
46 ( GCC_ATOMIC_INTRINSICS_MIN_X86 && \
47 GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER )
48
49#ifdef __cplusplus
50extern "C" {
51#endif
52
53/*
54 * We are optimistic that __sync_synchronize is implemented
55 * in all version four gcc invarient of target. The gnu doc
56 * seems to say that when not supported by architecture a call
57 * to an external function is generated but in practice
58 * this isnt the case for some of the atomic intrinsics, and
59 * so there is an undefined symbol. So far we have not seen
60 * that with __sync_synchronize, but we can only guess based
61 * on experimental evidence.
62 *
63 * For example we know that when generating object code for
64 * 386 most of the atomic instrinsics are not present and
65 * we see undefined symbols with mingw, but we dont have
66 * troubles with __sync_synchronize.
67 */
68#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER
69
70#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
71#define EPICS_ATOMIC_READ_MEMORY_BARRIER
72EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
73{
74 __sync_synchronize ();
75}
76#endif
77
78#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
79#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
80EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
81{
82 __sync_synchronize ();
83}
84#endif
85
86#endif /* if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER */
87
88#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
89 || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
90
91#define EPICS_ATOMIC_INCR_INTT
92EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
93{
94 return __sync_add_and_fetch ( pTarget, 1 );
95}
96
97#define EPICS_ATOMIC_DECR_INTT
98EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
99{
100 return __sync_sub_and_fetch ( pTarget, 1 );
101}
102
103#define EPICS_ATOMIC_ADD_INTT
104EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
105{
106 return __sync_add_and_fetch ( pTarget, delta );
107}
108
109#define EPICS_ATOMIC_CAS_INTT
110EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
111 int oldVal, int newVal )
112{
113 return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
114}
115
116#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T */
117
118#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
119 || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
120
121#define EPICS_ATOMIC_INCR_SIZET
122EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
123{
124 return __sync_add_and_fetch ( pTarget, 1u );
125}
126
127#define EPICS_ATOMIC_DECR_SIZET
128EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
129{
130 return __sync_sub_and_fetch ( pTarget, 1u );
131}
132
133#define EPICS_ATOMIC_ADD_SIZET
134EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
135{
136 return __sync_add_and_fetch ( pTarget, delta );
137}
138
139#define EPICS_ATOMIC_SUB_SIZET
140EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
141{
142 return __sync_sub_and_fetch ( pTarget, delta );
143}
144
145#define EPICS_ATOMIC_CAS_SIZET
146EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
147 size_t oldVal, size_t newVal )
148{
149 return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
150}
151
152#define EPICS_ATOMIC_CAS_PTRT
153EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
154 EpicsAtomicPtrT * pTarget,
155 EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
156{
157 return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
158}
159
160#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T */
161
162#ifdef __cplusplus
163} /* end of extern "C" */
164#endif
165
166/*
167 * if currently unavailable as gcc intrinsics we
168 * will try for an os specific inline solution
169 */
170#include "epicsAtomicOSD.h"
171
172#endif /* epicsAtomicCD_h */
0173
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerSpecific_h
18#define compilerSpecific_h
19
20#ifndef _MSC_VER
21# error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler
22#endif
23
24#ifdef __cplusplus
25
26/*
27 * in general we dont like ifdefs but they do allow us to check the
28 * compiler version and make the optimistic assumption that
29 * standards incompliance issues will be fixed by future compiler
30 * releases
31 */
32
33/*
34 * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete
35 * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification
36 */
37#if _MSC_VER >= 1200 /* visual studio 6.0 or later */
38# define CXX_PLACEMENT_DELETE
39#endif
40
41#if _MSC_VER > 1300 /* some release after visual studio 7 we hope */
42# define CXX_THROW_SPECIFICATION
43#endif
44
45#endif /* __cplusplus */
46
47/*
48 * Enable format-string checking if possible
49 */
50#define EPICS_PRINTF_STYLE(f,a)
51
52/*
53 * Deprecation marker
54 */
55#define EPICS_DEPRECATED
56
57#endif /* ifndef compilerSpecific_h */
058
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicCD_h
17#define epicsAtomicCD_h
18
19#include "epicsAssert.h"
20
21#ifndef _MSC_VER
22# error this header file is only for use with with the Microsoft Compiler
23#endif
24
25#ifdef _MSC_EXTENSIONS
26
27#include <intrin.h>
28
29#if _MSC_VER >= 1200
30# define EPICS_ATOMIC_INLINE __forceinline
31#else
32# define EPICS_ATOMIC_INLINE __inline
33#endif
34
35#if defined ( _M_IX86 )
36# pragma warning( push )
37# pragma warning( disable : 4793 )
38 EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
39 {
40 long fence;
41 __asm { xchg fence, eax }
42 }
43# pragma warning( pop )
44#elif defined ( _M_X64 )
45# define MS_ATOMIC_64
46# pragma intrinsic ( __faststorefence )
47 EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
48 {
49 __faststorefence ();
50 }
51#elif defined ( _M_IA64 )
52# define MS_ATOMIC_64
53# pragma intrinsic ( __mf )
54 EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier ()
55 {
56 __mf ();
57 }
58#else
59# error unexpected target architecture, msvc version of epicsAtomicCD.h
60#endif
61
62/*
63 * The windows doc appears to recommend defining InterlockedExchange
64 * to be _InterlockedExchange to cause it to be an intrinsic, but that
65 * creates issues when later, in a windows os specific header, we include
66 * windows.h. Therefore, we except some code duplication between the msvc
67 * csAtomic.h and win32 osdAtomic.h to avoid problems, and to keep the
68 * os specific windows.h header file out of the msvc cdAtomic.h
69 */
70#define MS_LONG long
71#define MS_InterlockedExchange _InterlockedExchange
72#define MS_InterlockedCompareExchange _InterlockedCompareExchange
73#define MS_InterlockedIncrement _InterlockedIncrement
74#define MS_InterlockedDecrement _InterlockedDecrement
75#define MS_InterlockedExchange _InterlockedExchange
76#define MS_InterlockedExchangeAdd _InterlockedExchangeAdd
77#if defined ( MS_ATOMIC_64 )
78# define MS_LONGLONG long long
79# define MS_InterlockedIncrement64 _InterlockedIncrement64
80# define MS_InterlockedDecrement64 _InterlockedDecrement64
81# define MS_InterlockedExchange64 _InterlockedExchange64
82# define MS_InterlockedExchangeAdd64 _InterlockedExchangeAdd64
83# define MS_InterlockedCompareExchange64 _InterlockedCompareExchange64
84#endif
85
86#ifdef __cplusplus
87extern "C" {
88#endif /* __cplusplus */
89
90#define EPICS_ATOMIC_READ_MEMORY_BARRIER
91EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
92{
93 epicsAtomicMemoryBarrier ();
94}
95
96#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
97EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
98{
99 epicsAtomicMemoryBarrier ();
100}
101
102#ifdef __cplusplus
103} /* end of extern "C" */
104#endif /* __cplusplus */
105
106#include "epicsAtomicMS.h"
107#include "epicsAtomicDefault.h"
108
109#else /* ifdef _MSC_EXTENSIONS */
110
111#if defined ( __cplusplus )
112# define EPICS_ATOMIC_INLINE inline
113#endif
114
115/*
116 * if unavailable as an intrinsic we will try
117 * for os specific solution
118 */
119#include "epicsAtomicOSD.h"
120
121#endif /* ifdef _MSC_EXTENSIONS */
122
123#endif /* epicsAtomicCD_h */
124
0125
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicCD_h
17#define epicsAtomicCD_h
18
19#if defined ( __cplusplus )
20# define EPICS_ATOMIC_INLINE inline
21#else
22# define EPICS_ATOMIC_INLINE __inline
23#endif
24
25#include "epicsAtomicOSD.h"
26
27#endif /* epicsAtomicCD_h */
028
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
4* National Laboratory.
5* Copyright (c) 2002 The Regents of the University of California, as
6* Operator of Los Alamos National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author:
13 * Jeffrey O. Hill
14 * johill@lanl.gov
15 */
16
17#ifndef compilerDependencies_h
18#define compilerDependencies_h
19
20#include "compilerSpecific.h"
21
22#ifdef __cplusplus
23
24/*
25 * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error ))
26 *
27 * Note: now a widely accepted concensus (ref Meyers and C++ faq) is that
28 * one should avoid using throw specifications in C++ code
29 */
30#if defined ( CXX_THROW_SPECIFICATION )
31# define epicsThrows(X) throw X
32#else
33# define epicsThrows(X)
34#endif
35
36/*
37 * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & ))
38 */
39#if defined ( CXX_PLACEMENT_DELETE )
40# define epicsPlacementDeleteOperator(X) void operator delete X;
41#else
42# define epicsPlacementDeleteOperator(X)
43#endif
44
45#endif /* __cplusplus */
46
47#endif /* ifndef compilerDependencies_h */
048
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomic_h
17#define epicsAtomic_h
18
19#include <stdlib.h> /* define size_t */
20
21#include "shareLib.h"
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27typedef void * EpicsAtomicPtrT;
28
29/* load target into cache */
30epicsShareFunc void epicsAtomicReadMemoryBarrier ();
31
32/* push cache version of target into target */
33epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
34
35/*
36 * lock out other smp processors from accessing the target,
37 * load target into cache, add one to target, flush cache
38 * to target, allow other smp processors to access the target,
39 * return new value of target as modified by this operation
40 */
41epicsShareFunc size_t epicsAtomicIncrSizeT ( size_t * pTarget );
42epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget );
43
44/*
45 * lock out other smp processors from accessing the target,
46 * load target into cache, subtract one from target, flush cache
47 * to target, allow out other smp processors to access the target,
48 * return new value of target as modified by this operation
49 */
50epicsShareFunc size_t epicsAtomicDecrSizeT ( size_t * pTarget );
51epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget );
52
53/*
54 * lock out other smp processors from accessing the target,
55 * load target into cache, add/sub delta to/from target, flush cache
56 * to target, allow other smp processors to access the target,
57 * return new value of target as modified by this operation
58 */
59epicsShareFunc size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta );
60epicsShareFunc size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta );
61epicsShareFunc int epicsAtomicAddIntT ( int * pTarget, int delta );
62
63/*
64 * set cache version of target, flush cache to target
65 */
66epicsShareFunc void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue );
67epicsShareFunc void epicsAtomicSetIntT ( int * pTarget, int newValue );
68epicsShareFunc void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue );
69
70/*
71 * fetch target into cache, return new value of target
72 */
73epicsShareFunc size_t epicsAtomicGetSizeT ( const size_t * pTarget );
74epicsShareFunc int epicsAtomicGetIntT ( const int * pTarget );
75epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget );
76
77/*
78 * lock out other smp processors from accessing the target,
79 * load target into cache, if target is equal to oldVal set target
80 * to newVal, flush cache to target, allow other smp processors
81 * to access the target, return the original value stored in the
82 * target
83 */
84epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
85 size_t oldVal, size_t newVal );
86epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget,
87 int oldVal, int newVal );
88epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
89 EpicsAtomicPtrT * pTarget,
90 EpicsAtomicPtrT oldVal,
91 EpicsAtomicPtrT newVal );
92
93#ifdef __cplusplus
94} /* end of extern "C" */
95#endif
96
97/*
98 * options for inline compiler instrinsic or os specific
99 * implementations of the above function prototypes
100 *
101 * its importnat for certaiin compiler to define the
102 * inline functions before they get used in the c++
103 * code below
104 */
105#include "epicsAtomicCD.h"
106
107#ifdef __cplusplus
108
109namespace epics {
110namespace atomic {
111
112/*
113 * overloaded c++ interface
114 */
115epicsShareFunc size_t increment ( size_t & v );
116epicsShareFunc int increment ( int & v );
117epicsShareFunc size_t decrement ( size_t & v );
118epicsShareFunc int decrement ( int & v );
119epicsShareFunc size_t add ( size_t & v, size_t delta );
120epicsShareFunc int add ( int & v, int delta );
121epicsShareFunc size_t subtract ( size_t & v, size_t delta );
122epicsShareFunc int subtract ( int & v, int delta );
123epicsShareFunc void set ( size_t & v , size_t newValue );
124epicsShareFunc void set ( int & v, int newValue );
125epicsShareFunc void set ( EpicsAtomicPtrT & v,
126 EpicsAtomicPtrT newValue );
127epicsShareFunc size_t get ( const size_t & v );
128epicsShareFunc int get ( const int & v );
129epicsShareFunc EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v );
130epicsShareFunc size_t compareAndSwap ( size_t & v, size_t oldVal,
131 size_t newVal );
132epicsShareFunc int compareAndSwap ( int & v, int oldVal, int newVal );
133epicsShareFunc EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
134 EpicsAtomicPtrT oldVal,
135 EpicsAtomicPtrT newVal );
136
137/************* incr ***************/
138inline size_t increment ( size_t & v )
139{
140 return epicsAtomicIncrSizeT ( & v );
141}
142
143inline int increment ( int & v )
144{
145 return epicsAtomicIncrIntT ( & v );
146}
147
148/************* decr ***************/
149inline size_t decrement ( size_t & v )
150{
151 return epicsAtomicDecrSizeT ( & v );
152}
153
154inline int decrement ( int & v )
155{
156 return epicsAtomicDecrIntT ( & v );
157}
158
159/************* add ***************/
160inline size_t add ( size_t & v, size_t delta )
161{
162 return epicsAtomicAddSizeT ( & v, delta );
163}
164
165inline int add ( int & v, int delta )
166{
167 return epicsAtomicAddIntT ( & v, delta );
168}
169
170/************* sub ***************/
171inline size_t subtract ( size_t & v, size_t delta )
172{
173 return epicsAtomicSubSizeT ( & v, delta );
174}
175
176inline int subtract ( int & v, int delta )
177{
178 return epicsAtomicAddIntT ( & v, -delta );
179}
180
181/************* set ***************/
182inline void set ( size_t & v , size_t newValue )
183{
184 epicsAtomicSetSizeT ( & v, newValue );
185}
186
187inline void set ( int & v, int newValue )
188{
189 epicsAtomicSetIntT ( & v, newValue );
190}
191
192inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue )
193{
194 epicsAtomicSetPtrT ( & v, newValue );
195}
196
197/************* get ***************/
198inline size_t get ( const size_t & v )
199{
200 return epicsAtomicGetSizeT ( & v );
201}
202
203inline int get ( const int & v )
204{
205 return epicsAtomicGetIntT ( & v );
206}
207
208inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v )
209{
210 return epicsAtomicGetPtrT ( & v );
211}
212
213/************* cas ***************/
214inline size_t compareAndSwap ( size_t & v,
215 size_t oldVal, size_t newVal )
216{
217 return epicsAtomicCmpAndSwapSizeT ( & v, oldVal, newVal );
218}
219
220inline int compareAndSwap ( int & v, int oldVal, int newVal )
221{
222 return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal );
223}
224
225inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v,
226 EpicsAtomicPtrT oldVal,
227 EpicsAtomicPtrT newVal )
228{
229 return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal );
230}
231
232} /* end of namespace atomic */
233} /* end of namespace epics */
234
235#endif /* ifdef __cplusplus */
236
237#endif /* epicsAtomic_h */
0238
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicDefault_h
17#define epicsAtomicDefault_h
18
19/*
20 * EPICS_ATOMIC_INLINE might be defined, but empty for an out-of-line
21 * instantiation
22 */
23#ifdef EPICS_ATOMIC_INLINE
24
25#ifdef __cpluplus
26extern "C" {
27#endif
28
29/*
30 * struct EpicsAtomicLockKey;
31 * epicsShareFunc void epicsAtomicReadMemoryBarrier ();
32 * epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
33 * epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
34 * epicsShareFunc void epicsAtomicUnock ( struct EpicsAtomicLockKey * );
35 */
36
37/*
38 * incr
39 */
40#ifndef EPICS_ATOMIC_INCR_INTT
41EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
42{
43 EpicsAtomicLockKey key;
44 epicsAtomicLock ( & key );
45 const int result = ++(*pTarget);
46 epicsAtomicUnlock ( & key );
47 return result;
48}
49#endif
50
51#ifndef EPICS_ATOMIC_INCR_SIZET
52EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
53{
54 EpicsAtomicLockKey key;
55 epicsAtomicLock ( & key );
56 const size_t result = ++(*pTarget);
57 epicsAtomicUnlock ( & key );
58 return result;
59}
60#endif
61
62/*
63 * decr
64 */
65#ifndef EPICS_ATOMIC_DECR_INTT
66EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
67{
68 EpicsAtomicLockKey key;
69 epicsAtomicLock ( & key );
70 const int result = --(*pTarget);
71 epicsAtomicUnlock ( & key );
72 return result;
73}
74#endif
75
76#ifndef EPICS_ATOMIC_DECR_SIZET
77EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
78{
79 EpicsAtomicLockKey key;
80 epicsAtomicLock ( & key );
81 const size_t result = --(*pTarget);
82 epicsAtomicUnlock ( & key );
83 return result;
84}
85#endif
86
87/*
88 * add/sub
89 */
90#ifndef EPICS_ATOMIC_ADD_INTT
91EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
92{
93 EpicsAtomicLockKey key;
94 epicsAtomicLock ( & key );
95 const int result = *pTarget += delta;
96 epicsAtomicUnlock ( & key );
97 return result;
98}
99#endif
100
101#ifndef EPICS_ATOMIC_ADD_SIZET
102EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
103{
104 EpicsAtomicLockKey key;
105 epicsAtomicLock ( & key );
106 const size_t result = *pTarget += delta;
107 epicsAtomicUnlock ( & key );
108 return result;
109}
110#endif
111
112#ifndef EPICS_ATOMIC_SUB_SIZET
113EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
114{
115 EpicsAtomicLockKey key;
116 epicsAtomicLock ( & key );
117 const size_t result = *pTarget -= delta;
118 epicsAtomicUnlock ( & key );
119 return result;
120}
121#endif
122
123/*
124 * set
125 */
126#ifndef EPICS_ATOMIC_SET_INTT
127EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newVal )
128{
129 *pTarget = newVal;
130 epicsAtomicWriteMemoryBarrier ();
131}
132#endif
133
134#ifndef EPICS_ATOMIC_SET_SIZET
135EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal )
136{
137 *pTarget = newVal;
138 epicsAtomicWriteMemoryBarrier ();
139}
140#endif
141
142#ifndef EPICS_ATOMIC_SET_PTRT
143EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget,
144 EpicsAtomicPtrT newVal )
145{
146 *pTarget = newVal;
147 epicsAtomicWriteMemoryBarrier ();
148}
149#endif
150
151/*
152 * get
153 */
154#ifndef EPICS_ATOMIC_GET_INTT
155EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget )
156{
157 epicsAtomicReadMemoryBarrier ();
158 return *pTarget;
159}
160#endif
161
162#ifndef EPICS_ATOMIC_GET_SIZET
163EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget )
164{
165 epicsAtomicReadMemoryBarrier ();
166 return *pTarget;
167}
168#endif
169
170#ifndef EPICS_ATOMIC_GET_PTRT
171EPICS_ATOMIC_INLINE EpicsAtomicPtrT
172 epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget )
173{
174 epicsAtomicReadMemoryBarrier ();
175 return *pTarget;
176}
177#endif
178
179/*
180 * cmp and swap
181 */
182#ifndef EPICS_ATOMIC_CAS_INTT
183EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldval, int newval )
184{
185 EpicsAtomicLockKey key;
186 epicsAtomicLock ( & key );
187 const int cur = *pTarget;
188 if ( cur == oldval ) {
189 *pTarget = newval;
190 }
191 epicsAtomicUnlock ( & key );
192 return cur;
193}
194#endif
195
196#ifndef EPICS_ATOMIC_CAS_SIZET
197EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
198 size_t oldval, size_t newval )
199{
200 EpicsAtomicLockKey key;
201 epicsAtomicLock ( & key );
202 const size_t cur = *pTarget;
203 if ( cur == oldval ) {
204 *pTarget = newval;
205 }
206 epicsAtomicUnlock ( & key );
207 return cur;
208}
209#endif
210
211#ifndef EPICS_ATOMIC_CAS_PTRT
212EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
213 EpicsAtomicPtrT * pTarget,
214 EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval )
215{
216 EpicsAtomicLockKey key;
217 epicsAtomicLock ( & key );
218 const EpicsAtomicPtrT cur = *pTarget;
219 if ( cur == oldval ) {
220 *pTarget = newval;
221 }
222 epicsAtomicUnlock ( & key );
223 return cur;
224}
225#endif
226
227#ifdef __cpluplus
228} /* end of extern "C" */
229#endif
230
231#endif /* EPICS_ATOMIC_INLINE */
232
233#endif /* epicsAtomicDefault_h */
234
235
0236
=== 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 @@
51/* (epicsThreadId)0 is guaranteed to be an invalid thread id */51/* (epicsThreadId)0 is guaranteed to be an invalid thread id */
52typedef struct epicsThreadOSD *epicsThreadId;52typedef struct epicsThreadOSD *epicsThreadId;
5353
54typedef epicsThreadId epicsThreadOnceId;54typedef void * epicsThreadOnceId;
55#define EPICS_THREAD_ONCE_INIT 055#define EPICS_THREAD_ONCE_INIT 0
5656
57epicsShareFunc void epicsShareAPI epicsThreadOnce(57epicsShareFunc void epicsShareAPI epicsThreadOnce(
5858
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* Copyright (c) 2002 The Regents of the University of California, as
8* Operator of Los Alamos National Laboratory.
9* EPICS BASE is distributed subject to a Software License Agreement found
10* in file LICENSE that is included with this distribution.
11\*************************************************************************/
12
13/*
14 * Author Jeffrey O. Hill johill@lanl.gov
15 * Original Authors (before converting to operating system independent code):
16 * Jeff Hill, Andrew Johnson, Marty Kraimer, Eric Norum
17 */
18
19#include <cstdlib>
20
21#define epicsExportSharedSymbols
22#include "errlog.h"
23#include "cantProceed.h"
24#include "epicsThread.h"
25#include "epicsAtomic.h"
26#include "epicsAssert.h"
27
28namespace {
29
30struct ThreadID {
31public:
32 ThreadID ();
33 ThreadID ( epicsThreadId id );
34 bool operator == ( const ThreadID & ) const;
35private:
36 epicsThreadId m_threadId;
37 ThreadID ( const ThreadID & ); // disabled
38 ThreadID & operator = ( const ThreadID & ); // disabled
39};
40
41inline ThreadID :: ThreadID ( epicsThreadId id ) :
42 m_threadId ( id )
43{
44}
45
46inline ThreadID :: ThreadID () : m_threadId ( 0 )
47{
48}
49
50inline bool ThreadID :: operator == ( const ThreadID & ctrl ) const
51{
52 return ctrl.m_threadId == m_threadId;
53}
54
55static ThreadID done;
56
57} // end of namespace annonymous
58
59using namespace epics;
60using namespace atomic;
61
62/*
63 * epicsThreadOnceOnly ()
64 */
65static void epicsShareAPI epicsThreadOnceOnly ( epicsThreadOnceId * pId,
66 void ( * pFunc )( void * ),
67 void * pArg )
68{
69 static const epicsThreadOnceId idStartup = EPICS_THREAD_ONCE_INIT;
70 ThreadID self ( epicsThreadGetIdSelf () );
71 epicsThreadOnceId pCurrent = compareAndSwap ( *pId, idStartup, & self );
72 if ( pCurrent != & done ) {
73 if ( pCurrent == idStartup ) {
74 ( *pFunc ) ( pArg );
75 set ( *pId, & done );
76 }
77 else {
78 {
79 ThreadID & initID =
80 * reinterpret_cast < ThreadID * > ( pCurrent );
81 if ( initID == self ) {
82 cantProceed( "epicsThreadOnce() once was called "
83 "recursively from the user's once fuction\n" );
84 }
85 }
86 static const std :: size_t spinDownInit = 1000u;
87 static const std :: size_t spinCount = 10u;
88 STATIC_ASSERT ( spinDownInit > spinCount );
89 static const std :: size_t spinThresh = spinDownInit - spinCount;
90 std :: size_t spinDown = spinDownInit;
91 do {
92 if ( spinDown <= spinThresh ) {
93 epicsThreadSleep ( epicsThreadSleepQuantum () );
94 }
95 if ( spinDown > 0u ) {
96 spinDown--;
97 }
98 else {
99 errlogPrintf ( "epicsThreadOnce: waiting for another "
100 "thread to finish calling the once function\n" );
101 spinDown = spinThresh;
102 }
103 pCurrent = get ( *pId );
104 } while ( pCurrent != & done );
105 }
106 }
107}
108
109//
110// we implement this as a separate function so that it is easy to see
111// that the performance impact of the primary (most commonly used) path
112// and that options for inlining this function are available (based on
113// source code organization)
114//
115// performance might be slightly better if this were implemented as an inline
116// function, but that would pull epicsAtomic.h into epicsThread.h, and on
117// windows this includes (the lean and mean version of) windows.h, so perhaps
118// its best to make this an out-of-line function as that type of instantiation
119// will probably have only a small negative impact on performance
120//
121extern "C" void epicsShareAPI epicsThreadOnce ( epicsThreadOnceId * pId,
122 void ( * pFunc )( void * ),
123 void * pArg )
124{
125 const epicsThreadOnceId pCurrent = get ( *pId );
126 if ( pCurrent != & done ) {
127 epicsThreadOnceOnly ( pId, pFunc, pArg );
128 }
129}
0130
=== 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 @@
60 * Support for `once-only' execution60 * Support for `once-only' execution
61 */61 */
62static int initialized = 0;62static int initialized = 0;
63static epicsMutexId onceMutex;
6463
65/*64/*
66 * Just map osi 0 to 99 into RTEMS 199 to 10065 * Just map osi 0 to 99 into RTEMS 199 to 100
@@ -231,7 +230,6 @@
231 rtems_task_priority old;230 rtems_task_priority old;
232231
233 rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);232 rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);
234 onceMutex = epicsMutexMustCreate();
235 taskVarMutex = epicsMutexMustCreate ();233 taskVarMutex = epicsMutexMustCreate ();
236 rtems_task_ident (RTEMS_SELF, 0, &tid);234 rtems_task_ident (RTEMS_SELF, 0, &tid);
237 setThreadInfo (tid, "_main_", NULL, NULL);235 setThreadInfo (tid, "_main_", NULL, NULL);
@@ -471,36 +469,6 @@
471}469}
472470
473/*471/*
474 * Ensure func() is run only once.
475 */
476void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
477{
478 #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1
479
480 if (!initialized) epicsThreadInit();
481 epicsMutexMustLock(onceMutex);
482 if (*id != EPICS_THREAD_ONCE_DONE) {
483 if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
484 *id = epicsThreadGetIdSelf(); /* mark active */
485 epicsMutexUnlock(onceMutex);
486 func(arg);
487 epicsMutexMustLock(onceMutex);
488 *id = EPICS_THREAD_ONCE_DONE; /* mark done */
489 } else if (*id == epicsThreadGetIdSelf()) {
490 epicsMutexUnlock(onceMutex);
491 cantProceed("Recursive epicsThreadOnce() initialization\n");
492 } else
493 while (*id != EPICS_THREAD_ONCE_DONE) {
494 /* Another thread is in the above func(arg) call. */
495 epicsMutexUnlock(onceMutex);
496 epicsThreadSleep(epicsThreadSleepQuantum());
497 epicsMutexMustLock(onceMutex);
498 }
499 }
500 epicsMutexUnlock(onceMutex);
501}
502
503/*
504 * Thread private storage implementation based on the vxWorks472 * Thread private storage implementation based on the vxWorks
505 * implementation by Andrew Johnson APS/ASD.473 * implementation by Andrew Johnson APS/ASD.
506 */474 */
507475
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicMS_h
17#define epicsAtomicMS_h
18
19#include "epicsAssert.h"
20
21#ifdef __cplusplus
22extern "C" {
23#endif /* __cplusplus */
24
25#ifndef EPICS_ATOMIC_INCR_INTT
26#define EPICS_ATOMIC_INCR_INTT
27EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
28{
29 STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
30 MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
31 return MS_InterlockedIncrement ( pTarg );
32}
33#endif
34
35#ifndef EPICS_ATOMIC_DECR_INTT
36#define EPICS_ATOMIC_DECR_INTT
37EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
38{
39 STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
40 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
41 return MS_InterlockedDecrement ( pTarg );
42}
43#endif
44
45#ifndef EPICS_ATOMIC_ADD_INTT
46#define EPICS_ATOMIC_ADD_INTT
47EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
48{
49 STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
50 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
51 /* we dont use InterlockedAdd because only latest windows is supported */
52 return delta + ( int ) MS_InterlockedExchangeAdd ( pTarg,
53 ( MS_LONG ) delta );
54}
55#endif
56
57#ifndef EPICS_ATOMIC_CAS_INTT
58#define EPICS_ATOMIC_CAS_INTT
59EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
60 int oldVal, int newVal )
61{
62 STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) );
63 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
64 return (int) MS_InterlockedCompareExchange ( pTarg,
65 (MS_LONG) newVal, (MS_LONG) oldVal );
66}
67#endif
68
69#if ! defined ( MS_ATOMIC_64 )
70
71/*
72 * necessary for next three functions
73 *
74 * looking at the MS documentation it appears that they will
75 * keep type long the same size as an int on 64 bit builds
76 */
77STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( size_t ) );
78
79#ifndef EPICS_ATOMIC_INCR_SIZET
80#define EPICS_ATOMIC_INCR_SIZET
81EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
82{
83 MS_LONG * const pTarg = ( MS_LONG * ) pTarget;
84 return MS_InterlockedIncrement ( pTarg );
85}
86#endif
87
88#ifndef EPICS_ATOMIC_DECR_SIZET
89#define EPICS_ATOMIC_DECR_SIZET
90EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
91{
92 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
93 return MS_InterlockedDecrement ( pTarg );
94}
95#endif
96
97#ifndef EPICS_ATOMIC_ADD_SIZET
98#define EPICS_ATOMIC_ADD_SIZET
99EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
100 size_t delta )
101{
102 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
103 /* we dont use InterlockedAdd because only latest windows is supported */
104 return delta + ( size_t ) MS_InterlockedExchangeAdd ( pTarg,
105 ( MS_LONG ) delta );
106}
107#endif
108
109#ifndef EPICS_ATOMIC_SUB_SIZET
110#define EPICS_ATOMIC_SUB_SIZET
111EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
112{
113 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
114 MS_LONG ldelta = (MS_LONG) delta;
115 /* we dont use InterlockedAdd because only latest windows is supported */
116 return ( ( size_t ) MS_InterlockedExchangeAdd ( pTarg, -ldelta ) ) - delta;
117}
118#endif
119
120#ifndef EPICS_ATOMIC_CAS_SIZET
121#define EPICS_ATOMIC_CAS_SIZET
122EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT (
123 size_t * pTarget,
124 size_t oldVal, size_t newVal )
125{
126 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
127 return (size_t) MS_InterlockedCompareExchange ( pTarg,
128 (MS_LONG) newVal, (MS_LONG) oldVal );
129}
130#endif
131
132#ifndef EPICS_ATOMIC_CAS_PTRT
133#define EPICS_ATOMIC_CAS_PTRT
134EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
135 EpicsAtomicPtrT * pTarget,
136 EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
137{
138 MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget );
139 return (EpicsAtomicPtrT) MS_InterlockedCompareExchange ( pTarg,
140 (MS_LONG) newVal, (MS_LONG) oldVal );
141}
142#endif
143
144#else /* ! MS_ATOMIC_64 */
145
146/*
147 * necessary for next three functions
148 */
149STATIC_ASSERT ( sizeof ( MS_LONGLONG ) == sizeof ( size_t ) );
150
151#ifndef EPICS_ATOMIC_INCR_SIZET
152#define EPICS_ATOMIC_INCR_SIZET
153EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
154{
155 MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) pTarget;
156 return ( size_t ) MS_InterlockedIncrement64 ( pTarg );
157}
158#endif
159
160#ifndef EPICS_ATOMIC_DECR_SIZET
161#define EPICS_ATOMIC_DECR_SIZET
162EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
163{
164 MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
165 return ( size_t ) MS_InterlockedDecrement64 ( pTarg );
166}
167#endif
168
169#ifndef EPICS_ATOMIC_ADD_SIZET
170#define EPICS_ATOMIC_ADD_SIZET
171EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
172{
173 MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
174 /* we dont use InterlockedAdd64 because only latest windows is supported */
175 return delta + ( size_t ) MS_InterlockedExchangeAdd64 ( pTarg,
176 ( MS_LONGLONG ) delta );
177}
178#endif
179
180#ifndef EPICS_ATOMIC_SUB_SIZET
181#define EPICS_ATOMIC_SUB_SIZET
182EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
183{
184 MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
185 MS_LONGLONG ldelta = (MS_LONGLONG) delta;
186 /* we dont use InterlockedAdd64 because only latest windows is supported */
187 return (( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, -ldelta )) - delta;
188}
189#endif
190
191#ifndef EPICS_ATOMIC_CAS_SIZET
192#define EPICS_ATOMIC_CAS_SIZET
193EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
194 size_t oldVal, size_t newVal )
195{
196 MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
197 return (size_t) MS_InterlockedCompareExchange64 ( pTarg,
198 (MS_LONGLONG) newVal,
199 (MS_LONGLONG) oldVal );
200}
201#endif
202
203#ifndef EPICS_ATOMIC_CAS_PTRT
204#define EPICS_ATOMIC_CAS_PTRT
205EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
206 EpicsAtomicPtrT * pTarget,
207 EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
208{
209 MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget );
210 return (EpicsAtomicPtrT) MS_InterlockedCompareExchange64 ( pTarg,
211 (MS_LONGLONG) newVal, (MS_LONGLONG) oldVal );
212}
213#endif
214
215#endif /* ! MS_ATOMIC_64 */
216
217#ifdef __cplusplus
218} /* end of extern "C" */
219#endif /* __cplusplus */
220
221#endif /* ifdef epicsAtomicMS_h */
222
0223
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* EPICS BASE is distributed subject to a Software License Agreement found
6* in file LICENSE that is included with this distribution.
7\*************************************************************************/
8
9/*
10 * Author Jeffrey O. Hill
11 * johill@lanl.gov
12 */
13
14#define epicsExportSharedSymbols
15#include "epicsAtomic.h"
16
17// if the compiler is unable to inline then instantiate out-of-line
18#ifndef EPICS_ATOMIC_INLINE
19#define EPICS_ATOMIC_INLINE
20#include "epicsAtomic.h"
21#endif
22
023
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicOSD_h
17#define epicsAtomicOSD_h
18
19#define VC_EXTRALEAN
20#define STRICT
21#include "windows.h"
22
23#if defined ( _WIN64 )
24# define MS_ATOMIC_64
25#endif
26
27#define MS_LONG LONG
28#define MS_InterlockedExchange InterlockedExchange
29#define MS_InterlockedCompareExchange InterlockedCompareExchange
30#define MS_InterlockedIncrement InterlockedIncrement
31#define MS_InterlockedDecrement InterlockedDecrement
32#define MS_InterlockedExchange InterlockedExchange
33#define MS_InterlockedExchangeAdd InterlockedExchangeAdd
34#if defined ( MS_ATOMIC_64 )
35# define MS_LONGLONG LONGLONG
36# define MS_InterlockedIncrement64 InterlockedIncrement64
37# define MS_InterlockedDecrement64 InterlockedDecrement64
38# define MS_InterlockedExchange64 InterlockedExchange64
39# define MS_InterlockedExchangeAdd64 InterlockedExchangeAdd64
40# define MS_InterlockedCompareExchange InterlockedCompareExchange64
41#endif
42
43#ifdef EPICS_ATOMIC_INLINE
44# include "epicsAtomicMS.h"
45# include "epicsAtomicDefault.h"
46#endif
47
48#endif /* epicsAtomicOSD_h */
49
050
=== 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 @@
1008}1008}
10091009
1010/*1010/*
1011 * epicsThreadOnce ()
1012 */
1013epicsShareFunc void epicsShareAPI epicsThreadOnce (
1014 epicsThreadOnceId *id, void (*func)(void *), void *arg )
1015{
1016 static struct epicsThreadOSD threadOnceComplete;
1017 #define EPICS_THREAD_ONCE_DONE & threadOnceComplete
1018 win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
1019
1020 assert ( pGbl );
1021
1022 EnterCriticalSection ( & pGbl->mutex );
1023
1024 if ( *id != EPICS_THREAD_ONCE_DONE ) {
1025 if ( *id == EPICS_THREAD_ONCE_INIT ) { /* first call */
1026 *id = epicsThreadGetIdSelf(); /* mark active */
1027 LeaveCriticalSection ( & pGbl->mutex );
1028 func ( arg );
1029 EnterCriticalSection ( & pGbl->mutex );
1030 *id = EPICS_THREAD_ONCE_DONE; /* mark done */
1031 } else if ( *id == epicsThreadGetIdSelf() ) {
1032 LeaveCriticalSection ( & pGbl->mutex );
1033 cantProceed( "Recursive epicsThreadOnce() initialization\n" );
1034 } else
1035 while ( *id != EPICS_THREAD_ONCE_DONE ) {
1036 /* Another thread is in the above func(arg) call. */
1037 LeaveCriticalSection ( & pGbl->mutex );
1038 epicsThreadSleep ( epicsThreadSleepQuantum() );
1039 EnterCriticalSection ( & pGbl->mutex );
1040 }
1041 }
1042 LeaveCriticalSection ( & pGbl->mutex );
1043}
1044
1045/*
1046 * epicsThreadPrivateCreate ()1011 * epicsThreadPrivateCreate ()
1047 */1012 */
1048epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate ()1013epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate ()
10491014
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* EPICS BASE is distributed subject to a Software License Agreement found
6* in file LICENSE that is included with this distribution.
7\*************************************************************************/
8
9/*
10 * Author Jeffrey O. Hill
11 * johill@lanl.gov
12 */
13
14#define epicsExportSharedSymbols
15#include "epicsAtomic.h"
16
17// if the compiler is unable to inline then instantiate out-of-line
18#ifndef EPICS_ATOMIC_INLINE
19#define EPICS_ATOMIC_INLINE
20#include "epicsAtomic.h"
21#endif
22
23/* Authors: Jeffrey O. Hill */
24#include <errno.h>
25#include <unistd.h>
26#include <pthread.h>
27
28#define epicsExportSharedSymbols
29#include "epicsAssert.h"
30
31// if the compiler is unable to inline then instantiate out-of-line
32#ifndef EPICS_ATOMIC_INLINE
33#define EPICS_ATOMIC_INLINE
34#include "epicsAtomic.h"
35#endif
36
37#ifndef EPICS_ATOMIC_LOCK
38
39/*
40 * Slow, but probably correct on all systems.
41 * Useful only if something more efficent isnt
42 * provided based on knowledge of the compiler
43 * or OS
44 *
45 * A statically initialized pthread mutex doesnt
46 * need to be destroyed
47 *
48 * !!!!!
49 * !!!!! WARNING
50 * !!!!!
51 * !!!!! Do not use this implementation on systems where
52 * !!!!! code runs at interrupt context. If so, then
53 * !!!!! an implementation must be provided that is based
54 * !!!!! on a compiler intrinsic or an interrpt lock and or
55 * !!!!! a spin lock primitive
56 * !!!!!
57 */
58static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59
60void epicsAtomicLock ( EpicsAtomicLockKey * )
61{
62 unsigned countDown = 1000u;
63 int status;
64 while ( true ) {
65 status = pthread_mutex_lock ( & mutex );
66 if ( status == 0 ) return;
67 assert ( status == EINTR );
68 static const useconds_t retryDelayUSec = 100000;
69 usleep ( retryDelayUSec );
70 countDown--;
71 assert ( countDown );
72 }
73}
74
75void epicsAtomicUnlock ( EpicsAtomicLockKey * )
76{
77 const int status = pthread_mutex_unlock ( & mutex );
78 assert ( status == 0 );
79}
80
81#endif // ifndef EPICS_ATOMIC_LOCK
82
83#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
84// Slow, but probably correct on all systems.
85// Useful only if something more efficent isnt
86// provided based on knowledge of the compiler
87// or OS
88void epicsAtomicReadMemoryBarrier ()
89{
90 EpicsAtomicLockKey key;
91 epicsAtomicLock ( & key );
92 epicsAtomicUnlock ( & key );
93}
94#endif
95
96#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
97// Slow, but probably correct on all systems.
98// Useful only if something more efficent isnt
99// provided based on knowledge of the compiler
100// or OS
101void epicsAtomicWriteMemoryBarrier ()
102{
103 EpicsAtomicLockKey key;
104 epicsAtomicLock ( & key );
105 epicsAtomicUnlock ( & key );
106}
107#endif
108
0109
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicOSD_h
17#define epicsAtomicOSD_h
18
19struct EpicsAtomicLockKey {};
20epicsShareFunc void epicsAtomicReadMemoryBarrier ();
21epicsShareFunc void epicsAtomicWriteMemoryBarrier ();
22epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * );
23epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * );
24
25#ifdef EPICS_ATOMIC_INLINE
26
27#include "epicsAtomicDefault.h"
28
29#endif /* ifdef EPICS_ATOMIC_INLINE */
30
31#endif /* epicsAtomicOSD_h */
32
033
=== 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 @@
76} epicsThreadOSD;76} epicsThreadOSD;
7777
78static pthread_key_t getpthreadInfo;78static pthread_key_t getpthreadInfo;
79static pthread_mutex_t onceLock;
80static pthread_mutex_t listLock;79static pthread_mutex_t listLock;
81static ELLLIST pthreadList = ELLLIST_INIT;80static ELLLIST pthreadList = ELLLIST_INIT;
82static commonAttr *pcommonAttr = 0;81static commonAttr *pcommonAttr = 0;
@@ -207,8 +206,6 @@
207 int status;206 int status;
208207
209 pthread_key_create(&getpthreadInfo,0);208 pthread_key_create(&getpthreadInfo,0);
210 status = pthread_mutex_init(&onceLock,0);
211 checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
212 status = pthread_mutex_init(&listLock,0);209 status = pthread_mutex_init(&listLock,0);
213 checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");210 checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
214 pcommonAttr = calloc(1,sizeof(commonAttr));211 pcommonAttr = calloc(1,sizeof(commonAttr));
@@ -321,47 +318,6 @@
321#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/318#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
322}319}
323320
324321
325epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
326{
327 static struct epicsThreadOSD threadOnceComplete;
328 #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
329 int status;
330
331 epicsThreadInit();
332 status = mutexLock(&onceLock);
333 if(status) {
334 fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
335 strerror(status));
336 exit(-1);
337 }
338
339 if (*id != EPICS_THREAD_ONCE_DONE) {
340 if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
341 *id = epicsThreadGetIdSelf(); /* mark active */
342 status = pthread_mutex_unlock(&onceLock);
343 checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
344 func(arg);
345 status = mutexLock(&onceLock);
346 checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
347 *id = EPICS_THREAD_ONCE_DONE; /* mark done */
348 } else if (*id == epicsThreadGetIdSelf()) {
349 status = pthread_mutex_unlock(&onceLock);
350 checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
351 cantProceed("Recursive epicsThreadOnce() initialization\n");
352 } else
353 while (*id != EPICS_THREAD_ONCE_DONE) {
354 /* Another thread is in the above func(arg) call. */
355 status = pthread_mutex_unlock(&onceLock);
356 checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
357 epicsThreadSleep(epicsThreadSleepQuantum());
358 status = mutexLock(&onceLock);
359 checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
360 }
361 }
362 status = pthread_mutex_unlock(&onceLock);
363 checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
364}
365
366epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,322epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
367 unsigned int priority, unsigned int stackSize,323 unsigned int priority, unsigned int stackSize,
368 EPICSTHREADFUNC funptr,void *parm)324 EPICSTHREADFUNC funptr,void *parm)
369325
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6* National Laboratory.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author Jeffrey O. Hill
13 * johill@lanl.gov
14 */
15
16#ifndef epicsAtomicOSD_h
17#define epicsAtomicOSD_h
18
19#if defined ( EPICS_ATOMIC_INLINE )
20
21/*
22 * atomic.h exists only in Solaris 10 or higher
23 */
24#if defined ( __SunOS_5_10 )
25
26#include <atomic.h>
27
28#ifdef __cplusplus
29extern "C" {
30#endif /* __cplusplus */
31
32#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
33#define EPICS_ATOMIC_READ_MEMORY_BARRIER
34EPICS_ATOMIC_INLINE int epicsAtomicReadMemoryBarrier ()
35{
36 membar_consumer ();
37}
38#endif
39
40#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
41#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
42EPICS_ATOMIC_INLINE int epicsAtomicWriteMemoryBarrier ()
43{
44 membar_producer ();
45}
46#endif
47
48#ifndef EPICS_ATOMIC_CAS_INTT
49#define EPICS_ATOMIC_CAS_INTT
50EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
51 int oldVal, int newVal )
52{
53 STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) );
54 return ( int ) atomic_cas_uint ( pTarget, ( unsigned ) oldVal,
55 ( unsigned ) newVal );
56}
57#endif
58
59#ifndef EPICS_ATOMIC_CAS_SIZET
60#define EPICS_ATOMIC_CAS_SIZET
61EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapSizeT (
62 size_t * pTarget,
63 size_t oldVal, size_t newVal )
64{
65 STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
66 void ** ppPtr = (void **) pTarget;
67 return ( size_t ) atomic_cas_ptr ( ppPtr, ( void * )oldVal, ( void * )newVal );
68}
69#endif
70
71#ifndef EPICS_ATOMIC_CAS_PTRT
72#define EPICS_ATOMIC_CAS_PTRT
73EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
74 EpicsAtomicPtrT * pTarget,
75 EpicsAtomicPtrT oldVal,
76 EpicsAtomicPtrT newVal )
77{
78 return atomic_cas_ptr ( pTarget, oldVal, newVal );
79}
80#endif
81
82#ifndef EPICS_ATOMIC_INCR_INTT
83#define EPICS_ATOMIC_INCR_INTT
84EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
85{
86 STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
87 unsigned * const pTarg = ( unsigned * ) ( pTarget );
88 return ( int ) atomic_inc_uint_nv ( pTarg );
89}
90#endif
91
92#ifndef EPICS_ATOMIC_INCR_SIZET
93#define EPICS_ATOMIC_INCR_SIZET
94EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
95{
96 STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
97 void ** const ppTarg = ( void ** ) ( pTarget );
98 return ( size_t ) atomic_inc_ptr_nv ( ppTarg );
99}
100#endif
101
102#ifndef EPICS_ATOMIC_DECR_INTT
103#define EPICS_ATOMIC_DECR_INTT
104EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
105{
106 STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
107 unsigned * const pTarg = ( unsigned * ) ( pTarget );
108 return ( int ) atomic_dec_uint_nv ( pTarg );
109}
110#endif
111
112#ifndef EPICS_ATOMIC_DECR_SIZET
113#define EPICS_ATOMIC_DECR_SIZET
114EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
115{
116 STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
117 void ** const pTarg = ( void ** ) ( pTarget );
118 return ( size_t ) atomic_dec_ptr_nv ( pTarg );
119}
120#endif
121
122#ifndef EPICS_ATOMIC_ADD_INTT
123#define EPICS_ATOMIC_ADD_INTT
124EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
125{
126 STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) );
127 unsigned * const pTarg = ( unsigned * ) ( pTarget );
128 return ( int ) atomic_add_int_nv ( pTarg, delta );
129}
130#endif
131
132#ifndef EPICS_ATOMIC_ADD_SIZET
133#define EPICS_ATOMIC_ADD_SIZET
134EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget,
135 size_t delta )
136{
137 STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
138 void ** const pTarg = ( void ** ) ( pTarget );
139 return ( size_t ) atomic_add_ptr_nv ( pTarg, ( ssize_t ) delta );
140}
141#endif
142
143#ifndef EPICS_ATOMIC_SUB_SIZET
144#define EPICS_ATOMIC_SUB_SIZET
145EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget,
146 size_t delta )
147{
148 STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) );
149 void ** const pTarg = ( void ** ) ( pTarget );
150 ssize_t = sdelta = ( ssize_t ) delta;
151 return ( size_t ) atomic_add_ptr_nv ( pTarg, -sdelta );
152}
153#endif
154
155#ifdef __cplusplus
156} /* end of extern "C" */
157#endif /* __cplusplus */
158
159#endif /* ifdef __SunOS_5_10 */
160
161#include "epicsAtomicDefault.h"
162
163#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
164
165#endif /* epicsAtomicOSD_h */
166
0167
=== 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 @@
1
2/*************************************************************************\
3* Copyright (c) 2011 LANS LLC, as Operator of
4* Los Alamos National Laboratory.
5* EPICS BASE is distributed subject to a Software License Agreement found
6* in file LICENSE that is included with this distribution.
7\*************************************************************************/
8
9/*
10 * Author Jeffrey O. Hill
11 * johill@lanl.gov
12 */
13
14#define epicsExportSharedSymbols
15#include "epicsAtomic.h"
16
17// if the compiler is unable to inline then instantiate out-of-line
18#ifndef EPICS_ATOMIC_INLINE
19#define EPICS_ATOMIC_INLINE
20#include "epicsAtomic.h"
21#endif
22
023
=== 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 @@
1/*************************************************************************\
2* Copyright (c) 2011 LANS LLC, as Operator of
3* Los Alamos National Laboratory.
4* Copyright (c) 2011 UChicago Argonne, LLC, as Operator of
5* Argonne National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/*
11 * Author Jeffrey O. Hill
12 * johill@lanl.gov
13 */
14
15#ifndef epicsAtomicOSD_h
16#define epicsAtomicOSD_h
17
18#if defined ( EPICS_ATOMIC_INLINE )
19
20#include "vxWorks.h" /* obtain the version of vxWorks */
21#include "epicsAssert.h"
22
23/*
24 * With vxWorks 6.6 and later we need to use vxAtomicLib
25 * to implement this functionality correctly on SMP systems
26 */
27#if _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606
28
29#include <limits.h>
30#include <vxAtomicLib.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif /* __cplusplus */
35
36#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
37#define EPICS_ATOMIC_READ_MEMORY_BARRIER
38EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier ()
39{
40 VX_MEM_BARRIER_R ();
41}
42#endif
43
44#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
45#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
46EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier ()
47{
48 VX_MEM_BARRIER_W ();
49}
50#endif
51
52/*
53 * we make the probably correct guess that if ULONG_MAX
54 * is the same as UINT_MAX then sizeof ( atomic_t )
55 * will be the same as sizeof ( size_t )
56 *
57 * if ULONG_MAX != UINT_MAX then its 64 bit vxWorks and
58 * WRS doesnt not supply at this time the atomic interface
59 * for 8 byte integers that is needed - so that architecture
60 * receives the lock synchronized version
61 */
62#if ULONG_MAX == UINT_MAX
63
64STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( size_t ) );
65STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( EpicsAtomicPtrT ) );
66
67
68#ifndef EPICS_ATOMIC_INCR_SIZET
69#define EPICS_ATOMIC_INCR_SIZET
70EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
71{
72 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
73 const atomic_t oldVal = vxAtomicInc ( pTarg );
74 return 1 + ( size_t ) ( oldVal );
75}
76#endif
77
78#ifndef EPICS_ATOMIC_DECR_SIZET
79#define EPICS_ATOMIC_DECR_SIZET
80EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
81{
82 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
83 const atomic_t oldVal = vxAtomicDec ( pTarg );
84 return ( ( size_t ) oldVal ) - 1u;
85}
86#endif
87
88#ifndef EPICS_ATOMIC_ADD_SIZET
89#define EPICS_ATOMIC_ADD_SIZET
90EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
91{
92 /*
93 * vxAtomicLib doc indicates that vxAtomicAdd is
94 * implemented using signed arithmetic, but it
95 * does not change the end result because twos
96 * complement addition is used in either case
97 */
98 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
99 const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
100 return delta + ( size_t ) oldVal;
101}
102#endif
103
104#ifndef EPICS_ATOMIC_SUB_SIZET
105#define EPICS_ATOMIC_SUB_SIZET
106EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
107{
108 /*
109 * vxAtomicLib doc indicates that vxAtomicSub is
110 * implemented using signed arithmetic, but it
111 * does not change the end result because twos
112 * complement subtraction is used in either case
113 */
114 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
115 const atomic_t oldVal = vxAtomicSub ( pTarg, (atomic_t) delta );
116 return ( ( size_t ) oldVal ) - delta;
117}
118#endif
119
120#ifndef EPICS_ATOMIC_CAS_SIZET
121#define EPICS_ATOMIC_CAS_SIZET
122EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
123 size_t oldVal, size_t newVal )
124{
125 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
126 return ( size_t ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
127}
128#endif
129
130#ifndef EPICS_ATOMIC_CAS_PTRT
131#define EPICS_ATOMIC_CAS_PTRT
132EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget,
133 EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
134{
135 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
136 return (EpicsAtomicPtrT) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
137}
138#endif
139
140#else /* ULONG_MAX == UINT_MAX */
141
142/*
143 * if its 64 bit SMP vxWorks and the compiler doesnt
144 * have an intrinsic then maybe there isnt any way to
145 * implement these without using a global lock because
146 * size_t is maybe bigger than atomic_t
147 *
148 * I dont yet have access to vxWorks manuals for
149 * 64 bit systems so this is still undecided, but is
150 * defaulting now to a global lock
151 */
152
153#endif /* ULONG_MAX == UINT_MAX */
154
155STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( int ) );
156
157#ifndef EPICS_ATOMIC_INCR_INTT
158#define EPICS_ATOMIC_INCR_INTT
159EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
160{
161 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
162 const atomic_t oldVal = vxAtomicInc ( pTarg );
163 return 1 + ( int ) oldVal;
164}
165#endif
166
167#ifndef EPICS_ATOMIC_DECR_INTT
168#define EPICS_ATOMIC_DECR_INTT
169EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
170{
171 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
172 const atomic_t oldVal = vxAtomicDec ( pTarg );
173 return ( ( int ) oldVal ) - 1;
174}
175#endif
176
177#ifndef EPICS_ATOMIC_ADD_INTT
178#define EPICS_ATOMIC_ADD_INTT
179EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
180{
181 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
182 const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
183 return delta + ( int ) oldVal;
184}
185#endif
186
187#ifndef EPICS_ATOMIC_CAS_INTT
188#define EPICS_ATOMIC_CAS_INTT
189EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
190 int oldVal, int newVal )
191{
192 atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
193 return ( int ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
194}
195#endif
196
197#ifdef __cplusplus
198} /* end of extern "C" */
199#endif /* __cplusplus */
200
201#else /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
202
203#include "vxLib.h"
204#include "intLib.h"
205
206#ifdef __cplusplus
207extern "C" {
208#endif /* __cplusplus */
209
210#ifndef EPICS_ATOMIC_LOCK
211#define EPICS_ATOMIC_LOCK
212
213typedef struct EpicsAtomicLockKey { int m_key; } EpicsAtomicLockKey;
214
215EPICS_ATOMIC_INLINE void epicsAtomicLock ( EpicsAtomicLockKey * pKey )
216{
217 pKey->m_key = intLock ();
218}
219
220EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey )
221{
222 intUnlock ( pKey->m_key );
223}
224#endif
225
226#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
227#define EPICS_ATOMIC_READ_MEMORY_BARRIER
228/*
229 * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
230 * (we are not protecting against multiple access to memory mapped IO)
231 */
232EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {}
233#endif
234
235#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
236#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
237/*
238 * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
239 * (we are not protecting against multiple access to memory mapped IO)
240 */
241EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () {}
242#endif
243
244#ifdef __cplusplus
245} /* end of extern "C" */
246#endif /* __cplusplus */
247
248#endif /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
249
250#include "epicsAtomicDefault.h"
251
252#endif /* if defined ( EPICS_ATOMIC_INLINE ) */
253
254#endif /* epicsAtomicOSD_h */
255
0256
=== 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 @@
53static void **papTSD = 0;53static void **papTSD = 0;
54static int nepicsThreadPrivate = 0;54static int nepicsThreadPrivate = 0;
5555
56static SEM_ID epicsThreadOnceMutex = 0;
5756
5857
59/* Just map osi 0 to 99 into vx 100 to 199 */58/* Just map osi 0 to 99 into vx 100 to 199 */
60/* remember that for vxWorks lower number means higher priority */59/* remember that for vxWorks lower number means higher priority */
@@ -83,19 +82,6 @@
83 }82 }
84}83}
8584
86static void epicsThreadInit(void)
87{
88 static int lock = 0;
89
90 while(!vxTas(&lock)) taskDelay(1);
91 if(epicsThreadOnceMutex==0) {
92 epicsThreadOnceMutex = semMCreate(
93 SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
94 assert(epicsThreadOnceMutex);
95 }
96 lock = 0;
97}
98
99unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass) 85unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
100{86{
10187
@@ -112,43 +98,6 @@
112 return stackSizeTable[stackSizeClass];98 return stackSizeTable[stackSizeClass];
113}99}
114100
115struct epicsThreadOSD {};
116 /* Strictly speaking this should be a WIND_TCB, but we only need it to
117 * be able to create an epicsThreadId that is guaranteed never to be
118 * the same as any current TID, and since TIDs are pointers this works.
119 */
120
121void epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
122{
123 static struct epicsThreadOSD threadOnceComplete;
124 #define EPICS_THREAD_ONCE_DONE &threadOnceComplete
125 int result;
126
127 epicsThreadInit();
128 result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
129 assert(result == OK);
130 if (*id != EPICS_THREAD_ONCE_DONE) {
131 if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
132 *id = epicsThreadGetIdSelf(); /* mark active */
133 semGive(epicsThreadOnceMutex);
134 func(arg);
135 result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
136 assert(result == OK);
137 *id = EPICS_THREAD_ONCE_DONE; /* mark done */
138 } else if (*id == epicsThreadGetIdSelf()) {
139 semGive(epicsThreadOnceMutex);
140 cantProceed("Recursive epicsThreadOnce() initialization\n");
141 } else
142 while (*id != EPICS_THREAD_ONCE_DONE) {
143 /* Another thread is in the above func(arg) call. */
144 semGive(epicsThreadOnceMutex);
145 epicsThreadSleep(epicsThreadSleepQuantum());
146 result = semTake(epicsThreadOnceMutex, WAIT_FOREVER);
147 assert(result == OK);
148 }
149 }
150 semGive(epicsThreadOnceMutex);
151}
152101
153102
154static void createFunction(EPICSTHREADFUNC func, void *parm)103static void createFunction(EPICSTHREADFUNC func, void *parm)
155{104{
@@ -173,7 +122,6 @@
173 EPICSTHREADFUNC funptr,void *parm)122 EPICSTHREADFUNC funptr,void *parm)
174{123{
175 int tid;124 int tid;
176 if(epicsThreadOnceMutex==0) epicsThreadInit();
177 if(stackSize<100) {125 if(stackSize<100) {
178 errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize);126 errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize);
179 return(0);127 return(0);
@@ -343,7 +291,6 @@
343 static int lock = 0;291 static int lock = 0;
344 epicsThreadPrivateId id;292 epicsThreadPrivateId id;
345293
346 epicsThreadInit();
347 /*lock is necessary because ++nepicsThreadPrivate may not be indivisible*/294 /*lock is necessary because ++nepicsThreadPrivate may not be indivisible*/
348 while(!vxTas(&lock)) taskDelay(1);295 while(!vxTas(&lock)) taskDelay(1);
349 id = (epicsThreadPrivateId)++nepicsThreadPrivate;296 id = (epicsThreadPrivateId)++nepicsThreadPrivate;
350297
=== 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 @@
108testHarness_SRCS += epicsMutexTest.cpp108testHarness_SRCS += epicsMutexTest.cpp
109TESTS += epicsMutexTest109TESTS += epicsMutexTest
110110
111TESTPROD_HOST += epicsAtomicTest
112epicsAtomicTest_SRCS += epicsAtomicTest.c
113testHarness_SRCS += epicsAtomicTest.c
114TESTS += epicsAtomicTest
115
111TESTPROD_HOST += epicsExceptionTest116TESTPROD_HOST += epicsExceptionTest
112epicsExceptionTest_SRCS += epicsExceptionTest.cpp117epicsExceptionTest_SRCS += epicsExceptionTest.cpp
113testHarness_SRCS += epicsExceptionTest.cpp118testHarness_SRCS += epicsExceptionTest.cpp
@@ -178,6 +183,10 @@
178fdmgrTest_LIBS += ca183fdmgrTest_LIBS += ca
179# FIXME: program never exits.184# FIXME: program never exits.
180185
186TESTPROD_HOST += epicsAtomicPerform
187epicsAtomicPerform_SRCS += epicsAtomicPerform.cpp
188testHarness_SRCS += epicsAtomicPerform.cpp
189
181TESTPROD_HOST += cvtFastPerform190TESTPROD_HOST += cvtFastPerform
182cvtFastPerform_SRCS += cvtFastPerform.cpp191cvtFastPerform_SRCS += cvtFastPerform.cpp
183testHarness_SRCS += cvtFastPerform.cpp192testHarness_SRCS += cvtFastPerform.cpp
184193
=== 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 @@
1
2#include <cstdlib>
3#include <cstdio>
4#include <cassert>
5#include <typeinfo>
6
7#include "epicsInterrupt.h"
8#include "epicsAtomic.h"
9#include "epicsTime.h"
10#include "epicsUnitTest.h"
11#include "testMain.h"
12
13using std :: size_t;
14using namespace epics;
15using namespace atomic;
16
17class RefCtr {
18public:
19 RefCtr ();
20 ~RefCtr ();
21 void reference ();
22 void unreference ();
23private:
24 size_t m_cnt;
25};
26
27class Ownership {
28public:
29 Ownership ();
30 Ownership ( RefCtr & refCtr );
31 Ownership ( const Ownership & );
32 ~Ownership ();
33 Ownership & operator = ( const Ownership & );
34private:
35 RefCtr * _pRefCtr;
36 static RefCtr m_noOwnership;
37};
38
39inline RefCtr :: RefCtr ()
40{
41 epicsAtomicSetSizeT ( & m_cnt, 0 );
42}
43
44inline RefCtr :: ~RefCtr ()
45{
46 unsigned cnt = epicsAtomicGetSizeT ( & m_cnt );
47 assert ( cnt == 0u );
48}
49
50inline void RefCtr :: reference ()
51{
52 epicsAtomicIncrSizeT ( & m_cnt );
53}
54
55inline void RefCtr :: unreference ()
56{
57 epicsAtomicDecrSizeT ( & m_cnt );
58}
59
60RefCtr Ownership :: m_noOwnership;
61
62inline Ownership :: Ownership () :
63 _pRefCtr ( & m_noOwnership )
64{
65 m_noOwnership.reference ();
66}
67
68inline Ownership :: Ownership ( RefCtr & refCtr ) :
69 _pRefCtr ( & refCtr )
70{
71 refCtr.reference ();
72}
73
74inline Ownership :: Ownership ( const Ownership & ownership ) :
75 _pRefCtr ( ownership._pRefCtr )
76{
77 _pRefCtr->reference ();
78}
79
80inline Ownership :: ~Ownership ()
81{
82 _pRefCtr->unreference ();
83}
84
85inline Ownership & Ownership ::
86 operator = ( const Ownership & ownership )
87{
88 RefCtr * const pOldRefCtr = _pRefCtr;
89 _pRefCtr = ownership._pRefCtr;
90 _pRefCtr->reference ();
91 pOldRefCtr->unreference ();
92 return *this;
93}
94
95inline Ownership retOwnership ( const Ownership & ownership )
96{
97 return Ownership ( ownership );
98}
99
100inline Ownership recurRetOwner10 ( const Ownership & ownershipIn )
101{
102 Ownership ownership =
103 retOwnership (
104 retOwnership (
105 retOwnership (
106 retOwnership (
107 retOwnership ( ownershipIn ) ) ) ) );
108 return retOwnership (
109 retOwnership (
110 retOwnership (
111 retOwnership (
112 retOwnership ( ownership ) ) ) ) );
113}
114
115inline Ownership recurRetOwner100 ( const Ownership & ownershipIn )
116{
117 Ownership ownership =
118 recurRetOwner10 (
119 recurRetOwner10 (
120 recurRetOwner10 (
121 recurRetOwner10 (
122 recurRetOwner10 ( ownershipIn ) ) ) ) );
123 return recurRetOwner10 (
124 recurRetOwner10 (
125 recurRetOwner10 (
126 recurRetOwner10 (
127 recurRetOwner10 ( ownership ) ) ) ) );
128}
129
130inline Ownership recurRetOwner1000 ( const Ownership & ownershipIn )
131{
132 Ownership ownership =
133 recurRetOwner100 (
134 recurRetOwner100 (
135 recurRetOwner100 (
136 recurRetOwner100 (
137 recurRetOwner100 ( ownershipIn ) ) ) ) );
138 return recurRetOwner100 (
139 recurRetOwner100 (
140 recurRetOwner100 (
141 recurRetOwner100 (
142 recurRetOwner100 ( ownership ) ) ) ) );
143}
144
145inline void passRefOwnership ( const Ownership & ownershipIn, Ownership & ownershipOut )
146{
147 ownershipOut = ownershipIn;
148}
149
150inline void passRefOwnership10 ( const Ownership & ownershipIn, Ownership & ownershipOut )
151{
152 Ownership ownershipTmp0;
153 passRefOwnership ( ownershipIn, ownershipTmp0 );
154 Ownership ownershipTmp1;
155 passRefOwnership ( ownershipTmp0, ownershipTmp1 );
156 Ownership ownershipTmp2;
157 passRefOwnership ( ownershipTmp1, ownershipTmp2 );
158 Ownership ownershipTmp3;
159 passRefOwnership ( ownershipTmp2, ownershipTmp3 );
160 Ownership ownershipTmp4;
161 passRefOwnership ( ownershipTmp3, ownershipTmp4 );
162 Ownership ownershipTmp5;
163 passRefOwnership ( ownershipTmp4, ownershipTmp5 );
164 Ownership ownershipTmp6;
165 passRefOwnership ( ownershipTmp5, ownershipTmp6 );
166 Ownership ownershipTmp7;
167 passRefOwnership ( ownershipTmp6, ownershipTmp7 );
168 Ownership ownershipTmp8;
169 passRefOwnership ( ownershipTmp7, ownershipTmp8 );
170 passRefOwnership ( ownershipTmp8, ownershipOut );
171}
172
173inline void passRefOwnership100 ( const Ownership & ownershipIn, Ownership & ownershipOut )
174{
175 Ownership ownershipTmp0;
176 passRefOwnership10 ( ownershipIn, ownershipTmp0 );
177 Ownership ownershipTmp1;
178 passRefOwnership10 ( ownershipTmp0, ownershipTmp1 );
179 Ownership ownershipTmp2;
180 passRefOwnership10 ( ownershipTmp1, ownershipTmp2 );
181 Ownership ownershipTmp3;
182 passRefOwnership10 ( ownershipTmp2, ownershipTmp3 );
183 Ownership ownershipTmp4;
184 passRefOwnership10 ( ownershipTmp3, ownershipTmp4 );
185 Ownership ownershipTmp5;
186 passRefOwnership10 ( ownershipTmp4, ownershipTmp5 );
187 Ownership ownershipTmp6;
188 passRefOwnership10 ( ownershipTmp5, ownershipTmp6 );
189 Ownership ownershipTmp7;
190 passRefOwnership10 ( ownershipTmp6, ownershipTmp7 );
191 Ownership ownershipTmp8;
192 passRefOwnership10 ( ownershipTmp7, ownershipTmp8 );
193 passRefOwnership10 ( ownershipTmp8, ownershipOut );
194}
195
196inline void passRefOwnership1000 ( const Ownership & ownershipIn, Ownership & ownershipOut )
197{
198 Ownership ownershipTmp0;
199 passRefOwnership100 ( ownershipIn, ownershipTmp0 );
200 Ownership ownershipTmp1;
201 passRefOwnership100 ( ownershipTmp0, ownershipTmp1 );
202 Ownership ownershipTmp2;
203 passRefOwnership100 ( ownershipTmp1, ownershipTmp2 );
204 Ownership ownershipTmp3;
205 passRefOwnership100 ( ownershipTmp2, ownershipTmp3 );
206 Ownership ownershipTmp4;
207 passRefOwnership100 ( ownershipTmp3, ownershipTmp4 );
208 Ownership ownershipTmp5;
209 passRefOwnership100 ( ownershipTmp4, ownershipTmp5 );
210 Ownership ownershipTmp6;
211 passRefOwnership100 ( ownershipTmp5, ownershipTmp6 );
212 Ownership ownershipTmp7;
213 passRefOwnership100 ( ownershipTmp6, ownershipTmp7 );
214 Ownership ownershipTmp8;
215 passRefOwnership100 ( ownershipTmp7, ownershipTmp8 );
216 passRefOwnership100 ( ownershipTmp8, ownershipOut );
217}
218
219time_t extTime = 0;
220
221template < class T >
222class OrdinaryIncr {
223public:
224 OrdinaryIncr () : m_target ( 0 ) {}
225 void run ();
226 void diagnostic ( double delay );
227private:
228 T m_target;
229};
230
231// tests the time it takes to perform a call to an external
232// function and also increment an integer word. The
233// epicsInterruptIsInterruptContext function is an
234// out-of-line function implemented in a sharable library
235// so hopefully it wont be optimized away.
236template < class T >
237inline void OrdinaryIncr < T > :: run ()
238{
239 m_target += epicsInterruptIsInterruptContext ();
240 m_target += epicsInterruptIsInterruptContext ();
241 m_target += epicsInterruptIsInterruptContext ();
242 m_target += epicsInterruptIsInterruptContext ();
243 m_target += epicsInterruptIsInterruptContext ();
244 m_target += epicsInterruptIsInterruptContext ();
245 m_target += epicsInterruptIsInterruptContext ();
246 m_target += epicsInterruptIsInterruptContext ();
247 m_target += epicsInterruptIsInterruptContext ();
248 m_target += epicsInterruptIsInterruptContext ();
249}
250
251template < class T >
252void OrdinaryIncr < T > :: diagnostic ( double delay )
253{
254 delay /= 10.0;
255 delay *= 1e6;
256 const char * const pName = typeid ( T ) . name ();
257 testDiag ( "raw incr of \"%s\" and a NOOP function call takes %f microseconds",
258 pName, delay );
259}
260
261template < class T >
262class AtomicIncr {
263public:
264 AtomicIncr () : m_target ( 0 ) {}
265 void run ();
266 void diagnostic ( double delay );
267private:
268 T m_target;
269};
270
271template < class T >
272inline void AtomicIncr < T > :: run ()
273{
274 increment ( m_target );
275 increment ( m_target );
276 increment ( m_target );
277 increment ( m_target );
278 increment ( m_target );
279 increment ( m_target );
280 increment ( m_target );
281 increment ( m_target );
282 increment ( m_target );
283 increment ( m_target );
284}
285
286template < class T >
287void AtomicIncr < T > :: diagnostic ( double delay )
288{
289 delay /= 10.0;
290 delay *= 1e6;
291 const char * const pName = typeid ( T ) . name ();
292 testDiag ( "epicsAtomicIncr \"%s\" takes %f microseconds",
293 pName, delay );
294}
295
296template < class T > T trueValue ();
297template < class T > T falseValue ();
298
299// int
300template <>
301inline int trueValue < int > () { return 1; }
302
303template <>
304inline int falseValue < int > () { return 0; }
305
306// size_t
307template <>
308inline size_t trueValue < size_t > () { return 1u; }
309
310template <>
311inline size_t falseValue < size_t > () { return 0u; }
312
313// EpicsAtomicPtrT
314template <>
315inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > ()
316{ static char c; return & c; }
317
318template <>
319inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > ()
320{ return 0u; }
321
322template < class T >
323class AtomicCmpAndSwap {
324public:
325 AtomicCmpAndSwap () : m_target ( 0 ) {}
326 void run ();
327 void diagnostic ( double delay );
328private:
329 T m_target;
330};
331
332template < class T >
333inline void AtomicCmpAndSwap < T > :: run ()
334{
335 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
336 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
337 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
338 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
339 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
340 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
341 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
342 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
343 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
344 compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () );
345}
346
347template < class T >
348void AtomicCmpAndSwap < T > :: diagnostic ( double delay )
349{
350 delay /= 10.0;
351 delay *= 1e6;
352 const char * const pName = typeid ( T ) . name ();
353 testDiag ( "epicsAtomicCmpAndSwap of \"%s\" takes %f microseconds",
354 pName, delay );
355}
356
357template < class T >
358class AtomicSet {
359public:
360 AtomicSet () : m_target ( 0 ) {}
361 void run ();
362 void diagnostic ( double delay );
363private:
364 T m_target;
365};
366
367template < class T >
368inline void AtomicSet < T > :: run ()
369{
370 set ( m_target, 0 );
371 set ( m_target, 0 );
372 set ( m_target, 0 );
373 set ( m_target, 0 );
374 set ( m_target, 0 );
375 set ( m_target, 0 );
376 set ( m_target, 0 );
377 set ( m_target, 0 );
378 set ( m_target, 0 );
379 set ( m_target, 0 );
380}
381
382template < class T >
383void AtomicSet < T > :: diagnostic ( double delay )
384{
385 delay /= 10.0;
386 delay *= 1e6;
387 const char * const pName = typeid ( T ) . name ();
388 testDiag ( "epicsAtomicSet of \"%s\" takes %f microseconds",
389 pName, delay );
390}
391
392static const unsigned N = 10000;
393
394void recursiveOwnershipRetPerformance ()
395{
396 RefCtr refCtr;
397 epicsTime begin = epicsTime::getCurrent ();
398 for ( size_t i = 0; i < N; i++ ) {
399 Ownership ownership ( refCtr );
400 recurRetOwner1000 ( ownership );
401 }
402 double delay = epicsTime::getCurrent () - begin;
403 delay /= N * 1000u; // convert to delay per call
404 delay *= 1e6; // convert to micro seconds
405 testDiag ( "retOwnership() takes %f microseconds", delay );
406}
407
408void ownershipPassRefPerformance ()
409{
410 RefCtr refCtr;
411 epicsTime begin = epicsTime::getCurrent ();
412 for ( size_t i = 0; i < N; i++ ) {
413 Ownership ownershipSrc ( refCtr );
414 Ownership ownershipDest;
415 passRefOwnership1000 ( ownershipSrc, ownershipDest );
416 }
417 double delay = epicsTime::getCurrent () - begin;
418 delay /= N * 1000u; // convert to delay per call
419 delay *= 1e6; // convert to micro seconds
420 testDiag ( "passRefOwnership() takes %f microseconds", delay );
421}
422
423template < class T >
424class Ten
425{
426public:
427 void run ();
428 void diagnostic ( double delay );
429 typedef Ten < Ten < T > > Hundred;
430 typedef Ten < Hundred > Thousand;
431private:
432 T m_target;
433};
434
435template < class T >
436inline void Ten < T > :: run ()
437{
438 m_target.run ();
439 m_target.run ();
440 m_target.run ();
441 m_target.run ();
442 m_target.run ();
443 m_target.run ();
444 m_target.run ();
445 m_target.run ();
446 m_target.run ();
447 m_target.run ();
448}
449
450template < class T >
451void Ten < T > :: diagnostic ( double delay )
452{
453 m_target.diagnostic ( delay / 10.0 );
454}
455
456template < class T >
457void measurePerformance ()
458{
459 epicsTime begin = epicsTime::getCurrent ();
460 T target;
461 for ( size_t i = 0; i < N; i++ ) {
462 target.run ();
463 target.run ();
464 target.run ();
465 target.run ();
466 target.run ();
467 target.run ();
468 target.run ();
469 target.run ();
470 target.run ();
471 target.run ();
472 }
473 double delay = epicsTime::getCurrent () - begin;
474 delay /= ( N * 10u ); // convert to delay per call
475 target.diagnostic ( delay );
476}
477
478template < class T >
479void measure ()
480{
481 measurePerformance < typename Ten < T > :: Hundred > ();
482}
483
484MAIN ( epicsAtomicPerform )
485{
486 testPlan ( 0 );
487 //
488 // The tests running here are measuring fast
489 // functions so they tend to be impacted
490 // by where the cache lines are wrt to the
491 // virtual pages perhap
492 //
493 measure < AtomicSet < int > > ();
494 measure < AtomicSet < size_t > > ();
495 measure < AtomicSet < void * > > ();
496 measure < OrdinaryIncr < int > > ();
497 measure < OrdinaryIncr < size_t > > ();
498 measure < AtomicIncr < int > > ();
499 measure < AtomicIncr < size_t > > ();
500 measure < AtomicCmpAndSwap < int > > ();
501 measure < AtomicCmpAndSwap < size_t > > ();
502 measure < AtomicCmpAndSwap < void * > > ();
503 recursiveOwnershipRetPerformance ();
504 ownershipPassRefPerformance ();
505 return testDone();
506}
0507
=== 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 @@
1
2#include <stdlib.h>
3#include <assert.h>
4
5#include "epicsAtomic.h"
6#include "epicsTime.h"
7#include "epicsThread.h"
8#include "epicsUnitTest.h"
9#include "testMain.h"
10
11using namespace epics;
12using namespace atomic;
13
14template < class T >
15struct TestDataIncrDecr {
16 T m_testValue;
17 size_t m_testIterations;
18};
19
20template < class T >
21struct TestDataAddSub {
22 T m_testValue;
23 size_t m_testIterations;
24 static const T delta = 17;
25};
26
27template < class T >
28static void incr ( void *arg )
29{
30 TestDataIncrDecr < T > * const pTestData =
31 reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
32 increment ( pTestData->m_testValue );
33 increment ( pTestData->m_testIterations );
34}
35
36template < class T >
37static void decr ( void *arg )
38{
39 TestDataIncrDecr < T > * const pTestData =
40 reinterpret_cast < TestDataIncrDecr < T > * > ( arg );
41 decrement ( pTestData->m_testValue );
42 increment ( pTestData->m_testIterations );
43}
44
45
46template < class T >
47static void add ( void *arg )
48{
49 TestDataAddSub < T > * const pTestData =
50 reinterpret_cast < TestDataAddSub < T > * > ( arg );
51 add ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
52 increment ( pTestData->m_testIterations );
53}
54
55template < class T >
56static void sub ( void *arg )
57{
58 TestDataAddSub < T > * const pTestData =
59 reinterpret_cast < TestDataAddSub < T > * > ( arg );
60 subtract ( pTestData->m_testValue, TestDataAddSub < T > :: delta );
61 increment ( pTestData->m_testIterations );
62}
63
64template < class T >
65struct TestDataCAS {
66 T m_testValue;
67 size_t m_testIterationsSet;
68 size_t m_testIterationsNotSet;
69};
70
71int isModulo ( size_t N, size_t n )
72{
73 return ( n % N ) == 0u;
74}
75
76template < class T >
77static T trueValue ();
78template < class T >
79static T falseValue ();
80
81// int
82template <>
83inline int trueValue < int > () { return 1; }
84
85template <>
86inline int falseValue < int > () { return 0; }
87
88// size_t
89template <>
90inline size_t trueValue < size_t > () { return 1u; }
91
92template <>
93inline size_t falseValue < size_t > () { return 0u; }
94
95// EpicsAtomicPtrT
96template <>
97inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > ()
98{ static char c; return & c; }
99
100template <>
101inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > ()
102{ return 0u; }
103
104template < class T >
105static void cas ( void *arg )
106{
107 TestDataCAS < T > * const pTestData =
108 reinterpret_cast < TestDataCAS < T > * > ( arg );
109 /*
110 * intentionally waste cpu and maximize
111 * contention for the shared data
112 */
113 increment ( pTestData->m_testIterationsNotSet );
114 while ( ! compareAndSwap ( pTestData->m_testValue,
115 falseValue < T > (),
116 trueValue < T > () ) ) {
117 }
118 decrement ( pTestData->m_testIterationsNotSet );
119 set ( pTestData->m_testValue, falseValue < T > () );
120 increment ( pTestData->m_testIterationsSet );
121}
122
123template < class T >
124void testIncrDecr ()
125{
126 static const size_t N = 100;
127 static const T NT = static_cast < T > ( N );
128
129 const unsigned int stackSize =
130 epicsThreadGetStackSize ( epicsThreadStackSmall );
131
132 TestDataIncrDecr < T > testData = { 0, N };
133 set ( testData.m_testValue, NT );
134 testOk ( get ( testData.m_testValue ) == NT,
135 "set/get %u", testData.m_testValue );
136 set ( testData.m_testIterations, 0u );
137 testOk ( get ( testData.m_testIterations ) == 0u,
138 "set/get %u", testData.m_testIterations );
139 for ( size_t i = 0u; i < N; i++ ) {
140 epicsThreadCreate ( "incr",
141 50, stackSize, incr < T >, & testData );
142 epicsThreadCreate ( "decr",
143 50, stackSize, decr < T >, & testData );
144 }
145 while ( testData.m_testIterations < 2 * N ) {
146 epicsThreadSleep ( 0.01 );
147 }
148 testOk ( get ( testData.m_testIterations ) == 2 * N,
149 "incr/decr iterations %u",
150 testData.m_testIterations );
151 testOk ( get ( testData.m_testValue ) == NT,
152 "incr/decr final value %u",
153 testData.m_testValue );
154}
155
156template < class T >
157void testAddSub ()
158{
159 static const size_t N = 100;
160 static const T NDT = TestDataAddSub < T > :: delta *
161 static_cast < T > ( N );
162
163 const unsigned int stackSize =
164 epicsThreadGetStackSize ( epicsThreadStackSmall );
165
166 TestDataIncrDecr < T > testData = { 0, N };
167 set ( testData.m_testValue, NDT );
168 testOk ( get ( testData.m_testValue ) == NDT,
169 "set/get %u", testData.m_testValue );
170 set ( testData.m_testIterations, 0u );
171 testOk ( get ( testData.m_testIterations ) == 0u,
172 "set/get %u", testData.m_testIterations );
173 for ( size_t i = 0u; i < N; i++ ) {
174 epicsThreadCreate ( "add",
175 50, stackSize, add < T >, & testData );
176 epicsThreadCreate ( "sub",
177 50, stackSize, sub < T >, & testData );
178 }
179 while ( testData.m_testIterations < 2 * N ) {
180 epicsThreadSleep ( 0.01 );
181 }
182 testOk ( get ( testData.m_testIterations ) == 2 * N,
183 "add/sub iterations %u",
184 testData.m_testIterations );
185 testOk ( get ( testData.m_testValue ) == NDT,
186 "add/sub final value %u",
187 testData.m_testValue );
188}
189
190template < class T >
191void testCAS ()
192{
193 static const size_t N = 10;
194
195 const unsigned int stackSize =
196 epicsThreadGetStackSize ( epicsThreadStackSmall );
197
198 TestDataCAS < T > testData = { 0, N, N };
199 set ( testData.m_testIterationsSet, 0 );
200 testOk ( get ( testData.m_testIterationsSet ) == 0u,
201 "set/get %u", testData.m_testIterationsSet );
202 set ( testData.m_testIterationsNotSet, 0 );
203 testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
204 "set/get %u", testData.m_testIterationsNotSet );
205 set ( testData.m_testValue, trueValue < T > () );
206 testOk ( get ( testData.m_testValue ) == trueValue < T > (),
207 "set/get a true value" );
208 for ( size_t i = 0u; i < N; i++ ) {
209 epicsThreadCreate ( "tns",
210 50, stackSize, cas < T >, & testData );
211 }
212 set ( testData.m_testValue, falseValue < T > () );
213 while ( testData.m_testIterationsSet < N ) {
214 epicsThreadSleep ( 0.01 );
215 }
216 testOk ( get ( testData.m_testIterationsSet ) == N,
217 "test and set iterations %u",
218 testData.m_testIterationsSet );
219 testOk ( get ( testData.m_testIterationsNotSet ) == 0u,
220 "test and set not-set tracking = %u",
221 testData.m_testIterationsNotSet );
222}
223
224MAIN ( epicsAtomicTest )
225{
226
227 testPlan ( 31 );
228
229 testIncrDecr < int > ();
230 testIncrDecr < size_t > ();
231 testAddSub < int > ();
232 testAddSub < size_t > ();
233 testCAS < int > ();
234 testCAS < size_t > ();
235 testCAS < EpicsAtomicPtrT > ();
236
237 return testDone ();
238}

Subscribers

People subscribed via source and target branches