Merge lp:~johill-lanl/epics-base/epicsThreadOnce-atomics-based into lp:~epics-core/epics-base/3.15
- epicsThreadOnce-atomics-based
- Merge into 3.15
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 |
Related bugs: |
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.
Commit message
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_
o removed OS dependent implementations of epicsThreadOnce from {posix, RTEMS, vxWorks, win32}
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 ipAddrToAsciiAs ynchronous. 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
1 | === modified file 'configure/CONFIG.gnuCommon' |
2 | --- configure/CONFIG.gnuCommon 2009-11-25 17:15:47 +0000 |
3 | +++ configure/CONFIG.gnuCommon 2011-08-31 22:29:24 +0000 |
4 | @@ -12,6 +12,8 @@ |
5 | |
6 | GNU = YES |
7 | |
8 | +CMPLR_CLASS = gcc |
9 | + |
10 | GNU_BIN = $(GNU_DIR)/bin |
11 | GNU_LIB = $(GNU_DIR)/lib |
12 | |
13 | |
14 | === modified file 'configure/CONFIG_COMMON' |
15 | --- configure/CONFIG_COMMON 2011-08-17 21:36:38 +0000 |
16 | +++ configure/CONFIG_COMMON 2011-08-31 22:29:24 +0000 |
17 | @@ -133,11 +133,14 @@ |
18 | GENERIC_SRC_DIRS = .. $(SRC_DIRS) |
19 | OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ |
20 | $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default )) |
21 | -ALL_SRC_DIRS = $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS) |
22 | +CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ |
23 | + $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default )) |
24 | +ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS) |
25 | |
26 | #-------------------------------------------------- |
27 | # compile line include directories |
28 | INSTALL_INCLUDES += \ |
29 | + -I$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) \ |
30 | -I$(INSTALL_INCLUDE)/os/$(OS_CLASS) \ |
31 | -I$(INSTALL_INCLUDE) |
32 | SRC_INCLUDES = -I$(COMMON_DIR) $(addprefix -I, $(wildcard $(ALL_SRC_DIRS))) |
33 | @@ -379,25 +382,36 @@ |
34 | # |
35 | # auto determine the directory paths that things are installed to |
36 | # RULES: |
37 | -# 1) found in any one of several os specific area |
38 | +# 0) found in any one of several compiler specific paths |
39 | +# => install to $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS) |
40 | +# 1) not found in (0) and found in any one of several OS specific paths |
41 | # => install to $(INSTALL_INCLUDE)/os/$(OS_CLASS) |
42 | -# 2) not foundin (1) and found in generic area |
43 | +# 2) not found in (1) and found in generic paths |
44 | # => install to $(INSTALL_INCLUDE) |
45 | # 3) not found in (1) or (2) then may be (not yet) computer generated |
46 | # => install into $(INSTALL_INCLUDE)/os/$(OS_CLASS) and let |
47 | # build rules work on vpath |
48 | # |
49 | # These rules guarantee that the users include from |
50 | -# no more than two directories |
51 | +# no more than three directories |
52 | # |
53 | INSTALL_INC += $(foreach inc, $(INC), \ |
54 | $(firstword \ |
55 | + $(CMPLR_INSTALL_INC) \ |
56 | $(OS_INSTALL_INC) \ |
57 | $(GENERIC_INSTALL_INC) \ |
58 | $(GENERATED_INSTALL_INC) ) ) |
59 | INSTALL_INC += $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INC_$(OS_CLASS)) ) |
60 | |
61 | # |
62 | +# Rule 0 |
63 | +# |
64 | +CMPLR_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/, $(INSTALL_INC_jjj) ) |
65 | +INSTALL_INC_jjj = $(foreach dir, $(CMPLR_SRC_DIRS), $(INSTALL_INC_iii) ) |
66 | +INSTALL_INC_iii = $(subst $(dir)/, , $(INSTALL_INC_hhh) ) |
67 | +INSTALL_INC_hhh = $(wildcard $(addsuffix /$(inc), $(dir)) ) |
68 | + |
69 | +# |
70 | # Rule 1 |
71 | # |
72 | OS_INSTALL_INC = $(addprefix $(INSTALL_INCLUDE)/os/$(OS_CLASS)/, $(INSTALL_INC_ggg) ) |
73 | |
74 | === modified file 'configure/RULES_BUILD' |
75 | --- configure/RULES_BUILD 2010-12-20 15:48:12 +0000 |
76 | +++ configure/RULES_BUILD 2011-08-31 22:29:24 +0000 |
77 | @@ -408,7 +408,11 @@ |
78 | @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) |
79 | |
80 | $(INSTALL_INCLUDE)/os/$(OS_CLASS)/% : % |
81 | - $(ECHO) "Installing os dependent include file $@" |
82 | + $(ECHO) "Installing OS dependent include file $@" |
83 | + @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) |
84 | + |
85 | +$(INSTALL_INCLUDE)/compiler/$(CMPLR_CLASS)/% : % |
86 | + $(ECHO) "Installing compiler dependent include file $@" |
87 | @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) |
88 | |
89 | $(INSTALL_DOC)/%: % |
90 | |
91 | === modified file 'configure/os/CONFIG.solarisCommon.solarisCommon' |
92 | --- configure/os/CONFIG.solarisCommon.solarisCommon 2010-10-05 19:27:37 +0000 |
93 | +++ configure/os/CONFIG.solarisCommon.solarisCommon 2011-08-31 22:29:24 +0000 |
94 | @@ -7,6 +7,8 @@ |
95 | # Sites may override these definitions in CONFIG_SITE.solaris-sparc.solaris-sparc |
96 | #------------------------------------------------------- |
97 | |
98 | +CMPLR_CLASS = solStudio |
99 | + |
100 | SPARCWORKS = /opt/SUNWspro |
101 | GNU = NO |
102 | |
103 | |
104 | === modified file 'configure/os/CONFIG.win32-x86.win32-x86' |
105 | --- configure/os/CONFIG.win32-x86.win32-x86 2011-08-17 21:36:38 +0000 |
106 | +++ configure/os/CONFIG.win32-x86.win32-x86 2011-08-31 22:29:24 +0000 |
107 | @@ -11,6 +11,8 @@ |
108 | |
109 | VALID_BUILDS = Host Ioc |
110 | |
111 | +CMPLR_CLASS = msvc |
112 | + |
113 | # convert UNIX path to native path |
114 | PATH_FILTER = $(subst /,\\,$(1)) |
115 | |
116 | @@ -122,7 +124,7 @@ |
117 | # /D_CRTDBG_MAP_ALLOC |
118 | # /RTCsu catch bugs occurring only in optimized code |
119 | # /DEPICS_FREELIST_DEBUG good for detecting mem mrg bugs |
120 | -OPT_CXXFLAGS_NO = /RTCsu /Zi |
121 | +OPT_CXXFLAGS_NO = /RTCsu /Zi |
122 | |
123 | # specify object file name and location |
124 | OBJ_CXXFLAG = /Fo |
125 | |
126 | === modified file 'src/libCom/Makefile' |
127 | --- src/libCom/Makefile 2011-08-23 22:28:20 +0000 |
128 | +++ src/libCom/Makefile 2011-08-31 22:29:24 +0000 |
129 | @@ -9,6 +9,7 @@ |
130 | TOP = ../.. |
131 | include $(TOP)/configure/CONFIG |
132 | |
133 | +<<<<<<< TREE |
134 | SRC = $(TOP)/src |
135 | LIBCOM = $(SRC)/libCom |
136 | |
137 | @@ -38,6 +39,288 @@ |
138 | include $(LIBCOM)/yacc/Makefile |
139 | |
140 | # Library to build: |
141 | +======= |
142 | +LIBCOM = $(TOP)/src/libCom |
143 | + |
144 | +# Command-line input support |
145 | +epicsReadline_CFLAGS += -DEPICS_COMMANDLINE_LIBRARY=EPICS_COMMANDLINE_LIBRARY_$(COMMANDLINE_LIBRARY) |
146 | +epicsReadline_INCLUDES += $(INCLUDES_$(COMMANDLINE_LIBRARY)) |
147 | + |
148 | +#POSIX thread priority scheduling flag |
149 | +THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING |
150 | +osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING)) |
151 | + |
152 | +#epicsVersion is created by this Makefile |
153 | +INC += epicsVersion.h |
154 | + |
155 | +SRC_DIRS += $(LIBCOM)/bucketLib |
156 | +INC += bucketLib.h |
157 | +SRCS += bucketLib.c |
158 | + |
159 | +SRC_DIRS += $(LIBCOM)/ring |
160 | +#following needed for locating epicsRingPointer.h and epicsRingBytes.h |
161 | +INC += epicsRingPointer.h |
162 | +INC += epicsRingBytes.h |
163 | +SRCS += epicsRingPointer.cpp |
164 | +SRCS += epicsRingBytes.c |
165 | + |
166 | +SRC_DIRS += $(LIBCOM)/calc |
167 | +INC += postfix.h |
168 | +SRCS += postfix.c |
169 | +SRCS += calcPerform.c |
170 | + |
171 | +SRC_DIRS += $(LIBCOM)/cvtFast |
172 | +INC += cvtFast.h |
173 | +SRCS += cvtFast.c |
174 | + |
175 | +# From cppStd |
176 | +SRC_DIRS += $(LIBCOM)/cppStd |
177 | +INC += epicsAlgorithm.h |
178 | +INC += epicsExcept.h |
179 | +INC += epicsMemory.h |
180 | + |
181 | +# From cxxTemplates |
182 | +SRC_DIRS += $(LIBCOM)/cxxTemplates |
183 | +INC += resourceLib.h |
184 | +INC += tsDLList.h |
185 | +INC += tsSLList.h |
186 | +INC += tsMinMax.h |
187 | +INC += tsBTree.h |
188 | +INC += tsFreeList.h |
189 | +INC += epicsSingleton.h |
190 | +INC += epicsGuard.h |
191 | +INC += epicsOnce.h |
192 | +SRCS += resourceLib.cpp |
193 | +SRCS += epicsOnce.cpp |
194 | +SRCS += epicsSingletonMutex.cpp |
195 | + |
196 | +SRC_DIRS += $(LIBCOM)/dbmf |
197 | +INC += dbmf.h |
198 | +SRCS += dbmf.c |
199 | + |
200 | +SRC_DIRS += $(LIBCOM)/ellLib |
201 | +INC += ellLib.h |
202 | +SRCS += ellLib.c |
203 | + |
204 | +SRC_DIRS += $(LIBCOM)/env |
205 | +INC += envDefs.h |
206 | +SRCS += envSubr.c |
207 | +SRCS += envData.c |
208 | + |
209 | +SRC_DIRS += $(LIBCOM)/error |
210 | +INC += epicsPrint.h |
211 | +INC += errMdef.h |
212 | +INC += errSymTbl.h |
213 | +INC += errlog.h |
214 | +INC += error.h |
215 | +SRCS += errlog.c |
216 | +SRCS += errSymLib.c |
217 | +SRCS += errSymTbl.c |
218 | + |
219 | +SRC_DIRS += $(LIBCOM)/fdmgr |
220 | +INC += fdManager.h |
221 | +INC += fdmgr.h |
222 | +SRCS += fdmgr.cpp |
223 | +SRCS += fdManager.cpp |
224 | + |
225 | +SRC_DIRS += $(LIBCOM)/freeList |
226 | +INC += freeList.h |
227 | +SRCS += freeListLib.c |
228 | +HTMLS += freeList/freeList.html |
229 | + |
230 | +SRC_DIRS += $(LIBCOM)/gpHash |
231 | +INC += gpHash.h |
232 | +SRCS += gpHashLib.c |
233 | +HTMLS += gpHash/gpHash.html |
234 | + |
235 | +SRC_DIRS += $(LIBCOM)/iocsh |
236 | +INC += iocsh.h |
237 | +INC += registry.h |
238 | +INC += libComRegister.h |
239 | +SRCS += iocsh.cpp |
240 | +SRCS += registry.c |
241 | +SRCS += libComRegister.c |
242 | + |
243 | +SRC_DIRS += $(LIBCOM)/logClient |
244 | +INC += iocLog.h |
245 | +INC += logClient.h |
246 | +SRCS += iocLog.c |
247 | +SRCS += logClient.c |
248 | + |
249 | +SRC_DIRS += $(LIBCOM)/macLib |
250 | +INC += macLib.h |
251 | +SRCS += macCore.c |
252 | +SRCS += macEnv.c |
253 | +SRCS += macUtil.c |
254 | + |
255 | +SRC_DIRS += $(LIBCOM)/misc |
256 | +INC += adjustment.h |
257 | +INC += cantProceed.h |
258 | +INC += dbDefs.h |
259 | +INC += epicsConvert.h |
260 | +INC += epicsExit.h |
261 | +INC += epicsStdlib.h |
262 | +INC += epicsString.h |
263 | +INC += epicsTypes.h |
264 | +INC += shareLib.h |
265 | +INC += epicsExport.h |
266 | +INC += unixFileName.h |
267 | +INC += locationException.h |
268 | +INC += ipAddrToAsciiAsynchronous.h |
269 | +INC += epicsUnitTest.h |
270 | +INC += testMain.h |
271 | +SRCS += aToIPAddr.c |
272 | +SRCS += adjustment.c |
273 | +SRCS += cantProceed.c |
274 | +SRCS += epicsConvert.c |
275 | +SRCS += epicsExit.c |
276 | +SRCS += epicsStdlib.c |
277 | +SRCS += epicsString.c |
278 | +SRCS += truncateFile.c |
279 | +SRCS += ipAddrToAsciiAsynchronous.cpp |
280 | +SRCS += epicsUnitTest.c |
281 | + |
282 | +# From osi |
283 | +SRC_DIRS += $(LIBCOM)/osi |
284 | +INC += osiFileName.h |
285 | +INC += osiSock.h |
286 | +INC += osdSock.h |
287 | +INC += epicsInterrupt.h |
288 | +INC += osdInterrupt.h |
289 | + |
290 | +INC += epicsMutex.h |
291 | +INC += osdMutex.h |
292 | +INC += epicsEvent.h |
293 | +INC += osdEvent.h |
294 | +INC += epicsMath.h |
295 | +INC += osdMessageQueue.h |
296 | +INC += osdStrtod.h |
297 | + |
298 | +INC += epicsAssert.h |
299 | +INC += epicsFindSymbol.h |
300 | +INC += osiPoolStatus.h |
301 | +INC += osdPoolStatus.h |
302 | +INC += osdThread.h |
303 | + |
304 | +INC += epicsThread.h |
305 | +INC += epicsTime.h |
306 | +INC += epicsGeneralTime.h |
307 | +INC += osdTime.h |
308 | +INC += generalTimeSup.h |
309 | +INC += osiClockTime.h |
310 | +INC += epicsSignal.h |
311 | +INC += osiProcess.h |
312 | +INC += osiUnistd.h |
313 | +INC += osiWireFormat.h |
314 | +INC += osdWireFormat.h |
315 | +INC += osdWireConfig.h |
316 | +INC += epicsAtomic.h |
317 | +INC += epicsAtomicCD.h |
318 | +INC += epicsAtomicOSD.h |
319 | +INC += epicsAtomicDefault.h |
320 | +INC += epicsEndian.h |
321 | +INC += epicsReadline.h |
322 | +INC += epicsMessageQueue.h |
323 | +INC += epicsStdio.h |
324 | +INC += epicsStdioRedirect.h |
325 | +INC += epicsGetopt.h |
326 | + |
327 | +INC += devLib.h |
328 | +INC += devLibVME.h |
329 | +INC += devLibVMEImpl.h |
330 | +INC += osdVME.h |
331 | +INC += compilerDependencies.h |
332 | +INC += compilerSpecific.h |
333 | + |
334 | +SRCS += epicsThread.cpp |
335 | +SRCS += epicsMutex.cpp |
336 | +SRCS += epicsEvent.cpp |
337 | +SRCS += epicsTime.cpp |
338 | +SRCS += epicsMessageQueue.cpp |
339 | +SRCS += epicsMath.cpp |
340 | +SRCS += epicsAtomicOSD.cpp |
341 | + |
342 | +SRCS += epicsGeneralTime.c |
343 | +SRCS += osiClockTime.c |
344 | + |
345 | +SRCS += osdSock.c |
346 | +SRCS += osdSockAddrReuse.cpp |
347 | +SRCS += osiSock.c |
348 | +SRCS += systemCallIntMech.cpp |
349 | +SRCS += epicsSocketConvertErrnoToString.cpp |
350 | +SRCS += osdAssert.c |
351 | +SRCS += osdFindSymbol.c |
352 | +SRCS += osdInterrupt.c |
353 | +SRCS += osdPoolStatus.c |
354 | +SRCS += osdSignal.cpp |
355 | +SRCS += osdEnv.c |
356 | +SRCS += epicsReadline.c |
357 | +SRCS += epicsTempFile.cpp |
358 | +SRCS += epicsThreadOnce.cpp |
359 | +SRCS += epicsStdio.c |
360 | +SRCS += osdStdio.c |
361 | + |
362 | +osdEnv_CFLAGS_WIN32= -U__STDC__ |
363 | + |
364 | +SRCS += osdThread.c |
365 | +SRCS += osdMutex.c |
366 | +SRCS += osdEvent.c |
367 | +SRCS += osdTime.cpp |
368 | +SRCS += osdProcess.c |
369 | +SRCS += osdNetIntf.c |
370 | +SRCS += osdMessageQueue.c |
371 | + |
372 | +SRCS += devLibVME.c |
373 | +SRCS += devLibVMEOSD.c |
374 | + |
375 | +SRC_DIRS += $(LIBCOM)/taskwd |
376 | +INC += taskwd.h |
377 | +SRCS += taskwd.c |
378 | + |
379 | +SRC_DIRS += $(LIBCOM)/timer |
380 | +INC += epicsTimer.h |
381 | +SRCS += epicsTimer.cpp |
382 | +SRCS += timer.cpp |
383 | +SRCS += timerQueue.cpp |
384 | +SRCS += timerQueueActive.cpp |
385 | +SRCS += timerQueueActiveMgr.cpp |
386 | +SRCS += timerQueuePassive.cpp |
387 | + |
388 | +#tsDefs contains R3.13 compatibility tsStamp code |
389 | +SRC_DIRS += $(LIBCOM)/tsDefs |
390 | +INC += tsDefs.h |
391 | +SRCS += tsDefs.c |
392 | + |
393 | +# Time providers, in osi |
394 | +SRCS_vxWorks += osiNTPTime.c |
395 | +SRCS_RTEMS += osiNTPTime.c |
396 | + |
397 | +# These files are in osi/os/vxWorks |
398 | +# Special reboot hook |
399 | +SRCS_vxWorks += atReboot.cpp |
400 | +# For old vxWorks applications |
401 | +INC_vxWorks += camacLib.h |
402 | +INC_vxWorks += epicsDynLink.h |
403 | +INC_vxWorks += module_types.h |
404 | +INC_vxWorks += task_params.h |
405 | +SRCS_vxWorks += epicsDynLink.c |
406 | +SRCS_vxWorks += veclist.c |
407 | +SRCS_vxWorks += logMsgToErrlog.cpp |
408 | + |
409 | +#This forces the vxWorks compatibility stuff to be loaded |
410 | +OBJS_vxWorks = vxComLibrary |
411 | + |
412 | +# These files are in osi/os/WIN32 |
413 | +INC_WIN32 += epicsAtomicMS.h |
414 | +SRCS_WIN32 += epicsGetopt.c |
415 | +SRCS_WIN32 += setThreadName.cpp |
416 | +#SRCS_WIN32 += dllmain.cpp |
417 | +SRCS_WIN32 += forceBadAllocException.cpp |
418 | + |
419 | +# Library to build: |
420 | +# lib$(LIBRARY).a or ..dll/..exp/..lib |
421 | +# |
422 | +>>>>>>> MERGE-SOURCE |
423 | LIBRARY=Com |
424 | |
425 | Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32 |
426 | |
427 | === removed file 'src/libCom/misc/compilerDependencies.h' |
428 | --- src/libCom/misc/compilerDependencies.h 2011-06-20 18:52:32 +0000 |
429 | +++ src/libCom/misc/compilerDependencies.h 1970-01-01 00:00:00 +0000 |
430 | @@ -1,104 +0,0 @@ |
431 | - |
432 | -/*************************************************************************\ |
433 | -* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
434 | -* National Laboratory. |
435 | -* Copyright (c) 2002 The Regents of the University of California, as |
436 | -* Operator of Los Alamos National Laboratory. |
437 | -* EPICS BASE is distributed subject to a Software License Agreement found |
438 | -* in file LICENSE that is included with this distribution. |
439 | -\*************************************************************************/ |
440 | - |
441 | -/* |
442 | - * Author: |
443 | - * Jeffrey O. Hill |
444 | - * johill@lanl.gov |
445 | - */ |
446 | - |
447 | -#ifndef compilerDependencies_h |
448 | -#define compilerDependencies_h |
449 | - |
450 | -/* |
451 | - * This is an attempt to move all tests identifying what features a |
452 | - * compiler supports into one file. |
453 | - * |
454 | - * Since this is a compiler, and not os dependent, issue then ifdefs |
455 | - * are used. The ifdefs allow us to make the default assumption that |
456 | - * standards incompliance issues will be fixed by future compiler |
457 | - * releases. |
458 | - */ |
459 | - |
460 | -#ifdef __cplusplus |
461 | - |
462 | -/* |
463 | - * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete |
464 | - * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification |
465 | - */ |
466 | - |
467 | -#if defined ( _MSC_VER ) |
468 | -# if _MSC_VER >= 1200 /* visual studio 6.0 or later */ |
469 | -# define CXX_PLACEMENT_DELETE |
470 | -# endif |
471 | -# if _MSC_VER > 1300 /* some release after visual studio 7 we hope */ |
472 | -# define CXX_THROW_SPECIFICATION |
473 | -# endif |
474 | -#elif defined ( __HP_aCC ) |
475 | -# if _HP_aCC > 33300 |
476 | -# define CXX_PLACEMENT_DELETE |
477 | -# endif |
478 | -# define CXX_THROW_SPECIFICATION |
479 | -#elif defined ( __BORLANDC__ ) |
480 | -# if __BORLANDC__ >= 0x600 |
481 | -# define CXX_PLACEMENT_DELETE |
482 | -# endif |
483 | -# define CXX_THROW_SPECIFICATION |
484 | -#elif defined ( __GNUC__ ) |
485 | -# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 ) |
486 | -# define CXX_THROW_SPECIFICATION |
487 | -# endif |
488 | -# if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 ) |
489 | -# define CXX_PLACEMENT_DELETE |
490 | -# endif |
491 | -#else |
492 | -# define CXX_PLACEMENT_DELETE |
493 | -# define CXX_THROW_SPECIFICATION |
494 | -#endif |
495 | - |
496 | -/* |
497 | - * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error )) |
498 | - */ |
499 | -#if defined ( CXX_THROW_SPECIFICATION ) |
500 | -# define epicsThrows(X) throw X |
501 | -#else |
502 | -# define epicsThrows(X) |
503 | -#endif |
504 | - |
505 | -/* |
506 | - * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & )) |
507 | - */ |
508 | -#if defined ( CXX_PLACEMENT_DELETE ) |
509 | -# define epicsPlacementDeleteOperator(X) void operator delete X; |
510 | -#else |
511 | -# define epicsPlacementDeleteOperator(X) |
512 | -#endif |
513 | - |
514 | -#endif /* __cplusplus */ |
515 | - |
516 | -/* |
517 | - * Enable format-string checking if possible |
518 | - */ |
519 | -#ifdef __GNUC__ |
520 | -# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a))) |
521 | -#else |
522 | -# define EPICS_PRINTF_STYLE(f,a) |
523 | -#endif |
524 | - |
525 | -/* |
526 | - * Deprecation marker |
527 | - */ |
528 | -#if defined( __GNUC__ ) && (__GNUC__ > 2) |
529 | -# define EPICS_DEPRECATED __attribute__((deprecated)) |
530 | -#else |
531 | -# define EPICS_DEPRECATED |
532 | -#endif |
533 | - |
534 | -#endif /* ifndef compilerDependencies_h */ |
535 | |
536 | === modified file 'src/libCom/misc/ipAddrToAsciiAsynchronous.cpp' |
537 | --- src/libCom/misc/ipAddrToAsciiAsynchronous.cpp 2008-10-21 20:26:48 +0000 |
538 | +++ src/libCom/misc/ipAddrToAsciiAsynchronous.cpp 2011-08-31 22:29:24 +0000 |
539 | @@ -127,7 +127,7 @@ |
540 | ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0; |
541 | unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u; |
542 | bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false; |
543 | -static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0; |
544 | +static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT; |
545 | |
546 | // the users are not required to supply a show routine |
547 | // for there transaction callback class |
548 | |
549 | === added directory 'src/libCom/osi/compiler' |
550 | === added directory 'src/libCom/osi/compiler/borland' |
551 | === added file 'src/libCom/osi/compiler/borland/compilerSpecific.h' |
552 | --- src/libCom/osi/compiler/borland/compilerSpecific.h 1970-01-01 00:00:00 +0000 |
553 | +++ src/libCom/osi/compiler/borland/compilerSpecific.h 2011-08-31 22:29:24 +0000 |
554 | @@ -0,0 +1,55 @@ |
555 | + |
556 | +/*************************************************************************\ |
557 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
558 | +* National Laboratory. |
559 | +* Copyright (c) 2002 The Regents of the University of California, as |
560 | +* Operator of Los Alamos National Laboratory. |
561 | +* EPICS BASE is distributed subject to a Software License Agreement found |
562 | +* in file LICENSE that is included with this distribution. |
563 | +\*************************************************************************/ |
564 | + |
565 | +/* |
566 | + * Author: |
567 | + * Jeffrey O. Hill |
568 | + * johill@lanl.gov |
569 | + */ |
570 | + |
571 | +#ifndef compilerSpecific_h |
572 | +#define compilerSpecific_h |
573 | + |
574 | +#ifndef __BORLANDC__ |
575 | +# error compiler/borland/compilerSpecific.h is only for use with the Borland compiler |
576 | +#endif |
577 | + |
578 | +#ifdef __cplusplus |
579 | + |
580 | +/* |
581 | + * in general we dont like ifdefs but they do allow us to check the |
582 | + * compiler version and make the optimistic assumption that |
583 | + * standards incompliance issues will be fixed by future compiler |
584 | + * releases |
585 | + */ |
586 | + |
587 | +/* |
588 | + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete |
589 | + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification |
590 | + */ |
591 | +#if __BORLANDC__ >= 0x600 |
592 | +# define CXX_PLACEMENT_DELETE |
593 | +#endif |
594 | + |
595 | +#define CXX_THROW_SPECIFICATION |
596 | + |
597 | +#endif /* __cplusplus */ |
598 | + |
599 | +/* |
600 | + * Enable format-string checking if possible |
601 | + */ |
602 | +#define EPICS_PRINTF_STYLE(f,a) |
603 | + |
604 | +/* |
605 | + * Deprecation marker |
606 | + */ |
607 | +#define EPICS_DEPRECATED |
608 | + |
609 | +#endif /* ifndef compilerSpecific_h */ |
610 | |
611 | === added directory 'src/libCom/osi/compiler/clang' |
612 | === added file 'src/libCom/osi/compiler/clang/compilerSpecific.h' |
613 | --- src/libCom/osi/compiler/clang/compilerSpecific.h 1970-01-01 00:00:00 +0000 |
614 | +++ src/libCom/osi/compiler/clang/compilerSpecific.h 2011-08-31 22:29:24 +0000 |
615 | @@ -0,0 +1,59 @@ |
616 | + |
617 | +/*************************************************************************\ |
618 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
619 | +* National Laboratory. |
620 | +* Copyright (c) 2002 The Regents of the University of California, as |
621 | +* Operator of Los Alamos National Laboratory. |
622 | +* EPICS BASE is distributed subject to a Software License Agreement found |
623 | +* in file LICENSE that is included with this distribution. |
624 | +\*************************************************************************/ |
625 | + |
626 | +/* |
627 | + * Author: |
628 | + * Jeffrey O. Hill |
629 | + * johill@lanl.gov |
630 | + */ |
631 | + |
632 | +#ifndef compilerSpecific_h |
633 | +#define compilerSpecific_h |
634 | + |
635 | +#ifndef __clang__ |
636 | +# error compiler/clang/compilerSpecific.h is only for use with the clang compiler |
637 | +#endif |
638 | + |
639 | +/* |
640 | + * WARNING: the current state of this file is only based on reading clang manuals |
641 | + * and has not actually been tested with the compiler |
642 | + */ |
643 | +#pragma warning compiler/clang/compilerSpecific.h is based on reading the manual, but hasnt been tested with the clang compiler |
644 | + |
645 | +#ifdef __cplusplus |
646 | + |
647 | +/* |
648 | + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete |
649 | + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification |
650 | + */ |
651 | +#define CXX_PLACEMENT_DELETE |
652 | +#define CXX_THROW_SPECIFICATION |
653 | + |
654 | +#endif /* __cplusplus */ |
655 | + |
656 | +/* |
657 | + * Enable format-string checking if possible |
658 | + */ |
659 | +#if __has_attribute(format) |
660 | +# define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a))) |
661 | +#else |
662 | +# define EPICS_PRINTF_STYLE |
663 | +#endif |
664 | + |
665 | +/* |
666 | + * Deprecation marker if possible |
667 | + */ |
668 | +#if __has_attribute(deprecated) |
669 | +# define EPICS_DEPRECATED __attribute__((deprecated)) |
670 | +#else |
671 | +# define EPICS_DEPRECATED |
672 | +#endif |
673 | + |
674 | +#endif /* ifndef compilerSpecific_h */ |
675 | |
676 | === added file 'src/libCom/osi/compiler/clang/epicsAtomicCD.h' |
677 | --- src/libCom/osi/compiler/clang/epicsAtomicCD.h 1970-01-01 00:00:00 +0000 |
678 | +++ src/libCom/osi/compiler/clang/epicsAtomicCD.h 2011-08-31 22:29:24 +0000 |
679 | @@ -0,0 +1,27 @@ |
680 | + |
681 | +/*************************************************************************\ |
682 | +* Copyright (c) 2011 LANS LLC, as Operator of |
683 | +* Los Alamos National Laboratory. |
684 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
685 | +* National Laboratory. |
686 | +* EPICS BASE is distributed subject to a Software License Agreement found |
687 | +* in file LICENSE that is included with this distribution. |
688 | +\*************************************************************************/ |
689 | + |
690 | +/* |
691 | + * Author Jeffrey O. Hill |
692 | + * johill@lanl.gov |
693 | + */ |
694 | + |
695 | +#ifndef epicsAtomicCD_h |
696 | +#define epicsAtomicCD_h |
697 | + |
698 | +#if defined ( __cplusplus ) |
699 | +# define EPICS_ATOMIC_INLINE inline |
700 | +#else |
701 | +# define EPICS_ATOMIC_INLINE __inline__ |
702 | +#endif |
703 | + |
704 | +#include "epicsAtomicOSD.h" |
705 | + |
706 | +#endif /* epicsAtomicCD_h */ |
707 | |
708 | === added directory 'src/libCom/osi/compiler/default' |
709 | === added file 'src/libCom/osi/compiler/default/compilerSpecific.h' |
710 | --- src/libCom/osi/compiler/default/compilerSpecific.h 1970-01-01 00:00:00 +0000 |
711 | +++ src/libCom/osi/compiler/default/compilerSpecific.h 2011-08-31 22:29:24 +0000 |
712 | @@ -0,0 +1,45 @@ |
713 | + |
714 | +/*************************************************************************\ |
715 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
716 | +* National Laboratory. |
717 | +* Copyright (c) 2002 The Regents of the University of California, as |
718 | +* Operator of Los Alamos National Laboratory. |
719 | +* EPICS BASE is distributed subject to a Software License Agreement found |
720 | +* in file LICENSE that is included with this distribution. |
721 | +\*************************************************************************/ |
722 | + |
723 | +/* |
724 | + * Author: |
725 | + * Jeffrey O. Hill |
726 | + * johill@lanl.gov |
727 | + */ |
728 | + |
729 | +#ifndef compilerSpecific_h |
730 | +#define compilerSpecific_h |
731 | + |
732 | +#ifdef __cplusplus |
733 | + |
734 | +/* |
735 | + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete |
736 | + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification |
737 | + * |
738 | + * (our default guess is that the compiler implements the C++ 97 standard) |
739 | + */ |
740 | +#define CXX_THROW_SPECIFICATION |
741 | +#define CXX_PLACEMENT_DELETE |
742 | + |
743 | +#endif /* __cplusplus */ |
744 | + |
745 | +/* |
746 | + * Enable format-string checking if possible |
747 | + * (our default guess is that the compiler doesnt implement non-standard extensions) |
748 | + */ |
749 | +#define EPICS_PRINTF_STYLE(f,a) |
750 | + |
751 | +/* |
752 | + * Deprecation marker |
753 | + * (our default guess is that the compiler doesnt implement non-standard extensions) |
754 | + */ |
755 | +#define EPICS_DEPRECATED |
756 | + |
757 | +#endif /* ifndef compilerSpecific_h */ |
758 | |
759 | === added file 'src/libCom/osi/compiler/default/epicsAtomicCD.h' |
760 | --- src/libCom/osi/compiler/default/epicsAtomicCD.h 1970-01-01 00:00:00 +0000 |
761 | +++ src/libCom/osi/compiler/default/epicsAtomicCD.h 2011-08-31 22:29:24 +0000 |
762 | @@ -0,0 +1,25 @@ |
763 | + |
764 | +/*************************************************************************\ |
765 | +* Copyright (c) 2011 LANS LLC, as Operator of |
766 | +* Los Alamos National Laboratory. |
767 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
768 | +* National Laboratory. |
769 | +* EPICS BASE is distributed subject to a Software License Agreement found |
770 | +* in file LICENSE that is included with this distribution. |
771 | +\*************************************************************************/ |
772 | + |
773 | +/* |
774 | + * Author Jeffrey O. Hill |
775 | + * johill@lanl.gov |
776 | + */ |
777 | + |
778 | +#ifndef epicsAtomicCD_h |
779 | +#define epicsAtomicCD_h |
780 | + |
781 | +#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus ) |
782 | +# define EPICS_ATOMIC_INLINE inline |
783 | +#endif |
784 | + |
785 | +#include "epicsAtomicOSD.h" |
786 | + |
787 | +#endif /* epicsAtomicCD_h */ |
788 | |
789 | === added directory 'src/libCom/osi/compiler/gcc' |
790 | === added file 'src/libCom/osi/compiler/gcc/compilerSpecific.h' |
791 | --- src/libCom/osi/compiler/gcc/compilerSpecific.h 1970-01-01 00:00:00 +0000 |
792 | +++ src/libCom/osi/compiler/gcc/compilerSpecific.h 2011-08-31 22:29:24 +0000 |
793 | @@ -0,0 +1,62 @@ |
794 | + |
795 | +/*************************************************************************\ |
796 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
797 | +* National Laboratory. |
798 | +* Copyright (c) 2002 The Regents of the University of California, as |
799 | +* Operator of Los Alamos National Laboratory. |
800 | +* EPICS BASE is distributed subject to a Software License Agreement found |
801 | +* in file LICENSE that is included with this distribution. |
802 | +\*************************************************************************/ |
803 | + |
804 | +/* |
805 | + * Author: |
806 | + * Jeffrey O. Hill |
807 | + * johill@lanl.gov |
808 | + */ |
809 | + |
810 | +#ifndef compilerSpecific_h |
811 | +#define compilerSpecific_h |
812 | + |
813 | +#ifndef __GNUC__ |
814 | +# error compiler/gcc/compilerSpecific.h is only for use with the gnu compiler |
815 | +#endif |
816 | + |
817 | +#ifdef __cplusplus |
818 | + |
819 | +/* |
820 | + * in general we dont like ifdefs but they do allow us to check the |
821 | + * compiler version and make the optimistic assumption that |
822 | + * standards incompliance issues will be fixed by future compiler |
823 | + * releases |
824 | + */ |
825 | + |
826 | +/* |
827 | + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete |
828 | + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification |
829 | + */ |
830 | + |
831 | +#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95 ) |
832 | +# define CXX_THROW_SPECIFICATION |
833 | +#endif |
834 | + |
835 | +#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 ) |
836 | +# define CXX_PLACEMENT_DELETE |
837 | +#endif |
838 | + |
839 | +#endif /* __cplusplus */ |
840 | + |
841 | +/* |
842 | + * Enable format-string checking if possible |
843 | + */ |
844 | +#define EPICS_PRINTF_STYLE(f,a) __attribute__((format(__printf__,f,a))) |
845 | + |
846 | +/* |
847 | + * Deprecation marker if possible |
848 | + */ |
849 | +#if (__GNUC__ > 2) |
850 | +# define EPICS_DEPRECATED __attribute__((deprecated)) |
851 | +#else |
852 | +# define EPICS_DEPRECATED |
853 | +#endif |
854 | + |
855 | +#endif /* ifndef compilerSpecific_h */ |
856 | |
857 | === added file 'src/libCom/osi/compiler/gcc/epicsAtomicCD.h' |
858 | --- src/libCom/osi/compiler/gcc/epicsAtomicCD.h 1970-01-01 00:00:00 +0000 |
859 | +++ src/libCom/osi/compiler/gcc/epicsAtomicCD.h 2011-08-31 22:29:24 +0000 |
860 | @@ -0,0 +1,172 @@ |
861 | + |
862 | +/*************************************************************************\ |
863 | +* Copyright (c) 2011 LANS LLC, as Operator of |
864 | +* Los Alamos National Laboratory. |
865 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
866 | +* National Laboratory. |
867 | +* EPICS BASE is distributed subject to a Software License Agreement found |
868 | +* in file LICENSE that is included with this distribution. |
869 | +\*************************************************************************/ |
870 | + |
871 | +/* |
872 | + * Author Jeffrey O. Hill |
873 | + * johill@lanl.gov |
874 | + */ |
875 | + |
876 | +#ifndef epicsAtomicCD_h |
877 | +#define epicsAtomicCD_h |
878 | + |
879 | +#ifndef __GNUC__ |
880 | +# error this header is only for use with the gnu compiler |
881 | +#endif |
882 | + |
883 | +#define EPICS_ATOMIC_INLINE __inline__ |
884 | + |
885 | +#define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B) |
886 | +#define GCC_ATOMIC_CONCATR( A, B ) ( A ## B ) |
887 | + |
888 | +#define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \ |
889 | + GCC_ATOMIC_CONCAT ( \ |
890 | + __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \ |
891 | + __SIZEOF_INT__ ) |
892 | + |
893 | +#define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \ |
894 | + GCC_ATOMIC_CONCAT ( \ |
895 | + __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \ |
896 | + __SIZEOF_SIZE_T__ ) |
897 | + |
898 | +#define GCC_ATOMIC_INTRINSICS_MIN_X86 \ |
899 | + ( defined ( __i486 ) || defined ( __pentium ) || \ |
900 | + defined ( __pentiumpro ) || defined ( __MMX__ ) ) |
901 | + |
902 | +#define GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER \ |
903 | + ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 ) |
904 | + |
905 | +#define GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER \ |
906 | + ( GCC_ATOMIC_INTRINSICS_MIN_X86 && \ |
907 | + GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER ) |
908 | + |
909 | +#ifdef __cplusplus |
910 | +extern "C" { |
911 | +#endif |
912 | + |
913 | +/* |
914 | + * We are optimistic that __sync_synchronize is implemented |
915 | + * in all version four gcc invarient of target. The gnu doc |
916 | + * seems to say that when not supported by architecture a call |
917 | + * to an external function is generated but in practice |
918 | + * this isnt the case for some of the atomic intrinsics, and |
919 | + * so there is an undefined symbol. So far we have not seen |
920 | + * that with __sync_synchronize, but we can only guess based |
921 | + * on experimental evidence. |
922 | + * |
923 | + * For example we know that when generating object code for |
924 | + * 386 most of the atomic instrinsics are not present and |
925 | + * we see undefined symbols with mingw, but we dont have |
926 | + * troubles with __sync_synchronize. |
927 | + */ |
928 | +#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER |
929 | + |
930 | +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER |
931 | +#define EPICS_ATOMIC_READ_MEMORY_BARRIER |
932 | +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () |
933 | +{ |
934 | + __sync_synchronize (); |
935 | +} |
936 | +#endif |
937 | + |
938 | +#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
939 | +#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
940 | +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () |
941 | +{ |
942 | + __sync_synchronize (); |
943 | +} |
944 | +#endif |
945 | + |
946 | +#endif /* if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER */ |
947 | + |
948 | +#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \ |
949 | + || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER |
950 | + |
951 | +#define EPICS_ATOMIC_INCR_INTT |
952 | +EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget ) |
953 | +{ |
954 | + return __sync_add_and_fetch ( pTarget, 1 ); |
955 | +} |
956 | + |
957 | +#define EPICS_ATOMIC_DECR_INTT |
958 | +EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget ) |
959 | +{ |
960 | + return __sync_sub_and_fetch ( pTarget, 1 ); |
961 | +} |
962 | + |
963 | +#define EPICS_ATOMIC_ADD_INTT |
964 | +EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ) |
965 | +{ |
966 | + return __sync_add_and_fetch ( pTarget, delta ); |
967 | +} |
968 | + |
969 | +#define EPICS_ATOMIC_CAS_INTT |
970 | +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, |
971 | + int oldVal, int newVal ) |
972 | +{ |
973 | + return __sync_val_compare_and_swap ( pTarget, oldVal, newVal); |
974 | +} |
975 | + |
976 | +#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T */ |
977 | + |
978 | +#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \ |
979 | + || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER |
980 | + |
981 | +#define EPICS_ATOMIC_INCR_SIZET |
982 | +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) |
983 | +{ |
984 | + return __sync_add_and_fetch ( pTarget, 1u ); |
985 | +} |
986 | + |
987 | +#define EPICS_ATOMIC_DECR_SIZET |
988 | +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) |
989 | +{ |
990 | + return __sync_sub_and_fetch ( pTarget, 1u ); |
991 | +} |
992 | + |
993 | +#define EPICS_ATOMIC_ADD_SIZET |
994 | +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ) |
995 | +{ |
996 | + return __sync_add_and_fetch ( pTarget, delta ); |
997 | +} |
998 | + |
999 | +#define EPICS_ATOMIC_SUB_SIZET |
1000 | +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ) |
1001 | +{ |
1002 | + return __sync_sub_and_fetch ( pTarget, delta ); |
1003 | +} |
1004 | + |
1005 | +#define EPICS_ATOMIC_CAS_SIZET |
1006 | +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, |
1007 | + size_t oldVal, size_t newVal ) |
1008 | +{ |
1009 | + return __sync_val_compare_and_swap ( pTarget, oldVal, newVal); |
1010 | +} |
1011 | + |
1012 | +#define EPICS_ATOMIC_CAS_PTRT |
1013 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( |
1014 | + EpicsAtomicPtrT * pTarget, |
1015 | + EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ) |
1016 | +{ |
1017 | + return __sync_val_compare_and_swap ( pTarget, oldVal, newVal); |
1018 | +} |
1019 | + |
1020 | +#endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T */ |
1021 | + |
1022 | +#ifdef __cplusplus |
1023 | +} /* end of extern "C" */ |
1024 | +#endif |
1025 | + |
1026 | +/* |
1027 | + * if currently unavailable as gcc intrinsics we |
1028 | + * will try for an os specific inline solution |
1029 | + */ |
1030 | +#include "epicsAtomicOSD.h" |
1031 | + |
1032 | +#endif /* epicsAtomicCD_h */ |
1033 | |
1034 | === added directory 'src/libCom/osi/compiler/msvc' |
1035 | === added file 'src/libCom/osi/compiler/msvc/compilerSpecific.h' |
1036 | --- src/libCom/osi/compiler/msvc/compilerSpecific.h 1970-01-01 00:00:00 +0000 |
1037 | +++ src/libCom/osi/compiler/msvc/compilerSpecific.h 2011-08-31 22:29:24 +0000 |
1038 | @@ -0,0 +1,57 @@ |
1039 | + |
1040 | +/*************************************************************************\ |
1041 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
1042 | +* National Laboratory. |
1043 | +* Copyright (c) 2002 The Regents of the University of California, as |
1044 | +* Operator of Los Alamos National Laboratory. |
1045 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1046 | +* in file LICENSE that is included with this distribution. |
1047 | +\*************************************************************************/ |
1048 | + |
1049 | +/* |
1050 | + * Author: |
1051 | + * Jeffrey O. Hill |
1052 | + * johill@lanl.gov |
1053 | + */ |
1054 | + |
1055 | +#ifndef compilerSpecific_h |
1056 | +#define compilerSpecific_h |
1057 | + |
1058 | +#ifndef _MSC_VER |
1059 | +# error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler |
1060 | +#endif |
1061 | + |
1062 | +#ifdef __cplusplus |
1063 | + |
1064 | +/* |
1065 | + * in general we dont like ifdefs but they do allow us to check the |
1066 | + * compiler version and make the optimistic assumption that |
1067 | + * standards incompliance issues will be fixed by future compiler |
1068 | + * releases |
1069 | + */ |
1070 | + |
1071 | +/* |
1072 | + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete |
1073 | + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification |
1074 | + */ |
1075 | +#if _MSC_VER >= 1200 /* visual studio 6.0 or later */ |
1076 | +# define CXX_PLACEMENT_DELETE |
1077 | +#endif |
1078 | + |
1079 | +#if _MSC_VER > 1300 /* some release after visual studio 7 we hope */ |
1080 | +# define CXX_THROW_SPECIFICATION |
1081 | +#endif |
1082 | + |
1083 | +#endif /* __cplusplus */ |
1084 | + |
1085 | +/* |
1086 | + * Enable format-string checking if possible |
1087 | + */ |
1088 | +#define EPICS_PRINTF_STYLE(f,a) |
1089 | + |
1090 | +/* |
1091 | + * Deprecation marker |
1092 | + */ |
1093 | +#define EPICS_DEPRECATED |
1094 | + |
1095 | +#endif /* ifndef compilerSpecific_h */ |
1096 | |
1097 | === added file 'src/libCom/osi/compiler/msvc/epicsAtomicCD.h' |
1098 | --- src/libCom/osi/compiler/msvc/epicsAtomicCD.h 1970-01-01 00:00:00 +0000 |
1099 | +++ src/libCom/osi/compiler/msvc/epicsAtomicCD.h 2011-08-31 22:29:24 +0000 |
1100 | @@ -0,0 +1,124 @@ |
1101 | + |
1102 | +/*************************************************************************\ |
1103 | +* Copyright (c) 2011 LANS LLC, as Operator of |
1104 | +* Los Alamos National Laboratory. |
1105 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
1106 | +* National Laboratory. |
1107 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1108 | +* in file LICENSE that is included with this distribution. |
1109 | +\*************************************************************************/ |
1110 | + |
1111 | +/* |
1112 | + * Author Jeffrey O. Hill |
1113 | + * johill@lanl.gov |
1114 | + */ |
1115 | + |
1116 | +#ifndef epicsAtomicCD_h |
1117 | +#define epicsAtomicCD_h |
1118 | + |
1119 | +#include "epicsAssert.h" |
1120 | + |
1121 | +#ifndef _MSC_VER |
1122 | +# error this header file is only for use with with the Microsoft Compiler |
1123 | +#endif |
1124 | + |
1125 | +#ifdef _MSC_EXTENSIONS |
1126 | + |
1127 | +#include <intrin.h> |
1128 | + |
1129 | +#if _MSC_VER >= 1200 |
1130 | +# define EPICS_ATOMIC_INLINE __forceinline |
1131 | +#else |
1132 | +# define EPICS_ATOMIC_INLINE __inline |
1133 | +#endif |
1134 | + |
1135 | +#if defined ( _M_IX86 ) |
1136 | +# pragma warning( push ) |
1137 | +# pragma warning( disable : 4793 ) |
1138 | + EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () |
1139 | + { |
1140 | + long fence; |
1141 | + __asm { xchg fence, eax } |
1142 | + } |
1143 | +# pragma warning( pop ) |
1144 | +#elif defined ( _M_X64 ) |
1145 | +# define MS_ATOMIC_64 |
1146 | +# pragma intrinsic ( __faststorefence ) |
1147 | + EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () |
1148 | + { |
1149 | + __faststorefence (); |
1150 | + } |
1151 | +#elif defined ( _M_IA64 ) |
1152 | +# define MS_ATOMIC_64 |
1153 | +# pragma intrinsic ( __mf ) |
1154 | + EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () |
1155 | + { |
1156 | + __mf (); |
1157 | + } |
1158 | +#else |
1159 | +# error unexpected target architecture, msvc version of epicsAtomicCD.h |
1160 | +#endif |
1161 | + |
1162 | +/* |
1163 | + * The windows doc appears to recommend defining InterlockedExchange |
1164 | + * to be _InterlockedExchange to cause it to be an intrinsic, but that |
1165 | + * creates issues when later, in a windows os specific header, we include |
1166 | + * windows.h. Therefore, we except some code duplication between the msvc |
1167 | + * csAtomic.h and win32 osdAtomic.h to avoid problems, and to keep the |
1168 | + * os specific windows.h header file out of the msvc cdAtomic.h |
1169 | + */ |
1170 | +#define MS_LONG long |
1171 | +#define MS_InterlockedExchange _InterlockedExchange |
1172 | +#define MS_InterlockedCompareExchange _InterlockedCompareExchange |
1173 | +#define MS_InterlockedIncrement _InterlockedIncrement |
1174 | +#define MS_InterlockedDecrement _InterlockedDecrement |
1175 | +#define MS_InterlockedExchange _InterlockedExchange |
1176 | +#define MS_InterlockedExchangeAdd _InterlockedExchangeAdd |
1177 | +#if defined ( MS_ATOMIC_64 ) |
1178 | +# define MS_LONGLONG long long |
1179 | +# define MS_InterlockedIncrement64 _InterlockedIncrement64 |
1180 | +# define MS_InterlockedDecrement64 _InterlockedDecrement64 |
1181 | +# define MS_InterlockedExchange64 _InterlockedExchange64 |
1182 | +# define MS_InterlockedExchangeAdd64 _InterlockedExchangeAdd64 |
1183 | +# define MS_InterlockedCompareExchange64 _InterlockedCompareExchange64 |
1184 | +#endif |
1185 | + |
1186 | +#ifdef __cplusplus |
1187 | +extern "C" { |
1188 | +#endif /* __cplusplus */ |
1189 | + |
1190 | +#define EPICS_ATOMIC_READ_MEMORY_BARRIER |
1191 | +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () |
1192 | +{ |
1193 | + epicsAtomicMemoryBarrier (); |
1194 | +} |
1195 | + |
1196 | +#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
1197 | +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () |
1198 | +{ |
1199 | + epicsAtomicMemoryBarrier (); |
1200 | +} |
1201 | + |
1202 | +#ifdef __cplusplus |
1203 | +} /* end of extern "C" */ |
1204 | +#endif /* __cplusplus */ |
1205 | + |
1206 | +#include "epicsAtomicMS.h" |
1207 | +#include "epicsAtomicDefault.h" |
1208 | + |
1209 | +#else /* ifdef _MSC_EXTENSIONS */ |
1210 | + |
1211 | +#if defined ( __cplusplus ) |
1212 | +# define EPICS_ATOMIC_INLINE inline |
1213 | +#endif |
1214 | + |
1215 | +/* |
1216 | + * if unavailable as an intrinsic we will try |
1217 | + * for os specific solution |
1218 | + */ |
1219 | +#include "epicsAtomicOSD.h" |
1220 | + |
1221 | +#endif /* ifdef _MSC_EXTENSIONS */ |
1222 | + |
1223 | +#endif /* epicsAtomicCD_h */ |
1224 | + |
1225 | |
1226 | === added directory 'src/libCom/osi/compiler/solStudio' |
1227 | === added file 'src/libCom/osi/compiler/solStudio/epicsAtomicCD.h' |
1228 | --- src/libCom/osi/compiler/solStudio/epicsAtomicCD.h 1970-01-01 00:00:00 +0000 |
1229 | +++ src/libCom/osi/compiler/solStudio/epicsAtomicCD.h 2011-08-31 22:29:24 +0000 |
1230 | @@ -0,0 +1,27 @@ |
1231 | + |
1232 | +/*************************************************************************\ |
1233 | +* Copyright (c) 2011 LANS LLC, as Operator of |
1234 | +* Los Alamos National Laboratory. |
1235 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
1236 | +* National Laboratory. |
1237 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1238 | +* in file LICENSE that is included with this distribution. |
1239 | +\*************************************************************************/ |
1240 | + |
1241 | +/* |
1242 | + * Author Jeffrey O. Hill |
1243 | + * johill@lanl.gov |
1244 | + */ |
1245 | + |
1246 | +#ifndef epicsAtomicCD_h |
1247 | +#define epicsAtomicCD_h |
1248 | + |
1249 | +#if defined ( __cplusplus ) |
1250 | +# define EPICS_ATOMIC_INLINE inline |
1251 | +#else |
1252 | +# define EPICS_ATOMIC_INLINE __inline |
1253 | +#endif |
1254 | + |
1255 | +#include "epicsAtomicOSD.h" |
1256 | + |
1257 | +#endif /* epicsAtomicCD_h */ |
1258 | |
1259 | === added file 'src/libCom/osi/compilerDependencies.h' |
1260 | --- src/libCom/osi/compilerDependencies.h 1970-01-01 00:00:00 +0000 |
1261 | +++ src/libCom/osi/compilerDependencies.h 2011-08-31 22:29:24 +0000 |
1262 | @@ -0,0 +1,47 @@ |
1263 | + |
1264 | +/*************************************************************************\ |
1265 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
1266 | +* National Laboratory. |
1267 | +* Copyright (c) 2002 The Regents of the University of California, as |
1268 | +* Operator of Los Alamos National Laboratory. |
1269 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1270 | +* in file LICENSE that is included with this distribution. |
1271 | +\*************************************************************************/ |
1272 | + |
1273 | +/* |
1274 | + * Author: |
1275 | + * Jeffrey O. Hill |
1276 | + * johill@lanl.gov |
1277 | + */ |
1278 | + |
1279 | +#ifndef compilerDependencies_h |
1280 | +#define compilerDependencies_h |
1281 | + |
1282 | +#include "compilerSpecific.h" |
1283 | + |
1284 | +#ifdef __cplusplus |
1285 | + |
1286 | +/* |
1287 | + * usage: void func () epicsThrows (( std::bad_alloc, std::logic_error )) |
1288 | + * |
1289 | + * Note: now a widely accepted concensus (ref Meyers and C++ faq) is that |
1290 | + * one should avoid using throw specifications in C++ code |
1291 | + */ |
1292 | +#if defined ( CXX_THROW_SPECIFICATION ) |
1293 | +# define epicsThrows(X) throw X |
1294 | +#else |
1295 | +# define epicsThrows(X) |
1296 | +#endif |
1297 | + |
1298 | +/* |
1299 | + * usage: epicsPlacementDeleteOperator (( void *, myMemoryManager & )) |
1300 | + */ |
1301 | +#if defined ( CXX_PLACEMENT_DELETE ) |
1302 | +# define epicsPlacementDeleteOperator(X) void operator delete X; |
1303 | +#else |
1304 | +# define epicsPlacementDeleteOperator(X) |
1305 | +#endif |
1306 | + |
1307 | +#endif /* __cplusplus */ |
1308 | + |
1309 | +#endif /* ifndef compilerDependencies_h */ |
1310 | |
1311 | === added file 'src/libCom/osi/epicsAtomic.h' |
1312 | --- src/libCom/osi/epicsAtomic.h 1970-01-01 00:00:00 +0000 |
1313 | +++ src/libCom/osi/epicsAtomic.h 2011-08-31 22:29:24 +0000 |
1314 | @@ -0,0 +1,237 @@ |
1315 | + |
1316 | +/*************************************************************************\ |
1317 | +* Copyright (c) 2011 LANS LLC, as Operator of |
1318 | +* Los Alamos National Laboratory. |
1319 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
1320 | +* National Laboratory. |
1321 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1322 | +* in file LICENSE that is included with this distribution. |
1323 | +\*************************************************************************/ |
1324 | + |
1325 | +/* |
1326 | + * Author Jeffrey O. Hill |
1327 | + * johill@lanl.gov |
1328 | + */ |
1329 | + |
1330 | +#ifndef epicsAtomic_h |
1331 | +#define epicsAtomic_h |
1332 | + |
1333 | +#include <stdlib.h> /* define size_t */ |
1334 | + |
1335 | +#include "shareLib.h" |
1336 | + |
1337 | +#ifdef __cplusplus |
1338 | +extern "C" { |
1339 | +#endif |
1340 | + |
1341 | +typedef void * EpicsAtomicPtrT; |
1342 | + |
1343 | +/* load target into cache */ |
1344 | +epicsShareFunc void epicsAtomicReadMemoryBarrier (); |
1345 | + |
1346 | +/* push cache version of target into target */ |
1347 | +epicsShareFunc void epicsAtomicWriteMemoryBarrier (); |
1348 | + |
1349 | +/* |
1350 | + * lock out other smp processors from accessing the target, |
1351 | + * load target into cache, add one to target, flush cache |
1352 | + * to target, allow other smp processors to access the target, |
1353 | + * return new value of target as modified by this operation |
1354 | + */ |
1355 | +epicsShareFunc size_t epicsAtomicIncrSizeT ( size_t * pTarget ); |
1356 | +epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget ); |
1357 | + |
1358 | +/* |
1359 | + * lock out other smp processors from accessing the target, |
1360 | + * load target into cache, subtract one from target, flush cache |
1361 | + * to target, allow out other smp processors to access the target, |
1362 | + * return new value of target as modified by this operation |
1363 | + */ |
1364 | +epicsShareFunc size_t epicsAtomicDecrSizeT ( size_t * pTarget ); |
1365 | +epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget ); |
1366 | + |
1367 | +/* |
1368 | + * lock out other smp processors from accessing the target, |
1369 | + * load target into cache, add/sub delta to/from target, flush cache |
1370 | + * to target, allow other smp processors to access the target, |
1371 | + * return new value of target as modified by this operation |
1372 | + */ |
1373 | +epicsShareFunc size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ); |
1374 | +epicsShareFunc size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ); |
1375 | +epicsShareFunc int epicsAtomicAddIntT ( int * pTarget, int delta ); |
1376 | + |
1377 | +/* |
1378 | + * set cache version of target, flush cache to target |
1379 | + */ |
1380 | +epicsShareFunc void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue ); |
1381 | +epicsShareFunc void epicsAtomicSetIntT ( int * pTarget, int newValue ); |
1382 | +epicsShareFunc void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue ); |
1383 | + |
1384 | +/* |
1385 | + * fetch target into cache, return new value of target |
1386 | + */ |
1387 | +epicsShareFunc size_t epicsAtomicGetSizeT ( const size_t * pTarget ); |
1388 | +epicsShareFunc int epicsAtomicGetIntT ( const int * pTarget ); |
1389 | +epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget ); |
1390 | + |
1391 | +/* |
1392 | + * lock out other smp processors from accessing the target, |
1393 | + * load target into cache, if target is equal to oldVal set target |
1394 | + * to newVal, flush cache to target, allow other smp processors |
1395 | + * to access the target, return the original value stored in the |
1396 | + * target |
1397 | + */ |
1398 | +epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, |
1399 | + size_t oldVal, size_t newVal ); |
1400 | +epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget, |
1401 | + int oldVal, int newVal ); |
1402 | +epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( |
1403 | + EpicsAtomicPtrT * pTarget, |
1404 | + EpicsAtomicPtrT oldVal, |
1405 | + EpicsAtomicPtrT newVal ); |
1406 | + |
1407 | +#ifdef __cplusplus |
1408 | +} /* end of extern "C" */ |
1409 | +#endif |
1410 | + |
1411 | +/* |
1412 | + * options for inline compiler instrinsic or os specific |
1413 | + * implementations of the above function prototypes |
1414 | + * |
1415 | + * its importnat for certaiin compiler to define the |
1416 | + * inline functions before they get used in the c++ |
1417 | + * code below |
1418 | + */ |
1419 | +#include "epicsAtomicCD.h" |
1420 | + |
1421 | +#ifdef __cplusplus |
1422 | + |
1423 | +namespace epics { |
1424 | +namespace atomic { |
1425 | + |
1426 | +/* |
1427 | + * overloaded c++ interface |
1428 | + */ |
1429 | +epicsShareFunc size_t increment ( size_t & v ); |
1430 | +epicsShareFunc int increment ( int & v ); |
1431 | +epicsShareFunc size_t decrement ( size_t & v ); |
1432 | +epicsShareFunc int decrement ( int & v ); |
1433 | +epicsShareFunc size_t add ( size_t & v, size_t delta ); |
1434 | +epicsShareFunc int add ( int & v, int delta ); |
1435 | +epicsShareFunc size_t subtract ( size_t & v, size_t delta ); |
1436 | +epicsShareFunc int subtract ( int & v, int delta ); |
1437 | +epicsShareFunc void set ( size_t & v , size_t newValue ); |
1438 | +epicsShareFunc void set ( int & v, int newValue ); |
1439 | +epicsShareFunc void set ( EpicsAtomicPtrT & v, |
1440 | + EpicsAtomicPtrT newValue ); |
1441 | +epicsShareFunc size_t get ( const size_t & v ); |
1442 | +epicsShareFunc int get ( const int & v ); |
1443 | +epicsShareFunc EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v ); |
1444 | +epicsShareFunc size_t compareAndSwap ( size_t & v, size_t oldVal, |
1445 | + size_t newVal ); |
1446 | +epicsShareFunc int compareAndSwap ( int & v, int oldVal, int newVal ); |
1447 | +epicsShareFunc EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v, |
1448 | + EpicsAtomicPtrT oldVal, |
1449 | + EpicsAtomicPtrT newVal ); |
1450 | + |
1451 | +/************* incr ***************/ |
1452 | +inline size_t increment ( size_t & v ) |
1453 | +{ |
1454 | + return epicsAtomicIncrSizeT ( & v ); |
1455 | +} |
1456 | + |
1457 | +inline int increment ( int & v ) |
1458 | +{ |
1459 | + return epicsAtomicIncrIntT ( & v ); |
1460 | +} |
1461 | + |
1462 | +/************* decr ***************/ |
1463 | +inline size_t decrement ( size_t & v ) |
1464 | +{ |
1465 | + return epicsAtomicDecrSizeT ( & v ); |
1466 | +} |
1467 | + |
1468 | +inline int decrement ( int & v ) |
1469 | +{ |
1470 | + return epicsAtomicDecrIntT ( & v ); |
1471 | +} |
1472 | + |
1473 | +/************* add ***************/ |
1474 | +inline size_t add ( size_t & v, size_t delta ) |
1475 | +{ |
1476 | + return epicsAtomicAddSizeT ( & v, delta ); |
1477 | +} |
1478 | + |
1479 | +inline int add ( int & v, int delta ) |
1480 | +{ |
1481 | + return epicsAtomicAddIntT ( & v, delta ); |
1482 | +} |
1483 | + |
1484 | +/************* sub ***************/ |
1485 | +inline size_t subtract ( size_t & v, size_t delta ) |
1486 | +{ |
1487 | + return epicsAtomicSubSizeT ( & v, delta ); |
1488 | +} |
1489 | + |
1490 | +inline int subtract ( int & v, int delta ) |
1491 | +{ |
1492 | + return epicsAtomicAddIntT ( & v, -delta ); |
1493 | +} |
1494 | + |
1495 | +/************* set ***************/ |
1496 | +inline void set ( size_t & v , size_t newValue ) |
1497 | +{ |
1498 | + epicsAtomicSetSizeT ( & v, newValue ); |
1499 | +} |
1500 | + |
1501 | +inline void set ( int & v, int newValue ) |
1502 | +{ |
1503 | + epicsAtomicSetIntT ( & v, newValue ); |
1504 | +} |
1505 | + |
1506 | +inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue ) |
1507 | +{ |
1508 | + epicsAtomicSetPtrT ( & v, newValue ); |
1509 | +} |
1510 | + |
1511 | +/************* get ***************/ |
1512 | +inline size_t get ( const size_t & v ) |
1513 | +{ |
1514 | + return epicsAtomicGetSizeT ( & v ); |
1515 | +} |
1516 | + |
1517 | +inline int get ( const int & v ) |
1518 | +{ |
1519 | + return epicsAtomicGetIntT ( & v ); |
1520 | +} |
1521 | + |
1522 | +inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v ) |
1523 | +{ |
1524 | + return epicsAtomicGetPtrT ( & v ); |
1525 | +} |
1526 | + |
1527 | +/************* cas ***************/ |
1528 | +inline size_t compareAndSwap ( size_t & v, |
1529 | + size_t oldVal, size_t newVal ) |
1530 | +{ |
1531 | + return epicsAtomicCmpAndSwapSizeT ( & v, oldVal, newVal ); |
1532 | +} |
1533 | + |
1534 | +inline int compareAndSwap ( int & v, int oldVal, int newVal ) |
1535 | +{ |
1536 | + return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal ); |
1537 | +} |
1538 | + |
1539 | +inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v, |
1540 | + EpicsAtomicPtrT oldVal, |
1541 | + EpicsAtomicPtrT newVal ) |
1542 | +{ |
1543 | + return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal ); |
1544 | +} |
1545 | + |
1546 | +} /* end of namespace atomic */ |
1547 | +} /* end of namespace epics */ |
1548 | + |
1549 | +#endif /* ifdef __cplusplus */ |
1550 | + |
1551 | +#endif /* epicsAtomic_h */ |
1552 | |
1553 | === added file 'src/libCom/osi/epicsAtomicDefault.h' |
1554 | --- src/libCom/osi/epicsAtomicDefault.h 1970-01-01 00:00:00 +0000 |
1555 | +++ src/libCom/osi/epicsAtomicDefault.h 2011-08-31 22:29:24 +0000 |
1556 | @@ -0,0 +1,235 @@ |
1557 | + |
1558 | +/*************************************************************************\ |
1559 | +* Copyright (c) 2011 LANS LLC, as Operator of |
1560 | +* Los Alamos National Laboratory. |
1561 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
1562 | +* National Laboratory. |
1563 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1564 | +* in file LICENSE that is included with this distribution. |
1565 | +\*************************************************************************/ |
1566 | + |
1567 | +/* |
1568 | + * Author Jeffrey O. Hill |
1569 | + * johill@lanl.gov |
1570 | + */ |
1571 | + |
1572 | +#ifndef epicsAtomicDefault_h |
1573 | +#define epicsAtomicDefault_h |
1574 | + |
1575 | +/* |
1576 | + * EPICS_ATOMIC_INLINE might be defined, but empty for an out-of-line |
1577 | + * instantiation |
1578 | + */ |
1579 | +#ifdef EPICS_ATOMIC_INLINE |
1580 | + |
1581 | +#ifdef __cpluplus |
1582 | +extern "C" { |
1583 | +#endif |
1584 | + |
1585 | +/* |
1586 | + * struct EpicsAtomicLockKey; |
1587 | + * epicsShareFunc void epicsAtomicReadMemoryBarrier (); |
1588 | + * epicsShareFunc void epicsAtomicWriteMemoryBarrier (); |
1589 | + * epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * ); |
1590 | + * epicsShareFunc void epicsAtomicUnock ( struct EpicsAtomicLockKey * ); |
1591 | + */ |
1592 | + |
1593 | +/* |
1594 | + * incr |
1595 | + */ |
1596 | +#ifndef EPICS_ATOMIC_INCR_INTT |
1597 | +EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget ) |
1598 | +{ |
1599 | + EpicsAtomicLockKey key; |
1600 | + epicsAtomicLock ( & key ); |
1601 | + const int result = ++(*pTarget); |
1602 | + epicsAtomicUnlock ( & key ); |
1603 | + return result; |
1604 | +} |
1605 | +#endif |
1606 | + |
1607 | +#ifndef EPICS_ATOMIC_INCR_SIZET |
1608 | +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) |
1609 | +{ |
1610 | + EpicsAtomicLockKey key; |
1611 | + epicsAtomicLock ( & key ); |
1612 | + const size_t result = ++(*pTarget); |
1613 | + epicsAtomicUnlock ( & key ); |
1614 | + return result; |
1615 | +} |
1616 | +#endif |
1617 | + |
1618 | +/* |
1619 | + * decr |
1620 | + */ |
1621 | +#ifndef EPICS_ATOMIC_DECR_INTT |
1622 | +EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget ) |
1623 | +{ |
1624 | + EpicsAtomicLockKey key; |
1625 | + epicsAtomicLock ( & key ); |
1626 | + const int result = --(*pTarget); |
1627 | + epicsAtomicUnlock ( & key ); |
1628 | + return result; |
1629 | +} |
1630 | +#endif |
1631 | + |
1632 | +#ifndef EPICS_ATOMIC_DECR_SIZET |
1633 | +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) |
1634 | +{ |
1635 | + EpicsAtomicLockKey key; |
1636 | + epicsAtomicLock ( & key ); |
1637 | + const size_t result = --(*pTarget); |
1638 | + epicsAtomicUnlock ( & key ); |
1639 | + return result; |
1640 | +} |
1641 | +#endif |
1642 | + |
1643 | +/* |
1644 | + * add/sub |
1645 | + */ |
1646 | +#ifndef EPICS_ATOMIC_ADD_INTT |
1647 | +EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ) |
1648 | +{ |
1649 | + EpicsAtomicLockKey key; |
1650 | + epicsAtomicLock ( & key ); |
1651 | + const int result = *pTarget += delta; |
1652 | + epicsAtomicUnlock ( & key ); |
1653 | + return result; |
1654 | +} |
1655 | +#endif |
1656 | + |
1657 | +#ifndef EPICS_ATOMIC_ADD_SIZET |
1658 | +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ) |
1659 | +{ |
1660 | + EpicsAtomicLockKey key; |
1661 | + epicsAtomicLock ( & key ); |
1662 | + const size_t result = *pTarget += delta; |
1663 | + epicsAtomicUnlock ( & key ); |
1664 | + return result; |
1665 | +} |
1666 | +#endif |
1667 | + |
1668 | +#ifndef EPICS_ATOMIC_SUB_SIZET |
1669 | +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ) |
1670 | +{ |
1671 | + EpicsAtomicLockKey key; |
1672 | + epicsAtomicLock ( & key ); |
1673 | + const size_t result = *pTarget -= delta; |
1674 | + epicsAtomicUnlock ( & key ); |
1675 | + return result; |
1676 | +} |
1677 | +#endif |
1678 | + |
1679 | +/* |
1680 | + * set |
1681 | + */ |
1682 | +#ifndef EPICS_ATOMIC_SET_INTT |
1683 | +EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newVal ) |
1684 | +{ |
1685 | + *pTarget = newVal; |
1686 | + epicsAtomicWriteMemoryBarrier (); |
1687 | +} |
1688 | +#endif |
1689 | + |
1690 | +#ifndef EPICS_ATOMIC_SET_SIZET |
1691 | +EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newVal ) |
1692 | +{ |
1693 | + *pTarget = newVal; |
1694 | + epicsAtomicWriteMemoryBarrier (); |
1695 | +} |
1696 | +#endif |
1697 | + |
1698 | +#ifndef EPICS_ATOMIC_SET_PTRT |
1699 | +EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, |
1700 | + EpicsAtomicPtrT newVal ) |
1701 | +{ |
1702 | + *pTarget = newVal; |
1703 | + epicsAtomicWriteMemoryBarrier (); |
1704 | +} |
1705 | +#endif |
1706 | + |
1707 | +/* |
1708 | + * get |
1709 | + */ |
1710 | +#ifndef EPICS_ATOMIC_GET_INTT |
1711 | +EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget ) |
1712 | +{ |
1713 | + epicsAtomicReadMemoryBarrier (); |
1714 | + return *pTarget; |
1715 | +} |
1716 | +#endif |
1717 | + |
1718 | +#ifndef EPICS_ATOMIC_GET_SIZET |
1719 | +EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget ) |
1720 | +{ |
1721 | + epicsAtomicReadMemoryBarrier (); |
1722 | + return *pTarget; |
1723 | +} |
1724 | +#endif |
1725 | + |
1726 | +#ifndef EPICS_ATOMIC_GET_PTRT |
1727 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT |
1728 | + epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget ) |
1729 | +{ |
1730 | + epicsAtomicReadMemoryBarrier (); |
1731 | + return *pTarget; |
1732 | +} |
1733 | +#endif |
1734 | + |
1735 | +/* |
1736 | + * cmp and swap |
1737 | + */ |
1738 | +#ifndef EPICS_ATOMIC_CAS_INTT |
1739 | +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldval, int newval ) |
1740 | +{ |
1741 | + EpicsAtomicLockKey key; |
1742 | + epicsAtomicLock ( & key ); |
1743 | + const int cur = *pTarget; |
1744 | + if ( cur == oldval ) { |
1745 | + *pTarget = newval; |
1746 | + } |
1747 | + epicsAtomicUnlock ( & key ); |
1748 | + return cur; |
1749 | +} |
1750 | +#endif |
1751 | + |
1752 | +#ifndef EPICS_ATOMIC_CAS_SIZET |
1753 | +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, |
1754 | + size_t oldval, size_t newval ) |
1755 | +{ |
1756 | + EpicsAtomicLockKey key; |
1757 | + epicsAtomicLock ( & key ); |
1758 | + const size_t cur = *pTarget; |
1759 | + if ( cur == oldval ) { |
1760 | + *pTarget = newval; |
1761 | + } |
1762 | + epicsAtomicUnlock ( & key ); |
1763 | + return cur; |
1764 | +} |
1765 | +#endif |
1766 | + |
1767 | +#ifndef EPICS_ATOMIC_CAS_PTRT |
1768 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( |
1769 | + EpicsAtomicPtrT * pTarget, |
1770 | + EpicsAtomicPtrT oldval, EpicsAtomicPtrT newval ) |
1771 | +{ |
1772 | + EpicsAtomicLockKey key; |
1773 | + epicsAtomicLock ( & key ); |
1774 | + const EpicsAtomicPtrT cur = *pTarget; |
1775 | + if ( cur == oldval ) { |
1776 | + *pTarget = newval; |
1777 | + } |
1778 | + epicsAtomicUnlock ( & key ); |
1779 | + return cur; |
1780 | +} |
1781 | +#endif |
1782 | + |
1783 | +#ifdef __cpluplus |
1784 | +} /* end of extern "C" */ |
1785 | +#endif |
1786 | + |
1787 | +#endif /* EPICS_ATOMIC_INLINE */ |
1788 | + |
1789 | +#endif /* epicsAtomicDefault_h */ |
1790 | + |
1791 | + |
1792 | |
1793 | === modified file 'src/libCom/osi/epicsThread.h' |
1794 | --- src/libCom/osi/epicsThread.h 2010-04-26 20:38:11 +0000 |
1795 | +++ src/libCom/osi/epicsThread.h 2011-08-31 22:29:24 +0000 |
1796 | @@ -51,7 +51,7 @@ |
1797 | /* (epicsThreadId)0 is guaranteed to be an invalid thread id */ |
1798 | typedef struct epicsThreadOSD *epicsThreadId; |
1799 | |
1800 | -typedef epicsThreadId epicsThreadOnceId; |
1801 | +typedef void * epicsThreadOnceId; |
1802 | #define EPICS_THREAD_ONCE_INIT 0 |
1803 | |
1804 | epicsShareFunc void epicsShareAPI epicsThreadOnce( |
1805 | |
1806 | === added file 'src/libCom/osi/epicsThreadOnce.cpp' |
1807 | --- src/libCom/osi/epicsThreadOnce.cpp 1970-01-01 00:00:00 +0000 |
1808 | +++ src/libCom/osi/epicsThreadOnce.cpp 2011-08-31 22:29:24 +0000 |
1809 | @@ -0,0 +1,129 @@ |
1810 | + |
1811 | +/*************************************************************************\ |
1812 | +* Copyright (c) 2011 LANS LLC, as Operator of |
1813 | +* Los Alamos National Laboratory. |
1814 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
1815 | +* National Laboratory. |
1816 | +* Copyright (c) 2002 The Regents of the University of California, as |
1817 | +* Operator of Los Alamos National Laboratory. |
1818 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1819 | +* in file LICENSE that is included with this distribution. |
1820 | +\*************************************************************************/ |
1821 | + |
1822 | +/* |
1823 | + * Author Jeffrey O. Hill johill@lanl.gov |
1824 | + * Original Authors (before converting to operating system independent code): |
1825 | + * Jeff Hill, Andrew Johnson, Marty Kraimer, Eric Norum |
1826 | + */ |
1827 | + |
1828 | +#include <cstdlib> |
1829 | + |
1830 | +#define epicsExportSharedSymbols |
1831 | +#include "errlog.h" |
1832 | +#include "cantProceed.h" |
1833 | +#include "epicsThread.h" |
1834 | +#include "epicsAtomic.h" |
1835 | +#include "epicsAssert.h" |
1836 | + |
1837 | +namespace { |
1838 | + |
1839 | +struct ThreadID { |
1840 | +public: |
1841 | + ThreadID (); |
1842 | + ThreadID ( epicsThreadId id ); |
1843 | + bool operator == ( const ThreadID & ) const; |
1844 | +private: |
1845 | + epicsThreadId m_threadId; |
1846 | + ThreadID ( const ThreadID & ); // disabled |
1847 | + ThreadID & operator = ( const ThreadID & ); // disabled |
1848 | +}; |
1849 | + |
1850 | +inline ThreadID :: ThreadID ( epicsThreadId id ) : |
1851 | + m_threadId ( id ) |
1852 | +{ |
1853 | +} |
1854 | + |
1855 | +inline ThreadID :: ThreadID () : m_threadId ( 0 ) |
1856 | +{ |
1857 | +} |
1858 | + |
1859 | +inline bool ThreadID :: operator == ( const ThreadID & ctrl ) const |
1860 | +{ |
1861 | + return ctrl.m_threadId == m_threadId; |
1862 | +} |
1863 | + |
1864 | +static ThreadID done; |
1865 | + |
1866 | +} // end of namespace annonymous |
1867 | + |
1868 | +using namespace epics; |
1869 | +using namespace atomic; |
1870 | + |
1871 | +/* |
1872 | + * epicsThreadOnceOnly () |
1873 | + */ |
1874 | +static void epicsShareAPI epicsThreadOnceOnly ( epicsThreadOnceId * pId, |
1875 | + void ( * pFunc )( void * ), |
1876 | + void * pArg ) |
1877 | +{ |
1878 | + static const epicsThreadOnceId idStartup = EPICS_THREAD_ONCE_INIT; |
1879 | + ThreadID self ( epicsThreadGetIdSelf () ); |
1880 | + epicsThreadOnceId pCurrent = compareAndSwap ( *pId, idStartup, & self ); |
1881 | + if ( pCurrent != & done ) { |
1882 | + if ( pCurrent == idStartup ) { |
1883 | + ( *pFunc ) ( pArg ); |
1884 | + set ( *pId, & done ); |
1885 | + } |
1886 | + else { |
1887 | + { |
1888 | + ThreadID & initID = |
1889 | + * reinterpret_cast < ThreadID * > ( pCurrent ); |
1890 | + if ( initID == self ) { |
1891 | + cantProceed( "epicsThreadOnce() once was called " |
1892 | + "recursively from the user's once fuction\n" ); |
1893 | + } |
1894 | + } |
1895 | + static const std :: size_t spinDownInit = 1000u; |
1896 | + static const std :: size_t spinCount = 10u; |
1897 | + STATIC_ASSERT ( spinDownInit > spinCount ); |
1898 | + static const std :: size_t spinThresh = spinDownInit - spinCount; |
1899 | + std :: size_t spinDown = spinDownInit; |
1900 | + do { |
1901 | + if ( spinDown <= spinThresh ) { |
1902 | + epicsThreadSleep ( epicsThreadSleepQuantum () ); |
1903 | + } |
1904 | + if ( spinDown > 0u ) { |
1905 | + spinDown--; |
1906 | + } |
1907 | + else { |
1908 | + errlogPrintf ( "epicsThreadOnce: waiting for another " |
1909 | + "thread to finish calling the once function\n" ); |
1910 | + spinDown = spinThresh; |
1911 | + } |
1912 | + pCurrent = get ( *pId ); |
1913 | + } while ( pCurrent != & done ); |
1914 | + } |
1915 | + } |
1916 | +} |
1917 | + |
1918 | +// |
1919 | +// we implement this as a separate function so that it is easy to see |
1920 | +// that the performance impact of the primary (most commonly used) path |
1921 | +// and that options for inlining this function are available (based on |
1922 | +// source code organization) |
1923 | +// |
1924 | +// performance might be slightly better if this were implemented as an inline |
1925 | +// function, but that would pull epicsAtomic.h into epicsThread.h, and on |
1926 | +// windows this includes (the lean and mean version of) windows.h, so perhaps |
1927 | +// its best to make this an out-of-line function as that type of instantiation |
1928 | +// will probably have only a small negative impact on performance |
1929 | +// |
1930 | +extern "C" void epicsShareAPI epicsThreadOnce ( epicsThreadOnceId * pId, |
1931 | + void ( * pFunc )( void * ), |
1932 | + void * pArg ) |
1933 | +{ |
1934 | + const epicsThreadOnceId pCurrent = get ( *pId ); |
1935 | + if ( pCurrent != & done ) { |
1936 | + epicsThreadOnceOnly ( pId, pFunc, pArg ); |
1937 | + } |
1938 | +} |
1939 | |
1940 | === modified file 'src/libCom/osi/os/RTEMS/osdThread.c' |
1941 | --- src/libCom/osi/os/RTEMS/osdThread.c 2010-10-05 19:27:37 +0000 |
1942 | +++ src/libCom/osi/os/RTEMS/osdThread.c 2011-08-31 22:29:24 +0000 |
1943 | @@ -60,7 +60,6 @@ |
1944 | * Support for `once-only' execution |
1945 | */ |
1946 | static int initialized = 0; |
1947 | -static epicsMutexId onceMutex; |
1948 | |
1949 | /* |
1950 | * Just map osi 0 to 99 into RTEMS 199 to 100 |
1951 | @@ -231,7 +230,6 @@ |
1952 | rtems_task_priority old; |
1953 | |
1954 | rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old); |
1955 | - onceMutex = epicsMutexMustCreate(); |
1956 | taskVarMutex = epicsMutexMustCreate (); |
1957 | rtems_task_ident (RTEMS_SELF, 0, &tid); |
1958 | setThreadInfo (tid, "_main_", NULL, NULL); |
1959 | @@ -471,36 +469,6 @@ |
1960 | } |
1961 | |
1962 | /* |
1963 | - * Ensure func() is run only once. |
1964 | - */ |
1965 | -void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg) |
1966 | -{ |
1967 | - #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1 |
1968 | - |
1969 | - if (!initialized) epicsThreadInit(); |
1970 | - epicsMutexMustLock(onceMutex); |
1971 | - if (*id != EPICS_THREAD_ONCE_DONE) { |
1972 | - if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ |
1973 | - *id = epicsThreadGetIdSelf(); /* mark active */ |
1974 | - epicsMutexUnlock(onceMutex); |
1975 | - func(arg); |
1976 | - epicsMutexMustLock(onceMutex); |
1977 | - *id = EPICS_THREAD_ONCE_DONE; /* mark done */ |
1978 | - } else if (*id == epicsThreadGetIdSelf()) { |
1979 | - epicsMutexUnlock(onceMutex); |
1980 | - cantProceed("Recursive epicsThreadOnce() initialization\n"); |
1981 | - } else |
1982 | - while (*id != EPICS_THREAD_ONCE_DONE) { |
1983 | - /* Another thread is in the above func(arg) call. */ |
1984 | - epicsMutexUnlock(onceMutex); |
1985 | - epicsThreadSleep(epicsThreadSleepQuantum()); |
1986 | - epicsMutexMustLock(onceMutex); |
1987 | - } |
1988 | - } |
1989 | - epicsMutexUnlock(onceMutex); |
1990 | -} |
1991 | - |
1992 | -/* |
1993 | * Thread private storage implementation based on the vxWorks |
1994 | * implementation by Andrew Johnson APS/ASD. |
1995 | */ |
1996 | |
1997 | === added file 'src/libCom/osi/os/WIN32/epicsAtomicMS.h' |
1998 | --- src/libCom/osi/os/WIN32/epicsAtomicMS.h 1970-01-01 00:00:00 +0000 |
1999 | +++ src/libCom/osi/os/WIN32/epicsAtomicMS.h 2011-08-31 22:29:24 +0000 |
2000 | @@ -0,0 +1,222 @@ |
2001 | + |
2002 | +/*************************************************************************\ |
2003 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2004 | +* Los Alamos National Laboratory. |
2005 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
2006 | +* National Laboratory. |
2007 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2008 | +* in file LICENSE that is included with this distribution. |
2009 | +\*************************************************************************/ |
2010 | + |
2011 | +/* |
2012 | + * Author Jeffrey O. Hill |
2013 | + * johill@lanl.gov |
2014 | + */ |
2015 | + |
2016 | +#ifndef epicsAtomicMS_h |
2017 | +#define epicsAtomicMS_h |
2018 | + |
2019 | +#include "epicsAssert.h" |
2020 | + |
2021 | +#ifdef __cplusplus |
2022 | +extern "C" { |
2023 | +#endif /* __cplusplus */ |
2024 | + |
2025 | +#ifndef EPICS_ATOMIC_INCR_INTT |
2026 | +#define EPICS_ATOMIC_INCR_INTT |
2027 | +EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget ) |
2028 | +{ |
2029 | + STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) ); |
2030 | + MS_LONG * const pTarg = ( MS_LONG * ) pTarget; |
2031 | + return MS_InterlockedIncrement ( pTarg ); |
2032 | +} |
2033 | +#endif |
2034 | + |
2035 | +#ifndef EPICS_ATOMIC_DECR_INTT |
2036 | +#define EPICS_ATOMIC_DECR_INTT |
2037 | +EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget ) |
2038 | +{ |
2039 | + STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) ); |
2040 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2041 | + return MS_InterlockedDecrement ( pTarg ); |
2042 | +} |
2043 | +#endif |
2044 | + |
2045 | +#ifndef EPICS_ATOMIC_ADD_INTT |
2046 | +#define EPICS_ATOMIC_ADD_INTT |
2047 | +EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ) |
2048 | +{ |
2049 | + STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) ); |
2050 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2051 | + /* we dont use InterlockedAdd because only latest windows is supported */ |
2052 | + return delta + ( int ) MS_InterlockedExchangeAdd ( pTarg, |
2053 | + ( MS_LONG ) delta ); |
2054 | +} |
2055 | +#endif |
2056 | + |
2057 | +#ifndef EPICS_ATOMIC_CAS_INTT |
2058 | +#define EPICS_ATOMIC_CAS_INTT |
2059 | +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, |
2060 | + int oldVal, int newVal ) |
2061 | +{ |
2062 | + STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( int ) ); |
2063 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2064 | + return (int) MS_InterlockedCompareExchange ( pTarg, |
2065 | + (MS_LONG) newVal, (MS_LONG) oldVal ); |
2066 | +} |
2067 | +#endif |
2068 | + |
2069 | +#if ! defined ( MS_ATOMIC_64 ) |
2070 | + |
2071 | +/* |
2072 | + * necessary for next three functions |
2073 | + * |
2074 | + * looking at the MS documentation it appears that they will |
2075 | + * keep type long the same size as an int on 64 bit builds |
2076 | + */ |
2077 | +STATIC_ASSERT ( sizeof ( MS_LONG ) == sizeof ( size_t ) ); |
2078 | + |
2079 | +#ifndef EPICS_ATOMIC_INCR_SIZET |
2080 | +#define EPICS_ATOMIC_INCR_SIZET |
2081 | +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) |
2082 | +{ |
2083 | + MS_LONG * const pTarg = ( MS_LONG * ) pTarget; |
2084 | + return MS_InterlockedIncrement ( pTarg ); |
2085 | +} |
2086 | +#endif |
2087 | + |
2088 | +#ifndef EPICS_ATOMIC_DECR_SIZET |
2089 | +#define EPICS_ATOMIC_DECR_SIZET |
2090 | +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) |
2091 | +{ |
2092 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2093 | + return MS_InterlockedDecrement ( pTarg ); |
2094 | +} |
2095 | +#endif |
2096 | + |
2097 | +#ifndef EPICS_ATOMIC_ADD_SIZET |
2098 | +#define EPICS_ATOMIC_ADD_SIZET |
2099 | +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, |
2100 | + size_t delta ) |
2101 | +{ |
2102 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2103 | + /* we dont use InterlockedAdd because only latest windows is supported */ |
2104 | + return delta + ( size_t ) MS_InterlockedExchangeAdd ( pTarg, |
2105 | + ( MS_LONG ) delta ); |
2106 | +} |
2107 | +#endif |
2108 | + |
2109 | +#ifndef EPICS_ATOMIC_SUB_SIZET |
2110 | +#define EPICS_ATOMIC_SUB_SIZET |
2111 | +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ) |
2112 | +{ |
2113 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2114 | + MS_LONG ldelta = (MS_LONG) delta; |
2115 | + /* we dont use InterlockedAdd because only latest windows is supported */ |
2116 | + return ( ( size_t ) MS_InterlockedExchangeAdd ( pTarg, -ldelta ) ) - delta; |
2117 | +} |
2118 | +#endif |
2119 | + |
2120 | +#ifndef EPICS_ATOMIC_CAS_SIZET |
2121 | +#define EPICS_ATOMIC_CAS_SIZET |
2122 | +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( |
2123 | + size_t * pTarget, |
2124 | + size_t oldVal, size_t newVal ) |
2125 | +{ |
2126 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2127 | + return (size_t) MS_InterlockedCompareExchange ( pTarg, |
2128 | + (MS_LONG) newVal, (MS_LONG) oldVal ); |
2129 | +} |
2130 | +#endif |
2131 | + |
2132 | +#ifndef EPICS_ATOMIC_CAS_PTRT |
2133 | +#define EPICS_ATOMIC_CAS_PTRT |
2134 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( |
2135 | + EpicsAtomicPtrT * pTarget, |
2136 | + EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ) |
2137 | +{ |
2138 | + MS_LONG * const pTarg = ( MS_LONG * ) ( pTarget ); |
2139 | + return (EpicsAtomicPtrT) MS_InterlockedCompareExchange ( pTarg, |
2140 | + (MS_LONG) newVal, (MS_LONG) oldVal ); |
2141 | +} |
2142 | +#endif |
2143 | + |
2144 | +#else /* ! MS_ATOMIC_64 */ |
2145 | + |
2146 | +/* |
2147 | + * necessary for next three functions |
2148 | + */ |
2149 | +STATIC_ASSERT ( sizeof ( MS_LONGLONG ) == sizeof ( size_t ) ); |
2150 | + |
2151 | +#ifndef EPICS_ATOMIC_INCR_SIZET |
2152 | +#define EPICS_ATOMIC_INCR_SIZET |
2153 | +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) |
2154 | +{ |
2155 | + MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) pTarget; |
2156 | + return ( size_t ) MS_InterlockedIncrement64 ( pTarg ); |
2157 | +} |
2158 | +#endif |
2159 | + |
2160 | +#ifndef EPICS_ATOMIC_DECR_SIZET |
2161 | +#define EPICS_ATOMIC_DECR_SIZET |
2162 | +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) |
2163 | +{ |
2164 | + MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget ); |
2165 | + return ( size_t ) MS_InterlockedDecrement64 ( pTarg ); |
2166 | +} |
2167 | +#endif |
2168 | + |
2169 | +#ifndef EPICS_ATOMIC_ADD_SIZET |
2170 | +#define EPICS_ATOMIC_ADD_SIZET |
2171 | +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ) |
2172 | +{ |
2173 | + MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget ); |
2174 | + /* we dont use InterlockedAdd64 because only latest windows is supported */ |
2175 | + return delta + ( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, |
2176 | + ( MS_LONGLONG ) delta ); |
2177 | +} |
2178 | +#endif |
2179 | + |
2180 | +#ifndef EPICS_ATOMIC_SUB_SIZET |
2181 | +#define EPICS_ATOMIC_SUB_SIZET |
2182 | +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ) |
2183 | +{ |
2184 | + MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget ); |
2185 | + MS_LONGLONG ldelta = (MS_LONGLONG) delta; |
2186 | + /* we dont use InterlockedAdd64 because only latest windows is supported */ |
2187 | + return (( size_t ) MS_InterlockedExchangeAdd64 ( pTarg, -ldelta )) - delta; |
2188 | +} |
2189 | +#endif |
2190 | + |
2191 | +#ifndef EPICS_ATOMIC_CAS_SIZET |
2192 | +#define EPICS_ATOMIC_CAS_SIZET |
2193 | +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, |
2194 | + size_t oldVal, size_t newVal ) |
2195 | +{ |
2196 | + MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget ); |
2197 | + return (size_t) MS_InterlockedCompareExchange64 ( pTarg, |
2198 | + (MS_LONGLONG) newVal, |
2199 | + (MS_LONGLONG) oldVal ); |
2200 | +} |
2201 | +#endif |
2202 | + |
2203 | +#ifndef EPICS_ATOMIC_CAS_PTRT |
2204 | +#define EPICS_ATOMIC_CAS_PTRT |
2205 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( |
2206 | + EpicsAtomicPtrT * pTarget, |
2207 | + EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ) |
2208 | +{ |
2209 | + MS_LONGLONG * const pTarg = ( MS_LONGLONG * ) ( pTarget ); |
2210 | + return (EpicsAtomicPtrT) MS_InterlockedCompareExchange64 ( pTarg, |
2211 | + (MS_LONGLONG) newVal, (MS_LONGLONG) oldVal ); |
2212 | +} |
2213 | +#endif |
2214 | + |
2215 | +#endif /* ! MS_ATOMIC_64 */ |
2216 | + |
2217 | +#ifdef __cplusplus |
2218 | +} /* end of extern "C" */ |
2219 | +#endif /* __cplusplus */ |
2220 | + |
2221 | +#endif /* ifdef epicsAtomicMS_h */ |
2222 | + |
2223 | |
2224 | === added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp' |
2225 | --- src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000 |
2226 | +++ src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp 2011-08-31 22:29:24 +0000 |
2227 | @@ -0,0 +1,22 @@ |
2228 | + |
2229 | +/*************************************************************************\ |
2230 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2231 | +* Los Alamos National Laboratory. |
2232 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2233 | +* in file LICENSE that is included with this distribution. |
2234 | +\*************************************************************************/ |
2235 | + |
2236 | +/* |
2237 | + * Author Jeffrey O. Hill |
2238 | + * johill@lanl.gov |
2239 | + */ |
2240 | + |
2241 | +#define epicsExportSharedSymbols |
2242 | +#include "epicsAtomic.h" |
2243 | + |
2244 | +// if the compiler is unable to inline then instantiate out-of-line |
2245 | +#ifndef EPICS_ATOMIC_INLINE |
2246 | +#define EPICS_ATOMIC_INLINE |
2247 | +#include "epicsAtomic.h" |
2248 | +#endif |
2249 | + |
2250 | |
2251 | === added file 'src/libCom/osi/os/WIN32/epicsAtomicOSD.h' |
2252 | --- src/libCom/osi/os/WIN32/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000 |
2253 | +++ src/libCom/osi/os/WIN32/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000 |
2254 | @@ -0,0 +1,49 @@ |
2255 | + |
2256 | +/*************************************************************************\ |
2257 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2258 | +* Los Alamos National Laboratory. |
2259 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
2260 | +* National Laboratory. |
2261 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2262 | +* in file LICENSE that is included with this distribution. |
2263 | +\*************************************************************************/ |
2264 | + |
2265 | +/* |
2266 | + * Author Jeffrey O. Hill |
2267 | + * johill@lanl.gov |
2268 | + */ |
2269 | + |
2270 | +#ifndef epicsAtomicOSD_h |
2271 | +#define epicsAtomicOSD_h |
2272 | + |
2273 | +#define VC_EXTRALEAN |
2274 | +#define STRICT |
2275 | +#include "windows.h" |
2276 | + |
2277 | +#if defined ( _WIN64 ) |
2278 | +# define MS_ATOMIC_64 |
2279 | +#endif |
2280 | + |
2281 | +#define MS_LONG LONG |
2282 | +#define MS_InterlockedExchange InterlockedExchange |
2283 | +#define MS_InterlockedCompareExchange InterlockedCompareExchange |
2284 | +#define MS_InterlockedIncrement InterlockedIncrement |
2285 | +#define MS_InterlockedDecrement InterlockedDecrement |
2286 | +#define MS_InterlockedExchange InterlockedExchange |
2287 | +#define MS_InterlockedExchangeAdd InterlockedExchangeAdd |
2288 | +#if defined ( MS_ATOMIC_64 ) |
2289 | +# define MS_LONGLONG LONGLONG |
2290 | +# define MS_InterlockedIncrement64 InterlockedIncrement64 |
2291 | +# define MS_InterlockedDecrement64 InterlockedDecrement64 |
2292 | +# define MS_InterlockedExchange64 InterlockedExchange64 |
2293 | +# define MS_InterlockedExchangeAdd64 InterlockedExchangeAdd64 |
2294 | +# define MS_InterlockedCompareExchange InterlockedCompareExchange64 |
2295 | +#endif |
2296 | + |
2297 | +#ifdef EPICS_ATOMIC_INLINE |
2298 | +# include "epicsAtomicMS.h" |
2299 | +# include "epicsAtomicDefault.h" |
2300 | +#endif |
2301 | + |
2302 | +#endif /* epicsAtomicOSD_h */ |
2303 | + |
2304 | |
2305 | === modified file 'src/libCom/osi/os/WIN32/osdThread.c' |
2306 | --- src/libCom/osi/os/WIN32/osdThread.c 2011-02-11 22:33:58 +0000 |
2307 | +++ src/libCom/osi/os/WIN32/osdThread.c 2011-08-31 22:29:24 +0000 |
2308 | @@ -1008,41 +1008,6 @@ |
2309 | } |
2310 | |
2311 | /* |
2312 | - * epicsThreadOnce () |
2313 | - */ |
2314 | -epicsShareFunc void epicsShareAPI epicsThreadOnce ( |
2315 | - epicsThreadOnceId *id, void (*func)(void *), void *arg ) |
2316 | -{ |
2317 | - static struct epicsThreadOSD threadOnceComplete; |
2318 | - #define EPICS_THREAD_ONCE_DONE & threadOnceComplete |
2319 | - win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); |
2320 | - |
2321 | - assert ( pGbl ); |
2322 | - |
2323 | - EnterCriticalSection ( & pGbl->mutex ); |
2324 | - |
2325 | - if ( *id != EPICS_THREAD_ONCE_DONE ) { |
2326 | - if ( *id == EPICS_THREAD_ONCE_INIT ) { /* first call */ |
2327 | - *id = epicsThreadGetIdSelf(); /* mark active */ |
2328 | - LeaveCriticalSection ( & pGbl->mutex ); |
2329 | - func ( arg ); |
2330 | - EnterCriticalSection ( & pGbl->mutex ); |
2331 | - *id = EPICS_THREAD_ONCE_DONE; /* mark done */ |
2332 | - } else if ( *id == epicsThreadGetIdSelf() ) { |
2333 | - LeaveCriticalSection ( & pGbl->mutex ); |
2334 | - cantProceed( "Recursive epicsThreadOnce() initialization\n" ); |
2335 | - } else |
2336 | - while ( *id != EPICS_THREAD_ONCE_DONE ) { |
2337 | - /* Another thread is in the above func(arg) call. */ |
2338 | - LeaveCriticalSection ( & pGbl->mutex ); |
2339 | - epicsThreadSleep ( epicsThreadSleepQuantum() ); |
2340 | - EnterCriticalSection ( & pGbl->mutex ); |
2341 | - } |
2342 | - } |
2343 | - LeaveCriticalSection ( & pGbl->mutex ); |
2344 | -} |
2345 | - |
2346 | -/* |
2347 | * epicsThreadPrivateCreate () |
2348 | */ |
2349 | epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate () |
2350 | |
2351 | === added file 'src/libCom/osi/os/posix/epicsAtomicOSD.cpp' |
2352 | --- src/libCom/osi/os/posix/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000 |
2353 | +++ src/libCom/osi/os/posix/epicsAtomicOSD.cpp 2011-08-31 22:29:24 +0000 |
2354 | @@ -0,0 +1,108 @@ |
2355 | + |
2356 | +/*************************************************************************\ |
2357 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2358 | +* Los Alamos National Laboratory. |
2359 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2360 | +* in file LICENSE that is included with this distribution. |
2361 | +\*************************************************************************/ |
2362 | + |
2363 | +/* |
2364 | + * Author Jeffrey O. Hill |
2365 | + * johill@lanl.gov |
2366 | + */ |
2367 | + |
2368 | +#define epicsExportSharedSymbols |
2369 | +#include "epicsAtomic.h" |
2370 | + |
2371 | +// if the compiler is unable to inline then instantiate out-of-line |
2372 | +#ifndef EPICS_ATOMIC_INLINE |
2373 | +#define EPICS_ATOMIC_INLINE |
2374 | +#include "epicsAtomic.h" |
2375 | +#endif |
2376 | + |
2377 | +/* Authors: Jeffrey O. Hill */ |
2378 | +#include <errno.h> |
2379 | +#include <unistd.h> |
2380 | +#include <pthread.h> |
2381 | + |
2382 | +#define epicsExportSharedSymbols |
2383 | +#include "epicsAssert.h" |
2384 | + |
2385 | +// if the compiler is unable to inline then instantiate out-of-line |
2386 | +#ifndef EPICS_ATOMIC_INLINE |
2387 | +#define EPICS_ATOMIC_INLINE |
2388 | +#include "epicsAtomic.h" |
2389 | +#endif |
2390 | + |
2391 | +#ifndef EPICS_ATOMIC_LOCK |
2392 | + |
2393 | +/* |
2394 | + * Slow, but probably correct on all systems. |
2395 | + * Useful only if something more efficent isnt |
2396 | + * provided based on knowledge of the compiler |
2397 | + * or OS |
2398 | + * |
2399 | + * A statically initialized pthread mutex doesnt |
2400 | + * need to be destroyed |
2401 | + * |
2402 | + * !!!!! |
2403 | + * !!!!! WARNING |
2404 | + * !!!!! |
2405 | + * !!!!! Do not use this implementation on systems where |
2406 | + * !!!!! code runs at interrupt context. If so, then |
2407 | + * !!!!! an implementation must be provided that is based |
2408 | + * !!!!! on a compiler intrinsic or an interrpt lock and or |
2409 | + * !!!!! a spin lock primitive |
2410 | + * !!!!! |
2411 | + */ |
2412 | +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; |
2413 | + |
2414 | +void epicsAtomicLock ( EpicsAtomicLockKey * ) |
2415 | +{ |
2416 | + unsigned countDown = 1000u; |
2417 | + int status; |
2418 | + while ( true ) { |
2419 | + status = pthread_mutex_lock ( & mutex ); |
2420 | + if ( status == 0 ) return; |
2421 | + assert ( status == EINTR ); |
2422 | + static const useconds_t retryDelayUSec = 100000; |
2423 | + usleep ( retryDelayUSec ); |
2424 | + countDown--; |
2425 | + assert ( countDown ); |
2426 | + } |
2427 | +} |
2428 | + |
2429 | +void epicsAtomicUnlock ( EpicsAtomicLockKey * ) |
2430 | +{ |
2431 | + const int status = pthread_mutex_unlock ( & mutex ); |
2432 | + assert ( status == 0 ); |
2433 | +} |
2434 | + |
2435 | +#endif // ifndef EPICS_ATOMIC_LOCK |
2436 | + |
2437 | +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER |
2438 | +// Slow, but probably correct on all systems. |
2439 | +// Useful only if something more efficent isnt |
2440 | +// provided based on knowledge of the compiler |
2441 | +// or OS |
2442 | +void epicsAtomicReadMemoryBarrier () |
2443 | +{ |
2444 | + EpicsAtomicLockKey key; |
2445 | + epicsAtomicLock ( & key ); |
2446 | + epicsAtomicUnlock ( & key ); |
2447 | +} |
2448 | +#endif |
2449 | + |
2450 | +#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
2451 | +// Slow, but probably correct on all systems. |
2452 | +// Useful only if something more efficent isnt |
2453 | +// provided based on knowledge of the compiler |
2454 | +// or OS |
2455 | +void epicsAtomicWriteMemoryBarrier () |
2456 | +{ |
2457 | + EpicsAtomicLockKey key; |
2458 | + epicsAtomicLock ( & key ); |
2459 | + epicsAtomicUnlock ( & key ); |
2460 | +} |
2461 | +#endif |
2462 | + |
2463 | |
2464 | === added file 'src/libCom/osi/os/posix/epicsAtomicOSD.h' |
2465 | --- src/libCom/osi/os/posix/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000 |
2466 | +++ src/libCom/osi/os/posix/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000 |
2467 | @@ -0,0 +1,32 @@ |
2468 | + |
2469 | +/*************************************************************************\ |
2470 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2471 | +* Los Alamos National Laboratory. |
2472 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
2473 | +* National Laboratory. |
2474 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2475 | +* in file LICENSE that is included with this distribution. |
2476 | +\*************************************************************************/ |
2477 | + |
2478 | +/* |
2479 | + * Author Jeffrey O. Hill |
2480 | + * johill@lanl.gov |
2481 | + */ |
2482 | + |
2483 | +#ifndef epicsAtomicOSD_h |
2484 | +#define epicsAtomicOSD_h |
2485 | + |
2486 | +struct EpicsAtomicLockKey {}; |
2487 | +epicsShareFunc void epicsAtomicReadMemoryBarrier (); |
2488 | +epicsShareFunc void epicsAtomicWriteMemoryBarrier (); |
2489 | +epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * ); |
2490 | +epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * ); |
2491 | + |
2492 | +#ifdef EPICS_ATOMIC_INLINE |
2493 | + |
2494 | +#include "epicsAtomicDefault.h" |
2495 | + |
2496 | +#endif /* ifdef EPICS_ATOMIC_INLINE */ |
2497 | + |
2498 | +#endif /* epicsAtomicOSD_h */ |
2499 | + |
2500 | |
2501 | === modified file 'src/libCom/osi/os/posix/osdThread.c' |
2502 | --- src/libCom/osi/os/posix/osdThread.c 2010-05-14 22:26:54 +0000 |
2503 | +++ src/libCom/osi/os/posix/osdThread.c 2011-08-31 22:29:24 +0000 |
2504 | @@ -76,7 +76,6 @@ |
2505 | } epicsThreadOSD; |
2506 | |
2507 | static pthread_key_t getpthreadInfo; |
2508 | -static pthread_mutex_t onceLock; |
2509 | static pthread_mutex_t listLock; |
2510 | static ELLLIST pthreadList = ELLLIST_INIT; |
2511 | static commonAttr *pcommonAttr = 0; |
2512 | @@ -207,8 +206,6 @@ |
2513 | int status; |
2514 | |
2515 | pthread_key_create(&getpthreadInfo,0); |
2516 | - status = pthread_mutex_init(&onceLock,0); |
2517 | - checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit"); |
2518 | status = pthread_mutex_init(&listLock,0); |
2519 | checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit"); |
2520 | pcommonAttr = calloc(1,sizeof(commonAttr)); |
2521 | @@ -321,47 +318,6 @@ |
2522 | #endif /*_POSIX_THREAD_ATTR_STACKSIZE*/ |
2523 | } |
2524 | |
2525 | |
2526 | -epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg) |
2527 | -{ |
2528 | - static struct epicsThreadOSD threadOnceComplete; |
2529 | - #define EPICS_THREAD_ONCE_DONE &threadOnceComplete |
2530 | - int status; |
2531 | - |
2532 | - epicsThreadInit(); |
2533 | - status = mutexLock(&onceLock); |
2534 | - if(status) { |
2535 | - fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n", |
2536 | - strerror(status)); |
2537 | - exit(-1); |
2538 | - } |
2539 | - |
2540 | - if (*id != EPICS_THREAD_ONCE_DONE) { |
2541 | - if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ |
2542 | - *id = epicsThreadGetIdSelf(); /* mark active */ |
2543 | - status = pthread_mutex_unlock(&onceLock); |
2544 | - checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); |
2545 | - func(arg); |
2546 | - status = mutexLock(&onceLock); |
2547 | - checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); |
2548 | - *id = EPICS_THREAD_ONCE_DONE; /* mark done */ |
2549 | - } else if (*id == epicsThreadGetIdSelf()) { |
2550 | - status = pthread_mutex_unlock(&onceLock); |
2551 | - checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); |
2552 | - cantProceed("Recursive epicsThreadOnce() initialization\n"); |
2553 | - } else |
2554 | - while (*id != EPICS_THREAD_ONCE_DONE) { |
2555 | - /* Another thread is in the above func(arg) call. */ |
2556 | - status = pthread_mutex_unlock(&onceLock); |
2557 | - checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); |
2558 | - epicsThreadSleep(epicsThreadSleepQuantum()); |
2559 | - status = mutexLock(&onceLock); |
2560 | - checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); |
2561 | - } |
2562 | - } |
2563 | - status = pthread_mutex_unlock(&onceLock); |
2564 | - checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce"); |
2565 | -} |
2566 | - |
2567 | epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name, |
2568 | unsigned int priority, unsigned int stackSize, |
2569 | EPICSTHREADFUNC funptr,void *parm) |
2570 | |
2571 | === added file 'src/libCom/osi/os/solaris/epicsAtomicOSD.h' |
2572 | --- src/libCom/osi/os/solaris/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000 |
2573 | +++ src/libCom/osi/os/solaris/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000 |
2574 | @@ -0,0 +1,166 @@ |
2575 | + |
2576 | +/*************************************************************************\ |
2577 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2578 | +* Los Alamos National Laboratory. |
2579 | +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne |
2580 | +* National Laboratory. |
2581 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2582 | +* in file LICENSE that is included with this distribution. |
2583 | +\*************************************************************************/ |
2584 | + |
2585 | +/* |
2586 | + * Author Jeffrey O. Hill |
2587 | + * johill@lanl.gov |
2588 | + */ |
2589 | + |
2590 | +#ifndef epicsAtomicOSD_h |
2591 | +#define epicsAtomicOSD_h |
2592 | + |
2593 | +#if defined ( EPICS_ATOMIC_INLINE ) |
2594 | + |
2595 | +/* |
2596 | + * atomic.h exists only in Solaris 10 or higher |
2597 | + */ |
2598 | +#if defined ( __SunOS_5_10 ) |
2599 | + |
2600 | +#include <atomic.h> |
2601 | + |
2602 | +#ifdef __cplusplus |
2603 | +extern "C" { |
2604 | +#endif /* __cplusplus */ |
2605 | + |
2606 | +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER |
2607 | +#define EPICS_ATOMIC_READ_MEMORY_BARRIER |
2608 | +EPICS_ATOMIC_INLINE int epicsAtomicReadMemoryBarrier () |
2609 | +{ |
2610 | + membar_consumer (); |
2611 | +} |
2612 | +#endif |
2613 | + |
2614 | +#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
2615 | +#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
2616 | +EPICS_ATOMIC_INLINE int epicsAtomicWriteMemoryBarrier () |
2617 | +{ |
2618 | + membar_producer (); |
2619 | +} |
2620 | +#endif |
2621 | + |
2622 | +#ifndef EPICS_ATOMIC_CAS_INTT |
2623 | +#define EPICS_ATOMIC_CAS_INTT |
2624 | +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, |
2625 | + int oldVal, int newVal ) |
2626 | +{ |
2627 | + STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) ); |
2628 | + return ( int ) atomic_cas_uint ( pTarget, ( unsigned ) oldVal, |
2629 | + ( unsigned ) newVal ); |
2630 | +} |
2631 | +#endif |
2632 | + |
2633 | +#ifndef EPICS_ATOMIC_CAS_SIZET |
2634 | +#define EPICS_ATOMIC_CAS_SIZET |
2635 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapSizeT ( |
2636 | + size_t * pTarget, |
2637 | + size_t oldVal, size_t newVal ) |
2638 | +{ |
2639 | + STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) ); |
2640 | + void ** ppPtr = (void **) pTarget; |
2641 | + return ( size_t ) atomic_cas_ptr ( ppPtr, ( void * )oldVal, ( void * )newVal ); |
2642 | +} |
2643 | +#endif |
2644 | + |
2645 | +#ifndef EPICS_ATOMIC_CAS_PTRT |
2646 | +#define EPICS_ATOMIC_CAS_PTRT |
2647 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( |
2648 | + EpicsAtomicPtrT * pTarget, |
2649 | + EpicsAtomicPtrT oldVal, |
2650 | + EpicsAtomicPtrT newVal ) |
2651 | +{ |
2652 | + return atomic_cas_ptr ( pTarget, oldVal, newVal ); |
2653 | +} |
2654 | +#endif |
2655 | + |
2656 | +#ifndef EPICS_ATOMIC_INCR_INTT |
2657 | +#define EPICS_ATOMIC_INCR_INTT |
2658 | +EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget ) |
2659 | +{ |
2660 | + STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) ); |
2661 | + unsigned * const pTarg = ( unsigned * ) ( pTarget ); |
2662 | + return ( int ) atomic_inc_uint_nv ( pTarg ); |
2663 | +} |
2664 | +#endif |
2665 | + |
2666 | +#ifndef EPICS_ATOMIC_INCR_SIZET |
2667 | +#define EPICS_ATOMIC_INCR_SIZET |
2668 | +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) |
2669 | +{ |
2670 | + STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) ); |
2671 | + void ** const ppTarg = ( void ** ) ( pTarget ); |
2672 | + return ( size_t ) atomic_inc_ptr_nv ( ppTarg ); |
2673 | +} |
2674 | +#endif |
2675 | + |
2676 | +#ifndef EPICS_ATOMIC_DECR_INTT |
2677 | +#define EPICS_ATOMIC_DECR_INTT |
2678 | +EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget ) |
2679 | +{ |
2680 | + STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) ); |
2681 | + unsigned * const pTarg = ( unsigned * ) ( pTarget ); |
2682 | + return ( int ) atomic_dec_uint_nv ( pTarg ); |
2683 | +} |
2684 | +#endif |
2685 | + |
2686 | +#ifndef EPICS_ATOMIC_DECR_SIZET |
2687 | +#define EPICS_ATOMIC_DECR_SIZET |
2688 | +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) |
2689 | +{ |
2690 | + STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) ); |
2691 | + void ** const pTarg = ( void ** ) ( pTarget ); |
2692 | + return ( size_t ) atomic_dec_ptr_nv ( pTarg ); |
2693 | +} |
2694 | +#endif |
2695 | + |
2696 | +#ifndef EPICS_ATOMIC_ADD_INTT |
2697 | +#define EPICS_ATOMIC_ADD_INTT |
2698 | +EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ) |
2699 | +{ |
2700 | + STATIC_ASSERT ( sizeof ( unsigned ) == sizeof ( int ) ); |
2701 | + unsigned * const pTarg = ( unsigned * ) ( pTarget ); |
2702 | + return ( int ) atomic_add_int_nv ( pTarg, delta ); |
2703 | +} |
2704 | +#endif |
2705 | + |
2706 | +#ifndef EPICS_ATOMIC_ADD_SIZET |
2707 | +#define EPICS_ATOMIC_ADD_SIZET |
2708 | +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, |
2709 | + size_t delta ) |
2710 | +{ |
2711 | + STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) ); |
2712 | + void ** const pTarg = ( void ** ) ( pTarget ); |
2713 | + return ( size_t ) atomic_add_ptr_nv ( pTarg, ( ssize_t ) delta ); |
2714 | +} |
2715 | +#endif |
2716 | + |
2717 | +#ifndef EPICS_ATOMIC_SUB_SIZET |
2718 | +#define EPICS_ATOMIC_SUB_SIZET |
2719 | +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, |
2720 | + size_t delta ) |
2721 | +{ |
2722 | + STATIC_ASSERT ( sizeof ( void * ) == sizeof ( size_t ) ); |
2723 | + void ** const pTarg = ( void ** ) ( pTarget ); |
2724 | + ssize_t = sdelta = ( ssize_t ) delta; |
2725 | + return ( size_t ) atomic_add_ptr_nv ( pTarg, -sdelta ); |
2726 | +} |
2727 | +#endif |
2728 | + |
2729 | +#ifdef __cplusplus |
2730 | +} /* end of extern "C" */ |
2731 | +#endif /* __cplusplus */ |
2732 | + |
2733 | +#endif /* ifdef __SunOS_5_10 */ |
2734 | + |
2735 | +#include "epicsAtomicDefault.h" |
2736 | + |
2737 | +#endif /* if defined ( EPICS_ATOMIC_INLINE ) */ |
2738 | + |
2739 | +#endif /* epicsAtomicOSD_h */ |
2740 | + |
2741 | |
2742 | === added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp' |
2743 | --- src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp 1970-01-01 00:00:00 +0000 |
2744 | +++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp 2011-08-31 22:29:24 +0000 |
2745 | @@ -0,0 +1,22 @@ |
2746 | + |
2747 | +/*************************************************************************\ |
2748 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2749 | +* Los Alamos National Laboratory. |
2750 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2751 | +* in file LICENSE that is included with this distribution. |
2752 | +\*************************************************************************/ |
2753 | + |
2754 | +/* |
2755 | + * Author Jeffrey O. Hill |
2756 | + * johill@lanl.gov |
2757 | + */ |
2758 | + |
2759 | +#define epicsExportSharedSymbols |
2760 | +#include "epicsAtomic.h" |
2761 | + |
2762 | +// if the compiler is unable to inline then instantiate out-of-line |
2763 | +#ifndef EPICS_ATOMIC_INLINE |
2764 | +#define EPICS_ATOMIC_INLINE |
2765 | +#include "epicsAtomic.h" |
2766 | +#endif |
2767 | + |
2768 | |
2769 | === added file 'src/libCom/osi/os/vxWorks/epicsAtomicOSD.h' |
2770 | --- src/libCom/osi/os/vxWorks/epicsAtomicOSD.h 1970-01-01 00:00:00 +0000 |
2771 | +++ src/libCom/osi/os/vxWorks/epicsAtomicOSD.h 2011-08-31 22:29:24 +0000 |
2772 | @@ -0,0 +1,255 @@ |
2773 | +/*************************************************************************\ |
2774 | +* Copyright (c) 2011 LANS LLC, as Operator of |
2775 | +* Los Alamos National Laboratory. |
2776 | +* Copyright (c) 2011 UChicago Argonne, LLC, as Operator of |
2777 | +* Argonne National Laboratory. |
2778 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2779 | +* in file LICENSE that is included with this distribution. |
2780 | +\*************************************************************************/ |
2781 | + |
2782 | +/* |
2783 | + * Author Jeffrey O. Hill |
2784 | + * johill@lanl.gov |
2785 | + */ |
2786 | + |
2787 | +#ifndef epicsAtomicOSD_h |
2788 | +#define epicsAtomicOSD_h |
2789 | + |
2790 | +#if defined ( EPICS_ATOMIC_INLINE ) |
2791 | + |
2792 | +#include "vxWorks.h" /* obtain the version of vxWorks */ |
2793 | +#include "epicsAssert.h" |
2794 | + |
2795 | +/* |
2796 | + * With vxWorks 6.6 and later we need to use vxAtomicLib |
2797 | + * to implement this functionality correctly on SMP systems |
2798 | + */ |
2799 | +#if _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 |
2800 | + |
2801 | +#include <limits.h> |
2802 | +#include <vxAtomicLib.h> |
2803 | + |
2804 | +#ifdef __cplusplus |
2805 | +extern "C" { |
2806 | +#endif /* __cplusplus */ |
2807 | + |
2808 | +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER |
2809 | +#define EPICS_ATOMIC_READ_MEMORY_BARRIER |
2810 | +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () |
2811 | +{ |
2812 | + VX_MEM_BARRIER_R (); |
2813 | +} |
2814 | +#endif |
2815 | + |
2816 | +#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
2817 | +#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
2818 | +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () |
2819 | +{ |
2820 | + VX_MEM_BARRIER_W (); |
2821 | +} |
2822 | +#endif |
2823 | + |
2824 | +/* |
2825 | + * we make the probably correct guess that if ULONG_MAX |
2826 | + * is the same as UINT_MAX then sizeof ( atomic_t ) |
2827 | + * will be the same as sizeof ( size_t ) |
2828 | + * |
2829 | + * if ULONG_MAX != UINT_MAX then its 64 bit vxWorks and |
2830 | + * WRS doesnt not supply at this time the atomic interface |
2831 | + * for 8 byte integers that is needed - so that architecture |
2832 | + * receives the lock synchronized version |
2833 | + */ |
2834 | +#if ULONG_MAX == UINT_MAX |
2835 | + |
2836 | +STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( size_t ) ); |
2837 | +STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( EpicsAtomicPtrT ) ); |
2838 | + |
2839 | + |
2840 | +#ifndef EPICS_ATOMIC_INCR_SIZET |
2841 | +#define EPICS_ATOMIC_INCR_SIZET |
2842 | +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ) |
2843 | +{ |
2844 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2845 | + const atomic_t oldVal = vxAtomicInc ( pTarg ); |
2846 | + return 1 + ( size_t ) ( oldVal ); |
2847 | +} |
2848 | +#endif |
2849 | + |
2850 | +#ifndef EPICS_ATOMIC_DECR_SIZET |
2851 | +#define EPICS_ATOMIC_DECR_SIZET |
2852 | +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ) |
2853 | +{ |
2854 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2855 | + const atomic_t oldVal = vxAtomicDec ( pTarg ); |
2856 | + return ( ( size_t ) oldVal ) - 1u; |
2857 | +} |
2858 | +#endif |
2859 | + |
2860 | +#ifndef EPICS_ATOMIC_ADD_SIZET |
2861 | +#define EPICS_ATOMIC_ADD_SIZET |
2862 | +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ) |
2863 | +{ |
2864 | + /* |
2865 | + * vxAtomicLib doc indicates that vxAtomicAdd is |
2866 | + * implemented using signed arithmetic, but it |
2867 | + * does not change the end result because twos |
2868 | + * complement addition is used in either case |
2869 | + */ |
2870 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2871 | + const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta ); |
2872 | + return delta + ( size_t ) oldVal; |
2873 | +} |
2874 | +#endif |
2875 | + |
2876 | +#ifndef EPICS_ATOMIC_SUB_SIZET |
2877 | +#define EPICS_ATOMIC_SUB_SIZET |
2878 | +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ) |
2879 | +{ |
2880 | + /* |
2881 | + * vxAtomicLib doc indicates that vxAtomicSub is |
2882 | + * implemented using signed arithmetic, but it |
2883 | + * does not change the end result because twos |
2884 | + * complement subtraction is used in either case |
2885 | + */ |
2886 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2887 | + const atomic_t oldVal = vxAtomicSub ( pTarg, (atomic_t) delta ); |
2888 | + return ( ( size_t ) oldVal ) - delta; |
2889 | +} |
2890 | +#endif |
2891 | + |
2892 | +#ifndef EPICS_ATOMIC_CAS_SIZET |
2893 | +#define EPICS_ATOMIC_CAS_SIZET |
2894 | +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, |
2895 | + size_t oldVal, size_t newVal ) |
2896 | +{ |
2897 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2898 | + return ( size_t ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal ); |
2899 | +} |
2900 | +#endif |
2901 | + |
2902 | +#ifndef EPICS_ATOMIC_CAS_PTRT |
2903 | +#define EPICS_ATOMIC_CAS_PTRT |
2904 | +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, |
2905 | + EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ) |
2906 | +{ |
2907 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2908 | + return (EpicsAtomicPtrT) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal ); |
2909 | +} |
2910 | +#endif |
2911 | + |
2912 | +#else /* ULONG_MAX == UINT_MAX */ |
2913 | + |
2914 | +/* |
2915 | + * if its 64 bit SMP vxWorks and the compiler doesnt |
2916 | + * have an intrinsic then maybe there isnt any way to |
2917 | + * implement these without using a global lock because |
2918 | + * size_t is maybe bigger than atomic_t |
2919 | + * |
2920 | + * I dont yet have access to vxWorks manuals for |
2921 | + * 64 bit systems so this is still undecided, but is |
2922 | + * defaulting now to a global lock |
2923 | + */ |
2924 | + |
2925 | +#endif /* ULONG_MAX == UINT_MAX */ |
2926 | + |
2927 | +STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( int ) ); |
2928 | + |
2929 | +#ifndef EPICS_ATOMIC_INCR_INTT |
2930 | +#define EPICS_ATOMIC_INCR_INTT |
2931 | +EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget ) |
2932 | +{ |
2933 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2934 | + const atomic_t oldVal = vxAtomicInc ( pTarg ); |
2935 | + return 1 + ( int ) oldVal; |
2936 | +} |
2937 | +#endif |
2938 | + |
2939 | +#ifndef EPICS_ATOMIC_DECR_INTT |
2940 | +#define EPICS_ATOMIC_DECR_INTT |
2941 | +EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget ) |
2942 | +{ |
2943 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2944 | + const atomic_t oldVal = vxAtomicDec ( pTarg ); |
2945 | + return ( ( int ) oldVal ) - 1; |
2946 | +} |
2947 | +#endif |
2948 | + |
2949 | +#ifndef EPICS_ATOMIC_ADD_INTT |
2950 | +#define EPICS_ATOMIC_ADD_INTT |
2951 | +EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ) |
2952 | +{ |
2953 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2954 | + const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta ); |
2955 | + return delta + ( int ) oldVal; |
2956 | +} |
2957 | +#endif |
2958 | + |
2959 | +#ifndef EPICS_ATOMIC_CAS_INTT |
2960 | +#define EPICS_ATOMIC_CAS_INTT |
2961 | +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, |
2962 | + int oldVal, int newVal ) |
2963 | +{ |
2964 | + atomic_t * const pTarg = ( atomic_t * ) ( pTarget ); |
2965 | + return ( int ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal ); |
2966 | +} |
2967 | +#endif |
2968 | + |
2969 | +#ifdef __cplusplus |
2970 | +} /* end of extern "C" */ |
2971 | +#endif /* __cplusplus */ |
2972 | + |
2973 | +#else /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */ |
2974 | + |
2975 | +#include "vxLib.h" |
2976 | +#include "intLib.h" |
2977 | + |
2978 | +#ifdef __cplusplus |
2979 | +extern "C" { |
2980 | +#endif /* __cplusplus */ |
2981 | + |
2982 | +#ifndef EPICS_ATOMIC_LOCK |
2983 | +#define EPICS_ATOMIC_LOCK |
2984 | + |
2985 | +typedef struct EpicsAtomicLockKey { int m_key; } EpicsAtomicLockKey; |
2986 | + |
2987 | +EPICS_ATOMIC_INLINE void epicsAtomicLock ( EpicsAtomicLockKey * pKey ) |
2988 | +{ |
2989 | + pKey->m_key = intLock (); |
2990 | +} |
2991 | + |
2992 | +EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey ) |
2993 | +{ |
2994 | + intUnlock ( pKey->m_key ); |
2995 | +} |
2996 | +#endif |
2997 | + |
2998 | +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER |
2999 | +#define EPICS_ATOMIC_READ_MEMORY_BARRIER |
3000 | +/* |
3001 | + * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system |
3002 | + * (we are not protecting against multiple access to memory mapped IO) |
3003 | + */ |
3004 | +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {} |
3005 | +#endif |
3006 | + |
3007 | +#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
3008 | +#define EPICS_ATOMIC_WRITE_MEMORY_BARRIER |
3009 | +/* |
3010 | + * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system |
3011 | + * (we are not protecting against multiple access to memory mapped IO) |
3012 | + */ |
3013 | +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () {} |
3014 | +#endif |
3015 | + |
3016 | +#ifdef __cplusplus |
3017 | +} /* end of extern "C" */ |
3018 | +#endif /* __cplusplus */ |
3019 | + |
3020 | +#endif /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */ |
3021 | + |
3022 | +#include "epicsAtomicDefault.h" |
3023 | + |
3024 | +#endif /* if defined ( EPICS_ATOMIC_INLINE ) */ |
3025 | + |
3026 | +#endif /* epicsAtomicOSD_h */ |
3027 | + |
3028 | |
3029 | === modified file 'src/libCom/osi/os/vxWorks/osdThread.c' |
3030 | --- src/libCom/osi/os/vxWorks/osdThread.c 2010-08-11 15:45:17 +0000 |
3031 | +++ src/libCom/osi/os/vxWorks/osdThread.c 2011-08-31 22:29:24 +0000 |
3032 | @@ -53,7 +53,6 @@ |
3033 | static void **papTSD = 0; |
3034 | static int nepicsThreadPrivate = 0; |
3035 | |
3036 | -static SEM_ID epicsThreadOnceMutex = 0; |
3037 | |
3038 | |
3039 | /* Just map osi 0 to 99 into vx 100 to 199 */ |
3040 | /* remember that for vxWorks lower number means higher priority */ |
3041 | @@ -83,19 +82,6 @@ |
3042 | } |
3043 | } |
3044 | |
3045 | -static void epicsThreadInit(void) |
3046 | -{ |
3047 | - static int lock = 0; |
3048 | - |
3049 | - while(!vxTas(&lock)) taskDelay(1); |
3050 | - if(epicsThreadOnceMutex==0) { |
3051 | - epicsThreadOnceMutex = semMCreate( |
3052 | - SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY); |
3053 | - assert(epicsThreadOnceMutex); |
3054 | - } |
3055 | - lock = 0; |
3056 | -} |
3057 | - |
3058 | unsigned int epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass) |
3059 | { |
3060 | |
3061 | @@ -112,43 +98,6 @@ |
3062 | return stackSizeTable[stackSizeClass]; |
3063 | } |
3064 | |
3065 | -struct epicsThreadOSD {}; |
3066 | - /* Strictly speaking this should be a WIND_TCB, but we only need it to |
3067 | - * be able to create an epicsThreadId that is guaranteed never to be |
3068 | - * the same as any current TID, and since TIDs are pointers this works. |
3069 | - */ |
3070 | - |
3071 | -void epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg) |
3072 | -{ |
3073 | - static struct epicsThreadOSD threadOnceComplete; |
3074 | - #define EPICS_THREAD_ONCE_DONE &threadOnceComplete |
3075 | - int result; |
3076 | - |
3077 | - epicsThreadInit(); |
3078 | - result = semTake(epicsThreadOnceMutex, WAIT_FOREVER); |
3079 | - assert(result == OK); |
3080 | - if (*id != EPICS_THREAD_ONCE_DONE) { |
3081 | - if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ |
3082 | - *id = epicsThreadGetIdSelf(); /* mark active */ |
3083 | - semGive(epicsThreadOnceMutex); |
3084 | - func(arg); |
3085 | - result = semTake(epicsThreadOnceMutex, WAIT_FOREVER); |
3086 | - assert(result == OK); |
3087 | - *id = EPICS_THREAD_ONCE_DONE; /* mark done */ |
3088 | - } else if (*id == epicsThreadGetIdSelf()) { |
3089 | - semGive(epicsThreadOnceMutex); |
3090 | - cantProceed("Recursive epicsThreadOnce() initialization\n"); |
3091 | - } else |
3092 | - while (*id != EPICS_THREAD_ONCE_DONE) { |
3093 | - /* Another thread is in the above func(arg) call. */ |
3094 | - semGive(epicsThreadOnceMutex); |
3095 | - epicsThreadSleep(epicsThreadSleepQuantum()); |
3096 | - result = semTake(epicsThreadOnceMutex, WAIT_FOREVER); |
3097 | - assert(result == OK); |
3098 | - } |
3099 | - } |
3100 | - semGive(epicsThreadOnceMutex); |
3101 | -} |
3102 | |
3103 | |
3104 | static void createFunction(EPICSTHREADFUNC func, void *parm) |
3105 | { |
3106 | @@ -173,7 +122,6 @@ |
3107 | EPICSTHREADFUNC funptr,void *parm) |
3108 | { |
3109 | int tid; |
3110 | - if(epicsThreadOnceMutex==0) epicsThreadInit(); |
3111 | if(stackSize<100) { |
3112 | errlogPrintf("epicsThreadCreate %s illegal stackSize %d\n",name,stackSize); |
3113 | return(0); |
3114 | @@ -343,7 +291,6 @@ |
3115 | static int lock = 0; |
3116 | epicsThreadPrivateId id; |
3117 | |
3118 | - epicsThreadInit(); |
3119 | /*lock is necessary because ++nepicsThreadPrivate may not be indivisible*/ |
3120 | while(!vxTas(&lock)) taskDelay(1); |
3121 | id = (epicsThreadPrivateId)++nepicsThreadPrivate; |
3122 | |
3123 | === modified file 'src/libCom/test/Makefile' |
3124 | --- src/libCom/test/Makefile 2011-08-30 23:09:11 +0000 |
3125 | +++ src/libCom/test/Makefile 2011-08-31 22:29:24 +0000 |
3126 | @@ -108,6 +108,11 @@ |
3127 | testHarness_SRCS += epicsMutexTest.cpp |
3128 | TESTS += epicsMutexTest |
3129 | |
3130 | +TESTPROD_HOST += epicsAtomicTest |
3131 | +epicsAtomicTest_SRCS += epicsAtomicTest.c |
3132 | +testHarness_SRCS += epicsAtomicTest.c |
3133 | +TESTS += epicsAtomicTest |
3134 | + |
3135 | TESTPROD_HOST += epicsExceptionTest |
3136 | epicsExceptionTest_SRCS += epicsExceptionTest.cpp |
3137 | testHarness_SRCS += epicsExceptionTest.cpp |
3138 | @@ -178,6 +183,10 @@ |
3139 | fdmgrTest_LIBS += ca |
3140 | # FIXME: program never exits. |
3141 | |
3142 | +TESTPROD_HOST += epicsAtomicPerform |
3143 | +epicsAtomicPerform_SRCS += epicsAtomicPerform.cpp |
3144 | +testHarness_SRCS += epicsAtomicPerform.cpp |
3145 | + |
3146 | TESTPROD_HOST += cvtFastPerform |
3147 | cvtFastPerform_SRCS += cvtFastPerform.cpp |
3148 | testHarness_SRCS += cvtFastPerform.cpp |
3149 | |
3150 | === added file 'src/libCom/test/epicsAtomicPerform.cpp' |
3151 | --- src/libCom/test/epicsAtomicPerform.cpp 1970-01-01 00:00:00 +0000 |
3152 | +++ src/libCom/test/epicsAtomicPerform.cpp 2011-08-31 22:29:24 +0000 |
3153 | @@ -0,0 +1,506 @@ |
3154 | + |
3155 | +#include <cstdlib> |
3156 | +#include <cstdio> |
3157 | +#include <cassert> |
3158 | +#include <typeinfo> |
3159 | + |
3160 | +#include "epicsInterrupt.h" |
3161 | +#include "epicsAtomic.h" |
3162 | +#include "epicsTime.h" |
3163 | +#include "epicsUnitTest.h" |
3164 | +#include "testMain.h" |
3165 | + |
3166 | +using std :: size_t; |
3167 | +using namespace epics; |
3168 | +using namespace atomic; |
3169 | + |
3170 | +class RefCtr { |
3171 | +public: |
3172 | + RefCtr (); |
3173 | + ~RefCtr (); |
3174 | + void reference (); |
3175 | + void unreference (); |
3176 | +private: |
3177 | + size_t m_cnt; |
3178 | +}; |
3179 | + |
3180 | +class Ownership { |
3181 | +public: |
3182 | + Ownership (); |
3183 | + Ownership ( RefCtr & refCtr ); |
3184 | + Ownership ( const Ownership & ); |
3185 | + ~Ownership (); |
3186 | + Ownership & operator = ( const Ownership & ); |
3187 | +private: |
3188 | + RefCtr * _pRefCtr; |
3189 | + static RefCtr m_noOwnership; |
3190 | +}; |
3191 | + |
3192 | +inline RefCtr :: RefCtr () |
3193 | +{ |
3194 | + epicsAtomicSetSizeT ( & m_cnt, 0 ); |
3195 | +} |
3196 | + |
3197 | +inline RefCtr :: ~RefCtr () |
3198 | +{ |
3199 | + unsigned cnt = epicsAtomicGetSizeT ( & m_cnt ); |
3200 | + assert ( cnt == 0u ); |
3201 | +} |
3202 | + |
3203 | +inline void RefCtr :: reference () |
3204 | +{ |
3205 | + epicsAtomicIncrSizeT ( & m_cnt ); |
3206 | +} |
3207 | + |
3208 | +inline void RefCtr :: unreference () |
3209 | +{ |
3210 | + epicsAtomicDecrSizeT ( & m_cnt ); |
3211 | +} |
3212 | + |
3213 | +RefCtr Ownership :: m_noOwnership; |
3214 | + |
3215 | +inline Ownership :: Ownership () : |
3216 | + _pRefCtr ( & m_noOwnership ) |
3217 | +{ |
3218 | + m_noOwnership.reference (); |
3219 | +} |
3220 | + |
3221 | +inline Ownership :: Ownership ( RefCtr & refCtr ) : |
3222 | + _pRefCtr ( & refCtr ) |
3223 | +{ |
3224 | + refCtr.reference (); |
3225 | +} |
3226 | + |
3227 | +inline Ownership :: Ownership ( const Ownership & ownership ) : |
3228 | + _pRefCtr ( ownership._pRefCtr ) |
3229 | +{ |
3230 | + _pRefCtr->reference (); |
3231 | +} |
3232 | + |
3233 | +inline Ownership :: ~Ownership () |
3234 | +{ |
3235 | + _pRefCtr->unreference (); |
3236 | +} |
3237 | + |
3238 | +inline Ownership & Ownership :: |
3239 | + operator = ( const Ownership & ownership ) |
3240 | +{ |
3241 | + RefCtr * const pOldRefCtr = _pRefCtr; |
3242 | + _pRefCtr = ownership._pRefCtr; |
3243 | + _pRefCtr->reference (); |
3244 | + pOldRefCtr->unreference (); |
3245 | + return *this; |
3246 | +} |
3247 | + |
3248 | +inline Ownership retOwnership ( const Ownership & ownership ) |
3249 | +{ |
3250 | + return Ownership ( ownership ); |
3251 | +} |
3252 | + |
3253 | +inline Ownership recurRetOwner10 ( const Ownership & ownershipIn ) |
3254 | +{ |
3255 | + Ownership ownership = |
3256 | + retOwnership ( |
3257 | + retOwnership ( |
3258 | + retOwnership ( |
3259 | + retOwnership ( |
3260 | + retOwnership ( ownershipIn ) ) ) ) ); |
3261 | + return retOwnership ( |
3262 | + retOwnership ( |
3263 | + retOwnership ( |
3264 | + retOwnership ( |
3265 | + retOwnership ( ownership ) ) ) ) ); |
3266 | +} |
3267 | + |
3268 | +inline Ownership recurRetOwner100 ( const Ownership & ownershipIn ) |
3269 | +{ |
3270 | + Ownership ownership = |
3271 | + recurRetOwner10 ( |
3272 | + recurRetOwner10 ( |
3273 | + recurRetOwner10 ( |
3274 | + recurRetOwner10 ( |
3275 | + recurRetOwner10 ( ownershipIn ) ) ) ) ); |
3276 | + return recurRetOwner10 ( |
3277 | + recurRetOwner10 ( |
3278 | + recurRetOwner10 ( |
3279 | + recurRetOwner10 ( |
3280 | + recurRetOwner10 ( ownership ) ) ) ) ); |
3281 | +} |
3282 | + |
3283 | +inline Ownership recurRetOwner1000 ( const Ownership & ownershipIn ) |
3284 | +{ |
3285 | + Ownership ownership = |
3286 | + recurRetOwner100 ( |
3287 | + recurRetOwner100 ( |
3288 | + recurRetOwner100 ( |
3289 | + recurRetOwner100 ( |
3290 | + recurRetOwner100 ( ownershipIn ) ) ) ) ); |
3291 | + return recurRetOwner100 ( |
3292 | + recurRetOwner100 ( |
3293 | + recurRetOwner100 ( |
3294 | + recurRetOwner100 ( |
3295 | + recurRetOwner100 ( ownership ) ) ) ) ); |
3296 | +} |
3297 | + |
3298 | +inline void passRefOwnership ( const Ownership & ownershipIn, Ownership & ownershipOut ) |
3299 | +{ |
3300 | + ownershipOut = ownershipIn; |
3301 | +} |
3302 | + |
3303 | +inline void passRefOwnership10 ( const Ownership & ownershipIn, Ownership & ownershipOut ) |
3304 | +{ |
3305 | + Ownership ownershipTmp0; |
3306 | + passRefOwnership ( ownershipIn, ownershipTmp0 ); |
3307 | + Ownership ownershipTmp1; |
3308 | + passRefOwnership ( ownershipTmp0, ownershipTmp1 ); |
3309 | + Ownership ownershipTmp2; |
3310 | + passRefOwnership ( ownershipTmp1, ownershipTmp2 ); |
3311 | + Ownership ownershipTmp3; |
3312 | + passRefOwnership ( ownershipTmp2, ownershipTmp3 ); |
3313 | + Ownership ownershipTmp4; |
3314 | + passRefOwnership ( ownershipTmp3, ownershipTmp4 ); |
3315 | + Ownership ownershipTmp5; |
3316 | + passRefOwnership ( ownershipTmp4, ownershipTmp5 ); |
3317 | + Ownership ownershipTmp6; |
3318 | + passRefOwnership ( ownershipTmp5, ownershipTmp6 ); |
3319 | + Ownership ownershipTmp7; |
3320 | + passRefOwnership ( ownershipTmp6, ownershipTmp7 ); |
3321 | + Ownership ownershipTmp8; |
3322 | + passRefOwnership ( ownershipTmp7, ownershipTmp8 ); |
3323 | + passRefOwnership ( ownershipTmp8, ownershipOut ); |
3324 | +} |
3325 | + |
3326 | +inline void passRefOwnership100 ( const Ownership & ownershipIn, Ownership & ownershipOut ) |
3327 | +{ |
3328 | + Ownership ownershipTmp0; |
3329 | + passRefOwnership10 ( ownershipIn, ownershipTmp0 ); |
3330 | + Ownership ownershipTmp1; |
3331 | + passRefOwnership10 ( ownershipTmp0, ownershipTmp1 ); |
3332 | + Ownership ownershipTmp2; |
3333 | + passRefOwnership10 ( ownershipTmp1, ownershipTmp2 ); |
3334 | + Ownership ownershipTmp3; |
3335 | + passRefOwnership10 ( ownershipTmp2, ownershipTmp3 ); |
3336 | + Ownership ownershipTmp4; |
3337 | + passRefOwnership10 ( ownershipTmp3, ownershipTmp4 ); |
3338 | + Ownership ownershipTmp5; |
3339 | + passRefOwnership10 ( ownershipTmp4, ownershipTmp5 ); |
3340 | + Ownership ownershipTmp6; |
3341 | + passRefOwnership10 ( ownershipTmp5, ownershipTmp6 ); |
3342 | + Ownership ownershipTmp7; |
3343 | + passRefOwnership10 ( ownershipTmp6, ownershipTmp7 ); |
3344 | + Ownership ownershipTmp8; |
3345 | + passRefOwnership10 ( ownershipTmp7, ownershipTmp8 ); |
3346 | + passRefOwnership10 ( ownershipTmp8, ownershipOut ); |
3347 | +} |
3348 | + |
3349 | +inline void passRefOwnership1000 ( const Ownership & ownershipIn, Ownership & ownershipOut ) |
3350 | +{ |
3351 | + Ownership ownershipTmp0; |
3352 | + passRefOwnership100 ( ownershipIn, ownershipTmp0 ); |
3353 | + Ownership ownershipTmp1; |
3354 | + passRefOwnership100 ( ownershipTmp0, ownershipTmp1 ); |
3355 | + Ownership ownershipTmp2; |
3356 | + passRefOwnership100 ( ownershipTmp1, ownershipTmp2 ); |
3357 | + Ownership ownershipTmp3; |
3358 | + passRefOwnership100 ( ownershipTmp2, ownershipTmp3 ); |
3359 | + Ownership ownershipTmp4; |
3360 | + passRefOwnership100 ( ownershipTmp3, ownershipTmp4 ); |
3361 | + Ownership ownershipTmp5; |
3362 | + passRefOwnership100 ( ownershipTmp4, ownershipTmp5 ); |
3363 | + Ownership ownershipTmp6; |
3364 | + passRefOwnership100 ( ownershipTmp5, ownershipTmp6 ); |
3365 | + Ownership ownershipTmp7; |
3366 | + passRefOwnership100 ( ownershipTmp6, ownershipTmp7 ); |
3367 | + Ownership ownershipTmp8; |
3368 | + passRefOwnership100 ( ownershipTmp7, ownershipTmp8 ); |
3369 | + passRefOwnership100 ( ownershipTmp8, ownershipOut ); |
3370 | +} |
3371 | + |
3372 | +time_t extTime = 0; |
3373 | + |
3374 | +template < class T > |
3375 | +class OrdinaryIncr { |
3376 | +public: |
3377 | + OrdinaryIncr () : m_target ( 0 ) {} |
3378 | + void run (); |
3379 | + void diagnostic ( double delay ); |
3380 | +private: |
3381 | + T m_target; |
3382 | +}; |
3383 | + |
3384 | +// tests the time it takes to perform a call to an external |
3385 | +// function and also increment an integer word. The |
3386 | +// epicsInterruptIsInterruptContext function is an |
3387 | +// out-of-line function implemented in a sharable library |
3388 | +// so hopefully it wont be optimized away. |
3389 | +template < class T > |
3390 | +inline void OrdinaryIncr < T > :: run () |
3391 | +{ |
3392 | + m_target += epicsInterruptIsInterruptContext (); |
3393 | + m_target += epicsInterruptIsInterruptContext (); |
3394 | + m_target += epicsInterruptIsInterruptContext (); |
3395 | + m_target += epicsInterruptIsInterruptContext (); |
3396 | + m_target += epicsInterruptIsInterruptContext (); |
3397 | + m_target += epicsInterruptIsInterruptContext (); |
3398 | + m_target += epicsInterruptIsInterruptContext (); |
3399 | + m_target += epicsInterruptIsInterruptContext (); |
3400 | + m_target += epicsInterruptIsInterruptContext (); |
3401 | + m_target += epicsInterruptIsInterruptContext (); |
3402 | +} |
3403 | + |
3404 | +template < class T > |
3405 | +void OrdinaryIncr < T > :: diagnostic ( double delay ) |
3406 | +{ |
3407 | + delay /= 10.0; |
3408 | + delay *= 1e6; |
3409 | + const char * const pName = typeid ( T ) . name (); |
3410 | + testDiag ( "raw incr of \"%s\" and a NOOP function call takes %f microseconds", |
3411 | + pName, delay ); |
3412 | +} |
3413 | + |
3414 | +template < class T > |
3415 | +class AtomicIncr { |
3416 | +public: |
3417 | + AtomicIncr () : m_target ( 0 ) {} |
3418 | + void run (); |
3419 | + void diagnostic ( double delay ); |
3420 | +private: |
3421 | + T m_target; |
3422 | +}; |
3423 | + |
3424 | +template < class T > |
3425 | +inline void AtomicIncr < T > :: run () |
3426 | +{ |
3427 | + increment ( m_target ); |
3428 | + increment ( m_target ); |
3429 | + increment ( m_target ); |
3430 | + increment ( m_target ); |
3431 | + increment ( m_target ); |
3432 | + increment ( m_target ); |
3433 | + increment ( m_target ); |
3434 | + increment ( m_target ); |
3435 | + increment ( m_target ); |
3436 | + increment ( m_target ); |
3437 | +} |
3438 | + |
3439 | +template < class T > |
3440 | +void AtomicIncr < T > :: diagnostic ( double delay ) |
3441 | +{ |
3442 | + delay /= 10.0; |
3443 | + delay *= 1e6; |
3444 | + const char * const pName = typeid ( T ) . name (); |
3445 | + testDiag ( "epicsAtomicIncr \"%s\" takes %f microseconds", |
3446 | + pName, delay ); |
3447 | +} |
3448 | + |
3449 | +template < class T > T trueValue (); |
3450 | +template < class T > T falseValue (); |
3451 | + |
3452 | +// int |
3453 | +template <> |
3454 | +inline int trueValue < int > () { return 1; } |
3455 | + |
3456 | +template <> |
3457 | +inline int falseValue < int > () { return 0; } |
3458 | + |
3459 | +// size_t |
3460 | +template <> |
3461 | +inline size_t trueValue < size_t > () { return 1u; } |
3462 | + |
3463 | +template <> |
3464 | +inline size_t falseValue < size_t > () { return 0u; } |
3465 | + |
3466 | +// EpicsAtomicPtrT |
3467 | +template <> |
3468 | +inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > () |
3469 | +{ static char c; return & c; } |
3470 | + |
3471 | +template <> |
3472 | +inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > () |
3473 | +{ return 0u; } |
3474 | + |
3475 | +template < class T > |
3476 | +class AtomicCmpAndSwap { |
3477 | +public: |
3478 | + AtomicCmpAndSwap () : m_target ( 0 ) {} |
3479 | + void run (); |
3480 | + void diagnostic ( double delay ); |
3481 | +private: |
3482 | + T m_target; |
3483 | +}; |
3484 | + |
3485 | +template < class T > |
3486 | +inline void AtomicCmpAndSwap < T > :: run () |
3487 | +{ |
3488 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3489 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3490 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3491 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3492 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3493 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3494 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3495 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3496 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3497 | + compareAndSwap ( m_target, falseValue < T > (), trueValue < T > () ); |
3498 | +} |
3499 | + |
3500 | +template < class T > |
3501 | +void AtomicCmpAndSwap < T > :: diagnostic ( double delay ) |
3502 | +{ |
3503 | + delay /= 10.0; |
3504 | + delay *= 1e6; |
3505 | + const char * const pName = typeid ( T ) . name (); |
3506 | + testDiag ( "epicsAtomicCmpAndSwap of \"%s\" takes %f microseconds", |
3507 | + pName, delay ); |
3508 | +} |
3509 | + |
3510 | +template < class T > |
3511 | +class AtomicSet { |
3512 | +public: |
3513 | + AtomicSet () : m_target ( 0 ) {} |
3514 | + void run (); |
3515 | + void diagnostic ( double delay ); |
3516 | +private: |
3517 | + T m_target; |
3518 | +}; |
3519 | + |
3520 | +template < class T > |
3521 | +inline void AtomicSet < T > :: run () |
3522 | +{ |
3523 | + set ( m_target, 0 ); |
3524 | + set ( m_target, 0 ); |
3525 | + set ( m_target, 0 ); |
3526 | + set ( m_target, 0 ); |
3527 | + set ( m_target, 0 ); |
3528 | + set ( m_target, 0 ); |
3529 | + set ( m_target, 0 ); |
3530 | + set ( m_target, 0 ); |
3531 | + set ( m_target, 0 ); |
3532 | + set ( m_target, 0 ); |
3533 | +} |
3534 | + |
3535 | +template < class T > |
3536 | +void AtomicSet < T > :: diagnostic ( double delay ) |
3537 | +{ |
3538 | + delay /= 10.0; |
3539 | + delay *= 1e6; |
3540 | + const char * const pName = typeid ( T ) . name (); |
3541 | + testDiag ( "epicsAtomicSet of \"%s\" takes %f microseconds", |
3542 | + pName, delay ); |
3543 | +} |
3544 | + |
3545 | +static const unsigned N = 10000; |
3546 | + |
3547 | +void recursiveOwnershipRetPerformance () |
3548 | +{ |
3549 | + RefCtr refCtr; |
3550 | + epicsTime begin = epicsTime::getCurrent (); |
3551 | + for ( size_t i = 0; i < N; i++ ) { |
3552 | + Ownership ownership ( refCtr ); |
3553 | + recurRetOwner1000 ( ownership ); |
3554 | + } |
3555 | + double delay = epicsTime::getCurrent () - begin; |
3556 | + delay /= N * 1000u; // convert to delay per call |
3557 | + delay *= 1e6; // convert to micro seconds |
3558 | + testDiag ( "retOwnership() takes %f microseconds", delay ); |
3559 | +} |
3560 | + |
3561 | +void ownershipPassRefPerformance () |
3562 | +{ |
3563 | + RefCtr refCtr; |
3564 | + epicsTime begin = epicsTime::getCurrent (); |
3565 | + for ( size_t i = 0; i < N; i++ ) { |
3566 | + Ownership ownershipSrc ( refCtr ); |
3567 | + Ownership ownershipDest; |
3568 | + passRefOwnership1000 ( ownershipSrc, ownershipDest ); |
3569 | + } |
3570 | + double delay = epicsTime::getCurrent () - begin; |
3571 | + delay /= N * 1000u; // convert to delay per call |
3572 | + delay *= 1e6; // convert to micro seconds |
3573 | + testDiag ( "passRefOwnership() takes %f microseconds", delay ); |
3574 | +} |
3575 | + |
3576 | +template < class T > |
3577 | +class Ten |
3578 | +{ |
3579 | +public: |
3580 | + void run (); |
3581 | + void diagnostic ( double delay ); |
3582 | + typedef Ten < Ten < T > > Hundred; |
3583 | + typedef Ten < Hundred > Thousand; |
3584 | +private: |
3585 | + T m_target; |
3586 | +}; |
3587 | + |
3588 | +template < class T > |
3589 | +inline void Ten < T > :: run () |
3590 | +{ |
3591 | + m_target.run (); |
3592 | + m_target.run (); |
3593 | + m_target.run (); |
3594 | + m_target.run (); |
3595 | + m_target.run (); |
3596 | + m_target.run (); |
3597 | + m_target.run (); |
3598 | + m_target.run (); |
3599 | + m_target.run (); |
3600 | + m_target.run (); |
3601 | +} |
3602 | + |
3603 | +template < class T > |
3604 | +void Ten < T > :: diagnostic ( double delay ) |
3605 | +{ |
3606 | + m_target.diagnostic ( delay / 10.0 ); |
3607 | +} |
3608 | + |
3609 | +template < class T > |
3610 | +void measurePerformance () |
3611 | +{ |
3612 | + epicsTime begin = epicsTime::getCurrent (); |
3613 | + T target; |
3614 | + for ( size_t i = 0; i < N; i++ ) { |
3615 | + target.run (); |
3616 | + target.run (); |
3617 | + target.run (); |
3618 | + target.run (); |
3619 | + target.run (); |
3620 | + target.run (); |
3621 | + target.run (); |
3622 | + target.run (); |
3623 | + target.run (); |
3624 | + target.run (); |
3625 | + } |
3626 | + double delay = epicsTime::getCurrent () - begin; |
3627 | + delay /= ( N * 10u ); // convert to delay per call |
3628 | + target.diagnostic ( delay ); |
3629 | +} |
3630 | + |
3631 | +template < class T > |
3632 | +void measure () |
3633 | +{ |
3634 | + measurePerformance < typename Ten < T > :: Hundred > (); |
3635 | +} |
3636 | + |
3637 | +MAIN ( epicsAtomicPerform ) |
3638 | +{ |
3639 | + testPlan ( 0 ); |
3640 | + // |
3641 | + // The tests running here are measuring fast |
3642 | + // functions so they tend to be impacted |
3643 | + // by where the cache lines are wrt to the |
3644 | + // virtual pages perhap |
3645 | + // |
3646 | + measure < AtomicSet < int > > (); |
3647 | + measure < AtomicSet < size_t > > (); |
3648 | + measure < AtomicSet < void * > > (); |
3649 | + measure < OrdinaryIncr < int > > (); |
3650 | + measure < OrdinaryIncr < size_t > > (); |
3651 | + measure < AtomicIncr < int > > (); |
3652 | + measure < AtomicIncr < size_t > > (); |
3653 | + measure < AtomicCmpAndSwap < int > > (); |
3654 | + measure < AtomicCmpAndSwap < size_t > > (); |
3655 | + measure < AtomicCmpAndSwap < void * > > (); |
3656 | + recursiveOwnershipRetPerformance (); |
3657 | + ownershipPassRefPerformance (); |
3658 | + return testDone(); |
3659 | +} |
3660 | |
3661 | === added file 'src/libCom/test/epicsAtomicTest.cpp' |
3662 | --- src/libCom/test/epicsAtomicTest.cpp 1970-01-01 00:00:00 +0000 |
3663 | +++ src/libCom/test/epicsAtomicTest.cpp 2011-08-31 22:29:24 +0000 |
3664 | @@ -0,0 +1,238 @@ |
3665 | + |
3666 | +#include <stdlib.h> |
3667 | +#include <assert.h> |
3668 | + |
3669 | +#include "epicsAtomic.h" |
3670 | +#include "epicsTime.h" |
3671 | +#include "epicsThread.h" |
3672 | +#include "epicsUnitTest.h" |
3673 | +#include "testMain.h" |
3674 | + |
3675 | +using namespace epics; |
3676 | +using namespace atomic; |
3677 | + |
3678 | +template < class T > |
3679 | +struct TestDataIncrDecr { |
3680 | + T m_testValue; |
3681 | + size_t m_testIterations; |
3682 | +}; |
3683 | + |
3684 | +template < class T > |
3685 | +struct TestDataAddSub { |
3686 | + T m_testValue; |
3687 | + size_t m_testIterations; |
3688 | + static const T delta = 17; |
3689 | +}; |
3690 | + |
3691 | +template < class T > |
3692 | +static void incr ( void *arg ) |
3693 | +{ |
3694 | + TestDataIncrDecr < T > * const pTestData = |
3695 | + reinterpret_cast < TestDataIncrDecr < T > * > ( arg ); |
3696 | + increment ( pTestData->m_testValue ); |
3697 | + increment ( pTestData->m_testIterations ); |
3698 | +} |
3699 | + |
3700 | +template < class T > |
3701 | +static void decr ( void *arg ) |
3702 | +{ |
3703 | + TestDataIncrDecr < T > * const pTestData = |
3704 | + reinterpret_cast < TestDataIncrDecr < T > * > ( arg ); |
3705 | + decrement ( pTestData->m_testValue ); |
3706 | + increment ( pTestData->m_testIterations ); |
3707 | +} |
3708 | + |
3709 | + |
3710 | +template < class T > |
3711 | +static void add ( void *arg ) |
3712 | +{ |
3713 | + TestDataAddSub < T > * const pTestData = |
3714 | + reinterpret_cast < TestDataAddSub < T > * > ( arg ); |
3715 | + add ( pTestData->m_testValue, TestDataAddSub < T > :: delta ); |
3716 | + increment ( pTestData->m_testIterations ); |
3717 | +} |
3718 | + |
3719 | +template < class T > |
3720 | +static void sub ( void *arg ) |
3721 | +{ |
3722 | + TestDataAddSub < T > * const pTestData = |
3723 | + reinterpret_cast < TestDataAddSub < T > * > ( arg ); |
3724 | + subtract ( pTestData->m_testValue, TestDataAddSub < T > :: delta ); |
3725 | + increment ( pTestData->m_testIterations ); |
3726 | +} |
3727 | + |
3728 | +template < class T > |
3729 | +struct TestDataCAS { |
3730 | + T m_testValue; |
3731 | + size_t m_testIterationsSet; |
3732 | + size_t m_testIterationsNotSet; |
3733 | +}; |
3734 | + |
3735 | +int isModulo ( size_t N, size_t n ) |
3736 | +{ |
3737 | + return ( n % N ) == 0u; |
3738 | +} |
3739 | + |
3740 | +template < class T > |
3741 | +static T trueValue (); |
3742 | +template < class T > |
3743 | +static T falseValue (); |
3744 | + |
3745 | +// int |
3746 | +template <> |
3747 | +inline int trueValue < int > () { return 1; } |
3748 | + |
3749 | +template <> |
3750 | +inline int falseValue < int > () { return 0; } |
3751 | + |
3752 | +// size_t |
3753 | +template <> |
3754 | +inline size_t trueValue < size_t > () { return 1u; } |
3755 | + |
3756 | +template <> |
3757 | +inline size_t falseValue < size_t > () { return 0u; } |
3758 | + |
3759 | +// EpicsAtomicPtrT |
3760 | +template <> |
3761 | +inline EpicsAtomicPtrT trueValue < EpicsAtomicPtrT > () |
3762 | +{ static char c; return & c; } |
3763 | + |
3764 | +template <> |
3765 | +inline EpicsAtomicPtrT falseValue < EpicsAtomicPtrT > () |
3766 | +{ return 0u; } |
3767 | + |
3768 | +template < class T > |
3769 | +static void cas ( void *arg ) |
3770 | +{ |
3771 | + TestDataCAS < T > * const pTestData = |
3772 | + reinterpret_cast < TestDataCAS < T > * > ( arg ); |
3773 | + /* |
3774 | + * intentionally waste cpu and maximize |
3775 | + * contention for the shared data |
3776 | + */ |
3777 | + increment ( pTestData->m_testIterationsNotSet ); |
3778 | + while ( ! compareAndSwap ( pTestData->m_testValue, |
3779 | + falseValue < T > (), |
3780 | + trueValue < T > () ) ) { |
3781 | + } |
3782 | + decrement ( pTestData->m_testIterationsNotSet ); |
3783 | + set ( pTestData->m_testValue, falseValue < T > () ); |
3784 | + increment ( pTestData->m_testIterationsSet ); |
3785 | +} |
3786 | + |
3787 | +template < class T > |
3788 | +void testIncrDecr () |
3789 | +{ |
3790 | + static const size_t N = 100; |
3791 | + static const T NT = static_cast < T > ( N ); |
3792 | + |
3793 | + const unsigned int stackSize = |
3794 | + epicsThreadGetStackSize ( epicsThreadStackSmall ); |
3795 | + |
3796 | + TestDataIncrDecr < T > testData = { 0, N }; |
3797 | + set ( testData.m_testValue, NT ); |
3798 | + testOk ( get ( testData.m_testValue ) == NT, |
3799 | + "set/get %u", testData.m_testValue ); |
3800 | + set ( testData.m_testIterations, 0u ); |
3801 | + testOk ( get ( testData.m_testIterations ) == 0u, |
3802 | + "set/get %u", testData.m_testIterations ); |
3803 | + for ( size_t i = 0u; i < N; i++ ) { |
3804 | + epicsThreadCreate ( "incr", |
3805 | + 50, stackSize, incr < T >, & testData ); |
3806 | + epicsThreadCreate ( "decr", |
3807 | + 50, stackSize, decr < T >, & testData ); |
3808 | + } |
3809 | + while ( testData.m_testIterations < 2 * N ) { |
3810 | + epicsThreadSleep ( 0.01 ); |
3811 | + } |
3812 | + testOk ( get ( testData.m_testIterations ) == 2 * N, |
3813 | + "incr/decr iterations %u", |
3814 | + testData.m_testIterations ); |
3815 | + testOk ( get ( testData.m_testValue ) == NT, |
3816 | + "incr/decr final value %u", |
3817 | + testData.m_testValue ); |
3818 | +} |
3819 | + |
3820 | +template < class T > |
3821 | +void testAddSub () |
3822 | +{ |
3823 | + static const size_t N = 100; |
3824 | + static const T NDT = TestDataAddSub < T > :: delta * |
3825 | + static_cast < T > ( N ); |
3826 | + |
3827 | + const unsigned int stackSize = |
3828 | + epicsThreadGetStackSize ( epicsThreadStackSmall ); |
3829 | + |
3830 | + TestDataIncrDecr < T > testData = { 0, N }; |
3831 | + set ( testData.m_testValue, NDT ); |
3832 | + testOk ( get ( testData.m_testValue ) == NDT, |
3833 | + "set/get %u", testData.m_testValue ); |
3834 | + set ( testData.m_testIterations, 0u ); |
3835 | + testOk ( get ( testData.m_testIterations ) == 0u, |
3836 | + "set/get %u", testData.m_testIterations ); |
3837 | + for ( size_t i = 0u; i < N; i++ ) { |
3838 | + epicsThreadCreate ( "add", |
3839 | + 50, stackSize, add < T >, & testData ); |
3840 | + epicsThreadCreate ( "sub", |
3841 | + 50, stackSize, sub < T >, & testData ); |
3842 | + } |
3843 | + while ( testData.m_testIterations < 2 * N ) { |
3844 | + epicsThreadSleep ( 0.01 ); |
3845 | + } |
3846 | + testOk ( get ( testData.m_testIterations ) == 2 * N, |
3847 | + "add/sub iterations %u", |
3848 | + testData.m_testIterations ); |
3849 | + testOk ( get ( testData.m_testValue ) == NDT, |
3850 | + "add/sub final value %u", |
3851 | + testData.m_testValue ); |
3852 | +} |
3853 | + |
3854 | +template < class T > |
3855 | +void testCAS () |
3856 | +{ |
3857 | + static const size_t N = 10; |
3858 | + |
3859 | + const unsigned int stackSize = |
3860 | + epicsThreadGetStackSize ( epicsThreadStackSmall ); |
3861 | + |
3862 | + TestDataCAS < T > testData = { 0, N, N }; |
3863 | + set ( testData.m_testIterationsSet, 0 ); |
3864 | + testOk ( get ( testData.m_testIterationsSet ) == 0u, |
3865 | + "set/get %u", testData.m_testIterationsSet ); |
3866 | + set ( testData.m_testIterationsNotSet, 0 ); |
3867 | + testOk ( get ( testData.m_testIterationsNotSet ) == 0u, |
3868 | + "set/get %u", testData.m_testIterationsNotSet ); |
3869 | + set ( testData.m_testValue, trueValue < T > () ); |
3870 | + testOk ( get ( testData.m_testValue ) == trueValue < T > (), |
3871 | + "set/get a true value" ); |
3872 | + for ( size_t i = 0u; i < N; i++ ) { |
3873 | + epicsThreadCreate ( "tns", |
3874 | + 50, stackSize, cas < T >, & testData ); |
3875 | + } |
3876 | + set ( testData.m_testValue, falseValue < T > () ); |
3877 | + while ( testData.m_testIterationsSet < N ) { |
3878 | + epicsThreadSleep ( 0.01 ); |
3879 | + } |
3880 | + testOk ( get ( testData.m_testIterationsSet ) == N, |
3881 | + "test and set iterations %u", |
3882 | + testData.m_testIterationsSet ); |
3883 | + testOk ( get ( testData.m_testIterationsNotSet ) == 0u, |
3884 | + "test and set not-set tracking = %u", |
3885 | + testData.m_testIterationsNotSet ); |
3886 | +} |
3887 | + |
3888 | +MAIN ( epicsAtomicTest ) |
3889 | +{ |
3890 | + |
3891 | + testPlan ( 31 ); |
3892 | + |
3893 | + testIncrDecr < int > (); |
3894 | + testIncrDecr < size_t > (); |
3895 | + testAddSub < int > (); |
3896 | + testAddSub < size_t > (); |
3897 | + testCAS < int > (); |
3898 | + testCAS < size_t > (); |
3899 | + testCAS < EpicsAtomicPtrT > (); |
3900 | + |
3901 | + return testDone (); |
3902 | +} |